From e611b132f9b8abe35b362e5870b74bce94a1e58e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 May 2020 20:51:50 -0700 Subject: initial commit --- private/oleutest/letest/bttncur/bttncur.c | 1070 ++++++ private/oleutest/letest/bttncur/bttncur.h | 201 ++ private/oleutest/letest/bttncur/bttncur.rc | 39 + private/oleutest/letest/bttncur/bttncur.rcv | 48 + private/oleutest/letest/bttncur/bttncuri.h | 88 + private/oleutest/letest/bttncur/changes.txt | 314 ++ private/oleutest/letest/bttncur/cursors.c | 150 + .../oleutest/letest/bttncur/daytona/bttncur.src | 39 + private/oleutest/letest/bttncur/daytona/makefile | 6 + .../oleutest/letest/bttncur/daytona/makefile.inc | 1 + private/oleutest/letest/bttncur/daytona/sources | 39 + private/oleutest/letest/bttncur/dirs | 4 + private/oleutest/letest/bttncur/dllentry.c | 55 + private/oleutest/letest/bttncur/makefile | 12 + private/oleutest/letest/bttncur/msvc.pdb | Bin 0 -> 49152 bytes private/oleutest/letest/bttncur/res/harrows.cur | Bin 0 -> 326 bytes private/oleutest/letest/bttncur/res/help.cur | Bin 0 -> 326 bytes private/oleutest/letest/bttncur/res/larrows.cur | Bin 0 -> 326 bytes private/oleutest/letest/bttncur/res/magnify.cur | Bin 0 -> 326 bytes private/oleutest/letest/bttncur/res/neswarrs.cur | Bin 0 -> 326 bytes private/oleutest/letest/bttncur/res/nodrop.cur | Bin 0 -> 326 bytes private/oleutest/letest/bttncur/res/nwsearrs.cur | Bin 0 -> 326 bytes private/oleutest/letest/bttncur/res/rarrow.cur | Bin 0 -> 326 bytes private/oleutest/letest/bttncur/res/sarrows.cur | Bin 0 -> 326 bytes private/oleutest/letest/bttncur/res/sizebarh.cur | Bin 0 -> 326 bytes private/oleutest/letest/bttncur/res/sizebarv.cur | Bin 0 -> 326 bytes private/oleutest/letest/bttncur/res/splith.cur | Bin 0 -> 326 bytes private/oleutest/letest/bttncur/res/splitv.cur | Bin 0 -> 326 bytes private/oleutest/letest/bttncur/res/stdim120.bmp | Bin 0 -> 2602 bytes private/oleutest/letest/bttncur/res/stdim72.bmp | Bin 0 -> 910 bytes private/oleutest/letest/bttncur/res/stdim96.bmp | Bin 0 -> 1198 bytes private/oleutest/letest/bttncur/res/tabletop.cur | Bin 0 -> 326 bytes private/oleutest/letest/bttncur/res/varrows.cur | Bin 0 -> 326 bytes private/oleutest/letest/data/letest12.olc | Bin 0 -> 5120 bytes private/oleutest/letest/data/tiger.bmp | Bin 0 -> 438198 bytes private/oleutest/letest/data/tigernph.wmf | Bin 0 -> 185288 bytes private/oleutest/letest/dirs | 7 + private/oleutest/letest/gizmobar/api.c | 846 +++++ private/oleutest/letest/gizmobar/book1632.h | 154 + .../oleutest/letest/gizmobar/daytona/gizmobar.src | 51 + private/oleutest/letest/gizmobar/daytona/makefile | 6 + .../oleutest/letest/gizmobar/daytona/makefile.inc | 1 + private/oleutest/letest/gizmobar/daytona/sources | 50 + private/oleutest/letest/gizmobar/dirs | 37 + private/oleutest/letest/gizmobar/dllentry.c | 55 + private/oleutest/letest/gizmobar/gizmo.c | 766 +++++ private/oleutest/letest/gizmobar/gizmo.h | 103 + private/oleutest/letest/gizmobar/gizmobar.c | 467 +++ private/oleutest/letest/gizmobar/gizmobar.h | 178 + private/oleutest/letest/gizmobar/gizmobar.rc | 20 + private/oleutest/letest/gizmobar/gizmobar.rcv | 53 + private/oleutest/letest/gizmobar/gizmoint.h | 105 + private/oleutest/letest/gizmobar/init.c | 233 ++ private/oleutest/letest/gizmobar/paint.c | 132 + private/oleutest/letest/ole2ui/bang.ico | Bin 0 -> 1846 bytes private/oleutest/letest/ole2ui/busy.c | 551 +++ private/oleutest/letest/ole2ui/busy.dlg | 13 + private/oleutest/letest/ole2ui/busy.h | 45 + private/oleutest/letest/ole2ui/common.c | 423 +++ private/oleutest/letest/ole2ui/common.h | 166 + private/oleutest/letest/ole2ui/convert.c | 1802 ++++++++++ private/oleutest/letest/ole2ui/convert.dlg | 32 + private/oleutest/letest/ole2ui/convert.h | 63 + private/oleutest/letest/ole2ui/daytona/makefile | 6 + .../oleutest/letest/ole2ui/daytona/ole2u32a.src | 200 ++ private/oleutest/letest/ole2ui/daytona/ole2ui.src | 199 ++ private/oleutest/letest/ole2ui/daytona/sources | 64 + private/oleutest/letest/ole2ui/dballoc.cpp | 900 +++++ private/oleutest/letest/ole2ui/dballoc.h | 36 + private/oleutest/letest/ole2ui/dbgutil.c | 419 +++ private/oleutest/letest/ole2ui/debug.h | 69 + private/oleutest/letest/ole2ui/default.ico | Bin 0 -> 766 bytes private/oleutest/letest/ole2ui/defuimak.ini | 20 + private/oleutest/letest/ole2ui/depend | 87 + private/oleutest/letest/ole2ui/depend.mk | 569 ++++ private/oleutest/letest/ole2ui/dirs | 3 + private/oleutest/letest/ole2ui/dllentry.c | 55 + private/oleutest/letest/ole2ui/dllfuncs.c | 110 + private/oleutest/letest/ole2ui/drawicon.c | 729 ++++ private/oleutest/letest/ole2ui/edlinks.h | 135 + private/oleutest/letest/ole2ui/egares.bmp | Bin 0 -> 6838 bytes private/oleutest/letest/ole2ui/enumfetc.c | 308 ++ private/oleutest/letest/ole2ui/enumfetc.h | 13 + private/oleutest/letest/ole2ui/enumstat.c | 336 ++ private/oleutest/letest/ole2ui/filelist.mk | 75 + private/oleutest/letest/ole2ui/fileopen.dlg | 33 + private/oleutest/letest/ole2ui/geticon.c | 1177 +++++++ private/oleutest/letest/ole2ui/geticon.h | 18 + private/oleutest/letest/ole2ui/hatch.c | 325 ++ private/oleutest/letest/ole2ui/hivgares.bmp | Bin 0 -> 20326 bytes private/oleutest/letest/ole2ui/icon.c | 857 +++++ private/oleutest/letest/ole2ui/icon.dlg | 48 + private/oleutest/letest/ole2ui/icon.h | 59 + private/oleutest/letest/ole2ui/iconbox.c | 253 ++ private/oleutest/letest/ole2ui/iconbox.h | 31 + private/oleutest/letest/ole2ui/insobj.c | 1724 ++++++++++ private/oleutest/letest/ole2ui/insobj.dlg | 51 + private/oleutest/letest/ole2ui/insobj.h | 52 + private/oleutest/letest/ole2ui/links.c | 2146 ++++++++++++ private/oleutest/letest/ole2ui/links.dlg | 35 + private/oleutest/letest/ole2ui/makefile | 12 + private/oleutest/letest/ole2ui/makefile.32 | 590 ++++ private/oleutest/letest/ole2ui/makefile.old | 607 ++++ private/oleutest/letest/ole2ui/makelib | 503 +++ private/oleutest/letest/ole2ui/msgfiltr.c | 809 +++++ private/oleutest/letest/ole2ui/msgfiltr.h | 64 + private/oleutest/letest/ole2ui/objfdbk.c | 246 ++ private/oleutest/letest/ole2ui/ole2ui.c | 971 ++++++ private/oleutest/letest/ole2ui/ole2ui.h | 958 ++++++ private/oleutest/letest/ole2ui/ole2ui.mak | 272 ++ private/oleutest/letest/ole2ui/ole2ui.rc | 65 + private/oleutest/letest/ole2ui/olestd.c | 3048 +++++++++++++++++ private/oleutest/letest/ole2ui/olestd.h | 852 +++++ private/oleutest/letest/ole2ui/olestr.c | 32 + private/oleutest/letest/ole2ui/olestr.h | 21 + private/oleutest/letest/ole2ui/olethunk.c | 649 ++++ private/oleutest/letest/ole2ui/olethunk.h | 193 ++ private/oleutest/letest/ole2ui/oleutl.c | 660 ++++ private/oleutest/letest/ole2ui/outlui.d32 | 138 + private/oleutest/letest/ole2ui/pastespl.c | 1713 ++++++++++ private/oleutest/letest/ole2ui/pastespl.dlg | 40 + private/oleutest/letest/ole2ui/pastespl.h | 110 + private/oleutest/letest/ole2ui/precomp.c | 23 + private/oleutest/letest/ole2ui/prompt.dlg | 80 + private/oleutest/letest/ole2ui/regdb.c | 401 +++ private/oleutest/letest/ole2ui/regdb.h | 8 + private/oleutest/letest/ole2ui/resimage.c | 363 ++ private/oleutest/letest/ole2ui/resimage.h | 61 + private/oleutest/letest/ole2ui/stdpal.c | 94 + private/oleutest/letest/ole2ui/stdpal.h | 292 ++ private/oleutest/letest/ole2ui/strings.rc | 124 + private/oleutest/letest/ole2ui/suminfo.cpp | 1371 ++++++++ private/oleutest/letest/ole2ui/suminfo.h | 331 ++ private/oleutest/letest/ole2ui/targtdev.c | 328 ++ private/oleutest/letest/ole2ui/template.c | 243 ++ private/oleutest/letest/ole2ui/template.h | 119 + private/oleutest/letest/ole2ui/uiclass.h | 2 + private/oleutest/letest/ole2ui/uimake.cmd | 1 + private/oleutest/letest/ole2ui/uimake.ini | 24 + private/oleutest/letest/ole2ui/utility.c | 1039 ++++++ private/oleutest/letest/ole2ui/utility.h | 37 + private/oleutest/letest/ole2ui/verlocal.h | 54 + private/oleutest/letest/ole2ui/vgares.bmp | Bin 0 -> 9078 bytes private/oleutest/letest/ole2ui/wn_dos.h | 174 + private/oleutest/letest/outline/classfac.c | 219 ++ private/oleutest/letest/outline/classfac.h | 219 ++ private/oleutest/letest/outline/clipbrd.c | 3401 +++++++++++++++++++ private/oleutest/letest/outline/cntrbase.c | 2002 +++++++++++ private/oleutest/letest/outline/cntrinpl.c | 1940 +++++++++++ private/oleutest/letest/outline/cntrline.c | 3540 +++++++++++++++++++ private/oleutest/letest/outline/cntrline.h | 3584 ++++++++++++++++++++ private/oleutest/letest/outline/cntroutl.h | 855 +++++ private/oleutest/letest/outline/cntroutl.ico | Bin 0 -> 766 bytes .../oleutest/letest/outline/cntroutl/cntroutl.rc | 179 + .../letest/outline/cntroutl/daytona/makefile | 6 + .../letest/outline/cntroutl/daytona/makefile.inc | 2 + .../letest/outline/cntroutl/daytona/sources | 114 + private/oleutest/letest/outline/cntroutl/dirs | 37 + private/oleutest/letest/outline/cntrrc.h | 30 + private/oleutest/letest/outline/debug.c | 100 + private/oleutest/letest/outline/debug.rc | 142 + private/oleutest/letest/outline/debug2.c | 329 ++ private/oleutest/letest/outline/defguid.h | 44 + private/oleutest/letest/outline/dialogs.c | 659 ++++ private/oleutest/letest/outline/dialogs.dlg | 92 + private/oleutest/letest/outline/dirs | 32 + private/oleutest/letest/outline/dragcopy.cur | Bin 0 -> 326 bytes private/oleutest/letest/outline/dragdrop.c | 674 ++++ private/oleutest/letest/outline/draglink.cur | Bin 0 -> 326 bytes private/oleutest/letest/outline/dragmove.cur | Bin 0 -> 326 bytes private/oleutest/letest/outline/dragnone.cur | Bin 0 -> 326 bytes private/oleutest/letest/outline/frametls.c | 1075 ++++++ private/oleutest/letest/outline/frametls.h | 102 + private/oleutest/letest/outline/heading.c | 451 +++ private/oleutest/letest/outline/heading.h | 59 + private/oleutest/letest/outline/icntrotl.ico | Bin 0 -> 766 bytes .../letest/outline/icntrotl/daytona/makefile | 6 + .../letest/outline/icntrotl/daytona/makefile.inc | 2 + .../letest/outline/icntrotl/daytona/sources | 108 + private/oleutest/letest/outline/icntrotl/dirs | 37 + .../oleutest/letest/outline/icntrotl/icntrotl.rc | 210 ++ private/oleutest/letest/outline/image120.bmp | Bin 0 -> 1498 bytes private/oleutest/letest/outline/image72.bmp | Bin 0 -> 558 bytes private/oleutest/letest/outline/image96.bmp | Bin 0 -> 758 bytes private/oleutest/letest/outline/install.bat | 7 + private/oleutest/letest/outline/isvrotl.ico | Bin 0 -> 766 bytes .../letest/outline/isvrotl/daytona/makefile | 6 + .../letest/outline/isvrotl/daytona/makefile.inc | 2 + .../letest/outline/isvrotl/daytona/sources | 108 + private/oleutest/letest/outline/isvrotl/dirs | 37 + private/oleutest/letest/outline/isvrotl/isvrotl.rc | 211 ++ private/oleutest/letest/outline/linking.c | 2157 ++++++++++++ private/oleutest/letest/outline/main.c | 2488 ++++++++++++++ private/oleutest/letest/outline/memmgr.c | 38 + private/oleutest/letest/outline/message.h | 109 + private/oleutest/letest/outline/ole2.bmp | Bin 0 -> 14862 bytes private/oleutest/letest/outline/oleapp.c | 2989 ++++++++++++++++ private/oleutest/letest/outline/oledoc.c | 1179 +++++++ private/oleutest/letest/outline/oleoutl.h | 734 ++++ private/oleutest/letest/outline/outlapp.c | 1514 +++++++++ private/oleutest/letest/outline/outldoc.c | 3247 ++++++++++++++++++ private/oleutest/letest/outline/outline.h | 790 +++++ private/oleutest/letest/outline/outline.ico | Bin 0 -> 766 bytes private/oleutest/letest/outline/outline.mst | 469 +++ private/oleutest/letest/outline/outline.rc | 173 + private/oleutest/letest/outline/outlline.c | 731 ++++ private/oleutest/letest/outline/outllist.c | 1183 +++++++ private/oleutest/letest/outline/outlname.c | 112 + private/oleutest/letest/outline/outlntbl.c | 460 +++ private/oleutest/letest/outline/outlrc.h | 164 + private/oleutest/letest/outline/outltxtl.c | 408 +++ private/oleutest/letest/outline/precomp.c | 13 + private/oleutest/letest/outline/selcross.cur | Bin 0 -> 326 bytes private/oleutest/letest/outline/state.rst | 12 + private/oleutest/letest/outline/status.c | 369 ++ private/oleutest/letest/outline/status.h | 47 + private/oleutest/letest/outline/svrbase.c | 2018 +++++++++++ private/oleutest/letest/outline/svrinpl.c | 1451 ++++++++ private/oleutest/letest/outline/svroutl.h | 888 +++++ private/oleutest/letest/outline/svroutl.ico | Bin 0 -> 766 bytes .../letest/outline/svroutl/daytona/makefile | 6 + .../letest/outline/svroutl/daytona/makefile.inc | 2 + .../letest/outline/svroutl/daytona/sources | 106 + private/oleutest/letest/outline/svroutl/dirs | 37 + private/oleutest/letest/outline/svroutl/svroutl.rc | 187 + private/oleutest/letest/outline/svrpsobj.c | 1538 +++++++++ private/oleutest/letest/outline/tests.c | 134 + private/oleutest/letest/readme.txt | 11 + 228 files changed, 83674 insertions(+) create mode 100644 private/oleutest/letest/bttncur/bttncur.c create mode 100644 private/oleutest/letest/bttncur/bttncur.h create mode 100644 private/oleutest/letest/bttncur/bttncur.rc create mode 100644 private/oleutest/letest/bttncur/bttncur.rcv create mode 100644 private/oleutest/letest/bttncur/bttncuri.h create mode 100644 private/oleutest/letest/bttncur/changes.txt create mode 100644 private/oleutest/letest/bttncur/cursors.c create mode 100644 private/oleutest/letest/bttncur/daytona/bttncur.src create mode 100644 private/oleutest/letest/bttncur/daytona/makefile create mode 100644 private/oleutest/letest/bttncur/daytona/makefile.inc create mode 100644 private/oleutest/letest/bttncur/daytona/sources create mode 100644 private/oleutest/letest/bttncur/dirs create mode 100644 private/oleutest/letest/bttncur/dllentry.c create mode 100644 private/oleutest/letest/bttncur/makefile create mode 100644 private/oleutest/letest/bttncur/msvc.pdb create mode 100644 private/oleutest/letest/bttncur/res/harrows.cur create mode 100644 private/oleutest/letest/bttncur/res/help.cur create mode 100644 private/oleutest/letest/bttncur/res/larrows.cur create mode 100644 private/oleutest/letest/bttncur/res/magnify.cur create mode 100644 private/oleutest/letest/bttncur/res/neswarrs.cur create mode 100644 private/oleutest/letest/bttncur/res/nodrop.cur create mode 100644 private/oleutest/letest/bttncur/res/nwsearrs.cur create mode 100644 private/oleutest/letest/bttncur/res/rarrow.cur create mode 100644 private/oleutest/letest/bttncur/res/sarrows.cur create mode 100644 private/oleutest/letest/bttncur/res/sizebarh.cur create mode 100644 private/oleutest/letest/bttncur/res/sizebarv.cur create mode 100644 private/oleutest/letest/bttncur/res/splith.cur create mode 100644 private/oleutest/letest/bttncur/res/splitv.cur create mode 100644 private/oleutest/letest/bttncur/res/stdim120.bmp create mode 100644 private/oleutest/letest/bttncur/res/stdim72.bmp create mode 100644 private/oleutest/letest/bttncur/res/stdim96.bmp create mode 100644 private/oleutest/letest/bttncur/res/tabletop.cur create mode 100644 private/oleutest/letest/bttncur/res/varrows.cur create mode 100644 private/oleutest/letest/data/letest12.olc create mode 100644 private/oleutest/letest/data/tiger.bmp create mode 100644 private/oleutest/letest/data/tigernph.wmf create mode 100644 private/oleutest/letest/dirs create mode 100644 private/oleutest/letest/gizmobar/api.c create mode 100644 private/oleutest/letest/gizmobar/book1632.h create mode 100644 private/oleutest/letest/gizmobar/daytona/gizmobar.src create mode 100644 private/oleutest/letest/gizmobar/daytona/makefile create mode 100644 private/oleutest/letest/gizmobar/daytona/makefile.inc create mode 100644 private/oleutest/letest/gizmobar/daytona/sources create mode 100644 private/oleutest/letest/gizmobar/dirs create mode 100644 private/oleutest/letest/gizmobar/dllentry.c create mode 100644 private/oleutest/letest/gizmobar/gizmo.c create mode 100644 private/oleutest/letest/gizmobar/gizmo.h create mode 100644 private/oleutest/letest/gizmobar/gizmobar.c create mode 100644 private/oleutest/letest/gizmobar/gizmobar.h create mode 100644 private/oleutest/letest/gizmobar/gizmobar.rc create mode 100644 private/oleutest/letest/gizmobar/gizmobar.rcv create mode 100644 private/oleutest/letest/gizmobar/gizmoint.h create mode 100644 private/oleutest/letest/gizmobar/init.c create mode 100644 private/oleutest/letest/gizmobar/paint.c create mode 100644 private/oleutest/letest/ole2ui/bang.ico create mode 100644 private/oleutest/letest/ole2ui/busy.c create mode 100644 private/oleutest/letest/ole2ui/busy.dlg create mode 100644 private/oleutest/letest/ole2ui/busy.h create mode 100644 private/oleutest/letest/ole2ui/common.c create mode 100644 private/oleutest/letest/ole2ui/common.h create mode 100644 private/oleutest/letest/ole2ui/convert.c create mode 100644 private/oleutest/letest/ole2ui/convert.dlg create mode 100644 private/oleutest/letest/ole2ui/convert.h create mode 100644 private/oleutest/letest/ole2ui/daytona/makefile create mode 100644 private/oleutest/letest/ole2ui/daytona/ole2u32a.src create mode 100644 private/oleutest/letest/ole2ui/daytona/ole2ui.src create mode 100644 private/oleutest/letest/ole2ui/daytona/sources create mode 100644 private/oleutest/letest/ole2ui/dballoc.cpp create mode 100644 private/oleutest/letest/ole2ui/dballoc.h create mode 100644 private/oleutest/letest/ole2ui/dbgutil.c create mode 100644 private/oleutest/letest/ole2ui/debug.h create mode 100644 private/oleutest/letest/ole2ui/default.ico create mode 100644 private/oleutest/letest/ole2ui/defuimak.ini create mode 100644 private/oleutest/letest/ole2ui/depend create mode 100644 private/oleutest/letest/ole2ui/depend.mk create mode 100644 private/oleutest/letest/ole2ui/dirs create mode 100644 private/oleutest/letest/ole2ui/dllentry.c create mode 100644 private/oleutest/letest/ole2ui/dllfuncs.c create mode 100644 private/oleutest/letest/ole2ui/drawicon.c create mode 100644 private/oleutest/letest/ole2ui/edlinks.h create mode 100644 private/oleutest/letest/ole2ui/egares.bmp create mode 100644 private/oleutest/letest/ole2ui/enumfetc.c create mode 100644 private/oleutest/letest/ole2ui/enumfetc.h create mode 100644 private/oleutest/letest/ole2ui/enumstat.c create mode 100644 private/oleutest/letest/ole2ui/filelist.mk create mode 100644 private/oleutest/letest/ole2ui/fileopen.dlg create mode 100644 private/oleutest/letest/ole2ui/geticon.c create mode 100644 private/oleutest/letest/ole2ui/geticon.h create mode 100644 private/oleutest/letest/ole2ui/hatch.c create mode 100644 private/oleutest/letest/ole2ui/hivgares.bmp create mode 100644 private/oleutest/letest/ole2ui/icon.c create mode 100644 private/oleutest/letest/ole2ui/icon.dlg create mode 100644 private/oleutest/letest/ole2ui/icon.h create mode 100644 private/oleutest/letest/ole2ui/iconbox.c create mode 100644 private/oleutest/letest/ole2ui/iconbox.h create mode 100644 private/oleutest/letest/ole2ui/insobj.c create mode 100644 private/oleutest/letest/ole2ui/insobj.dlg create mode 100644 private/oleutest/letest/ole2ui/insobj.h create mode 100644 private/oleutest/letest/ole2ui/links.c create mode 100644 private/oleutest/letest/ole2ui/links.dlg create mode 100644 private/oleutest/letest/ole2ui/makefile create mode 100644 private/oleutest/letest/ole2ui/makefile.32 create mode 100644 private/oleutest/letest/ole2ui/makefile.old create mode 100644 private/oleutest/letest/ole2ui/makelib create mode 100644 private/oleutest/letest/ole2ui/msgfiltr.c create mode 100644 private/oleutest/letest/ole2ui/msgfiltr.h create mode 100644 private/oleutest/letest/ole2ui/objfdbk.c create mode 100644 private/oleutest/letest/ole2ui/ole2ui.c create mode 100644 private/oleutest/letest/ole2ui/ole2ui.h create mode 100644 private/oleutest/letest/ole2ui/ole2ui.mak create mode 100644 private/oleutest/letest/ole2ui/ole2ui.rc create mode 100644 private/oleutest/letest/ole2ui/olestd.c create mode 100644 private/oleutest/letest/ole2ui/olestd.h create mode 100644 private/oleutest/letest/ole2ui/olestr.c create mode 100644 private/oleutest/letest/ole2ui/olestr.h create mode 100644 private/oleutest/letest/ole2ui/olethunk.c create mode 100644 private/oleutest/letest/ole2ui/olethunk.h create mode 100644 private/oleutest/letest/ole2ui/oleutl.c create mode 100644 private/oleutest/letest/ole2ui/outlui.d32 create mode 100644 private/oleutest/letest/ole2ui/pastespl.c create mode 100644 private/oleutest/letest/ole2ui/pastespl.dlg create mode 100644 private/oleutest/letest/ole2ui/pastespl.h create mode 100644 private/oleutest/letest/ole2ui/precomp.c create mode 100644 private/oleutest/letest/ole2ui/prompt.dlg create mode 100644 private/oleutest/letest/ole2ui/regdb.c create mode 100644 private/oleutest/letest/ole2ui/regdb.h create mode 100644 private/oleutest/letest/ole2ui/resimage.c create mode 100644 private/oleutest/letest/ole2ui/resimage.h create mode 100644 private/oleutest/letest/ole2ui/stdpal.c create mode 100644 private/oleutest/letest/ole2ui/stdpal.h create mode 100644 private/oleutest/letest/ole2ui/strings.rc create mode 100644 private/oleutest/letest/ole2ui/suminfo.cpp create mode 100644 private/oleutest/letest/ole2ui/suminfo.h create mode 100644 private/oleutest/letest/ole2ui/targtdev.c create mode 100644 private/oleutest/letest/ole2ui/template.c create mode 100644 private/oleutest/letest/ole2ui/template.h create mode 100644 private/oleutest/letest/ole2ui/uiclass.h create mode 100644 private/oleutest/letest/ole2ui/uimake.cmd create mode 100644 private/oleutest/letest/ole2ui/uimake.ini create mode 100644 private/oleutest/letest/ole2ui/utility.c create mode 100644 private/oleutest/letest/ole2ui/utility.h create mode 100644 private/oleutest/letest/ole2ui/verlocal.h create mode 100644 private/oleutest/letest/ole2ui/vgares.bmp create mode 100644 private/oleutest/letest/ole2ui/wn_dos.h create mode 100644 private/oleutest/letest/outline/classfac.c create mode 100644 private/oleutest/letest/outline/classfac.h create mode 100644 private/oleutest/letest/outline/clipbrd.c create mode 100644 private/oleutest/letest/outline/cntrbase.c create mode 100644 private/oleutest/letest/outline/cntrinpl.c create mode 100644 private/oleutest/letest/outline/cntrline.c create mode 100644 private/oleutest/letest/outline/cntrline.h create mode 100644 private/oleutest/letest/outline/cntroutl.h create mode 100644 private/oleutest/letest/outline/cntroutl.ico create mode 100644 private/oleutest/letest/outline/cntroutl/cntroutl.rc create mode 100644 private/oleutest/letest/outline/cntroutl/daytona/makefile create mode 100644 private/oleutest/letest/outline/cntroutl/daytona/makefile.inc create mode 100644 private/oleutest/letest/outline/cntroutl/daytona/sources create mode 100644 private/oleutest/letest/outline/cntroutl/dirs create mode 100644 private/oleutest/letest/outline/cntrrc.h create mode 100644 private/oleutest/letest/outline/debug.c create mode 100644 private/oleutest/letest/outline/debug.rc create mode 100644 private/oleutest/letest/outline/debug2.c create mode 100644 private/oleutest/letest/outline/defguid.h create mode 100644 private/oleutest/letest/outline/dialogs.c create mode 100644 private/oleutest/letest/outline/dialogs.dlg create mode 100644 private/oleutest/letest/outline/dirs create mode 100644 private/oleutest/letest/outline/dragcopy.cur create mode 100644 private/oleutest/letest/outline/dragdrop.c create mode 100644 private/oleutest/letest/outline/draglink.cur create mode 100644 private/oleutest/letest/outline/dragmove.cur create mode 100644 private/oleutest/letest/outline/dragnone.cur create mode 100644 private/oleutest/letest/outline/frametls.c create mode 100644 private/oleutest/letest/outline/frametls.h create mode 100644 private/oleutest/letest/outline/heading.c create mode 100644 private/oleutest/letest/outline/heading.h create mode 100644 private/oleutest/letest/outline/icntrotl.ico create mode 100644 private/oleutest/letest/outline/icntrotl/daytona/makefile create mode 100644 private/oleutest/letest/outline/icntrotl/daytona/makefile.inc create mode 100644 private/oleutest/letest/outline/icntrotl/daytona/sources create mode 100644 private/oleutest/letest/outline/icntrotl/dirs create mode 100644 private/oleutest/letest/outline/icntrotl/icntrotl.rc create mode 100644 private/oleutest/letest/outline/image120.bmp create mode 100644 private/oleutest/letest/outline/image72.bmp create mode 100644 private/oleutest/letest/outline/image96.bmp create mode 100644 private/oleutest/letest/outline/install.bat create mode 100644 private/oleutest/letest/outline/isvrotl.ico create mode 100644 private/oleutest/letest/outline/isvrotl/daytona/makefile create mode 100644 private/oleutest/letest/outline/isvrotl/daytona/makefile.inc create mode 100644 private/oleutest/letest/outline/isvrotl/daytona/sources create mode 100644 private/oleutest/letest/outline/isvrotl/dirs create mode 100644 private/oleutest/letest/outline/isvrotl/isvrotl.rc create mode 100644 private/oleutest/letest/outline/linking.c create mode 100644 private/oleutest/letest/outline/main.c create mode 100644 private/oleutest/letest/outline/memmgr.c create mode 100644 private/oleutest/letest/outline/message.h create mode 100644 private/oleutest/letest/outline/ole2.bmp create mode 100644 private/oleutest/letest/outline/oleapp.c create mode 100644 private/oleutest/letest/outline/oledoc.c create mode 100644 private/oleutest/letest/outline/oleoutl.h create mode 100644 private/oleutest/letest/outline/outlapp.c create mode 100644 private/oleutest/letest/outline/outldoc.c create mode 100644 private/oleutest/letest/outline/outline.h create mode 100644 private/oleutest/letest/outline/outline.ico create mode 100644 private/oleutest/letest/outline/outline.mst create mode 100644 private/oleutest/letest/outline/outline.rc create mode 100644 private/oleutest/letest/outline/outlline.c create mode 100644 private/oleutest/letest/outline/outllist.c create mode 100644 private/oleutest/letest/outline/outlname.c create mode 100644 private/oleutest/letest/outline/outlntbl.c create mode 100644 private/oleutest/letest/outline/outlrc.h create mode 100644 private/oleutest/letest/outline/outltxtl.c create mode 100644 private/oleutest/letest/outline/precomp.c create mode 100644 private/oleutest/letest/outline/selcross.cur create mode 100644 private/oleutest/letest/outline/state.rst create mode 100644 private/oleutest/letest/outline/status.c create mode 100644 private/oleutest/letest/outline/status.h create mode 100644 private/oleutest/letest/outline/svrbase.c create mode 100644 private/oleutest/letest/outline/svrinpl.c create mode 100644 private/oleutest/letest/outline/svroutl.h create mode 100644 private/oleutest/letest/outline/svroutl.ico create mode 100644 private/oleutest/letest/outline/svroutl/daytona/makefile create mode 100644 private/oleutest/letest/outline/svroutl/daytona/makefile.inc create mode 100644 private/oleutest/letest/outline/svroutl/daytona/sources create mode 100644 private/oleutest/letest/outline/svroutl/dirs create mode 100644 private/oleutest/letest/outline/svroutl/svroutl.rc create mode 100644 private/oleutest/letest/outline/svrpsobj.c create mode 100644 private/oleutest/letest/outline/tests.c create mode 100644 private/oleutest/letest/readme.txt (limited to 'private/oleutest/letest') diff --git a/private/oleutest/letest/bttncur/bttncur.c b/private/oleutest/letest/bttncur/bttncur.c new file mode 100644 index 000000000..4e5dee40f --- /dev/null +++ b/private/oleutest/letest/bttncur/bttncur.c @@ -0,0 +1,1070 @@ +/* + * BTTNCUR.C + * Buttons & Cursors Version 1.1, Win32 version August 1993 + * + * Public functions to generate different states of toolbar buttons from + * a single bitmap. States are normal, pressed, checked, and disabled. + * + * Copyright (c)1992-1993 Microsoft Corporation, All Rights Reserved, + * as applied to redistribution of this source code in source form + * License is granted to use of compiled code in shipped binaries. + */ + +#ifdef WIN32 +#define _INC_OLE +#define __RPC_H__ +#endif + +#include +#include +#include "bttncur.h" +#include "bttncuri.h" + + +//Display sensitive information +TOOLDISPLAYDATA tdd; + +//Library instance +HINSTANCE ghInst; + + +//Cache GDI objects to speed drawing. +HDC hDCGlyphs = NULL; +HDC hDCMono = NULL; +HBRUSH hBrushDither = NULL; + +// Common clean up code +void FAR PASCAL WEP(int bSystemExit); + + +//Standard images to use in case caller doesn't provide them +HBITMAP rghBmpStandardImages[3]; + +//Standard button colors. +const COLORREF crStandard[4]={ RGB(0, 0, 0) //STDCOLOR_BLACK + , RGB(128, 128, 128) //STDCOLOR_DKGRAY + , RGB(192, 192, 192) //STDCOLOR_LTGRAY + , RGB(255, 255, 255)}; //STDCOLOR_WHITE + + +/* + * Mapping from image identifier to button type (command/attribute). + * Version 1.00 of this DLL has no attribute images defined, so + * the code will only support three states for each command + * button. Any state is, however, valid for an application + * defined image. + */ + +UINT mpButtonType[TOOLIMAGE_MAX-TOOLIMAGE_MIN+1]= + { + BUTTONTYPE_COMMAND, BUTTONTYPE_COMMAND, BUTTONTYPE_COMMAND, + BUTTONTYPE_COMMAND, BUTTONTYPE_COMMAND, BUTTONTYPE_COMMAND, + BUTTONTYPE_COMMAND, BUTTONTYPE_COMMAND, BUTTONTYPE_COMMAND + }; + + + +/* + * LibMain + * + * Purpose: + * Entry point conditionally compiled for Windows NT and Windows + * 3.1. Provides the proper structure for each environment + * and calls InternalLibMain for real initialization. + */ + +#ifdef WIN32 +BOOL _cdecl LibMain( + HINSTANCE hDll, + DWORD dwReason, + LPVOID lpvReserved) + { + if (DLL_PROCESS_ATTACH == dwReason) + { + return FInitialize(hDll); + } + else if (DLL_PROCESS_DETACH == dwReason) + { + WEP(0); + } + else + { + return TRUE; + } + } + +#else +HANDLE FAR PASCAL LibMain(HANDLE hInstance, WORD wDataSeg + , WORD cbHeapSize, LPSTR lpCmdLine) + { + //Perform global initialization. + if (FInitialize(hInstance)) + { + if (0!=cbHeapSize) + UnlockData(0); + } + + return hInstance; + } +#endif + + + + +/* + * FInitialize + * + * Purpose: + * Initialization function for the DLL. + * + * Parameters: + * hInstance HANDLE instance of the DLL. + * + * Return Value: + * BOOL TRUE if the function was successful, FALSE otherwise. + */ + +BOOL FInitialize(HANDLE hInstance) + { + UINT i; + + /* + * To remain backwards compatible with 1.0 we'll default to 96DPI + * like we forced in the older version. If the application calls + * UIToolButtonDraw we use the values here. If the application + * calls UIToolButtonDrawTDD then we use the pointer to the + * application-provided TOOLDISPLAYDATA structure. + */ + tdd.uDPI =96; + tdd.cyBar =CYBUTTONBAR96; + tdd.cxButton =TOOLBUTTON_STD96WIDTH; + tdd.cyButton =TOOLBUTTON_STD96HEIGHT; + tdd.cxImage =TOOLBUTTON_STD96IMAGEWIDTH; + tdd.cyImage =TOOLBUTTON_STD96IMAGEHEIGHT; + tdd.uIDImages=IDB_STANDARDIMAGES96; + + for (i=0; i < 3; i++) + { + rghBmpStandardImages[i]=LoadBitmap(hInstance + , MAKEINTRESOURCE(IDB_STANDARDIMAGESMIN+i)); + + if (NULL==rghBmpStandardImages[i]) + return FALSE; + } + + ghInst=hInstance; + + //Perform global initialization. + if (ToolButtonInit()) + { + CursorsCache(hInstance); + return TRUE; + } + + return FALSE; + } + + + + +/* + * WEP + * + * Purpose: + * Required DLL Exit function. Does nothing. + * + * Parameters: + * bSystemExit BOOL indicating if the system is being shut + * down or the DLL has just been unloaded. + * + * Return Value: + * void + * + */ + +void FAR PASCAL WEP(int bSystemExit) + { + /* + * **Developers: Note that WEP is called AFTER Windows does any + * automatic task cleanup. You may see warnings for + * that two DCs, a bitmap, and a brush, were not + * deleted before task termination. THIS IS NOT A + * PROBLEM WITH THIS CODE AND IT IS NOT A BUG. This + * WEP function is properly called and performs the + * cleanup as appropriate. The fact that Windows is + * calling WEP after checking task cleanup is not + * something we can control. Just to prove it, the + * OutputDebugStrings in this and ToolButtonFree + * show that the code is exercised. + */ + + #ifdef DEBUG + OutputDebugString("BTTNCUR.DLL: WEP Entry\r\n"); + OutputDebugString("BTTNCUR.DLL: The two DC's, the brush, and the three\r\n"); + OutputDebugString("BTTNCUR.DLL: bitmaps that Debug Windows shows\r\n"); + OutputDebugString("BTTNCUR.DLL: above were detected BEFORE this WEP\r\n"); + OutputDebugString("BTTNCUR.DLL: had a chance to do it! NOT A BUG!\r\n"); + #endif + + CursorsFree(); + ToolButtonFree(); + + #ifdef DEBUG + OutputDebugString("BTTNCUR.DLL: WEP Exit\r\n"); + #endif + return; + } + + + + + +/* + * UIToolConfigureForDisplay + * Public API + * + * Purpose: + * Initializes the library to scale button images for the display type. + * Without calling this function the library defaults to 96 DPI (VGA). + * By calling this function an application acknowledges that it must + * use the data returned from this function to configure itself for + * the display. + * + * Parameters: + * lpDD LPTOOLDISPLAYDATA to fill with the display-sensitive + * size values. + * + * Return Value: + * BOOL TRUE if the sizes were obtained, FALSE otherwise. + */ + +BOOL WINAPI UIToolConfigureForDisplay(LPTOOLDISPLAYDATA lpDD) + { + int cy; + HDC hDC; + + + if (NULL==lpDD || IsBadWritePtr(lpDD, sizeof(TOOLDISPLAYDATA))) + return FALSE; + + /* + * Determine the aspect ratio of the display we're currently + * running on and calculate the necessary information. + * + * By retrieving the logical Y extent of the display driver, you + * only have limited possibilities: + * LOGPIXELSY Display + * ---------------------------------------- + * 48 CGA (unsupported) + * 72 EGA + * 96 VGA + * 120 8514/a (i.e. HiRes VGA) + */ + + hDC=GetDC(NULL); + + if (NULL==hDC) + return FALSE; + + cy=GetDeviceCaps(hDC, LOGPIXELSY); + ReleaseDC(NULL, hDC); + + /* + * Instead of single comparisons, check ranges instead, so in case + * we get something funky, we'll act reasonable. + */ + if (72 >=cy) + { + lpDD->uDPI =72; + lpDD->cyBar =CYBUTTONBAR72; + lpDD->cxButton =TOOLBUTTON_STD72WIDTH; + lpDD->cyButton =TOOLBUTTON_STD72HEIGHT; + lpDD->cxImage =TOOLBUTTON_STD72IMAGEWIDTH; + lpDD->cyImage =TOOLBUTTON_STD72IMAGEHEIGHT; + lpDD->uIDImages=IDB_STANDARDIMAGES72; + } + else + { + if (72 < cy && 120 > cy) + { + lpDD->uDPI =96; + lpDD->cyBar =CYBUTTONBAR96; + lpDD->cxButton =TOOLBUTTON_STD96WIDTH; + lpDD->cyButton =TOOLBUTTON_STD96HEIGHT; + lpDD->cxImage =TOOLBUTTON_STD96IMAGEWIDTH; + lpDD->cyImage =TOOLBUTTON_STD96IMAGEHEIGHT; + lpDD->uIDImages=IDB_STANDARDIMAGES96; + } + else + { + lpDD->uDPI =120; + lpDD->cyBar =CYBUTTONBAR120; + lpDD->cxButton =TOOLBUTTON_STD120WIDTH; + lpDD->cyButton =TOOLBUTTON_STD120HEIGHT; + lpDD->cxImage =TOOLBUTTON_STD120IMAGEWIDTH; + lpDD->cyImage =TOOLBUTTON_STD120IMAGEHEIGHT; + lpDD->uIDImages=IDB_STANDARDIMAGES120; + } + } + + return TRUE; + } + + + + + + + + +/* + * ToolButtonInit + * Internal + * + * Purpose: + * Initializes GDI objects for drawing images through UIToolButtonDraw. + * If the function fails, the function has already performed proper + * cleanup. + * + * Parameters: + * None + * + * Return Value: + * BOOL TRUE if initialization succeeded. FALSE otherwise. + */ + +static BOOL ToolButtonInit(void) + { + COLORREF rgbHi; + + //DC for BitBltting the image (the glyph) + hDCGlyphs=CreateCompatibleDC(NULL); + + //Create a monochrome DC and a brush for doing pattern dithering. + hDCMono=CreateCompatibleDC(NULL); + + //Windows 3.0 doesn't support COLOR_BTNHIGHLIGHT, so leave it white. + if (0x0300 < (UINT)GetVersion()) + rgbHi=GetSysColor(COLOR_BTNHIGHLIGHT); + else + rgbHi=crStandard[STDCOLOR_WHITE]; + + hBrushDither=HBrushDitherCreate(GetSysColor(COLOR_BTNFACE), rgbHi); + + if (NULL==hDCGlyphs || NULL==hDCMono || NULL==hBrushDither) + { + //On failure, cleanup whatever might have been allocated. + ToolButtonFree(); + return FALSE; + } + + return TRUE; + } + + + + + +/* + * ToolButtonFree + * Internal + * + * Purpose: + * Free all GDI allocations made during initialization. Note that the + * DEBUG output included here shows that WEP is called and cleanup actually + * occurs. However, if you watch debug output in DBWIN or on a terminal, + * the debugging version of Windows does automatic app cleanup before WEP + * is called, leading some to believe that this code is buggy. The + * debug output below shows that we do perform all necessary cleanup. + * + * Parameters: + * None + * + * Return Value: + * None + */ + +static void ToolButtonFree(void) + { + UINT i; + + if (NULL!=hDCMono) + DeleteDC(hDCMono); + + hDCMono=NULL; + + if (NULL!=hDCGlyphs) + DeleteDC(hDCGlyphs); + + hDCGlyphs=NULL; + + if (NULL!=hBrushDither) + DeleteObject(hBrushDither); + + hBrushDither=NULL; + + for (i=0; i < 3; i++) + { + if (NULL!=rghBmpStandardImages[i]) + DeleteObject(rghBmpStandardImages[i]); + rghBmpStandardImages[i]=NULL; + } + + return; + } + + + + + +/* + * HBrushDitherCreate + * Internal + * + * Purpose: + * Creates and returns a handle to a pattern brush created from + * an 8*8 monochrome pattern bitmap. We use the button face and + * highlight colors to indicate the resulting colors of a PatBlt + * using this brush. + * + * Parameters: + * rgbFace COLORREF of the button face color. + * rgbHilight COLORREF of the button highlight color. + * + * Return Value: + * HBITMAP Handle to the dither bitmap. + */ + +static HBRUSH HBrushDitherCreate(COLORREF rgbFace, COLORREF rgbHilight) + { + struct //BITMAPINFO with 16 colors + { + BITMAPINFOHEADER bmiHeader; + RGBQUAD bmiColors[16]; + } bmi; + + HBRUSH hBrush=NULL; + DWORD patGray[8]; + HDC hDC; + HBITMAP hBmp; + static COLORREF rgbFaceOld =0xFFFFFFFF; //Initially an impossible color + static COLORREF rgbHilightOld=0xFFFFFFFF; //so at first we always create + + /* + * If the colors haven't changed from last time, just return the + * existing brush. + */ + if (rgbFace==rgbFaceOld && rgbHilight==rgbHilightOld) + return hBrushDither; + + rgbFaceOld=rgbFace; + rgbHilightOld=rgbHilight; + + /* + * We're going to create an 8*8 brush for PatBlt using the + * button face color and button highlight color. We use this + * brush to affect the pressed state and the disabled state. + */ + bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmi.bmiHeader.biWidth = 8; + bmi.bmiHeader.biHeight = 8; + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 1; + bmi.bmiHeader.biCompression = BI_RGB; + bmi.bmiHeader.biSizeImage = 0; + bmi.bmiHeader.biXPelsPerMeter= 0; + bmi.bmiHeader.biYPelsPerMeter= 0; + bmi.bmiHeader.biClrUsed = 0; + bmi.bmiHeader.biClrImportant = 0; + + bmi.bmiColors[0].rgbBlue = GetBValue(rgbFace); + bmi.bmiColors[0].rgbGreen = GetGValue(rgbFace); + bmi.bmiColors[0].rgbRed = GetRValue(rgbFace); + bmi.bmiColors[0].rgbReserved = 0; + + bmi.bmiColors[1].rgbBlue = GetBValue(rgbHilight); + bmi.bmiColors[1].rgbGreen = GetGValue(rgbHilight); + bmi.bmiColors[1].rgbRed = GetRValue(rgbHilight); + bmi.bmiColors[1].rgbReserved = 0; + + //Create the byte array for CreateDIBitmap. + patGray[6]=patGray[4]=patGray[2]=patGray[0]=0x5555AAAAL; + patGray[7]=patGray[5]=patGray[3]=patGray[1]=0xAAAA5555L; + + //Create the bitmap + hDC=GetDC(NULL); + hBmp=CreateDIBitmap(hDC, &bmi.bmiHeader, CBM_INIT, patGray + , (LPBITMAPINFO)&bmi, DIB_RGB_COLORS); + ReleaseDC(NULL, hDC); + + //Create the brush from the bitmap + if (NULL!=hBmp) + { + hBrush=CreatePatternBrush(hBmp); + DeleteObject(hBmp); + } + + /* + * If we could recreate a brush, clean up and make it the current + * pattern. Otherwise the best we can do it return the old one, + * which will be colored wrong, but at least it works. + */ + if (NULL!=hBrush) + { + if (NULL!=hBrushDither) + DeleteObject(hBrushDither); + + hBrushDither=hBrush; + } + + return hBrushDither; + } + + + + + +/* + * UIToolButtonDraw + * Public API + * + * Purpose: + * Draws the complete image of a toolbar-style button with a given + * image in the center and in a specific state. The button is drawn + * on a specified hDC at a given location, so this function is useful + * on standard owner-draw buttons as well as on toolbar controls that + * have only one window but show images of multiple buttons. + * + * Parameters: + * hDC HDC on which to draw. + * x, y int coordinates at which to draw. + * dx, dy int dimensions of the *button*, not necessarily the image. + * hBmp HBITMAP from which to draw the image. + * bmx, bmy int dimensions of each bitmap in hBmp. If hBmp is NULL + * then these are forced to the standard sizes. + * iImage int index to the image to draw in the button + * uStateIn UINT containing the state index for the button and the + * color control bits. + * + * Return Value: + * BOOL TRUE if drawing succeeded, FALSE otherwise meaning that + * hDC is NULL or hBmp is NULL and iImage is not a valid + * index for a standard image. + */ + +BOOL WINAPI UIToolButtonDraw(HDC hDC, int x, int y, int dx, int dy + , HBITMAP hBmp, int bmx, int bmy, int iImage, UINT uStateIn) + { + return UIToolButtonDrawTDD(hDC, x, y, dx, dy, hBmp, bmx, bmy, iImage + , uStateIn, &tdd); + } + + + + + + +/* + * UIToolButtonDrawTDD + * Public API + * + * Purpose: + * Draws the complete image of a toolbar-style button with a given + * image in the center and in a specific state. The button is drawn + * on a specified hDC at a given location, so this function is useful + * on standard owner-draw buttons as well as on toolbar controls that + * have only one window but show images of multiple buttons. + * + * This is the same as UIToolButtonDraw but adds the pTDD configuration + * structure. UIToolButtonDraw calls us with that pointing to the + * default 96dpi structure. + * + * Parameters: + * hDC HDC on which to draw. + * x, y int coordinates at which to draw. + * dx, dy int dimensions of the *button*, not necessarily the image. + * hBmp HBITMAP from which to draw the image. + * bmx, bmy int dimensions of each bitmap in hBmp. If hBmp is NULL + * then these are forced to the standard sizes. + * iImage int index to the image to draw in the button + * uStateIn UINT containing the state index for the button and the + * color control bits. + * pTDD LPTOOLDISPLAYDATA containing display configuration. + * Can be NULL if hBmp is non-NULL. + * + * Return Value: + * BOOL TRUE if drawing succeeded, FALSE otherwise meaning that + * hDC is NULL or hBmp is NULL and iImage is not a valid + * index for a standard image. + */ + +BOOL WINAPI UIToolButtonDrawTDD(HDC hDC, int x, int y, int dx, int dy + , HBITMAP hBmp, int bmx, int bmy, int iImage, UINT uStateIn + , LPTOOLDISPLAYDATA pTDD) + { + static COLORREF crSys[5]; //Avoid stack arrays in DLLs: use static + UINT uState=(UINT)LOBYTE((WORD)uStateIn); + UINT uColors=(UINT)HIBYTE((WORD)uStateIn & PRESERVE_ALL); + int xOffsetGlyph, yOffsetGlyph; + int i, iSaveDC; + HDC hMemDC; + HGDIOBJ hObj; + HBRUSH hBR; + HBITMAP hBmpT; + HBITMAP hBmpMono; + HBITMAP hBmpMonoOrg; + HBITMAP hBmpSave=NULL; + + if (NULL==hDC) + return FALSE; + + /* + * If we're given no image bitmap, then use the standard and validate the + * image index. We also enforce the standard bitmap size and the size of + * the button (as requested by User Interface designers). + */ + if (NULL==hBmp && !(uState & BUTTONGROUP_BLANK)) + { + hBmp=rghBmpStandardImages[pTDD->uIDImages-IDB_STANDARDIMAGESMIN]; + + bmx=pTDD->cxImage; //Force bitmap dimensions + bmy=pTDD->cyImage; + + dx=pTDD->cxButton; //Force button dimensions + dy=pTDD->cyButton; + + if (iImage > TOOLIMAGE_MAX) + return FALSE; + + /* + * If we are using a standard command button, verify that the state + * does not contain the LIGHTFACE group which only applies to + * attribute buttons. + */ + if (BUTTONTYPE_COMMAND==mpButtonType[iImage] + && (uState & BUTTONGROUP_LIGHTFACE)) + return FALSE; + } + + //Create a dithered bitmap. + hBmpMono=CreateBitmap(dx-2, dy-2, 1, 1, NULL); + + if (NULL==hBmpMono) + return FALSE; + + hBmpMonoOrg=(HBITMAP)SelectObject(hDCMono, hBmpMono); + + + //Save the DC state before we munge on it. + iSaveDC=SaveDC(hDC); + + /* + * Draw a button sans image. This also fills crSys with the system + * colors for us which has space for five colors. We don't use the + * fifth, the frame color, in this function. + */ + DrawBlankButton(hDC, x, y, dx, dy, (BOOL)(uState & BUTTONGROUP_DOWN), crSys); + + //Shift coordinates to account for the button's border + x++; + y++; + dx-=2; + dy-=2; + + /* + * Determine the offset necessary to center the image but also reflect + * the pushed-in state, which means just adding 1 to the up state. + */ + i=(uState & BUTTONGROUP_DOWN) ? 1 : 0; + xOffsetGlyph=((dx-bmx) >> 1)+i; + yOffsetGlyph=((dy-bmy) >> 1)+i; + + + //Select the given image bitmap into the glyph DC before calling MaskCreate + if (NULL!=hBmp) + hBmpSave=(HBITMAP)SelectObject(hDCGlyphs, hBmp); + + + /* + * Draw the face on the button. If we have an up or [mouse]down + * button then we can just draw it as-is. For indeterminate, + * disabled, or down disabled we have to gray the image and possibly + * add a white shadow to it (disabled/down disabled). + * + * Also note that for the intermediate state we first draw the normal + * up state, then proceed to add disabling looking highlights. + */ + + //Up, mouse down, down, indeterminate + if ((uState & BUTTONGROUP_ACTIVE) && !(uState & BUTTONGROUP_BLANK)) + { + BOOL fColorsSame=TRUE; + + /* + * In here we pay close attention to the system colors. Where + * the source image is black, we paint COLOR_BTNTEXT. Where + * light gray, we paint COLOR_BTNFACE. Where dark gray we paint + * COLOR_BTNSHADOW, and where white we paint COLOR_BTNHILIGHT. + * + * The uColors variable contains flags to prevent color + * conversion. To do a little optimization, we just do a + * single BitBlt if we're preserving all colors or if no colors + * are different than the standards, which is by far the most + * common case. Otherwise, cycle through the four colors we can + * convert and do a BitBlt that converts it to the system color. + */ + + //See what colors are different. + for (i=STDCOLOR_BLACK; i<=STDCOLOR_WHITE; i++) + fColorsSame &= (crSys[i]==crStandard[i]); + + if (PRESERVE_ALL==uColors || fColorsSame) + { + BitBlt(hDC, x+xOffsetGlyph, y+yOffsetGlyph, bmx, bmy + , hDCGlyphs, iImage*bmx, 0, SRCCOPY); + } + else + { + /* + * Cycle through hard-coded colors and create a mask that has all + * regions of that color in white and all other regions black. + * Then we select a pattern brush of the color to convert to: + * if we aren't converting the color then we use a brush of + * the standard hard-coded color, otherwise we use the actual + * system color. The ROP_DSPDxax means that anything that's + * 1's in the mask get the pattern, anything that's 0 is unchanged + * in the destination. + * + * To prevent too many Blts to the screen, we use an intermediate + * bitmap and DC. + */ + + hMemDC=CreateCompatibleDC(hDC); + + //Make sure conversion of monochrome to color stays B&W + SetTextColor(hMemDC, 0L); //0's in mono -> 0 + SetBkColor(hMemDC, (COLORREF)0x00FFFFFF); //1's in mono -> 1 + + hBmpT=CreateCompatibleBitmap(hDC, bmx, bmy); + SelectObject(hMemDC, hBmpT); + + //Copy the unmodified bitmap to the temporary bitmap + BitBlt(hMemDC, 0, 0, bmx, bmy, hDCGlyphs, iImage*bmx, 0, SRCCOPY); + + for (i=STDCOLOR_BLACK; i<=STDCOLOR_WHITE; i++) + { + //Convert pixels of the color to convert to 1's in the mask + SetBkColor(hDCGlyphs, crStandard[i]); + BitBlt(hDCMono, 0, 0, bmx, bmy, hDCGlyphs, iImage*bmx, 0, SRCCOPY); + + //Preserve or modify the color depending on the flag. + hBR=CreateSolidBrush((uColors & (1 << i)) + ? crStandard[i] : crSys[i]); + + if (NULL!=hBR) + { + hObj=SelectObject(hMemDC, hBR); + + if (NULL!=hObj) + { + BitBlt(hMemDC, 0, 0, dx-1, dy-1, hDCMono, 0, 0, ROP_DSPDxax); + SelectObject(hMemDC, hObj); + } + + DeleteObject(hBR); + } + } + + //Now put the final version on the display and clean up + BitBlt(hDC, x+xOffsetGlyph, y+yOffsetGlyph, dx-1, dy-1 + , hMemDC, 0, 0, SRCCOPY); + + DeleteDC(hMemDC); + DeleteObject(hBmpT); + + } + } + + + //Disabled and indeterminate states (unless we're blank) + if ((uState & BUTTONGROUP_DISABLED || ATTRIBUTEBUTTON_INDETERMINATE==uState) + && !(uState & BUTTONGROUP_BLANK)) + { + //Grayed state (up or down, no difference) + MaskCreate(iImage, dx, dy, bmx, bmy, xOffsetGlyph, yOffsetGlyph, 0); + + //Make sure conversion of monochrome to color stays B&W + SetTextColor(hDC, 0L); //0's in mono -> 0 + SetBkColor(hDC, (COLORREF)0x00FFFFFF); //1's in mono -> 1 + + //If we're disabled, up or down, draw the highlighted shadow. + if (uState & BUTTONGROUP_DISABLED) + { + hBR=CreateSolidBrush(crSys[SYSCOLOR_HILIGHT]); + + if (NULL!=hBR) + { + hObj=SelectObject(hDC, hBR); + + if (NULL!=hObj) + { + //Draw hilight color where we have 0's in the mask + BitBlt(hDC, x+1, y+1, dx-2, dy-2, hDCMono, 0, 0, ROP_PSDPxax); + SelectObject(hDC, hObj); + } + DeleteObject(hBR); + } + } + + //Draw the gray image. + hBR=CreateSolidBrush(crSys[SYSCOLOR_SHADOW]); + + if (NULL!=hBR) + { + hObj=SelectObject(hDC, hBR); + + if (NULL!=hObj) + { + //Draw the shadow color where we have 0's in the mask + BitBlt(hDC, x, y, dx-2, dy-2, hDCMono, 0, 0, ROP_PSDPxax); + SelectObject(hDC, hObj); + } + + DeleteObject(hBR); + } + } + + //If the button is selected do the dither brush avoiding the glyph + if (uState & BUTTONGROUP_LIGHTFACE) + { + HBRUSH hBRDither; + + /* + * Get the dither brush. This function will recreate it if + * necessary or return the global one if the colors already match. + */ + hBRDither=HBrushDitherCreate(crSys[SYSCOLOR_FACE], crSys[SYSCOLOR_HILIGHT]); + hObj=SelectObject(hDC, hBRDither); + + if (NULL!=hObj) + { + /* + * The mask we create now determines where the dithering + * ends up. In the down disabled state, we have to preserve + * the highlighted shadow, so the mask we create must have + * two masks of the original glyph, one of them offset by + * one pixel in both x & y. For the indeterminate state, + * we have to mask all highlighted areas. The state passed + * to MaskCreate matters here (we've used zero before). + */ + MaskCreate(iImage, dx, dy, bmx, bmy + , xOffsetGlyph-1, yOffsetGlyph-1, uState); + + //Convert monochrome masks to B&W color bitmap in the BitBlt. + SetTextColor(hDC, 0L); + SetBkColor(hDC, (COLORREF)0x00FFFFFF); + + /* + * Only draw the dither brush where the mask is 1's. For + * the indeterminate state we have to not overdraw the + * shadow highlight so we use dx-3, dy-3 instead of dx-1 + * and dy-1. We do this whether or not we're blank. + */ + i=(ATTRIBUTEBUTTON_INDETERMINATE==uState + || BLANKBUTTON_INDETERMINATE==uState) ? 3 : 1; + + BitBlt(hDC, x+1, y+1, dx-i, dy-i, hDCMono, 0, 0, ROP_DSPDxax); + SelectObject(hDC, hObj); + } + + //DO NOT delete hBRDither! It's a reference to a shared global. + } + + //Cleanup hDCGlyphs: Must do AFTER calling MaskCreate + if (NULL!=hBmpSave) + SelectObject(hDCGlyphs, hBmpSave); + + SelectObject(hDCMono, hBmpMonoOrg); + DeleteObject(hBmpMono); + + //Restore everything in the DC. + RestoreDC(hDC, iSaveDC); + return TRUE; + } + + + + + + +/* + * DrawBlankButton + * + * Purpose: + * Draws a button with no face using the current system colors in either + * an up or down state. + * + * Parameters: + * hDC HDC on which to draw + * x, y int coordinates where we start drawing + * dx,dy int size of the button + * fDown BOOL indicating the up or down state of the button + * pcr COLORREF FAR * to five colors in which we store text, + * shadow, face, highlight, and frame colors. This is + * a matter of convenience for the caller, since we have + * to load these colors anyway we might as well send them + * back. + * + * Return Value: + * None + */ + +static void DrawBlankButton(HDC hDC, int x, int y, int dx, int dy + , BOOL fDown, COLORREF FAR *pcr) + { + //Get the current system colors for buttons. + pcr[0]=GetSysColor(COLOR_BTNTEXT); + pcr[1]=GetSysColor(COLOR_BTNSHADOW); + pcr[2]=GetSysColor(COLOR_BTNFACE); + + //Windows 3.0 doesn't support COLOR_BTNHIGHLIGHT, so leave it white. + if (0x0300 < (UINT)GetVersion()) + pcr[3]=GetSysColor(COLOR_BTNHIGHLIGHT); + else + pcr[3]=crStandard[STDCOLOR_WHITE]; + + pcr[4]=GetSysColor(COLOR_WINDOWFRAME); + + //Draw the border around the button. + PatB(hDC, x+1, y, dx-2, 1, pcr[4]); + PatB(hDC, x+1, y+dy-1, dx-2, 1, pcr[4]); + PatB(hDC, x, y+1, 1, dy-2, pcr[4]); + PatB(hDC, x+dx-1, y+1, 1, dy-2, pcr[4]); + + //Shift coordinates to account for the border we just drew + x++; + y++; + dx-=2; + dy-=2; + + //Paint the interior grey as a default. + PatB(hDC, x, y, dx, dy, pcr[2]); + + /* + * Draw shadows and highlights. The DOWN grouping that contains + * down, mouse down, and down disabled are drawn depressed. Up, + * indeterminate, and disabled are drawn up. + */ + + if (fDown) + { + PatB(hDC, x, y, 1, dy, pcr[1]); + PatB(hDC, x, y, dx, 1, pcr[1]); + } + else + { + //Normal button look. + PatB(hDC, x, y, 1, dy-1, pcr[3]); + PatB(hDC, x, y, dx-1, 1, pcr[3]); + + PatB(hDC, x+dx-1, y, 1, dy, pcr[1]); + PatB(hDC, x, y+dy-1, dx, 1, pcr[1]); + + PatB(hDC, x+1+dx-3, y+1, 1, dy-2, pcr[1]); + PatB(hDC, x+1, y+dy-2, dx-2, 1, pcr[1]); + } + + return; + } + + + + + + +/* + * PatB + * Internal + * + * Purpose: + * A more convenient PatBlt operation for drawing button borders and + * highlights. + * + * Parameters: + * hDC HDC on which to paint. + * x, y int coordinates at which to paint. + * dx, dy int dimensions of rectangle to paint. + * rgb COLORREF to use as the background color. + * + * Return Value: + * None + */ + +static void PatB(HDC hDC, int x, int y, int dx, int dy, COLORREF rgb) + { + RECT rc; + + SetBkColor(hDC, rgb); + SetRect(&rc, x, y, x+dx, y+dy); + ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL); + } + + + + +/* + * MaskCreate + * Internal + * + * Purpose: + * Creates a monochrome mask bitmap of the given image at the given offset + * in the global hDCMono. Anywhere in the image that you have the light + * gray (STDCOLOR_LTGRAY) or the white highlight (STDCOLOR_WHITE) you get + * get 1's. All other pixels are 0's + * + * Parameters: + * iImage UINT index of the image for which to create a mask. + * dx, dy int dimensions of the button. + * bmx, bmy int dimensions of the bitmap to use. + * xOffset int offset for x inside hDCMono where we paint. + * yOffset int offset for y inside hDCMono where we paint. + * uState UINT state of the image. Special cases are made + * for ATTRIBUTEBUTTON_DOWNDISABLED and + * ATTRIBUTEBUTTON_INDETERMINATE. In any case where you + * do not want a special case, pass zero here, regardless + * of the true button state. + * + * Return Value: + * None + */ + +static void MaskCreate(UINT iImage, int dx, int dy, int bmx, int bmy + ,int xOffset, int yOffset, UINT uState) + { + //Initalize whole area with zeros + PatBlt(hDCMono, 0, 0, dx, dy, WHITENESS); + + if (uState & BUTTONGROUP_BLANK) + return; + + //Convert face colored pixels to 1's. all others to black. + SetBkColor(hDCGlyphs, crStandard[STDCOLOR_LTGRAY]); + BitBlt(hDCMono, xOffset, yOffset, bmx, bmy, hDCGlyphs, iImage*bmx, 0, SRCCOPY); + + //In the indeterminate state, don't turn highlight's to 1's. Leave black. + if (ATTRIBUTEBUTTON_INDETERMINATE!=uState) + { + //Convert highlight colored pixels to 1's and OR them with the previous. + SetBkColor(hDCGlyphs, crStandard[STDCOLOR_WHITE]); + BitBlt(hDCMono, xOffset, yOffset, bmx, bmy, hDCGlyphs, iImage*bmx, 0, SRCPAINT); + } + + /* + * For the down disabled state, AND this same mask with itself at an + * offset of 1, which accounts for the highlight shadow. + */ + if (ATTRIBUTEBUTTON_DOWNDISABLED==uState) + BitBlt(hDCMono, 1, 1, dx-1, dy-1, hDCMono, 0, 0, SRCAND); + + return; + } diff --git a/private/oleutest/letest/bttncur/bttncur.h b/private/oleutest/letest/bttncur/bttncur.h new file mode 100644 index 000000000..a9685c971 --- /dev/null +++ b/private/oleutest/letest/bttncur/bttncur.h @@ -0,0 +1,201 @@ +/* + * BTTNCUR.H + * Buttons & Cursors Version 1.1, March 1993 + * + * Public include file for the Button Images and Cursor DLL, including + * structures, definitions, and function prototypes. + * + * Copyright (c)1992-1993 Microsoft Corporation, All Rights Reserved, + * as applied to redistribution of this source code in source form + * License is granted to use of compiled code in shipped binaries. + */ + + +#ifndef _BTTNCUR_H_ +#define _BTTNCUR_H_ + +#ifdef __cplusplus +extern "C" + { +#endif + + +//Standard image bitmap + +//WARNING: Obsolete. Use the return from UIToolDisplayData +#define IDB_STANDARDIMAGES 400 + +//New values for display types +#define IDB_STANDARDIMAGESMIN 400 +#define IDB_STANDARDIMAGES96 400 +#define IDB_STANDARDIMAGES72 401 +#define IDB_STANDARDIMAGES120 402 + + + +//Image indices inside the standard bitmap. +#define TOOLIMAGE_MIN 0 +#define TOOLIMAGE_EDITCUT 0 +#define TOOLIMAGE_EDITCOPY 1 +#define TOOLIMAGE_EDITPASTE 2 +#define TOOLIMAGE_FILENEW 3 +#define TOOLIMAGE_FILEOPEN 4 +#define TOOLIMAGE_FILESAVE 5 +#define TOOLIMAGE_FILEPRINT 6 +#define TOOLIMAGE_HELP 7 +#define TOOLIMAGE_HELPCONTEXT 8 +#define TOOLIMAGE_MAX 8 + + +//Additional Standard Cursors as defined in the UI Design Guide. +#define IDC_NEWUICURSORMIN 500 +#define IDC_RIGHTARROW 500 +#define IDC_CONTEXTHELP 501 +#define IDC_MAGNIFY 502 +#define IDC_NODROP 503 +#define IDC_TABLETOP 504 +#define IDC_HSIZEBAR 505 +#define IDC_VSIZEBAR 506 +#define IDC_HSPLITBAR 507 +#define IDC_VSPLITBAR 508 +#define IDC_SMALLARROWS 509 +#define IDC_LARGEARROWS 510 +#define IDC_HARROWS 511 +#define IDC_VARROWS 512 +#define IDC_NESWARROWS 513 +#define IDC_NWSEARROWS 514 +#define IDC_NEWUICURSORMAX 514 + + + +//Standard sizes for toolbar buttons and bitmaps on display types + +//WARNING: These are obsolete for version 1.0 compatibility/ +#define TOOLBUTTON_STDWIDTH 24 +#define TOOLBUTTON_STDHEIGHT 22 +#define TOOLBUTTON_STDIMAGEWIDTH 16 +#define TOOLBUTTON_STDIMAGEHEIGHT 15 + +/* + * Applications can call UIToolDisplayData to get the particular + * values to use for the current display instead of using these values + * directly. However, if the application has the aspect ratio already + * then these are available for them. + */ + +//Sizes for 72 DPI (EGA) +#define TOOLBUTTON_STD72WIDTH 24 +#define TOOLBUTTON_STD72HEIGHT 16 +#define TOOLBUTTON_STD72IMAGEWIDTH 16 +#define TOOLBUTTON_STD72IMAGEHEIGHT 11 + +//Sizes for 96 DPI (VGA) +#define TOOLBUTTON_STD96WIDTH 24 +#define TOOLBUTTON_STD96HEIGHT 22 +#define TOOLBUTTON_STD96IMAGEWIDTH 16 +#define TOOLBUTTON_STD96IMAGEHEIGHT 15 + +//Sizes for 120 DPI (8514/a) +#define TOOLBUTTON_STD120WIDTH 32 +#define TOOLBUTTON_STD120HEIGHT 31 +#define TOOLBUTTON_STD120IMAGEWIDTH 24 +#define TOOLBUTTON_STD120IMAGEHEIGHT 23 + + +//Sizes of a standard button bar depending on the display +#define CYBUTTONBAR72 23 +#define CYBUTTONBAR96 29 +#define CYBUTTONBAR120 38 + + + +/* + * The low-word of the state contains the display state where each + * value is mutually exclusive and contains one or more grouping bits. + * Each group represents buttons that share some sub-state in common. + * + * The high-order byte controls which colors in the source bitmap, + * black, white, gray, and dark gray, are to be converted into the + * system colors COLOR_BTNTEXT, COLOR_HILIGHT, COLOR_BTNFACE, and + * COLOR_BTNSHADOW. Any or all of these bits may be set to allow + * the application control over specific colors. + * + * The actual state values are split into a command group and an + * attribute group. Up, mouse down, and disabled states are identical, + * but only attributes can have down, down disabled, and indeterminate + * states. + * + * BUTTONGROUP_BLANK is defined so an application can draw only the button + * without an image in the up, down, mouse down, or indeterminate + * state, that is, BUTTONGROUP_BLANK is inclusive with BUTTONGROUP_DOWN + * and BUTTONGROUP_LIGHTFACE. + */ + + +#define BUTTONGROUP_DOWN 0x0001 +#define BUTTONGROUP_ACTIVE 0x0002 +#define BUTTONGROUP_DISABLED 0x0004 +#define BUTTONGROUP_LIGHTFACE 0x0008 +#define BUTTONGROUP_BLANK 0x0010 + +//Command buttons only +#define COMMANDBUTTON_UP (BUTTONGROUP_ACTIVE) +#define COMMANDBUTTON_MOUSEDOWN (BUTTONGROUP_ACTIVE | BUTTONGROUP_DOWN) +#define COMMANDBUTTON_DISABLED (BUTTONGROUP_DISABLED) + +//Attribute buttons only +#define ATTRIBUTEBUTTON_UP (BUTTONGROUP_ACTIVE) +#define ATTRIBUTEBUTTON_MOUSEDOWN (BUTTONGROUP_ACTIVE | BUTTONGROUP_DOWN) +#define ATTRIBUTEBUTTON_DISABLED (BUTTONGROUP_DISABLED) +#define ATTRIBUTEBUTTON_DOWN (BUTTONGROUP_ACTIVE | BUTTONGROUP_DOWN | BUTTONGROUP_LIGHTFACE) +#define ATTRIBUTEBUTTON_INDETERMINATE (BUTTONGROUP_ACTIVE | BUTTONGROUP_LIGHTFACE) +#define ATTRIBUTEBUTTON_DOWNDISABLED (BUTTONGROUP_DISABLED | BUTTONGROUP_DOWN | BUTTONGROUP_LIGHTFACE) + +//Blank buttons only +#define BLANKBUTTON_UP (BUTTONGROUP_ACTIVE | BUTTONGROUP_BLANK) +#define BLANKBUTTON_DOWN (BUTTONGROUP_ACTIVE | BUTTONGROUP_BLANK | BUTTONGROUP_DOWN | BUTTONGROUP_LIGHTFACE) +#define BLANKBUTTON_MOUSEDOWN (BUTTONGROUP_ACTIVE | BUTTONGROUP_BLANK | BUTTONGROUP_DOWN) +#define BLANKBUTTON_INDETERMINATE (BUTTONGROUP_ACTIVE | BUTTONGROUP_BLANK | BUTTONGROUP_LIGHTFACE) + + +/* + * Specific bits to prevent conversions of specific colors to system + * colors. If an application uses this newer library and never specified + * any bits, then they benefit from color conversion automatically. + */ +#define PRESERVE_BLACK 0x0100 +#define PRESERVE_DKGRAY 0x0200 +#define PRESERVE_LTGRAY 0x0400 +#define PRESERVE_WHITE 0x0800 + +#define PRESERVE_ALL (PRESERVE_BLACK | PRESERVE_DKGRAY | PRESERVE_LTGRAY | PRESERVE_WHITE) +#define PRESERVE_NONE 0 //Backwards compatible + + + +//Structure for UIToolConfigureForDisplay +typedef struct tagTOOLDISPLAYDATA + { + UINT uDPI; //Display driver DPI + UINT cyBar; //Vertical size for a bar containing buttons. + UINT cxButton; //Dimensions of a button. + UINT cyButton; + UINT cxImage; //Dimensions of bitmap image + UINT cyImage; + UINT uIDImages; //Standard resource ID for display-sensitive images + } TOOLDISPLAYDATA, FAR *LPTOOLDISPLAYDATA; + + + +//Public functions in BTTNCUR.DLL +HCURSOR WINAPI UICursorLoad(UINT); +BOOL WINAPI UIToolConfigureForDisplay(LPTOOLDISPLAYDATA); +BOOL WINAPI UIToolButtonDraw(HDC, int, int, int, int, HBITMAP, int, int, int, UINT); +BOOL WINAPI UIToolButtonDrawTDD(HDC, int, int, int, int, HBITMAP, int, int, int, UINT, LPTOOLDISPLAYDATA); + + +#ifdef __cplusplus + } +#endif + +#endif //_BTTNCUR_H_ diff --git a/private/oleutest/letest/bttncur/bttncur.rc b/private/oleutest/letest/bttncur/bttncur.rc new file mode 100644 index 000000000..38ddfc2a9 --- /dev/null +++ b/private/oleutest/letest/bttncur/bttncur.rc @@ -0,0 +1,39 @@ +/* + * BTTNCUR.RC + * Buttons & Cursors Version 1.1, March 1993 + * + * Resource file for the Button Image & Cursors DLL, including cursors and + * standard bitmaps. + * + * Copyright (c)1992-1993 Microsoft Corporation, All Rights Reserved, + * as applied to redistribution of this source code in source form + * License is granted to use of compiled code in shipped binaries. + */ + +#include +#include "bttncur.h" +#include "bttncuri.h" + +IDB_STANDARDIMAGES72 BITMAP res\stdim72.bmp +IDB_STANDARDIMAGES96 BITMAP res\stdim96.bmp +IDB_STANDARDIMAGES120 BITMAP res\stdim120.bmp + +IDC_RIGHTARROW CURSOR res\rarrow.cur +IDC_CONTEXTHELP CURSOR res\help.cur +IDC_MAGNIFY CURSOR res\magnify.cur +IDC_NODROP CURSOR res\nodrop.cur +IDC_TABLETOP CURSOR res\tabletop.cur +IDC_HSIZEBAR CURSOR res\sizebarh.cur +IDC_VSIZEBAR CURSOR res\sizebarv.cur +IDC_HSPLITBAR CURSOR res\splith.cur +IDC_VSPLITBAR CURSOR res\splitv.cur +IDC_SMALLARROWS CURSOR res\sarrows.cur +IDC_LARGEARROWS CURSOR res\larrows.cur +IDC_HARROWS CURSOR res\harrows.cur +IDC_VARROWS CURSOR res\varrows.cur +IDC_NESWARROWS CURSOR res\neswarrs.cur +IDC_NWSEARROWS CURSOR res\nwsearrs.cur + + +//Include the version information +rcinclude bttncur.rcv diff --git a/private/oleutest/letest/bttncur/bttncur.rcv b/private/oleutest/letest/bttncur/bttncur.rcv new file mode 100644 index 000000000..7e3fcea4b --- /dev/null +++ b/private/oleutest/letest/bttncur/bttncur.rcv @@ -0,0 +1,48 @@ +/* + * BTTNCUR.RCV + * Buttons & Cursors Version 1.1, Win32 version August 1993 + * + * Version resource file for the Button Images and Cursors DLL. + * + * Copyright (c)1992-1993 Microsoft Corporation, All Rights Reserved, + * as applied to redistribution of this source code in source form + * License is granted to use of compiled code in shipped binaries. + */ + +//Default is nodebug +#ifndef DEBUG +#define VER_DEBUG 0 +#else +#define VER_DEBUG VS_FF_DEBUG +#endif + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,1,0,0 + PRODUCTVERSION 1,1,0,0 + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK + FILEFLAGS VER_DEBUG + FILEOS VOS_DOS_WINDOWS16 + FILETYPE VFT_DLL + FILESUBTYPE VFT_UNKNOWN + + BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + BEGIN + VALUE "CompanyName", "Microsoft Corporation\0", "\0" + VALUE "FileDescription", "Microsoft Windows(TM) Standard Button Images and Cursors", "\0" + VALUE "FileVersion", "1.10\0", "\0" + VALUE "InternalName", "BTTNCUR.DLL", "\0" + VALUE "LegalCopyright", "Copyright \251 1993 Microsoft Corp.", "\0" + VALUE "OriginalFilename","BTTNCUR.DLL", "\0" + VALUE "ProductName", "Microsoft Windows(TM) Standard Button Images and Cursors", "\0" + VALUE "ProductVersion", "1.10\0" + END + END + + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 0x04E4 + END + END diff --git a/private/oleutest/letest/bttncur/bttncuri.h b/private/oleutest/letest/bttncur/bttncuri.h new file mode 100644 index 000000000..53d088712 --- /dev/null +++ b/private/oleutest/letest/bttncur/bttncuri.h @@ -0,0 +1,88 @@ +/* + * BTTNCURI.H + * + * Private include file for the Button Images and Cursors DLL. + * + * Copyright (c)1992-1993 Microsoft Corporation, All Right Reserved, + * as applied to redistribution of this source code in source form + * License is granted to use of compiled code in shipped binaries. + */ + +#ifdef __cplusplus +extern "C" + { +#endif + +//Function prototypes. + +//BTTNCUR.C +#ifdef WIN32 + extern BOOL WINAPI _CRT_INIT(HINSTANCE, DWORD, LPVOID); + extern _cexit(void); +#else + HANDLE FAR PASCAL LibMain(HANDLE, WORD, WORD, LPSTR); +#endif + +BOOL FInitialize(HANDLE); +void FAR PASCAL WEP(int); +static BOOL ToolButtonInit(void); +static void ToolButtonFree(void); +static HBRUSH HBrushDitherCreate(COLORREF, COLORREF); +static void DrawBlankButton(HDC, int, int, int, int, BOOL, COLORREF FAR *); +static void PatB(HDC, int, int, int, int, COLORREF); +static void MaskCreate(UINT, int, int, int, int, int, int, UINT); + + +//CURSORS.C +void CursorsCache(HINSTANCE); +void CursorsFree(void); + + + +/* + * Wierd Wild Wooly Waster (raster) Ops for special bltting. See the + * Windows SDK reference on Raster Operation Codes for explanation of + * these. The DSPDxax and PSDPxax is a reverse-polish notation for + * operations where D==Destination, S==Source, P==Patterm, a==AND, + * x==XOR. Both of these codes are actually described in Programming + * Windows by Charles Petzold, Second Edition, pages 622-624. + */ +#define ROP_DSPDxax 0x00E20746 +#define ROP_PSDPxax 0x00B8074A + + +/* + * Color indices into an array of standard hard-coded black, white, and + * gray colors. + */ + +#define STDCOLOR_BLACK 0 +#define STDCOLOR_DKGRAY 1 +#define STDCOLOR_LTGRAY 2 +#define STDCOLOR_WHITE 3 + +/* + * Color indices into an array of system colors, matching those in + * the hard-coded array for the colors they replace. + */ + +#define SYSCOLOR_TEXT 0 +#define SYSCOLOR_SHADOW 1 +#define SYSCOLOR_FACE 2 +#define SYSCOLOR_HILIGHT 3 + + +/* + * Button types, used internally to distinguish command buttons from + * attribute buttons to enforce three-state or six-state possibilities. + * Command buttons can only have three states (up, mouse down, disabled) + * while attribute buttons add (down, down disabled, and indeterminate). + */ + +#define BUTTONTYPE_COMMAND 0 +#define BUTTONTYPE_ATTRIBUTE 1 + + +#ifdef __cplusplus + } +#endif diff --git a/private/oleutest/letest/bttncur/changes.txt b/private/oleutest/letest/bttncur/changes.txt new file mode 100644 index 000000000..ef945130f --- /dev/null +++ b/private/oleutest/letest/bttncur/changes.txt @@ -0,0 +1,314 @@ +NOTE: This DLL is the same as that shipped with the OLE 2.0 SDK +but is updated from that shipped with "The Windows Interface" book +from Microsoft Press. It is now compatible with Windows NT. + + +---------- + + +Changes in BTTNCUR.DLL Source Code and Documentation from Version 1.00b +to Version 1.1. See also below for 1.00 to 1.00b changes. + +BTTNCUR.DLL version 1.1 is now fully compatible and tested under Windows +3.0. Previously the demo application crashed under Windows 3.0 +on calls to the non-existent MoveToEx (Win32 compatible). Version 1.1 only +uses MoveToEx for builds where the symbol WINVER < 0x030a. + +Windows NT changes are surrounded by #ifdef WIN32. The largest change +is the DLL entry point: LibMain. Both Win3.1 and Win32 versions +call FInitialize now. + +The images have been updated slightly and are now provided for 72dpi +(ega), 96dpi (vga), and 120dpi (super vga) + +Version 1.1 completely handles system color changes unlike version 1.00x. +This new version will dynamically convert black, light gray, dark gray, +and white pixels in the image bitmap into system colors set for the +button text, button shadow, button face, and button highlight, respectively. +If you have blue, red, yellow, and green button colors, BTTNCUR.DLL will +now work perfectly with all of them. + +BTTNCUR.DLL Version 1.1 also supports color images better by allowing +you to control which colors in the image bitmap are converted to system +colors. By default, any black, gray, or white colors are converted +into system button colors as decribed in the last paragraph. BTTNCUR.H +defines new PRESERVE_* flags for each of the four colors that are liable +to be converted. By specifing one or more flags you prevent BTTNCUR +from changing that color to a system color. For example, if you +want to preserve all black pixels in your image, specify PRESERVE_BLACK +when calling UIToolButtonDraw. + +Applications should obtain configuration data for the current display +through UIToolConfigureForDisplay. With this data the application can +configure itself for the correct toolbar size and button sizes and load +the appropriate application supplied bitmaps. + +Applications using UIToolConfigureForDisplay should now use +UIToolButtonDrawTDD instead of UIToolButtonDraw, passing one extra +parameter, a pointer to the TOOLDISPLAYDATA. Applications that +still call UIToolButtonDraw will always use 96dpi. + + +------------------------ +BTTNCUR.H changes + Added PRESERVE_ flags to allow application to control color conversions + from black, dark gray, light gray, and white into the + file compatible with C++. + + Added prototype for UIToolConfigureForDisplay, TOOLDISPLAYDATA structure, + and definitions for button and image sizes on 72dpi, 96dpi, and 120dpi. + +------------------------ +BTTNCUR.RCV version changes + FILEVERSION and PRODUCTVERSION changed from 1,0,0,2 to 1,0,1,0 + + VALUE "FileVersion" and VALUE "ProductVersion" changed from + "1.00b\0","\0" to "1.1\0","\0" + + +------------------------ +BTTNCURI.H changes + Defined STDCOLOR_* values as indices into an array in BTTNCUR.C + that holds hard-coded default button color that never change + regardless of the system colors. Also defined SYSCOLOR_* + flags that matched STDCOLOR_* flags for uniform array indices. + + Removed NEAR, FAR, and PASCAL from any function that didn't need it + so we can port to Windows NT cleanly. + +------------------------ +BTTNCUR.C source code changes. There are significant modifications. + +Overall: + Updated header comment + + Removed NEAR, FAR, and PASCAL from any function that didn't need it + so we can port to Windows NT cleanly. + +Globals: + Eliminated the COLORREFs prefixed with RGB. Only a few are needed + statically and were moved to HBrushDitherCreate. + + Also added an array of standard colors used in the standard images: + + static const + COLORREF crStandard[4]={ RGB(0, 0, 0) //STDCOLOR_BLACK + , RGB(128, 128, 128) //STDCOLOR_DKGRAY + , RGB(192, 192, 192) //STDCOLOR_LTGRAY + , RGB(255, 255, 255)}; //STDCOLOR_WHITE + + Added an array of standard images instead of just 96dpi versions. + +UIToolConfigureForDisplay: + Added function to return the resolution of the display and + size information about button and image sizes. + + +ToolButtonInit(): + Call to CreatePatternBrush moved into HBrushDitherCreate. + Conditionally sets the highlight color for HDitherBrushCreate + depending on Windows 3.x or Windows 3.0 (3.0 did not support + COLOR_BTNHIGHLIGHT). + + +ToolButtonFree(): + Removed some old debug output no longer useful. + + +HDitherBitmapCreate() + Renamed to HBrushDitherCreate. + Moved CreatePatterBrush code from ToolButtonInit into this + function. + + To support changing system colors, this function maintains + static variables for the face and highlight colors that we + use to create the brush. If the function is called and the + current colors in the global hBrushDither are different than + the system colors, we recreate the brush and update the global + hBrushDither, deleting the old brush. Otherwise we just return + hBrushDither. + + Note that if we fail to create the new brush we just maintain + the old. We'll paint something, albeit not in the right colors, + but something nontheless. + + +UIToolButtonDraw(): + Calls UIToolButtonDrawTDD with default display configuration. + +UIToolButtonDrawTDD(): + This is the function that was overhauled the most, specifically + to handle variable colors. + + First, we added several local variables of which two are important. + crSys is an array of system colors for the text, shadow, face, + highlight, and frame, declared as static to keep references to + it off DS instead of SS; if it's in SS things will crash. The second + important variable is uColor, which receives the color preservation + flags passed in the hibyte of the uState parameter to UIToolButtonDraw. + + All the code to draw a blank button outline was moved into a separate + function DrawBlankButton. Since this procedure needs all the system + colors to do it's thing, I've set it up to take an array of five + COLORREFs (exactly crSys) in which it stores those color (it also + uses it as its color variables). This way we only have to call + GetSysColor once for each system color. + + Anything dealing with the dithered brush is moved to the + BUTTONGROUP_LIGHTFACE case where we just get the current brush + by calling HBrushDitherCreate, passing it the current face + and highlight colors. Remember that is these colors match those + used in the currently held global hBrushDither, this function just + returns that global, so it's quite fast. We have to be very careful + not to delete this brush where we're done with it since it is global. + + The largest amount of new code is under the line: + + if ((uState & BUTTONGROUP_ACTIVE) && !(uState & BUTTONGROUP_BLANK)) + + This has changed from a single BitBlt call to a much more complex + operation to handle specific color conversions and preservations. + A little optimization was done to detect when the system colors + for buttons match the defaults, that is, black, dark gray, light gray, + and white for text, shadow, face, and highlight. If these colors + all match, or if the caller requested preservation of all colors, + the we just do the single BitBlt of old. + + Otherwise we loop through each of the black/white/gray colors + that need possible conversion. For each one we create a mask + that contains 1's where the converting color exists in the image + and 0's everywhere else. For each color then we BitBlt the + mask, a brush matching the system color we're converting to, + and the destination bitmap (which we initialize with the unmodified + image itself) using ROP_DSPDxax. This leaves any color but the + one under conversion alone and replaces the converted color with + the system color. + + If the caller set a specific flag to preserve one or more specific + colors, then we replace the standard color with the standard color, + resulting in a no-op. + + Finally, to reduce flicker for this four Blt operation we create + and build the final image in a temporary bitmap, making it 6 total + Blts to handle the color changes. But since we optimized for the + 99% case where the system colors are the standard colors, this isn't + too much of a consideration. + + color conversions. + + +DrawBlankButton(): + New internal function. Moved code from UIToolButtonDraw here. + + + + +------------------------ +CURSORS.C + Updated header comment + + Removed PASCAL on both internal functions. + + + CursorsFree + Eliminated all the code inside this function as it was unnecessary. + + UICursorLoad + Eliminated code to revalidate a cursor in the array. Unnecessary. + + +------------------------ +BCDEMO.C + + Tested for running under Windows 3.0 and avoided MoveToEx calls, + using MoveTo instead. Calling MoveToEx in a Windows 3.1 app + marked as 3.0 compatible under 3.0 causes an unknown GP fault. + + Uses UIToolButtonConfigureForDisplay and UIToolButtonDrawTDD. + + +------------------------------------------------------------------------------ + +Changes in BTTNCUR.DLL Source Code and Documentation from Version 1.00 +to Version 1.00b + +------------------------ +BTTNCUR.H changes + Added #ifdef __cplusplus to include extern "C" making the + file compatible with C++. + + +------------------------ +BTTNCURI.H changes + Added #ifdef __cplusplus to include extern "C" making the + file compatible with C++. + + Removed code contained between a #ifdef NEVER that is unused. + + +------------------------ +BTTNCUR.RCV version changes + FILEVERSION and PRODUCTVERSION changed from 1,0,0,0 to 1,0,0,2 + + VALUE "FileVersion" and VALUE "ProductVersion" changed from + "1.00\0","\0" to "1.00b\0","\0" + + +------------------------ +BTTNCUR.C source code changes. + + Added a global for the frame color + static COLORREF rgbFrame =RGB(0, 0, 0); + +WEP(): + Added comment about resource cleanup messages in DEBUG mode. + + +ToolButtonInit(): + Added the line below just before the assignment of hDCGlyphs: + + rgbFrame=GetSysColor(COLOR_WINDOWFRAME); + + This insures that the frame color is properly shown on plasma + displays. + + +ToolButtonFree(): + Added the following lines just before return: + + if (NULL!=hBmpStandardImages) + DeleteObject(hBmpStandardImages); + hBmpStandardImages=NULL; + + +UIToolButtonDraw(): + The image centering is one too high. The line + + yOffsetGlyph=((dy-bmy) >> 1)-1; + + now reads: + + yOffsetGlyph=(dy-bmy) >> 1; + + + The declaration HBITMAP hBmp; now read HBITMAP hBmp=NULL; + + The line hBmpT=SelectObject(hDCGlyphs, hBmp); is now two: + + if (NULL!=hBmp) + SelectObject(hDCGlyphs, hBmp); + + The line SelectObject(hDCGlyphs, hBmpT); is now two: + + if (NULL!=hBmpT) + SelectObject(hDCGlyphs, hBmpT); + + + +------------------------ +BTTNCUR.BMP + Fixed the images to be 16*15 (the standard) instead of 16*16 + as they originally were. Changed the label "16x16" to "16x15". + + Copied an image of the disabled state of Context-Sensitive Help + to this bitmap as it was previously missing. diff --git a/private/oleutest/letest/bttncur/cursors.c b/private/oleutest/letest/bttncur/cursors.c new file mode 100644 index 000000000..625f6e5ed --- /dev/null +++ b/private/oleutest/letest/bttncur/cursors.c @@ -0,0 +1,150 @@ +/* + * CURSORS.C + * Buttons & Cursors Version 1.1, Win32 version August 1993 + * + * Public functions to retrieve new cursors from the BTTNCUR DLL based + * on ordinal to prevent applications from necessarily calling LoadCursor + * directly on the DLL. + * + * Copyright (c)1992-1993 Microsoft Corporation, All Rights Reserved, + * as applied to redistribution of this source code in source form + * License is granted to use of compiled code in shipped binaries. + */ + +#ifdef WIN32 +#define _INC_OLE +#define __RPC_H__ +#endif + +#include +#include "bttncur.h" +#include "bttncuri.h" + + +/* + * The +1 is because MAX is the highest allowable number and MIN is not + * necessarily zero. + */ +HCURSOR rgHCursors[IDC_NEWUICURSORMAX-IDC_NEWUICURSORMIN+1]; + + + +/* + * CursorsCache + * Internal + * + * Purpose: + * Loads all the cursors available through NewUICursorLoad into + * a global array. This way we can clean up all the cursors without + * placing the burden on the application. + * + * Parameters: + * hInst HANDLE of the DLL instance. + * + * Return Value: + * None. If any of the LoadCursor calls fail, then the corresponding + * array entry is NULL and NewUICursorLoad will fail. Better to fail + * an app getting a cursor than failing to load the app just for that + * reason; and app can attempt to load the cursor on startup if it's + * that important, and fail itself. + */ + +void CursorsCache(HINSTANCE hInst) + { + UINT i; + + for (i=IDC_NEWUICURSORMIN; i<=IDC_NEWUICURSORMAX; i++) + rgHCursors[i-IDC_NEWUICURSORMIN]=LoadCursor(hInst, MAKEINTRESOURCE(i)); + + return; + } + + + + +/* + * CursorsFree + * Internal + * + * Purpose: + * Frees all the cursors previously loaded through CursorsCache. + * + * Parameters: + * None + * + * Return Value: + * None + */ + +void CursorsFree(void) + { + /* + * Note that since cursors are discardable resources and should + * not be used with DestroyCursor, there's nothing to do here. + * We still provide this API for compatibility and to maintain + * symmetry. + */ + return; + } + + + + + +/* + * UICursorLoad + * Public API + * + * Purpose: + * Loads and returns a handle to one of the new standard UI cursors + * contained in UITOOLS.DLL. The application must not call DestroyCursor + * on this cursor as it is managed by the DLL. + * + * Parameters: + * iCursor UINT index to the cursor to load which must be one + * of the following values: + * + * IDC_RIGHTARROW Right pointing standard arrow + * IDC_CONTEXTHELP Arrow with a ? (context help) + * IDC_MAGNIFY Magnifying glass for zooming + * IDC_NODROP Circle with a slash + * IDC_TABLETOP Small arrow pointing down + * + * IDC_SMALLARROWS Thin four-headed arrow + * IDC_LARGEARROWS Wide four-headed arrow + * IDC_HARROWS Horizontal two-headed arrow + * IDC_VARROWS Vertical two-headed arrow + * IDC_NESWARROWS Two-headed arrow pointing NE<->SW + * IDC_NWSEHARROWS Two-headed arrow pointing NW<->SE + * + * IDC_HSIZEBAR Horizontal two-headed arrow with + * a single vertical bar down the + * middle + * + * IDC_VSIZEBAR Vertical two-headed arrow with a + * single horizontal bar down the + * middle + * + * IDC_HSPLITBAR Horizontal two-headed arrow with + * split double vertical bars down the + * middle + * + * IDC_VSPLITBAR Vertical two-headed arrow with split + * double horizontal bars down the + * middle + * + * Return Value: + * HCURSOR Handle to the loaded cursor if successful, NULL + * if iCursor is out of range or the function could not + * load the cursor. + */ + +HCURSOR WINAPI UICursorLoad(UINT iCursor) + { + HCURSOR hCur=NULL; + + if ((iCursor >= IDC_NEWUICURSORMIN) && (iCursor <= IDC_NEWUICURSORMAX)) + hCur=rgHCursors[iCursor-IDC_NEWUICURSORMIN]; + + return hCur; + } diff --git a/private/oleutest/letest/bttncur/daytona/bttncur.src b/private/oleutest/letest/bttncur/daytona/bttncur.src new file mode 100644 index 000000000..12c011464 --- /dev/null +++ b/private/oleutest/letest/bttncur/daytona/bttncur.src @@ -0,0 +1,39 @@ +#if 0 + + Microsoft Windows + Copyright (C) Microsoft Corporation, 1992 - 1992. + All rights reserved. + + This .def file is preprocessed by the compiler to create the version for + the current build in the appropriate subdir. Basically, whatever you + would have used in your code to control what is compiled when can be + used in this file for the same purpose. The following defines are in + use at the time this file was written: + + FLAT - Used to indicate a NT/DOS7 build + i386 - Intel i386/i486 build + MIPS - MIPS R3000/R4000 build + ALPHA - DEC Alpha build + DBG - Used to control Debug/Retail. Set to 1 if Debug, + 0 if Retail. + WIN31 - Win16 build + __OS2__ - OS/2 build (used by CT mostly) + + If none of these are used, it is assumed the entire file can be used + for all builds. + +#endif + +#ifdef FLAT + +LIBRARY bttncur + +DESCRIPTION 'BTTNCUR' + +EXPORTS + UICursorLoad + UIToolConfigureForDisplay + UIToolButtonDraw + UIToolButtonDrawTDD + +#endif // FLAT diff --git a/private/oleutest/letest/bttncur/daytona/makefile b/private/oleutest/letest/bttncur/daytona/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/oleutest/letest/bttncur/daytona/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/oleutest/letest/bttncur/daytona/makefile.inc b/private/oleutest/letest/bttncur/daytona/makefile.inc new file mode 100644 index 000000000..fc473f167 --- /dev/null +++ b/private/oleutest/letest/bttncur/daytona/makefile.inc @@ -0,0 +1 @@ +obj\*\bttncur.def: bttncur.src diff --git a/private/oleutest/letest/bttncur/daytona/sources b/private/oleutest/letest/bttncur/daytona/sources new file mode 100644 index 000000000..6beeb9661 --- /dev/null +++ b/private/oleutest/letest/bttncur/daytona/sources @@ -0,0 +1,39 @@ + +TARGETNAME=bttncur + +TARGETPATH=obj + +TARGETTYPE=DYNLINK + +DLLDEF= obj\*\bttncur.def + +TARGETLIBS=$(GUI32_LIBS) $(WIN32_LIBS) + +DLLBASE=@$(BASEDIR)\PUBLIC\SDK\LIB\coffbase.txt,usermode + +DLLENTRY= DllEntryPoint + +UMTYPE=windows + +INCLUDES=..;..\res + +C_DEFINES=-DWIN32 -DFLAT + +BLDCRT=1 + +SOURCES=..\bttncur.rc \ + ..\bttncur.c \ + ..\dllentry.c \ + ..\cursors.c + +!IF $(386) +NTTARGETFILE0=$(DLLDEF:*=i386) +!ENDIF + +!IF $(MIPS) +NTTARGETFILE0=$(DLLDEF:*=mips) +!ENDIF + +!IF $(ALPHA) +NTTARGETFILE0=$(DLLDEF:*=alpha) +!ENDIF diff --git a/private/oleutest/letest/bttncur/dirs b/private/oleutest/letest/bttncur/dirs new file mode 100644 index 000000000..d0b57ca11 --- /dev/null +++ b/private/oleutest/letest/bttncur/dirs @@ -0,0 +1,4 @@ +DIRS= +OPTIONAL_DIRS= \ + daytona \ + diff --git a/private/oleutest/letest/bttncur/dllentry.c b/private/oleutest/letest/bttncur/dllentry.c new file mode 100644 index 000000000..1cd1159e4 --- /dev/null +++ b/private/oleutest/letest/bttncur/dllentry.c @@ -0,0 +1,55 @@ +//+------------------------------------------------------------------- +// +// Microsoft Windows +// Copyright (C) Microsoft Corporation, 1991 - 1992. +// +// File: dllentry.c +// +// Contents: Dll Entry point code. Calls the appropriate run-time +// init/term code and then defers to LibMain for further +// processing. +// +// Classes: +// +// Functions: DllEntryPoint - Called by loader +// +// History: 10-May-92 BryanT Created +// 22-Jul-92 BryanT Switch to calling _cexit/_mtdeletelocks +// on cleanup. +// 06-Oct-92 BryanT Call RegisterWithCommnot on entry +// and DeRegisterWithCommnot on exit. +// This should fix the heap dump code. +// 27-Dec-93 AlexT Post 543 builds don't need special code. +// +//-------------------------------------------------------------------- + +#define USE_CRTDLL +#include + +BOOL WINAPI _CRT_INIT (HANDLE hDll, DWORD dwReason, LPVOID lpReserved); + +BOOL DllEntryPoint (HANDLE hDll, DWORD dwReason, LPVOID lpReserved); + +BOOL _CRTAPI1 LibMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved); + +BOOL DllEntryPoint (HANDLE hDll, DWORD dwReason, LPVOID lpReserved) +{ + BOOL fRc = FALSE; + + switch (dwReason) + { + case DLL_PROCESS_ATTACH: + _CRT_INIT(hDll, dwReason, lpReserved); + + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + fRc = LibMain (hDll, dwReason, lpReserved); + break; + + case DLL_PROCESS_DETACH: + fRc = LibMain (hDll, dwReason, lpReserved); + _CRT_INIT(hDll, dwReason, lpReserved); + } + + return(fRc); +} diff --git a/private/oleutest/letest/bttncur/makefile b/private/oleutest/letest/bttncur/makefile new file mode 100644 index 000000000..21eedcbe0 --- /dev/null +++ b/private/oleutest/letest/bttncur/makefile @@ -0,0 +1,12 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!ifdef NTMAKEENV +all: + echo $(BUILDMSG) +clean: all +!else +!INCLUDE $(NTMAKEENV)\makefile.def +!endif diff --git a/private/oleutest/letest/bttncur/msvc.pdb b/private/oleutest/letest/bttncur/msvc.pdb new file mode 100644 index 000000000..917b59b09 Binary files /dev/null and b/private/oleutest/letest/bttncur/msvc.pdb differ diff --git a/private/oleutest/letest/bttncur/res/harrows.cur b/private/oleutest/letest/bttncur/res/harrows.cur new file mode 100644 index 000000000..571dd0ef7 Binary files /dev/null and b/private/oleutest/letest/bttncur/res/harrows.cur differ diff --git a/private/oleutest/letest/bttncur/res/help.cur b/private/oleutest/letest/bttncur/res/help.cur new file mode 100644 index 000000000..d0a2aa307 Binary files /dev/null and b/private/oleutest/letest/bttncur/res/help.cur differ diff --git a/private/oleutest/letest/bttncur/res/larrows.cur b/private/oleutest/letest/bttncur/res/larrows.cur new file mode 100644 index 000000000..8574ffb2d Binary files /dev/null and b/private/oleutest/letest/bttncur/res/larrows.cur differ diff --git a/private/oleutest/letest/bttncur/res/magnify.cur b/private/oleutest/letest/bttncur/res/magnify.cur new file mode 100644 index 000000000..0d3289422 Binary files /dev/null and b/private/oleutest/letest/bttncur/res/magnify.cur differ diff --git a/private/oleutest/letest/bttncur/res/neswarrs.cur b/private/oleutest/letest/bttncur/res/neswarrs.cur new file mode 100644 index 000000000..c38501ee1 Binary files /dev/null and b/private/oleutest/letest/bttncur/res/neswarrs.cur differ diff --git a/private/oleutest/letest/bttncur/res/nodrop.cur b/private/oleutest/letest/bttncur/res/nodrop.cur new file mode 100644 index 000000000..b002e96b3 Binary files /dev/null and b/private/oleutest/letest/bttncur/res/nodrop.cur differ diff --git a/private/oleutest/letest/bttncur/res/nwsearrs.cur b/private/oleutest/letest/bttncur/res/nwsearrs.cur new file mode 100644 index 000000000..570cbbb57 Binary files /dev/null and b/private/oleutest/letest/bttncur/res/nwsearrs.cur differ diff --git a/private/oleutest/letest/bttncur/res/rarrow.cur b/private/oleutest/letest/bttncur/res/rarrow.cur new file mode 100644 index 000000000..5691efbaf Binary files /dev/null and b/private/oleutest/letest/bttncur/res/rarrow.cur differ diff --git a/private/oleutest/letest/bttncur/res/sarrows.cur b/private/oleutest/letest/bttncur/res/sarrows.cur new file mode 100644 index 000000000..a407a1298 Binary files /dev/null and b/private/oleutest/letest/bttncur/res/sarrows.cur differ diff --git a/private/oleutest/letest/bttncur/res/sizebarh.cur b/private/oleutest/letest/bttncur/res/sizebarh.cur new file mode 100644 index 000000000..dda3483bb Binary files /dev/null and b/private/oleutest/letest/bttncur/res/sizebarh.cur differ diff --git a/private/oleutest/letest/bttncur/res/sizebarv.cur b/private/oleutest/letest/bttncur/res/sizebarv.cur new file mode 100644 index 000000000..a87811cb4 Binary files /dev/null and b/private/oleutest/letest/bttncur/res/sizebarv.cur differ diff --git a/private/oleutest/letest/bttncur/res/splith.cur b/private/oleutest/letest/bttncur/res/splith.cur new file mode 100644 index 000000000..f2f0be363 Binary files /dev/null and b/private/oleutest/letest/bttncur/res/splith.cur differ diff --git a/private/oleutest/letest/bttncur/res/splitv.cur b/private/oleutest/letest/bttncur/res/splitv.cur new file mode 100644 index 000000000..a4260808f Binary files /dev/null and b/private/oleutest/letest/bttncur/res/splitv.cur differ diff --git a/private/oleutest/letest/bttncur/res/stdim120.bmp b/private/oleutest/letest/bttncur/res/stdim120.bmp new file mode 100644 index 000000000..89d1be7d1 Binary files /dev/null and b/private/oleutest/letest/bttncur/res/stdim120.bmp differ diff --git a/private/oleutest/letest/bttncur/res/stdim72.bmp b/private/oleutest/letest/bttncur/res/stdim72.bmp new file mode 100644 index 000000000..57bcbe029 Binary files /dev/null and b/private/oleutest/letest/bttncur/res/stdim72.bmp differ diff --git a/private/oleutest/letest/bttncur/res/stdim96.bmp b/private/oleutest/letest/bttncur/res/stdim96.bmp new file mode 100644 index 000000000..eef487dbd Binary files /dev/null and b/private/oleutest/letest/bttncur/res/stdim96.bmp differ diff --git a/private/oleutest/letest/bttncur/res/tabletop.cur b/private/oleutest/letest/bttncur/res/tabletop.cur new file mode 100644 index 000000000..b61fec41a Binary files /dev/null and b/private/oleutest/letest/bttncur/res/tabletop.cur differ diff --git a/private/oleutest/letest/bttncur/res/varrows.cur b/private/oleutest/letest/bttncur/res/varrows.cur new file mode 100644 index 000000000..76449be89 Binary files /dev/null and b/private/oleutest/letest/bttncur/res/varrows.cur differ diff --git a/private/oleutest/letest/data/letest12.olc b/private/oleutest/letest/data/letest12.olc new file mode 100644 index 000000000..4d82e7069 Binary files /dev/null and b/private/oleutest/letest/data/letest12.olc differ diff --git a/private/oleutest/letest/data/tiger.bmp b/private/oleutest/letest/data/tiger.bmp new file mode 100644 index 000000000..3eaedbcdf Binary files /dev/null and b/private/oleutest/letest/data/tiger.bmp differ diff --git a/private/oleutest/letest/data/tigernph.wmf b/private/oleutest/letest/data/tigernph.wmf new file mode 100644 index 000000000..99f176cff Binary files /dev/null and b/private/oleutest/letest/data/tigernph.wmf differ diff --git a/private/oleutest/letest/dirs b/private/oleutest/letest/dirs new file mode 100644 index 000000000..55c391db6 --- /dev/null +++ b/private/oleutest/letest/dirs @@ -0,0 +1,7 @@ +DIRS= \ + bttncur \ + ole2ui \ + gizmobar \ + outline + + diff --git a/private/oleutest/letest/gizmobar/api.c b/private/oleutest/letest/gizmobar/api.c new file mode 100644 index 000000000..526d66a5f --- /dev/null +++ b/private/oleutest/letest/gizmobar/api.c @@ -0,0 +1,846 @@ +/* + * API.C + * GizmoBar Version 1.00, Win32 version August 1993 + * + * API functions affecting a GizmoBar and a message processing function to + * handle the equivalent called through messages. + * + * Copyright (c)1993 Microsoft Corporation, All Rights Reserved + * + * Kraig Brockschmidt, Software Design Engineer + * Microsoft Systems Developer Relations + * + * Internet : kraigb@microsoft.com + * Compuserve: >INTERNET:kraigb@microsoft.com + */ + + +#include +#include "gizmoint.h" + + + +/* + * GBMessageHandler + * + * Purpose: + * Processes control messages that are equivalents of available + * control API. The data passed with these messages is simply + * extracted from structures and passed as parameters to their + * equivalent function. + * + * Parameters: + * plus + * pGB LPGIZMOBAR providing control-specific data. + * + * Return Value: + * LRESULT Return value from equivalent API function. + */ + +LRESULT GBMessageHandler(HWND hWnd, UINT iMsg, WPARAM wParam + , LPARAM lParam, LPGIZMOBAR pGB) + { + LRESULT lRet=0L; + LPCREATEGIZMO pCG; + LPGBMSG pMsg; + LPGBGETTEXT pGT; + LPGBGETINT pGI; + LPGBSETINT pSI; + + if (NULL==pGB) + return 0L; + + switch (iMsg) + { + case GBM_HWNDASSOCIATESET: + lRet=(LRESULT)(UINT)GBHwndAssociateSet(hWnd, (HWND)wParam); + break; + + case GBM_HWNDASSOCIATEGET: + lRet=(LRESULT)(UINT)GBHwndAssociateGet(hWnd); + break; + + case GBM_GIZMOADD: + pCG=(LPCREATEGIZMO)lParam; + lRet=(LRESULT)GBGizmoAdd(pCG->hWndParent, pCG->iType, pCG->iGizmo + , pCG->uID, pCG->dx, pCG->dy, pCG->pszText, pCG->hBmp + , pCG->iImage, pCG->uState); + break; + + case GBM_GIZMOREMOVE: + lRet=(LRESULT)GBGizmoRemove(hWnd, wParam); + break; + + case GBM_GIZMOSENDMESSAGE: + pMsg=(LPGBMSG)lParam; + lRet=GBGizmoSendMessage(hWnd, wParam, pMsg->iMsg, pMsg->wParam, pMsg->lParam); + break; + + case GBM_GIZMOSHOW: + lRet=(LRESULT)GBGizmoShow(hWnd, wParam, (BOOL)LOWORD(lParam)); + break; + + case GBM_GIZMOENABLE: + lRet=(LRESULT)GBGizmoEnable(hWnd, wParam, (BOOL)LOWORD(lParam)); + break; + + case GBM_GIZMOCHECK: + lRet=(LRESULT)GBGizmoCheck(hWnd, wParam, (BOOL)LOWORD(lParam)); + break; + + case GBM_GIZMOFOCUSSET: + lRet=(LRESULT)GBGizmoFocusSet(hWnd, wParam); + break; + + case GBM_GIZMOEXIST: + lRet=(LRESULT)GBGizmoExist(hWnd, wParam); + break; + + case GBM_GIZMOTYPEGET: + lRet=(LRESULT)GBGizmoTypeGet(hWnd, wParam); + break; + + case GBM_GIZMODATASET: + lRet=(LRESULT)GBGizmoDataSet(hWnd, wParam, (DWORD)lParam); + break; + + case GBM_GIZMODATAGET: + lRet=(LRESULT)GBGizmoDataGet(hWnd, wParam); + break; + + case GBM_GIZMONOTIFYSET: + lRet=(LRESULT)GBGizmoNotifySet(hWnd, wParam, (BOOL)LOWORD(lParam)); + break; + + case GBM_GIZMONOTIFYGET: + lRet=(LRESULT)GBGizmoNotifyGet(hWnd, wParam); + break; + + case GBM_GIZMOTEXTGET: + pGT=(LPGBGETTEXT)lParam; + lRet=(LRESULT)GBGizmoTextGet(hWnd, wParam, pGT->psz, pGT->cch); + break; + + case GBM_GIZMOTEXTSET: + GBGizmoTextSet(hWnd, wParam, (LPTSTR)lParam); + break; + + case GBM_GIZMOINTGET: + pGI=(LPGBGETINT)lParam; + lRet=(LRESULT)GBGizmoIntGet(hWnd, wParam, &pGI->fSuccess, pGI->fSigned); + break; + + + case GBM_GIZMOINTSET: + pSI=(LPGBSETINT)lParam; + GBGizmoIntSet(hWnd, wParam, pSI->uValue, pSI->fSigned); + break; + + default: + break; + } + + return lRet; + } + + + + + + + + + + +/* + * PGizmoFromHwndID + * + * Purpose: + * Retrieves the pGizmo for the given GizmoBar and the gizmo ID. + * + * Parameters: + * hWnd HWND of a GizmoBar. + * uID UINT gizmo identifier. + * + * Return Value: + * LPGIZMO NULL if the gizmo does not exist or hWnd is invalid. + * non-NULL LPGIZMO otherwise. + */ + +LPGIZMO PGizmoFromHwndID(HWND hWnd, UINT uID) + { + LPGIZMOBAR pGB; + + if (!IsWindow(hWnd)) + return FALSE; + + pGB=(LPGIZMOBAR)GetWindowLong(hWnd, GBWL_STRUCTURE); + + if (NULL==pGB) + return FALSE; + + return GizmoPFind(&pGB->pGizmos, uID); + } + + + + + + +/* + * GBHwndAssociateSet + * + * Purpose: + * Changes the associate window of a GizmoBar. + * + * Parameters: + * hWnd HWND of the control window. + * + * Set Parameters: + * hWndAssociate HWND of new associate. + * + * Return Value: + * HWND Handle of previous associate. + */ + +HWND WINAPI GBHwndAssociateSet(HWND hWnd, HWND hWndNew) + { + HWND hWndOld=NULL; + LPGIZMOBAR pGB; + + pGB=(LPGIZMOBAR)GetWindowLong(hWnd, GBWL_STRUCTURE); + + if (NULL!=pGB) + { + hWndOld=pGB->hWndAssociate; + pGB->hWndAssociate=hWndNew; + + if (NULL!=hWndOld) + SendCommand(hWndOld, pGB->uID, GBN_ASSOCIATELOSS, hWnd); + + if (NULL!=hWndNew) + SendCommand(hWndNew, pGB->uID, GBN_ASSOCIATEGAIN, hWnd); + } + + return hWndOld; + } + + + + + +/* + * GBHwndAssociateGet + * + * Purpose: + * Retrieves the associate window of a GizmoBar + * + * Parameters: + * hWnd HWND of the control window. + * + * Set Parameters: + * hWndAssociate HWND of new associate. + * + * Return Value: + * HWND Handle of current associate. + */ + +HWND WINAPI GBHwndAssociateGet(HWND hWnd) + { + HWND hWndOld=NULL; + LPGIZMOBAR pGB; + + pGB=(LPGIZMOBAR)GetWindowLong(hWnd, GBWL_STRUCTURE); + + if (NULL!=pGB) + hWndOld=pGB->hWndAssociate; + + return hWndOld; + } + + + + + +/* + * GBGizmoAdd + * + * Purpose: + * Creates a new gizmo on the GizmoBar. Subsequent operations should + * be done using the identifier, uID, for this gizmo. + * + * Parameters: + * hWnd HWND of the GizmoBar. + * iType UINT type of the gizmo to create. + * iGizmo UINT position (zero-based) at which to place the gizmo. + * uID UINT identifier for WM_COMMAND from this gizmo. + * dx, dy UINT dimensions of the gizmo. + * pszText LPTSTR initial text for edit, list, combo, and text gizmos. + * hBitmap HBITMAP for gizmos of the button types (COMMAND or + * ATTRIBUTE) specifies a source bitmap from which the + * button image is taken. + * iImage UINT index into hBitmap for the image for this button. + * uState UINT initial state of the gizmo. + * + * Return Value: + * BOOL TRUE if creation succeeded, FALSE otherwise. + */ + +BOOL WINAPI GBGizmoAdd(HWND hWnd, UINT iType, UINT iGizmo, UINT uID + , UINT dx, UINT dy, LPTSTR pszText, HBITMAP hBmp, UINT iImage, UINT uState) + { + BOOL fSuccess; + LPGIZMOBAR pGB; + LPGIZMO pGizmo; + + if (!IsWindow(hWnd)) + return FALSE; + + pGB=(LPGIZMOBAR)GetWindowLong(hWnd, GBWL_STRUCTURE); + + if (NULL==pGB) + return FALSE; + + /* + * This automatically creates the windows, allocates structures, includes + * the gizmo in pGB->pGizmos, and so forth. + */ + pGizmo=GizmoPAllocate((LPINT)&fSuccess, &pGB->pGizmos, hWnd, iType + , iGizmo, uID, dx, dy, pszText, hBmp, iImage, uState); + + if (fSuccess) + { + if (NULL!=pGB->hWndAssociate) + SendCommand(pGB->hWndAssociate,GBN_GIZMOADDED, pGB->uID, hWnd); + + InvalidateRect(hWnd, NULL, TRUE); + UpdateWindow(hWnd); + } + else + GizmoPFree(&pGB->pGizmos, pGizmo); + + return fSuccess; + } + + + + + +/* + * GBGizmoRemove + * + * Purpose: + * Removes an existing gizmo from the GizmoBar. + * + * Parameters: + * hWnd HWND of the GizmoBar. + * uID UINT identifier for this gizmo. + * + * Return Value: + * BOOL TRUE if deletion succeeded, FALSE otherwise. + */ + +BOOL WINAPI GBGizmoRemove(HWND hWnd, UINT uID) + { + LPGIZMOBAR pGB; + LPGIZMO pGizmo; + + if (!IsWindow(hWnd)) + return FALSE; + + pGB=(LPGIZMOBAR)GetWindowLong(hWnd, GBWL_STRUCTURE); + + if (NULL==pGB) + return FALSE; + + pGizmo=GizmoPFind(&pGB->pGizmos, uID); + + if (NULL==pGizmo) + return FALSE; + + GizmoPFree(&pGB->pGizmos, pGizmo); + + if (NULL!=pGB->hWndAssociate) + SendCommand(pGB->hWndAssociate, GBN_GIZMOREMOVED, pGB->uID, hWnd); + + InvalidateRect(hWnd, NULL, TRUE); + UpdateWindow(hWnd); + return TRUE; + } + + + + + + +/* + * GBGizmoSendMessage + * + * Purpose: + * Implements the equivalent of SendMessage to a gizmo in the + * GizmoBar. Separators, command buttons, and attribute buttons + * do not accept messages. + * + * Parameters: + * hWnd HWND of the GizmoBar. + * uID UINT identifier of the gizmo to affect. + * iMsg UINT message to send. + * wParam WPARAM of the message. + * lParam LPARAM of the message. + * + * Return Value: + * LRESULT Return value from the message. 0L if the + * gizmo does not accept messages. + */ + +LRESULT WINAPI GBGizmoSendMessage(HWND hWnd, UINT uID, UINT iMsg + , WPARAM wParam, LPARAM lParam) + { + LPGIZMO pGizmo; + LONG lRet=0L; + + pGizmo=PGizmoFromHwndID(hWnd, uID); + + if (NULL!=pGizmo && NULL!=pGizmo->hWnd) + lRet=SendMessage(pGizmo->hWnd, iMsg, wParam, lParam); + + return lRet; + } + + + + + + +/* + * GBGizmoShow + * + * Purpose: + * Shows or hides a control, adjusting the positions of all others + * to make room for or reuse the space for this control. + * + * Parameters: + * hWnd HWND of the GizmoBar. + * uID UINT identifier of the gizmo to affect. + * fShow BOOL TRUE to show the gizmo, FALSE to hide it. + * + * Return Value: + * BOOL TRUE if the function was successful, FALSE otherwise. + */ + +BOOL WINAPI GBGizmoShow(HWND hWnd, UINT uID, BOOL fShow) + { + BOOL fRet=FALSE; + LPGIZMO pGizmo; + + pGizmo=PGizmoFromHwndID(hWnd, uID); + + if (NULL!=pGizmo) + { + if (fShow && pGizmo->fHidden) + { + if (NULL!=pGizmo->hWnd) + ShowWindow(pGizmo->hWnd, SW_SHOWNORMAL); + + GizmosExpand(pGizmo); + } + + if (!fShow && !pGizmo->fHidden) + { + if (NULL!=pGizmo->hWnd) + ShowWindow(pGizmo->hWnd, SW_HIDE); + + GizmosCompact(pGizmo); + } + + //This will be right even if we didn't change anything. + pGizmo->fHidden=!fShow; + } + + InvalidateRect(hWnd, NULL, TRUE); + UpdateWindow(hWnd); + return fRet; + } + + + + + + +/* + * GBGizmoEnable + * + * Purpose: + * Enables or disables a control on the GizmoBar. + * + * Parameters: + * hWnd HWND of the GizmoBar. + * uID UINT identifier of the gizmo to affect. + * fEnable BOOL TRUE to enable the gizmo, FALSE otherwise. + * + * Return Value: + * BOOL TRUE if the gizmo was previously disabled, FALSE + * otherwise. + */ + +BOOL WINAPI GBGizmoEnable(HWND hWnd, UINT uID, BOOL fEnable) + { + LPGIZMO pGizmo; + BOOL fRet=FALSE; + + pGizmo=PGizmoFromHwndID(hWnd, uID); + + if (NULL==pGizmo) + return FALSE; + + fRet=(BOOL)(BUTTONGROUP_DISABLED & pGizmo->uState); + + //Use windows to enable or disable window gizmos + if (NULL!=pGizmo->hWnd) + EnableWindow(pGizmo->hWnd, fEnable); + else + { + //If we're not down, command and attribute buttons act the same. + if (!(BUTTONGROUP_DOWN & pGizmo->uState)) + GizmoPStateSet(hWnd, pGizmo, fEnable ? COMMANDBUTTON_UP : COMMANDBUTTON_DISABLED); + else + { + //Attribute buttons are a little more sensitive with DOWNDISABLED + GizmoPStateSet(hWnd, pGizmo + , fEnable ? ATTRIBUTEBUTTON_DOWN : ATTRIBUTEBUTTON_DOWNDISABLED); + } + } + + return fRet; + } + + + + + + + +/* + * GBGizmoCheck + * + * Purpose: + * Checks or unchecks an attribute button in the GizmoBar. If the + * gizmo is part of a group of mutually exclusive attributes, then + * other gizmos are unchecked when this one is checked. If this is + * the only one checked in these circumstances, this function is a NOP. + * + * Parameters: + * hWnd HWND of the GizmoBar. + * uID UINT identifier of the gizmo to affect. + * fCheck BOOL TRUE to check this gizmo, FALSE to uncheck. + * + * Return Value: + * BOOL TRUE if the change took place. FALSE otherwise. + */ + +BOOL WINAPI GBGizmoCheck(HWND hWnd, UINT uID, BOOL fCheck) + { + LPGIZMOBAR pGB; + LPGIZMO pGizmo; + + if (!IsWindow(hWnd)) + return FALSE; + + pGB=(LPGIZMOBAR)GetWindowLong(hWnd, GBWL_STRUCTURE); + + if (NULL==pGB) + return FALSE; + + pGizmo=GizmoPFind(&pGB->pGizmos, uID); + + if (NULL!=pGizmo) + GizmoPCheck(hWnd, pGizmo, fCheck); + + return TRUE; + } + + + + + + +/* + * GBGizmoFocusSet + * + * Purpose: + * Sets the focus to a partuclar gizmo in the gizmo if that gizmo + * can accept the focus. Separators, attribute buttons, text, + * and command buttons cannot have the focus. + * + * Parameters: + * hWnd HWND of the GizmoBar. + * uID UINT identifier of the gizmo to affect. + * + * Return Value: + * BOOL TRUE if the focus was set. FALSE otherwise, such as + * when uID identifies a control that cannot have focus. + */ + +UINT WINAPI GBGizmoFocusSet(HWND hWnd, UINT uID) + { + LPGIZMO pGizmo; + BOOL fRet=FALSE; + + pGizmo=PGizmoFromHwndID(hWnd, uID); + + if (NULL!=pGizmo && NULL!=pGizmo->hWnd) + { + fRet=TRUE; + SetFocus(pGizmo->hWnd); + } + + return fRet; + } + + + + + +/* + * GBGizmoExist + * + * Purpose: + * Determines if a gizmo of a given identifier exists in the GizmoBar. + * + * Parameters: + * hWnd HWND of the GizmoBar. + * uID UINT identifier to verify. + * + * Return Value: + * BOOL TRUE if the gizmo exists, FALSE otherwise. + */ + +BOOL WINAPI GBGizmoExist(HWND hWnd, UINT uID) + { + return (NULL!=PGizmoFromHwndID(hWnd, uID)); + } + + + + + +/* + * GBGizmoTypeGet + * + * Purpose: + * Returns the type of the gizmo specified by the given identifer. + * + * Parameters: + * hWnd HWND of the GizmoBar. + * uID UINT identifier to find. + * + * Return Value: + * int A GIZMOTYPE_* value if the function is successful, + * otherwise -1. + */ + +int WINAPI GBGizmoTypeGet(HWND hWnd, UINT uID) + { + int iRet=-1; + LPGIZMO pGizmo; + + pGizmo=PGizmoFromHwndID(hWnd, uID); + + if (NULL!=pGizmo) + iRet=pGizmo->iType; + + return iRet; + } + + + + + +/* + * GBGizmoDataSet + * GBGizmoDataGet + * + * Purpose: + * Sets or retrieves an extra DWORD value associated with the given gizmo. + * Applications can store any information here they please. + * + * Parameters: + * hWnd HWND of the GizmoBar. + * uID UINT identifier of the gizmo. + * dwData (Set only) DWORD data to store with the gizmo. + * + * Return Value: + * DWORD Set: Previous value + * Get: Current value + */ + +DWORD WINAPI GBGizmoDataSet(HWND hWnd, UINT uID, DWORD dwData) + { + LPGIZMO pGizmo; + DWORD dw=0L; + + pGizmo=PGizmoFromHwndID(hWnd, uID); + + if (NULL!=pGizmo) + { + dw=pGizmo->dwData; + pGizmo->dwData=dwData; + } + + return dw; + } + + + +DWORD WINAPI GBGizmoDataGet(HWND hWnd, UINT uID) + { + LPGIZMO pGizmo; + DWORD dw=0L; + + pGizmo=PGizmoFromHwndID(hWnd, uID); + + if (NULL!=pGizmo) + dw=pGizmo->dwData; + + return dw; + } + + + + + + +/* + * GBGizmoNotifySet + * GBGizmoNotifyGet + * + * Purpose: + * Sets or retrieves the notify status of a gizmo. If notify is FALSE, + * the no WM_COMMAND messages are sent from the GizmoBar to the parent + * window when this gizmo is used. + * + * Parameters: + * hWnd HWND of the GizmoBar. + * uID UINT identifier of the gizmo. + * fNotify (Set only) BOOL new notify status to set. + * + * Return Value: + * BOOL Set: Previous value of the notify flag. + * Get: Current value of the notify flag. + */ + +BOOL WINAPI GBGizmoNotifySet(HWND hWnd, UINT uID, BOOL fNotify) + { + LPGIZMO pGizmo; + BOOL fRet=FALSE; + + pGizmo=PGizmoFromHwndID(hWnd, uID); + + if (NULL!=pGizmo) + { + fRet=pGizmo->fNotify; + pGizmo->fNotify=fNotify; + } + + return fRet; + } + + +BOOL WINAPI GBGizmoNotifyGet(HWND hWnd, UINT uID) + { + LPGIZMO pGizmo; + BOOL fRet=FALSE; + + pGizmo=PGizmoFromHwndID(hWnd, uID); + + if (NULL!=pGizmo) + fRet=pGizmo->fNotify; + + return fRet; + } + + + + + + + +/* + * GBGizmoTextSet + * GBGizmoTextGet + * + * Purpose: + * Retrieves or sets text in a GizmoBar gizmo. Separators, command buttons, + * and attribute buttons are not affected by this call. + * + * Parameters: + * hWnd HWND of the GizmoBar. + * uID UINT identifying the gizmo. + * psz LPTSTR (Set) providing the text to show in the window + * or (Get) pointing to a buffer to receive the text. + * cch (Get only) UINT maximum number of chars to copy to psz. + * + * Return Value: + * int Number of characters copied to psz. + */ + +void WINAPI GBGizmoTextSet(HWND hWnd, UINT uID, LPTSTR psz) + { + //This fails on non-windowed gizmos anyway, so we don't check. + SetDlgItemText(hWnd, uID, psz); + return; + } + + +int WINAPI GBGizmoTextGet(HWND hWnd, UINT uID, LPTSTR psz, UINT cch) + { + //This fails on non-windowed gizmos anyway, so we don't check. + return GetDlgItemText(hWnd, uID, psz, cch); + } + + + + + + + + +/* + * GBGizmoIntSet + * GBGizmoIntGet + * + * Purpose: + * Retrieves or sets an integer in a GizmoBar gizmo. Separators, command + * buttons, and attribute buttons are not affected by this call. + * + * Parameters: + * hWnd HWND of the GizmoBar. + * uID UINT identifying the gizmo. + * + * (Set only) + * u UINT value to set in the gizmo. + * fSigned BOOL TRUE to indicate if the value is signed. + * + * (Get only) + * pfTrans BOOL FAR * in which the success of the function is returned. + * fSigned BOOL TRUE to indicate if the value is signed. + * + * Return Value: + * (Set): None + * (Get): UINT Integer translation of the gizmo's text. + */ + +void WINAPI GBGizmoIntSet(HWND hWnd, UINT uID, UINT u, BOOL fSigned) + { + //This fails on non-windowed gizmos anyway, so we don't check. + SetDlgItemInt(hWnd, uID, u, fSigned); + return; + } + + + +UINT WINAPI GBGizmoIntGet(HWND hWnd, UINT uID, BOOL FAR *pfTrans, BOOL fSigned) + { + //This fails on non-windowed gizmos anyway, so we don't check. + return GetDlgItemInt(hWnd, uID, pfTrans, fSigned); + } diff --git a/private/oleutest/letest/gizmobar/book1632.h b/private/oleutest/letest/gizmobar/book1632.h new file mode 100644 index 000000000..435fb200c --- /dev/null +++ b/private/oleutest/letest/gizmobar/book1632.h @@ -0,0 +1,154 @@ +/* + * WIN1632.H + * + * Macros and other definitions that assist in porting between Win16 + * and Win32 applications. Define WIN32 to enable 32-bit versions. + * + * Copyright (c)1993 Microsoft Corporation, All Rights Reserved + * + * Kraig Brockschmidt, Software Design Engineer + * Microsoft Systems Developer Relations + * + * Internet : kraigb@microsoft.com + * Compuserve: INTERNET>kraigb@microsoft.com + */ + + +#ifndef _BOOK1632_H_ +#define _BOOK1632_H_ + +//Macros to handle control message packing between Win16 and Win32 +#ifdef WIN32 + +#define MAKEPOINT MAKEPOINTS + +#ifndef COMMANDPARAMS +#define COMMANDPARAMS(wID, wCode, hWndMsg) \ + WORD wID = LOWORD(wParam); \ + WORD wCode = HIWORD(wParam); \ + HWND hWndMsg = (HWND)(UINT)lParam; +#endif //COMMANDPARAMS + +#ifndef SendCommand +#define SendCommand(hWnd, wID, wCode, hControl) \ + SendMessage(hWnd, WM_COMMAND, MAKELONG(wID, wCode) \ + , (LPARAM)hControl) +#endif //SendCommand + +#ifndef MENUSELECTPARAMS +#define MENUSELECTPARAMS(wID, wFlags, hMenu) \ + WORD wID = LOWORD(wParam); \ + WORD wFlags = HIWORD(wParam); \ + HMENU hMenu = (HMENU)lParam; +#endif //MENUSELECTPARAMS + + +#ifndef SendMenuSelect +#define SendMenuSelect(hWnd, wID, wFlags, hMenu) \ + SendMessage(hWnd, WM_MENUSELECT, MAKELONG(wID, wFlags) \ + , (LPARAM)hMenu) +#endif //SendMenuSelect + +#ifndef SendScrollPosition +#define SendScrollPosition(hWnd, iMsg, iPos) \ + SendMessage(hWnd, iMsg, MAKELONG(SB_THUMBPOSITION, iPos), 0) +#endif //SendScrollPosition + +#ifndef ScrollThumbPosition +#define ScrollThumbPosition(w, l) HIWORD(w) +#endif //ScrollThumbPosition + +#ifndef GETWINDOWINSTANCE +#define GETWINDOWINSTANCE(h) (HINSTANCE)GetWindowLong(h, GWL_HINSTANCE) +#endif //GETWINDOWINSTANCE + +#ifndef GETWINDOWID +#define GETWINDOWID(h) (UINT)GetWindowLong(h, GWW_ID) +#endif //GETWINDOWID + +#ifndef POINTFROMLPARAM +#define POINTFROMLPARAM(p, l) {p.x=(LONG)(SHORT)LOWORD(l); \ + p.y=(LONG)(SHORT)HIWORD(l);} +#endif //POINTEFROMLPARAM + +#ifndef EXPORT +#define EXPORT +#endif //EXPORT + +#ifndef MDIREFRESHMENU +#define MDIREFRESHMENU(h) SendMessage(h, WM_MDIREFRESHMENU, 0, 0L) +#endif //MDIREFRESHMENU + + +//****END WIN32 + + + +#else + + + +//****START !WIN32 + +#ifndef COMMANDPARAMS +#define COMMANDPARAMS(wID, wCode, hWndMsg) \ + WORD wID = LOWORD(wParam); \ + WORD wCode = HIWORD(lParam); \ + HWND hWndMsg = (HWND)(UINT)lParam; +#endif //COMMANDPARAMS + +#ifndef SendCommand +#define SendCommand(hWnd, wID, wCode, hControl) \ + SendMessage(hWnd, WM_COMMAND, wID \ + , MAKELONG(hControl, wCode)) +#endif //SendCommand + +#ifndef MENUSELECTPARAMS +#define MENUSELECTPARAMS(wID, wFlags, hMenu) \ + WORD wID = LOWORD(wParam); \ + WORD wFlags = LOWORD(lParam); \ + HMENU hMenu = (HMENU)HIWORD(lParam); +#endif //MENUSELECTPARAMS + +#ifndef SendMenuSelect +#define SendMenuSelect(hWnd, wID, wFlags, hMenu) \ + SendMessage(hWnd, WM_MENUSELECT, wID \ + , MAKELONG(wFlags, hMenu)) +#endif //SendMenuSelect + +#ifndef SendScrollPosition +#define SendScrollPosition(hWnd, iMsg, iPos) \ + SendMessage(hWnd, iMsg, SB_THUMBPOSITION, MAKELONG(iPos, 0)) +#endif //Send ScrollPosition + +#ifndef ScrollThumbPosition +#define ScrollThumbPosition(w, l) LOWORD(l) +#endif //ScrollThumbPosition + +#ifndef GETWINDOWINSTANCE +#define GETWINDOWINSTANCE(h) (HINSTANCE)GetWindowWord(h, GWW_HINSTANCE) +#endif //GETWINDOWINSTANCE + +#ifndef GETWINDOWID +#define GETWINDOWID(h) (UINT)GetWindowWord(h, GWW_ID) +#endif //GETWINDOWID + +#ifndef POINTFROMLPARAM +#define POINTFROMLPARAM(p, l) {p.x=LOWORD(l); p.y=HIWORD(l);} +#endif //POINTEFROMLPARAM + +#ifndef EXPORT +#define EXPORT __export +#endif //EXPORT + + +#ifndef MDIREFRESHMENU +#define MDIREFRESHMENU(h) SendMessage(h, WM_MDISETMENU, TRUE, 0L) +#endif //MDIREFRESHMENU + + + + +#endif //!WIN32 + +#endif //_BOOK1632_H_ diff --git a/private/oleutest/letest/gizmobar/daytona/gizmobar.src b/private/oleutest/letest/gizmobar/daytona/gizmobar.src new file mode 100644 index 000000000..b59771e9a --- /dev/null +++ b/private/oleutest/letest/gizmobar/daytona/gizmobar.src @@ -0,0 +1,51 @@ +#if 0 + + Microsoft Windows + Copyright (C) Microsoft Corporation, 1992 - 1992. + All rights reserved. + + This .def file is preprocessed by the compiler to create the version for + the current build in the appropriate subdir. Basically, whatever you + would have used in your code to control what is compiled when can be + used in this file for the same purpose. The following defines are in + use at the time this file was written: + + FLAT - Used to indicate a NT/DOS7 build + i386 - Intel i386/i486 build + MIPS - MIPS R3000/R4000 build + ALPHA - DEC Alpha build + DBG - Used to control Debug/Retail. Set to 1 if Debug, + 0 if Retail. + WIN31 - Win16 build + __OS2__ - OS/2 build (used by CT mostly) + + If none of these are used, it is assumed the entire file can be used + for all builds. + +#endif + +#ifdef FLAT + +LIBRARY gizmobar + +DESCRIPTION 'GIZMOBAR' + +EXPORTS + GizmoPAllocate + GizmosExpand + GizmoPFree + GizmosCompact + GizmoPFind + GizmoPEnum + GizmoPStateSet + GizmoPCheck + GBGizmoAdd + GBGizmoEnable + GBGizmoFocusSet + GBGizmoSendMessage + GBGizmoTextGet + GBGizmoTextSet + GBHwndAssociateSet + + +#endif // FLAT diff --git a/private/oleutest/letest/gizmobar/daytona/makefile b/private/oleutest/letest/gizmobar/daytona/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/oleutest/letest/gizmobar/daytona/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/oleutest/letest/gizmobar/daytona/makefile.inc b/private/oleutest/letest/gizmobar/daytona/makefile.inc new file mode 100644 index 000000000..afd853b6b --- /dev/null +++ b/private/oleutest/letest/gizmobar/daytona/makefile.inc @@ -0,0 +1 @@ +obj\*\gizmobar.def: gizmobar.src diff --git a/private/oleutest/letest/gizmobar/daytona/sources b/private/oleutest/letest/gizmobar/daytona/sources new file mode 100644 index 000000000..bbce019a8 --- /dev/null +++ b/private/oleutest/letest/gizmobar/daytona/sources @@ -0,0 +1,50 @@ +# This links against bttncur.lib so block all threads to assure that +# bttncur is built. +SYNCHRONIZE_BLOCK=1 +SYNCHRONIZE_DRAIN=1 + +TARGETNAME=gizmobar + +TARGETPATH=obj + +TARGETTYPE=DYNLINK + +DLLDEF= obj\*\gizmobar.def + +TARGETLIBS=$(GUI32_LIBS) \ + $(WIN32_LIBS) \ + ..\..\bttncur\daytona\obj\*\bttncur.lib + +DLLBASE=@$(BASEDIR)\PUBLIC\SDK\LIB\coffbase.txt,usermode + +DLLENTRY= DllEntryPoint + +UMTYPE=windows + +C_DEFINES=-DWIN32 -DFLAT + +INCLUDES=..\..\bttncur; \ + .. + +BLDCRT=1 + +SOURCES= \ + ..\gizmobar.rc \ + ..\api.c \ + ..\init.c \ + ..\dllentry.c \ + ..\paint.c \ + ..\gizmo.c \ + ..\gizmobar.c + +!IF $(386) +NTTARGETFILE0=$(DLLDEF:*=i386) +!ENDIF + +!IF $(MIPS) +NTTARGETFILE0=$(DLLDEF:*=mips) +!ENDIF + +!IF $(ALPHA) +NTTARGETFILE0=$(DLLDEF:*=alpha) +!ENDIF diff --git a/private/oleutest/letest/gizmobar/dirs b/private/oleutest/letest/gizmobar/dirs new file mode 100644 index 000000000..c33a3de9b --- /dev/null +++ b/private/oleutest/letest/gizmobar/dirs @@ -0,0 +1,37 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + dirs. + +Abstract: + + This file specifies the subdirectories of the current directory that + contain component makefiles. + + +Author: + + JohannP 01/11/95 + +!ENDIF + +# +# This is a list of all subdirectories that build required components. +# Each subdirectory name should appear on a line by itself. The build +# follows the order in which the subdirectories are specified. +# + +DIRS= + +# +# This is a list of all subdirectories that build optional components. +# Each subdirectory name should appear on a line by itself. The build +# follows the order in which the subdirectories are specified. +# + +OPTIONAL_DIRS= \ + \ + daytona diff --git a/private/oleutest/letest/gizmobar/dllentry.c b/private/oleutest/letest/gizmobar/dllentry.c new file mode 100644 index 000000000..1cd1159e4 --- /dev/null +++ b/private/oleutest/letest/gizmobar/dllentry.c @@ -0,0 +1,55 @@ +//+------------------------------------------------------------------- +// +// Microsoft Windows +// Copyright (C) Microsoft Corporation, 1991 - 1992. +// +// File: dllentry.c +// +// Contents: Dll Entry point code. Calls the appropriate run-time +// init/term code and then defers to LibMain for further +// processing. +// +// Classes: +// +// Functions: DllEntryPoint - Called by loader +// +// History: 10-May-92 BryanT Created +// 22-Jul-92 BryanT Switch to calling _cexit/_mtdeletelocks +// on cleanup. +// 06-Oct-92 BryanT Call RegisterWithCommnot on entry +// and DeRegisterWithCommnot on exit. +// This should fix the heap dump code. +// 27-Dec-93 AlexT Post 543 builds don't need special code. +// +//-------------------------------------------------------------------- + +#define USE_CRTDLL +#include + +BOOL WINAPI _CRT_INIT (HANDLE hDll, DWORD dwReason, LPVOID lpReserved); + +BOOL DllEntryPoint (HANDLE hDll, DWORD dwReason, LPVOID lpReserved); + +BOOL _CRTAPI1 LibMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved); + +BOOL DllEntryPoint (HANDLE hDll, DWORD dwReason, LPVOID lpReserved) +{ + BOOL fRc = FALSE; + + switch (dwReason) + { + case DLL_PROCESS_ATTACH: + _CRT_INIT(hDll, dwReason, lpReserved); + + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + fRc = LibMain (hDll, dwReason, lpReserved); + break; + + case DLL_PROCESS_DETACH: + fRc = LibMain (hDll, dwReason, lpReserved); + _CRT_INIT(hDll, dwReason, lpReserved); + } + + return(fRc); +} diff --git a/private/oleutest/letest/gizmobar/gizmo.c b/private/oleutest/letest/gizmobar/gizmo.c new file mode 100644 index 000000000..c763c3bba --- /dev/null +++ b/private/oleutest/letest/gizmobar/gizmo.c @@ -0,0 +1,766 @@ +/* + * GIZMO.C + * GizmoBar Version 1.00, Win32 version August 1993 + * + * Allocate, free, find, and enumerate functions for the GIZMO structure + * and a generic subclass procedure to handle tabbing between gizmos. + * + * Copyright (c)1993 Microsoft Corporation, All Rights Reserved + * + * Kraig Brockschmidt, Software Design Engineer + * Microsoft Systems Developer Relations + * + * Internet : kraigb@microsoft.com + * Compuserve: >INTERNET:kraigb@microsoft.com + */ + + +#include +#include "gizmoint.h" + + +/* + * In order to control tabbing in the gizmos, we need to subclass + * real pushbuttons, edit controls, listboxes, and comboboxes. So + * we keep an array of the four original procs for such controls. + */ +WNDPROC pfnOrg[CSUBGIZMOS]={NULL, NULL, NULL, NULL}; + + +TCHAR szStatic[]=TEXT("static"); +TCHAR szEdit[]=TEXT("edit"); +TCHAR szCombobox[]=TEXT("combobox"); +TCHAR szListbox[]=TEXT("listbox"); +TCHAR szButton[]=TEXT("button"); + + +//Here so PAINT.C can get at it. +TOOLDISPLAYDATA tdd; + + + +/* + * GizmoPAllocate + * + * Purpose: + * Allocates and initializes a GIZMO data structure. + * + * Parameters: + * pfSuccess LPINT flag indicating success of failure. + * ppFirst LPLPGIZMO providing the first gizmo in this list. + * hWndParent HWND of the parent of this gizmo. Can be NULL for + * iType==GIZMOTYPE_BUTTON* or GIZMOTYPE_SEPARATOR. + * iType UINT gizmo control type. + * iGizmo UINT index of this gizmo in the GizmoBar. + * uID UINT identifier to send with WM_COMMAND for this control. + * dx, dy UINT width and height of the gizmo. + * pszText LPTSTR to the text for edits, listboxes, combobox, and text. + * dwStyle DWORD style for edits, lists, and combos, and texts. + * hBmp HBITMAP for button gizmos, is applicable. + * iImage UINT index into hBmp for the button image, if applicable. + * uState UINT initial state of the control. + * + * Return Value: + * LPGIZMO If NULL returned then GizmoPAllocate could not allocate + * memory. If a non-NULL pointer is returned with + * *pfSuccess, then call GizmoPFree immediately. If you + * get a non-NULL pointer and *pfSuccess==TRUE then the + * function succeeded. + */ + +LPGIZMO GizmoPAllocate(LPINT pfSuccess, LPLPGIZMO ppFirst, HWND hWndParent + , UINT iType, UINT iGizmo, UINT uID, UINT dx, UINT dy, LPTSTR pszText + , HBITMAP hBmp, UINT iImage, UINT uState) + { + LPGIZMO pGizmo; + LPGIZMO pCur, pPrev; + LPTSTR pszClass; + HINSTANCE hInst; + UINT i; + DWORD dwStyle; + HWND hWndE; + + if (NULL==pfSuccess) + return NULL; + + //Make sure we know of this gizmo type. + if (GIZMOTYPE_MIN > iType || GIZMOTYPE_MAX < iType) + return NULL; + + *pfSuccess=FALSE; + + //Allocate the structure + pGizmo=(LPGIZMO)LocalAlloc(LPTR, CBGIZMO); + + if (NULL==pGizmo) + return NULL; + + + //Store the necessary information for this gizmo. + pGizmo->iType =iType; + pGizmo->uID =uID; + pGizmo->hBmp =hBmp; + pGizmo->iBmp =iImage; + pGizmo->uState =uState; + pGizmo->fNotify =TRUE; + + + /* + * Insert this structure into our gizmo list. Each time we scan + * we increment the index counter (starting at zero) comparing it + * to the desired index of insertion. We then know exactly where + * to insert this new gizmo. Note that we insert the new gizmo in + * the list appropriately for the given owner, so enumerations will + * come out ordered in the same way for that owner. + */ + + i=0; + pCur=*ppFirst; + pPrev=NULL; + + while (NULL!=pCur && i++ < iGizmo) + { + pPrev=pCur; + pCur =pCur->pNext; + } + + //Point to our neighbors + pGizmo->pPrev=pPrev; + pGizmo->pNext=pCur; + + + //Point out neighbors to us. + if (NULL==pPrev) + *ppFirst=pGizmo; + else + pPrev->pNext=pGizmo; + + if (NULL!=pCur) + pCur->pPrev=pGizmo; + + + //Our x-coordinate is the x of the previous gizmo plus its width. + if (NULL!=pPrev) + pGizmo->x=pGizmo->pPrev->x+pGizmo->pPrev->dx; + else + pGizmo->x=4; //First gizmo is at x=4 + + + //If we're a separator or image button, force standards on dx. + UIToolConfigureForDisplay(&tdd); + pGizmo->cxImage=tdd.cxImage; + pGizmo->cyImage=tdd.cyImage; + + if ((GIZMOTYPE_DRAWN & iType) && NULL==hBmp) + dx=tdd.cxButton; + + if (GIZMOTYPE_SEPARATOR==iType) + dx=6; + + /* + * Now create windows for edits, texts, lists, and comboboxes. + * First calculate the most often defaults used in the switch. + */ + pGizmo->dx=dx+6; + pGizmo->dy=min(dy, tdd.cyButton); + pGizmo->y=2; + pszClass=NULL; + + //If this is new gizmo is a window, create it. + switch (iType) + { + case GIZMOTYPE_TEXT: + pGizmo->dx=dx; + pGizmo->y=(tdd.cyBar-1-pGizmo->dy) >> 1; //Center vertically. + pszClass=szStatic; + dwStyle=SS_LEFT; + break; + + case GIZMOTYPE_EDIT: + pGizmo->y=(tdd.cyBar-1-pGizmo->dy) >> 1; //Center vertically. + pszClass=szEdit; + dwStyle=ES_LEFT | WS_BORDER | WS_TABSTOP; + break; + + case GIZMOTYPE_LISTBOX: + pGizmo->dy=dy; + pszClass=szCombobox; + dwStyle=CBS_DROPDOWNLIST | WS_TABSTOP; + break; + + case GIZMOTYPE_COMBOBOX: + pGizmo->dy=dy; + pszClass=szCombobox; + dwStyle=CBS_DROPDOWN | WS_TABSTOP; + break; + + case GIZMOTYPE_BUTTONNORMAL: + pGizmo->dy=dy; + pszClass=szButton; + dwStyle=BS_PUSHBUTTON | WS_TABSTOP; + break; + + case GIZMOTYPE_SEPARATOR: + pGizmo->dx=dx; + pGizmo->y=3; + break; + + case GIZMOTYPE_BUTTONATTRIBUTEIN: + case GIZMOTYPE_BUTTONATTRIBUTEEX: + case GIZMOTYPE_BUTTONCOMMAND: + pGizmo->dx=dx; + pGizmo->y=3; + break; + } + + + //If we matched a classname, create a window. + if (GIZMOTYPE_WINDOWS & iType) + { + if (!IsWindow(hWndParent)) + return pGizmo; + + hInst=(HINSTANCE) GetWindowLong(hWndParent, GWL_HINSTANCE); + + pGizmo->hWnd=CreateWindow(pszClass, pszText + , dwStyle | WS_CHILD | WS_VISIBLE, pGizmo->x, pGizmo->y + , dx, pGizmo->dy, hWndParent, (HMENU)uID, hInst, NULL); + + if (NULL==pGizmo->hWnd) + return pGizmo; + + /* + * Subclass comboboxes, listboxes, edits, and windowed buttons. + * We use iType to index the original proc array so we can use + * a single subclass procedure for all controls. If you mess + * with the gizmo type definitions, this is going to break. + */ + + if (GIZMOTYPE_WINDOWS & iType && GIZMOTYPE_TEXT!=iType) + { + //Give the window its type. + BITPOSITION(iType, i); + SetProp(pGizmo->hWnd, SZTYPEPROP, (HANDLE)i); + + if (NULL==pfnOrg[i]) + pfnOrg[i]=(WNDPROC)GetWindowLong(pGizmo->hWnd, GWL_WNDPROC); + + SetWindowLong(pGizmo->hWnd, GWL_WNDPROC, (LONG)GenericSubProc); + + //If we're a combobox, get the edit control and subclass it. + if (GIZMOTYPE_COMBOBOX==iType) + { + hWndE=GetDlgItem(pGizmo->hWnd, ID_COMBOEDIT); + SetProp(hWndE, SZTYPEPROP, (HANDLE)-1); //Special flag. + + if (NULL==pfnOrg[0]) + pfnOrg[0]=(WNDPROC)GetWindowLong(pGizmo->hWnd, GWL_WNDPROC); + + SetWindowLong(hWndE, GWL_WNDPROC, (LONG)GenericSubProc); + } + } + } + + + //Finally, move all our neighbors to the right over to accomodate us. + GizmosExpand(pGizmo); + + *pfSuccess=TRUE; + return pGizmo; + } + + + + + + +/* + * GizmoPFree + * + * Purpose: + * Reverses all initialization done by GizmoPAllocate, cleaning up + * any allocations including the application structure itself. + * + * Parameters: + * ppFirst LPLPGIZMO providing the first gizmo in this list. + * pGizmo LPGIZMO to the structure + * + * Return Value: + * LPGIZMO NULL if successful, pGizmo if not, meaning we couldn't + * free something. + */ + +LPGIZMO GizmoPFree(LPLPGIZMO ppFirst, LPGIZMO pGizmo) + { + int i; + + if (NULL==pGizmo) + return NULL; + + //Move other gizmos to fill in this gap. + GizmosCompact(pGizmo); + + //Unsubclass + if (GIZMOTYPE_WINDOWS & pGizmo->iType && GIZMOTYPE_TEXT!=pGizmo->iType) + { + i=(int)GetProp(pGizmo->hWnd, SZTYPEPROP); + RemoveProp(pGizmo->hWnd, SZTYPEPROP); + + SetWindowLong(pGizmo->hWnd, GWL_WNDPROC, (LONG)pfnOrg[i]); + } + + //If this was a window gizmo, destroy the window. + if (NULL!=pGizmo->hWnd && IsWindow(pGizmo->hWnd)) + DestroyWindow(pGizmo->hWnd); + + //Unlink ourselves. + if (NULL!=pGizmo->pNext) + pGizmo->pNext->pPrev=pGizmo->pPrev; + + if (NULL!=pGizmo->pPrev) + pGizmo->pPrev->pNext=pGizmo->pNext; + else + *ppFirst=pGizmo->pNext; + + return (LPGIZMO)LocalFree((HLOCAL)(UINT)(LONG)pGizmo); + } + + + + + + +/* + * GizmosExpand + * + * Purpose: + * Given a starting gizmo and a width, moves it and all gizmos to its + * right to the right by the width to make space for showing or creating + * a new gizmo. + * + * Parameters: + * pGizmo LPGIZMO specifying the gizmo that was inserted. + * + * Return Value: + * None + */ + +void GizmosExpand(LPGIZMO pGizmo) + { + int cx; + + cx=(int)pGizmo->dx; + + /* + * If we and the next control are buttons, use our width-1 to + * expand so we overlap borders with our neighboring button. + */ + + if (NULL!=pGizmo->pNext) + { + if ((GIZMOTYPE_BUTTONS & pGizmo->pNext->iType) + && (GIZMOTYPE_BUTTONS & pGizmo->iType)) + cx-=1; + } + + //Walk the gizmo list moving them right by our width. + pGizmo=pGizmo->pNext; + + while (NULL!=pGizmo) + { + pGizmo->x+=cx; + + //hWnd is NULL for buttons and separators. + if (NULL!=pGizmo->hWnd) + SetWindowPos(pGizmo->hWnd, NULL, pGizmo->x, pGizmo->y, 0, 0, SWP_NOZORDER | SWP_NOSIZE); + + pGizmo=pGizmo->pNext; + } + + return; + } + + + + + + + +/* + * GizmosCompact + * + * Purpose: + * Given a gizmo, moves all other gizmos to the right of it to the + * left by its width on the GizmoBar. Used when removing or hiding + * the gizmo. + * + * Parameters: + * pGizmo LPGIZMO that is going away, visibly or physically. + * + * Return Value: + * None + */ + +void GizmosCompact(LPGIZMO pGizmo) + { + UINT cx; + LPGIZMO pCur; + + //Move all the gizmos beyond us on the GizmoBar back by our width. + if (NULL!=pGizmo->pNext) + { + cx=pGizmo->pNext->x - pGizmo->x; + pCur=pGizmo->pNext; + + while (NULL!=pCur) + { + pCur->x-=cx; + + if (NULL!=pCur->hWnd) + { + SetWindowPos(pCur->hWnd, NULL, pCur->x, pCur->y + , 0, 0, SWP_NOZORDER | SWP_NOSIZE); + } + + pCur=pCur->pNext; + } + } + + return; + } + + + + + + +/* + * GizmoPFind + * + * Purpose: + * Given a GIZMO identifier, locates and returns a pointer to the structure + * for that position. + * + * Parameters: + * ppFirst LPLPGIZMO providing the first gizmo in this list. + * uID UINT identifier to find. + * + * Return Value: + * LPGIZMO A pointer to a GIZMO structure allocated through + * GizmoPAllocate, NULL if iGizmo is out of range. + */ + +LPGIZMO GizmoPFind(LPLPGIZMO ppFirst, UINT uID) + { + LPGIZMO pGizmo; + + pGizmo=*ppFirst; + + /* + * Yep, linear search, but a better search algorithm won't improve + * things appreciably. The better thing to optimize is what the + * caller passes as ppFirst. + */ + while (NULL!=pGizmo && uID!=pGizmo->uID) + pGizmo=pGizmo->pNext; + + return pGizmo; + } + + + + + + +/* + * GizmoFEnum + * + * Purpose: + * Enumerates the list of GIZMO structures, passing each one to + * an application-defined callback. + * + * Parameters: + * ppFirst LPLPGIZMO providing the first gizmo in this list. + * pfnEnum LPFNGIZMOENUM to call for each enumerated structure. + * dw DWORD extra data to pass to the enumeration function. + * + * Return Value: + * LPGIZMO NULL if the enumeration completed. Otherwise a pointer + * to the gizmo that enumeration stopped on. + */ + +LPGIZMO GizmoPEnum(LPLPGIZMO ppFirst, LPFNGIZMOENUM pfnEnum, DWORD dw) + { + LPGIZMO pGizmo; + UINT i=0; + + pGizmo=*ppFirst; + + while (NULL!=pGizmo) + { + if (!(*pfnEnum)(pGizmo, i++, dw)) + break; + + pGizmo=pGizmo->pNext; + } + + return pGizmo; + } + + + + +/* + * GizmoPStateSet + * + * Purpose: + * State maniuplation functions. Set and Clear also invalidate + * this gizmo's rectangle on the given window and forces a repaint. + * + * Parameters: + * hWnd HWND of the window to repaint. + * pGizmo LPGIZMO affected. + * dwNew DWORD new state flags. + * + * Return Value: + * UINT Previous state. + */ + +UINT GizmoPStateSet(HWND hWnd, LPGIZMO pGizmo, UINT uNew) + { + UINT uRet; + RECT rc; + + if (GIZMOTYPE_SEPARATOR==pGizmo->iType) + return pGizmo->uState; + + //Preserve the color conversion flags across this state change. + uRet=pGizmo->uState; + pGizmo->uState=(uNew & 0x00FF) | (uRet & 0xFF00); + + //Adjust the rectangle by one to avoid repainting borders. + SetRect(&rc, pGizmo->x+1, pGizmo->y+1, pGizmo->x+pGizmo->dx-1, pGizmo->y+pGizmo->dy-1); + InvalidateRect(hWnd, &rc, FALSE); + UpdateWindow(hWnd); + + return uRet; + } + + + + + + + + +/* + * GizmoPCheck + * + * Purpose: + * Handles checking a single button in a group of attribute buttons. + * If the gizmo belongs to a group of mutually exclusive buttons then + * the others surrounding it are unchecked appropriately. + * + * Parameters: + * hWnd HWND of the GizmoBar. + * pGizmo LPGIZMO of the gizmo affected. + * fCheck BOOL TRUE to check the button, FALSE to uncheck. + * + * Return Value: + * BOOL TRUE if the gizmo was previously checked, FALSE + * otherwise. + */ + +BOOL GizmoPCheck(HWND hWnd, LPGIZMO pGizmo, BOOL fCheck) + { + BOOL fPrevCheck; + LPGIZMO pCur; + + + //Ignore command buttons. + if (GIZMOTYPE_BUTTONCOMMAND==pGizmo->iType) + return FALSE; + + //Get the previous state + fPrevCheck=(BOOL)(BUTTONGROUP_DOWN & pGizmo->uState); + + + //Simply set the state for inclusive attribute buttons. + if (GIZMOTYPE_BUTTONATTRIBUTEIN==pGizmo->iType) + { + if (pGizmo->fDisabled) + { + GizmoPStateSet(hWnd, pGizmo + , fCheck ? ATTRIBUTEBUTTON_DOWNDISABLED : ATTRIBUTEBUTTON_DISABLED); + } + else + { + GizmoPStateSet(hWnd, pGizmo + , fCheck ? ATTRIBUTEBUTTON_DOWN : ATTRIBUTEBUTTON_UP); + } + } + + + if (GIZMOTYPE_BUTTONATTRIBUTEEX==pGizmo->iType) + { + //We cannot uncheck an exclusive attribute + if (!fCheck) + return fPrevCheck; + + /* + * For exclusive buttons we have to do more work. First, if we're + * already checked (incliding DOWN and MOUSEDOWN) then we set DOWN + * and exit. If we're not already checked, then we look for the + * gizmo around us, backwards and forwards, that is checked and + * uncheck him. + */ + + //Search backwards. + pCur=pGizmo->pPrev; + + while (NULL!=pCur) + { + //Stop at any non-exclusive attribute. + if (GIZMOTYPE_BUTTONATTRIBUTEEX!=pCur->iType) + { + pCur=NULL; + break; + } + + //If it's down, set it up and we've finished. + if (BUTTONGROUP_DOWN & pCur->uState) + break; + + pCur=pCur->pPrev; + } + + + //If we didn't find a previous one, pCur is NULL, so look ahead. + if (NULL==pCur) + { + pCur=pGizmo->pNext; + + while (NULL!=pCur) + { + //Stop at any non-exclusive attribute. + if (GIZMOTYPE_BUTTONATTRIBUTEEX!=pCur->iType) + { + pCur=NULL; + break; + } + + //If it's down, set it up and we've finished. + if (BUTTONGROUP_DOWN & pCur->uState) + break; + + pCur=pCur->pNext; + } + } + + //If pCur is non-NULL, the we found a neighbor, so uncheck him + if (NULL!=pCur) + { + GizmoPStateSet(hWnd, pCur + , (pGizmo->fDisabled) ? ATTRIBUTEBUTTON_DISABLED : ATTRIBUTEBUTTON_UP); + } + + //Always set ourselves down + GizmoPStateSet(hWnd, pGizmo + , (pGizmo->fDisabled) ? ATTRIBUTEBUTTON_DOWNDISABLED : ATTRIBUTEBUTTON_DOWN); + } + + return fPrevCheck; + } + + + + + + + +/* + * GenericSubProc + * + * Purpose: + * Subclasses window controls in Gizmos so we can trap the tab key and + * tab to the next control. We can have one shared generic subclass + * procedure because we save the type index for this control in the + * property "iType." This allows us to look up the original procedure + * in the pfnOrg array. + * + * Parameters: + * Standard + * + * Return Value: + * Standard + */ + +//LRESULT FAR PASCAL EXPORT GenericSubProc(HWND hWnd, UINT iMsg +LRESULT FAR PASCAL GenericSubProc(HWND hWnd, UINT iMsg + , WPARAM wParam, LPARAM lParam) + { + LONG lRet; + RECT rc; + RECT rcE; + HWND hWndE; + HBRUSH hBr; + HDC hDC; + UINT dx; + UINT iType, i; + + i=(int)GetProp(hWnd, SZTYPEPROP); + iType=POSITIONBIT(i); + + //Special: paint the gap in drop-down comboboxes. + if (GIZMOTYPE_COMBOBOX==iType && WM_PAINT==iMsg) + { + //Do default painting. + lRet=(*pfnOrg[i])(hWnd, iMsg, wParam, lParam); + + hWndE=GetDlgItem(hWnd, ID_COMBOEDIT); + + GetClientRect(hWnd, &rc); + GetClientRect(hWndE, &rcE); + + //The width of the button is the scroll bar width. + dx=GetSystemMetrics(SM_CXVSCROLL); + + //Calculate the rectangle + rc.right -=dx; + rc.left =rcE.right; + rc.bottom+=1; + + //Paint the gap + hDC=GetDC(hWnd); //Already did BeginPaint and EndPaint + + hBr=CreateSolidBrush(GetSysColor(COLOR_BTNFACE)); + FillRect(hDC, &rc, hBr); + DeleteObject(hBr); + + ReleaseDC(hWnd, hDC); + return lRet; + } + + //Control tabbing to the next or previous control in the GizmoBar. + if (WM_KEYDOWN==iMsg && VK_TAB==wParam) + { + hWndE=hWnd; + + if (-1==i) + hWndE=GetParent(hWnd); + + hWndE=GetNextDlgTabItem(GetParent(hWndE), hWnd, (BOOL)(GetKeyState(VK_SHIFT))); + SetFocus(hWndE); + return 0L; + } + + if (-1==i) i=0; + + //Eat tab chars in edit controls to prevent beeping. + if (0==i && WM_CHAR==iMsg && VK_TAB==wParam) + return 0L; + + + //Do this or edit controls bomb big-time. + return CallWindowProc(pfnOrg[i], hWnd, iMsg, wParam, lParam); + } diff --git a/private/oleutest/letest/gizmobar/gizmo.h b/private/oleutest/letest/gizmobar/gizmo.h new file mode 100644 index 000000000..e99e06379 --- /dev/null +++ b/private/oleutest/letest/gizmobar/gizmo.h @@ -0,0 +1,103 @@ +/* + * GIZMO.H + * GizmoBar Version 1.00, Win32 version August 1993 + * + * Data structure and type definitions for the GIZMO data structure. Each + * gizmo on a gizmobar has one of these structures associated with it. + * + * Copyright (c)1993 Microsoft Corporation, All Rights Reserved + * + * Kraig Brockschmidt, Software Design Engineer + * Microsoft Systems Developer Relations + * + * Internet : kraigb@microsoft.com + * Compuserve: >INTERNET:kraigb@microsoft.com + */ + + +#ifndef _GIZMO_H_ +#define _GIZMO_H_ + +#ifdef __cplusplus +extern "C" + { +#endif + + +typedef struct tagGIZMO + { + struct tagGIZMO FAR *pPrev; + struct tagGIZMO FAR *pNext; + UINT iType; + HWND hWnd; //Texts, edits, lists, and combos only. + UINT uID; + UINT x, y; + UINT dx, dy; + UINT cxImage; //From UIToolConfigureForDisplay + UINT cyImage; + HBITMAP hBmp; //Buttons only. + UINT iBmp; + BOOL fNotify; //Indicates whether we send WM_COMMANDs + BOOL fHidden; //Independent of state + BOOL fDisabled; + UINT uState; + UINT uStateOrg; + DWORD dwData; //Application-supplied data. + } GIZMO, FAR * LPGIZMO; + +typedef LPGIZMO FAR *LPLPGIZMO; +#define CBGIZMO sizeof(GIZMO) + +//Property name we attach to controls in a gizmo to identify control type +#define SZTYPEPROP TEXT("iType") + +//Number of controls we subclass +#define CSUBGIZMOS 4 + +//ID of edit controls in comboboxes +#define ID_COMBOEDIT 1001 + + +/* + * Conversion of iType (a positioned bit) into its position. + * The BITPOSITION macro does not need to be fast because we only + * use it once when creating a gizmo. POSITIONBIT does, however, since + * we use it in subclass procedures. + */ +#define BITPOSITION(i, j) {int k=i; for (j=0; k>>=1; j++);} +#define POSITIONBIT(i) (1 << i) + +//Control classifications. GIZMOBAR.H must be included first. +#define GIZMOTYPE_WINDOWS (GIZMOTYPE_TEXT | GIZMOTYPE_EDIT | GIZMOTYPE_LISTBOX | GIZMOTYPE_COMBOBOX | GIZMOTYPE_BUTTONNORMAL) +#define GIZMOTYPE_BUTTONS (GIZMOTYPE_BUTTONATTRIBUTEIN | GIZMOTYPE_BUTTONATTRIBUTEEX | GIZMOTYPE_BUTTONCOMMAND | GIZMOTYPE_BUTTONNORMAL) +#define GIZMOTYPE_DRAWN (GIZMOTYPE_BUTTONATTRIBUTEIN | GIZMOTYPE_BUTTONATTRIBUTEEX | GIZMOTYPE_BUTTONCOMMAND) + + +//These must stay in sync with GIZMOBAR.H +#define GIZMOTYPE_MIN GIZMOTYPE_EDIT +#define GIZMOTYPE_MAX GIZMOTYPE_BUTTONCOMMAND + + +//Enumeration callback +typedef BOOL (FAR PASCAL *LPFNGIZMOENUM)(LPGIZMO, UINT, DWORD); + + +//GIZMO.C +LPGIZMO GizmoPAllocate(LPINT, LPLPGIZMO, HWND, UINT, UINT, UINT, UINT, UINT, LPTSTR, HBITMAP, UINT, UINT); +void GizmosExpand(LPGIZMO); +LPGIZMO GizmoPFree(LPLPGIZMO, LPGIZMO); +void GizmosCompact(LPGIZMO); +LPGIZMO GizmoPFind(LPLPGIZMO, UINT); +LPGIZMO GizmoPEnum(LPLPGIZMO, LPFNGIZMOENUM, DWORD); +UINT GizmoPStateSet(HWND, LPGIZMO, UINT); +BOOL GizmoPCheck(HWND, LPGIZMO, BOOL); + +//LRESULT FAR PASCAL EXPORT GenericSubProc(HWND, UINT, WPARAM, LPARAM); +LRESULT FAR PASCAL GenericSubProc(HWND, UINT, WPARAM, LPARAM); + + +#ifdef __cplusplus + } +#endif + +#endif //_GIZMO_H_ diff --git a/private/oleutest/letest/gizmobar/gizmobar.c b/private/oleutest/letest/gizmobar/gizmobar.c new file mode 100644 index 000000000..78b4fafd0 --- /dev/null +++ b/private/oleutest/letest/gizmobar/gizmobar.c @@ -0,0 +1,467 @@ +/* + * GIZMOBAR.C + * GizmoBar Version 1.00, Win32 version August 1993 + * + * Contains the main window procedure of the GizmoBar control + * that handles mouse logic and Windows messages. + * + * Copyright (c)1993 Microsoft Corporation, All Rights Reserved + * + * Kraig Brockschmidt, Software Design Engineer + * Microsoft Systems Developer Relations + * + * Internet : kraigb@microsoft.com + * Compuserve: >INTERNET:kraigb@microsoft.com + */ + + +#include +#include "gizmoint.h" + + + +/* + * GizmoBarWndProc + * + * Purpose: + * Window Procedure for the GizmoBar custom control. Handles all + * messages like WM_PAINT just as a normal application window would. + * Any message not processed here should go to DefWindowProc. + * + * Parameters: + * Standard + * + * Return Value: + * Standard + */ + +LRESULT FAR PASCAL GizmoBarWndProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam) + { + BOOL fSuccess; + BOOL fTemp; + LPCREATESTRUCT pCreate; + LPGIZMOBAR pGB; + LPGIZMO pGizmo; + RECT rc; + POINT pt; + short x, y; + COLORREF cr; + + COMMANDPARAMS(wID, wCode, hWndMsg); + + pGB=(LPGIZMOBAR)GetWindowLong(hWnd, GBWL_STRUCTURE); + + //Pass control messages onto another function for processing. + if (iMsg >= WM_USER) + return GBMessageHandler(hWnd, iMsg, wParam, lParam, pGB); + + switch (iMsg) + { + case WM_NCCREATE: + pCreate=(LPCREATESTRUCT)lParam; + + pGB=GizmoBarPAllocate((LPINT)&fSuccess, hWnd, pCreate->hInstance + , pCreate->hwndParent, pCreate->style, 0 + , (UINT)pCreate->hMenu); + + if (!fSuccess) + { + GizmoBarPFree(pGB); + return -1L; + } + else + SetWindowLong(hWnd, GBWL_STRUCTURE, (LONG)pGB); + + return DefWindowProc(hWnd, iMsg, wParam, lParam); + + + case WM_DESTROY: + /* + * We want to clean up before DestroyWindow nukes all the + * children, so WM_DESTROY is a better to do it than + * WM_NCDESTROY. + */ + GizmoBarPFree(pGB); + break; + + + case WM_ERASEBKGND: + /* + * Eat this message to avoid erasing portions that + * we are going to repaint in WM_PAINT. Part of a + * change-state-and-repaint strategy is to rely on + * WM_PAINT to do anything visual, which includes + * erasing invalid portions. Letting WM_ERASEBKGND + * erase the background is redundant. + */ + return TRUE; + + #ifdef WIN32 + case WM_CTLCOLORBTN: + case WM_CTLCOLORSTATIC: + fTemp=TRUE; + #else + case WM_CTLCOLOR: + //Change the color of static text on the GizmoBar. + fTemp=(HIWORD(lParam)==CTLCOLOR_STATIC + || HIWORD(lParam)==CTLCOLOR_BTN); + #endif + + if (fTemp) + { + cr=GetSysColor(COLOR_BTNFACE); + SetTextColor((HDC)wParam, GetSysColor(COLOR_BTNTEXT)); + SetBkColor((HDC)wParam, cr); + + /* + * If the system colors have changed, then crFace will + * not be equal to COLOR_BTNFACE, so we reinitialize the + * background brush. This scheme handles system color + * changes appropriately without processing WM_WININICHANGE + * and without blindly creating a new brush on every + * WM_CTLCOLOR message. + */ + if (cr!=pGB->crFace) + { + pGB->crFace=cr; + + if (NULL!=pGB->hBrFace) + DeleteObject(pGB->hBrFace); + + pGB->hBrFace=CreateSolidBrush(pGB->crFace); + } + + return (LONG)(UINT)pGB->hBrFace; + } + + return DefWindowProc(hWnd, iMsg, wParam, lParam); + + + case WM_PAINT: + GizmoBarPaint(hWnd, pGB); + break; + + + case WM_SETFONT: + /* + * wParam has the new font that we now send to all other + * windows controls in us. We control repaints here to + * prevent a lot of repainting for each control. + */ + DefWindowProc(hWnd, WM_SETREDRAW, FALSE, 0L); + + if ((WPARAM)NULL!=wParam) + { + pGB->hFont=(HFONT)wParam; + GizmoPEnum(&pGB->pGizmos, FEnumChangeFont, (DWORD)(LPSTR)pGB); + + DefWindowProc(hWnd, WM_SETREDRAW, TRUE, 0L); + InvalidateRect(hWnd, NULL, FALSE); + UpdateWindow(hWnd); + } + + break; + + + case WM_GETFONT: + return (LRESULT)(UINT)pGB->hFont; + + + case WM_ENABLE: + /* + * wParam has the new enable flag that we use to enable + * or disable ALL controls in us at one time. We also turn + * the redraw off to prevent a lot of flicker. + */ + DefWindowProc(hWnd, WM_SETREDRAW, FALSE, 0L); + + pGB->fEnabled=(BOOL)wParam; + GizmoPEnum(&pGB->pGizmos, FEnumEnable, (DWORD)(LPSTR)pGB); + + DefWindowProc(hWnd, WM_SETREDRAW, TRUE, 0L); + InvalidateRect(hWnd, NULL, FALSE); + UpdateWindow(hWnd); + break; + + + case WM_CANCELMODE: + pGizmo=pGB->pGizmoTrack; + + pGB->fTracking=FALSE; + pGB->fMouseOut=FALSE; + + if (NULL!=pGizmo) + GizmoPStateSet(hWnd, pGizmo, COMMANDBUTTON_UP); + + ReleaseCapture(); + break; + + + case WM_LBUTTONDBLCLK: + case WM_LBUTTONDOWN: + //Get the mouse coordinates. + x=LOWORD(lParam); + y=HIWORD(lParam); + + + /* + * See if we hit a command or attribute gizmo or not. Anything + * else that is a control will get the message instead of + * us anyway, so we don't have to check. FEnumHitTest also + * validates drawn gizmos, enabled, and visible, so we don't. + */ + pGizmo=GizmoPEnum(&pGB->pGizmos, FEnumHitTest, lParam); + + if (NULL==pGizmo) + break; //Didn't hit one matching our needs. + + /* + * Inform the associate that a command was hit like a menu item. + */ + if (NULL!=pGB->hWndAssociate) + { + if (pGizmo->fNotify) + SendMenuSelect(pGB->hWndAssociate, pGizmo->uID, 0, 0); + } + + /* + * We hit a button. If it's a command or attribute, then change + * the state and start tracking. + */ + pGB->fTracking=TRUE; + pGB->pGizmoTrack=pGizmo; + pGB->fMouseOut=FALSE; + SetCapture(hWnd); + + pGizmo->uStateOrg=pGizmo->uState; + GizmoPStateSet(hWnd, pGizmo, ATTRIBUTEBUTTON_MOUSEDOWN); + + break; + + + case WM_MOUSEMOVE: + POINTFROMLPARAM(pt, lParam); + + if (!pGB->fTracking) + break; + + pGizmo=pGB->pGizmoTrack; + SetRect(&rc, pGizmo->x, pGizmo->y, pGizmo->x+pGizmo->dx, pGizmo->y+pGizmo->dy); + + fTemp=pGB->fMouseOut; + pGB->fMouseOut=!PtInRect(&rc, pt); + + //If the mouse went out, change state to the original. + if (!fTemp && pGB->fMouseOut) + { + GizmoPStateSet(hWnd, pGizmo, pGizmo->uStateOrg); + + if (NULL!=pGB->hWndAssociate) + { + //Notify that we left the button + if (pGizmo->fNotify) + SendMenuSelect(pGB->hWndAssociate, 0x0000, 0xFFFF, 0); + } + } + + if (fTemp && !pGB->fMouseOut) + { + GizmoPStateSet(hWnd, pGizmo, ATTRIBUTEBUTTON_MOUSEDOWN); + + if (NULL!=pGB->hWndAssociate) + { + //Notify that we pressed down again + if (pGizmo->fNotify) + SendMenuSelect(pGB->hWndAssociate, pGizmo->uID, 0x0000, 0); + } + } + + break; + + + case WM_LBUTTONUP: + if (!pGB->fTracking) + break; + + pGB->fTracking=FALSE; + pGizmo=pGB->pGizmoTrack; + ReleaseCapture(); + + + /* + * Repaint if we were actually below the mouse when this + * occurred. For command buttons, pop the button up. For + * attributes, either toggle the state (inclusive buttons) + * or check the selected one (exclusive buttons). + */ + + if (!pGB->fMouseOut) + { + //Command buttons always come up. + if (GIZMOTYPE_BUTTONCOMMAND==pGizmo->iType) + GizmoPStateSet(hWnd, pGizmo, COMMANDBUTTON_UP); + + //Attribute inclusive buttons toggle + if (GIZMOTYPE_BUTTONATTRIBUTEIN==pGizmo->iType) + GizmoPCheck(hWnd, pGizmo, !(BUTTONGROUP_DOWN & pGizmo->uStateOrg)); + + //Attribure exclusive buttons are always checked. + if (GIZMOTYPE_BUTTONATTRIBUTEEX==pGizmo->iType) + GizmoPCheck(hWnd, pGizmo, TRUE); + + //Only send messages if notify is ON. + if (NULL!=pGB->hWndAssociate && pGizmo->fNotify) + { + SendMenuSelect(pGB->hWndAssociate, 0, 0xFFFF, 0); + SendCommand(pGB->hWndAssociate, pGizmo->uID, BN_CLICKED, hWnd); + } + } + + break; + + + case WM_COMMAND: + //Pass control messages on if the gizmo's notify is ON. + if (NULL!=pGB->hWndAssociate) + { + pGizmo=PGizmoFromHwndID(hWnd, wID); + + if (NULL!=pGizmo) + { + if (pGizmo->fNotify) + SendMessage(pGB->hWndAssociate, iMsg, wParam, lParam); + } + } + break; + + default: + return DefWindowProc(hWnd, iMsg, wParam, lParam); + } + + return 0L; + } + + + + + +/* + * FEnumChangeFont + * + * Purpose: + * Enumeration callback for all the gizmos we know about in order to + * send a new font to them that's stored in LPGIZMOBAR in dw. + * + * Parameters: + * pGizmo LPGIZMO to draw. + * iGizmo UINT index on the GizmoBar of this gizmo. + * dw DWORD extra data passed to GizmoPEnum, in our case + * the GizmoBar's pGB. + * + * Return Value: + * BOOL TRUE to continue the enumeration, FALSE otherwise. + */ + +BOOL FAR PASCAL FEnumChangeFont(LPGIZMO pGizmo, UINT iGizmo, DWORD dw) + { + LPGIZMOBAR pGB=(LPGIZMOBAR)dw; + + //We only need to change fonts in windowed controls using WM_SETFONT + if (NULL!=pGizmo->hWnd) + SendMessage(pGizmo->hWnd, WM_SETFONT, (WPARAM)pGB->hFont, 1L); + + return TRUE; + } + + + + + + +/* + * FEnumEnable + * + * Purpose: + * Enumeration callback for all the gizmos we know about in order to + * enable or disable them from the WM_ENABLE message. + * + * Parameters: + * pGizmo LPGIZMO to draw. + * iGizmo UINT index on the GizmoBar of this gizmo. + * dw DWORD extra data passed to GizmoPEnum, in our case + * the GizmoBar's pGB. + * + * Return Value: + * BOOL TRUE to continue the enumeration, FALSE otherwise. + */ + +BOOL FAR PASCAL FEnumEnable(LPGIZMO pGizmo, UINT iGizmo, DWORD dw) + { + LPGIZMOBAR pGB=(LPGIZMOBAR)dw; + BOOL fEnable=pGB->fEnabled; + + //NOTE: This code is duplicated in GBGizmoEnable in API.C + if (NULL!=pGizmo->hWnd) + EnableWindow(pGizmo->hWnd, fEnable); + else + { + //If we're not down, command and attribute buttons act the same. + if (!(BUTTONGROUP_DOWN & pGizmo->uState)) + { + GizmoPStateSet(pGB->hWnd, pGizmo + , fEnable ? COMMANDBUTTON_UP : COMMANDBUTTON_DISABLED); + } + else + { + //Attribute buttons are a little more sensitive with DOWNDISABLED + GizmoPStateSet(pGB->hWnd, pGizmo + , fEnable ? ATTRIBUTEBUTTON_DOWN : ATTRIBUTEBUTTON_DOWNDISABLED); + } + } + + return TRUE; + } + + + + + + + +/* + * FEnumHitTest + * + * Purpose: + * Enumeration callback for all the gizmos we know about in order to + * hit-test them. + * + * Parameters: + * pGizmo LPGIZMO to draw. + * iGizmo UINT index on the GizmoBar of this gizmo. + * dw DWORD extra data passed to GizmoPEnum, in our case + * the hDC on which to draw. + * + * Return Value: + * BOOL TRUE to continue the enumeration, FALSE otherwise. + */ + +BOOL FAR PASCAL FEnumHitTest(LPGIZMO pGizmo, UINT iGizmo, DWORD dw) + { + RECT rc; + POINT pt; + + POINTFROMLPARAM(pt, dw); + + //Hit tests have to happen on visible, enabled, and drawn controls only. + if (GIZMOTYPE_DRAWN & pGizmo->iType + && !pGizmo->fHidden && !(BUTTONGROUP_DISABLED & pGizmo->uState)) + { + SetRect(&rc, pGizmo->x, pGizmo->y + , pGizmo->x+pGizmo->dx, pGizmo->y+pGizmo->dy); + + //Stop enumeration if we have a hit. + return !PtInRect(&rc, pt); + } + + return TRUE; + } diff --git a/private/oleutest/letest/gizmobar/gizmobar.h b/private/oleutest/letest/gizmobar/gizmobar.h new file mode 100644 index 000000000..f4888f925 --- /dev/null +++ b/private/oleutest/letest/gizmobar/gizmobar.h @@ -0,0 +1,178 @@ +/* + * GIZMOBAR.H + * GizmoBar Version 1.00, Win32 version August 1993 + * + * Public definitions for application that use the GizmoBar such as + * messages, prototypes for API functions, notification codes, and + * control styles. + * + * Copyright (c)1993 Microsoft Corporation, All Rights Reserved + * + * Kraig Brockschmidt, Software Design Engineer + * Microsoft Systems Developer Relations + * + * Internet : kraigb@microsoft.com + * Compuserve: >INTERNET:kraigb@microsoft.com + */ + + +#ifndef _GIZMOBAR_H_ +#define _GIZMOBAR_H_ + +#ifdef __cplusplus +extern "C" + { +#endif + + +//Classname +#define CLASS_GIZMOBAR TEXT("gizmobar") + + +//Message API Functions +HWND WINAPI GBHwndAssociateSet(HWND, HWND); +HWND WINAPI GBHwndAssociateGet(HWND); + +BOOL WINAPI GBGizmoAdd(HWND, UINT, UINT, UINT, UINT, UINT, LPTSTR, HBITMAP, UINT, UINT); +BOOL WINAPI GBGizmoRemove(HWND, UINT); + +LRESULT WINAPI GBGizmoSendMessage(HWND, UINT, UINT, WPARAM, LPARAM); + +BOOL WINAPI GBGizmoShow(HWND, UINT, BOOL); +BOOL WINAPI GBGizmoEnable(HWND, UINT, BOOL); +BOOL WINAPI GBGizmoCheck(HWND, UINT, BOOL); +UINT WINAPI GBGizmoFocusSet(HWND, UINT); +BOOL WINAPI GBGizmoExist(HWND, UINT); + +int WINAPI GBGizmoTypeGet(HWND, UINT); + +DWORD WINAPI GBGizmoDataSet(HWND, UINT, DWORD); +DWORD WINAPI GBGizmoDataGet(HWND, UINT); +BOOL WINAPI GBGizmoNotifySet(HWND, UINT, BOOL); +BOOL WINAPI GBGizmoNotifyGet(HWND, UINT); + +int WINAPI GBGizmoTextGet(HWND, UINT, LPTSTR, UINT); +void WINAPI GBGizmoTextSet(HWND, UINT, LPTSTR); +UINT WINAPI GBGizmoIntGet(HWND, UINT, BOOL FAR *, BOOL); +void WINAPI GBGizmoIntSet(HWND, UINT, UINT, BOOL); + + + +//Notification codes sent via WM_COMMAND from GBHwndAssociateSet +#define GBN_ASSOCIATEGAIN 1 +#define GBN_ASSOCIATELOSS 2 +#define GBN_GIZMOADDED 3 +#define GBN_GIZMOREMOVED 4 + +//Message equivalents for functions. +#define GBM_HWNDASSOCIATESET (WM_USER+0) +#define GBM_HWNDASSOCIATEGET (WM_USER+1) +#define GBM_GIZMOADD (WM_USER+2) +#define GBM_GIZMOREMOVE (WM_USER+3) +#define GBM_GIZMOSENDMESSAGE (WM_USER+4) +#define GBM_GIZMOSHOW (WM_USER+5) +#define GBM_GIZMOENABLE (WM_USER+6) +#define GBM_GIZMOCHECK (WM_USER+7) +#define GBM_GIZMOFOCUSSET (WM_USER+8) +#define GBM_GIZMOEXIST (WM_USER+9) +#define GBM_GIZMOTYPEGET (WM_USER+10) +#define GBM_GIZMODATASET (WM_USER+11) +#define GBM_GIZMODATAGET (WM_USER+12) +#define GBM_GIZMONOTIFYSET (WM_USER+13) +#define GBM_GIZMONOTIFYGET (WM_USER+14) +#define GBM_GIZMOTEXTGET (WM_USER+15) +#define GBM_GIZMOTEXTSET (WM_USER+16) +#define GBM_GIZMOINTGET (WM_USER+17) +#define GBM_GIZMOINTSET (WM_USER+18) + + + + +/* + * Structure passed in lParam of GBM_GIZMOADD that mirrors the parameters + * to GBGizmoAdd. + */ + +typedef struct + { + HWND hWndParent; //Parent window + UINT iType; //Type of gizmo + UINT iGizmo; //Position in which to create gizmo + UINT uID; //Identifier of gizmo (for WM_COMMAND messages) + UINT dx; //Dimensions of gizmo + UINT dy; + LPTSTR pszText; //Gizmo text + HBITMAP hBmp; //Source of gizmo button image. + UINT iImage; //Index of image from hBmp + UINT uState; //Initial state of the gizmo. + } CREATEGIZMO, FAR *LPCREATEGIZMO; + +#define CBCREATEGIZMO sizeof(CREATEGIZMO) + + +//For GBM_GIZMOSENDMESSAGE +typedef struct + { + UINT iMsg; + WPARAM wParam; + LPARAM lParam; + } GBMSG, FAR * LPGBMSG; + +#define CBGBMSG sizeof(GBMSG); + +//For GBM_GIZMOGETTEXT +typedef struct + { + LPTSTR psz; + UINT cch; + } GBGETTEXT, FAR * LPGBGETTEXT; + +#define CBGBGETTEXT sizeof(GBGETTEXT); + + +//For GBM_GIZMOGETINT +typedef struct + { + BOOL fSigned; + BOOL fSuccess; + } GBGETINT, FAR * LPGBGETINT; + +#define CBGBGETINT sizeof(GBGETINT); + + +//For GBM_GIZMOSETINT +typedef struct + { + UINT uValue; + BOOL fSigned; + } GBSETINT, FAR * LPGBSETINT; + +#define CBGBSETINT sizeof(GBSETINT); + + + +//Gizmo control types. DO NOT CHANGE THESE! +#define GIZMOTYPE_EDIT 0x0001 +#define GIZMOTYPE_LISTBOX 0x0002 +#define GIZMOTYPE_COMBOBOX 0x0004 +#define GIZMOTYPE_BUTTONNORMAL 0x0008 //Top of windowed gizmos. +#define GIZMOTYPE_TEXT 0x0010 +#define GIZMOTYPE_SEPARATOR 0x0020 +#define GIZMOTYPE_BUTTONATTRIBUTEIN 0x0040 +#define GIZMOTYPE_BUTTONATTRIBUTEEX 0x0080 +#define GIZMOTYPE_BUTTONCOMMAND 0x0100 + + +//Generic state flags for non-buttons based on BTTNCUR.H's button groups. +#define GIZMO_NORMAL (BUTTONGROUP_ACTIVE) +#define GIZMO_DISABLED (BUTTONGROUP_DISABLED) + + + +#ifdef __cplusplus + } //Match with extern "C" above. +#endif + + + +#endif //_GIZMOBAR_H_ diff --git a/private/oleutest/letest/gizmobar/gizmobar.rc b/private/oleutest/letest/gizmobar/gizmobar.rc new file mode 100644 index 000000000..e1550028e --- /dev/null +++ b/private/oleutest/letest/gizmobar/gizmobar.rc @@ -0,0 +1,20 @@ +/* + * GIZMOBAR.RC + * GizmoBar Version 1.00, Win32 version August 1993 + * + * Strings and other resources for the GizmoBar. + * + * Copyright (c)1993 Microsoft Corporation, All Rights Reserved + * + * Kraig Brockschmidt, Software Design Engineer + * Microsoft Systems Developer Relations + * + * Internet : kraigb@microsoft.com + * Compuserve: >INTERNET:kraigb@microsoft.com + */ + + +#include +#include "gizmoint.h" + +rcinclude gizmobar.rcv diff --git a/private/oleutest/letest/gizmobar/gizmobar.rcv b/private/oleutest/letest/gizmobar/gizmobar.rcv new file mode 100644 index 000000000..8958b7a2f --- /dev/null +++ b/private/oleutest/letest/gizmobar/gizmobar.rcv @@ -0,0 +1,53 @@ +/* + * GIZMOBAR.RCV + * GizmoBar Version 1.00, Win32 version August 1993 + * + * Version resource file for the GizmoBar Control DLL + * + * Copyright (c)1993 Microsoft Corporation, All Rights Reserved + * + * Kraig Brockschmidt, Software Design Engineer + * Microsoft Systems Developer Relations + * + * Internet : kraigb@microsoft.com + * Compuserve: >INTERNET:kraigb@microsoft.com + */ + +//Default is nodebug +#ifndef DEBUG +#define VER_DEBUG 0 +#else +#define VER_DEBUG VS_FF_DEBUG +#endif + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,0 + PRODUCTVERSION 1,0,0,0 + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK + FILEFLAGS VER_DEBUG + FILEOS VOS_DOS_WINDOWS16 + FILETYPE VFT_DLL + FILESUBTYPE VFT_UNKNOWN + + BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + BEGIN + VALUE "CompanyName", "Microsoft Corporation\0", "\0" + VALUE "FileDescription", "Kraig Brockschmidt's GizmoBar", "\0" + VALUE "FileVersion", "1.00\0", "\0" + VALUE "InternalName", "GIZMOBAR.DLL", "\0" + VALUE "LegalCopyright", "Copyright \251 1993 Microsoft Corp.", "\0" + VALUE "OriginalFilename","GIZMOBAR.DLL", "\0" + VALUE "ProductName", "Kraig Brockschmidt's GizmoBar", "\0" + VALUE "ProductVersion", "1.00\0" + END + END + + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 0x04E4 + END + END + diff --git a/private/oleutest/letest/gizmobar/gizmoint.h b/private/oleutest/letest/gizmobar/gizmoint.h new file mode 100644 index 000000000..842b62a3e --- /dev/null +++ b/private/oleutest/letest/gizmobar/gizmoint.h @@ -0,0 +1,105 @@ +/* + * GIZMOINT.H + * GizmoBar Version 1.00, Win32 version August 1993 + * + * Internal definitions for the GizmoBar DLL + * + * Copyright (c)1993 Microsoft Corporation, All Rights Reserved + * + * Kraig Brockschmidt, Software Design Engineer + * Microsoft Systems Developer Relations + * + * Internet : kraigb@microsoft.com + * Compuserve: >INTERNET:kraigb@microsoft.com + */ + + +#ifndef _GIZMOINT_H_ +#define _GIZMOINT_H_ + +#include +#include +#include "gizmo.h" +#include "gizmobar.h" + +#ifdef __cplusplus +extern "C" + { +#endif + + +/* + * The main gizmobar structure itself. There's only one of these, + * but it references the first GIZMO in the list. + */ + +typedef struct tagGIZMOBAR + { + LPGIZMO pGizmos; //List of gizmos we own. + HWND hWnd; //Window handle of ourselves. + HINSTANCE hInst; + HWND hWndAssociate; //Associate window handle who gets messages. + DWORD dwStyle; //Copy of GetWindowLong(hWnd, GWL_STYLE) + UINT uState; //State flags + UINT uID; //Control ID. + + HBRUSH hBrFace; //Static control background color + COLORREF crFace; //Color of hBrFace + HFONT hFont; //Font in use, defaults to system, WM_SETFONT + BOOL fEnabled; //Are we enabled? + + LPGIZMO pGizmoTrack; //Current pressed button. + BOOL fTracking; + BOOL fMouseOut; + } GIZMOBAR, FAR * LPGIZMOBAR; + +#define CBGIZMOBAR sizeof(GIZMOBAR) + + +//Extra bytes for the window if the size of a local handle. +#define CBWINDOWEXTRA sizeof(LPGIZMOBAR) + +#define GBWL_STRUCTURE 0 + + +//Structure for passing paint information to a gizmo enumeration callback. +typedef struct + { + HDC hDC; + BOOL fPaint; + } PAINTGIZMO, FAR * LPPAINTGIZMO; + + + +//Private functions specific to the control. + +//INIT.C +#ifdef WIN32 + extern BOOL WINAPI _CRT_INIT(HINSTANCE, DWORD, LPVOID); + extern _cexit(void); +#endif //WIN32 + +void FAR PASCAL WEP(int); +BOOL FRegisterControl(HINSTANCE); +LPGIZMOBAR GizmoBarPAllocate(LPINT, HWND, HINSTANCE, HWND, DWORD, UINT, UINT); +LPGIZMOBAR GizmoBarPFree(LPGIZMOBAR); + + +//PAINT.C +void GizmoBarPaint(HWND, LPGIZMOBAR); +BOOL FAR PASCAL FEnumPaintGizmos(LPGIZMO, UINT, DWORD); + + +//GIZMOBAR.C +LRESULT FAR PASCAL GizmoBarWndProc(HWND, UINT, WPARAM, LPARAM); +BOOL FAR PASCAL FEnumChangeFont(LPGIZMO, UINT, DWORD); +BOOL FAR PASCAL FEnumEnable(LPGIZMO, UINT, DWORD); +BOOL FAR PASCAL FEnumHitTest(LPGIZMO, UINT, DWORD); + + +//API.C Also see GIZMOBAR.H for others +LRESULT GBMessageHandler(HWND, UINT, WPARAM, LPARAM, LPGIZMOBAR); +LPGIZMO PGizmoFromHwndID(HWND, UINT); + + +#endif //_GIZMOINT_H_ diff --git a/private/oleutest/letest/gizmobar/init.c b/private/oleutest/letest/gizmobar/init.c new file mode 100644 index 000000000..736ef47b4 --- /dev/null +++ b/private/oleutest/letest/gizmobar/init.c @@ -0,0 +1,233 @@ +/* + * INIT.C + * GizmoBar Version 1.00, Win32 version August 1993 + * + * LibMain entry point and initialization code for the GizmoBar + * DLL that is likely to be used once or very infrequently. + * + * Copyright (c)1993 Microsoft Corporation, All Rights Reserved + * + * Kraig Brockschmidt, Software Design Engineer + * Microsoft Systems Developer Relations + * + * Internet : kraigb@microsoft.com + * Compuserve: >INTERNET:kraigb@microsoft.com + */ + + +#include +#include "gizmoint.h" + + +/* + * LibMain + * + * Purpose: + * Entry point conditionally compiled for Windows NT and Windows + * 3.1. Provides the proper structure for each environment + * and calls InternalLibMain for real initialization. + */ + +#ifdef WIN32 +BOOL _cdecl LibMain( + HINSTANCE hDll, + DWORD dwReason, + LPVOID lpvReserved) + { + if (DLL_PROCESS_ATTACH == dwReason) + { + return FRegisterControl(hDll); + } + else + { + return TRUE; + } + } + +#else +HANDLE FAR PASCAL LibMain(HANDLE hInstance, WORD wDataSeg + , WORD cbHeapSize, LPSTR lpCmdLine) + { + //Perform global initialization. + if (FRegisterControl(hInstance)) + { + if (0!=cbHeapSize) + UnlockData(0); + } + + return hInstance; + } +#endif + + + + +/* + * WEP + * + * Purpose: + * Required DLL Exit function. Does nothing. + * + * Parameters: + * bSystemExit BOOL indicating if the system is being shut + * down or the DLL has just been unloaded. + * + * Return Value: + * void + * + */ + +void FAR PASCAL WEP(int bSystemExit) + { + return; + } + + + + +/* + * FRegisterControl + * + * Purpose: + * Registers the GizmoBar control class, including CS_GLOBALCLASS + * to make the control available to all applications in the system. + * + * Parameters: + * hInst HINSTANCE of the DLL that will own this class. + * + * Return Value: + * BOOL TRUE if the class is registered, FALSE otherwise. + */ + +BOOL FRegisterControl(HINSTANCE hInst) + { + static BOOL fRegistered=FALSE; + WNDCLASS wc; + + if (!fRegistered) + { + wc.lpfnWndProc =GizmoBarWndProc; + wc.cbClsExtra =0; + wc.cbWndExtra =CBWINDOWEXTRA; + wc.hInstance =hInst; + wc.hIcon =NULL; + wc.hCursor =LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground =(HBRUSH)(COLOR_BTNFACE+1); + wc.lpszMenuName =NULL; + wc.lpszClassName =CLASS_GIZMOBAR; + wc.style =CS_DBLCLKS | CS_GLOBALCLASS | CS_VREDRAW | CS_HREDRAW; + + fRegistered=RegisterClass(&wc); + } + + return fRegistered; + } + + + + + + +/* + * GizmoBarPAllocate + * + * Purpose: + * Allocates and initializes the control's primary data structure for + * each window that gets created. + * + * Parameters: + * pfSuccess LPINT indicating success of the function. + * hWnd HWND that is tied to this structure. + * hInst HINSTANCE of the DLL. + * hWndAssociate HWND to which we send messages. + * dwStyle DWORD initial style. + * uState UINT initial state. + * uID UINT identifier for this window. + * + * Return Value: + * LPGIZMOBAR If NULL returned then GizmoBarPAllocate could not allocate + * memory. If a non-NULL pointer is returned with + * *pfSuccess, then call GizmoBarPFree immediately. If you + * get a non-NULL pointer and *pfSuccess==TRUE then the + * function succeeded. + */ + +LPGIZMOBAR GizmoBarPAllocate(LPINT pfSuccess, HWND hWnd, HINSTANCE hInst + , HWND hWndAssociate, DWORD dwStyle, UINT uState, UINT uID) + { + LPGIZMOBAR pGB; + + if (NULL==pfSuccess) + return NULL; + + *pfSuccess=FALSE; + + //Allocate the structure + pGB=(LPGIZMOBAR)(void *)LocalAlloc(LPTR, CBGIZMOBAR); + + if (NULL==pGB) + return NULL; + + //Initialize LibMain parameter holders. + pGB->hWnd =hWnd; + pGB->hInst =hInst; + pGB->hWndAssociate=hWndAssociate; + pGB->dwStyle =dwStyle; + pGB->uState =uState; + pGB->uID =uID; + pGB->fEnabled =TRUE; + + pGB->crFace=GetSysColor(COLOR_BTNFACE); + pGB->hBrFace=CreateSolidBrush(pGB->crFace); + + if (NULL==pGB->hBrFace) + return pGB; + + pGB->hFont=GetStockObject(SYSTEM_FONT); + + *pfSuccess=TRUE; + return pGB; + } + + + + +/* + * GizmoBarPFree + * + * Purpose: + * Reverses all initialization done by GizmoBarPAllocate, cleaning up + * any allocations including the application structure itself. + * + * Parameters: + * pGB LPGIZMOBAR to the control's structure + * + * Return Value: + * LPGIZMOBAR NULL if successful, pGB if not, meaning we couldn't + * free some allocation. + */ + +LPGIZMOBAR GizmoBarPFree(LPGIZMOBAR pGB) + { + if (NULL==pGB) + return NULL; + + /* + * Free all the gizmos we own. When we call GizmoPFree we always + * free the first one in the list which updates pGB->pGizmos for + * us, so we just have to keep going until pGizmos is NULL, meaning + * we're at the end of the list. + */ + while (NULL!=pGB->pGizmos) + GizmoPFree(&pGB->pGizmos, pGB->pGizmos); + + if (NULL!=pGB->hBrFace) + DeleteObject(pGB->hBrFace); + + /* + * Notice that since we never create a font, we aren't responsible + * for our hFont member. + */ + + return (LPGIZMOBAR)(void *)LocalFree((HLOCAL)(void *)(LONG)pGB); + } diff --git a/private/oleutest/letest/gizmobar/paint.c b/private/oleutest/letest/gizmobar/paint.c new file mode 100644 index 000000000..14f6c5930 --- /dev/null +++ b/private/oleutest/letest/gizmobar/paint.c @@ -0,0 +1,132 @@ +/* + * PAINT.C + * GizmoBar Version 1.00, Win32 version August 1993 + * + * Contains any code related to GizmoBar visuals, primarily + * the WM_PAINT handler. + * + * Copyright (c)1993 Microsoft Corporation, All Rights Reserved + * + * Kraig Brockschmidt, Software Design Engineer + * Microsoft Systems Developer Relations + * + * Internet : kraigb@microsoft.com + * Compuserve: >INTERNET:kraigb@microsoft.com + */ + + +#include +#include "gizmoint.h" + + +//In GIZMO.C +extern TOOLDISPLAYDATA tdd; + + +/* + * GizmoBarPaint + * + * Purpose: + * Handles all WM_PAINT messages for the control and paints either the + * entire thing or just one GizmoBar button if pGB->pGizmoPaint is non-NULL. + * + * Parameters: + * hWnd HWND Handle to the control. + * pGB LPGIZMOBAR control data pointer. + * + * Return Value: + * None + */ + +void GizmoBarPaint(HWND hWnd, LPGIZMOBAR pGB) + { + PAINTSTRUCT ps; + RECT rc; + HDC hDC; + HBRUSH hBr=NULL; + HPEN hPen=NULL; + + + hDC=BeginPaint(hWnd, &ps); + GetClientRect(hWnd, &rc); + + /* + * The only part of the frame we need to draw is the bottom line, + * so we inflate the rectangle such that all other parts are outside + * the visible region. + */ + hBr =CreateSolidBrush(GetSysColor(COLOR_BTNFACE)); + + if (NULL!=hBr) + SelectObject(hDC, hBr); + + hPen=CreatePen(PS_SOLID, 1, GetSysColor(COLOR_WINDOWFRAME)); + + if (NULL!=hPen) + SelectObject(hDC, hPen); + + Rectangle(hDC, rc.left-1, rc.top-1, rc.right+1, rc.bottom); + + + /* + * All that we have to do to draw the controls is start through the + * list, ignoring anything but buttons, and calling BTTNCUR's + * UIToolButtonDraw for buttons. Since we don't even have to track + * positions of things, we can just use an enum. + */ + GizmoPEnum(&pGB->pGizmos, FEnumPaintGizmos, (DWORD)(LPSTR)&ps); + + //Clean up + EndPaint(hWnd, &ps); + + if (NULL!=hBr) + DeleteObject(hBr); + + if (NULL!=hPen) + DeleteObject(hPen); + + return; + } + + + + + +/* + * FEnumPaintGizmos + * + * Purpose: + * Enumeration callback for all the gizmos we know about in order to + * draw them. + * + * Parameters: + * pGizmo LPGIZMO to draw. + * iGizmo UINT index on the GizmoBar of this gizmo. + * dw DWORD extra data passed to GizmoPEnum, in our case + * a pointer to the PAINTSTRUCT. + * + * Return Value: + * BOOL TRUE to continue the enumeration, FALSE otherwise. + */ + +BOOL FAR PASCAL FEnumPaintGizmos(LPGIZMO pGizmo, UINT iGizmo, DWORD dw) + { + LPPAINTSTRUCT pps=(LPPAINTSTRUCT)dw; + RECT rc, rcI; + + //Only draw those marked for repaint. + if ((GIZMOTYPE_DRAWN & pGizmo->iType)) + { + SetRect(&rc, pGizmo->x, pGizmo->y, pGizmo->x+pGizmo->dx, pGizmo->y+pGizmo->dy); + + //Only draw gizmos in the repaint area + if (IntersectRect(&rcI, &rc, &pps->rcPaint)) + { + UIToolButtonDrawTDD(pps->hdc, pGizmo->x, pGizmo->y + , pGizmo->dx, pGizmo->dy, pGizmo->hBmp, pGizmo->cxImage + , pGizmo->cyImage, pGizmo->iBmp, (UINT)pGizmo->uState, &tdd); + } + } + + return TRUE; + } diff --git a/private/oleutest/letest/ole2ui/bang.ico b/private/oleutest/letest/ole2ui/bang.ico new file mode 100644 index 000000000..90fe0f220 Binary files /dev/null and b/private/oleutest/letest/ole2ui/bang.ico differ diff --git a/private/oleutest/letest/ole2ui/busy.c b/private/oleutest/letest/ole2ui/busy.c new file mode 100644 index 000000000..7be5c7414 --- /dev/null +++ b/private/oleutest/letest/ole2ui/busy.c @@ -0,0 +1,551 @@ +/* + * BUSY.C + * + * Implements the OleUIBusy function which invokes the "Server Busy" + * dialog. + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + +#define STRICT 1 +#include "ole2ui.h" +#include "common.h" +#include "utility.h" +#include "busy.h" +#include // for tolower() and toupper() + +#ifndef WIN32 +#include +#endif + + +/* + * OleUIBusy + * + * Purpose: + * Invokes the standard OLE "Server Busy" dialog box which + * notifies the user that the server application is not receiving + * messages. The dialog then asks the user to either cancel + * the operation, switch to the task which is blocked, or continue + * waiting. + * + * Parameters: + * lpBZ LPOLEUIBUSY pointing to the in-out structure + * for this dialog. + * + * Return Value: + * OLEUI_BZERR_HTASKINVALID : Error + * OLEUI_BZ_SWITCHTOSELECTED : Success, user selected "switch to" + * OLEUI_BZ_RETRYSELECTED : Success, user selected "retry" + * OLEUI_CANCEL : Success, user selected "cancel" + */ + +STDAPI_(UINT) OleUIBusy(LPOLEUIBUSY lpOBZ) + { + UINT uRet = 0; + HGLOBAL hMemDlg=NULL; + +#if !defined( WIN32 ) +// BUGBUG32: this is not yet ported to NT + + uRet=UStandardValidation((LPOLEUISTANDARD)lpOBZ, sizeof(OLEUIBUSY) + , &hMemDlg); + + // Error out if the standard validation failed + if (OLEUI_SUCCESS!=uRet) + return uRet; + + // Validate HTASK + if (!IsTask(lpOBZ->hTask)) + uRet = OLEUI_BZERR_HTASKINVALID; + + // Error out if our secondary validation failed + if (OLEUI_ERR_STANDARDMIN <= uRet) + { + if (NULL!=hMemDlg) + FreeResource(hMemDlg); + + return uRet; + } + + // Invoke the dialog. + uRet=UStandardInvocation(BusyDialogProc, (LPOLEUISTANDARD)lpOBZ, + hMemDlg, MAKEINTRESOURCE(IDD_BUSY)); +#endif + + return uRet; +} + + +/* + * BusyDialogProc + * + * Purpose: + * Implements the OLE Busy dialog as invoked through the OleUIBusy function. + * + * Parameters: + * Standard + * + * Return Value: + * Standard + * + */ + +BOOL CALLBACK EXPORT BusyDialogProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam) + { + LPBUSY lpBZ; + UINT uRet = 0; + + //Declare Win16/Win32 compatible WM_COMMAND parameters. + COMMANDPARAMS(wID, wCode, hWndMsg); + + //This will fail under WM_INITDIALOG, where we allocate it. + lpBZ=(LPBUSY)LpvStandardEntry(hDlg, iMsg, wParam, lParam, &uRet); + + //If the hook processed the message, we're done. + if (0!=uRet) + return (BOOL)uRet; + + //Process the temination message + if (iMsg==uMsgEndDialog) + { + BusyCleanup(hDlg); + StandardCleanup(lpBZ, hDlg); + EndDialog(hDlg, wParam); + return TRUE; + } + + // Process our special "close" message. If we get this message, + // this means that the call got unblocked, so we need to + // return OLEUI_BZ_CALLUNBLOCKED to our calling app. + if (iMsg == uMsgCloseBusyDlg) + { + SendMessage(hDlg, uMsgEndDialog, OLEUI_BZ_CALLUNBLOCKED, 0L); + return TRUE; + } + + switch (iMsg) + { + case WM_INITDIALOG: + FBusyInit(hDlg, wParam, lParam); + return TRUE; + + case WM_ACTIVATEAPP: + { + /* try to bring down our Busy/NotResponding dialog as if + ** the user entered RETRY. + */ + BOOL fActive = (BOOL)wParam; + if (fActive) { + // If this is the app BUSY case, then bring down our + // dialog when switching BACK to our app + if (lpBZ && !(lpBZ->dwFlags & BZ_NOTRESPONDINGDIALOG)) + SendMessage(hDlg,uMsgEndDialog,OLEUI_BZ_RETRYSELECTED,0L); + } else { + // If this is the app NOT RESPONDING case, then bring down + // our dialog when switching AWAY to another app + if (lpBZ && (lpBZ->dwFlags & BZ_NOTRESPONDINGDIALOG)) + SendMessage(hDlg,uMsgEndDialog,OLEUI_BZ_RETRYSELECTED,0L); + } + return TRUE; + } + + case WM_COMMAND: + switch (wID) + { + case IDBZ_SWITCHTO: + { + BOOL fNotRespondingDlg = + (BOOL)(lpBZ->dwFlags & BZ_NOTRESPONDINGDIALOG); + + // If user selects "Switch To...", switch activation + // directly to the window which is causing the problem. + if (IsWindow(lpBZ->hWndBlocked)) + MakeWindowActive(lpBZ->hWndBlocked); + else + StartTaskManager(); // Fail safe: Start Task Manager + + // If this is the app not responding case, then we want + // to bring down the dialog when "SwitchTo" is selected. + // If the app is busy (RetryRejectedCall situation) then + // we do NOT want to bring down the dialog. this is + // the OLE2.0 user model design. + if (fNotRespondingDlg) + SendMessage(hDlg, uMsgEndDialog, OLEUI_BZ_SWITCHTOSELECTED, 0L); + break; + } + case IDBZ_RETRY: + SendMessage(hDlg, uMsgEndDialog, OLEUI_BZ_RETRYSELECTED, 0L); + break; + + case IDCANCEL: + SendMessage(hDlg, uMsgEndDialog, OLEUI_CANCEL, 0L); + break; + } + break; + } + return FALSE; + } + + +/* + * FBusyInit + * + * Purpose: + * WM_INITIDIALOG handler for the Busy dialog box. + * + * Parameters: + * hDlg HWND of the dialog + * wParam WPARAM of the message + * lParam LPARAM of the message + * + * Return Value: + * BOOL Value to return for WM_INITDIALOG. + */ + +BOOL FBusyInit(HWND hDlg, WPARAM wParam, LPARAM lParam) + { + LPBUSY lpBZ; + LPOLEUIBUSY lpOBZ; + HFONT hFont; + LPTSTR lpTaskName; + LPTSTR lpWindowName; + HICON hIcon; + + lpBZ=(LPBUSY)LpvStandardInit(hDlg, sizeof(OLEUIBUSY), TRUE, &hFont); + + // PvStandardInit sent a termination to us already. + if (NULL==lpBZ) + return FALSE; + + // Our original structure is in lParam + lpOBZ = (LPOLEUIBUSY)lParam; + + // Copy it to our instance of the structure (in lpBZ) + lpBZ->lpOBZ=lpOBZ; + + //Copy other information from lpOBZ that we might modify. + lpBZ->dwFlags = lpOBZ->dwFlags; + + // Set default information + lpBZ->hWndBlocked = NULL; + + // Insert HWND of our dialog into the address pointed to by + // lphWndDialog. This can be used by the app who called + // OleUIBusy to bring down the dialog with uMsgCloseBusyDialog + if (lpOBZ->lphWndDialog && + !IsBadWritePtr((VOID FAR *)lpOBZ->lphWndDialog, sizeof(HWND))) + { + *lpOBZ->lphWndDialog = hDlg; + } + + // Update text in text box -- + // GetTaskInfo will return two pointers, one to the task name + // (file name) and one to the window name. We need to call + // OleStdFree on these when we're done with them. We also + // get the HWND which is blocked in this call + // + // In the case where this call fails, a default message should already + // be present in the dialog template, so no action is needed + + if (GetTaskInfo(hDlg, lpOBZ->hTask, &lpTaskName, &lpWindowName, &lpBZ->hWndBlocked)) + { + // Build string to present to user, place in IDBZ_MESSAGE1 control + BuildBusyDialogString(hDlg, lpBZ->dwFlags, IDBZ_MESSAGE1, lpTaskName, lpWindowName); + OleStdFree(lpTaskName); + OleStdFree(lpWindowName); + } + + // Update icon with the system "exclamation" icon + hIcon = LoadIcon(NULL, IDI_EXCLAMATION); + SendDlgItemMessage(hDlg, IDBZ_ICON, STM_SETICON, (WPARAM)hIcon, 0L); + + // Disable/Enable controls + if ((lpBZ->dwFlags & BZ_DISABLECANCELBUTTON) || + (lpBZ->dwFlags & BZ_NOTRESPONDINGDIALOG)) // Disable cancel for "not responding" dialog + EnableWindow(GetDlgItem(hDlg, IDCANCEL), FALSE); + + if (lpBZ->dwFlags & BZ_DISABLESWITCHTOBUTTON) + EnableWindow(GetDlgItem(hDlg, IDBZ_SWITCHTO), FALSE); + + if (lpBZ->dwFlags & BZ_DISABLERETRYBUTTON) + EnableWindow(GetDlgItem(hDlg, IDBZ_RETRY), FALSE); + + // Call the hook with lCustData in lParam + UStandardHook((LPVOID)lpBZ, hDlg, WM_INITDIALOG, wParam, lpOBZ->lCustData); + + // Update caption if lpszCaption was specified + if (lpBZ->lpOBZ->lpszCaption && !IsBadReadPtr(lpBZ->lpOBZ->lpszCaption, 1) + && lpBZ->lpOBZ->lpszCaption[0] != '\0') + SetWindowText(hDlg, lpBZ->lpOBZ->lpszCaption); + + return TRUE; + } + + +/* + * BuildBusyDialogString + * + * Purpose: + * Builds the string that will be displayed in the dialog from the + * task name and window name parameters. + * + * Parameters: + * hDlg HWND of the dialog + * dwFlags DWORD containing flags passed into dialog + * iControl Control ID to place the text string + * lpTaskName LPSTR pointing to name of task (e.g. C:\TEST\TEST.EXE) + * lpWindowName LPSTR for name of window + * + * Caveats: + * The caller of this function MUST de-allocate the lpTaskName and + * lpWindowName pointers itself with OleStdFree + * + * Return Value: + * void + */ + +void BuildBusyDialogString(HWND hDlg, DWORD dwFlags, int iControl, LPTSTR lpTaskName, LPTSTR lpWindowName) +{ + LPTSTR pszT, psz1, psz2, psz3; + UINT cch; + LPTSTR pszDot, pszSlash; + UINT uiStringNum; + + /* + * We need scratch memory for loading the stringtable string, + * the task name, and constructing the final string. We therefore + * allocate three buffers as large as the maximum message + * length (512) plus the object type, guaranteeing that we have enough + * in all cases. + */ + cch=512; + + // Use OLE-supplied allocation + if ((pszT = OleStdMalloc((ULONG)(3*cch))) == NULL) + return; + + psz1=pszT; + psz2=psz1+cch; + psz3=psz2+cch; + + // Parse base name out of path name, use psz2 for the task + // name to display + // In Win32, _fstrcpy is mapped to handle UNICODE stuff + _fstrcpy(psz2, lpTaskName); + pszDot = _fstrrchr(psz2, TEXT('.')); + pszSlash = _fstrrchr(psz2, TEXT('\\')); // Find last backslash in path + + if (pszDot != NULL) +#ifdef UNICODE + *pszDot = TEXT('\0'); // Null terminate at the DOT +#else + *pszDot = '\0'; // Null terminate at the DOT +#endif + + if (pszSlash != NULL) + psz2 = pszSlash + 1; // Nuke everything up to this point + +#ifdef LOWERCASE_NAME + // Compile this with /DLOWERCASE_NAME if you want the lower-case + // module name to be displayed in the dialog rather than the + // all-caps name. + { + int i,l; + + // Now, lowercase all letters except first one + l = _fstrlen(psz2); + for(i=0;i 80) +#ifdef UNICODE + lpWindowName[80] = TEXT('\0'); +#else + lpWindowName[80] = '\0'; +#endif + + // Load the format string out of stringtable, choose a different + // string depending on what flags are passed in to the dialog + if (dwFlags & BZ_NOTRESPONDINGDIALOG) + uiStringNum = IDS_BZRESULTTEXTNOTRESPONDING; + else + uiStringNum = IDS_BZRESULTTEXTBUSY; + + if (LoadString(ghInst, uiStringNum, psz1, cch) == 0) + return; + + // Build the string. The format string looks like this: + // "This action cannot be completed because the '%s' application + // (%s) is [busy | not responding]. Choose \"Switch To\" to activate '%s' and + // correct the problem." + + wsprintf(psz3, psz1, (LPSTR)psz2, (LPTSTR)lpWindowName, (LPTSTR)psz2); + SetDlgItemText(hDlg, iControl, (LPTSTR)psz3); + OleStdFree(pszT); + + return; +} + + + +/* + * BusyCleanup + * + * Purpose: + * Performs busy-specific cleanup before termination. + * + * Parameters: + * hDlg HWND of the dialog box so we can access controls. + * + * Return Value: + * None + */ +void BusyCleanup(HWND hDlg) +{ + return; +} + + + +/* + * GetTaskInfo() + * + * Purpose: Gets information about the specified task and places the + * module name, window name and top-level HWND for the task in the specified + * pointers + * + * NOTE: The two string pointers allocated in this routine are + * the responsibility of the CALLER to de-allocate. + * + * Parameters: + * hWnd HWND who called this function + * htask HTASK which we want to find out more info about + * lplpszTaskName Location that the module name is returned + * lplpszWindowName Location where the window name is returned + * + */ + +BOOL GetTaskInfo(HWND hWnd, HTASK htask, LPTSTR FAR* lplpszTaskName, LPTSTR FAR*lplpszWindowName, HWND FAR*lphWnd) +{ + BOOL fRet = FALSE; +#if !defined( WIN32 ) + TASKENTRY te; +#endif + HWND hwndNext; + LPTSTR lpszTN = NULL; + LPTSTR lpszWN = NULL; + HWND hwndFind = NULL; + + // Clear out return values in case of error + *lplpszTaskName = NULL; + *lplpszWindowName = NULL; + +#if !defined( WIN32 ) + te.dwSize = sizeof(TASKENTRY); + if (TaskFindHandle(&te, htask)) +#endif + { + // Now, enumerate top-level windows in system + hwndNext = GetWindow(hWnd, GW_HWNDFIRST); + while (hwndNext) + { + // See if we can find a non-owned top level window whose + // hInstance matches the one we just got passed. If we find one, + // we can be fairly certain that this is the top-level window for + // the task which is blocked. + // + // REVIEW: Will this filter hold true for InProcServer DLL-created + // windows? + // + if ((hwndNext != hWnd) && +#if !defined( WIN32 ) + (GetWindowWord(hwndNext, GWW_HINSTANCE) == (WORD)te.hInst) && +#else + ((HTASK) GetWindowThreadProcessId(hwndNext,NULL) == htask) && +#endif + (IsWindowVisible(hwndNext)) && + !GetWindow(hwndNext, GW_OWNER)) + { + // We found our window! Alloc space for new strings + if ((lpszTN = OleStdMalloc(OLEUI_CCHPATHMAX_SIZE)) == NULL) + return TRUE; // continue task window enumeration + + if ((lpszWN = OleStdMalloc(OLEUI_CCHPATHMAX_SIZE)) == NULL) + return TRUE; // continue task window enumeration + + // We found the window we were looking for, copy info to + // local vars + GetWindowText(hwndNext, lpszWN, OLEUI_CCHPATHMAX); +#if !defined( WIN32 ) + LSTRCPYN(lpszTN, te.szModule, OLEUI_CCHPATHMAX); +#else + /* WIN32 NOTE: we are not able to get a module name + ** given a thread process id on WIN32. the best we + ** can do is use the window title as the module/app + ** name. + */ + LSTRCPYN(lpszTN, lpszWN, OLEUI_CCHPATHMAX); +#endif + hwndFind = hwndNext; + + fRet = TRUE; + goto OKDone; + } + + hwndNext = GetWindow(hwndNext, GW_HWNDNEXT); + } + } + +OKDone: + + // OK, everything was successful. Set string pointers to point to + // our data. + + *lplpszTaskName = lpszTN; + *lplpszWindowName = lpszWN; + *lphWnd = hwndFind; + + return fRet; +} + + +/* + * StartTaskManager() + * + * Purpose: Starts Task Manager. Used to bring up task manager to + * assist in switching to a given blocked task. + * + */ + +StartTaskManager() +{ + WinExec("taskman.exe", SW_SHOW); + return TRUE; +} + + + +/* + * MakeWindowActive() + * + * Purpose: Makes specified window the active window. + * + */ + +void MakeWindowActive(HWND hWndSwitchTo) +{ + // Move the new window to the top of the Z-order + SetWindowPos(hWndSwitchTo, HWND_TOP, 0, 0, 0, 0, + SWP_NOSIZE | SWP_NOMOVE); + + // If it's iconic, we need to restore it. + if (IsIconic(hWndSwitchTo)) + ShowWindow(hWndSwitchTo, SW_RESTORE); +} diff --git a/private/oleutest/letest/ole2ui/busy.dlg b/private/oleutest/letest/ole2ui/busy.dlg new file mode 100644 index 000000000..c2151956c --- /dev/null +++ b/private/oleutest/letest/ole2ui/busy.dlg @@ -0,0 +1,13 @@ +IDD_BUSY DIALOG DISCARDABLE 0, 0, 214, 76 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Server Busy" +FONT 8, "MS Shell Dlg" +BEGIN + DEFPUSHBUTTON "&Switch To...", IDBZ_SWITCHTO, 33, 55, 53, 15 + PUSHBUTTON "&Cancel", IDCANCEL, 152, 55, 53, 15 + PUSHBUTTON "&Retry", IDBZ_RETRY, 92, 55, 53, 15 + LTEXT "This action cannot be completed because the other application is busy. Choose 'Switch To' to activate the busy application and correct the problem.", IDBZ_MESSAGE1, 35, 11, 167, 35 + ICON "", IDBZ_ICON, 8, 18, 18, 20 +END + + diff --git a/private/oleutest/letest/ole2ui/busy.h b/private/oleutest/letest/ole2ui/busy.h new file mode 100644 index 000000000..3656aecf6 --- /dev/null +++ b/private/oleutest/letest/ole2ui/busy.h @@ -0,0 +1,45 @@ +/* + * BUSY.H + * + * Internal definitions, structures, and function prototypes for the + * OLE 2.0 UI Busy dialog. + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + +#ifndef _BUSY_H_ +#define _BUSY_H_ + +//Internally used structure +typedef struct tagBUSY + { + //Keep this item first as the Standard* functions depend on it here. + LPOLEUIBUSY lpOBZ; //Original structure passed. + + /* + * What we store extra in this structure besides the original caller's + * pointer are those fields that we need to modify during the life of + * the dialog or that we don't want to change in the original structure + * until the user presses OK. + */ + + DWORD dwFlags; // Flags passed in + HWND hWndBlocked; // HWND of app which is blocking + } BUSY, *PBUSY, FAR *LPBUSY; + +// Internal function prototypes +BOOL GetTaskInfo(HWND hWnd, HTASK htask, LPTSTR FAR* lplpszTaskName, LPTSTR FAR*lplpszWindowName, HWND FAR*lphWnd); +void BuildBusyDialogString(HWND, DWORD, int, LPTSTR, LPTSTR); +BOOL CALLBACK EXPORT BusyDialogProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam); +void BusyCleanup(HWND hDlg); +BOOL FBusyInit(HWND hDlg, WPARAM wParam, LPARAM lParam); +BOOL InitEnumeration(void); +void UnInitEnumeration(void); + StartTaskManager(void); +void MakeWindowActive(HWND hWndSwitchTo); + +#endif //_BUSY_H_ + + + + diff --git a/private/oleutest/letest/ole2ui/common.c b/private/oleutest/letest/ole2ui/common.c new file mode 100644 index 000000000..40f450c72 --- /dev/null +++ b/private/oleutest/letest/ole2ui/common.c @@ -0,0 +1,423 @@ +/* + * COMMON.C + * + * Standardized (and centralized) pieces of each OLE2UI dialog function: + * UStandardValidation Validates standard fields in each dialog structure + * UStandardInvocation Invokes a dialog through DialogBoxIndirectParam + * LpvStandardInit Common WM_INITDIALOG processing + * LpvStandardEntry Common code to execute on dialog proc entry. + * FStandardHook Centralized hook calling function. + * StandardCleanup Common exit/cleanup code. + * OleUIShowDlgItem Show-Enable/Hide-Disable dialog item + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + +#define STRICT 1 +#include "ole2ui.h" +#include "common.h" +#include "utility.h" +#include + + +/* + * UStandardValidation + * + * Purpose: + * Performs validation on the standard pieces of any dialog structure, + * that is, the fields defined in the OLEUISTANDARD structure. + * + * Parameters: + * lpUI const LPOLEUISTANDARD pointing to the shared data of + * all structs. + * cbExpect const UINT structure size desired by the caller. + * phDlgMem const HGLOBAL FAR * in which to store a loaded customized + * template, if one exists. + * + * Return Value: + * UINT OLEUI_SUCCESS if all validation succeeded. Otherwise + * it will be one of the standard error codes. + */ + +UINT WINAPI UStandardValidation(const LPOLEUISTANDARD lpUI, const UINT cbExpect + , const HGLOBAL FAR *phMemDlg) + { + HRSRC hRes=NULL; + HGLOBAL hMem=NULL; + + + /* + * 1. Validate non-NULL pointer parameter. Note: We don't validate + * phDlg since it's not passed from an external source. + */ + if (NULL==lpUI) + return OLEUI_ERR_STRUCTURENULL; + + //2. Validate that the structure is readable and writable. + if (IsBadReadPtr(lpUI, cbExpect) || IsBadWritePtr(lpUI, cbExpect)) + return OLEUI_ERR_STRUCTUREINVALID; + + //3. Validate the structure size + if (cbExpect!=lpUI->cbStruct) + return OLEUI_ERR_CBSTRUCTINCORRECT; + + //4. Validate owner-window handle. NULL is considered valid. + if (NULL!=lpUI->hWndOwner && !IsWindow(lpUI->hWndOwner)) + return OLEUI_ERR_HWNDOWNERINVALID; + + //5. Validate the dialog caption. NULL is considered valid. + if (NULL!=lpUI->lpszCaption && IsBadReadPtr(lpUI->lpszCaption, 1)) + return OLEUI_ERR_LPSZCAPTIONINVALID; + + //6. Validate the hook pointer. NULL is considered valid. + if ((LPFNOLEUIHOOK)NULL!=lpUI->lpfnHook + && IsBadCodePtr((FARPROC)lpUI->lpfnHook)) + return OLEUI_ERR_LPFNHOOKINVALID; + + /* + * 7. If hInstance is non-NULL, we have to also check lpszTemplate. + * Otherwise, lpszTemplate is not used and requires no validation. + * lpszTemplate cannot be NULL if used. + */ + if (NULL!=lpUI->hInstance) + { + //Best we can try is one character + if (NULL==lpUI->lpszTemplate || IsBadReadPtr(lpUI->lpszTemplate, 1)) + return OLEUI_ERR_LPSZTEMPLATEINVALID; + + hRes=FindResource(lpUI->hInstance, lpUI->lpszTemplate, RT_DIALOG); + + //This is the only thing that catches invalid non-NULL hInstance + if (NULL==hRes) + return OLEUI_ERR_FINDTEMPLATEFAILURE; + + hMem=LoadResource(lpUI->hInstance, hRes); + + if (NULL==hMem) + return OLEUI_ERR_LOADTEMPLATEFAILURE; + } + + + //8. If hResource is non-NULL, be sure we can lock it. + if (NULL!=lpUI->hResource) + { + if ((LPSTR)NULL==GlobalLock(lpUI->hResource)) + return OLEUI_ERR_HRESOURCEINVALID; + + GlobalUnlock(lpUI->hResource); + } + + /* + * Here we have hMem==NULL if we should use the standard template + * or the one in lpUI->hResource. If hMem is non-NULL, then we + * loaded one from the calling application's resources which the + * caller of this function has to free if it sees any other error. + */ + *(HGLOBAL FAR *)phMemDlg=hMem; + return OLEUI_SUCCESS; + } + + + + + +/* + * UStandardInvocation + * + * Purpose: + * Provides standard template loading and calling on DialogBoxIndirectParam + * for all the OLE UI dialogs. + * + * Parameters: + * lpDlgProc DLGPROC of the dialog function. + * lpUI LPOLEUISTANDARD containing the dialog structure. + * hMemDlg HGLOBAL containing the dialog template. If this + * is NULL and lpUI->hResource is NULL, then we load + * the standard template given the name in lpszStdTemplate + * lpszStdTemplate LPCSTR standard template to load if hMemDlg is NULL + * and lpUI->hResource is NULL. + * + * Return Value: + * UINT OLEUI_SUCCESS if all is well, otherwise and error + * code. + */ + +UINT WINAPI UStandardInvocation +#ifdef WIN32 +(DLGPROC lpDlgProc, LPOLEUISTANDARD lpUI, HGLOBAL hMemDlg, LPTSTR lpszStdTemplate) +#else +(DLGPROC lpDlgProc, LPOLEUISTANDARD lpUI, HGLOBAL hMemDlg, LPCTSTR lpszStdTemplate) +#endif + { + HGLOBAL hTemplate=hMemDlg; + HRSRC hRes; + int iRet; + + //Make sure we have a template, then lock it down + if (NULL==hTemplate) + hTemplate=lpUI->hResource; + + if (NULL==hTemplate) + { + hRes=FindResource(ghInst, (LPCTSTR) lpszStdTemplate, RT_DIALOG); + + if (NULL==hRes) + { + return OLEUI_ERR_FINDTEMPLATEFAILURE; + } + + hTemplate=LoadResource(ghInst, hRes); + + if (NULL==hTemplate) + { + return OLEUI_ERR_LOADTEMPLATEFAILURE; + } + } + + /* + * hTemplate has the template to use, so now we can invoke the dialog. + * Since we have exported all of our dialog procedures using the + * _export keyword, we do not need to call MakeProcInstance, + * we can ue the dialog procedure address directly. + */ + + iRet=DialogBoxIndirectParam(ghInst, hTemplate, lpUI->hWndOwner + , lpDlgProc, (LPARAM)lpUI); + + /* + * Cleanup the template if we explicitly loaded it. Caller is + * responsible for already loaded template resources. + */ + if (hTemplate!=lpUI->hResource) + FreeResource(hTemplate); + + if (-1==iRet) + return OLEUI_ERR_DIALOGFAILURE; + + //Return the code from EndDialog, generally OLEUI_OK or OLEUI_CANCEL + return (UINT)iRet; + } + + + + + + +/* + * LpvStandardInit + * + * Purpose: + * Default actions for WM_INITDIALOG handling in the dialog, allocating + * a dialog-specific structure, setting that memory as a dialog property, + * and creating a small font if necessary setting that font as a property. + * + * Parameters: + * hDlg HWND of the dialog + * cbStruct UINT size of dialog-specific structure to allocate. + * fCreateFont BOOL indicating if we need to create a small Helv + * font for this dialog. + * phFont HFONT FAR * in which to place a created font. Can be + * NULL if fCreateFont is FALSE. + * + * Return Value: + * LPVOID Pointer to global memory allocated for the dialog. + * The memory will have been set as a dialog property + * using the STRUCTUREPROP label. + */ + +LPVOID WINAPI LpvStandardInit(HWND hDlg, UINT cbStruct, BOOL fCreateFont, HFONT FAR * phFont) + { + LPVOID lpv; + HFONT hFont; + LOGFONT lf; + HGLOBAL gh; + + //Must have at least sizeof(OLEUISTANDARD) bytes in cbStruct + if (sizeof(OLEUISTANDARD) > cbStruct || (fCreateFont && NULL==phFont)) + { + PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_GLOBALMEMALLOC, 0L); + return NULL; + } + + gh=GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT, cbStruct); + + if (NULL==gh) + { + PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_GLOBALMEMALLOC, 0L); + return NULL; + } + lpv = GlobalLock(gh); + SetProp(hDlg, STRUCTUREPROP, gh); + + if (fCreateFont) { + //Create the non-bold font for result and file texts. We call + hFont=(HFONT)SendMessage(hDlg, WM_GETFONT, 0, 0L); + GetObject(hFont, sizeof(LOGFONT), &lf); + lf.lfWeight=FW_NORMAL; + + //Attempt to create the font. If this fails, then we return no font. + *phFont=CreateFontIndirect(&lf); + + //If we couldn't create the font, we'll do with the default. + if (NULL!=*phFont) + SetProp(hDlg, FONTPROP, (HANDLE)*phFont); + } + + return lpv; + } + + + + + +/* + * LpvStandardEntry + * + * Purpose: + * Retrieves the dialog's structure property and calls the hook + * as necessary. This should be called on entry into all dialog + * procedures. + * + * Parameters: + * hDlg HWND of the dialog + * iMsg UINT message to the dialog + * wParam, lParam WPARAM, LPARAM message parameters + * puHookResult UINT FAR * in which this function stores the return value + * from the hook if it is called. If no hook is available, + * this will be FALSE. + * + * Return Value: + * LPVOID Pointer to the dialog's extra structure held in the + * STRUCTUREPROP property. + */ + +LPVOID WINAPI LpvStandardEntry(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam + , UINT FAR * puHookResult) + { + LPVOID lpv = NULL; + HGLOBAL gh; + + // This will fail under WM_INITDIALOG, where we allocate using StandardInit + gh = GetProp(hDlg, STRUCTUREPROP); + + if (NULL!=puHookResult && NULL!=gh) + { + *puHookResult=0; + + // gh was locked previously, lock and unlock to get lpv + lpv = GlobalLock(gh); + GlobalUnlock(gh); + + //Call the hook for all messages except WM_INITDIALOG + if (NULL!=lpv && WM_INITDIALOG!=iMsg) + *puHookResult=UStandardHook(lpv, hDlg, iMsg, wParam, lParam); + } + + return lpv; + } + + + + +/* + * UStandardHook + * + * Purpose: + * Provides a generic hook calling function assuming that all private + * dialog structures have a far pointer to their assocated public + * structure as the first field, and that the first part of the public + * structure matches an OLEUISTANDARD. + * + * Parameters: + * pv PVOID to the dialog structure. + * hDlg HWND to send with the call to the hook. + * iMsg UINT message to send to the hook. + * wParam, lParam WPARAM, LPARAM message parameters + * + * Return Value: + * UINT Return value from the hook, zero to indicate that + * default action should occur, nonzero to specify + * that the hook did process the message. In some + * circumstances it will be important for the hook to + * return a non-trivial non-zero value here, such as + * a brush from WM_CTLCOLOR, in which case the caller + * should return that value from the dialog procedure. + */ + +UINT WINAPI UStandardHook(LPVOID lpv, HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam) + { + LPOLEUISTANDARD lpUI; + UINT uRet=0; + + lpUI=*((LPOLEUISTANDARD FAR *)lpv); + + if (NULL!=lpUI && NULL!=lpUI->lpfnHook) + { + /* + * In order for the hook to have the proper DS, they should be + * compiling with -GA -GEs so and usin __export to get everything + * set up properly. + */ + uRet=(*lpUI->lpfnHook)(hDlg, iMsg, wParam, lParam); + } + + return uRet; + } + + + + + +/* + * StandardCleanup + * + * Purpose: + * Removes properties and reverses any other standard initiazation + * done through StandardSetup. + * + * Parameters: + * lpv LPVOID containing the private dialog structure. + * hDlg HWND of the dialog closing. + * + * Return Value: + * None + */ + +void WINAPI StandardCleanup(LPVOID lpv, HWND hDlg) + { + HFONT hFont; + HGLOBAL gh; + + hFont=(HFONT)GetProp(hDlg, FONTPROP); + + if (NULL!=hFont) + DeleteObject(hFont); + + RemoveProp(hDlg, FONTPROP); + + gh = RemoveProp(hDlg, STRUCTUREPROP); + if (gh) + { + GlobalUnlock(gh); + GlobalFree(gh); + } + return; + } + + +/* StandardShowDlgItem +** ------------------- +** Show & Enable or Hide & Disable a dialog item as appropriate. +** it is NOT sufficient to simply hide the item; it must be disabled +** too or the keyboard accelerator still functions. +*/ +void WINAPI StandardShowDlgItem(HWND hDlg, int idControl, int nCmdShow) +{ + if (SW_HIDE == nCmdShow) { + ShowWindow(GetDlgItem(hDlg, idControl), SW_HIDE); + EnableWindow(GetDlgItem(hDlg, idControl), FALSE); + } else { + ShowWindow(GetDlgItem(hDlg, idControl), SW_SHOWNORMAL); + EnableWindow(GetDlgItem(hDlg, idControl), TRUE); + } +} diff --git a/private/oleutest/letest/ole2ui/common.h b/private/oleutest/letest/ole2ui/common.h new file mode 100644 index 000000000..00466661f --- /dev/null +++ b/private/oleutest/letest/ole2ui/common.h @@ -0,0 +1,166 @@ +/* + * COMMON.H + * + * Structures and definitions applicable to all OLE 2.0 UI dialogs. + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + + +#ifndef _COMMON_H_ +#define _COMMON_H_ + + +//Macros to handle control message packing between Win16 and Win32 +#ifdef WIN32 + +#ifndef COMMANDPARAMS +#define COMMANDPARAMS(wID, wCode, hWndMsg) \ + WORD wID = LOWORD(wParam); \ + WORD wCode = HIWORD(wParam); \ + HWND hWndMsg = (HWND)(UINT)lParam; +#endif //COMMANDPARAMS + +#ifndef SendCommand +#define SendCommand(hWnd, wID, wCode, hControl) \ + SendMessage(hWnd, WM_COMMAND, MAKELONG(wID, wCode) \ + , (LPARAM)hControl) +#endif //SendCommand + +#else //Start !WIN32 + +#ifndef COMMANDPARAMS +#define COMMANDPARAMS(wID, wCode, hWndMsg) \ + WORD wID = LOWORD(wParam); \ + WORD wCode = HIWORD(lParam); \ + HWND hWndMsg = (HWND)(UINT)lParam; +#endif //COMMANDPARAMS + +#ifndef SendCommand +#define SendCommand(hWnd, wID, wCode, hControl) \ + SendMessage(hWnd, WM_COMMAND, wID \ + , MAKELONG(hControl, wCode)) +#endif //SendCommand + +#endif //!WIN32 + + + +//Property labels used to store dialog structures and fonts +#define STRUCTUREPROP TEXT("Structure") +#define FONTPROP TEXT("Font") + + +/* + * Standard structure for all dialogs. This commonality lets us make + * a single piece of code that will validate this entire structure and + * perform any necessary initialization. + */ + +typedef struct tagOLEUISTANDARD + { + //These IN fields are standard across all OLEUI dialog functions. + DWORD cbStruct; //Structure Size + DWORD dwFlags; //IN-OUT: Flags + HWND hWndOwner; //Owning window + LPCTSTR lpszCaption; //Dialog caption bar contents + LPFNOLEUIHOOK lpfnHook; //Hook callback + LPARAM lCustData; //Custom data to pass to hook + HINSTANCE hInstance; //Instance for customized template name + LPCTSTR lpszTemplate; //Customized template name + HRSRC hResource; //Customized template handle + } OLEUISTANDARD, *POLEUISTANDARD, FAR *LPOLEUISTANDARD; + + + +//Function prototypes +//COMMON.C +UINT WINAPI UStandardValidation(const LPOLEUISTANDARD, const UINT, const HGLOBAL FAR *); + +#ifdef WIN32 +UINT WINAPI UStandardInvocation(DLGPROC, LPOLEUISTANDARD, HGLOBAL, LPTSTR); +#else +UINT WINAPI UStandardInvocation(DLGPROC, LPOLEUISTANDARD, HGLOBAL, LPCTSTR); +#endif + +LPVOID WINAPI LpvStandardInit(HWND, UINT, BOOL, HFONT FAR *); +LPVOID WINAPI LpvStandardEntry(HWND, UINT, WPARAM, LPARAM, UINT FAR *); +UINT WINAPI UStandardHook(LPVOID, HWND, UINT, WPARAM, LPARAM); +void WINAPI StandardCleanup(LPVOID, HWND); +void WINAPI StandardShowDlgItem(HWND hDlg, int idControl, int nCmdShow); + + +//DRAWICON.C + +//Structure for label and source extraction from a metafile +typedef struct tagLABELEXTRACT + { + LPTSTR lpsz; + UINT Index; // index in lpsz (so we can retrieve 2+ lines) + DWORD PrevIndex; // index of last line (so we can mimic word wrap) + + union + { + UINT cch; //Length of label for label extraction + UINT iIcon; //Index of icon in source extraction. + } u; + + //For internal use in enum procs + BOOL fFoundIconOnly; + BOOL fFoundSource; + BOOL fFoundIndex; + } LABELEXTRACT, FAR * LPLABELEXTRACT; + + +//Structure for extracting icons from a metafile (CreateIcon parameters) +typedef struct tagICONEXTRACT + { + HICON hIcon; //Icon created in the enumeration proc. + + /* + * Since we want to handle multitasking well we have the caller + * of the enumeration proc instantiate these variables instead of + * using statics in the enum proc (which would be bad). + */ + BOOL fAND; + HGLOBAL hMemAND; //Enumeration proc allocates and copies + } ICONEXTRACT, FAR * LPICONEXTRACT; + + +//Structure to use to pass info to EnumMetafileDraw +typedef struct tagDRAWINFO + { + RECT Rect; + BOOL fIconOnly; + } DRAWINFO, FAR * LPDRAWINFO; + + +int CALLBACK EXPORT EnumMetafileIconDraw(HDC, HANDLETABLE FAR *, METARECORD FAR *, int, LPARAM); +int CALLBACK EXPORT EnumMetafileExtractLabel(HDC, HANDLETABLE FAR *, METARECORD FAR *, int, LPLABELEXTRACT); +int CALLBACK EXPORT EnumMetafileExtractIcon(HDC, HANDLETABLE FAR *, METARECORD FAR *, int, LPICONEXTRACT); +int CALLBACK EXPORT EnumMetafileExtractIconSource(HDC, HANDLETABLE FAR *, METARECORD FAR *, int, LPLABELEXTRACT); + + +//Shared globals: our instance, registered messages used from all dialogs and clipboard +// formats used by the PasteSpecial dialog +extern HINSTANCE ghInst; + +extern UINT uMsgHelp; +extern UINT uMsgEndDialog; +extern UINT uMsgBrowse; +extern UINT uMsgChangeIcon; +extern UINT uMsgFileOKString; +extern UINT uMsgCloseBusyDlg; + +extern UINT cfObjectDescriptor; +extern UINT cfLinkSrcDescriptor; +extern UINT cfEmbedSource; +extern UINT cfEmbeddedObject; +extern UINT cfLinkSource; +extern UINT cfOwnerLink; +extern UINT cfFileName; + +//Standard control identifiers +#define ID_NULL 98 + +#endif //_COMMON_H_ diff --git a/private/oleutest/letest/ole2ui/convert.c b/private/oleutest/letest/ole2ui/convert.c new file mode 100644 index 000000000..e5ca54131 --- /dev/null +++ b/private/oleutest/letest/ole2ui/convert.c @@ -0,0 +1,1802 @@ +/* + * CONVERT.C + * + * Implements the OleUIConvert function which invokes the complete + * Convert dialog. + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + +#define STRICT 1 +#include "ole2ui.h" +#include +#include "common.h" +#include "utility.h" +#include "geticon.h" +#include "regdb.h" +#include "convert.h" + +#define CF_CLIPBOARDMIN 0xc000 +#define CF_CLIPBOARDMAX 0xffff + +#define AUXUSERTYPE_SHORTNAME USERCLASSTYPE_SHORT // short name + +static TCHAR szOLE2DLL[] = TEXT("ole2.dll"); // name of OLE 2.0 library + +static TCHAR szVanillaDocIcon[] = TEXT("DefIcon"); + +/* + * OleUIConvert + * + * Purpose: + * Invokes the standard OLE Change Type dialog box allowing the user + * to change the type of the single specified object, or change the + * type of all OLE objects of a specified type. + * + * Parameters: + * lpCV LPOLEUICONVERT pointing to the in-out structure + * for this dialog. + * + * Return Value: + * UINT One of the following codes, indicating success or error: + * OLEUI_SUCCESS Success + * OLEUI_ERR_STRUCTSIZE The dwStructSize value is wrong + */ + +STDAPI_(UINT) OleUIConvert(LPOLEUICONVERT lpCV) + { + UINT uRet; + HGLOBAL hMemDlg=NULL; + + uRet=UStandardValidation((LPOLEUISTANDARD)lpCV, sizeof(OLEUICONVERT) + , &hMemDlg); + + if (OLEUI_SUCCESS!=uRet) + return uRet; + + // Validate structure members passed in. +#if defined( OBSOLETE ) + if (!IsValidClassID(lpCV->clsid)) + uRet = OLEUI_CTERR_CLASSIDINVALID; +#endif + + if ( (lpCV->dwFlags & CF_SETCONVERTDEFAULT) + && (!IsValidClassID(lpCV->clsidConvertDefault)) ) + uRet = OLEUI_CTERR_CLASSIDINVALID; + + if ( (lpCV->dwFlags & CF_SETACTIVATEDEFAULT) + && (!IsValidClassID(lpCV->clsidActivateDefault)) ) + uRet = OLEUI_CTERR_CLASSIDINVALID; + + if ( (lpCV->dvAspect != DVASPECT_ICON) + && (lpCV->dvAspect != DVASPECT_CONTENT) ) + uRet = OLEUI_CTERR_DVASPECTINVALID; + + if ( (lpCV->wFormat >= CF_CLIPBOARDMIN) + && (lpCV->wFormat <= CF_CLIPBOARDMAX) ) + { + TCHAR szTemp[8]; + + if (0 == GetClipboardFormatName(lpCV->wFormat, (LPTSTR)szTemp, 8)) + uRet = OLEUI_CTERR_CBFORMATINVALID; + } + + + if ( (NULL != lpCV->lpszUserType) + && (IsBadReadPtr(lpCV->lpszUserType, 1)) ) + uRet = OLEUI_CTERR_STRINGINVALID; + + if ( (NULL != lpCV->lpszDefLabel) + && (IsBadReadPtr(lpCV->lpszDefLabel, 1)) ) + uRet = OLEUI_CTERR_STRINGINVALID; + + if (0!=lpCV->cClsidExclude) + { + if (NULL!=lpCV->lpClsidExclude && IsBadReadPtr(lpCV->lpClsidExclude + , lpCV->cClsidExclude*sizeof(CLSID))) + uRet=OLEUI_IOERR_LPCLSIDEXCLUDEINVALID; + } + + + if (OLEUI_ERR_STANDARDMIN <= uRet) + { + if (NULL!=hMemDlg) + FreeResource(hMemDlg); + + return uRet; + } + + //Now that we've validated everything, we can invoke the dialog. + uRet=UStandardInvocation(ConvertDialogProc, (LPOLEUISTANDARD)lpCV, + hMemDlg, MAKEINTRESOURCE(IDD_CONVERT)); + + return uRet; + } + + + + + +/* + * ConvertDialogProc + * + * Purpose: + * Implements the OLE Convert dialog as invoked through the + * OleUIConvert function. + * + * Parameters: + * Standard + * + * Return Value: + * Standard + * + */ + +BOOL CALLBACK EXPORT ConvertDialogProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam) + { + LPCONVERT lpCV; + UINT uRet = 0; + OLEUICHANGEICON ci; + + //Declare Win16/Win32 compatible WM_COMMAND parameters. + COMMANDPARAMS(wID, wCode, hWndMsg); + + //This will fail under WM_INITDIALOG, where we allocate it. + lpCV=(LPCONVERT)LpvStandardEntry(hDlg, iMsg, wParam, lParam, (UINT FAR *)&uRet); + + //If the hook processed the message, we're done. + if (0!=uRet) + return (BOOL)uRet; + + //Process the temination message + if (iMsg==uMsgEndDialog) + { + ConvertCleanup(hDlg, lpCV); + StandardCleanup(lpCV, hDlg); + EndDialog(hDlg, wParam); + return TRUE; + } + + // Process help message from Change Icon + if (iMsg == uMsgHelp) + { + + PostMessage(lpCV->lpOCV->hWndOwner, uMsgHelp, wParam, lParam); + return FALSE; + + } + + switch (iMsg) + { + case WM_INITDIALOG: + FConvertInit(hDlg, wParam, lParam); + return TRUE; + + case WM_COMMAND: + switch (wID) + { + case IDCV_ACTIVATELIST: + case IDCV_CONVERTLIST: + switch (wCode) + { + case LBN_SELCHANGE: + + // Change "Results" window to reflect current selection + SetConvertResults(hDlg, lpCV); + + // Update the icon we display, if we are indeed + // displaying an icon. + if ( (lpCV->dwFlags & CF_SELECTCONVERTTO) + && (lpCV->dvAspect == DVASPECT_ICON) + && (!lpCV->fCustomIcon) ) + UpdateCVClassIcon(hDlg, lpCV, hWndMsg); + + break; + + case LBN_DBLCLK: + //Same as pressing OK. + SendCommand(hDlg, IDOK, BN_CLICKED, hWndMsg); + break; + } + break; + + case IDCV_CONVERTTO: + case IDCV_ACTIVATEAS: + { + HWND hList, hListInvisible; + LRESULT lRetVal; + BOOL fState; + + hList = lpCV->hListVisible; + hListInvisible = lpCV->hListInvisible; + + + if (IDCV_CONVERTTO == wParam) + { + + // User just click on the button again - it was + // already selected. + if (lpCV->dwFlags & CF_SELECTCONVERTTO) + break; + + + // Turn painting updates off. + SendMessage(hDlg, WM_SETREDRAW, FALSE, 0L); + + + // If we're working with a linked object, don't + // add the activate list - just the object's + // class should appear in the listbox. + + SwapWindows(hDlg, + hList, + hListInvisible); + + lpCV->hListVisible = hListInvisible; + lpCV->hListInvisible = hList; + + EnableWindow(lpCV->hListInvisible, FALSE); + EnableWindow(lpCV->hListVisible, TRUE); + + // Update our flags. + lpCV->dwFlags &= ~CF_SELECTACTIVATEAS; + lpCV->dwFlags |= CF_SELECTCONVERTTO; + + } + else + { + if (lpCV->dwFlags & CF_SELECTACTIVATEAS) + break; + + // Turn painting updates off. + SendMessage(hDlg, WM_SETREDRAW, FALSE, 0L); + + SwapWindows(hDlg, + hList, + hListInvisible); + + lpCV->hListVisible = hListInvisible; + lpCV->hListInvisible = hList; + + EnableWindow(lpCV->hListInvisible, FALSE); + EnableWindow(lpCV->hListVisible, TRUE); + + + // Update our flags. + lpCV->dwFlags |= CF_SELECTACTIVATEAS; + lpCV->dwFlags &= ~CF_SELECTCONVERTTO; + } + + + if (lpCV->dwFlags & CF_SELECTCONVERTTO) + lRetVal = SendMessage(lpCV->hListVisible, LB_SELECTSTRING, (WPARAM)-1, (LPARAM)lpCV->lpszConvertDefault); + else + lRetVal = SendMessage(lpCV->hListVisible, LB_SELECTSTRING, (WPARAM)-1, (LPARAM)lpCV->lpszActivateDefault); + + if (LB_ERR == lRetVal) + { + TCHAR szCurrentObject[40]; + + GetDlgItemText(hDlg, IDCV_OBJECTTYPE, (LPTSTR)szCurrentObject, 40); + SendMessage(lpCV->hListVisible, LB_SELECTSTRING, (WPARAM)-1, (LPARAM)(LPTSTR)szCurrentObject); + } + + // Turn updates back on. + SendMessage(hDlg, WM_SETREDRAW, TRUE, 0L); + + InvalidateRect(lpCV->hListVisible, NULL, TRUE); + UpdateWindow(lpCV->hListVisible); + + if ((lpCV->dvAspect & DVASPECT_ICON) && (lpCV->dwFlags & CF_SELECTCONVERTTO)) + UpdateCVClassIcon(hDlg, lpCV, lpCV->hListVisible); + + // Hide the icon stuff when Activate is selected...show + // it again when Convert is selected. + + fState = ((lpCV->dwFlags & CF_SELECTACTIVATEAS) || + (lpCV->dwFlags & CF_DISABLEDISPLAYASICON)) ? + SW_HIDE : SW_SHOW; + + StandardShowDlgItem(hDlg, IDCV_DISPLAYASICON, fState); + + // Only display the icon if convert is selected AND + // display as icon is checked. + if ((SW_SHOW==fState) && (DVASPECT_ICON!=lpCV->dvAspect)) + fState = SW_HIDE; + + StandardShowDlgItem(hDlg, IDCV_CHANGEICON, fState); + StandardShowDlgItem(hDlg, IDCV_ICON, fState); + StandardShowDlgItem(hDlg, IDCV_ICONLABEL1, fState); + StandardShowDlgItem(hDlg, IDCV_ICONLABEL2, fState); + + SetConvertResults(hDlg, lpCV); + + } + break; + + + case IDOK: + { + + LRESULT iCurSel; + LPTSTR lpszCLSID; + TCHAR szBuffer[256]; + + // Set OUT parameters + + // + // Set output flags to current ones + // + lpCV->lpOCV->dwFlags = lpCV->dwFlags; + + + // Update the dvAspect and fObjectsIconChanged members + // as appropriate. + // + if (lpCV->dwFlags & CF_SELECTACTIVATEAS) + { + // DON'T update aspect if activate as was selected. + lpCV->lpOCV->fObjectsIconChanged = FALSE; + } + else + lpCV->lpOCV->dvAspect = lpCV->dvAspect; + + + // + // Get the new clsid + // + iCurSel = SendMessage(lpCV->hListVisible, LB_GETCURSEL, 0, 0); + SendMessage(lpCV->hListVisible, LB_GETTEXT, iCurSel, (LPARAM)szBuffer); + + lpszCLSID = PointerToNthField((LPTSTR)szBuffer, 2, TEXT('\t')); + + CLSIDFromStringA(lpszCLSID, (&(lpCV->lpOCV->clsidNew))); + + // Free the hMetaPict we got in. + OleUIMetafilePictIconFree(lpCV->lpOCV->hMetaPict); + + // + // Get the hMetaPict (if display as icon is checked) + // + if (DVASPECT_ICON == lpCV->dvAspect) + { + HICON hIcon; + TCHAR szLabel[OLEUI_CCHLABELMAX]; + INT Index; + + + // Create the hMetaPict here from icon, label, + // index, and path + + hIcon = (HICON)SendDlgItemMessage(hDlg, IDCV_ICON, STM_GETICON, 0, 0L); + + // the combined length of the 2 label lines won't ever be more than + // OLEUI_CCHLABELMAX. + Index = (INT)SendDlgItemMessage(hDlg, IDCV_ICONLABEL1, + WM_GETTEXT, OLEUI_CCHLABELMAX, (LPARAM)szLabel); + + if (Index < OLEUI_CCHLABELMAX) + { + LPTSTR lpszSecondLine = szLabel + Index; + + + SendDlgItemMessage(hDlg, IDCV_ICONLABEL2, WM_GETTEXT, + OLEUI_CCHLABELMAX-Index, + (LPARAM)lpszSecondLine); + } + +#ifdef OLE201 + lpCV->lpOCV->hMetaPict = + OleUIMetafilePictFromIconAndLabel(hIcon, + (LPTSTR)szLabel, + lpCV->lpszIconSource, + lpCV->IconIndex); +#endif + + } + else + lpCV->lpOCV->hMetaPict = (HGLOBAL)NULL; + + + // + // End the dialog + // + SendMessage(hDlg, uMsgEndDialog, OLEUI_OK, 0L); + } + break; + + case IDCANCEL: + SendMessage(hDlg, uMsgEndDialog, OLEUI_CANCEL, 0L); + break; + + + case ID_OLEUIHELP: + PostMessage(lpCV->lpOCV->hWndOwner, + uMsgHelp, (WPARAM)hDlg, MAKELPARAM(IDD_CONVERT, 0)); + break; + + case IDCV_DISPLAYASICON: + { + + int i; + BOOL fCheck; + + fCheck=IsDlgButtonChecked(hDlg, wID); + + if (fCheck) + lpCV->dvAspect = DVASPECT_ICON; + else + lpCV->dvAspect = DVASPECT_CONTENT; + + if (fCheck && (!lpCV->fCustomIcon)) + UpdateCVClassIcon(hDlg, lpCV, lpCV->hListVisible); + + //Show or hide the icon depending on the check state. + + i=(fCheck) ? SW_SHOWNORMAL : SW_HIDE; + + StandardShowDlgItem(hDlg, IDCV_CHANGEICON, i); + StandardShowDlgItem(hDlg, IDCV_ICON, i); + StandardShowDlgItem(hDlg, IDCV_ICONLABEL1, i); + StandardShowDlgItem(hDlg, IDCV_ICONLABEL2, i); + + SetConvertResults(hDlg, lpCV); + + } + break; + + case IDCV_CHANGEICON: + { + LPMALLOC pIMalloc; + LPTSTR pszString, pszCLSID; + INT iSel; + HICON hIcon; + TCHAR szLabel[OLEUI_CCHLABELMAX]; + INT Index; + + + //Initialize the structure for the hook. + _fmemset((LPOLEUICHANGEICON)&ci, 0, sizeof(ci)); + + // Create the hMetaPict here from icon, label, + // index, and path + + hIcon = (HICON)SendDlgItemMessage(hDlg, IDCV_ICON, STM_GETICON, 0, 0L); + + // the combined length of the 2 label lines won't ever be more than + // OLEUI_CCHLABELMAX. + + Index = (INT)SendDlgItemMessage(hDlg, IDCV_ICONLABEL1, WM_GETTEXT, + OLEUI_CCHLABELMAX, (LPARAM)szLabel); + + if (Index < OLEUI_CCHLABELMAX) + { + LPTSTR lpszSecondLine; + + lpszSecondLine = szLabel + Index; + + SendDlgItemMessage(hDlg, IDCV_ICONLABEL2, WM_GETTEXT, + OLEUI_CCHLABELMAX-Index, + (LPARAM)lpszSecondLine); + } + +#ifdef OLE201 + ci.hMetaPict = + OleUIMetafilePictFromIconAndLabel(hIcon, + szLabel, + lpCV->lpszIconSource, + lpCV->IconIndex); +#endif + + ci.cbStruct =sizeof(ci); + ci.hWndOwner=hDlg; + ci.dwFlags = CIF_SELECTCURRENT; + + // Only show help if we're showing it for this dialog. + if (lpCV->dwFlags & CF_SHOWHELPBUTTON) + ci.dwFlags |= CIF_SHOWHELP; + + iSel = (INT)SendMessage(lpCV->hListVisible, LB_GETCURSEL, 0, 0L); + + CoGetMalloc(MEMCTX_TASK, &pIMalloc); + + pszString = (LPTSTR)pIMalloc->lpVtbl->Alloc(pIMalloc, + OLEUI_CCHLABELMAX_SIZE + + OLEUI_CCHCLSIDSTRING_SIZE); + + // Get whole string + SendMessage(lpCV->hListVisible, LB_GETTEXT, iSel, (LONG)pszString); + + // Set pointer to CLSID (string) + pszCLSID = PointerToNthField(pszString, 2, TEXT('\t')); + + // Get the clsid to pass to change icon. + CLSIDFromStringA(pszCLSID, &(ci.clsid)); + + pIMalloc->lpVtbl->Free(pIMalloc, (LPVOID)pszString); + pIMalloc->lpVtbl->Release(pIMalloc); + + //Let the hook in to customize Change Icon if desired. + uRet=UStandardHook(lpCV, hDlg, uMsgChangeIcon + , 0, (LONG)(LPTSTR)&ci); + + if (0==uRet) + uRet=(UINT)(OLEUI_OK==OleUIChangeIcon((LPOLEUICHANGEICON)&ci)); + + //Update the display if necessary. + if (0!=uRet) + { + HICON hIcon; + TCHAR szLabel[OLEUI_CCHLABELMAX]; + DWORD dwWrapIndex; + + + hIcon = OleUIMetafilePictExtractIcon(ci.hMetaPict); + + SendDlgItemMessage(hDlg, IDCV_ICON, STM_SETICON, (WPARAM)hIcon, 0L); + + OleUIMetafilePictExtractIconSource(ci.hMetaPict, lpCV->lpszIconSource, &(lpCV->IconIndex)); + + OleUIMetafilePictExtractLabel(ci.hMetaPict, szLabel, OLEUI_CCHLABELMAX, &dwWrapIndex); + + if (0 == dwWrapIndex) // no second line + { + SendDlgItemMessage(hDlg, IDCV_ICONLABEL1, WM_SETTEXT, 0, (LPARAM)(LPTSTR)szLabel); + SendDlgItemMessage(hDlg, IDCV_ICONLABEL2, WM_SETTEXT, 0, (LPARAM)(LPTSTR)TEXT("")); + } + else + { + + LPTSTR lpszSecondLine; + + lpszSecondLine = szLabel + dwWrapIndex; + SendDlgItemMessage(hDlg, IDCV_ICONLABEL2, + WM_SETTEXT, 0, (LPARAM)lpszSecondLine); + + *lpszSecondLine = TEXT('\0'); + SendDlgItemMessage(hDlg, IDCV_ICONLABEL1, + WM_SETTEXT, 0, (LPARAM)(LPTSTR)szLabel); + } + + + // Update our custom/default flag + + if (ci.dwFlags & CIF_SELECTDEFAULT) + lpCV->fCustomIcon = FALSE; // we're in default mode (icon changes on each LB selchange) + else if (ci.dwFlags & CIF_SELECTFROMFILE) + lpCV->fCustomIcon = TRUE; // we're in custom mode (icon doesn't change) + // no change in fCustomIcon if user selected current + + + lpCV->lpOCV->fObjectsIconChanged = TRUE; + } + } + break; + + } + break; + } + return FALSE; + } + + +/* + * FConvertInit + * + * Purpose: + * WM_INITIDIALOG handler for the Convert dialog box. + * + * Parameters: + * hDlg HWND of the dialog + * wParam WPARAM of the message + * lParam LPARAM of the message + * + * Return Value: + * BOOL Value to return for WM_INITDIALOG. + */ + +BOOL FConvertInit(HWND hDlg, WPARAM wParam, LPARAM lParam) + { + LPCONVERT lpCV; + LPOLEUICONVERT lpOCV; + LPMALLOC pIMalloc; + HFONT hFont; // non-bold version of dialog's font + RECT rc; + DWORD dw; + INT cItemsActivate; + HKEY hKey; + LONG lRet; + UINT nRet; + + + //Copy the structure at lParam into our instance memory. + lpCV=(LPCONVERT)LpvStandardInit(hDlg, sizeof(CONVERT), TRUE, (HFONT FAR *)&hFont); + + //PvStandardInit send a termination to us already. + if (NULL==lpCV) + return FALSE; + + lpOCV=(LPOLEUICONVERT)lParam; + + lpCV->lpOCV=lpOCV; + + lpCV->fCustomIcon = FALSE; + + //Copy other information from lpOCV that we might modify. + lpCV->dwFlags = lpOCV->dwFlags; + lpCV->clsid = lpOCV->clsid; + lpCV->dvAspect = lpOCV->dvAspect; + lpCV->hListVisible = GetDlgItem(hDlg, IDCV_ACTIVATELIST); + lpCV->hListInvisible = GetDlgItem(hDlg, IDCV_CONVERTLIST); + lpCV->lpszCurrentObject = lpOCV->lpszUserType; + + lpOCV->clsidNew = CLSID_NULL; + + lpOCV->fObjectsIconChanged = FALSE; + + //Allocate space for our strings + if (NOERROR != CoGetMalloc(MEMCTX_TASK, &pIMalloc)) + return FALSE; + + lpCV->lpszConvertDefault = (LPTSTR)pIMalloc->lpVtbl->Alloc(pIMalloc, OLEUI_CCHLABELMAX_SIZE); + lpCV->lpszActivateDefault = (LPTSTR)pIMalloc->lpVtbl->Alloc(pIMalloc, OLEUI_CCHLABELMAX_SIZE); + lpCV->lpszIconSource = (LPTSTR)pIMalloc->lpVtbl->Alloc(pIMalloc, OLEUI_CCHPATHMAX_SIZE); + pIMalloc->lpVtbl->Release(pIMalloc); + + //If we got a font, send it to the necessary controls. + if (NULL!=hFont) + { + SendDlgItemMessage(hDlg, IDCV_OBJECTTYPE, WM_SETFONT, (WPARAM)hFont, 0L); + SendDlgItemMessage(hDlg, IDCV_RESULTTEXT, WM_SETFONT, (WPARAM)hFont, 0L); + SendDlgItemMessage(hDlg, IDCV_ICONLABEL1, WM_SETFONT, (WPARAM)hFont, 0L); + SendDlgItemMessage(hDlg, IDCV_ICONLABEL2, WM_SETFONT, (WPARAM)hFont, 0L); + } + + //Hide the help button if necessary + if (!(lpCV->dwFlags & CF_SHOWHELPBUTTON)) + StandardShowDlgItem(hDlg, ID_OLEUIHELP, SW_HIDE); + + //Fill the Object Type listbox with entries from the reg DB. + nRet = FillClassList(lpOCV->clsid, + lpCV->hListVisible, + lpCV->hListInvisible, + &(lpCV->lpszCurrentObject), + lpOCV->fIsLinkedObject, + lpOCV->wFormat, + lpOCV->cClsidExclude, + lpOCV->lpClsidExclude); + + if (nRet == -1) { + // bring down dialog if error when filling list box + PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_LOADSTRING, 0L); + } + + // Set the name of the current object. + SetDlgItemText(hDlg, IDCV_OBJECTTYPE, (LPTSTR)lpCV->lpszCurrentObject); + + // Disable the "Activate As" button if the Activate list doesn't + // have any objects in it. + + cItemsActivate = (INT)SendMessage(lpCV->hListVisible, LB_GETCOUNT, 0, 0L); + + if (1 >= cItemsActivate || (lpCV->dwFlags & CF_DISABLEACTIVATEAS)) + EnableWindow(GetDlgItem(hDlg, IDCV_ACTIVATEAS), FALSE); + + //Set the tab width in the list to push all the tabs off the side. + GetClientRect(lpCV->hListVisible, (LPRECT)&rc); + dw=GetDialogBaseUnits(); + rc.right =(8*rc.right)/LOWORD(dw); //Convert pixels to 2x dlg units. + SendMessage(lpCV->hListVisible, LB_SETTABSTOPS, 1, (LPARAM)(LPINT)(&rc.right)); + SendMessage(lpCV->hListInvisible, LB_SETTABSTOPS, 1, (LPARAM)(LPINT)(&rc.right)); + + + // Make sure that either "Convert To" or "Activate As" is selected + // and initialize listbox contents and selection accordingly + if (lpCV->dwFlags & CF_SELECTACTIVATEAS) + { + // Don't need to adjust listbox here because FillClassList + // initializes to the "Activate As" state. + CheckRadioButton(hDlg, IDCV_CONVERTTO, IDCV_ACTIVATEAS, IDCV_ACTIVATEAS); + + // Hide the icon stuff when Activate is selected...it gets shown + // again when Convert is selected. + + StandardShowDlgItem(hDlg, IDCV_DISPLAYASICON, SW_HIDE); + StandardShowDlgItem(hDlg, IDCV_CHANGEICON, SW_HIDE); + StandardShowDlgItem(hDlg, IDCV_ICON, SW_HIDE); + StandardShowDlgItem(hDlg, IDCV_ICONLABEL1, SW_HIDE); + StandardShowDlgItem(hDlg, IDCV_ICONLABEL2, SW_HIDE); + } + else + { + // Default case. If user hasn't selected either flag, we will + // come here anyway. + // swap listboxes. + + HWND hWndTemp = lpCV->hListVisible; + + if ( lpCV->dwFlags & CF_DISABLEDISPLAYASICON ) { + StandardShowDlgItem(hDlg, IDCV_DISPLAYASICON, SW_HIDE); + StandardShowDlgItem(hDlg, IDCV_CHANGEICON, SW_HIDE); + StandardShowDlgItem(hDlg, IDCV_ICON, SW_HIDE); + StandardShowDlgItem(hDlg, IDCV_ICONLABEL1, SW_HIDE); + StandardShowDlgItem(hDlg, IDCV_ICONLABEL2, SW_HIDE); + } + + lpCV->dwFlags |= CF_SELECTCONVERTTO; // Make sure flag is set + CheckRadioButton(hDlg, IDCV_CONVERTTO, IDCV_ACTIVATEAS, IDCV_CONVERTTO); + + SwapWindows(hDlg, lpCV->hListVisible, lpCV->hListInvisible); + + lpCV->hListVisible = lpCV->hListInvisible; + lpCV->hListInvisible = hWndTemp; + + EnableWindow(lpCV->hListInvisible, FALSE); + EnableWindow(lpCV->hListVisible, TRUE); + } + + + + // Initialize Default strings. + + // Default convert string is easy...just user the user type name from + // the clsid we got, or the current object + if ( (lpCV->dwFlags & CF_SETCONVERTDEFAULT) + && (IsValidClassID(lpCV->lpOCV->clsidConvertDefault)) ) + { + dw = OleStdGetUserTypeOfClass((LPCLSID)(&lpCV->lpOCV->clsidConvertDefault), + lpCV->lpszConvertDefault, + OLEUI_CCHLABELMAX_SIZE, + NULL); + + if (0 == dw) + lstrcpy((LPTSTR)lpCV->lpszConvertDefault, (LPTSTR)lpCV->lpszCurrentObject); + } + else + lstrcpy((LPTSTR)lpCV->lpszConvertDefault, (LPTSTR)lpCV->lpszCurrentObject); + + + // Default activate is a bit trickier. We want to use the user type + // name if from the clsid we got (assuming we got one), or the current + // object if it fails or we didn't get a clsid. But...if there's a + // Treat As entry in the reg db, then we use that instead. So... the + // logic boils down to this: + // + // if ("Treat As" in reg db) + // use it; + // else + // if (CF_SETACTIVATEDEFAULT) + // use it; + // else + // use current object; + + + + lRet = RegOpenKey(HKEY_CLASSES_ROOT, TEXT("CLSID"), (HKEY FAR *)&hKey); + + if (lRet != ERROR_SUCCESS) + goto CheckInputFlag; + + else + { + LPTSTR lpszCLSID; + TCHAR szKey[OLEUI_CCHKEYMAX]; + CLSID clsid; + TCHAR szValue[OLEUI_CCHKEYMAX]; + + StringFromCLSIDA(&(lpCV->lpOCV->clsid), &lpszCLSID); + lstrcpy(szKey, lpszCLSID); + lstrcat(szKey, TEXT("\\TreatAs")); + + dw = OLEUI_CCHKEYMAX_SIZE; + lRet = RegQueryValue(hKey, (LPTSTR)szKey, (LPTSTR)szValue, (LPDWORD)&dw); + + if (lRet != ERROR_SUCCESS) + { + + RegCloseKey(hKey); + OleStdFreeString(lpszCLSID, NULL); + goto CheckInputFlag; + } + else + { + CLSIDFromStringA(szValue, &clsid); + + if (0 == OleStdGetUserTypeOfClass(&clsid, + lpCV->lpszActivateDefault, + OLEUI_CCHLABELMAX_SIZE, + NULL)) + { + RegCloseKey(hKey); + OleStdFreeString(lpszCLSID, NULL); + goto CheckInputFlag; + } + } + RegCloseKey(hKey); + OleStdFreeString(lpszCLSID, NULL); + goto SelectStringInListbox; + } + + +CheckInputFlag: + if ( (lpCV->dwFlags & CF_SETACTIVATEDEFAULT) + && (IsValidClassID(lpCV->lpOCV->clsidActivateDefault)) ) + { + dw = OleStdGetUserTypeOfClass((LPCLSID)(&lpCV->lpOCV->clsidActivateDefault), + lpCV->lpszActivateDefault, + OLEUI_CCHLABELMAX_SIZE, + NULL); + + if (0 == dw) + lstrcpy((LPTSTR)lpCV->lpszActivateDefault, (LPTSTR)lpCV->lpszCurrentObject); + } + else + lstrcpy((LPTSTR)(lpCV->lpszActivateDefault), (LPTSTR)lpCV->lpszCurrentObject); + + +SelectStringInListbox: + + if (lpCV->dwFlags & CF_SELECTCONVERTTO) + lRet = SendMessage(lpCV->hListVisible, LB_SELECTSTRING, (WPARAM)-1, (LPARAM)(LPTSTR)(lpCV->lpszConvertDefault)); + + else + lRet = SendMessage(lpCV->hListVisible, LB_SELECTSTRING, (WPARAM)-1, (LPARAM)(LPTSTR)(lpCV->lpszActivateDefault)); + + if (LB_ERR == lRet) + SendMessage(lpCV->hListVisible, LB_SETCURSEL, (WPARAM)0, 0L); + + + // Initialize icon stuff + if (DVASPECT_ICON == lpCV->dvAspect ) + { + SendDlgItemMessage(hDlg, IDCV_DISPLAYASICON, BM_SETCHECK, TRUE, 0L); + + if ((HGLOBAL)NULL != lpOCV->hMetaPict) + { + TCHAR szLabel[OLEUI_CCHLABELMAX]; + HICON hIcon; + DWORD dwWrapIndex; + + + // Set the icon to the icon from the hMetaPict, + // set the label to the label from the hMetaPict. + + if (0 != OleUIMetafilePictExtractLabel(lpOCV->hMetaPict, (LPTSTR)szLabel, OLEUI_CCHLABELMAX_SIZE, &dwWrapIndex)) + { + if (0 == dwWrapIndex) // no second line + { + SendDlgItemMessage(hDlg, IDCV_ICONLABEL1, WM_SETTEXT, 0, (LPARAM)(LPTSTR)szLabel); + SendDlgItemMessage(hDlg, IDCV_ICONLABEL2, WM_SETTEXT, 0, (LPARAM)(LPTSTR)TEXT("")); + } + else + { + + LPTSTR lpszSecondLine; + + lpszSecondLine = szLabel + dwWrapIndex; + SendDlgItemMessage(hDlg, IDCV_ICONLABEL2, + WM_SETTEXT, 0, (LPARAM)lpszSecondLine); + + *lpszSecondLine = TEXT('\0'); + SendDlgItemMessage(hDlg, IDCV_ICONLABEL1, + WM_SETTEXT, 0, (LPARAM)(LPTSTR)szLabel); + } + + + } + + hIcon = OleUIMetafilePictExtractIcon(lpOCV->hMetaPict); + + if (NULL != hIcon) + { + SendDlgItemMessage(hDlg, IDCV_ICON, STM_SETICON, (WPARAM)hIcon, 0L); + lpCV->fCustomIcon = TRUE; + } + + OleUIMetafilePictExtractIconSource(lpOCV->hMetaPict, + (LPTSTR)(lpCV->lpszIconSource), + &(lpCV->IconIndex)); + + } + else + UpdateCVClassIcon(hDlg, lpCV, lpCV->hListVisible); + } + else + { + // Hide & disable icon stuff + StandardShowDlgItem(hDlg, IDCV_ICON, SW_HIDE); + StandardShowDlgItem(hDlg, IDCV_ICONLABEL1, SW_HIDE); + StandardShowDlgItem(hDlg, IDCV_ICONLABEL2, SW_HIDE); + StandardShowDlgItem(hDlg, IDCV_CHANGEICON, SW_HIDE); + } + + // Call the hook with lCustData in lParam + UStandardHook((LPVOID)lpCV, hDlg, WM_INITDIALOG, wParam, lpOCV->lCustData); + // Update results window + SetConvertResults(hDlg, lpCV); + + // Update caption if lpszCaption was specified + if (lpCV->lpOCV->lpszCaption && !IsBadReadPtr(lpCV->lpOCV->lpszCaption, 1) + && lpCV->lpOCV->lpszCaption[0] != '\0') + SetWindowText(hDlg, (LPTSTR)lpCV->lpOCV->lpszCaption); + + return TRUE; + } + + +/* + * FillClassList + * + * Purpose: + * Enumerates available OLE object classes from the registration + * database that we can convert or activate the specified clsid from. + * + * Note that this function removes any prior contents of the listbox. + * + * Parameters: + * clsid Class ID for class to find convert classes for + * hList HWND to the listbox to fill. + * hListActivate HWND to invisible listbox that stores "activate as" list. + * lpszClassName LPSTR to put the (hr) class name of the clsid; we + * do it here since we've already got the reg db open. + * fIsLinkedObject BOOL is the original object a linked object + * wFormat WORD specifying the format of the original class. + * cClsidExclude UINT number of entries in exclude list + * lpClsidExclude LPCLSID array classes to exclude for list + * + * Return Value: + * UINT Number of strings added to the listbox, -1 on failure. + */ + +UINT FillClassList( + CLSID clsid, + HWND hList, + HWND hListInvisible, + LPTSTR FAR *lplpszCurrentClass, + BOOL fIsLinkedObject, + WORD wFormat, + UINT cClsidExclude, + LPCLSID lpClsidExclude) +{ + + DWORD dw; + UINT cStrings=0; + HKEY hKey; + LONG lRet; + TCHAR szFormatKey[OLEUI_CCHKEYMAX]; + TCHAR szClass[OLEUI_CCHKEYMAX]; + TCHAR szFormat[OLEUI_CCHKEYMAX]; + TCHAR szHRClassName[OLEUI_CCHKEYMAX]; + CLSID clsidForList; + + LPTSTR lpszCLSID; + + + //Clean out the existing strings. + SendMessage(hList, LB_RESETCONTENT, 0, 0L); + SendMessage(hListInvisible, LB_RESETCONTENT, 0, 0L); + + //Open up the root key. + lRet=RegOpenKey(HKEY_CLASSES_ROOT, (LPCTSTR) TEXT("CLSID"), (HKEY FAR *)&hKey); + + if ((LONG)ERROR_SUCCESS!=lRet) + return (UINT)-1; + + if (NULL == *lplpszCurrentClass) + { + // alloc buffer here... + + LPMALLOC pIMalloc = NULL; + HRESULT hrErr; + + + hrErr = CoGetMalloc(MEMCTX_TASK, &pIMalloc); + + if (hrErr != NOERROR) + { + RegCloseKey(hKey); + return FALSE; + } + + // Allocate space for lpszCurrentClass + *lplpszCurrentClass = (LPTSTR)pIMalloc->lpVtbl->Alloc(pIMalloc, OLEUI_CCHKEYMAX_SIZE); + pIMalloc->lpVtbl->Release(pIMalloc); + + lRet = OleStdGetUserTypeOfClass((REFCLSID)&clsid, + *lplpszCurrentClass, + OLEUI_CCHLABELMAX_SIZE, + NULL); + + if (0 ==lRet) + { + INT n = LoadString(ghInst, IDS_PSUNKNOWNTYPE, *lplpszCurrentClass, + OLEUI_CCHKEYMAX); + if (!n) + { + OutputDebugString(TEXT("Cannot LoadString\n")); + RegCloseKey(hKey); + return (UINT)-1; + } + } + } + + // Get the class name of the original class. + StringFromCLSIDA(&clsid, &lpszCLSID); + + + // Here, we step through the entire registration db looking for + // class that can read or write the original class' format. We + // maintain two lists - an activate list and a convert list. The + // activate list is a subset of the convert list - activate == read/write + // and convert == read. We swap the listboxes as needed with + // SwapWindows, and keep track of which is which in the lpCV structure. + + // Every item has the following format: + // + // Class Name\tclsid\0 + + + cStrings=0; + lRet=RegEnumKey(hKey, cStrings++, szClass, OLEUI_CCHKEYMAX_SIZE); + + while ((LONG)ERROR_SUCCESS==lRet) + { + INT j; + BOOL fExclude=FALSE; + + + //Check if this CLSID is in the exclusion list. + CLSIDFromStringA(szClass, &clsidForList); + + for (j=0; j < (int)cClsidExclude; j++) + { + if (IsEqualCLSID(&clsidForList, (LPCLSID)(lpClsidExclude+j))) + { + fExclude=TRUE; + break; + } + } + if (fExclude) + goto Next; // don't add this class to list + + // Check for a \Conversion\Readwritable\Main - if its + // readwriteable, then the class can be added to the ActivateAs + // list. + // NOTE: the presence of this key should NOT automatically be + // used to add the class to the CONVERT list. + + lstrcpy((LPTSTR)szFormatKey, (LPTSTR)szClass); + lstrcat((LPTSTR)szFormatKey, (LPTSTR) TEXT("\\Conversion\\Readwritable\\Main")); + + dw=OLEUI_CCHKEYMAX_SIZE; + + lRet=RegQueryValue(hKey, (LPTSTR)szFormatKey, (LPTSTR)szFormat, (LONG FAR *)&dw); + + if ( ((LONG)ERROR_SUCCESS==lRet) + && (FormatIncluded((LPTSTR)szFormat, wFormat)) ) + { + // Here, we've got a list of formats that this class can read + // and write. We need to see if the original class' format is + // in this list. We do that by looking for wFormat in + // szFormat - if it in there, then we add this class to the + // ACTIVATEAS list only. we do NOT automatically add it to the + // CONVERT list. Readable and Readwritable format lists should + // be handled separately. + + dw=OLEUI_CCHKEYMAX_SIZE; + lRet=RegQueryValue(hKey, (LPTSTR)szClass, (LPTSTR)szHRClassName, (LPDWORD)&dw); + + if ((LONG)ERROR_SUCCESS==lRet) + { + lstrcat((LPTSTR)szHRClassName, (LPTSTR) TEXT("\t")); + + // only add if not already in list + if (LB_ERR==SendMessage(hList,LB_FINDSTRING, 0, + (LPARAM)(LPSTR)szHRClassName)) { + lstrcat((LPTSTR)szHRClassName, (LPTSTR)szClass); + SendMessage(hList, LB_ADDSTRING, 0, + (DWORD)(LPTSTR)szHRClassName); + } + } + + } + + + // Here we'll check to see if the original class' format is in the + // readable list. if so, we will add the class to the CONVERTLIST + + + // We've got a special case for a linked object here. + // If an object is linked, then the only class that + // should appear in the convert list is the object's + // class. So, here we check to see if the object is + // linked. If it is, then we compare the classes. If + // they aren't the same, then we just go to the next key. + + if ( (!fIsLinkedObject)||(lstrcmp((LPCTSTR)lpszCLSID, szClass) == 0)) + { + + //Check for a \Conversion\Readable\Main entry + lstrcpy((LPTSTR)szFormatKey, (LPTSTR)szClass); + lstrcat((LPTSTR)szFormatKey, (LPTSTR) TEXT("\\Conversion\\Readable\\Main")); + + dw=OLEUI_CCHKEYMAX_SIZE; + + // Check to see if this class can read the original class + // format. If it can, add the string to the listbox as + // CONVERT_LIST. + + lRet=RegQueryValue(hKey, (LPCTSTR)szFormatKey, (LPTSTR)szFormat, (LPDWORD)&dw); + + if ( ((LONG)ERROR_SUCCESS==lRet) + && (FormatIncluded((LPTSTR)szFormat, wFormat)) ) + { + + + dw=OLEUI_CCHKEYMAX_SIZE; + lRet=RegQueryValue(hKey, (LPCTSTR)szClass, (LPTSTR)szHRClassName, (LPDWORD)&dw); + + if ((LONG)ERROR_SUCCESS==lRet) + { + lstrcat((LPTSTR)szHRClassName, (LPTSTR) TEXT("\t")); + + // only add if not already in list + if (LB_ERR==SendMessage(hListInvisible,LB_FINDSTRING, 0, + (LPARAM)(LPSTR)szHRClassName)) { + lstrcat((LPTSTR)szHRClassName, szClass); + SendMessage(hListInvisible, LB_ADDSTRING, 0, + (DWORD)(LPTSTR)szHRClassName); + } + } // end if + + } // end if + } // end else +Next: + //Continue with the next key. + lRet=RegEnumKey(hKey, cStrings++, (LPTSTR)szClass, OLEUI_CCHKEYMAX_SIZE); + + } // end while + + // If the original class isn't already in the list, add it. + + lstrcpy((LPTSTR)szHRClassName, *lplpszCurrentClass); + lstrcat((LPTSTR)szHRClassName, (LPTSTR) TEXT("\t")); + + lRet = SendMessage(hList, LB_FINDSTRING, (WPARAM)-1, (LPARAM)(LPTSTR)szHRClassName); + + // only add it if it's not there already. + if (LB_ERR == lRet) { + lstrcat((LPTSTR)szHRClassName, lpszCLSID); + SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)(LPTSTR)szHRClassName); + } + + lRet = SendMessage(hListInvisible, LB_FINDSTRING, (WPARAM)-1, (LPARAM)(LPTSTR)szHRClassName); + + // only add it if it's not there already. + if (LB_ERR == lRet) + SendMessage(hListInvisible, LB_ADDSTRING, 0, (LPARAM)(LPTSTR)szHRClassName); + + // Free the string we got from StringFromCLSID. + // OLE2NOTE: StringFromCLSID uses your IMalloc to alloc a + // string, so you need to be sure to free the string you + // get back, otherwise you'll have leaky memory. + + OleStdFreeString(lpszCLSID, NULL); + + RegCloseKey(hKey); + + return cStrings; +} + + +/* + * OleUICanConvertOrActivateAs + * + * Purpose: + * Determine if there is any OLE object class from the registration + * database that we can convert or activate the specified clsid from. + * + * Parameters: + * rClsid REFCLSID Class ID for class to find convert classes for + * fIsLinkedObject BOOL is the original object a linked object + * wFormat WORD specifying the format of the original class. + * + * Return Value: + * BOOL TRUE if Convert command should be enabled, else FALSE + */ + +STDAPI_(BOOL) OleUICanConvertOrActivateAs( + REFCLSID rClsid, + BOOL fIsLinkedObject, + WORD wFormat +) +{ + + DWORD dw; + UINT cStrings=0; + HKEY hKey; + LONG lRet; + TCHAR szFormatKey[OLEUI_CCHKEYMAX]; + TCHAR szClass[OLEUI_CCHKEYMAX]; + TCHAR szFormat[OLEUI_CCHKEYMAX]; + TCHAR szHRClassName[OLEUI_CCHKEYMAX]; + BOOL fEnableConvert = FALSE; + + LPTSTR lpszCLSID; + + //Open up the root key. + lRet=RegOpenKey(HKEY_CLASSES_ROOT, "CLSID", (HKEY FAR *)&hKey); + + if ((LONG)ERROR_SUCCESS!=lRet) + return FALSE; + + // Get the class name of the original class. + StringFromCLSIDA(rClsid, &lpszCLSID); + + // Here, we step through the entire registration db looking for + // class that can read or write the original class' format. + // This loop stops if a single class is found. + + cStrings=0; + lRet=RegEnumKey(hKey, cStrings++, szClass, OLEUI_CCHKEYMAX_SIZE); + + while ((LONG)ERROR_SUCCESS==lRet) + { + if (lstrcmp(lpszCLSID, szClass)== 0) + goto next; // we don't want to consider the source class + + // Check for a \Conversion\ReadWriteable\Main entry first - if its + // readwriteable, then we don't need to bother checking to see if + // its readable. + + lstrcpy((LPTSTR)szFormatKey, (LPTSTR)szClass); + lstrcat((LPTSTR)szFormatKey, (LPTSTR) TEXT("\\Conversion\\Readwritable\\Main")); + + dw=OLEUI_CCHKEYMAX_SIZE; + + lRet=RegQueryValue(hKey, (LPCTSTR)szFormatKey, (LPTSTR)szFormat, (LONG FAR *)&dw); + + if ( (LONG)ERROR_SUCCESS != lRet) + { + // Try \\DataFormats\DefaultFile too + + lstrcpy((LPTSTR)szFormatKey, (LPTSTR)szClass); + lstrcat((LPTSTR)szFormatKey, (LPTSTR) TEXT("\\DataFormats\\DefaultFile")); + + dw=OLEUI_CCHKEYMAX_SIZE; + + lRet=RegQueryValue(hKey, (LPCTSTR)szFormatKey, (LPTSTR)szFormat, (LONG FAR *)&dw); + } + + + if ( ((LONG)ERROR_SUCCESS==lRet) + && (FormatIncluded((LPTSTR)szFormat, wFormat)) ) + { + + // Here, we've got a list of formats that this class can read + // and write. We need to see if the original class' format is + // in this list. We do that by looking for wFormat in + // szFormat - if it in there, then we add this class to the + // both lists and continue. If not, then we look at the + // class' readable formats. + + + dw=OLEUI_CCHKEYMAX_SIZE; + lRet=RegQueryValue(hKey, (LPCTSTR)szClass, (LPTSTR)szHRClassName, (LPDWORD)&dw); + + if ((LONG)ERROR_SUCCESS==lRet) + { + fEnableConvert = TRUE; + break; // STOP -- found one! + } + + } + + + // We either didn't find the readwritable key, or the + // list of readwritable formats didn't include the + // original class format. So, here we'll check to + // see if its in the readable list. + + + // We've got a special case for a linked object here. + // If an object is linked, then the only class that + // should appear in the convert list is the object's + // class. So, here we check to see if the object is + // linked. If it is, then we compare the classes. If + // they aren't the same, then we just go to the next key. + + else if ( (!fIsLinkedObject)|| + (lstrcmp((LPTSTR)lpszCLSID, (LPTSTR)szClass)== 0)) + { + + //Check for a \Conversion\Readable\Main entry + lstrcpy((LPTSTR)szFormatKey, (LPTSTR)szClass); + lstrcat((LPTSTR)szFormatKey, (LPTSTR) TEXT("\\Conversion\\Readable\\Main")); + + dw=OLEUI_CCHKEYMAX_SIZE; + + // Check to see if this class can read the original class + // format. If it can, add the string to the listbox as + // CONVERT_LIST. + + lRet=RegQueryValue(hKey, (LPTSTR)szFormatKey, (LPTSTR)szFormat, (LPDWORD)&dw); + + if ( ((LONG)ERROR_SUCCESS==lRet) + && (FormatIncluded((LPTSTR)szFormat, wFormat)) ) + { + + + dw=OLEUI_CCHKEYMAX_SIZE; + lRet=RegQueryValue(hKey, (LPTSTR)szClass, (LPTSTR)szHRClassName, (LPDWORD)&dw); + + if ((LONG)ERROR_SUCCESS==lRet) + { + + fEnableConvert = TRUE; + break; // STOP -- found one! + } // end if + + } // end if + } // end else +next: + //Continue with the next key. + lRet=RegEnumKey(hKey, cStrings++, (LPTSTR)szClass, OLEUI_CCHKEYMAX_SIZE); + + } // end while + + // Free the string we got from StringFromCLSID. + // OLE2NOTE: StringFromCLSID uses your IMalloc to alloc a + // string, so you need to be sure to free the string you + // get back, otherwise you'll have leaky memory. + + OleStdFreeString(lpszCLSID, NULL); + + RegCloseKey(hKey); + + return fEnableConvert; +} + + +/* + * FormatIncluded + * + * Purpose: + * Parses the string for format from the word. + * + * Parameters: + * szStringToSearch String to parse + * wFormat format to find + * + * Return Value: + * BOOL TRUE if format is found in string, + * FALSE otherwise. + */ +BOOL FormatIncluded(LPTSTR szStringToSearch, WORD wFormat) +{ + + LPTSTR lpToken; + TCHAR seps[] = TEXT(","); + static TCHAR szFormat[255]; // max size of atom (what GetClipboardName returns) + + + if (wFormat < 0xC000) // RegisterClipboardFormat returns values + { + char szTemp[11]; + + _itoa(wFormat, szTemp, 10); // between 0xC000 and 0xFFFF. + +#ifdef UNICODE + mbstowcs(szFormat, szTemp, 11); +#else + strncpy(szFormat, szTemp, 11); +#endif + + } + + else + GetClipboardFormatName(wFormat, szFormat, 255); + + lpToken = (LPTSTR)_fstrtok(szStringToSearch, seps); + + while (lpToken != NULL) + { + + if (0 ==lstrcmpi(lpToken, szFormat)) + return TRUE; + + else + lpToken = (LPTSTR)_fstrtok(NULL, seps); + } + + return FALSE; +} + + +/* + * UpdateCVClassIcon + * + * Purpose: + * Handles LBN_SELCHANGE for the Object Type listbox. On a selection + * change, we extract an icon from the server handling the currently + * selected object type using the utility function HIconFromClass. + * Note that we depend on the behavior of FillClassList to stuff the + * object class after a tab in the listbox string that we hide from + * view (see WM_INITDIALOG). + * + * Parameters + * hDlg HWND of the dialog box. + * lpCV LPCONVERT pointing to the dialog structure + * hList HWND of the Object Type listbox. + * + * Return Value: + * None + */ + +void UpdateCVClassIcon(HWND hDlg, LPCONVERT lpCV, HWND hList) + { + UINT iSel; + DWORD cb; + HGLOBAL hMem; + LPTSTR pszName, pszCLSID; + CLSID clsid; + HICON hIcon, hOldIcon; + UINT cch, uWrapIndex; + RECT LabelRect; + TCHAR szLabel[OLEUI_CCHLABELMAX]; + LPTSTR lpszLabel = szLabel; + HFONT hFont; + HWND hLabel1; + + /* + * When we change object type selection, get the new icon for that + * type into our structure and update it in the display. + */ + + iSel=(UINT)SendMessage(hList, LB_GETCURSEL, 0, 0L); + + if (LB_ERR==(INT)iSel) + return; + + //Allocate a string to hold the entire listbox string + cb=SendMessage(hList, LB_GETTEXTLEN, iSel, 0L); + + hMem=GlobalAlloc(GHND, cb+1); + + if (NULL==hMem) + return; + + pszName=GlobalLock(hMem); + + // Get whole string + SendMessage(hList, LB_GETTEXT, iSel, (LONG)pszName); + + // Set pointer to CLSID (string) + pszCLSID = PointerToNthField(pszName, 2, TEXT('\t')); + + //Create the class ID with this string. + CLSIDFromStringA(pszCLSID, &clsid); + + hIcon = HIconAndSourceFromClass(&clsid, (LPTSTR)(lpCV->lpszIconSource), &(lpCV->IconIndex)); + + if (NULL == hIcon) // Use Vanilla Document + { + lstrcpy((LPTSTR)(lpCV->lpszIconSource), (LPTSTR)szOLE2DLL); + lpCV->IconIndex = 0; // 1st icon in OLE2.DLL + hIcon = ExtractIcon(ghInst, + (LPTSTR)(lpCV->lpszIconSource), + lpCV->IconIndex); + } + + //Replace the current display with this new one. + hOldIcon = (HICON)SendDlgItemMessage(hDlg, IDCV_ICON, STM_SETICON, (WPARAM)hIcon, 0L); + + hLabel1 = GetDlgItem(hDlg, IDCV_ICONLABEL1); + + GetWindowRect(hLabel1, &LabelRect); + + // Get the label + if (lpCV->lpOCV->lpszDefLabel) { + // width is used as 1.5 times width of icon window + lpszLabel = ChopText(hLabel1, ((LabelRect.right-LabelRect.left)*3)/2, (LPTSTR)lpCV->lpOCV->lpszDefLabel); + LSTRCPYN(szLabel, lpCV->lpOCV->lpszDefLabel, sizeof(szLabel)/sizeof(TCHAR)); + } else { + if ((cch = OleStdGetAuxUserType(&clsid, AUXUSERTYPE_SHORTNAME, + (LPTSTR)szLabel, OLEUI_CCHLABELMAX_SIZE, NULL)) == 0) { + // If we can't get the AuxUserType2, then try the long name + if ((cch = OleStdGetUserTypeOfClass(&clsid, (LPTSTR)szLabel, + OLEUI_CCHKEYMAX_SIZE, NULL)) == 0) { + // last resort; use "Document" as label + LoadString(ghInst,IDS_DEFICONLABEL,(LPTSTR)szLabel,OLEUI_CCHLABELMAX); + cch = lstrlen((LPCTSTR)szLabel); + } + } + } + + hFont = (HFONT)SendMessage(hLabel1, WM_GETFONT, 0, 0L); + + // Figure out where to split the label + uWrapIndex = OleStdIconLabelTextOut(NULL, hFont, 0, 0, 0, &LabelRect, (LPTSTR)lpszLabel, cch, NULL); + + if (0 == uWrapIndex) + { + SendMessage(hLabel1, WM_SETTEXT, 0, (LPARAM)(LPTSTR)lpszLabel); + SendDlgItemMessage(hDlg, IDCV_ICONLABEL2, WM_SETTEXT, 0, (LPARAM)(LPTSTR)""); + } + else + { + TCHAR chKeep; + LPTSTR lpszSecondLine; + + chKeep = szLabel[uWrapIndex]; + lpszLabel[uWrapIndex] = TEXT('\0'); + + SendMessage(hLabel1, WM_SETTEXT, 0, (LPARAM)(LPTSTR)lpszLabel); + + lpszLabel[uWrapIndex] = chKeep; + lpszSecondLine = lpszLabel + uWrapIndex; + + SendDlgItemMessage(hDlg, IDCV_ICONLABEL2, WM_SETTEXT, 0, (LPARAM)lpszSecondLine); + } + + // get rid of the old icon + if ((HICON)NULL != hOldIcon) + DestroyIcon(hOldIcon); + + GlobalUnlock(hMem); + GlobalFree(hMem); + return; + } + + + + + + +BOOL IsValidClassID(CLSID cID) +{ + if (0 == _fmemcmp(&cID, &CLSID_NULL, sizeof(CLSID))) // if (CLSID_NULL == cID) + return FALSE; + else + return TRUE; +} + + + +/* + * SetConvertResults + * + * Purpose: + * Centralizes setting of the Result display in the Convert + * dialog. Handles loading the appropriate string from the module's + * resources and setting the text, displaying the proper result picture, + * and showing the proper icon. + * + * Parameters: + * hDlg HWND of the dialog box so we can access controls. + * lpCV LPCONVERT in which we assume that the dwFlags is + * set to the appropriate radio button selection, and + * the list box has the appropriate class selected. + * + * Return Value: + * None + */ + +void SetConvertResults(HWND hDlg, LPCONVERT lpCV) + { + LPTSTR pszT, // temp + lpszOutput, // text sent in SetDlgItemText + lpszDefObj, // string containing default object class + lpszSelObj, // string containing selected object class + lpszString; // stirng we get from loadstring + + UINT i, cch; + HGLOBAL hMem; + + HWND hList; // handle to listbox (so we can just use SendMsg i + // instead of SendDlgItemMsg). + + + hList = lpCV->hListVisible; + /* + * We need scratch memory for loading the stringtable string, loading + * the object type from the listbox, loading the source object + * type, and constructing the final string. We therefore allocate + * four buffers as large as the maximum message length (512) plus + * the object type, guaranteeing that we have enough + * in all cases. + */ + i=(UINT)SendMessage(hList, LB_GETCURSEL, 0, 0L); + + cch=512+(UINT)SendMessage(hList, LB_GETTEXTLEN, i, 0L); + + hMem=GlobalAlloc(GHND, (DWORD)(4*cch)); + + if (NULL==hMem) + return; + + lpszOutput = (LPTSTR)GlobalLock(hMem); + lpszSelObj = lpszOutput + cch; + lpszDefObj = lpszSelObj + cch; + lpszString = lpszDefObj + cch; + + // Get selected object and null terminate human-readable name (1st field). + SendMessage(hList, LB_GETTEXT, i, (LONG)lpszSelObj); + + pszT = PointerToNthField(lpszSelObj, 2, TEXT('\t')); + +#ifdef WIN32 + // AnsiPrev is obsolete in Win32 + pszT = CharPrev((LPCTSTR) lpszSelObj, (LPCTSTR) pszT); +#else + pszT = AnsiPrev((LPCTSTR) lpszSelObj, (LPCTSTR) pszT); +#endif + + *pszT = TEXT('\0'); + + // Get default object + + GetDlgItemText(hDlg, IDCV_OBJECTTYPE, lpszDefObj, 512); + + + //Default is an empty string. + *lpszOutput=0; + + + if (lpCV->dwFlags & CF_SELECTCONVERTTO) + { + + if (lpCV->lpOCV->fIsLinkedObject) // working with linked object + LoadString(ghInst, IDS_CVRESULTCONVERTLINK, lpszOutput, cch); + + else + { + // converting to a new class + if (0 !=lstrcmp(lpszDefObj, lpszSelObj)) + { + if (0 != LoadString(ghInst, IDS_CVRESULTCONVERTTO, lpszString, cch)) + wsprintf(lpszOutput, lpszString, lpszDefObj, lpszSelObj); + + } + else // converting to the same class (no conversion) + { + + if (0 != LoadString(ghInst, IDS_CVRESULTNOCHANGE, lpszString, cch)) + wsprintf(lpszOutput, lpszString, lpszDefObj); + } + + } + + if (lpCV->dvAspect == DVASPECT_ICON) // Display as icon is checked + { + if (0 != LoadString(ghInst, IDS_CVRESULTDISPLAYASICON, lpszString, cch)) + lstrcat(lpszOutput, lpszString); + } + } + + if (lpCV->dwFlags & CF_SELECTACTIVATEAS) + { + + if (0!=LoadString(ghInst, IDS_CVRESULTACTIVATEAS, lpszString, cch)) + wsprintf(lpszOutput, lpszString, lpszDefObj, lpszSelObj); + + // activating as a new class + if (0 !=lstrcmp(lpszDefObj, lpszSelObj)) + { + if (0!=LoadString(ghInst, IDS_CVRESULTACTIVATEDIFF, lpszString, cch)) + lstrcat(lpszOutput, lpszString); + } + else // activating as itself. + { + lstrcat(lpszOutput, TEXT(".")); + } + } + + + //If LoadString failed, we simply clear out the results (*lpszOutput=0 above) + SetDlgItemText(hDlg, IDCV_RESULTTEXT, lpszOutput); + + GlobalUnlock(hMem); + GlobalFree(hMem); + return; + } + + + + + + +/* + * ConvertCleanup + * + * Purpose: + * Performs convert-specific cleanup before Convert termination. + * + * Parameters: + * hDlg HWND of the dialog box so we can access controls. + * + * Return Value: + * None + */ +void ConvertCleanup(HWND hDlg, LPCONVERT lpCV) +{ + + LPMALLOC pIMalloc; + + + // Free our strings. Zero out the user type name string + // the the calling app doesn't free to it. + + if (NOERROR == CoGetMalloc(MEMCTX_TASK, &pIMalloc)) + { + pIMalloc->lpVtbl->Free(pIMalloc, (LPVOID)lpCV->lpszConvertDefault); + pIMalloc->lpVtbl->Free(pIMalloc, (LPVOID)lpCV->lpszActivateDefault); + pIMalloc->lpVtbl->Free(pIMalloc, (LPVOID)lpCV->lpszIconSource); + if (lpCV->lpOCV->lpszUserType) { + pIMalloc->lpVtbl->Free(pIMalloc,(LPVOID)lpCV->lpOCV->lpszUserType); + lpCV->lpOCV->lpszUserType = NULL; + } + if (lpCV->lpOCV->lpszDefLabel) { + pIMalloc->lpVtbl->Free(pIMalloc,(LPVOID)lpCV->lpOCV->lpszDefLabel); + lpCV->lpOCV->lpszDefLabel = NULL; + } + + pIMalloc->lpVtbl->Release(pIMalloc); + } + + return; +} + + + + + +/* + * SwapWindows + * + * Purpose: + * Moves hWnd1 to hWnd2's position and hWnd2 to hWnd1's position. + * Does NOT change sizes. + * + * + * Parameters: + * hDlg HWND of the dialog box so we can turn redraw off + * + * Return Value: + * None + */ +void SwapWindows(HWND hDlg, HWND hWnd1, HWND hWnd2) +{ + + RECT Rect1, Rect2; + + + GetWindowRect(hWnd1, &Rect1); + GetWindowRect(hWnd2, &Rect2); + + ScreenToClient(hDlg, (LPPOINT)&Rect1.left); + ScreenToClient(hDlg, (LPPOINT)&Rect1.right); + + ScreenToClient(hDlg, (LPPOINT)&Rect2.left); + ScreenToClient(hDlg, (LPPOINT)&Rect2.right); + + SetWindowPos(hWnd1, + NULL, + Rect2.left, + Rect2.top, + 0, + 0, + SWP_NOZORDER | SWP_NOSIZE); + + SetWindowPos(hWnd2, + NULL, + Rect1.left, + Rect1.top, + 0, + 0, + SWP_NOZORDER | SWP_NOSIZE); + + return; + +} + diff --git a/private/oleutest/letest/ole2ui/convert.dlg b/private/oleutest/letest/ole2ui/convert.dlg new file mode 100644 index 000000000..4f6f4dfc0 --- /dev/null +++ b/private/oleutest/letest/ole2ui/convert.dlg @@ -0,0 +1,32 @@ + +IDD_CONVERT DIALOG 60, 26, 270, 146 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Convert" +FONT 8, "MS Shell Dlg" +BEGIN + RTEXT "Current Type:", IDCV_STXCURTYPE, 5, 7, 47, 8 + LTEXT "Current Object Type", IDCV_OBJECTTYPE, 55, 7, 129, 8 + LTEXT "Object T&ype:", IDCV_STXCONVERTTO, 71, 21, 89, 8 + LISTBOX IDCV_ACTIVATELIST, 71, 32, 118, 53, + LBS_USETABSTOPS | LBS_SORT | WS_VSCROLL | WS_GROUP | WS_TABSTOP + LISTBOX IDCV_CONVERTLIST, 350, 180, 118, 53, + LBS_USETABSTOPS | LBS_SORT | WS_VSCROLL | WS_GROUP | WS_TABSTOP + DEFPUSHBUTTON "OK", IDOK, 197, 6, 67, 14, WS_GROUP + PUSHBUTTON "Cancel", IDCANCEL, 197, 24, 66, 14 + PUSHBUTTON "&Help", ID_OLEUIHELP, 197, 42, 66, 14 + CONTROL "&Display As Icon", IDCV_DISPLAYASICON, "Button", + BS_AUTOCHECKBOX | WS_TABSTOP, 200, 61, 64, 10 + GROUPBOX "Result", IDCV_GRPRESULT, 6, 87, 183, 50 + CONTROL "&Convert to:", IDCV_CONVERTTO, "Button", + BS_AUTORADIOBUTTON, 6, 34, 59, 10 + CONTROL "&Activate as:", IDCV_ACTIVATEAS, "Button", + BS_AUTORADIOBUTTON, 7, 58, 59, 10 + LTEXT "Result Text...", IDCV_RESULTTEXT, 11, 98, 174, 27 + ICON "", IDCV_ICON, 221, 75, 18, 20 + CTEXT "", IDCV_ICONLABEL1, 197, 100, 66, 8 + CTEXT "", IDCV_ICONLABEL2, 197, 108, 66, 12 + PUSHBUTTON "Change &Icon...", IDCV_CHANGEICON, 197, 121, 67, 14 +END + + + diff --git a/private/oleutest/letest/ole2ui/convert.h b/private/oleutest/letest/ole2ui/convert.h new file mode 100644 index 000000000..c6df6aa4f --- /dev/null +++ b/private/oleutest/letest/ole2ui/convert.h @@ -0,0 +1,63 @@ +/* + * CONVERT.H + * + * Internal definitions, structures, and function prototypes for the + * OLE 2.0 UI Convert dialog. + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + + +#ifndef _CONVERT_H_ +#define _CONVERT_H_ + + +//Internally used structure +typedef struct tagCONVERT + { + //Keep this item first as the Standard* functions depend on it here. + LPOLEUICONVERT lpOCV; //Original structure passed. + + /* + * What we store extra in this structure besides the original caller's + * pointer are those fields that we need to modify during the life of + * the dialog but that we don't want to change in the original structure + * until the user presses OK. + */ + + DWORD dwFlags; // Flags passed in + HWND hListVisible; // listbox that is currently visible + HWND hListInvisible; // listbox that is currently hidden + CLSID clsid; // Class ID sent in to dialog: IN only + DWORD dvAspect; + BOOL fCustomIcon; + UINT IconIndex; // index (in exe) of current icon + LPTSTR lpszIconSource; // path to current icon source + LPTSTR lpszCurrentObject; + LPTSTR lpszConvertDefault; + LPTSTR lpszActivateDefault; + } CONVERT, *PCONVERT, FAR *LPCONVERT; + + + +//Internal function prototypes in CONVERT.C +BOOL CALLBACK EXPORT ConvertDialogProc(HWND, UINT, WPARAM, LPARAM); +BOOL FConvertInit(HWND hDlg, WPARAM, LPARAM); +UINT FPopulateListbox(HWND hListbox, CLSID cID); +BOOL IsValidClassID(CLSID cID); +void SetConvertResults(HWND, LPCONVERT); +UINT FillClassList( + CLSID clsid, + HWND hList, + HWND hListInvisible, + LPTSTR FAR *lplpszCurrentClass, + BOOL fIsLinkedObject, + WORD wFormat, + UINT cClsidExclude, + LPCLSID lpClsidExclude); +BOOL FormatIncluded(LPTSTR szStringToSearch, WORD wFormat); +void UpdateCVClassIcon(HWND hDlg, LPCONVERT lpCV, HWND hList); +void SwapWindows(HWND, HWND, HWND); +void ConvertCleanup(HWND hDlg, LPCONVERT lpCV); + +#endif // _CONVERT_H_ diff --git a/private/oleutest/letest/ole2ui/daytona/makefile b/private/oleutest/letest/ole2ui/daytona/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/oleutest/letest/ole2ui/daytona/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/oleutest/letest/ole2ui/daytona/ole2u32a.src b/private/oleutest/letest/ole2ui/daytona/ole2u32a.src new file mode 100644 index 000000000..fe30edf8e --- /dev/null +++ b/private/oleutest/letest/ole2ui/daytona/ole2u32a.src @@ -0,0 +1,200 @@ +#if 0 + + Microsoft Windows + Copyright (C) Microsoft Corporation, 1992 - 1992. + All rights reserved. + + This .def file is preprocessed by the compiler to create the version for + the current build in the appropriate subdir. Basically, whatever you + would have used in your code to control what is compiled when can be + used in this file for the same purpose. The following defines are in + use at the time this file was written: + + FLAT - Used to indicate a NT/DOS7 build + i386 - Intel i386/i486 build + MIPS - MIPS R3000/R4000 build + ALPHA - DEC Alpha build + DBG - Used to control Debug/Retail. Set to 1 if Debug, + 0 if Retail. + WIN31 - Win16 build + __OS2__ - OS/2 build (used by CT mostly) + + If none of these are used, it is assumed the entire file can be used + for all builds. + +#endif + +LIBRARY ole2u32a + +DESCRIPTION 'ole2u32a' + +EXPORTS + + SetDCToAnisotropic + SetDCToDrawInHimetricRect + ResetOrigDC + XformRectInPixelsToHimetric + XformRectInHimetricToPixels + XformSizeInPixelsToHimetric + XformSizeInHimetricToPixels + XformWidthInHimetricToPixels + XformWidthInPixelsToHimetric + XformHeightInHimetricToPixels + XformHeightInPixelsToHimetric + ParseCmdLine + OleStdIsOleLink + OleStdQueryInterface + OleStdCreateRootStorage + OleStdOpenRootStorage + OleStdOpenOrCreateRootStorage + OleStdCreateChildStorage + OleStdOpenChildStorage + OleStdCommitStorage + OleStdCreateStorageOnHGlobal + OleStdCreateTempStorage + OleStdDoConvert + OleStdGetTreatAsFmtUserType + OleStdDoTreatAsClass + OleStdSetupAdvises + OleStdSwitchDisplayAspect + OleStdSetIconInCache + OleStdGetData + OleStdMarkPasteEntryList + OleStdGetPriorityClipboardFormat + OleStdIsDuplicateFormat + OleStdRegisterAsRunning + OleStdRevokeAsRunning + OleStdNoteFileChangeTime + OleStdNoteObjectChangeTime + OleStdGetOleObjectData + OleStdGetLinkSourceData + OleStdGetObjectDescriptorData + OleStdGetObjectDescriptorDataFromOleObject + OleStdFillObjectDescriptorFromData + OleStdGetMetafilePictFromOleObject + OleStdCreateTempFileMoniker + OleStdGetFirstMoniker + OleStdGetLenFilePrefixOfMoniker + OleStdMalloc + OleStdRealloc + OleStdFree + OleStdGetSize + OleStdFreeString + OleStdCopyString + OleStdGetItemToken + OleStdInitVtbl + OleStdCheckVtbl + OleStdVerifyRelease + OleStdRelease + OleStdCreateDC + OleStdCreateIC + OleStdDeleteTargetDevice + OleStdCopyTargetDevice + OleStdCopyFormatEtc + FnAssert + OleDbgPrint + OleDbgPrintAlways + OleDbgSetDbgLevel + OleDbgGetDbgLevel + OleDbgIndent + OleDbgPrintRefCnt + OleDbgPrintRefCntAlways + OleDbgPrintRect + OleDbgPrintRectAlways + OleDbgPrintScodeAlways + OleUIInitialize + OleUIUnInitialize + OleUIAddVerbMenu + OleUIMetafilePictIconFree + OleUIMetafilePictIconDraw + OleUIMetafilePictExtractLabel + OleUIMetafilePictExtractIcon + OleUIMetafilePictExtractIconSource + OleUIInsertObject + OleUIPasteSpecial + OleUIEditLinks + OleUIChangeIcon + OleUIConvert + OleUIBusy + OleUIUpdateLinks + OleUIDrawHandles + OleUICanConvertOrActivateAs + OleUIDrawShading + OleUIShowObject + OleUIPromptUser + RegisterHatchWindowClass + CreateHatchWindow + GetHatchWidth + GetHatchRect + SetHatchRect + SetHatchWindowSize + OleStdEnumFmtEtc_Create + OleStdGetAuxUserType + OleStdGetUserTypeOfClass + OleStdIconLabelTextOut + OleStdMsgFilter_Create + OleStdMsgFilter_SetInComingCallStatus + OleStdMsgFilter_GetInComingCallStatus + OleStdMsgFilter_EnableBusyDialog + OleStdMsgFilter_EnableNotRespondingDialog + OleStdMsgFilter_SetParentWindow + OleStdGetMiscStatusOfClass + OleStdGetDefaultFileFormatOfClass + OleStdDestroyAllElements + OleStdCreateDbAlloc + OleStdInitSummaryInfo + OleStdFreeSummaryInfo + OleStdClearSummaryInfo + OleStdReadSummaryInfo + OleStdWriteSummaryInfo + OleStdGetSecurityProperty + OleStdSetSecurityProperty + OleStdGetStringProperty + OleStdSetStringProperty + OleStdGetStringZProperty + OleStdGetDocProperty + OleStdSetDocProperty + OleStdGetThumbNailProperty + OleStdSetThumbNailProperty + OleStdGetDateProperty + OleStdSetDateProperty + OleStdMsgFilter_SetHandleInComingCallbackProc + OleStdEnumStatData_Create + OleStdCopyStatData + OleStdCreateStandardPalette + OleStdMkParseDisplayName + CopyAndFreeOLESTR + CopyAndFreeSTR + CreateOLESTR + CreateSTR + CLSIDFromStringA + CLSIDFromProgIDA + CreateFileMonikerA + CreateItemMonikerA + GetClassFileA + MkParseDisplayNameA + OleCreateFromFileA + OleCreateLinkToFileA + OleGetIconOfClassA + OleGetIconOfFileA + OleMetafilePictFromIconAndLabelA + OleRegGetUserTypeA + ProgIDFromCLSIDA + ReadFmtUserTypeStgA + StgCreateDocfileA + StgOpenStorageA + StgSetTimesA + StringFromCLSIDA + WriteFmtUserTypeStgA + CallIMonikerGetDisplayNameA + CallIOleLinkGetSourceDisplayNameA + CallIOleLinkSetSourceDisplayNameA + CallIOleInPlaceFrameSetStatusTextA + CallIOleInPlaceUIWindowSetActiveObjectA + CallIOleObjectGetUserTypeA + CallIOleObjectSetHostNamesA + CallIStorageCreateStorageA + CallIStorageDestroyElementA + CallIStorageOpenStorageA + CallIStorageCreateStreamA + CallIStorageOpenStreamA diff --git a/private/oleutest/letest/ole2ui/daytona/ole2ui.src b/private/oleutest/letest/ole2ui/daytona/ole2ui.src new file mode 100644 index 000000000..24b82dcf6 --- /dev/null +++ b/private/oleutest/letest/ole2ui/daytona/ole2ui.src @@ -0,0 +1,199 @@ +#if 0 + + Microsoft Windows + Copyright (C) Microsoft Corporation, 1992 - 1992. + All rights reserved. + + This .def file is preprocessed by the compiler to create the version for + the current build in the appropriate subdir. Basically, whatever you + would have used in your code to control what is compiled when can be + used in this file for the same purpose. The following defines are in + use at the time this file was written: + + FLAT - Used to indicate a NT/DOS7 build + i386 - Intel i386/i486 build + MIPS - MIPS R3000/R4000 build + ALPHA - DEC Alpha build + DBG - Used to control Debug/Retail. Set to 1 if Debug, + 0 if Retail. + WIN31 - Win16 build + __OS2__ - OS/2 build (used by CT mostly) + + If none of these are used, it is assumed the entire file can be used + for all builds. + +#endif + +LIBRARY ole2ui + +DESCRIPTION 'ole2ui' + +EXPORTS + + SetDCToAnisotropic + SetDCToDrawInHimetricRect + ResetOrigDC + XformRectInPixelsToHimetric + XformRectInHimetricToPixels + XformSizeInPixelsToHimetric + XformSizeInHimetricToPixels + XformWidthInHimetricToPixels + XformWidthInPixelsToHimetric + XformHeightInHimetricToPixels + XformHeightInPixelsToHimetric + ParseCmdLine + OleStdIsOleLink + OleStdQueryInterface + OleStdCreateRootStorage + OleStdOpenRootStorage + OleStdOpenOrCreateRootStorage + OleStdCreateChildStorage + OleStdOpenChildStorage + OleStdCommitStorage + OleStdCreateStorageOnHGlobal + OleStdCreateTempStorage + OleStdDoConvert + OleStdGetTreatAsFmtUserType + OleStdDoTreatAsClass + OleStdSetupAdvises + OleStdSwitchDisplayAspect + OleStdSetIconInCache + OleStdGetData + OleStdMarkPasteEntryList + OleStdGetPriorityClipboardFormat + OleStdIsDuplicateFormat + OleStdRegisterAsRunning + OleStdRevokeAsRunning + OleStdNoteFileChangeTime + OleStdNoteObjectChangeTime + OleStdGetOleObjectData + OleStdGetLinkSourceData + OleStdGetObjectDescriptorData + OleStdGetObjectDescriptorDataFromOleObject + OleStdFillObjectDescriptorFromData + OleStdGetMetafilePictFromOleObject + OleStdCreateTempFileMoniker + OleStdGetFirstMoniker + OleStdGetLenFilePrefixOfMoniker + OleStdMalloc + OleStdRealloc + OleStdFree + OleStdGetSize + OleStdFreeString + OleStdCopyString + OleStdGetItemToken + OleStdInitVtbl + OleStdCheckVtbl + OleStdVerifyRelease + OleStdRelease + OleStdCreateDC + OleStdCreateIC + OleStdDeleteTargetDevice + OleStdCopyTargetDevice + OleStdCopyFormatEtc + OleDbgPrint + OleDbgPrintAlways + OleDbgSetDbgLevel + OleDbgGetDbgLevel + OleDbgIndent + OleDbgPrintRefCnt + OleDbgPrintRefCntAlways + OleDbgPrintRect + OleDbgPrintRectAlways + OleDbgPrintScodeAlways + OleUIInitialize + OleUIUnInitialize + OleUIAddVerbMenu + OleUIMetafilePictIconFree + OleUIMetafilePictIconDraw + OleUIMetafilePictExtractLabel + OleUIMetafilePictExtractIcon + OleUIMetafilePictExtractIconSource + OleUIInsertObject + OleUIPasteSpecial + OleUIEditLinks + OleUIChangeIcon + OleUIConvert + OleUIBusy + OleUIUpdateLinks + OleUIDrawHandles + OleUICanConvertOrActivateAs + OleUIDrawShading + OleUIShowObject + OleUIPromptUser + RegisterHatchWindowClass + CreateHatchWindow + GetHatchWidth + GetHatchRect + SetHatchRect + SetHatchWindowSize + OleStdEnumFmtEtc_Create + OleStdGetAuxUserType + OleStdGetUserTypeOfClass + OleStdIconLabelTextOut + OleStdMsgFilter_Create + OleStdMsgFilter_SetInComingCallStatus + OleStdMsgFilter_GetInComingCallStatus + OleStdMsgFilter_EnableBusyDialog + OleStdMsgFilter_EnableNotRespondingDialog + OleStdMsgFilter_SetParentWindow + OleStdGetMiscStatusOfClass + OleStdGetDefaultFileFormatOfClass + OleStdDestroyAllElements + OleStdCreateDbAlloc + OleStdInitSummaryInfo + OleStdFreeSummaryInfo + OleStdClearSummaryInfo + OleStdReadSummaryInfo + OleStdWriteSummaryInfo + OleStdGetSecurityProperty + OleStdSetSecurityProperty + OleStdGetStringProperty + OleStdSetStringProperty + OleStdGetStringZProperty + OleStdGetDocProperty + OleStdSetDocProperty + OleStdGetThumbNailProperty + OleStdSetThumbNailProperty + OleStdGetDateProperty + OleStdSetDateProperty + OleStdMsgFilter_SetHandleInComingCallbackProc + OleStdEnumStatData_Create + OleStdCopyStatData + OleStdCreateStandardPalette + OleStdMkParseDisplayName + CopyAndFreeOLESTR + CopyAndFreeSTR + CreateOLESTR + CreateSTR + CLSIDFromStringA + CLSIDFromProgIDA + CreateFileMonikerA + CreateItemMonikerA + GetClassFileA + MkParseDisplayNameA + OleCreateFromFileA + OleCreateLinkToFileA + OleGetIconOfClassA + OleGetIconOfFileA + OleMetafilePictFromIconAndLabelA + OleRegGetUserTypeA + ProgIDFromCLSIDA + ReadFmtUserTypeStgA + StgCreateDocfileA + StgOpenStorageA + StgSetTimesA + StringFromCLSIDA + WriteFmtUserTypeStgA + CallIMonikerGetDisplayNameA + CallIOleLinkGetSourceDisplayNameA + CallIOleLinkSetSourceDisplayNameA + CallIOleInPlaceFrameSetStatusTextA + CallIOleInPlaceUIWindowSetActiveObjectA + CallIOleObjectGetUserTypeA + CallIOleObjectSetHostNamesA + CallIStorageCreateStorageA + CallIStorageDestroyElementA + CallIStorageOpenStorageA + CallIStorageCreateStreamA + CallIStorageOpenStreamA diff --git a/private/oleutest/letest/ole2ui/daytona/sources b/private/oleutest/letest/ole2ui/daytona/sources new file mode 100644 index 000000000..91c6ca237 --- /dev/null +++ b/private/oleutest/letest/ole2ui/daytona/sources @@ -0,0 +1,64 @@ + +MAJORCOMP = cairole +MINORCOMP = com + +TARGETNAME= ole2u32a +TARGETPATH= obj +TARGETTYPE= DYNLINK + +DLLDEF= obj\*\ole2u32a.def +DLLENTRY= DllEntryPoint +DLLBASE=@$(BASEDIR)\PUBLIC\SDK\LIB\coffbase.txt,usermode + +INCLUDES=.. + +C_DEFINES=-DWIN32 -DDEBUG -DINC_OLE2 -DCLIENT -DWINDOWS -DOLE201 + +SOURCES= \ + ..\BUSY.C \ + ..\COMMON.C \ + ..\CONVERT.C \ + ..\DBALLOC.CPP \ + ..\DBGUTIL.C \ + ..\DLLENTRY.C \ + ..\DLLFUNCS.C \ + ..\DRAWICON.C \ + ..\ENUMFETC.C \ + ..\ENUMSTAT.C \ + ..\GETICON.C \ + ..\HATCH.C \ + ..\ICON.C \ + ..\ICONBOX.C \ + ..\INSOBJ.C \ + ..\LINKS.C \ + ..\MSGFILTR.C \ + ..\OBJFDBK.C \ + ..\OLE2UI.C \ + ..\OLESTD.C \ + ..\OLETHUNK.C \ + ..\OLEUTL.C \ + ..\PASTESPL.C \ + ..\PRECOMP.C \ + ..\REGDB.C \ + ..\RESIMAGE.C \ + ..\STDPAL.C \ + ..\SUMINFO.CPP \ + ..\TARGTDEV.C \ + ..\UTILITY.C \ + ..\OLE2UI.RC + +UMTYPE=windows + +TARGETLIBS= \ + $(BASEDIR)\public\sdk\lib\*\ole32.lib \ + $(BASEDIR)\public\sdk\lib\*\shell32.lib \ + $(BASEDIR)\public\sdk\lib\*\gdi32.lib \ + $(BASEDIR)\public\sdk\lib\*\kernel32.lib \ + $(BASEDIR)\public\sdk\lib\*\user32.lib \ + $(BASEDIR)\public\sdk\lib\*\advapi32.lib \ + $(BASEDIR)\public\sdk\lib\*\comdlg32.lib \ + $(BASEDIR)\public\sdk\lib\*\uuid.lib + +USE_CRTDLL= 1 + +MISCFILES=..\..\data\letest12.olc diff --git a/private/oleutest/letest/ole2ui/dballoc.cpp b/private/oleutest/letest/ole2ui/dballoc.cpp new file mode 100644 index 000000000..b62259c64 --- /dev/null +++ b/private/oleutest/letest/ole2ui/dballoc.cpp @@ -0,0 +1,900 @@ + +/*** +*dballoc.cpp +* +* Copyright (C) 1992-93, Microsoft Corporation. All Rights Reserved. +* +*Purpose: +* This file contains a debug implementation of the IMalloc interface. +* +* This implementation is basically a simple wrapping of the C runtime, +* with additional work to detect memory leakage, and memory overwrite. +* +* Leakage is detected by tracking each allocation in an address +* instance table, and then checking to see if the table is empty +* when the last reference to the allocator is released. +* +* Memory overwrite is detected by placing a signature at the end +* of every allocated block, and checking to make sure the signature +* is unchanged when the block is freed. +* +* This implementation also has additional param validation code, as +* well as additional check make sure that instances that are passed +* to Free() were actually allocated by the corresponding instance +* of the allocator. +* +* +* Creating an instance of this debug allocator that uses the default +* output interface would look like the following, +* +* +* BOOL init_application_instance() +* { +* HRESULT hresult; +* IMalloc FAR* pmalloc; +* +* pmalloc = NULL; +* +* if((hresult = OleStdCreateDbAlloc(0,&pmalloc))!=NOERROR) +* goto LReturn; +* +* hresult = OleInitialize(pmalloc); +* +* // release pmalloc to let OLE hold the only ref to the it. later +* // when OleUnitialize is called, memory leaks will be reported. +* if(pmalloc != NULL) +* pmalloc->Release(); +* +* LReturn: +* +* return (hresult == NOERROR) ? TRUE : FALSE; +* } +* +* +* CONSIDER: could add an option to force error generation, something +* like DBALLOC_ERRORGEN +* +* CONSIDER: add support for heap-checking. say for example, +* DBALLOC_HEAPCHECK would do a heapcheck every free? every 'n' +* calls to free? ... +* +* +*Implementation Notes: +* +* The method IMalloc::DidAlloc() is allowed to always return +* "Dont Know" (-1). This method is called by Ole, and they take +* some appropriate action when they get this answer. + +The debugging allocator has the option to catch bugs where code is writing off +the end of allocated memory. This is implemented by using NT's virtual memory +services. To switch on this option, use + +#define DBALLOC_POWERDEBUG + +Note it will ONLY WORK ON NT. This option consumes a very large amount of +memory. Basically, for every allocation, it cooks the allocation so that the +end of the allocation will fall on a page boundary. An extra page of memory +is allocated after the requested memory. The protection bits for this page +are altered so that it is an error to read or write to it. Any incident of +writing past the end of allocated memory is trapped at the point of the error. + +This consumes a great deal of memory because at least two pages must be +allocated for each allocation. +* +*****************************************************************************/ + + +// Note: this file is designed to be stand-alone; it includes a +// carefully chosen, minimal set of headers. +// +// For conditional compilation we use the ole2 conventions, +// _MAC = mac +// WIN32 = Win32 (NT really) +// = defaults to Win16 + + +// REVIEW: the following needs to modified to handle _MAC +#define STRICT +#ifndef INC_OLE2 + #define INC_OLE2 +#endif + +#include + +#include "ole2.h" + +#if defined( __TURBOC__) +#define __STDC__ (1) +#endif + +#define WINDLL 1 // make far pointer version of stdargs.h +#include + +#if defined( __TURBOC__) +#undef __STDC__ +#endif + +#include +#include +#include +#include +#include + +#include "dballoc.h" + + +#define DIM(X) (sizeof(X)/sizeof((X)[0])) + +#define UNREACHED 0 + +#if defined(WIN32) +# define MEMCMP(PV1, PV2, CB) memcmp((PV1), (PV2), (CB)) +# define MEMCPY(PV1, PV2, CB) memcpy((PV1), (PV2), (CB)) +# define MEMSET(PV, VAL, CB) memset((PV), (VAL), (CB)) +# define MALLOC(CB) malloc(CB) +# define REALLOC(PV, CB) realloc((PV), (CB)) +# define FREE(PV) free(PV) + +#ifndef WIN32 +# define HEAPMIN() _heapmin() +#else +# define HEAPMIN() +#endif + +#elif defined(_MAC) +# define MEMCMP(PV1, PV2) ERROR -- NYI +# define MEMCPY(PV1, PV2, CB) ERROR -- NYI +# define MEMSET(PV, VAL, CB) ERROR -- NYI +# define MALLOC(CB) ERROR -- NYI +# define REALLOC(PV, CB) ERROR -- NYI +# define FREE(PV) ERROR -- NYI +# define HEAPMIN() ERROR -- NYI +#else +# define MEMCMP(PV1, PV2, CB) _fmemcmp((PV1), (PV2), (CB)) +# define MEMCPY(PV1, PV2, CB) _fmemcpy((PV1), (PV2), (CB)) +# define MEMSET(PV, VAL, CB) _fmemset((PV), (VAL), (CB)) +# define MALLOC(CB) _fmalloc(CB) +# define REALLOC(PV, CB) _frealloc(PV, CB) +# define FREE(PV) _ffree(PV) +# define HEAPMIN() _fheapmin() +#endif + +#if defined( __TURBOC__ ) +#define classmodel _huge +#else +#define classmodel FAR +#endif + +class classmodel CStdDbOutput : public IDbOutput { +public: + static IDbOutput FAR* Create(); + + // IUnknown methods + + STDMETHOD(QueryInterface)(REFIID riid, void FAR* FAR* ppv); + STDMETHOD_(ULONG, AddRef)(void); + STDMETHOD_(ULONG, Release)(void); + + + // IDbOutput methods + + STDMETHOD_(void, Printf)(TCHAR FAR* szFmt, ...); + + STDMETHOD_(void, Assertion)( + BOOL cond, + TCHAR FAR* szExpr, + TCHAR FAR* szFile, + UINT uLine, + TCHAR FAR* szMsg); + + + void FAR* operator new(size_t cb){ + return MALLOC(cb); + } + void operator delete(void FAR* pv){ + FREE(pv); + } + + CStdDbOutput(){ + m_refs = 0; + } + +private: + ULONG m_refs; + + TCHAR m_rgch[128]; // buffer for output formatting +}; + + +//--------------------------------------------------------------------- +// implementation of the debug allocator +//--------------------------------------------------------------------- + +class FAR CAddrNode +{ +public: + void FAR* m_pv; // instance + ULONG m_cb; // size of allocation in BYTES + ULONG m_nAlloc; // the allocation pass count + CAddrNode FAR* m_next; + + void FAR* operator new(size_t cb){ + return MALLOC(cb); + } + void operator delete(void FAR* pv){ + FREE(pv); + } +}; + + +class classmodel CDbAlloc : public IMalloc +{ +public: + static HRESULT Create( + ULONG options, IDbOutput FAR* pdbout, IMalloc FAR* FAR* ppmalloc); + + // IUnknown methods + + STDMETHOD(QueryInterface)(REFIID riid, void FAR* FAR* ppv); + STDMETHOD_(ULONG, AddRef)(void); + STDMETHOD_(ULONG, Release)(void); + + // IMalloc methods + + STDMETHOD_(void FAR*, Alloc)(ULONG cb); + STDMETHOD_(void FAR*, Realloc)(void FAR* pv, ULONG cb); + STDMETHOD_(void, Free)(void FAR* pv); + STDMETHOD_(ULONG, GetSize)(void FAR* pv); + STDMETHOD_(int, DidAlloc)(void FAR* pv); + STDMETHOD_(void, HeapMinimize)(void); + + + void FAR* operator new(size_t cb){ + return MALLOC(cb); + } + void operator delete(void FAR* pv){ + FREE(pv); + } + + CDbAlloc(){ + m_refs = 1; + m_pdbout = NULL; + m_cAllocCalls = 0; + m_nBreakAtNthAlloc = 0; + m_nBreakAtAllocSize = 0; + MEMSET(m_rganode, 0, sizeof(m_rganode)); +#ifdef DBALLOC_POWERDEBUG + { + SYSTEM_INFO si; + + GetSystemInfo(&si); + m_virtPgSz = si.dwPageSize; + } +#endif // DBALLOC_POWERDEBUG + } + +private: + + ULONG m_refs; + ULONG m_cAllocCalls; // total count of allocation calls + ULONG m_nBreakAtNthAlloc; // allocation number to break to debugger + // this value should be set typically in the + // debugger. + ULONG m_nBreakAtAllocSize; // allocation size to break to debugger + // this value should be set typically in the + // debugger. + IDbOutput FAR* m_pdbout; // output interface + CAddrNode FAR* m_rganode[64]; // address instance table + + + // instance table methods + + BOOL IsEmpty(void); + + void AddInst(void FAR* pv, ULONG nAlloc, ULONG cb); + void DelInst(void FAR* pv); + CAddrNode FAR* GetInst(void FAR* pv); + + void DumpInst(CAddrNode FAR* pn); + void DumpInstTable(void); + + inline UINT HashInst(void FAR* pv) const { + return ((UINT)((ULONG)pv >> 4)) % DIM(m_rganode); + + } + + // output method(s) + + inline void Assertion( + BOOL cond, + TCHAR FAR* szExpr, + TCHAR FAR* szFile, + UINT uLine, + TCHAR FAR* szMsg) + { + m_pdbout->Assertion(cond, szExpr, szFile, uLine, szMsg); + } + + #define ASSERT(X) Assertion(X, TEXT(#X), TEXT(__FILE__), __LINE__, NULL) + + #define ASSERTSZ(X, SZ) Assertion(X, TEXT(#X), TEXT(__FILE__), __LINE__, SZ) + + static const BYTE m_rgchSig[]; + +#ifdef DBALLOC_POWERDEBUG + size_t m_virtPgSz; +#endif // DBALLOC_POWERDEBUG +}; + +const BYTE CDbAlloc::m_rgchSig[] = { 0xDE, 0xAD, 0xBE, 0xEF }; + + +/*** +*HRESULT OleStdCreateDbAlloc(ULONG reserved, IMalloc** ppmalloc) +* Purpose: +* Create an instance of CDbAlloc -- a debug implementation +* of IMalloc. +* +* Parameters: +* ULONG reserved - reserved for future use. must be 0. +* IMalloc FAR* FAR* ppmalloc - (OUT) pointer to an IMalloc interface +* of new debug allocator object +* Returns: +* HRESULT +* NOERROR - if no error. +* E_OUTOFMEMORY - allocation failed. +* +***********************************************************************/ +STDAPI OleStdCreateDbAlloc(ULONG reserved,IMalloc FAR* FAR* ppmalloc) +{ + return CDbAlloc::Create(reserved, NULL, ppmalloc); +} + + +HRESULT +CDbAlloc::Create( + ULONG options, + IDbOutput FAR* pdbout, + IMalloc FAR* FAR* ppmalloc) +{ + HRESULT hresult; + CDbAlloc FAR* pmalloc; + + + // default the instance of IDbOutput if the user didn't supply one + if(pdbout == NULL && ((pdbout = CStdDbOutput::Create()) == NULL)){ + hresult = ResultFromScode(E_OUTOFMEMORY); + goto LError0; + } + + pdbout->AddRef(); + + if((pmalloc = new FAR CDbAlloc()) == NULL){ + hresult = ResultFromScode(E_OUTOFMEMORY); + goto LError1; + } + + pmalloc->m_pdbout = pdbout; + + *ppmalloc = pmalloc; + + return NOERROR; + +LError1:; + pdbout->Release(); + pmalloc->Release(); + +LError0:; + return hresult; +} + +STDMETHODIMP +CDbAlloc::QueryInterface(REFIID riid, void FAR* FAR* ppv) +{ + if(IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IMalloc)){ + *ppv = this; + AddRef(); + return NOERROR; + } + return ResultFromScode(E_NOINTERFACE); +} + +STDMETHODIMP_(ULONG) +CDbAlloc::AddRef() +{ + return ++m_refs; +} + +STDMETHODIMP_(ULONG) +CDbAlloc::Release() +{ + if(--m_refs == 0){ + + // check for memory leakage + if(IsEmpty()){ + m_pdbout->Printf(TEXT("No Memory Leaks.\n")); + }else{ + m_pdbout->Printf(TEXT("Memory Leak Detected,\n")); + DumpInstTable(); + } + + m_pdbout->Release(); + delete this; + return 0; + } + return m_refs; +} + +STDMETHODIMP_(void FAR*) +CDbAlloc::Alloc(ULONG cb) +{ + size_t size; + void FAR* pv; + + ++m_cAllocCalls; + + if (m_nBreakAtNthAlloc && m_cAllocCalls == m_nBreakAtNthAlloc) { + ASSERTSZ(FALSE, TEXT("DBALLOC: NthAlloc Break target reached\r\n")); + } else if (m_nBreakAtAllocSize && cb == m_nBreakAtAllocSize) { + ASSERTSZ(FALSE, TEXT("DBALLOC: AllocSize Break target reached\r\n")); + } + +#ifndef DBALLOC_POWERDEBUG + // REVIEW: need to add support for huge allocations (on win16) + if((cb + sizeof(m_rgchSig)) > UINT_MAX) + return NULL; + + size = (size_t)cb; + + if((pv = MALLOC(size + sizeof(m_rgchSig))) == NULL) + return NULL; + + // set allocated block to some non-zero value + MEMSET(pv, -1, size); + + // put signature at end of allocated block + MEMCPY(((char FAR*)pv) + size, m_rgchSig, sizeof(m_rgchSig)); + + AddInst(pv, m_cAllocCalls, size); +#else + // for each allocate, allocate the amount of memory required, and + // one more page beyond that. We will change the protection bits of + // the trailing page so that we get an access violation if someone + // writes beyond the end of their allocated memory + { + size_t allocpgs; // number of pages to allocate + DWORD dwOldProt; // previous protection of the last page + void *plastpg; // points to the beginning of the last page + + // allocate at least one page for the allocation, and + // one to go after it + allocpgs = (cb + 2*m_virtPgSz) / m_virtPgSz; + pv = VirtualAlloc(NULL, allocpgs*m_virtPgSz, + MEM_COMMIT, PAGE_READWRITE); + + // change the protection of the last page + plastpg = (void *)(((BYTE *)pv)+m_virtPgSz*(allocpgs-1)); + VirtualProtect(plastpg, m_virtPgSz, PAGE_NOACCESS, &dwOldProt); + + // figure out what pointer to return to the user + pv = (void *)(((BYTE *)plastpg)-cb); + + // record the allocation + AddInst(pv, m_cAllocCalls, cb); + } +#endif // DBALLOC_POWERDEBUG + + return pv; +} + +STDMETHODIMP_(void FAR*) +CDbAlloc::Realloc(void FAR* pv, ULONG cb) +{ + size_t size; + CAddrNode *pcan; + +#ifndef DBALLOC_POWERDEBUG + // REVIEW: need to add support for huge realloc + if((cb + sizeof(m_rgchSig)) > UINT_MAX) + return NULL; +#endif // DBALLOC_POWERDEBUG + + if(pv == NULL){ + return Alloc(cb); + } + + ++m_cAllocCalls; + + ASSERT((pcan = GetInst(pv)) != NULL); +#ifndef DBALLOC_POWERDEBUG + + DelInst(pv); + + if(cb == 0){ + Free(pv); + return NULL; + } + + size = (size_t)cb; + + if((pv = REALLOC(pv, size + sizeof(m_rgchSig))) == NULL) + return NULL; + + // put signature at end of allocated block + MEMCPY(((char FAR*)pv) + size, m_rgchSig, sizeof(m_rgchSig)); + + AddInst(pv, m_cAllocCalls, size); +#else + { + void *pnew; + DWORD dwOldProt; + + // allocate new memory + pnew = Alloc(cb); + + // copy in the previous material + memcpy(pnew, pcan->m_pv, pcan->m_cb); + + // protect the old memory + VirtualProtect(pcan->m_pv, pcan->m_cb, PAGE_NOACCESS, + &dwOldProt); + + DelInst(pv); + AddInst(pv, m_cAllocCalls, cb); + pv = pnew; + } +#endif // DBALLOC_POWERDEBUG + + return pv; +} + +STDMETHODIMP_(void) +CDbAlloc::Free(void FAR* pv) +{ + if (pv == NULL) + { + // Free of NULL is a NO-OP + return; + } + + CAddrNode FAR* pn; + static TCHAR szSigMsg[] = TEXT("Signature Check Failed"); + + pn = GetInst(pv); + + // check for attempt to free an instance we didnt allocate + if(pn == NULL){ + ASSERTSZ(FALSE, TEXT("pointer freed by wrong allocator")); + return; + } + +#ifndef DBALLOC_POWERDEBUG + // verify the signature + if(MEMCMP(((char FAR*)pv) + pn->m_cb, m_rgchSig, sizeof(m_rgchSig)) != 0){ + m_pdbout->Printf(szSigMsg); m_pdbout->Printf(TEXT("\n")); + DumpInst(GetInst(pv)); + ASSERTSZ(FALSE, szSigMsg); + } + + // stomp on the contents of the block + MEMSET(pv, 0xCC, ((size_t)pn->m_cb + sizeof(m_rgchSig))); + + DelInst(pv); + FREE(pv); +#else + { + DWORD dwOldProt; + + // make the block inaccessible + VirtualProtect(pv, pn->m_cb, PAGE_NOACCESS, &dwOldProt); + DelInst(pv); + } +#endif // DBALLOC_POWERDEBUG +} + + +STDMETHODIMP_(ULONG) +CDbAlloc::GetSize(void FAR* pv) +{ + CAddrNode FAR* pn; + + if (pv == NULL) + { + // GetSize is supposed to return a -1 when NULL is passed in. + return (ULONG) -1; + } + + pn = GetInst(pv); + + if (pn == NULL) { + ASSERT(pn != NULL); + return 0; + } + + return pn->m_cb; +} + + +/*** +*PUBLIC HRESULT CDbAlloc::DidAlloc +*Purpose: +* Answer if the given address belongs to a block allocated by +* this allocator. +* +*Entry: +* pv = the instance to lookup +* +*Exit: +* return value = int +* 1 - did alloc +* 0 - did *not* alloc +* -1 - dont know (according to the ole2 spec it is always legal +* for the allocator to answer "dont know") +* +***********************************************************************/ +STDMETHODIMP_(int) +CDbAlloc::DidAlloc(void FAR* pv) +{ + return -1; // answer "I dont know" +} + + +STDMETHODIMP_(void) +CDbAlloc::HeapMinimize() +{ + HEAPMIN(); +} + + +//--------------------------------------------------------------------- +// instance table methods +//--------------------------------------------------------------------- + +/*** +*PRIVATE CDbAlloc::AddInst +*Purpose: +* Add the given instance to the address instance table. +* +*Entry: +* pv = the instance to add +* nAlloc = the allocation passcount of this instance +* +*Exit: +* None +* +***********************************************************************/ +void +CDbAlloc::AddInst(void FAR* pv, ULONG nAlloc, ULONG cb) +{ + UINT hash; + CAddrNode FAR* pn; + + + ASSERT(pv != NULL); + + pn = (CAddrNode FAR*)new FAR CAddrNode(); + + if (pn == NULL) { + ASSERT(pn != NULL); + return; + } + + pn->m_pv = pv; + pn->m_cb = cb; + pn->m_nAlloc = nAlloc; + + hash = HashInst(pv); + pn->m_next = m_rganode[hash]; + m_rganode[hash] = pn; +} + + +/*** +*UNDONE +*Purpose: +* Remove the given instance from the address instance table. +* +*Entry: +* pv = the instance to remove +* +*Exit: +* None +* +***********************************************************************/ +void +CDbAlloc::DelInst(void FAR* pv) +{ + CAddrNode FAR* FAR* ppn, FAR* pnDead; + + for(ppn = &m_rganode[HashInst(pv)]; *ppn != NULL; ppn = &(*ppn)->m_next){ + if((*ppn)->m_pv == pv){ + pnDead = *ppn; + *ppn = (*ppn)->m_next; + delete pnDead; + // make sure it doesnt somehow appear twice + ASSERT(GetInst(pv) == NULL); + return; + } + } + + // didnt find the instance + ASSERT(UNREACHED); +} + + +CAddrNode FAR* +CDbAlloc::GetInst(void FAR* pv) +{ + CAddrNode FAR* pn; + + for(pn = m_rganode[HashInst(pv)]; pn != NULL; pn = pn->m_next){ + if(pn->m_pv == pv) + return pn; + } + return NULL; +} + + +void +CDbAlloc::DumpInst(CAddrNode FAR* pn) +{ + if (pn == NULL) + return; + + m_pdbout->Printf(TEXT("[0x%lx] nAlloc=%ld size=%ld\n"), + pn->m_pv, pn->m_nAlloc, GetSize(pn->m_pv)); +} + + +/*** +*PRIVATE BOOL IsEmpty +*Purpose: +* Answer if the address instance table is empty. +* +*Entry: +* None +* +*Exit: +* return value = BOOL, TRUE if empty, FALSE otherwise +* +***********************************************************************/ +BOOL +CDbAlloc::IsEmpty() +{ + UINT u; + + for(u = 0; u < DIM(m_rganode); ++u){ + if(m_rganode[u] != NULL) + return FALSE; + } + + return TRUE; +} + + +/*** +*PRIVATE CDbAlloc::Dump +*Purpose: +* Print the current contents of the address instance table, +* +*Entry: +* None +* +*Exit: +* None +* +***********************************************************************/ +void +CDbAlloc::DumpInstTable() +{ + UINT u; + CAddrNode FAR* pn; + + for(u = 0; u < DIM(m_rganode); ++u){ + for(pn = m_rganode[u]; pn != NULL; pn = pn->m_next){ + DumpInst(pn); + } + } +} + + +//--------------------------------------------------------------------- +// implementation of CStdDbOutput +//--------------------------------------------------------------------- + +IDbOutput FAR* +CStdDbOutput::Create() +{ + return (IDbOutput FAR*)new FAR CStdDbOutput(); +} + +STDMETHODIMP +CStdDbOutput::QueryInterface(REFIID riid, void FAR* FAR* ppv) +{ + if(IsEqualIID(riid, IID_IUnknown)) + { + *ppv = this; + AddRef(); + return NOERROR; + } + return ResultFromScode(E_NOINTERFACE); +} + +STDMETHODIMP_(ULONG) +CStdDbOutput::AddRef() +{ + return ++m_refs; +} + +STDMETHODIMP_(ULONG) +CStdDbOutput::Release() +{ + if(--m_refs == 0){ + delete this; + return 0; + } + return m_refs; +} + +STDMETHODIMP_(void) +CStdDbOutput::Printf(TCHAR FAR* lpszFmt, ...) +{ + va_list args; + TCHAR szBuf[256]; +#if defined( OBSOLETE ) + TCHAR *pn, FAR* pf; +static TCHAR rgchFmtBuf[128]; +static TCHAR rgchOutputBuf[128]; + + // copy the 'far' format string to a near buffer so we can use + // a medium model vsprintf, which only supports near data pointers. + // + pn = rgchFmtBuf, pf=szFmt; + while(*pf != TEXT('\0')) + *pn++ = *pf++; + *pn = TEXT('\0'); +#endif + + va_start(args, lpszFmt); + +// wvsprintf(rgchOutputBuf, rgchFmtBuf, args); + wvsprintf(szBuf, lpszFmt, args); + + OutputDebugString(szBuf); +} + +STDMETHODIMP_(void) +CStdDbOutput::Assertion( + BOOL cond, + TCHAR FAR* szExpr, + TCHAR FAR* szFile, + UINT uLine, + TCHAR FAR* szMsg) +{ + if(cond) + return; + +#ifdef _DEBUG + // following is from compobj.dll (ole2) + #ifdef UNICODE + #ifndef NOASSERT + FnAssert(szExpr, szMsg, szFile, uLine); + #endif + #else + // we need to talk to comobj in UNICODE even though we are not defined + // as UNICODE + { + WCHAR wszExpr[255], wszMsg[255], wszFile[255]; + mbstowcs(wszExpr, szExpr, 255); + mbstowcs(wszMsg, szMsg, 255); + mbstowcs(wszFile, szFile, 255); + #ifndef NOASSERT + FnAssert(wszExpr, wszMsg, wszFile, uLine); + #endif + } + #endif +#else + // REVIEW: should be able to do something better that this... + DebugBreak(); +#endif +} diff --git a/private/oleutest/letest/ole2ui/dballoc.h b/private/oleutest/letest/ole2ui/dballoc.h new file mode 100644 index 000000000..42ccbaff2 --- /dev/null +++ b/private/oleutest/letest/ole2ui/dballoc.h @@ -0,0 +1,36 @@ +/*** +*dballoc.h +* +* Copyright (C) 1992-93, Microsoft Corporation. All Rights Reserved. +* +*Purpose: +* This file contains the definition of CDbAlloc - A debug implementation +* of the IMalloc interface. +* +*Implementation Notes: +* +*****************************************************************************/ + +#ifndef DBALLOC_H_INCLUDED /* { */ +#define DBALLOC_H_INCLUDED + + +interface IDbOutput : public IUnknown +{ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, void FAR* FAR* ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + STDMETHOD_(void, Printf)(THIS_ + TCHAR FAR* szFmt, ...) PURE; + + STDMETHOD_(void, Assertion)(THIS_ + BOOL cond, + TCHAR FAR* szExpr, + TCHAR FAR* szFile, + UINT uLine, + TCHAR FAR* szMsg) PURE; +}; + + +#endif /* } DBALLOC_H_INCLUDED */ diff --git a/private/oleutest/letest/ole2ui/dbgutil.c b/private/oleutest/letest/ole2ui/dbgutil.c new file mode 100644 index 000000000..15c17a248 --- /dev/null +++ b/private/oleutest/letest/ole2ui/dbgutil.c @@ -0,0 +1,419 @@ +/************************************************************************* +** +** OLE 2.0 Common Utilities +** +** dbgutil.h +** +** This file contains file contains functions to support debug output. +** +** (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved +** +*************************************************************************/ + +#define STRICT 1 +#include "ole2ui.h" + +static int s_nDbgIndent = 0; // indent level for debug message +#if defined( _DEBUG ) +static int s_nDbgLevel = 0; // default dbg level printed +#else +static int s_nDbgLevel = 0; // default dbg level printed +#endif + +STDAPI_(void) OleDbgPrint( + int nDbgLvl, + LPTSTR lpszPrefix, + LPTSTR lpszMsg, + int nIndent +) +{ + if (nDbgLvl <= s_nDbgLevel) + OleDbgPrintAlways(lpszPrefix, lpszMsg, nIndent); +} + + +STDAPI_(void) OleDbgPrintAlways(LPTSTR lpszPrefix, LPTSTR lpszMsg, int nIndent) +{ + int i; + + if (nIndent < 0) + OleDbgIndent(nIndent); + + if (lpszPrefix && *lpszPrefix != TEXT('\0')) { + OutputDebugString(TEXT("| ")); + for (i = 0; i < s_nDbgIndent; i++) + OutputDebugString(TEXT("----")); + + OutputDebugString(lpszPrefix); + OutputDebugString(TEXT(": ")); + } + + OutputDebugString(lpszMsg); + if (nIndent > 0) + OleDbgIndent(nIndent); +} + +STDAPI_(void) OleDbgSetDbgLevel(int nDbgLvl) +{ + s_nDbgLevel = nDbgLvl; +} + +STDAPI_(int) OleDbgGetDbgLevel( void ) +{ + return s_nDbgLevel; +} + +STDAPI_(void) OleDbgIndent(int n) +{ + switch (n) { + case -1: + s_nDbgIndent--; + break; + case 1: + s_nDbgIndent++; + break; + case -2: + s_nDbgIndent = 0; + break; + } +} + + +STDAPI_(void) OleDbgPrintRefCnt( + int nDbgLvl, + LPTSTR lpszPrefix, + LPTSTR lpszMsg, + LPVOID lpObj, + ULONG refcnt +) +{ + if (nDbgLvl <= s_nDbgLevel) + OleDbgPrintRefCntAlways(lpszPrefix, lpszMsg, lpObj, refcnt); +} + + +STDAPI_(void) OleDbgPrintRefCntAlways( + LPTSTR lpszPrefix, + LPTSTR lpszMsg, + LPVOID lpObj, + ULONG refcnt +) +{ +#if defined( _DEBUG ) + TCHAR szBuf[256]; + + wsprintf(szBuf, TEXT("[obj=(0x%lx) cnt=%ld] %s"), lpObj, refcnt, lpszMsg); + OleDbgPrintAlways(lpszPrefix, szBuf, 0); +#endif +} + + +STDAPI_(void) OleDbgPrintRect( + int nDbgLvl, + LPTSTR lpszPrefix, + LPTSTR lpszMsg, + LPRECT lpRect +) +{ + if (nDbgLvl <= s_nDbgLevel) + OleDbgPrintRectAlways(lpszPrefix, lpszMsg, lpRect); +} + + +STDAPI_(void) OleDbgPrintRectAlways( + LPTSTR lpszPrefix, + LPTSTR lpszMsg, + LPRECT lpRect +) +{ +#if defined( _DEBUG ) + TCHAR szBuf[256]; + + wsprintf( + szBuf, + TEXT("%s: (%d,%d)-(%d,%d) %dx%d\r\n"), + lpszMsg, + lpRect->left, + lpRect->top, + lpRect->right, + lpRect->bottom, + (lpRect->right-lpRect->left), + (lpRect->bottom-lpRect->top) + ); + OleDbgPrintAlways(lpszPrefix, szBuf, 0); +#endif +} + + +#define CASE_SCODE(sc) \ + case sc: \ + lstrcpy((LPTSTR)szErrName, (LPTSTR)#sc); \ + break; + +STDAPI_(void) OleDbgPrintScodeAlways(LPTSTR lpszPrefix, LPTSTR lpszMsg, SCODE sc) +{ +#if defined( _DEBUG ) + TCHAR szBuf[256]; + TCHAR szErrName[40]; + + switch (sc) { + + /* SCODE's defined in SCODE.H */ + + CASE_SCODE(S_OK) + CASE_SCODE(S_FALSE) + CASE_SCODE(E_UNEXPECTED) + CASE_SCODE(E_OUTOFMEMORY) + CASE_SCODE(E_INVALIDARG) + CASE_SCODE(E_NOINTERFACE) + CASE_SCODE(E_POINTER) + CASE_SCODE(E_HANDLE) + CASE_SCODE(E_ABORT) + CASE_SCODE(E_FAIL) + CASE_SCODE(E_ACCESSDENIED) + + /* SCODE's defined in OLE2.H */ + + CASE_SCODE(OLE_E_OLEVERB) + CASE_SCODE(OLE_E_ADVF) + CASE_SCODE(OLE_E_ENUM_NOMORE) + CASE_SCODE(OLE_E_ADVISENOTSUPPORTED) + CASE_SCODE(OLE_E_NOCONNECTION) + CASE_SCODE(OLE_E_NOTRUNNING) + CASE_SCODE(OLE_E_NOCACHE) + CASE_SCODE(OLE_E_BLANK) + CASE_SCODE(OLE_E_CLASSDIFF) + CASE_SCODE(OLE_E_CANT_GETMONIKER) + CASE_SCODE(OLE_E_CANT_BINDTOSOURCE) + CASE_SCODE(OLE_E_STATIC) + CASE_SCODE(OLE_E_PROMPTSAVECANCELLED) + CASE_SCODE(OLE_E_INVALIDRECT) + CASE_SCODE(OLE_E_WRONGCOMPOBJ) + CASE_SCODE(OLE_E_INVALIDHWND) + CASE_SCODE(OLE_E_NOT_INPLACEACTIVE) + CASE_SCODE(OLE_E_CANTCONVERT) + CASE_SCODE(OLE_E_NOSTORAGE) + + CASE_SCODE(DV_E_FORMATETC) + CASE_SCODE(DV_E_DVTARGETDEVICE) + CASE_SCODE(DV_E_STGMEDIUM) + CASE_SCODE(DV_E_STATDATA) + CASE_SCODE(DV_E_LINDEX) + CASE_SCODE(DV_E_TYMED) + CASE_SCODE(DV_E_CLIPFORMAT) + CASE_SCODE(DV_E_DVASPECT) + CASE_SCODE(DV_E_DVTARGETDEVICE_SIZE) + CASE_SCODE(DV_E_NOIVIEWOBJECT) + + CASE_SCODE(OLE_S_USEREG) + CASE_SCODE(OLE_S_STATIC) + CASE_SCODE(OLE_S_MAC_CLIPFORMAT) + + CASE_SCODE(CONVERT10_E_OLESTREAM_GET) + CASE_SCODE(CONVERT10_E_OLESTREAM_PUT) + CASE_SCODE(CONVERT10_E_OLESTREAM_FMT) + CASE_SCODE(CONVERT10_E_OLESTREAM_BITMAP_TO_DIB) + CASE_SCODE(CONVERT10_E_STG_FMT) + CASE_SCODE(CONVERT10_E_STG_NO_STD_STREAM) + CASE_SCODE(CONVERT10_E_STG_DIB_TO_BITMAP) + CASE_SCODE(CONVERT10_S_NO_PRESENTATION) + + CASE_SCODE(CLIPBRD_E_CANT_OPEN) + CASE_SCODE(CLIPBRD_E_CANT_EMPTY) + CASE_SCODE(CLIPBRD_E_CANT_SET) + CASE_SCODE(CLIPBRD_E_BAD_DATA) + CASE_SCODE(CLIPBRD_E_CANT_CLOSE) + + CASE_SCODE(DRAGDROP_E_NOTREGISTERED) + CASE_SCODE(DRAGDROP_E_ALREADYREGISTERED) + CASE_SCODE(DRAGDROP_E_INVALIDHWND) + CASE_SCODE(DRAGDROP_S_DROP) + CASE_SCODE(DRAGDROP_S_CANCEL) + CASE_SCODE(DRAGDROP_S_USEDEFAULTCURSORS) + + CASE_SCODE(OLEOBJ_E_NOVERBS) + CASE_SCODE(OLEOBJ_E_INVALIDVERB) + CASE_SCODE(OLEOBJ_S_INVALIDVERB) + CASE_SCODE(OLEOBJ_S_CANNOT_DOVERB_NOW) + CASE_SCODE(OLEOBJ_S_INVALIDHWND) + CASE_SCODE(INPLACE_E_NOTUNDOABLE) + CASE_SCODE(INPLACE_E_NOTOOLSPACE) + CASE_SCODE(INPLACE_S_TRUNCATED) + + /* SCODE's defined in COMPOBJ.H */ + + CASE_SCODE(CO_E_NOTINITIALIZED) + CASE_SCODE(CO_E_ALREADYINITIALIZED) + CASE_SCODE(CO_E_CANTDETERMINECLASS) + CASE_SCODE(CO_E_CLASSSTRING) + CASE_SCODE(CO_E_IIDSTRING) + CASE_SCODE(CO_E_APPNOTFOUND) + CASE_SCODE(CO_E_APPSINGLEUSE) + CASE_SCODE(CO_E_ERRORINAPP) + CASE_SCODE(CO_E_DLLNOTFOUND) + CASE_SCODE(CO_E_ERRORINDLL) + CASE_SCODE(CO_E_WRONGOSFORAPP) + CASE_SCODE(CO_E_OBJNOTREG) + CASE_SCODE(CO_E_OBJISREG) + CASE_SCODE(CO_E_OBJNOTCONNECTED) + CASE_SCODE(CO_E_APPDIDNTREG) + CASE_SCODE(CLASS_E_NOAGGREGATION) +// CASE_SCODE(CLASS_E_CLASSNOTAVAILABLE) + CASE_SCODE(REGDB_E_READREGDB) + CASE_SCODE(REGDB_E_WRITEREGDB) + CASE_SCODE(REGDB_E_KEYMISSING) + CASE_SCODE(REGDB_E_INVALIDVALUE) + CASE_SCODE(REGDB_E_CLASSNOTREG) + CASE_SCODE(REGDB_E_IIDNOTREG) + CASE_SCODE(RPC_E_CALL_REJECTED) + CASE_SCODE(RPC_E_CALL_CANCELED) + CASE_SCODE(RPC_E_CANTPOST_INSENDCALL) + CASE_SCODE(RPC_E_CANTCALLOUT_INASYNCCALL) + CASE_SCODE(RPC_E_CANTCALLOUT_INEXTERNALCALL) + CASE_SCODE(RPC_E_CONNECTION_TERMINATED) + CASE_SCODE(RPC_E_SERVER_DIED) + CASE_SCODE(RPC_E_CLIENT_DIED) + CASE_SCODE(RPC_E_INVALID_DATAPACKET) + CASE_SCODE(RPC_E_CANTTRANSMIT_CALL) + CASE_SCODE(RPC_E_CLIENT_CANTMARSHAL_DATA) + CASE_SCODE(RPC_E_CLIENT_CANTUNMARSHAL_DATA) + CASE_SCODE(RPC_E_SERVER_CANTMARSHAL_DATA) + CASE_SCODE(RPC_E_SERVER_CANTUNMARSHAL_DATA) + CASE_SCODE(RPC_E_INVALID_DATA) + CASE_SCODE(RPC_E_INVALID_PARAMETER) +// CASE_SCODE(RPC_E_CANTCALLOUT_AGAIN) + CASE_SCODE(RPC_E_UNEXPECTED) + + /* SCODE's defined in DVOBJ.H */ + + CASE_SCODE(DATA_S_SAMEFORMATETC) + CASE_SCODE(VIEW_E_DRAW) + CASE_SCODE(VIEW_S_ALREADY_FROZEN) + CASE_SCODE(CACHE_E_NOCACHE_UPDATED) + CASE_SCODE(CACHE_S_FORMATETC_NOTSUPPORTED) + CASE_SCODE(CACHE_S_SAMECACHE) + CASE_SCODE(CACHE_S_SOMECACHES_NOTUPDATED) + + /* SCODE's defined in STORAGE.H */ + + CASE_SCODE(STG_E_INVALIDFUNCTION) + CASE_SCODE(STG_E_FILENOTFOUND) + CASE_SCODE(STG_E_PATHNOTFOUND) + CASE_SCODE(STG_E_TOOMANYOPENFILES) + CASE_SCODE(STG_E_ACCESSDENIED) + CASE_SCODE(STG_E_INVALIDHANDLE) + CASE_SCODE(STG_E_INSUFFICIENTMEMORY) + CASE_SCODE(STG_E_INVALIDPOINTER) + CASE_SCODE(STG_E_NOMOREFILES) + CASE_SCODE(STG_E_DISKISWRITEPROTECTED) + CASE_SCODE(STG_E_SEEKERROR) + CASE_SCODE(STG_E_WRITEFAULT) + CASE_SCODE(STG_E_READFAULT) + CASE_SCODE(STG_E_SHAREVIOLATION) + CASE_SCODE(STG_E_LOCKVIOLATION) + CASE_SCODE(STG_E_FILEALREADYEXISTS) + CASE_SCODE(STG_E_INVALIDPARAMETER) + CASE_SCODE(STG_E_MEDIUMFULL) + CASE_SCODE(STG_E_ABNORMALAPIEXIT) + CASE_SCODE(STG_E_INVALIDHEADER) + CASE_SCODE(STG_E_INVALIDNAME) + CASE_SCODE(STG_E_UNKNOWN) + CASE_SCODE(STG_E_UNIMPLEMENTEDFUNCTION) + CASE_SCODE(STG_E_INVALIDFLAG) + CASE_SCODE(STG_E_INUSE) + CASE_SCODE(STG_E_NOTCURRENT) + CASE_SCODE(STG_E_REVERTED) + CASE_SCODE(STG_E_CANTSAVE) + CASE_SCODE(STG_E_OLDFORMAT) + CASE_SCODE(STG_E_OLDDLL) + CASE_SCODE(STG_E_SHAREREQUIRED) + CASE_SCODE(STG_E_NOTFILEBASEDSTORAGE) + CASE_SCODE(STG_E_EXTANTMARSHALLINGS) + CASE_SCODE(STG_S_CONVERTED) + + /* SCODE's defined in STORAGE.H */ + + CASE_SCODE(MK_E_CONNECTMANUALLY) + CASE_SCODE(MK_E_EXCEEDEDDEADLINE) + CASE_SCODE(MK_E_NEEDGENERIC) + CASE_SCODE(MK_E_UNAVAILABLE) + CASE_SCODE(MK_E_SYNTAX) + CASE_SCODE(MK_E_NOOBJECT) + CASE_SCODE(MK_E_INVALIDEXTENSION) + CASE_SCODE(MK_E_INTERMEDIATEINTERFACENOTSUPPORTED) + CASE_SCODE(MK_E_NOTBINDABLE) + CASE_SCODE(MK_E_NOTBOUND) + CASE_SCODE(MK_E_CANTOPENFILE) + CASE_SCODE(MK_E_MUSTBOTHERUSER) + CASE_SCODE(MK_E_NOINVERSE) + CASE_SCODE(MK_E_NOSTORAGE) + CASE_SCODE(MK_E_NOPREFIX) + CASE_SCODE(MK_S_REDUCED_TO_SELF) + CASE_SCODE(MK_S_ME) + CASE_SCODE(MK_S_HIM) + CASE_SCODE(MK_S_US) + CASE_SCODE(MK_S_MONIKERALREADYREGISTERED) + + default: + lstrcpy(szErrName, TEXT("UNKNOWN SCODE")); + } + + wsprintf(szBuf, TEXT("%s %s (0x%lx)\n"), lpszMsg, (LPTSTR)szErrName, sc); + OleDbgPrintAlways(lpszPrefix, szBuf, 0); +#endif // _DEBUG +} + +STDAPI FnAssert(LPSTR lpstrExpr, LPSTR lpstrMsg, LPSTR lpstrFileName, UINT iLine) +{ +#ifdef _DEBUG + char szOutput[1024]; + char szTitle[256]; + char szModuleName[128]; + char *pszModuleName; + int id; + + DWORD tid = GetCurrentThreadId(); + DWORD pid = GetCurrentProcessId(); + + wsprintfA(szOutput, "%s %s File: %s Line: %d PID: %d TID: %d\n", + lpstrExpr, lpstrMsg ? lpstrMsg : "", lpstrFileName, pid, tid); + OutputDebugString(szOutput); + + if (GetModuleFileNameA(NULL, szModuleName, 128)) + { + pszModuleName = strrchr(szModuleName, '\\'); + if (!pszModuleName) + { + pszModuleName = szModuleName; + } + else + { + pszModuleName++; + } + } + else + { + pszModuleName = "Unknown"; + } + + wsprintfA(szTitle, "Process: %s File: %s, line %u", + pszModuleName, lpstrFileName, iLine); + + wsprintfA(szOutput, "%s %s PID.TID %d.%d", + lpstrExpr, lpstrMsg ? lpstrMsg : "", pid, tid); + + id = MessageBoxA(NULL, + szOutput, + szTitle, + MB_SETFOREGROUND | MB_DEFAULT_DESKTOP_ONLY | + MB_TASKMODAL | MB_ICONEXCLAMATION | MB_OKCANCEL); + + + if (id == IDCANCEL) + { + DebugBreak(); + } + +#endif // _DEBUG + return NOERROR; +} diff --git a/private/oleutest/letest/ole2ui/debug.h b/private/oleutest/letest/ole2ui/debug.h new file mode 100644 index 000000000..fa5bfc7ef --- /dev/null +++ b/private/oleutest/letest/ole2ui/debug.h @@ -0,0 +1,69 @@ +/* + * DEBUG.H + * + * Definitions, structures, types, and function prototypes for debugging + * purposes. + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved, + * as applied to redistribution of this source code in source form + * License is granted to use of compiled code in shipped binaries. + */ + +#ifndef _DEBUG_H_ +#define _DEBUG_H_ + +#ifdef DEBUG + +//Basic debug macros +#define D(x) {x;} +#define ODS(x) D(OutputDebugString(x);OutputDebugString("\r\n")) + +#define ODSsz(f, s) {\ + char szDebug[128];\ + wsprintf(szDebug, f, (LPSTR)s);\ + ODS(szDebug);\ + } + + +#define ODSu(f, u) {\ + char szDebug[128];\ + wsprintf(szDebug, f, (UINT)u);\ + ODS(szDebug);\ + } + + +#define ODSlu(f, lu) {\ + char szDebug[128];\ + wsprintf(szDebug, f, (DWORD)lu);\ + ODS(szDebug);\ + } + +#define ODSszu(f, s, u) {\ + char szDebug[128];\ + wsprintf(szDebug, f, (LPSTR)s, (UINT)u);\ + ODS(szDebug);\ + } + + +#define ODSszlu(f, s, lu) {\ + char szDebug[128];\ + wsprintf(szDebug, f, (LPSTR)s, (DWORD)lu);\ + ODS(szDebug);\ + } + + +#else //NO DEBUG + +#define D(x) +#define ODS(x) + +#define ODSsz(f, s) +#define ODSu(f, u) +#define ODSlu(f, lu) +#define ODSszu(f, s, u) +#define ODSszlu(f, s, lu) + + +#endif //DEBUG + +#endif //_DEBUG_H_ diff --git a/private/oleutest/letest/ole2ui/default.ico b/private/oleutest/letest/ole2ui/default.ico new file mode 100644 index 000000000..4542c57d3 Binary files /dev/null and b/private/oleutest/letest/ole2ui/default.ico differ diff --git a/private/oleutest/letest/ole2ui/defuimak.ini b/private/oleutest/letest/ole2ui/defuimak.ini new file mode 100644 index 000000000..39517d711 --- /dev/null +++ b/private/oleutest/letest/ole2ui/defuimak.ini @@ -0,0 +1,20 @@ +# This is the DEBUG UILibrary INI file +MSG=DEBUG Version ($(LANG)) +DEBUG=1 +LIBNAME=outlui +REL_DIR=c:\ole2samp\release +OLEREL_DIR=c:\ole2samp\release +OBJ=DEBUG +RESOURCE=RESOURCE +CFLAGS=-c -Od -Gw2cs -W3 -Zpei -AMw -D_DEBUG -D_WINDLL -Gi +AFLAGS=-mx -Zi -DDEBUG +RFLAGS=-D DEBUG +LFLAGS=/MAP /CO /L /NOD /NOE /SE:300 +UILIBS=mdllcew libw ole2 storage shell commdlg toolhelp +CC=cl +AS=masm +RS=rc +LK=link +LANG=USA +DLLOBJS = $(UI_DLLOBJS:D^\=DEBUG^\) +LIBOBJS = $(UI_COBJS:D^\=DEBUG^\) $(UI_NOPCOBJS:D^\=DEBUG\NOPC^\) diff --git a/private/oleutest/letest/ole2ui/depend b/private/oleutest/letest/ole2ui/depend new file mode 100644 index 000000000..4007c4980 --- /dev/null +++ b/private/oleutest/letest/ole2ui/depend @@ -0,0 +1,87 @@ +$(O)busy.obj : $(PRECOMP) \ + ole2ui.h olestd.h uiclass.h common.h utility.h busy.h + +$(O)common.obj : $(PRECOMP) \ + ole2ui.h olestd.h uiclass.h common.h utility.h + +$(O)convert.obj : $(PRECOMP) \ + ole2ui.h olestd.h uiclass.h common.h utility.h geticon.h regdb.h \ + convert.h + +$(O)dbgutil.obj : $(PRECOMP) \ + ole2ui.h olestd.h uiclass.h + +$(O)regdb.obj : $(PRECOMP) \ + ole2ui.h olestd.h uiclass.h + +$(O)drawicon.obj : $(PRECOMP) \ + ole2ui.h olestd.h uiclass.h common.h utility.h geticon.h + +$(O)hatch.obj : $(PRECOMP) \ + ole2ui.h olestd.h uiclass.h + +$(O)icon.obj : $(PRECOMP) \ + ole2ui.h olestd.h uiclass.h common.h utility.h icon.h geticon.h + +$(O)iconbox.obj : $(PRECOMP) \ + ole2ui.h olestd.h uiclass.h iconbox.h + +$(O)insobj.obj : $(PRECOMP) \ + ole2ui.h olestd.h uiclass.h common.h utility.h icon.h insobj.h \ + resimage.h iconbox.h geticon.h + +$(O)links.obj : $(PRECOMP) \ + ole2ui.h olestd.h uiclass.h common.h edlinks.h utility.h + +$(O)msgfiltr.obj : $(PRECOMP) \ + ole2ui.h olestd.h uiclass.h msgfiltr.h + +$(O)enumfetc.obj : $(PRECOMP) \ + ole2ui.h olestd.h + +$(O)enumstat.obj : $(PRECOMP) \ + ole2ui.h olestd.h + +$(O)objfdbk.obj : $(PRECOMP) \ + ole2ui.h olestd.h + +$(O)ole2ui.obj : $(PRECOMP) \ + ole2ui.h olestd.h common.h utility.h resimage.h iconbox.h + +$(O)olestd.obj : $(PRECOMP) \ + ole2ui.h olestd.h regdb.h geticon.h common.h + +$(O)targtdev.obj : $(PRECOMP) \ + ole2ui.h olestd.h + +$(O)oleutl.obj : $(PRECOMP) \ + ole2ui.h olestd.h + +$(O)pastespl.obj : $(PRECOMP) \ + ole2ui.h olestd.h pastespl.h common.h utility.h resimage.h iconbox.h \ + geticon.h regdb.h + +$(O)resimage.obj : $(PRECOMP) \ + ole2ui.h olestd.h resimage.h + +$(O)utility.obj : $(PRECOMP) \ + ole2ui.h olestd.h common.h utility.h geticon.h + +$(O)dllfuncs.obj : $(PRECOMP) \ + ole2ui.h olestd.h common.h uiclass.h + +$(O)NOPC\geticon.obj : \ + ole2ui.h olestd.h uiclass.h geticon.h + +$(O)NOPC\dballoc.obj : \ + dballoc.h + +$(O)NOPC\suminfo.obj : \ + suminfo.h wn_dos.h + +$(O)NOPC\stdpal.obj : \ + stdpal.h + +$(O)precomp.pch : \ + ole2ui.h olestd.h uiclass.h + diff --git a/private/oleutest/letest/ole2ui/depend.mk b/private/oleutest/letest/ole2ui/depend.mk new file mode 100644 index 000000000..2b6c05155 --- /dev/null +++ b/private/oleutest/letest/ole2ui/depend.mk @@ -0,0 +1,569 @@ +# +# Built automatically +# + +# +# Source files +# + +$(OBJDIR)\busy.obj $(OBJDIR)\busy.lst: .\busy.c $(CAIROLE)\h\export\coguid.h \ + $(CAIROLE)\h\export\compobj.h $(CAIROLE)\h\export\dvobj.h \ + $(CAIROLE)\h\export\initguid.h $(CAIROLE)\h\export\moniker.h \ + $(CAIROLE)\h\export\ole2.h $(CAIROLE)\h\export\oleguid.h \ + $(CAIROLE)\h\export\scode.h $(CAIROLE)\h\export\storage.h \ + $(CRTINC)\ctype.h $(CRTINC)\dos.h $(CRTINC)\excpt.h \ + $(CRTINC)\stdarg.h $(CRTINC)\string.h $(OSINC)\cderr.h \ + $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \ + $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \ + $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \ + $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \ + $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \ + $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \ + $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \ + $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \ + $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \ + $(OSINC)\winuser.h $(OSINC)\winver.h .\busy.h .\common.h .\ole2ui.h \ + .\olestd.h .\utility.h + +$(OBJDIR)\common.obj $(OBJDIR)\common.lst: .\common.c \ + $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \ + $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \ + $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \ + $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \ + $(CAIROLE)\h\export\storage.h $(CRTINC)\malloc.h $(CRTINC)\ctype.h \ + $(CRTINC)\dos.h $(CRTINC)\excpt.h $(CRTINC)\stdarg.h \ + $(CRTINC)\string.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \ + $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \ + $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \ + $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \ + $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \ + $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \ + $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \ + $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \ + $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \ + $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \ + $(OSINC)\winver.h .\common.h .\ole2ui.h .\olestd.h .\utility.h + +$(OBJDIR)\convert.obj $(OBJDIR)\convert.lst: .\convert.c \ + $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \ + $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \ + $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \ + $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \ + $(CAIROLE)\h\export\storage.h $(CRTINC)\stdlib.h $(CRTINC)\ctype.h \ + $(CRTINC)\dos.h $(CRTINC)\excpt.h $(CRTINC)\stdarg.h \ + $(CRTINC)\string.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \ + $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \ + $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \ + $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \ + $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \ + $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \ + $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \ + $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \ + $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \ + $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \ + $(OSINC)\winver.h .\convert.h .\geticon.h .\regdb.h .\common.h \ + .\ole2ui.h .\olestd.h .\utility.h + +$(OBJDIR)\dballoc.obj $(OBJDIR)\dballoc.lst: .\dballoc.cpp \ + $(CAIROLE)\h\export\ole2.h $(CAIROLE)\h\export\coguid.h \ + $(CAIROLE)\h\export\compobj.h $(CAIROLE)\h\export\dvobj.h \ + $(CAIROLE)\h\export\initguid.h $(CAIROLE)\h\export\moniker.h \ + $(CAIROLE)\h\export\ole2.h $(CAIROLE)\h\export\oleguid.h \ + $(CAIROLE)\h\export\scode.h $(CAIROLE)\h\export\storage.h \ + $(CRTINC)\limits.h $(CRTINC)\stdio.h $(CRTINC)\ctype.h \ + $(CRTINC)\excpt.h $(CRTINC)\malloc.h $(CRTINC)\stdarg.h \ + $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OSINC)\cderr.h \ + $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \ + $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \ + $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \ + $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \ + $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \ + $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \ + $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \ + $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \ + $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \ + $(OSINC)\winuser.h $(OSINC)\winver.h .\dballoc.h + +$(OBJDIR)\dbgutil.obj $(OBJDIR)\dbgutil.lst: .\dbgutil.c \ + $(CAIROLE)\h\export\ole2.h $(CAIROLE)\h\export\coguid.h \ + $(CAIROLE)\h\export\compobj.h $(CAIROLE)\h\export\dvobj.h \ + $(CAIROLE)\h\export\initguid.h $(CAIROLE)\h\export\moniker.h \ + $(CAIROLE)\h\export\ole2.h $(CAIROLE)\h\export\oleguid.h \ + $(CAIROLE)\h\export\scode.h $(CAIROLE)\h\export\storage.h \ + $(CRTINC)\ctype.h $(CRTINC)\dos.h $(CRTINC)\excpt.h \ + $(CRTINC)\stdarg.h $(CRTINC)\string.h $(OSINC)\shellapi.h \ + $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \ + $(OSINC)\dlgs.h $(OSINC)\drivinit.h $(OSINC)\lzexpand.h \ + $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h \ + $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h \ + $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \ + $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \ + $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \ + $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \ + $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \ + $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\ole2ui.h \ + .\olestd.h + +$(OBJDIR)\dllfuncs.obj $(OBJDIR)\dllfuncs.lst: .\dllfuncs.c \ + $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \ + $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \ + $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \ + $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \ + $(CAIROLE)\h\export\storage.h $(CRTINC)\ctype.h $(CRTINC)\dos.h \ + $(CRTINC)\excpt.h $(CRTINC)\stdarg.h $(CRTINC)\string.h \ + $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \ + $(OSINC)\dlgs.h $(OSINC)\drivinit.h $(OSINC)\lzexpand.h \ + $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h \ + $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h \ + $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \ + $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \ + $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \ + $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \ + $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \ + $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\uiclass.h \ + .\common.h .\ole2ui.h .\olestd.h + +$(OBJDIR)\drawicon.obj $(OBJDIR)\drawicon.lst: .\drawicon.c \ + $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \ + $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \ + $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \ + $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \ + $(CAIROLE)\h\export\storage.h $(CRTINC)\ctype.h $(CRTINC)\dos.h \ + $(CRTINC)\excpt.h $(CRTINC)\stdarg.h $(CRTINC)\string.h \ + $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \ + $(OSINC)\dlgs.h $(OSINC)\drivinit.h $(OSINC)\lzexpand.h \ + $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h \ + $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h \ + $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \ + $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \ + $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \ + $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \ + $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \ + $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\common.h \ + .\geticon.h .\ole2ui.h .\olestd.h .\utility.h + +$(OBJDIR)\enumfetc.obj $(OBJDIR)\enumfetc.lst: .\enumfetc.c \ + $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \ + $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \ + $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \ + $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \ + $(CAIROLE)\h\export\storage.h $(CRTINC)\ctype.h $(CRTINC)\dos.h \ + $(CRTINC)\excpt.h $(CRTINC)\stdarg.h $(CRTINC)\string.h \ + $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \ + $(OSINC)\dlgs.h $(OSINC)\drivinit.h $(OSINC)\lzexpand.h \ + $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h \ + $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h \ + $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \ + $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \ + $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \ + $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \ + $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \ + $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\enumfetc.h \ + .\ole2ui.h .\olestd.h + +$(OBJDIR)\enumstat.obj $(OBJDIR)\enumstat.lst: .\enumstat.c \ + $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \ + $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \ + $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \ + $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \ + $(CAIROLE)\h\export\storage.h $(CRTINC)\ctype.h $(CRTINC)\dos.h \ + $(CRTINC)\excpt.h $(CRTINC)\stdarg.h $(CRTINC)\string.h \ + $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \ + $(OSINC)\dlgs.h $(OSINC)\drivinit.h $(OSINC)\lzexpand.h \ + $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h \ + $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h \ + $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \ + $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \ + $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \ + $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \ + $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \ + $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\ole2ui.h \ + .\olestd.h + +$(OBJDIR)\geticon.obj $(OBJDIR)\geticon.lst: .\geticon.c \ + $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \ + $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \ + $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \ + $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \ + $(CAIROLE)\h\export\storage.h $(CRTINC)\memory.h $(CRTINC)\ctype.h \ + $(CRTINC)\dos.h $(CRTINC)\excpt.h $(CRTINC)\stdarg.h \ + $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OSINC)\cderr.h \ + $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \ + $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \ + $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \ + $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \ + $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \ + $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \ + $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \ + $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \ + $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \ + $(OSINC)\winuser.h $(OSINC)\winver.h .\common.h .\ole2ui.h \ + .\olestd.h .\utility.h + +$(OBJDIR)\hatch.obj $(OBJDIR)\hatch.lst: .\hatch.c \ + $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \ + $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \ + $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \ + $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \ + $(CAIROLE)\h\export\storage.h $(CRTINC)\ctype.h $(CRTINC)\dos.h \ + $(CRTINC)\excpt.h $(CRTINC)\stdarg.h $(CRTINC)\string.h \ + $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \ + $(OSINC)\dlgs.h $(OSINC)\drivinit.h $(OSINC)\lzexpand.h \ + $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h \ + $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h \ + $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \ + $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \ + $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \ + $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \ + $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \ + $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\ole2ui.h \ + .\olestd.h + +$(OBJDIR)\icon.obj $(OBJDIR)\icon.lst: .\icon.c $(CAIROLE)\h\export\coguid.h \ + $(CAIROLE)\h\export\compobj.h $(CAIROLE)\h\export\dvobj.h \ + $(CAIROLE)\h\export\initguid.h $(CAIROLE)\h\export\moniker.h \ + $(CAIROLE)\h\export\ole2.h $(CAIROLE)\h\export\oleguid.h \ + $(CAIROLE)\h\export\scode.h $(CAIROLE)\h\export\storage.h \ + $(CRTINC)\ctype.h $(CRTINC)\dos.h $(CRTINC)\excpt.h \ + $(CRTINC)\stdarg.h $(CRTINC)\string.h $(OSINC)\cderr.h \ + $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \ + $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \ + $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \ + $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \ + $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \ + $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \ + $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \ + $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \ + $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \ + $(OSINC)\winuser.h $(OSINC)\winver.h .\icon.h .\common.h .\geticon.h \ + .\ole2ui.h .\olestd.h .\utility.h + +$(OBJDIR)\iconbox.obj $(OBJDIR)\iconbox.lst: .\iconbox.c \ + $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \ + $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \ + $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \ + $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \ + $(CAIROLE)\h\export\storage.h $(CRTINC)\ctype.h $(CRTINC)\dos.h \ + $(CRTINC)\excpt.h $(CRTINC)\stdarg.h $(CRTINC)\string.h \ + $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \ + $(OSINC)\dlgs.h $(OSINC)\drivinit.h $(OSINC)\lzexpand.h \ + $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h \ + $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h \ + $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \ + $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \ + $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \ + $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \ + $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \ + $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\iconbox.h \ + .\ole2ui.h .\olestd.h + +$(OBJDIR)\insobj.obj $(OBJDIR)\insobj.lst: .\insobj.c \ + $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \ + $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \ + $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \ + $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \ + $(CAIROLE)\h\export\storage.h $(CRTINC)\direct.h $(CRTINC)\ctype.h \ + $(CRTINC)\dos.h $(CRTINC)\excpt.h $(CRTINC)\malloc.h \ + $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdlib.h \ + $(CRTINC)\string.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \ + $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \ + $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \ + $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \ + $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \ + $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \ + $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \ + $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \ + $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \ + $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \ + $(OSINC)\winver.h .\insobj.h .\resimage.h .\common.h .\geticon.h \ + .\icon.h .\iconbox.h .\ole2ui.h .\olestd.h .\utility.h + +$(OBJDIR)\links.obj $(OBJDIR)\links.lst: .\links.c \ + $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \ + $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \ + $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \ + $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \ + $(CAIROLE)\h\export\storage.h $(CRTINC)\ctype.h $(CRTINC)\dos.h \ + $(CRTINC)\excpt.h $(CRTINC)\stdarg.h $(CRTINC)\stdlib.h \ + $(CRTINC)\string.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \ + $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \ + $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \ + $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \ + $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \ + $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \ + $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \ + $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \ + $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \ + $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \ + $(OSINC)\winver.h .\edlinks.h .\common.h .\ole2ui.h .\olestd.h \ + .\utility.h + +$(OBJDIR)\msgfiltr.obj $(OBJDIR)\msgfiltr.lst: .\msgfiltr.c \ + $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \ + $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \ + $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \ + $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \ + $(CAIROLE)\h\export\storage.h $(CRTINC)\ctype.h $(CRTINC)\dos.h \ + $(CRTINC)\excpt.h $(CRTINC)\stdarg.h $(CRTINC)\string.h \ + $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \ + $(OSINC)\dlgs.h $(OSINC)\drivinit.h $(OSINC)\lzexpand.h \ + $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h \ + $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h \ + $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \ + $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \ + $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \ + $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \ + $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \ + $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\msgfiltr.h \ + .\ole2ui.h .\olestd.h + +$(OBJDIR)\objfdbk.obj $(OBJDIR)\objfdbk.lst: .\objfdbk.c \ + $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \ + $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \ + $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \ + $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \ + $(CAIROLE)\h\export\storage.h $(CRTINC)\ctype.h $(CRTINC)\dos.h \ + $(CRTINC)\excpt.h $(CRTINC)\stdarg.h $(CRTINC)\string.h \ + $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \ + $(OSINC)\dlgs.h $(OSINC)\drivinit.h $(OSINC)\lzexpand.h \ + $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h \ + $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h \ + $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \ + $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \ + $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \ + $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \ + $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \ + $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\ole2ui.h \ + .\olestd.h + +$(OBJDIR)\ole2ui.obj $(OBJDIR)\ole2ui.lst: .\ole2ui.c \ + $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \ + $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \ + $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \ + $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \ + $(CAIROLE)\h\export\storage.h $(CRTINC)\ctype.h $(CRTINC)\dos.h \ + $(CRTINC)\excpt.h $(CRTINC)\stdarg.h $(CRTINC)\string.h \ + $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \ + $(OSINC)\dlgs.h $(OSINC)\drivinit.h $(OSINC)\lzexpand.h \ + $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h \ + $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h \ + $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \ + $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \ + $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \ + $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \ + $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \ + $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\common.h \ + .\iconbox.h .\ole2ui.h .\olestd.h .\resimage.h .\utility.h + +$(OBJDIR)\olestd.obj $(OBJDIR)\olestd.lst: .\olestd.c \ + $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \ + $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \ + $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \ + $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \ + $(CAIROLE)\h\export\storage.h $(CRTINC)\ctype.h $(CRTINC)\dos.h \ + $(CRTINC)\excpt.h $(CRTINC)\stdarg.h $(CRTINC)\stdlib.h \ + $(CRTINC)\string.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \ + $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \ + $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \ + $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \ + $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \ + $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \ + $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \ + $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \ + $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \ + $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \ + $(OSINC)\winver.h .\common.h .\geticon.h .\ole2ui.h .\olestd.h \ + .\regdb.h + +$(OBJDIR)\oleutl.obj $(OBJDIR)\oleutl.lst: .\oleutl.c \ + $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \ + $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \ + $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \ + $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \ + $(CAIROLE)\h\export\storage.h $(CRTINC)\ctype.h $(CRTINC)\dos.h \ + $(CRTINC)\excpt.h $(CRTINC)\stdarg.h $(CRTINC)\stdlib.h \ + $(CRTINC)\string.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \ + $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \ + $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \ + $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \ + $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \ + $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \ + $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \ + $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \ + $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \ + $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \ + $(OSINC)\winver.h .\ole2ui.h .\olestd.h + +$(OBJDIR)\pastespl.obj $(OBJDIR)\pastespl.lst: .\pastespl.c \ + $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \ + $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \ + $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \ + $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \ + $(CAIROLE)\h\export\storage.h $(CRTINC)\ctype.h $(CRTINC)\dos.h \ + $(CRTINC)\excpt.h $(CRTINC)\stdarg.h $(CRTINC)\stdlib.h \ + $(CRTINC)\string.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \ + $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \ + $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \ + $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \ + $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \ + $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \ + $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \ + $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \ + $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \ + $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \ + $(OSINC)\winver.h .\pastespl.h .\common.h .\geticon.h .\icon.h \ + .\iconbox.h .\ole2ui.h .\olestd.h .\regdb.h .\resimage.h \ + .\utility.h + +$(OBJDIR)\precomp.obj $(OBJDIR)\precomp.lst: .\precomp.c \ + $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \ + $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \ + $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \ + $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \ + $(CAIROLE)\h\export\storage.h $(CRTINC)\ctype.h $(CRTINC)\dos.h \ + $(CRTINC)\excpt.h $(CRTINC)\stdarg.h $(CRTINC)\string.h \ + $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \ + $(OSINC)\dlgs.h $(OSINC)\drivinit.h $(OSINC)\lzexpand.h \ + $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h \ + $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h \ + $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \ + $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \ + $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \ + $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \ + $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \ + $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\ole2ui.h \ + .\olestd.h + +$(OBJDIR)\regdb.obj $(OBJDIR)\regdb.lst: .\regdb.c \ + $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \ + $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \ + $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \ + $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \ + $(CAIROLE)\h\export\storage.h $(CRTINC)\ctype.h $(CRTINC)\dos.h \ + $(CRTINC)\excpt.h $(CRTINC)\stdarg.h $(CRTINC)\string.h \ + $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \ + $(OSINC)\dlgs.h $(OSINC)\drivinit.h $(OSINC)\lzexpand.h \ + $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h \ + $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h \ + $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \ + $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \ + $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \ + $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \ + $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \ + $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\common.h \ + .\ole2ui.h .\olestd.h + +$(OBJDIR)\resimage.obj $(OBJDIR)\resimage.lst: .\resimage.c \ + $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \ + $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \ + $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \ + $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \ + $(CAIROLE)\h\export\storage.h $(CRTINC)\ctype.h $(CRTINC)\dos.h \ + $(CRTINC)\excpt.h $(CRTINC)\stdarg.h $(CRTINC)\string.h \ + $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \ + $(OSINC)\dlgs.h $(OSINC)\drivinit.h $(OSINC)\lzexpand.h \ + $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h \ + $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h \ + $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \ + $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \ + $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \ + $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \ + $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \ + $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\ole2ui.h \ + .\olestd.h .\resimage.h + +$(OBJDIR)\stdpal.obj $(OBJDIR)\stdpal.lst: .\stdpal.c \ + $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \ + $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \ + $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \ + $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \ + $(CAIROLE)\h\export\storage.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \ + $(CRTINC)\stdarg.h $(CRTINC)\string.h $(OSINC)\cderr.h \ + $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \ + $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \ + $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \ + $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \ + $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \ + $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \ + $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \ + $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \ + $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \ + $(OSINC)\winuser.h $(OSINC)\winver.h .\stdpal.h + +$(OBJDIR)\suminfo.obj $(OBJDIR)\suminfo.lst: .\suminfo.cpp \ + $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \ + $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \ + $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \ + $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \ + $(CAIROLE)\h\export\storage.h $(CRTINC)\ctype.h $(CRTINC)\dos.h \ + $(CRTINC)\excpt.h $(CRTINC)\stdarg.h $(CRTINC)\string.h \ + $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \ + $(OSINC)\dlgs.h $(OSINC)\drivinit.h $(OSINC)\lzexpand.h \ + $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h \ + $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h \ + $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \ + $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \ + $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \ + $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \ + $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \ + $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h \ + .\..\release\variant.h .\suminfo.h .\wn_dos.h .\ole2ui.h .\olestd.h + +$(OBJDIR)\targtdev.obj $(OBJDIR)\targtdev.lst: .\targtdev.c \ + $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \ + $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \ + $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \ + $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \ + $(CAIROLE)\h\export\storage.h $(CRTINC)\ctype.h $(CRTINC)\dos.h \ + $(CRTINC)\excpt.h $(CRTINC)\stdarg.h $(CRTINC)\string.h \ + $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \ + $(OSINC)\dlgs.h $(OSINC)\drivinit.h $(OSINC)\lzexpand.h \ + $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h \ + $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h \ + $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \ + $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \ + $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \ + $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \ + $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \ + $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\ole2ui.h \ + .\olestd.h + +$(OBJDIR)\template.obj $(OBJDIR)\template.lst: .\template.c \ + $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \ + $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \ + $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \ + $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \ + $(CAIROLE)\h\export\storage.h $(CRTINC)\ctype.h $(CRTINC)\dos.h \ + $(CRTINC)\excpt.h $(CRTINC)\stdarg.h $(CRTINC)\string.h \ + $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \ + $(OSINC)\dlgs.h $(OSINC)\drivinit.h $(OSINC)\lzexpand.h \ + $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h \ + $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h \ + $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \ + $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \ + $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \ + $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \ + $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \ + $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\common.h \ + .\ole2ui.h .\olestd.h + +$(OBJDIR)\utility.obj $(OBJDIR)\utility.lst: .\utility.c \ + $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \ + $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \ + $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \ + $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \ + $(CAIROLE)\h\export\storage.h $(CRTINC)\ctype.h $(CRTINC)\dos.h \ + $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\stdarg.h \ + $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OSINC)\cderr.h \ + $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \ + $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \ + $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \ + $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \ + $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \ + $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \ + $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \ + $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \ + $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \ + $(OSINC)\winuser.h $(OSINC)\winver.h .\common.h .\geticon.h \ + .\ole2ui.h .\olestd.h .\utility.h + diff --git a/private/oleutest/letest/ole2ui/dirs b/private/oleutest/letest/ole2ui/dirs new file mode 100644 index 000000000..90a66698e --- /dev/null +++ b/private/oleutest/letest/ole2ui/dirs @@ -0,0 +1,3 @@ +DIRS= +OPTIONAL_DIRS= daytona \ + diff --git a/private/oleutest/letest/ole2ui/dllentry.c b/private/oleutest/letest/ole2ui/dllentry.c new file mode 100644 index 000000000..1cd1159e4 --- /dev/null +++ b/private/oleutest/letest/ole2ui/dllentry.c @@ -0,0 +1,55 @@ +//+------------------------------------------------------------------- +// +// Microsoft Windows +// Copyright (C) Microsoft Corporation, 1991 - 1992. +// +// File: dllentry.c +// +// Contents: Dll Entry point code. Calls the appropriate run-time +// init/term code and then defers to LibMain for further +// processing. +// +// Classes: +// +// Functions: DllEntryPoint - Called by loader +// +// History: 10-May-92 BryanT Created +// 22-Jul-92 BryanT Switch to calling _cexit/_mtdeletelocks +// on cleanup. +// 06-Oct-92 BryanT Call RegisterWithCommnot on entry +// and DeRegisterWithCommnot on exit. +// This should fix the heap dump code. +// 27-Dec-93 AlexT Post 543 builds don't need special code. +// +//-------------------------------------------------------------------- + +#define USE_CRTDLL +#include + +BOOL WINAPI _CRT_INIT (HANDLE hDll, DWORD dwReason, LPVOID lpReserved); + +BOOL DllEntryPoint (HANDLE hDll, DWORD dwReason, LPVOID lpReserved); + +BOOL _CRTAPI1 LibMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved); + +BOOL DllEntryPoint (HANDLE hDll, DWORD dwReason, LPVOID lpReserved) +{ + BOOL fRc = FALSE; + + switch (dwReason) + { + case DLL_PROCESS_ATTACH: + _CRT_INIT(hDll, dwReason, lpReserved); + + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + fRc = LibMain (hDll, dwReason, lpReserved); + break; + + case DLL_PROCESS_DETACH: + fRc = LibMain (hDll, dwReason, lpReserved); + _CRT_INIT(hDll, dwReason, lpReserved); + } + + return(fRc); +} diff --git a/private/oleutest/letest/ole2ui/dllfuncs.c b/private/oleutest/letest/ole2ui/dllfuncs.c new file mode 100644 index 000000000..283ca9d67 --- /dev/null +++ b/private/oleutest/letest/ole2ui/dllfuncs.c @@ -0,0 +1,110 @@ +/* + * DLLFUNCS.C + * + * Contains entry and exit points for the DLL implementation + * of the OLE 2.0 User Interface Support Library. + * + * This file is not needed if we are linking the static library + * version of this library. + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + +#define STRICT 1 +#include "ole2ui.h" +#include "uiclass.h" +#include "common.h" + +OLEDBGDATA_MAIN("ole2u32a") + + +/* + * LibMain + * + * Purpose: + * DLL-specific entry point called from LibEntry. Initializes + * the DLL's heap and registers the GizmoBar GizmoBar. + * + * Parameters: + * hInst HINSTANCE instance of the DLL. + * wDataSeg WORD segment selector of the DLL's data segment. + * wHeapSize WORD byte count of the heap. + * lpCmdLine LPSTR to command line used to start the module. + * + * Return Value: + * HANDLE Instance handle of the DLL. + * + */ + +#ifdef WIN32 + +BOOL _cdecl LibMain( + HINSTANCE hDll, + DWORD dwReason, + LPVOID lpvReserved) +{ + if (dwReason == DLL_PROCESS_ATTACH) + { + // Initialize OLE UI libraries. If you're linking with the static + // LIB version of this library, you need to make the below call in + // your application (because this LibMain won't be executed). + OleUIInitialize(hDll, (HINSTANCE)0, SZCLASSICONBOX, SZCLASSRESULTIMAGE); + } + else if (dwReason == DLL_PROCESS_DETACH) + { + OleUIUnInitialize(); + } + + return TRUE; +} + +#else + +int FAR PASCAL LibMain(HINSTANCE hInst, WORD wDataSeg + , WORD cbHeapSize, LPTSTR lpCmdLine) + { + OleDbgOut2(TEXT("LibMain: OLE2UI.DLL loaded\r\n")); + + // Initialize OLE UI libraries. If you're linking with the static LIB version + // of this library, you need to make the below call in your application (because + // this LibMain won't be executed). + + // The symbols SZCLASSICONBOX and SZCLASSRESULTIMAGE are both defined + // in uiclass.h + + OleUIInitialize(hInst, (HINSTANCE)0, TEXT(SZCLASSICONBOX), TEXT(SZCLASSRESULTIMAGE)); + + //All done... + if (0!=cbHeapSize) + UnlockData(0); + + return (int)hInst; + } + +#endif + +/* + * WEP + * + * Purpose: + * Required DLL Exit function. + * + * Parameters: + * bSystemExit BOOL indicating if the system is being shut + * down or the DLL has just been unloaded. + * + * Return Value: + * void + * + */ +int CALLBACK EXPORT WEP(int bSystemExit) +{ + OleUIUnInitialize(); + return 0; +} + + + + + + diff --git a/private/oleutest/letest/ole2ui/drawicon.c b/private/oleutest/letest/ole2ui/drawicon.c new file mode 100644 index 000000000..06cdd3ab7 --- /dev/null +++ b/private/oleutest/letest/ole2ui/drawicon.c @@ -0,0 +1,729 @@ +/* + * DRAWICON.C + * + * Functions to handle creation of metafiles with icons and labels + * as well as functions to draw such metafiles with or without the label. + * + * The metafile is created with a comment that marks the records containing + * the label code. Drawing the metafile enumerates the records, draws + * all records up to that point, then decides to either skip the label + * or draw it. + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + +#define STRICT 1 +#include "ole2ui.h" +#include "common.h" +#include "utility.h" +#include "geticon.h" + +/* + * Strings for metafile comments. KEEP THESE IN SYNC WITH THE + * STRINGS IN GETICON.C. + */ + +static TCHAR szIconOnly[]=TEXT("IconOnly"); //Where to stop to exclude label. + + + + +/* + * OleUIMetafilePictIconFree + * + * Purpose: + * Deletes the metafile contained in a METAFILEPICT structure and + * frees the memory for the structure itself. + * + * Parameters: + * hMetaPict HGLOBAL metafilepict structure created in + * OleUIMetafilePictFromIconAndLabel + * + * Return Value: + * None + */ + +STDAPI_(void) OleUIMetafilePictIconFree(HGLOBAL hMetaPict) + { + LPMETAFILEPICT pMF; + + if (NULL==hMetaPict) + return; + + pMF=(LPMETAFILEPICT)GlobalLock(hMetaPict); + + if (NULL!=pMF) + { + if (NULL!=pMF->hMF) + DeleteMetaFile(pMF->hMF); + } + + GlobalUnlock(hMetaPict); + GlobalFree(hMetaPict); + return; + } + + + + + + + + +/* + * OleUIMetafilePictIconDraw + * + * Purpose: + * Draws the metafile from OleUIMetafilePictFromIconAndLabel, either with + * the label or without. + * + * Parameters: + * hDC HDC on which to draw. + * pRect LPRECT in which to draw the metafile. + * hMetaPict HGLOBAL to the METAFILEPICT from + * OleUIMetafilePictFromIconAndLabel + * fIconOnly BOOL specifying to draw the label or not. + * + * Return Value: + * BOOL TRUE if the function is successful, FALSE if the + * given metafilepict is invalid. + */ + +STDAPI_(BOOL) OleUIMetafilePictIconDraw(HDC hDC, LPRECT pRect, HGLOBAL hMetaPict + , BOOL fIconOnly) + { + LPMETAFILEPICT pMF; + DRAWINFO di; + int cx, cy; + SIZE size; + POINT point; + + if (NULL==hMetaPict) + return FALSE; + + pMF=GlobalLock(hMetaPict); + + if (NULL==pMF) + return FALSE; + + di.Rect = *pRect; + di.fIconOnly = fIconOnly; + + //Transform to back to pixels + cx=XformWidthInHimetricToPixels(hDC, pMF->xExt); + cy=XformHeightInHimetricToPixels(hDC, pMF->yExt); + + SaveDC(hDC); + + SetMapMode(hDC, pMF->mm); + SetViewportOrgEx(hDC, (pRect->right - cx) / 2, 0, &point); + + SetViewportExtEx(hDC, min ((pRect->right - cx) / 2 + cx, cx), cy, &size); + + if (fIconOnly) + { + // Since we've used the __export keyword on the + // EnumMetafileIconDraw proc, we do not need to use + // MakeProcInstance + EnumMetaFile(hDC, pMF->hMF, (MFENUMPROC)EnumMetafileIconDraw + , (LPARAM)(LPDRAWINFO)&di); + } + else + PlayMetaFile(hDC, pMF->hMF); + + RestoreDC(hDC, -1); + + GlobalUnlock(hMetaPict); + return TRUE; + } + + + + +/* + * EnumMetafileIconDraw + * + * Purpose: + * EnumMetaFile callback function that draws either the icon only or + * the icon and label depending on given flags. + * + * Parameters: + * hDC HDC into which the metafile should be played. + * phTable HANDLETABLE FAR * providing handles selected into the DC. + * pMFR METARECORD FAR * giving the enumerated record. + * lParam LPARAM flags passed in EnumMetaFile. + * + * Return Value: + * int 0 to stop enumeration, 1 to continue. + */ + +int CALLBACK EXPORT EnumMetafileIconDraw(HDC hDC, HANDLETABLE FAR *phTable + , METARECORD FAR *pMFR, int cObj, LPARAM lParam) + { + LPDRAWINFO lpdi = (LPDRAWINFO)lParam; + + /* + * We play everything blindly except for DIBBITBLT (or DIBSTRETCHBLT) + * and ESCAPE with MFCOMMENT. For the BitBlts we change the x,y to + * draw at (0,0) instead of wherever it was written to draw. The + * comment tells us there to stop if we don't want to draw the label. + */ + + //If we're playing icon only, stop enumeration at the comment. + if (lpdi->fIconOnly) + { + if (META_ESCAPE==pMFR->rdFunction && MFCOMMENT==pMFR->rdParm[0]) + { + if (0==lstrcmpi(szIconOnly, (LPTSTR)&pMFR->rdParm[2])) + return 0; + } + + /* + * Check for the records in which we want to munge the coordinates. + * destX is offset 6 for BitBlt, offset 9 for StretchBlt, either of + * which may appear in the metafile. + */ + if (META_DIBBITBLT==pMFR->rdFunction) + pMFR->rdParm[6]=0; + + if (META_DIBSTRETCHBLT==pMFR->rdFunction) + pMFR->rdParm[9] = 0; + + } + + + PlayMetaFileRecord(hDC, phTable, pMFR, cObj); + return 1; + } + + + + + +/* + * OleUIMetafilePictExtractLabel + * + * Purpose: + * Retrieves the label string from metafile representation of an icon. + * + * Parameters: + * hMetaPict HGLOBAL to the METAFILEPICT containing the metafile. + * lpszLabel LPSTR in which to store the label. + * cchLabel UINT length of lpszLabel. + * lpWrapIndex DWORD index of first character in last line. Can be NULL + * if calling function doesn't care about word wrap. + * + * Return Value: + * UINT Number of characters copied. + */ +STDAPI_(UINT) OleUIMetafilePictExtractLabel(HGLOBAL hMetaPict, LPTSTR lpszLabel + , UINT cchLabel, LPDWORD lpWrapIndex) + { + LPMETAFILEPICT pMF; + LABELEXTRACT le; + HDC hDC; + + /* + * We extract the label by getting a screen DC and walking the metafile + * records until we see the ExtTextOut record we put there. That + * record will have the string embedded in it which we then copy out. + */ + + if (NULL==hMetaPict || NULL==lpszLabel || 0==cchLabel) + return FALSE; + + pMF=GlobalLock(hMetaPict); + + if (NULL==pMF) + return FALSE; + + le.lpsz=lpszLabel; + le.u.cch=cchLabel; + le.Index=0; + le.fFoundIconOnly=FALSE; + le.fFoundSource=FALSE; //Unused for this function. + le.fFoundIndex=FALSE; //Unused for this function. + le.PrevIndex = 0; + + //Use a screen DC so we have something valid to pass in. + hDC=GetDC(NULL); + + // Since we've used the EXPORT keyword on the + // EnumMetafileExtractLabel proc, we do not need to use + // MakeProcInstance + + EnumMetaFile(hDC, pMF->hMF, (MFENUMPROC)EnumMetafileExtractLabel, (LONG)(LPLABELEXTRACT)&le); + + ReleaseDC(NULL, hDC); + + GlobalUnlock(hMetaPict); + + //Tell where we wrapped (if calling function cares) + if (NULL != lpWrapIndex) + *lpWrapIndex = le.PrevIndex; + + //Return amount of text copied + return le.u.cch; + } + + + + + +/* + * EnumMetafileExtractLabel + * + * Purpose: + * EnumMetaFile callback function that walks a metafile looking for + * ExtTextOut, then concatenates the text from each one into a buffer + * in lParam. + * + * Parameters: + * hDC HDC into which the metafile should be played. + * phTable HANDLETABLE FAR * providing handles selected into the DC. + * pMFR METARECORD FAR * giving the enumerated record. + * pLE LPLABELEXTRACT providing the destination buffer and length. + * + * Return Value: + * int 0 to stop enumeration, 1 to continue. + */ + +int CALLBACK EXPORT EnumMetafileExtractLabel(HDC hDC, HANDLETABLE FAR *phTable + , METARECORD FAR *pMFR, int cObj, LPLABELEXTRACT pLE) + { + + /* + * We don't allow anything to happen until we see "IconOnly" + * in an MFCOMMENT that is used to enable everything else. + */ + if (!pLE->fFoundIconOnly) + { + if (META_ESCAPE==pMFR->rdFunction && MFCOMMENT==pMFR->rdParm[0]) + { + if (0==lstrcmpi(szIconOnly, (LPTSTR)&pMFR->rdParm[2])) + pLE->fFoundIconOnly=TRUE; + } + + return 1; + } + + //Enumerate all records looking for META_EXTTEXTOUT - there can be more + //than one. + if (META_EXTTEXTOUT==pMFR->rdFunction) + { + UINT cchMax; + LPTSTR lpszTemp; + + /* + * If ExtTextOut has NULL fuOptions, then the rectangle is omitted + * from the record, and the string starts at rdParm[4]. If + * fuOptions is non-NULL, then the string starts at rdParm[8] + * (since the rectange takes up four WORDs in the array). In + * both cases, the string continues for (rdParm[2]+1) >> 1 + * words. We just cast a pointer to rdParm[8] to an LPSTR and + * lstrcpyn into the buffer we were given. + * + * Note that we use element 8 in rdParm instead of 4 because we + * passed ETO_CLIPPED in for the options on ExtTextOut--docs say + * [4] which is rect doesn't exist if we passed zero there. + * + */ + + cchMax=min(pLE->u.cch - pLE->Index, (UINT)pMFR->rdParm[2]); + lpszTemp = pLE->lpsz + pLE->Index; + + lstrcpyn(lpszTemp, (LPTSTR)&(pMFR->rdParm[8]), cchMax + 1); +// lstrcpyn(lpszTemp, (LPTSTR)&(pMFR->rdParm[4]), cchMax + 1); + + pLE->PrevIndex = pLE->Index; + + pLE->Index += cchMax; + } + + return 1; + } + + + + + +/* + * OleUIMetafilePictExtractIcon + * + * Purpose: + * Retrieves the icon from metafile into which DrawIcon was done before. + * + * Parameters: + * hMetaPict HGLOBAL to the METAFILEPICT containing the metafile. + * + * Return Value: + * HICON Icon recreated from the data in the metafile. + */ +STDAPI_(HICON) OleUIMetafilePictExtractIcon(HGLOBAL hMetaPict) + { + LPMETAFILEPICT pMF; + HDC hDC; + ICONEXTRACT ie; + + /* + * We extract the label by getting a screen DC and walking the metafile + * records until we see the ExtTextOut record we put there. That + * record will have the string embedded in it which we then copy out. + */ + + if (NULL==hMetaPict) + return NULL; + + pMF=GlobalLock(hMetaPict); + + if (NULL==pMF) + return FALSE; + + //Use a screen DC so we have something valid to pass in. + hDC=GetDC(NULL); + ie.fAND=TRUE; + + // We get information back in the ICONEXTRACT structure. + // (Since we've used the EXPORT keyword on the + // EnumMetafileExtractLabel proc, we do not need to use + // MakeProcInstance) + EnumMetaFile(hDC, pMF->hMF, (MFENUMPROC)EnumMetafileExtractIcon, (LONG)(LPICONEXTRACT)&ie); + + ReleaseDC(NULL, hDC); + GlobalUnlock(hMetaPict); + + return ie.hIcon; + } + + + + + +/* + * EnumMetafileExtractIcon + * + * Purpose: + * EnumMetaFile callback function that walks a metafile looking for + * StretchBlt (3.1) and BitBlt (3.0) records. We expect to see two + * of them, the first being the AND mask and the second being the XOR + * data. We + * ExtTextOut, then copies the text into a buffer in lParam. + * + * Parameters: + * hDC HDC into which the metafile should be played. + * phTable HANDLETABLE FAR * providing handles selected into the DC. + * pMFR METARECORD FAR * giving the enumerated record. + * pIE LPICONEXTRACT providing the destination buffer and length. + * + * Return Value: + * int 0 to stop enumeration, 1 to continue. + */ + +int CALLBACK EXPORT EnumMetafileExtractIcon(HDC hDC, HANDLETABLE FAR *phTable + , METARECORD FAR *pMFR, int cObj, LPICONEXTRACT pIE) + { + LPBITMAPINFO lpBI; + LPBITMAPINFOHEADER lpBH; + LPBYTE lpbSrc; + LPBYTE lpbDst; + UINT uWidth, uHeight; + DWORD cb; + HGLOBAL hMem; + BITMAP bm; + HBITMAP hBmp; + int cxIcon, cyIcon; + + + //Continue enumeration if we don't see the records we want. + if (META_DIBBITBLT!=pMFR->rdFunction && META_DIBSTRETCHBLT!=pMFR->rdFunction) + return 1; + + /* + * Windows 3.0 DrawIcon uses META_DIBBITBLT in whereas 3.1 uses + * META_DIBSTRETCHBLT so we have to handle each case separately. + */ + + if (META_DIBBITBLT==pMFR->rdFunction) //Win3.0 + { + //Get dimensions and the BITMAPINFO struct. + uHeight=pMFR->rdParm[1]; + uWidth =pMFR->rdParm[2]; + lpBI=(LPBITMAPINFO)&(pMFR->rdParm[8]); + } + + if (META_DIBSTRETCHBLT==pMFR->rdFunction) //Win3.1 + { + //Get dimensions and the BITMAPINFO struct. + uHeight=pMFR->rdParm[2]; + uWidth =pMFR->rdParm[3]; + lpBI=(LPBITMAPINFO)&(pMFR->rdParm[10]); + } + + lpBH=(LPBITMAPINFOHEADER)&(lpBI->bmiHeader); + + //Pointer to the bits which follows the BITMAPINFO structure. + lpbSrc=(LPBYTE)lpBI+sizeof(BITMAPINFOHEADER); + + //Add the length of the color table (if one exists) + + if (0!=lpBH->biClrUsed) + { + // If we have an explicit count of colors used, we + // can find the offset to the data directly + + lpbSrc += (lpBH->biClrUsed*sizeof(RGBQUAD)); + } + else if (lpBH->biCompression == BI_BITFIELDS) + { + // 16 or 32 bpp, indicated by BI_BITFIELDS in the compression + // field, have 3 DWORD masks for adjusting subsequent + // direct-color values, and no palette + + lpbSrc += 3 * sizeof(DWORD); + } + else + { + // In other cases, there is an array of RGBQUAD entries + // equal to 2^(biBitCount) where biBitCount is the number + // of bits per pixel. The exception is 24 bpp bitmaps, + // which have no color table and just use direct RGB values. + + lpbSrc+= + (lpBH->biBitCount == 24) ? 0 : + (1 << (lpBH->biBitCount)) * sizeof(RGBQUAD); + } + + + /* + * All the bits we have in lpbSrc are device-independent, so we + * need to change them over to be device-dependent using SetDIBits. + * Once we have a bitmap with the device-dependent bits, we can + * GetBitmapBits to have buffers with the real data. + * + * For each pass we have to allocate memory for the bits. We save + * the memory for the mask between passes. + */ + + //Use CreateBitmap for ANY monochrome bitmaps + if (pIE->fAND || 1==lpBH->biBitCount || lpBH->biBitCount > 8) + hBmp=CreateBitmap((UINT)lpBH->biWidth, (UINT)lpBH->biHeight, 1, 1, NULL); + else if (lpBH->biBitCount <= 8) + hBmp=CreateCompatibleBitmap(hDC, (UINT)lpBH->biWidth, (UINT)lpBH->biHeight); + + if (!hBmp || !SetDIBits(hDC, hBmp, 0, (UINT)lpBH->biHeight, (LPVOID)lpbSrc, lpBI, DIB_RGB_COLORS)) + { + if (!pIE->fAND) + GlobalFree(pIE->hMemAND); + + DeleteObject(hBmp); + return 0; + } + + //Allocate memory and get the DDBits into it. + GetObject(hBmp, sizeof(bm), &bm); + + cb=bm.bmHeight*bm.bmWidthBytes * bm.bmPlanes; + +// if (cb % 4 != 0) // dword align +// cb += 4 - (cb % 4); + + hMem=GlobalAlloc(GHND, cb); + + if (NULL==hMem) + { + if (NULL!=pIE->hMemAND) + GlobalFree(pIE->hMemAND); + + DeleteObject(hBmp); + return 0; + } + + lpbDst=(LPBYTE)GlobalLock(hMem); + GetBitmapBits(hBmp, cb, (LPVOID)lpbDst); + + DeleteObject(hBmp); + GlobalUnlock(hMem); + + + /* + * If this is the first pass (pIE->fAND==TRUE) then save the memory + * of the AND bits for the next pass. + */ + if (pIE->fAND) + { + pIE->fAND=FALSE; + pIE->hMemAND=hMem; + + //Continue enumeration looking for the next blt record. + return 1; + } + else + { + //Get the AND pointer again. + lpbSrc=(LPBYTE)GlobalLock(pIE->hMemAND); + + /* + * Create the icon now that we have all the data. lpbDst already + * points to the XOR bits. + */ + cxIcon = GetSystemMetrics(SM_CXICON); + cyIcon = GetSystemMetrics(SM_CYICON); + + pIE->hIcon=CreateIcon(ghInst, + uWidth, + uHeight, + (BYTE)bm.bmPlanes, + (BYTE)bm.bmBitsPixel, + (LPVOID)lpbSrc, + (LPVOID)lpbDst); + + GlobalUnlock(pIE->hMemAND); + GlobalFree(pIE->hMemAND); + GlobalFree(hMem); + + //We're done so we can stop. + return 0; + } + } + + + + + +/* + * OleUIMetafilePictExtractIconSource + * + * Purpose: + * Retrieves the filename and index of the icon source from a metafile + * created with OleUIMetafilePictFromIconAndLabel. + * + * Parameters: + * hMetaPict HGLOBAL to the METAFILEPICT containing the metafile. + * lpszSource LPTSTR in which to store the source filename. This + * buffer should be OLEUI_CCHPATHMAX characters. + * piIcon UINT FAR * in which to store the icon's index + * within lpszSource + * + * Return Value: + * BOOL TRUE if the records were found, FALSE otherwise. + */ +STDAPI_(BOOL) OleUIMetafilePictExtractIconSource(HGLOBAL hMetaPict + , LPTSTR lpszSource, UINT FAR *piIcon) + { + LPMETAFILEPICT pMF; + LABELEXTRACT le; + HDC hDC; + + /* + * We will walk the metafile looking for the two comment records + * following the IconOnly comment. The flags fFoundIconOnly and + * fFoundSource indicate if we have found IconOnly and if we have + * found the source comment already. + */ + + if (NULL==hMetaPict || NULL==lpszSource || NULL==piIcon) + return FALSE; + + pMF=GlobalLock(hMetaPict); + + if (NULL==pMF) + return FALSE; + + le.lpsz=lpszSource; + le.fFoundIconOnly=FALSE; + le.fFoundSource=FALSE; + le.fFoundIndex=FALSE; + + //Use a screen DC so we have something valid to pass in. + hDC=GetDC(NULL); + + EnumMetaFile(hDC, pMF->hMF, (MFENUMPROC)EnumMetafileExtractIconSource, (LONG)(LPLABELEXTRACT)&le); + + ReleaseDC(NULL, hDC); + GlobalUnlock(hMetaPict); + + //Copy the icon index to the caller's variable. + *piIcon=le.u.iIcon; + + //Check that we found everything. + return (le.fFoundIconOnly && le.fFoundSource && le.fFoundIndex); + } + + + + + +/* + * EnumMetafileExtractIconSource + * + * Purpose: + * EnumMetaFile callback function that walks a metafile skipping the first + * comment record, extracting the source filename from the second, and + * the index of the icon in the third. + * + * Parameters: + * hDC HDC into which the metafile should be played. + * phTable HANDLETABLE FAR * providing handles selected into the DC. + * pMFR METARECORD FAR * giving the enumerated record. + * pLE LPLABELEXTRACT providing the destination buffer and + * area to store the icon index. + * + * Return Value: + * int 0 to stop enumeration, 1 to continue. + */ + +int CALLBACK EXPORT EnumMetafileExtractIconSource(HDC hDC, HANDLETABLE FAR *phTable + , METARECORD FAR *pMFR, int cObj, LPLABELEXTRACT pLE) + { + LPTSTR psz; + + /* + * We don't allow anything to happen until we see "IconOnly" + * in an MFCOMMENT that is used to enable everything else. + */ + if (!pLE->fFoundIconOnly) + { + if (META_ESCAPE==pMFR->rdFunction && MFCOMMENT==pMFR->rdParm[0]) + { + if (0==lstrcmpi(szIconOnly, (LPTSTR)&pMFR->rdParm[2])) + pLE->fFoundIconOnly=TRUE; + } + + return 1; + } + + //Now see if we find the source string. + if (!pLE->fFoundSource) + { + if (META_ESCAPE==pMFR->rdFunction && MFCOMMENT==pMFR->rdParm[0]) + { + LSTRCPYN(pLE->lpsz, (LPTSTR)&pMFR->rdParm[2], OLEUI_CCHPATHMAX); + pLE->lpsz[OLEUI_CCHPATHMAX-1] = TEXT('\0'); + pLE->fFoundSource=TRUE; + } + + return 1; + } + + //Next comment will be the icon index. + if (META_ESCAPE==pMFR->rdFunction && MFCOMMENT==pMFR->rdParm[0]) + { + /* + * This string contains the icon index in string form, + * so we need to convert back to a UINT. After we see this + * we can stop the enumeration. The comment will have + * a null terminator because we made sure to save it. + */ + psz=(LPTSTR)&pMFR->rdParm[2]; + pLE->u.iIcon=0; + + //Do Ye Olde atoi + while (*psz) + pLE->u.iIcon=(10*pLE->u.iIcon)+((*psz++)-'0'); + + pLE->fFoundIndex=TRUE; + return 0; + } + + return 1; + } diff --git a/private/oleutest/letest/ole2ui/edlinks.h b/private/oleutest/letest/ole2ui/edlinks.h new file mode 100644 index 000000000..db721f47f --- /dev/null +++ b/private/oleutest/letest/ole2ui/edlinks.h @@ -0,0 +1,135 @@ +/* + * EDLINKS.H + * + * Internal definitions, structures, and function prototypes for the + * OLE 2.0 UI Edit Links dialog. + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + + +#ifndef _LINKS_H_ +#define _LINKS_H_ + +//INTERNAL INFORMATION STARTS HERE +#define OLEUI_SZMAX 255 +#define LINKTYPELEN 9 +#define szNULL TEXT("\0") + +typedef UINT (CALLBACK* COMMDLGHOOKPROC)(HWND, UINT, WPARAM, LPARAM); + +//Internally used structure + +typedef struct tagLINKINFO + { + DWORD dwLink; // app specific identifier of a link + LPTSTR lpszDisplayName; // file based part of name + LPTSTR lpszItemName; // object part of name + LPTSTR lpszShortFileName; // filename without path + LPTSTR lpszShortLinkType; // Short link type - progID + LPTSTR lpszFullLinkType; // Full link type - user friendly name + LPTSTR lpszAMX; // Is the link auto (A) man (M) or dead (X) + ULONG clenFileName; // count of file part of mon. + BOOL fSourceAvailable; // bound or not - on boot assume yes?? + BOOL fIsAuto; // 1 =automatic, 0=manual update + BOOL fIsMarked; // 1 = marked, 0 = not + BOOL fDontFree; // Don't free this data since it's being reused + BOOL fIsSelected; // item selected or to be selected + } LINKINFO, FAR* LPLINKINFO; + + /* + * What we store extra in this structure besides the original caller's + * pointer are those fields that we need to modify during the life of + * the dialog but that we don't want to change in the original structure + * until the user presses OK. + */ + +typedef struct tagEDITLINKS + { + //Keep this item first as the Standard* functions depend on it here. + + LPOLEUIEDITLINKS lpOEL; //Original structure passed. + + BOOL fClose; // Does the button read cancel (0) or + // close (1)? + int *rgIndex; // Array to hold indexes of selected items + int cSelItems; // Number of selected items + BOOL fItemsExist; // TRUE, items in lbox, FALSE, none + UINT nChgSrcHelpID; // ID for Help callback from ChangeSrc dlg + TCHAR szClose[50]; // Text for Close button + // (when Cancel button gets renamed) +} EDITLINKS, *PEDITLINKS, FAR *LPEDITLINKS; + +// Data to and from the ChangeSource dialog hook +typedef struct tagOLEUICHANGESOURCEHOOKDATA +{ + //These IN fields are standard across all OLEUI dialog functions. + DWORD cbStruct; //Structure Size + DWORD dwFlags; //IN-OUT: Flags + HWND hWndOwner; //Owning window + LPCTSTR lpszCaption; //Dialog caption bar contents + LPFNOLEUIHOOK lpfnHook; //Hook callback + LPARAM lCustData; //Custom data to pass to hook + HINSTANCE hInstance; //Instance for customized template name + LPCTSTR lpszTemplate; //Customized template name + HRSRC hResource; //Customized template handle + + //Specifics for OLEUIINSERTOBJECT. All are IN-OUT unless otherwise spec. + LPLINKINFO lpLI; // IN: ptr to LinkInfo entry + LPEDITLINKS lpEL; // IN: ptr to EditLinks dialog struct + BOOL fValidLink; // OUT: was link source validated + LPTSTR lpszFrom; // OUT: string containing prefix of + // source changed from + LPTSTR lpszTo; // OUT: string containing prefix of + // source changed to +} OLEUICHANGESOURCEHOOKDATA, *POLEUICHANGESOURCEHOOKDATA, + FAR *LPOLEUICHANGESOURCEHOOKDATA; + + +// Data to and from the ChangeSource dialog hook +typedef struct tagCHANGESOURCEHOOKDATA +{ + LPOLEUICHANGESOURCEHOOKDATA lpOCshData; //Original structure passed. + LPOPENFILENAME lpOfn; + BOOL fValidLink; + int nFileLength; + int nEditLength; + TCHAR szFileName[OLEUI_CCHPATHMAX]; + TCHAR szItemName[OLEUI_CCHPATHMAX]; + BOOL bFileNameStored; + BOOL bItemNameStored; + TCHAR szEdit[OLEUI_CCHPATHMAX]; + LPTSTR lpszFrom; // string containing prefix of source + // changed from + LPTSTR lpszTo; // string containing prefix of source + // source changed to +} CHANGESOURCEHOOKDATA, *PCHANGESOURCEHOOKDATA, FAR *LPCHANGESOURCEHOOKDATA; + + +//Internal function prototypes +//LINKS.C +BOOL CALLBACK EXPORT EditLinksDialogProc(HWND, UINT, WPARAM, LPARAM); +BOOL FEditLinksInit(HWND, WPARAM, LPARAM); +BOOL Container_ChangeSource(HWND, LPEDITLINKS); +HRESULT Container_AutomaticManual(HWND, BOOL, LPEDITLINKS); +HRESULT CancelLink(HWND, LPEDITLINKS); +HRESULT Container_UpdateNow(HWND, LPEDITLINKS); +HRESULT Container_OpenSource(HWND, LPEDITLINKS); +int AddLinkLBItem(HWND hListBox, LPOLEUILINKCONTAINER lpOleUILinkCntr, LPLINKINFO lpLI, BOOL fGetSelected); +VOID BreakString(LPLINKINFO); +int GetSelectedItems(HWND, int FAR* FAR*); +BOOL WINAPI ChangeSource(HWND hWndOwner, + LPTSTR lpszFile, + UINT cchFile, + UINT iFilterString, + COMMDLGHOOKPROC lpfnBrowseHook, + LPOLEUICHANGESOURCEHOOKDATA lpLbhData); +UINT CALLBACK EXPORT ChangeSourceHook(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); +VOID InitControls(HWND hDlg, LPEDITLINKS lpEL); +VOID UpdateLinkLBItem(HWND hListBox, int nIndex, LPEDITLINKS lpEL, BOOL bSelect); +VOID DiffPrefix(LPCTSTR lpsz1, LPCTSTR lpsz2, TCHAR FAR* FAR* lplpszPrefix1, TCHAR FAR* FAR* lplpszPrefix2); +int PopupMessage(HWND hwndParent, UINT idTitle, UINT idMessage, UINT fuStyle); +VOID ChangeAllLinks(HWND hLIstBox, LPOLEUILINKCONTAINER lpOleUILinkCntr, LPTSTR lpszFrom, LPTSTR lpszTo); +int LoadLinkLB(HWND hListBox, LPOLEUILINKCONTAINER lpOleUILinkCntr); +VOID RefreshLinkLB(HWND hListBox, LPOLEUILINKCONTAINER lpOleUILinkCntr); +#endif // __LINKS_H__ diff --git a/private/oleutest/letest/ole2ui/egares.bmp b/private/oleutest/letest/ole2ui/egares.bmp new file mode 100644 index 000000000..e9dbb065a Binary files /dev/null and b/private/oleutest/letest/ole2ui/egares.bmp differ diff --git a/private/oleutest/letest/ole2ui/enumfetc.c b/private/oleutest/letest/ole2ui/enumfetc.c new file mode 100644 index 000000000..15a6b3a90 --- /dev/null +++ b/private/oleutest/letest/ole2ui/enumfetc.c @@ -0,0 +1,308 @@ +/************************************************************************* +** +** OLE 2 Utility Code +** +** enumfetc.c +** +** This file contains a standard implementation of IEnumFormatEtc +** interface. +** This file is part of the OLE 2.0 User Interface support library. +** +** (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved +** +*************************************************************************/ + +#define STRICT 1 +#include "ole2ui.h" +#include "enumfetc.h" + + +typedef struct tagOleStdEnumFmtEtc { + IEnumFORMATETCVtbl FAR* lpVtbl; + ULONG m_dwRefs; /* referance count */ + ULONG m_nIndex; /* current index in list */ + ULONG m_nCount; /* how many items in list */ + LPFORMATETC m_lpEtc; /* list of formatetc */ +} OLESTDENUMFMTETC, FAR* LPOLESTDENUMFMTETC; + +VOID OleStdEnumFmtEtc_Destroy(LPOLESTDENUMFMTETC pEtc); + +STDMETHODIMP OleStdEnumFmtEtc_QueryInterface( + LPENUMFORMATETC lpThis, REFIID riid, LPVOID FAR* ppobj); +STDMETHODIMP_(ULONG) OleStdEnumFmtEtc_AddRef(LPENUMFORMATETC lpThis); +STDMETHODIMP_(ULONG) OleStdEnumFmtEtc_Release(LPENUMFORMATETC lpThis); +STDMETHODIMP OleStdEnumFmtEtc_Next(LPENUMFORMATETC lpThis, ULONG celt, + LPFORMATETC rgelt, ULONG FAR* pceltFetched); +STDMETHODIMP OleStdEnumFmtEtc_Skip(LPENUMFORMATETC lpThis, ULONG celt); +STDMETHODIMP OleStdEnumFmtEtc_Reset(LPENUMFORMATETC lpThis); +STDMETHODIMP OleStdEnumFmtEtc_Clone(LPENUMFORMATETC lpThis, + LPENUMFORMATETC FAR* ppenum); + +static IEnumFORMATETCVtbl g_EnumFORMATETCVtbl = { + OleStdEnumFmtEtc_QueryInterface, + OleStdEnumFmtEtc_AddRef, + OleStdEnumFmtEtc_Release, + OleStdEnumFmtEtc_Next, + OleStdEnumFmtEtc_Skip, + OleStdEnumFmtEtc_Reset, + OleStdEnumFmtEtc_Clone, +}; + +///////////////////////////////////////////////////////////////////////////// + + +STDAPI_(LPENUMFORMATETC) + OleStdEnumFmtEtc_Create(ULONG nCount, LPFORMATETC lpEtc) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +{ + LPMALLOC lpMalloc=NULL; + LPOLESTDENUMFMTETC lpEF=NULL; + DWORD dwSize; + WORD i; + HRESULT hRes; + + hRes = CoGetMalloc(MEMCTX_TASK, &lpMalloc); + if (hRes != NOERROR) { + return NULL; + } + + lpEF = (LPOLESTDENUMFMTETC)lpMalloc->lpVtbl->Alloc(lpMalloc, + sizeof(OLESTDENUMFMTETC)); + if (lpEF == NULL) { + goto errReturn; + } + + lpEF->lpVtbl = &g_EnumFORMATETCVtbl; + lpEF->m_dwRefs = 1; + lpEF->m_nCount = nCount; + lpEF->m_nIndex = 0; + + dwSize = sizeof(FORMATETC) * lpEF->m_nCount; + + lpEF->m_lpEtc = (LPFORMATETC)lpMalloc->lpVtbl->Alloc(lpMalloc, dwSize); + if (lpEF->m_lpEtc == NULL) + goto errReturn; + + lpMalloc->lpVtbl->Release(lpMalloc); + + for (i=0; im_lpEtc[i]), (LPFORMATETC)&(lpEtc[i])); + } + + return (LPENUMFORMATETC)lpEF; + +errReturn: + if (lpEF != NULL) + lpMalloc->lpVtbl->Free(lpMalloc, lpEF); + + if (lpMalloc != NULL) + lpMalloc->lpVtbl->Release(lpMalloc); + + return NULL; + +} /* OleStdEnumFmtEtc_Create() + */ + + +VOID + OleStdEnumFmtEtc_Destroy(LPOLESTDENUMFMTETC lpEF) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +{ + LPMALLOC lpMalloc=NULL; + WORD i; + + if (lpEF != NULL) { + + if (CoGetMalloc(MEMCTX_TASK, &lpMalloc) == NOERROR) { + + /* OLE2NOTE: we MUST free any memory that was allocated for + ** TARGETDEVICES contained within the FORMATETC elements. + */ + for (i=0; im_nCount; i++) { + OleStdFree(lpEF->m_lpEtc[i].ptd); + } + + if (lpEF->m_lpEtc != NULL) { + lpMalloc->lpVtbl->Free(lpMalloc, lpEF->m_lpEtc); + } + + lpMalloc->lpVtbl->Free(lpMalloc, lpEF); + lpMalloc->lpVtbl->Release(lpMalloc); + } + } +} /* OleStdEnumFmtEtc_Destroy() + */ + + +STDMETHODIMP + OleStdEnumFmtEtc_QueryInterface( + LPENUMFORMATETC lpThis, REFIID riid, LPVOID FAR* ppobj) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +{ + LPOLESTDENUMFMTETC lpEF = (LPOLESTDENUMFMTETC)lpThis; + *ppobj = NULL; + + if (IsEqualIID(riid,&IID_IUnknown) || IsEqualIID(riid,&IID_IEnumFORMATETC)){ + *ppobj = (LPVOID)lpEF; + } + + if (*ppobj == NULL) return ResultFromScode(E_NOINTERFACE); + else{ + OleStdEnumFmtEtc_AddRef(lpThis); + return NOERROR; + } + +} /* OleStdEnumFmtEtc_QueryInterface() + */ + + +STDMETHODIMP_(ULONG) + OleStdEnumFmtEtc_AddRef(LPENUMFORMATETC lpThis) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +{ + LPOLESTDENUMFMTETC lpEF = (LPOLESTDENUMFMTETC)lpThis; + return lpEF->m_dwRefs++; + +} /* OleStdEnumFmtEtc_AddRef() + */ + + +STDMETHODIMP_(ULONG) + OleStdEnumFmtEtc_Release(LPENUMFORMATETC lpThis) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +{ + LPOLESTDENUMFMTETC lpEF = (LPOLESTDENUMFMTETC)lpThis; + DWORD dwRefs = --lpEF->m_dwRefs; + + if (dwRefs == 0) + OleStdEnumFmtEtc_Destroy(lpEF); + + return dwRefs; + +} /* OleStdEnumFmtEtc_Release() + */ + + +STDMETHODIMP + OleStdEnumFmtEtc_Next(LPENUMFORMATETC lpThis, ULONG celt, LPFORMATETC rgelt, + ULONG FAR* pceltFetched) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +{ + LPOLESTDENUMFMTETC lpEF = (LPOLESTDENUMFMTETC)lpThis; + ULONG i=0; + ULONG nOffset; + + if (rgelt == NULL) { + return ResultFromScode(E_INVALIDARG); + } + + while (i < celt) { + nOffset = lpEF->m_nIndex + i; + + if (nOffset < lpEF->m_nCount) { + OleStdCopyFormatEtc( + (LPFORMATETC)&(rgelt[i]), (LPFORMATETC)&(lpEF->m_lpEtc[nOffset])); + i++; + }else{ + break; + } + } + + lpEF->m_nIndex += (WORD)i; + + if (pceltFetched != NULL) { + *pceltFetched = i; + } + + if (i != celt) { + return ResultFromScode(S_FALSE); + } + + return NOERROR; +} /* OleStdEnumFmtEtc_Next() + */ + + +STDMETHODIMP + OleStdEnumFmtEtc_Skip(LPENUMFORMATETC lpThis, ULONG celt) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +{ + LPOLESTDENUMFMTETC lpEF = (LPOLESTDENUMFMTETC)lpThis; + ULONG i=0; + ULONG nOffset; + + while (i < celt) { + nOffset = lpEF->m_nIndex + i; + + if (nOffset < lpEF->m_nCount) { + i++; + }else{ + break; + } + } + + lpEF->m_nIndex += (WORD)i; + + if (i != celt) { + return ResultFromScode(S_FALSE); + } + + return NOERROR; +} /* OleStdEnumFmtEtc_Skip() + */ + + +STDMETHODIMP + OleStdEnumFmtEtc_Reset(LPENUMFORMATETC lpThis) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +{ + LPOLESTDENUMFMTETC lpEF = (LPOLESTDENUMFMTETC)lpThis; + lpEF->m_nIndex = 0; + + return NOERROR; +} /* OleStdEnumFmtEtc_Reset() + */ + + +STDMETHODIMP + OleStdEnumFmtEtc_Clone(LPENUMFORMATETC lpThis, LPENUMFORMATETC FAR* ppenum) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +{ + LPOLESTDENUMFMTETC lpEF = (LPOLESTDENUMFMTETC)lpThis; + + if (ppenum == NULL) { + return ResultFromScode(E_INVALIDARG); + } + + *ppenum = OleStdEnumFmtEtc_Create(lpEF->m_nCount, lpEF->m_lpEtc); + + // make sure cloned enumerator has same index state as the original + if (*ppenum) { + LPOLESTDENUMFMTETC lpEFClone = (LPOLESTDENUMFMTETC)*ppenum; + lpEFClone->m_nIndex = lpEF->m_nIndex; + return NOERROR; + } else + return ResultFromScode(E_OUTOFMEMORY); + +} /* OleStdEnumFmtEtc_Clone() + */ + diff --git a/private/oleutest/letest/ole2ui/enumfetc.h b/private/oleutest/letest/ole2ui/enumfetc.h new file mode 100644 index 000000000..60b82d151 --- /dev/null +++ b/private/oleutest/letest/ole2ui/enumfetc.h @@ -0,0 +1,13 @@ +// This file is now OBSOLETE (include olestd.h instead) + +/************************************************************************* +** +** OLE 2 Utility Code +** +** enumfetc.c +** +** (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved +** +*************************************************************************/ + +// Function prototypes moved to olestd.h diff --git a/private/oleutest/letest/ole2ui/enumstat.c b/private/oleutest/letest/ole2ui/enumstat.c new file mode 100644 index 000000000..17a42048f --- /dev/null +++ b/private/oleutest/letest/ole2ui/enumstat.c @@ -0,0 +1,336 @@ +/************************************************************************* +** +** OLE 2 Utility Code +** +** enumstat.c +** +** This file contains a standard implementation of IEnumStatData +** interface. +** This file is part of the OLE 2.0 User Interface support library. +** +** (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved +** +*************************************************************************/ + +#define STRICT 1 +#include "ole2ui.h" + + +typedef struct tagOleStdEnumStatData { + IEnumSTATDATAVtbl FAR* lpVtbl; + ULONG m_dwRefs; /* referance count */ + ULONG m_nIndex; /* current index in list */ + ULONG m_nCount; /* how many items in list */ + LPSTATDATA m_lpStat; /* list of STATDATA */ +} OLESTDENUMSTATDATA, FAR* LPOLESTDENUMSTATDATA; + +VOID OleStdEnumStatData_Destroy(LPOLESTDENUMSTATDATA pStat); + +STDMETHODIMP OleStdEnumStatData_QueryInterface( + LPENUMSTATDATA lpThis, REFIID riid, LPVOID FAR* ppobj); +STDMETHODIMP_(ULONG) OleStdEnumStatData_AddRef(LPENUMSTATDATA lpThis); +STDMETHODIMP_(ULONG) OleStdEnumStatData_Release(LPENUMSTATDATA lpThis); +STDMETHODIMP OleStdEnumStatData_Next(LPENUMSTATDATA lpThis, ULONG celt, + LPSTATDATA rgelt, ULONG FAR* pceltFetched); +STDMETHODIMP OleStdEnumStatData_Skip(LPENUMSTATDATA lpThis, ULONG celt); +STDMETHODIMP OleStdEnumStatData_Reset(LPENUMSTATDATA lpThis); +STDMETHODIMP OleStdEnumStatData_Clone(LPENUMSTATDATA lpThis, + LPENUMSTATDATA FAR* ppenum); + +static IEnumSTATDATAVtbl g_EnumSTATDATAVtbl = { + OleStdEnumStatData_QueryInterface, + OleStdEnumStatData_AddRef, + OleStdEnumStatData_Release, + OleStdEnumStatData_Next, + OleStdEnumStatData_Skip, + OleStdEnumStatData_Reset, + OleStdEnumStatData_Clone, +}; + +///////////////////////////////////////////////////////////////////////////// + +STDAPI_(BOOL) + OleStdCopyStatData(LPSTATDATA pDest, LPSTATDATA pSrc) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +{ + if ((pDest == NULL) || (pSrc == NULL)) { + return FALSE; + } + + if (OleStdCopyFormatEtc(&pDest->formatetc, &pSrc->formatetc) == FALSE) { + return FALSE; + } + + pDest->advf = pSrc->advf; + pDest->pAdvSink = pSrc->pAdvSink; + pDest->dwConnection = pSrc->dwConnection; + + if (pDest->pAdvSink != NULL) { + pDest->pAdvSink->lpVtbl->AddRef(pDest->pAdvSink); + } + + return TRUE; + +} /* OleStdCopyStatData() + */ + +STDAPI_(LPENUMSTATDATA) + OleStdEnumStatData_Create(ULONG nCount, LPSTATDATA lpStatOrg) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +{ + LPMALLOC lpMalloc=NULL; + LPOLESTDENUMSTATDATA lpSD=NULL; + DWORD dwSize; + WORD i; + HRESULT hRes; + + hRes = CoGetMalloc(MEMCTX_TASK, &lpMalloc); + if (hRes != NOERROR) { + return NULL; + } + + lpSD = (LPOLESTDENUMSTATDATA)lpMalloc->lpVtbl->Alloc(lpMalloc, + sizeof(OLESTDENUMSTATDATA)); + if (lpSD == NULL) { + goto errReturn; + } + + lpSD->lpVtbl = &g_EnumSTATDATAVtbl; + lpSD->m_dwRefs = 1; + lpSD->m_nCount = nCount; + lpSD->m_nIndex = 0; + + dwSize = sizeof(STATDATA) * lpSD->m_nCount; + + lpSD->m_lpStat = (LPSTATDATA)lpMalloc->lpVtbl->Alloc(lpMalloc, dwSize); + if (lpSD->m_lpStat == NULL) + goto errReturn; + + lpMalloc->lpVtbl->Release(lpMalloc); + + for (i=0; im_lpStat[i]), (LPSTATDATA)&(lpStatOrg[i])); + } + + return (LPENUMSTATDATA)lpSD; + +errReturn: + if (lpSD != NULL) + lpMalloc->lpVtbl->Free(lpMalloc, lpSD); + + if (lpMalloc != NULL) + lpMalloc->lpVtbl->Release(lpMalloc); + + return NULL; + +} /* OleStdEnumStatData_Create() + */ + + +VOID + OleStdEnumStatData_Destroy(LPOLESTDENUMSTATDATA lpSD) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +{ + LPMALLOC lpMalloc=NULL; + WORD i; + + if (lpSD != NULL) { + + if (CoGetMalloc(MEMCTX_TASK, &lpMalloc) == NOERROR) { + + /* OLE2NOTE: we MUST free any memory that was allocated for + ** TARGETDEVICES contained within the STATDATA elements. + */ + for (i=0; im_nCount; i++) { + if( lpSD->m_lpStat[i].pAdvSink ) + lpSD->m_lpStat[i].pAdvSink->lpVtbl->Release(lpSD->m_lpStat[i].pAdvSink); + + OleStdFree(lpSD->m_lpStat[i].formatetc.ptd); + } + + if (lpSD->m_lpStat != NULL) { + lpMalloc->lpVtbl->Free(lpMalloc, lpSD->m_lpStat); + } + + lpMalloc->lpVtbl->Free(lpMalloc, lpSD); + lpMalloc->lpVtbl->Release(lpMalloc); + } + } +} /* OleStdEnumStatData_Destroy() + */ + + +STDMETHODIMP + OleStdEnumStatData_QueryInterface( + LPENUMSTATDATA lpThis, REFIID riid, LPVOID FAR* ppobj) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +{ + LPOLESTDENUMSTATDATA lpSD = (LPOLESTDENUMSTATDATA)lpThis; + *ppobj = NULL; + + if (IsEqualIID(riid,&IID_IUnknown) || IsEqualIID(riid,&IID_IEnumSTATDATA)){ + *ppobj = (LPVOID)lpSD; + } + + if (*ppobj == NULL) return ResultFromScode(E_NOINTERFACE); + else{ + OleStdEnumStatData_AddRef(lpThis); + return NOERROR; + } + +} /* OleStdEnumStatData_QueryInterface() + */ + + +STDMETHODIMP_(ULONG) + OleStdEnumStatData_AddRef(LPENUMSTATDATA lpThis) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +{ + LPOLESTDENUMSTATDATA lpSD = (LPOLESTDENUMSTATDATA)lpThis; + return lpSD->m_dwRefs++; + +} /* OleStdEnumStatData_AddRef() + */ + + +STDMETHODIMP_(ULONG) + OleStdEnumStatData_Release(LPENUMSTATDATA lpThis) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +{ + LPOLESTDENUMSTATDATA lpSD = (LPOLESTDENUMSTATDATA)lpThis; + DWORD dwRefs = --lpSD->m_dwRefs; + + if (dwRefs == 0) + OleStdEnumStatData_Destroy(lpSD); + + return dwRefs; + +} /* OleStdEnumStatData_Release() + */ + + +STDMETHODIMP + OleStdEnumStatData_Next(LPENUMSTATDATA lpThis, ULONG celt, LPSTATDATA rgelt, + ULONG FAR* pceltFetched) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +{ + LPOLESTDENUMSTATDATA lpSD = (LPOLESTDENUMSTATDATA)lpThis; + ULONG i=0; + ULONG nOffset; + + if (rgelt == NULL) { + return ResultFromScode(E_INVALIDARG); + } + + while (i < celt) { + nOffset = lpSD->m_nIndex + i; + + if (nOffset < lpSD->m_nCount) { + OleStdCopyStatData( + (LPSTATDATA)&(rgelt[i]), (LPSTATDATA)&(lpSD->m_lpStat[nOffset])); + i++; + }else{ + break; + } + } + + lpSD->m_nIndex += (WORD)i; + + if (pceltFetched != NULL) { + *pceltFetched = i; + } + + if (i != celt) { + return ResultFromScode(S_FALSE); + } + + return NOERROR; +} /* OleStdEnumStatData_Next() + */ + + +STDMETHODIMP + OleStdEnumStatData_Skip(LPENUMSTATDATA lpThis, ULONG celt) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +{ + LPOLESTDENUMSTATDATA lpSD = (LPOLESTDENUMSTATDATA)lpThis; + ULONG i=0; + ULONG nOffset; + + while (i < celt) { + nOffset = lpSD->m_nIndex + i; + + if (nOffset < lpSD->m_nCount) { + i++; + }else{ + break; + } + } + + lpSD->m_nIndex += (WORD)i; + + if (i != celt) { + return ResultFromScode(S_FALSE); + } + + return NOERROR; +} /* OleStdEnumStatData_Skip() + */ + + +STDMETHODIMP + OleStdEnumStatData_Reset(LPENUMSTATDATA lpThis) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +{ + LPOLESTDENUMSTATDATA lpSD = (LPOLESTDENUMSTATDATA)lpThis; + lpSD->m_nIndex = 0; + + return NOERROR; +} /* OleStdEnumStatData_Reset() + */ + + +STDMETHODIMP + OleStdEnumStatData_Clone(LPENUMSTATDATA lpThis, LPENUMSTATDATA FAR* ppenum) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +{ + LPOLESTDENUMSTATDATA lpSD = (LPOLESTDENUMSTATDATA)lpThis; + + if (ppenum == NULL) { + return ResultFromScode(E_INVALIDARG); + } + + *ppenum = OleStdEnumStatData_Create(lpSD->m_nCount, lpSD->m_lpStat); + + // make sure cloned enumerator has same index state as the original + if (*ppenum) { + LPOLESTDENUMSTATDATA lpSDClone = (LPOLESTDENUMSTATDATA)*ppenum; + lpSDClone->m_nIndex = lpSD->m_nIndex; + return NOERROR; + } else + return ResultFromScode(E_OUTOFMEMORY); + +} /* OleStdEnumStatData_Clone() + */ + diff --git a/private/oleutest/letest/ole2ui/filelist.mk b/private/oleutest/letest/ole2ui/filelist.mk new file mode 100644 index 000000000..1a15317c7 --- /dev/null +++ b/private/oleutest/letest/ole2ui/filelist.mk @@ -0,0 +1,75 @@ +############################################################################ +# +# Microsoft Windows +# Copyright (C) Microsoft Corporation, 1992 - 1992. +# All rights reserved. +# +############################################################################ + + +# +# Name of target. Include an extension (.dll, .lib, .exe) +# If the target is part of the release, set RELEASE to 1. +# + +TARGET = ole2uixd.lib +RELEASE = 0 +TARGET_DESCRIPTION = "$(PLATFORM) $(BUILDTYPE) OLE 2 UI Library" + + +# +# Source files. Remember to prefix each name with .\ +# + +CFILES = .\busy.c \ + .\common.c \ + .\convert.c \ + .\dbgutil.c \ + .\dllfuncs.c \ + .\drawicon.c \ + .\enumfetc.c \ + .\enumstat.c \ + .\geticon.c \ + .\hatch.c \ + .\icon.c \ + .\iconbox.c \ + .\insobj.c \ + .\links.c \ + .\msgfiltr.c \ + .\objfdbk.c \ + .\ole2ui.c \ + .\olestd.c \ + .\oleutl.c \ + .\pastespl.c \ + .\precomp.c \ + .\regdb.c \ + .\resimage.c \ + .\stdpal.c \ + .\targtdev.c \ + .\utility.c + +CPPFILES = .\suminfo.cpp \ + .\dballoc.cpp + +RCFILES = .\ole2ui.rc + +# +# Libraries and other object files to link. +# +OBJFILES = +LIBS = + +DEFFILE = + + +# +# Precompiled headers. +# + +PXXFILE = +PFILE = +CINC = -I$(CAIROLE)\h -I$(CAIROLE)\common \ + -I.\resource\usa -I.\resource\static + +CFLAGS=/DWIN32 /D_DEBUG /DOLE201 /D_INC_OLE + diff --git a/private/oleutest/letest/ole2ui/fileopen.dlg b/private/oleutest/letest/ole2ui/fileopen.dlg new file mode 100644 index 000000000..65f6e91dc --- /dev/null +++ b/private/oleutest/letest/ole2ui/fileopen.dlg @@ -0,0 +1,33 @@ +DLGINCLUDE RCDATA DISCARDABLE +BEGIN + "OLE2UI.H\0" +END + +IDD_FILEOPEN DIALOG 36, 24, 264, 134 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Open" +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "&Source:", stc3, 6, 3, 76, 9 + EDITTEXT edt1, 7, 13, 195, 12, ES_AUTOHSCROLL | ES_OEMCONVERT + LISTBOX lst1, 6, 34, 90, 68, LBS_SORT | LBS_OWNERDRAWFIXED | + LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL | + WS_TABSTOP + LTEXT "&Directories:", ID_DUMMY, 110, 28, 92, 9 + LTEXT "", stc1, 110, 36, 92, 9, SS_NOPREFIX + LISTBOX lst2, 110, 49, 92, 53, LBS_SORT | LBS_OWNERDRAWFIXED | + LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL | + WS_TABSTOP + LTEXT "List Files of &Type:", stc2, 6, 104, 90, 9 + COMBOBOX cmb1, 6, 114, 90, 36, CBS_DROPDOWNLIST | CBS_AUTOHSCROLL | + WS_BORDER | WS_VSCROLL | WS_TABSTOP + LTEXT "Dri&ves:", stc4, 110, 104, 92, 9 + COMBOBOX cmb2, 110, 114, 92, 68, CBS_DROPDOWNLIST | + CBS_OWNERDRAWFIXED | CBS_AUTOHSCROLL | CBS_SORT | + CBS_HASSTRINGS | WS_BORDER | WS_VSCROLL | WS_TABSTOP + DEFPUSHBUTTON "OK", IDOK, 208, 6, 50, 14, WS_GROUP + PUSHBUTTON "Cancel", IDCANCEL, 208, 24, 50, 14, WS_GROUP + PUSHBUTTON "&Help", IDHELP, 208, 46, 50, 14, WS_GROUP + CONTROL "&Read Only", chx1, "Button", BS_AUTOCHECKBOX | WS_GROUP | + WS_TABSTOP, 208, 68, 50, 12 +END diff --git a/private/oleutest/letest/ole2ui/geticon.c b/private/oleutest/letest/ole2ui/geticon.c new file mode 100644 index 000000000..0bf1e13b3 --- /dev/null +++ b/private/oleutest/letest/ole2ui/geticon.c @@ -0,0 +1,1177 @@ +/************************************************************************* +** +** The following API's are now OBSOLETE because equivalent API's have been +** added to the OLE2.DLL library +** GetIconOfFile superceeded by OleGetIconOfFile +** GetIconOfClass superceeded by OleGetIconOfClass +** OleUIMetafilePictFromIconAndLabel +** superceeded by OleMetafilePictFromIconAndLabel +*************************************************************************/ + +/* + * GETICON.C + * + * Functions to create DVASPECT_ICON metafile from filename or classname. + * + * GetIconOfFile + * GetIconOfClass + * OleUIMetafilePictFromIconAndLabel + * HIconAndSourceFromClass Extracts the first icon in a class's server path + * and returns the path and icon index to caller. + * FIconFileFromClass Retrieves the path to the exe/dll containing the + * default icon, and the index of the icon. + * OleStdIconLabelTextOut Draw icon label text (line break if necessary) + * + * (c) Copyright Microsoft Corp. 1992-1993 All Rights Reserved + */ + + +/******* + * + * ICON (DVASPECT_ICON) METAFILE FORMAT: + * + * The metafile generated with OleUIMetafilePictFromIconAndLabel contains + * the following records which are used by the functions in DRAWICON.C + * to draw the icon with and without the label and to extract the icon, + * label, and icon source/index. + * + * SetWindowOrg + * SetWindowExt + * DrawIcon: + * Inserts records of DIBBITBLT or DIBSTRETCHBLT, once for the + * AND mask, one for the image bits. + * Escape with the comment "IconOnly" + * This indicates where to stop record enumeration to draw only + * the icon. + * SetTextColor + * SetTextAlign + * SetBkColor + * CreateFont + * SelectObject on the font. + * ExtTextOut + * One or more ExtTextOuts occur if the label is wrapped. The + * text in these records is used to extract the label. + * SelectObject on the old font. + * DeleteObject on the font. + * Escape with a comment that contains the path to the icon source. + * Escape with a comment that is the ASCII of the icon index. + * + *******/ + +#define STRICT 1 +#include "ole2ui.h" + +#include +#include +#include +#include +#include +#include +#include "common.h" +#include "utility.h" + +static TCHAR szSeparators[] = TEXT(" \t\\/!:"); + +#define IS_SEPARATOR(c) ( (c) == TEXT(' ') || (c) == TEXT('\\') \ + || (c) == TEXT('/') || (c) == TEXT('\t') \ + || (c) == TEXT('!') || (c) == TEXT(':') ) +#define IS_FILENAME_DELIM(c) ( (c) == TEXT('\\') || (c) == TEXT('/') \ + || (c) == TEXT(':') ) + + +#if defined( OBSOLETE ) +static HINSTANCE s_hInst; + +static TCHAR szMaxWidth[] =TEXT("WWWWWWWWWW"); + +//Strings for metafile comments. +static TCHAR szIconOnly[]=TEXT("IconOnly"); //Where to stop to exclude label. + +#ifdef WIN32 +static TCHAR szOLE2DLL[] = TEXT("ole2w32.dll"); // name of OLE 2.0 library +#else +static TCHAR szOLE2DLL[] = TEXT("ole2.dll"); // name of OLE 2.0 library +#endif + +#define ICONINDEX 0 + +#define AUXUSERTYPE_SHORTNAME USERCLASSTYPE_SHORT // short name +#define HIMETRIC_PER_INCH 2540 // number HIMETRIC units per inch +#define PTS_PER_INCH 72 // number points (font size) per inch + +#define MAP_PIX_TO_LOGHIM(x,ppli) MulDiv(HIMETRIC_PER_INCH, (x), (ppli)) +#define MAP_LOGHIM_TO_PIX(x,ppli) MulDiv((ppli), (x), HIMETRIC_PER_INCH) + +static TCHAR szVanillaDocIcon[] = TEXT("DefIcon"); + +static TCHAR szDocument[40] = TEXT(""); + + +/* + * GetIconOfFile(HINSTANCE hInst, LPSTR lpszPath, BOOL fUseFileAsLabel) + * + * Purpose: + * Returns a hMetaPict containing an icon and label (filename) for the + * specified filename. + * + * Parameters: + * hinst + * lpszPath LPTSTR path including filename to use + * fUseFileAsLabel BOOL TRUE if the icon's label is the filename, FALSE if + * there should be no label. + * + * Return Value: + * HGLOBAL hMetaPict containing the icon and label - if there's no + * class in reg db for the file in lpszPath, then we use + * Document. If lpszPath is NULL, then we return NULL. + */ + +STDAPI_(HGLOBAL) GetIconOfFile(HINSTANCE hInst, LPTSTR lpszPath, BOOL fUseFileAsLabel) +{ + TCHAR szIconFile[OLEUI_CCHPATHMAX]; + TCHAR szLabel[OLEUI_CCHLABELMAX]; + LPTSTR lpszClsid = NULL; + CLSID clsid; + HICON hDefIcon = NULL; + UINT IconIndex = 0; + HGLOBAL hMetaPict; + HRESULT hResult; + + if (NULL == lpszPath) // even if fUseFileAsLabel is FALSE, we still + return NULL; // need a valid filename to get the class. + + s_hInst = hInst; + + hResult = GetClassFileA(lpszPath, &clsid); + + if (NOERROR == hResult) // use the clsid we got to get to the icon + { + hDefIcon = HIconAndSourceFromClass(&clsid, + (LPTSTR)szIconFile, + &IconIndex); + } + + if ( (NOERROR != hResult) || (NULL == hDefIcon) ) + { + // Here, either GetClassFile failed or HIconAndSourceFromClass failed. + + LPTSTR lpszTemp; + + lpszTemp = lpszPath; + + while ((*lpszTemp != TEXT('.')) && (*lpszTemp != TEXT('\0'))) + lpszTemp++; + + + if (TEXT('.') != *lpszTemp) + goto UseVanillaDocument; + + + if (FALSE == GetAssociatedExecutable(lpszTemp, (LPTSTR)szIconFile)) + goto UseVanillaDocument; + + hDefIcon = ExtractIcon(s_hInst, szIconFile, IconIndex); + } + + if (hDefIcon <= (HICON)1) // ExtractIcon returns 1 if szExecutable is not exe, + { // 0 if there are no icons. +UseVanillaDocument: + + lstrcpy((LPTSTR)szIconFile, (LPTSTR)szOLE2DLL); + IconIndex = ICONINDEX; + hDefIcon = ExtractIcon(s_hInst, szIconFile, IconIndex); + + } + + // Now let's get the label we want to use. + + if (fUseFileAsLabel) // strip off path, so we just have the filename. + { + int istrlen; + LPTSTR lpszBeginFile; + + istrlen = lstrlen(lpszPath); + + // set pointer to END of path, so we can walk backwards through it. + lpszBeginFile = lpszPath + istrlen -1; + + while ( (lpszBeginFile >= lpszPath) + && (!IS_FILENAME_DELIM(*lpszBeginFile)) ) + lpszBeginFile--; + + + lpszBeginFile++; // step back over the delimiter + + + LSTRCPYN(szLabel, lpszBeginFile, sizeof(szLabel)/sizeof(TCHAR)); + } + + else // use the short user type (AuxUserType2) for the label + { + + if (0 == OleStdGetAuxUserType(&clsid, AUXUSERTYPE_SHORTNAME, + (LPTSTR)szLabel, OLEUI_CCHLABELMAX_SIZE, NULL)) { + + if ('\0'==szDocument[0]) { + LoadString( + s_hInst,IDS_DEFICONLABEL,szDocument,sizeof(szDocument)/sizeof(TCHAR)); + } + lstrcpy(szLabel, szDocument); + } + } + + + hMetaPict = OleUIMetafilePictFromIconAndLabel(hDefIcon, + szLabel, + (LPTSTR)szIconFile, + IconIndex); + + DestroyIcon(hDefIcon); + + return hMetaPict; + +} + + + +/* + * GetIconOfClass(HINSTANCE hInst, REFCLSID rclsid, LPSTR lpszLabel, BOOL fUseTypeAsLabel) + * + * Purpose: + * Returns a hMetaPict containing an icon and label (human-readable form + * of class) for the specified clsid. + * + * Parameters: + * hinst + * rclsid REFCLSID pointing to clsid to use. + * lpszLabel label to use for icon. + * fUseTypeAsLabel Use the clsid's user type name as the icon's label. + * + * Return Value: + * HGLOBAL hMetaPict containing the icon and label - if we + * don't find the clsid in the reg db then we + * return NULL. + */ + +STDAPI_(HGLOBAL) GetIconOfClass(HINSTANCE hInst, REFCLSID rclsid, LPTSTR lpszLabel, BOOL fUseTypeAsLabel) +{ + + TCHAR szLabel[OLEUI_CCHLABELMAX]; + TCHAR szIconFile[OLEUI_CCHPATHMAX]; + HICON hDefIcon; + UINT IconIndex; + HGLOBAL hMetaPict; + + + s_hInst = hInst; + + if (!fUseTypeAsLabel) // Use string passed in as label + { + if (NULL != lpszLabel) + LSTRCPYN(szLabel, lpszLabel, OLEUI_CCHLABELMAX_SIZE); + else + *szLabel = TEXT('\0'); + } + else // Use AuxUserType2 (short name) as label + { + + if (0 == OleStdGetAuxUserType(rclsid, + AUXUSERTYPE_SHORTNAME, + (LPTSTR)szLabel, + OLEUI_CCHLABELMAX_SIZE, + NULL)) + + // If we can't get the AuxUserType2, then try the long name + if (0 == OleStdGetUserTypeOfClass(rclsid, szLabel, OLEUI_CCHKEYMAX_SIZE, NULL)) { + if (TEXT('\0')==szDocument[0]) { + LoadString( + s_hInst,IDS_DEFICONLABEL,szDocument,sizeof(szDocument)/sizeof(TCHAR)); + } + lstrcpy(szLabel, szDocument); // last resort + } + } + + // Get the icon, icon index, and path to icon file + hDefIcon = HIconAndSourceFromClass(rclsid, + (LPTSTR)szIconFile, + &IconIndex); + + if (NULL == hDefIcon) // Use Vanilla Document + { + lstrcpy((LPTSTR)szIconFile, (LPTSTR)szOLE2DLL); + IconIndex = ICONINDEX; + hDefIcon = ExtractIcon(s_hInst, szIconFile, IconIndex); + } + + // Create the metafile + hMetaPict = OleUIMetafilePictFromIconAndLabel(hDefIcon, szLabel, + (LPTSTR)szIconFile, IconIndex); + + DestroyIcon(hDefIcon); + + return hMetaPict; + +} + + +/* + * OleUIMetafilePictFromIconAndLabel + * + * Purpose: + * Creates a METAFILEPICT structure that container a metafile in which + * the icon and label are drawn. A comment record is inserted between + * the icon and the label code so our special draw function can stop + * playing before the label. + * + * Parameters: + * hIcon HICON to draw into the metafile + * pszLabel LPTSTR to the label string. + * pszSourceFile LPTSTR containing the local pathname of the icon + * as we either get from the user or from the reg DB. + * iIcon UINT providing the index into pszSourceFile where + * the icon came from. + * + * Return Value: + * HGLOBAL Global memory handle containing a METAFILEPICT where + * the metafile uses the MM_ANISOTROPIC mapping mode. The + * extents reflect both icon and label. + */ + +STDAPI_(HGLOBAL) OleUIMetafilePictFromIconAndLabel(HICON hIcon, LPTSTR pszLabel + , LPTSTR pszSourceFile, UINT iIcon) + { + HDC hDC, hDCScreen; + HMETAFILE hMF; + HGLOBAL hMem; + LPMETAFILEPICT pMF; + UINT cxIcon, cyIcon; + UINT cxText, cyText; + UINT cx, cy; + UINT cchLabel = 0; + HFONT hFont, hFontT; + int cyFont; + TCHAR szIndex[10]; + RECT TextRect; + SIZE size; + POINT point; + UINT fuAlign; + + if (NULL==hIcon) // null label is valid but NOT a null icon + return NULL; + + //Create a memory metafile + hDC=(HDC)CreateMetaFile(NULL); + + if (NULL==hDC) + return NULL; + + //Allocate the metafilepict + hMem=GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, sizeof(METAFILEPICT)); + + if (NULL==hMem) + { + hMF=CloseMetaFile(hDC); + DeleteMetaFile(hMF); + return NULL; + } + + + if (NULL!=pszLabel) + { + cchLabel=lstrlen(pszLabel); + + if (cchLabel >= OLEUI_CCHLABELMAX) + pszLabel[cchLabel] = TEXT('\0'); // truncate string + } + + //Need to use the screen DC for these operations + hDCScreen=GetDC(NULL); + cyFont=-(8*GetDeviceCaps(hDCScreen, LOGPIXELSY))/72; + + //cyFont was calculated to give us 8 point. + hFont=CreateFont(cyFont, 5, 0, 0, FW_NORMAL, 0, 0, 0, ANSI_CHARSET + , OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY + , FF_SWISS, TEXT("MS Sans Serif")); + + hFontT=SelectObject(hDCScreen, hFont); + + GetTextExtentPoint(hDCScreen,szMaxWidth,lstrlen(szMaxWidth),&size); + SelectObject(hDCScreen, hFontT); + + cxText = size.cx; + cyText = size.cy * 2; + + cxIcon = GetSystemMetrics(SM_CXICON); + cyIcon = GetSystemMetrics(SM_CYICON); + + + // If we have no label, then we want the metafile to be the width of + // the icon (plus margin), not the width of the fattest string. + if ( (NULL == pszLabel) || (TEXT('\0') == *pszLabel) ) + cx = cxIcon + cxIcon / 4; + else + cx = max(cxText, cxIcon); + + cy=cyIcon+cyText+4; + + //Set the metafile size to fit the icon and label + SetWindowOrgEx(hDC, 0, 0, &point); + SetWindowExtEx(hDC, cx, cy, &size); + + //Set up rectangle to pass to OleStdIconLabelTextOut + SetRectEmpty(&TextRect); + + TextRect.right = cx; + TextRect.bottom = cy; + + //Draw the icon and the text, centered with respect to each other. + DrawIcon(hDC, (cx-cxIcon)/2, 0, hIcon); + + //String that indicates where to stop if we're only doing icons + Escape(hDC, MFCOMMENT, lstrlen(szIconOnly)+1, szIconOnly, NULL); + + SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT)); + SetBkMode(hDC, TRANSPARENT); + fuAlign = SetTextAlign(hDC, TA_LEFT | TA_TOP | TA_NOUPDATECP); + + OleStdIconLabelTextOut(hDC, + hFont, + 0, + cy - cyText, + ETO_CLIPPED, + &TextRect, + pszLabel, + cchLabel, + NULL); + + //Write comments containing the icon source file and index. + if (NULL!=pszSourceFile) + { + //+1 on string lengths insures the null terminator is embedded. + Escape(hDC, MFCOMMENT, lstrlen(pszSourceFile)+1, pszSourceFile, NULL); + + cchLabel=wsprintf(szIndex, TEXT("%u"), iIcon); + Escape(hDC, MFCOMMENT, cchLabel+1, szIndex, NULL); + } + + SetTextAlign(hDC, fuAlign); + + //All done with the metafile, now stuff it all into a METAFILEPICT. + hMF=CloseMetaFile(hDC); + + if (NULL==hMF) + { + GlobalFree(hMem); + ReleaseDC(NULL, hDCScreen); + return NULL; + } + + //Fill out the structure + pMF=(LPMETAFILEPICT)GlobalLock(hMem); + + //Transform to HIMETRICS + cx=XformWidthInPixelsToHimetric(hDCScreen, cx); + cy=XformHeightInPixelsToHimetric(hDCScreen, cy); + ReleaseDC(NULL, hDCScreen); + + pMF->mm=MM_ANISOTROPIC; + pMF->xExt=cx; + pMF->yExt=cy; + pMF->hMF=hMF; + + GlobalUnlock(hMem); + + DeleteObject(hFont); + + return hMem; + } + +#endif // OBSOLETE + + +/* + * GetAssociatedExecutable + * + * Purpose: Finds the executable associated with the provided extension + * + * Parameters: + * lpszExtension LPSTR points to the extension we're trying to find + * an exe for. Does **NO** validation. + * + * lpszExecutable LPSTR points to where the exe name will be returned. + * No validation here either - pass in 128 char buffer. + * + * Return: + * BOOL TRUE if we found an exe, FALSE if we didn't. + * + */ + +BOOL FAR PASCAL GetAssociatedExecutable(LPTSTR lpszExtension, LPTSTR lpszExecutable) + +{ + HKEY hKey; + LONG dw; + LRESULT lRet; + TCHAR szValue[OLEUI_CCHKEYMAX]; + TCHAR szKey[OLEUI_CCHKEYMAX]; + LPTSTR lpszTemp, lpszExe; + + + lRet = RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hKey); + + if (ERROR_SUCCESS != lRet) + return FALSE; + + dw = OLEUI_CCHPATHMAX_SIZE; + lRet = RegQueryValue(hKey, lpszExtension, (LPTSTR)szValue, &dw); //ProgId + + if (ERROR_SUCCESS != lRet) + { + RegCloseKey(hKey); + return FALSE; + } + + + // szValue now has ProgID + lstrcpy(szKey, szValue); + lstrcat(szKey, TEXT("\\Shell\\Open\\Command")); + + + dw = OLEUI_CCHPATHMAX_SIZE; + lRet = RegQueryValue(hKey, (LPTSTR)szKey, (LPTSTR)szValue, &dw); + + if (ERROR_SUCCESS != lRet) + { + RegCloseKey(hKey); + return FALSE; + } + + // szValue now has an executable name in it. Let's null-terminate + // at the first post-executable space (so we don't have cmd line + // args. + + lpszTemp = (LPTSTR)szValue; + + while ((TEXT('\0') != *lpszTemp) && (iswspace(*lpszTemp))) + lpszTemp++; // Strip off leading spaces + + lpszExe = lpszTemp; + + while ((TEXT('\0') != *lpszTemp) && (!iswspace(*lpszTemp))) + lpszTemp++; // Step through exe name + + *lpszTemp = TEXT('\0'); // null terminate at first space (or at end). + + + lstrcpy(lpszExecutable, lpszExe); + + return TRUE; + +} + + +/* + * HIconAndSourceFromClass + * + * Purpose: + * Given an object class name, finds an associated executable in the + * registration database and extracts the first icon from that + * executable. If none is available or the class has no associated + * executable, this function returns NULL. + * + * Parameters: + * rclsid pointer to clsid to look up. + * pszSource LPSTR in which to place the source of the icon. + * This is assumed to be OLEUI_CCHPATHMAX + * puIcon UINT FAR * in which to store the index of the + * icon in pszSource. + * + * Return Value: + * HICON Handle to the extracted icon if there is a module + * associated to pszClass. NULL on failure to either + * find the executable or extract and icon. + */ + +HICON FAR PASCAL HIconAndSourceFromClass(REFCLSID rclsid, LPTSTR pszSource, UINT FAR *puIcon) + { + HICON hIcon; + UINT IconIndex; + + if (NULL==rclsid || NULL==pszSource || IsEqualCLSID(rclsid,&CLSID_NULL)) + return NULL; + + if (!FIconFileFromClass(rclsid, pszSource, OLEUI_CCHPATHMAX_SIZE, &IconIndex)) + return NULL; + + hIcon=ExtractIcon(ghInst, pszSource, IconIndex); + + if ((HICON)32 > hIcon) + hIcon=NULL; + else + *puIcon= IconIndex; + + return hIcon; + } + + +/* + * PointerToNthField + * + * Purpose: + * Returns a pointer to the beginning of the nth field. + * Assumes null-terminated string. + * + * Parameters: + * lpszString string to parse + * nField field to return starting index of. + * chDelimiter char that delimits fields + * + * Return Value: + * LPSTR pointer to beginning of nField field. + * NOTE: If the null terminator is found + * Before we find the Nth field, then + * we return a pointer to the null terminator - + * calling app should be sure to check for + * this case. + * + */ +LPTSTR FAR PASCAL PointerToNthField(LPTSTR lpszString, int nField, TCHAR chDelimiter) +{ + LPTSTR lpField = lpszString; + int cFieldFound = 1; + + if (1 ==nField) + return lpszString; + + while (*lpField != TEXT('\0')) + { + + if (*lpField++ == chDelimiter) + { + + cFieldFound++; + + if (nField == cFieldFound) + return lpField; + } + } + + return lpField; + +} + + +/* + * FIconFileFromClass + * + * Purpose: + * Looks up the path to executable that contains the class default icon. + * + * Parameters: + * rclsid pointer to CLSID to look up. + * pszEXE LPSTR at which to store the server name + * cch UINT size of pszEXE + * lpIndex LPUINT to index of icon within executable + * + * Return Value: + * BOOL TRUE if one or more characters were loaded into pszEXE. + * FALSE otherwise. + */ + +BOOL FAR PASCAL FIconFileFromClass(REFCLSID rclsid, LPTSTR pszEXE, UINT cchBytes, UINT FAR *lpIndex) +{ + + LONG dw; + LONG lRet; + HKEY hKey; + LPMALLOC lpIMalloc; + HRESULT hrErr; + LPTSTR lpBuffer; + LPTSTR lpIndexString; + UINT cBufferSize = 136;// room for 128 char path and icon's index + TCHAR szKey[64]; + LPSTR pszClass; + UINT cch=cchBytes / sizeof(TCHAR); // number of characters + + + if (NULL==rclsid || NULL==pszEXE || 0==cch || IsEqualCLSID(rclsid,&CLSID_NULL)) + return FALSE; + + //Here, we use CoGetMalloc and alloc a buffer (maxpathlen + 8) to + //pass to RegQueryValue. Then, we copy the exe to pszEXE and the + //index to *lpIndex. + + hrErr = CoGetMalloc(MEMCTX_TASK, &lpIMalloc); + + if (NOERROR != hrErr) + return FALSE; + + lpBuffer = (LPTSTR)lpIMalloc->lpVtbl->Alloc(lpIMalloc, cBufferSize); + + if (NULL == lpBuffer) + { + lpIMalloc->lpVtbl->Release(lpIMalloc); + return FALSE; + } + + + if (CoIsOle1Class(rclsid)) + { + + LPOLESTR lpszProgID; + + // we've got an ole 1.0 class on our hands, so we look at + // progID\protocol\stdfileedting\server to get the + // name of the executable. + + ProgIDFromCLSID(rclsid, &lpszProgID); + + //Open up the class key +#ifdef UNICODE + lRet=RegOpenKey(HKEY_CLASSES_ROOT, lpszProgID, &hKey); +#else + { + char szTemp[255]; + + wcstombs(szTemp, lpszProgID, 255); + lRet=RegOpenKey(HKEY_CLASSES_ROOT, szTemp, &hKey); + } +#endif + + if (ERROR_SUCCESS != lRet) + { + lpIMalloc->lpVtbl->Free(lpIMalloc, lpszProgID); + lpIMalloc->lpVtbl->Free(lpIMalloc, lpBuffer); + lpIMalloc->lpVtbl->Release(lpIMalloc); + return FALSE; + } + + dw=(LONG)cBufferSize; + lRet = RegQueryValue(hKey, TEXT("Protocol\\StdFileEditing\\Server"), lpBuffer, &dw); + + if (ERROR_SUCCESS != lRet) + { + + RegCloseKey(hKey); + lpIMalloc->lpVtbl->Free(lpIMalloc, lpszProgID); + lpIMalloc->lpVtbl->Free(lpIMalloc, lpBuffer); + lpIMalloc->lpVtbl->Release(lpIMalloc); + return FALSE; + } + + + // Use server and 0 as the icon index + LSTRCPYN(pszEXE, lpBuffer, cch); + + *lpIndex = 0; + + RegCloseKey(hKey); + lpIMalloc->lpVtbl->Free(lpIMalloc, lpszProgID); + lpIMalloc->lpVtbl->Free(lpIMalloc, lpBuffer); + lpIMalloc->lpVtbl->Release(lpIMalloc); + return TRUE; + + } + + + + /* + * We have to go walking in the registration database under the + * classname, so we first open the classname key and then check + * under "\\DefaultIcon" to get the file that contains the icon. + */ + + StringFromCLSIDA(rclsid, &pszClass); + + lstrcpy(szKey, TEXT("CLSID\\")); + + lstrcat(szKey, pszClass); + + //Open up the class key + lRet=RegOpenKey(HKEY_CLASSES_ROOT, szKey, &hKey); + + if (ERROR_SUCCESS != lRet) + { + lpIMalloc->lpVtbl->Free(lpIMalloc, lpBuffer); + lpIMalloc->lpVtbl->Free(lpIMalloc, pszClass); + lpIMalloc->lpVtbl->Release(lpIMalloc); + return FALSE; + } + + //Get the executable path and icon index. + + dw=(LONG)cBufferSize; + lRet=RegQueryValue(hKey, TEXT("DefaultIcon"), lpBuffer, &dw); + + if (ERROR_SUCCESS != lRet) + { + // no DefaultIcon key...try LocalServer + + dw=(LONG)cBufferSize; + lRet=RegQueryValue(hKey, TEXT("LocalServer"), lpBuffer, &dw); + + if (ERROR_SUCCESS != lRet) + { + // no LocalServer entry either...they're outta luck. + + RegCloseKey(hKey); + lpIMalloc->lpVtbl->Free(lpIMalloc, lpBuffer); + lpIMalloc->lpVtbl->Free(lpIMalloc, pszClass); + lpIMalloc->lpVtbl->Release(lpIMalloc); + return FALSE; + } + + + // Use server from LocalServer or Server and 0 as the icon index + LSTRCPYN(pszEXE, lpBuffer, cch); + + *lpIndex = 0; + + RegCloseKey(hKey); + lpIMalloc->lpVtbl->Free(lpIMalloc, lpBuffer); + lpIMalloc->lpVtbl->Free(lpIMalloc, pszClass); + lpIMalloc->lpVtbl->Release(lpIMalloc); + return TRUE; + } + + RegCloseKey(hKey); + + // lpBuffer contains a string that looks like ",", + // so we need to separate the path and the icon index. + + lpIndexString = PointerToNthField(lpBuffer, 2, TEXT(',')); + + if (TEXT('\0') == *lpIndexString) // no icon index specified - use 0 as default. + { + *lpIndex = 0; + + } + else + { + LPTSTR lpTemp; + static TCHAR szTemp[16]; + + lstrcpy((LPTSTR)szTemp, lpIndexString); + + // Put the icon index part into *pIconIndex +#ifdef UNICODE + { + char szTEMP1[16]; + + wcstombs(szTEMP1, szTemp, 16); + *lpIndex = atoi((const char *)szTEMP1); + } +#else + *lpIndex = atoi((const char *)szTemp); +#endif + + // Null-terminate the exe part. +#ifdef WIN32 + lpTemp = CharPrev(lpBuffer, lpIndexString); +#else + lpTemp = AnsiPrev(lpBuffer, lpIndexString); +#endif + *lpTemp = TEXT('\0'); + } + + if (!LSTRCPYN(pszEXE, lpBuffer, cch)) + { + lpIMalloc->lpVtbl->Free(lpIMalloc, lpBuffer); + lpIMalloc->lpVtbl->Free(lpIMalloc, pszClass); + lpIMalloc->lpVtbl->Release(lpIMalloc); + return FALSE; + } + + // Free the memory we alloc'd and leave. + lpIMalloc->lpVtbl->Free(lpIMalloc, lpBuffer); + lpIMalloc->lpVtbl->Free(lpIMalloc, pszClass); + lpIMalloc->lpVtbl->Release(lpIMalloc); + return TRUE; +} + + + +/* + * OleStdIconLabelTextOut + * + * Purpose: + * Replacement for DrawText to be used in the "Display as Icon" metafile. + * Uses ExtTextOut to output a string center on (at most) two lines. + * Uses a very simple word wrap algorithm to split the lines. + * + * Parameters: (same as for ExtTextOut, except for hFont) + * hDC device context to draw into; if this is NULL, then we don't + * ETO the text, we just return the index of the beginning + * of the second line + * hFont font to use + * nXStart x-coordinate of starting position + * nYStart y-coordinate of starting position + * fuOptions rectangle type + * lpRect rect far * containing rectangle to draw text in. + * lpszString string to draw + * cchString length of string (truncated if over OLEUI_CCHLABELMAX) + * lpDX spacing between character cells + * + * Return Value: + * UINT Index of beginning of last line (0 if there's only one + * line of text). + * + */ + +STDAPI_(UINT) OleStdIconLabelTextOut(HDC hDC, + HFONT hFont, + int nXStart, + int nYStart, + UINT fuOptions, + RECT FAR * lpRect, + LPTSTR lpszString, + UINT cchString, + int FAR * lpDX) +{ + + HDC hDCScreen; + static TCHAR szTempBuff[OLEUI_CCHLABELMAX]; + int cxString, cyString, cxMaxString; + int cxFirstLine, cyFirstLine, cxSecondLine; + int index; + int cch = cchString; + TCHAR chKeep; + LPTSTR lpszSecondLine; + HFONT hFontT; + BOOL fPrintText = TRUE; + UINT iLastLineStart = 0; + SIZE size; + + // Initialization stuff... + + if (NULL == hDC) // If we got NULL as the hDC, then we don't actually call ETO + fPrintText = FALSE; + + + // Make a copy of the string (NULL or non-NULL) that we're using + if (NULL == lpszString) + *szTempBuff = TEXT('\0'); + + else + LSTRCPYN(szTempBuff, lpszString, sizeof(szTempBuff)/sizeof(TCHAR)); + + // set maximum width + cxMaxString = lpRect->right - lpRect->left; + + // get screen DC to do text size calculations + hDCScreen = GetDC(NULL); + + hFontT=SelectObject(hDCScreen, hFont); + + // get the extent of our label +#ifdef WIN32 + // GetTextExtentPoint32 has fixed the off-by-one bug. + GetTextExtentPoint32(hDCScreen, szTempBuff, cch, &size); +#else + GetTextExtentPoint(hDCScreen, szTempBuff, cch, &size); +#endif + + cxString = size.cx; + cyString = size.cy; + + // Select in the font we want to use + if (fPrintText) + SelectObject(hDC, hFont); + + // String is smaller than max string - just center, ETO, and return. + if (cxString <= cxMaxString) + { + + if (fPrintText) + ExtTextOut(hDC, + nXStart + (lpRect->right - cxString) / 2, + nYStart, + fuOptions, + lpRect, + szTempBuff, + cch, + NULL); + + iLastLineStart = 0; // only 1 line of text + goto CleanupAndLeave; + } + + // String is too long...we've got to word-wrap it. + + + // Are there any spaces, slashes, tabs, or bangs in string? + + if (lstrlen(szTempBuff) != (int) +#ifdef UNICODE + wcscspn(szTempBuff, szSeparators) +#else + strcspn(szTempBuff, szSeparators) +#endif + ) + { + // Yep, we've got spaces, so we'll try to find the largest + // space-terminated string that will fit on the first line. + + index = cch; + + + while (index >= 0) + { + + TCHAR cchKeep; + + // scan the string backwards for spaces, slashes, tabs, or bangs + + while (!IS_SEPARATOR(szTempBuff[index]) ) + index--; + + + if (index <= 0) + break; + + cchKeep = szTempBuff[index]; // remember what char was there + + szTempBuff[index] = TEXT('\0'); // just for now + +#ifdef WIN32 + GetTextExtentPoint32( + hDCScreen, (LPTSTR)szTempBuff,lstrlen((LPTSTR)szTempBuff),&size); +#else + GetTextExtentPoint( + hDCScreen, (LPTSTR)szTempBuff,lstrlen((LPTSTR)szTempBuff),&size); +#endif + + cxFirstLine = size.cx; + cyFirstLine = size.cy; + + szTempBuff[index] = cchKeep; // put the right char back + + if (cxFirstLine <= cxMaxString) + { + + iLastLineStart = index + 1; + + if (!fPrintText) + goto CleanupAndLeave; + + ExtTextOut(hDC, + nXStart + (lpRect->right - cxFirstLine) / 2, + nYStart, + fuOptions, + lpRect, + (LPTSTR)szTempBuff, + index + 1, + lpDX); + + lpszSecondLine = (LPTSTR)szTempBuff; + + lpszSecondLine += (index + 1) ; + + GetTextExtentPoint(hDCScreen, + lpszSecondLine, + lstrlen(lpszSecondLine), + &size); + + // If the second line is wider than the rectangle, we + // just want to clip the text. + cxSecondLine = min(size.cx, cxMaxString); + + ExtTextOut(hDC, + nXStart + (lpRect->right - cxSecondLine) / 2, + nYStart + cyFirstLine, + fuOptions, + lpRect, + lpszSecondLine, + lstrlen(lpszSecondLine), + lpDX); + + goto CleanupAndLeave; + + } // end if + + index--; + + } // end while + + } // end if + + // Here, there are either no spaces in the string (strchr(szTempBuff, ' ') + // returned NULL), or there spaces in the string, but they are + // positioned so that the first space terminated string is still + // longer than one line. So, we walk backwards from the end of the + // string until we find the largest string that will fit on the first + // line , and then we just clip the second line. + + cch = lstrlen((LPTSTR)szTempBuff); + + chKeep = szTempBuff[cch]; + szTempBuff[cch] = TEXT('\0'); + + GetTextExtentPoint(hDCScreen, szTempBuff, lstrlen(szTempBuff),&size); + + cxFirstLine = size.cx; + cyFirstLine = size.cy; + + while (cxFirstLine > cxMaxString) + { + // We allow 40 characters in the label, but the metafile is + // only as wide as 10 W's (for aesthetics - 20 W's wide looked + // dumb. This means that if we split a long string in half (in + // terms of characters), then we could still be wider than the + // metafile. So, if this is the case, we just step backwards + // from the halfway point until we get something that will fit. + // Since we just let ETO clip the second line + + szTempBuff[cch--] = chKeep; + if (0 == cch) + goto CleanupAndLeave; + + chKeep = szTempBuff[cch]; + szTempBuff[cch] = TEXT('\0'); + + GetTextExtentPoint( + hDCScreen, szTempBuff, lstrlen(szTempBuff), &size); + cxFirstLine = size.cx; + } + + iLastLineStart = cch; + + if (!fPrintText) + goto CleanupAndLeave; + + ExtTextOut(hDC, + nXStart + (lpRect->right - cxFirstLine) / 2, + nYStart, + fuOptions, + lpRect, + (LPTSTR)szTempBuff, + lstrlen((LPTSTR)szTempBuff), + lpDX); + + szTempBuff[cch] = chKeep; + lpszSecondLine = szTempBuff; + lpszSecondLine += cch ; + + GetTextExtentPoint( + hDCScreen, (LPTSTR)lpszSecondLine, lstrlen(lpszSecondLine), &size); + + // If the second line is wider than the rectangle, we + // just want to clip the text. + cxSecondLine = min(size.cx, cxMaxString); + + ExtTextOut(hDC, + nXStart + (lpRect->right - cxSecondLine) / 2, + nYStart + cyFirstLine, + fuOptions, + lpRect, + lpszSecondLine, + lstrlen(lpszSecondLine), + lpDX); + +CleanupAndLeave: + SelectObject(hDCScreen, hFontT); + ReleaseDC(NULL, hDCScreen); + return iLastLineStart; + +} + diff --git a/private/oleutest/letest/ole2ui/geticon.h b/private/oleutest/letest/ole2ui/geticon.h new file mode 100644 index 000000000..223411385 --- /dev/null +++ b/private/oleutest/letest/ole2ui/geticon.h @@ -0,0 +1,18 @@ +// This file is now OBSOLETE (include olestd.h instead) +/* + * GETICON.H + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + +/************************************************************************* +** +** The following API's are now OBSOLETE because equivalent API's have been +** added to the OLE2.DLL library +** GetIconOfFile superceeded by OleGetIconOfFile +** GetIconOfClass superceeded by OleGetIconOfClass +** OleUIMetafilePictFromIconAndLabel +** superceeded by OleMetafilePictFromIconAndLabel +*************************************************************************/ + +// Other function prototypes moved to olestd.h diff --git a/private/oleutest/letest/ole2ui/hatch.c b/private/oleutest/letest/ole2ui/hatch.c new file mode 100644 index 000000000..1e156a1e0 --- /dev/null +++ b/private/oleutest/letest/ole2ui/hatch.c @@ -0,0 +1,325 @@ +/* + * HATCH.C + * + * Miscellaneous API's to generate hatch window for in-place active + * objects. This is part of the OLE 2.0 User Interface Support Library. + * + * Copyright (c)1993 Microsoft Corporation, All Right Reserved + */ + +#define STRICT 1 +#include "ole2ui.h" + +// offsets in the extra bytes stored with the hatch window +#define EB_HATCHWIDTH 0 +#define EB_HATCHRECT_LEFT 2 +#define EB_HATCHRECT_TOP 4 +#define EB_HATCHRECT_RIGHT 6 +#define EB_HATCHRECT_BOTTOM 8 + +// class name of hatch window +#define CLASS_HATCH TEXT("Hatch Window") + +// local function prototypes +LRESULT FAR PASCAL EXPORT HatchWndProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam); + + +/* + * HatchRegisterClass + * + * Purpose: + * Register the hatch window + * + * Parameters: + * hInst Process instance + * + * Return Value: + * TRUE if successful + * FALSE if failed + * + */ +STDAPI_(BOOL) RegisterHatchWindowClass(HINSTANCE hInst) +{ + WNDCLASS wc; + + // Register Hatch Window Class + wc.style = CS_BYTEALIGNWINDOW; + wc.lpfnWndProc = HatchWndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 5 * sizeof(int); // extra bytes stores + // uHatchWidth + // rcHatchRect + wc.hInstance = hInst; + wc.hIcon = NULL; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wc.lpszMenuName = NULL; + wc.lpszClassName = CLASS_HATCH; + + if (!RegisterClass(&wc)) + return FALSE; + else + return TRUE; +} + + +/* + * CreateHatchWindow + * + * Purpose: + * Create the hatch window + * + * Parameters: + * hWndParent parent of hatch window + * hInst instance handle + * + * Return Value: + * pointer to hatch window if successful + * NULL if failed + * + */ +STDAPI_(HWND) CreateHatchWindow(HWND hWndParent, HINSTANCE hInst) +{ + HWND hWnd; + + if (!hWndParent || !hInst) + return NULL; + + hWnd = CreateWindow( + CLASS_HATCH, + TEXT("Hatch Window"), + WS_CHILDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, + 0, 0, 0, 0, + hWndParent, + (HMENU)NULL, + hInst, + 0L + ); + + if (!hWnd) + return NULL; + + return hWnd; +} + +/* + * GetHatchWidth + * + * Purpose: + * Get width of hatch border + * + * Parameters: + * hWndHatch hatch window handle + * + * Return Value: + * width of the hatch border + */ +STDAPI_(UINT) GetHatchWidth(HWND hWndHatch) +{ + if (!IsWindow(hWndHatch)) + return 0; + + return (UINT)GetWindowWord(hWndHatch, EB_HATCHWIDTH); +} + +/* + * GetHatchRect + * + * Purpose: + * Get hatch rect. this is the size of the hatch window if it were + * not clipped by the ClipRect. + * + * Parameters: + * hWndHatch hatch window handle + * lprcHatchRect hatch rect + * + * Return Value: + * none + */ +STDAPI_(void) GetHatchRect(HWND hWndHatch, LPRECT lprcHatchRect) +{ + if (!IsWindow(hWndHatch)) { + SetRect(lprcHatchRect, 0, 0, 0, 0); + return; + } + + lprcHatchRect->left = GetWindowWord(hWndHatch, EB_HATCHRECT_LEFT); + lprcHatchRect->top = GetWindowWord(hWndHatch, EB_HATCHRECT_TOP); + lprcHatchRect->right = GetWindowWord(hWndHatch, EB_HATCHRECT_RIGHT); + lprcHatchRect->bottom = GetWindowWord(hWndHatch, EB_HATCHRECT_BOTTOM); +} + + +/* SetHatchRect + * + * + * Purpose: + * Store hatch rect with HatchRect window. + * this rect is the size of the hatch window if it were + * not clipped by the ClipRect. + * + * Parameters: + * hWndHatch hatch window handle + * lprcHatchRect hatch rect + * + * Return Value: + * none + */ +STDAPI_(void) SetHatchRect(HWND hWndHatch, LPRECT lprcHatchRect) +{ + if (!IsWindow(hWndHatch)) + return; + + SetWindowWord(hWndHatch, EB_HATCHRECT_LEFT, (WORD)lprcHatchRect->left); + SetWindowWord(hWndHatch, EB_HATCHRECT_TOP, (WORD)lprcHatchRect->top); + SetWindowWord(hWndHatch, EB_HATCHRECT_RIGHT, (WORD)lprcHatchRect->right); + SetWindowWord(hWndHatch, EB_HATCHRECT_BOTTOM,(WORD)lprcHatchRect->bottom); +} + + +/* SetHatchWindowSize + * + * + * Purpose: + * Move/size the HatchWindow correctly given the rect required by the + * in-place server object window and the lprcClipRect imposed by the + * in-place container. both rect's are expressed in the client coord. + * of the in-place container's window (which is the parent of the + * HatchWindow). + * + * OLE2NOTE: the in-place server must honor the lprcClipRect specified + * by its in-place container. it must NOT draw outside of the ClipRect. + * in order to achieve this, the hatch window is sized to be + * exactly the size that should be visible (rcVisRect). the + * rcVisRect is defined as the intersection of the full size of + * the HatchRect window and the lprcClipRect. + * the ClipRect could infact clip the HatchRect on the + * right/bottom and/or on the top/left. if it is clipped on the + * right/bottom then it is sufficient to simply resize the hatch + * window. but if the HatchRect is clipped on the top/left then + * in-place server document window (child of HatchWindow) must be moved + * by the delta that was clipped. the window origin of the + * in-place server window will then have negative coordinates relative + * to its parent HatchWindow. + * + * Parameters: + * hWndHatch hatch window handle + * lprcIPObjRect full size of in-place server object window + * lprcClipRect clipping rect imposed by in-place container + * lpptOffset offset required to position in-place server object + * window properly. caller should call: + * OffsetRect(&rcObjRect,lpptOffset->x,lpptOffset->y) + * + * Return Value: + * none + */ +STDAPI_(void) SetHatchWindowSize( + HWND hWndHatch, + LPRECT lprcIPObjRect, + LPRECT lprcClipRect, + LPPOINT lpptOffset +) +{ + RECT rcHatchRect; + RECT rcVisRect; + UINT uHatchWidth; + POINT ptOffset; + + if (!IsWindow(hWndHatch)) + return; + + rcHatchRect = *lprcIPObjRect; + uHatchWidth = GetHatchWidth(hWndHatch); + InflateRect((LPRECT)&rcHatchRect, uHatchWidth + 1, uHatchWidth + 1); + + IntersectRect((LPRECT)&rcVisRect, (LPRECT)&rcHatchRect, lprcClipRect); + MoveWindow( + hWndHatch, + rcVisRect.left, + rcVisRect.top, + rcVisRect.right-rcVisRect.left, + rcVisRect.bottom-rcVisRect.top, + TRUE /* fRepaint */ + ); + InvalidateRect(hWndHatch, NULL, TRUE); + + ptOffset.x = -rcHatchRect.left + (rcHatchRect.left - rcVisRect.left); + ptOffset.y = -rcHatchRect.top + (rcHatchRect.top - rcVisRect.top); + + /* convert the rcHatchRect into the client coordinate system of the + ** HatchWindow itself + */ + OffsetRect((LPRECT)&rcHatchRect, ptOffset.x, ptOffset.y); + + SetHatchRect(hWndHatch, (LPRECT)&rcHatchRect); + + // calculate offset required to position in-place server doc window + lpptOffset->x = ptOffset.x; + lpptOffset->y = ptOffset.y; +} + + +/* + * HatchWndProc + * + * Purpose: + * WndProc for hatch window + * + * Parameters: + * hWnd + * Message + * wParam + * lParam + * + * Return Value: + * message dependent + */ +LRESULT FAR PASCAL EXPORT HatchWndProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam) +{ + int nBorderWidth; + + switch (Message) { + + case WM_CREATE: + nBorderWidth = GetProfileInt( + TEXT("windows"), + TEXT("oleinplaceborderwidth"), + DEFAULT_HATCHBORDER_WIDTH + ); + SetWindowWord(hWnd, EB_HATCHWIDTH, (WORD)nBorderWidth); + break; + + case WM_PAINT: + { + HDC hDC; + PAINTSTRUCT ps; + RECT rcHatchRect; + + nBorderWidth = GetHatchWidth(hWnd); + hDC = BeginPaint(hWnd, &ps); + GetHatchRect(hWnd, (LPRECT)&rcHatchRect); + OleUIDrawShading(&rcHatchRect, hDC, OLEUI_SHADE_BORDERIN, + nBorderWidth); + InflateRect((LPRECT)&rcHatchRect, -nBorderWidth, -nBorderWidth); + OleUIDrawHandles(&rcHatchRect, hDC, OLEUI_HANDLES_OUTSIDE, + nBorderWidth+1, TRUE); + EndPaint(hWnd, &ps); + break; + } + + /* OLE2NOTE: Any window that is used during in-place activation + ** must handle the WM_SETCURSOR message or else the cursor + ** of the in-place parent will be used. if WM_SETCURSOR is + ** not handled, then DefWindowProc sends the message to the + ** window's parent. + */ + case WM_SETCURSOR: + SetCursor(LoadCursor( NULL, MAKEINTRESOURCE(IDC_ARROW) ) ); + return (LRESULT)TRUE; + + default: + return DefWindowProc(hWnd, Message, wParam, lParam); + } + + return 0L; +} diff --git a/private/oleutest/letest/ole2ui/hivgares.bmp b/private/oleutest/letest/ole2ui/hivgares.bmp new file mode 100644 index 000000000..0011166da Binary files /dev/null and b/private/oleutest/letest/ole2ui/hivgares.bmp differ diff --git a/private/oleutest/letest/ole2ui/icon.c b/private/oleutest/letest/ole2ui/icon.c new file mode 100644 index 000000000..048a991fe --- /dev/null +++ b/private/oleutest/letest/ole2ui/icon.c @@ -0,0 +1,857 @@ +/* + * ICON.C + * + * Implements the OleUIChangeIcon function which invokes the complete + * Change Icon dialog. + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + +#define STRICT 1 +#include "ole2ui.h" +#include "common.h" +#include "utility.h" +#include "icon.h" +#include "geticon.h" + +/* + * OleUIChangeIcon + * + * Purpose: + * Invokes the standard OLE Change Icon dialog box allowing the user + * to select an icon from an icon file, executable, or DLL. + * + * Parameters: + * lpCI LPOLEUIChangeIcon pointing to the in-out structure + * for this dialog. + * + * Return Value: + * UINT OLEUI_SUCCESS or OLEUI_OK if all is well, otherwise + * an error value. + */ + +STDAPI_(UINT) OleUIChangeIcon(LPOLEUICHANGEICON lpCI) + { + UINT uRet; + HGLOBAL hMemDlg=NULL; + + uRet=UStandardValidation((LPOLEUISTANDARD)lpCI, sizeof(OLEUICHANGEICON) + , &hMemDlg); + + if (OLEUI_SUCCESS!=uRet) + return uRet; + +#if defined( OBSOLETE ) + if (NULL==lpCI->hMetaPict) + uRet=OLEUI_CIERR_MUSTHAVECURRENTMETAFILE; +#endif + + if (lpCI->dwFlags & CIF_USEICONEXE) + { + if ( (NULL == lpCI->szIconExe) + || (IsBadReadPtr(lpCI->szIconExe, lpCI->cchIconExe)) + || (IsBadWritePtr(lpCI->szIconExe, lpCI->cchIconExe)) ) + uRet = OLEUI_CIERR_SZICONEXEINVALID; + + } + + // REVIEW: how do we validate the CLSID? +/* + if ('\0'==*((LPSTR)&lpCI->clsid)) + uRet=OLEUI_CIERR_MUSTHAVECLSID; +*/ + if (OLEUI_ERR_STANDARDMIN <= uRet) + { + if (NULL!=hMemDlg) + FreeResource(hMemDlg); + + return uRet; + } + + //Now that we've validated everything, we can invoke the dialog. + return UStandardInvocation(ChangeIconDialogProc, (LPOLEUISTANDARD)lpCI + , hMemDlg, MAKEINTRESOURCE(IDD_CHANGEICON)); + } + + + + + +/* + * ChangeIconDialogProc + * + * Purpose: + * Implements the OLE Change Icon dialog as invoked through the + * OleUIChangeIcon function. + * + * Parameters: + * Standard + * + * Return Value: + * Standard + */ + +BOOL CALLBACK EXPORT ChangeIconDialogProc(HWND hDlg, UINT iMsg + , WPARAM wParam, LPARAM lParam) + { + LPCHANGEICON lpCI; + HICON hIcon; + HGLOBAL hMetaPict; + BOOL fOK=FALSE; + UINT uRet=0; + LPTSTR psz; + TCHAR szTemp[OLEUI_CCHPATHMAX]; + + //Declare Win16/Win32 compatible WM_COMMAND parameters. + COMMANDPARAMS(wID, wCode, hWndMsg); + + lpCI=(LPCHANGEICON)LpvStandardEntry(hDlg, iMsg, wParam, lParam, &uRet); + + //If the hook processed the message, we're done. + if (0!=uRet) + return uRet; + + //Process the temination message + if (iMsg==uMsgEndDialog) + { + //Insure that icons are properly destroyed. + SendDlgItemMessage(hDlg, ID_ICONLIST, LB_RESETCONTENT, 0, 0L); + + StandardCleanup(lpCI, hDlg); + EndDialog(hDlg, wParam); + return TRUE; + } + + switch (iMsg) + { + case WM_INITDIALOG: + FChangeIconInit(hDlg, wParam, lParam); + return TRUE; + + + case WM_MEASUREITEM: + { + LPMEASUREITEMSTRUCT lpMI=(LPMEASUREITEMSTRUCT)lParam; + + //All icons are system metric+padding in width and height + lpMI->itemWidth =GetSystemMetrics(SM_CXICON)+CXICONPAD; + lpMI->itemHeight=GetSystemMetrics(SM_CYICON)+CYICONPAD; + } + break; + + + case WM_DRAWITEM: + return FDrawListIcon((LPDRAWITEMSTRUCT)lParam); + + + case WM_DELETEITEM: + //Free the GDI object for the item + DestroyIcon((HICON)LOWORD(((LPDELETEITEMSTRUCT)lParam)->itemData)); + break; + + + case WM_COMMAND: + switch (wID) + { + case ID_CURRENT: + case ID_DEFAULT: + case ID_FROMFILE: + UpdateResultIcon(lpCI, hDlg, wID); + break; + + case ID_LABELEDIT: + //When the edit loses focus, update the result display + if (EN_KILLFOCUS==wCode) + { + GetDlgItemText(hDlg, ID_LABELEDIT, szTemp, sizeof(szTemp)/sizeof(TCHAR)); + SetDlgItemText(hDlg, ID_RESULTLABEL, szTemp); + } + break; + + case ID_FROMFILEEDIT: + //If the text changed, remove any selection in the list. + GetDlgItemText(hDlg, ID_FROMFILEEDIT, szTemp, sizeof(szTemp)/sizeof(TCHAR)); + + if (lpCI && lstrcmpi(szTemp, lpCI->szFile)) + { + SendDlgItemMessage(hDlg, ID_ICONLIST, LB_SETCURSEL + , (WPARAM)-1, 0); + + //Also force selection of ID_FROMFILE + CheckRadioButton(hDlg, ID_CURRENT, ID_FROMFILE, ID_FROMFILE); + } + break; + + + case ID_ICONLIST: + switch (wCode) + { + case LBN_SETFOCUS: + //If we got the focus, see about updating. + GetDlgItemText(hDlg, ID_FROMFILEEDIT, szTemp + , sizeof(szTemp)/sizeof(TCHAR)); + + //Check if file changed and update the list if so + if (lpCI && 0!=lstrcmpi(szTemp, lpCI->szFile)) + { + lstrcpy(lpCI->szFile, szTemp); + UFillIconList(hDlg, ID_ICONLIST, lpCI->szFile); + UpdateResultIcon(lpCI, hDlg, ID_FROMFILE); + } + break; + + case LBN_SELCHANGE: + UpdateResultIcon(lpCI, hDlg, ID_FROMFILE); + break; + + case LBN_DBLCLK: + //Same as pressing OK. + SendCommand(hDlg, IDOK, BN_CLICKED, hWndMsg); + break; + } + break; + + + case ID_BROWSE: + { + DWORD dwOfnFlags; + + /* + * To allow the hook to customize the browse dialog, we + * send OLEUI_MSG_BROWSE. If the hook returns FALSE + * we use the default, otherwise we trust that it retrieved + * a filename for us. This mechanism prevents hooks from + * trapping ID_BROWSE to customize the dialog and from + * trying to figure out what we do after we have the name. + */ + + //Copy for reference + LSTRCPYN(szTemp, lpCI->szFile, sizeof(szTemp)/sizeof(TCHAR)); + + uRet=UStandardHook(lpCI, hDlg, uMsgBrowse, OLEUI_CCHPATHMAX_SIZE + , (LONG)(LPSTR)lpCI->szFile); + + dwOfnFlags = OFN_FILEMUSTEXIST; + if (lpCI->lpOCI->dwFlags & CIF_SHOWHELP) + dwOfnFlags |= OFN_SHOWHELP; + + if (0==uRet) + uRet=(BOOL)Browse(hDlg, lpCI->szFile, NULL, OLEUI_CCHPATHMAX_SIZE, IDS_ICONFILTERS, dwOfnFlags); + + /* + * Only reinitialize if the file changed, so if we got + * TRUE from the hook but the user hit Cancel, we don't + * spend time unecessarily refilling the list. + */ + if (0!=uRet && 0!=lstrcmpi(szTemp, lpCI->szFile)) + { + CheckRadioButton(hDlg, ID_CURRENT, ID_FROMFILE, ID_FROMFILE); + SetDlgItemText(hDlg, ID_FROMFILEEDIT, lpCI->szFile); + UFillIconList(hDlg, ID_ICONLIST, lpCI->szFile); + UpdateResultIcon(lpCI, hDlg, ID_FROMFILE); + } + } + break; + + + case IDOK: + /* + * If the user pressed enter, compare the current file + * and the one we have stored. If they match, then + * refill the listbox instead of closing down. This is + * so the user can press Enter in the edit control as + * they would expect to be able to do. + */ + GetDlgItemText(hDlg, ID_FROMFILEEDIT, szTemp, sizeof(szTemp)/sizeof(TCHAR)); + + //Check if the file changed at all. + if (0!=lstrcmpi(szTemp, lpCI->szFile)) + { + lstrcpy(lpCI->szFile, szTemp); + UFillIconList(hDlg, ID_ICONLIST, lpCI->szFile); + UpdateResultIcon(lpCI, hDlg, ID_FROMFILE); + + //Eat this message to prevent focus change. + return TRUE; + } + + // Check if the file name is valid + // (if FromFile is enabled) + if (ID_FROMFILE & lpCI->dwFlags) + { + OFSTRUCT of; + HWND hWnd; + if (HFILE_ERROR==DoesFileExist(lpCI->szFile, &of)) + { + OpenFileError(hDlg, of.nErrCode, lpCI->szFile); + hWnd = GetDlgItem(hDlg, ID_FROMFILEEDIT); + SetFocus(hWnd); + SendMessage(hWnd, EM_SETSEL, 0, MAKELPARAM(0, (WORD)-1)); + return TRUE; // eat this message + } + } + + if ((HWND)LOWORD(lParam) != GetFocus()) + SetFocus((HWND)LOWORD(lParam)); + + /* + * On closing, create a new metafilepict with the + * current icon and label, destroying the old structure. + * + * Since we make a copy of the icon by placing it into + * the metafile, we have to make sure we delete the + * icon in the current field. When the listbox is + * destroyed WM_DELETEITEMs will clean it up appropriately. + */ + + hIcon=(HICON)SendDlgItemMessage(hDlg, ID_RESULTICON + , STM_GETICON, 0, 0L); + + /* + * If default is selected then we get the source + * information from registrion database for the + * current class to put in the metafile. If current + * is selected the we just retrieve the original file + * again and recreate the metafile. If from file is + * selected we use the current filename from the + * control and the current listbox selection. + */ + + psz=lpCI->szFile; + + if (lpCI->dwFlags & CIF_SELECTDEFAULT) + { + psz=lpCI->szDefIconFile; + lpCI->iIcon=lpCI->iDefIcon; + hIcon=lpCI->hDefIcon; + } + + if (lpCI->dwFlags & CIF_SELECTCURRENT) + { + //Go get the current icon source back. + OleUIMetafilePictExtractIconSource(lpCI->lpOCI->hMetaPict + , psz, &lpCI->iIcon); + } + + if (lpCI->dwFlags & CIF_SELECTFROMFILE) + { + GetDlgItemText(hDlg, ID_FROMFILEEDIT, psz, OLEUI_CCHPATHMAX); + + lpCI->iIcon=(UINT)SendDlgItemMessage(hDlg + , ID_ICONLIST, LB_GETCURSEL, 0, 0L); + } + + + //Get the label and go create the metafile + GetDlgItemText(hDlg, ID_LABELEDIT, szTemp, sizeof(szTemp)/sizeof(TCHAR)); + + //If psz is NULL (default) we get no source comments. + +#ifdef OLE201 + hMetaPict=OleUIMetafilePictFromIconAndLabel(hIcon, + szTemp, psz, lpCI->iIcon); +#endif + + //Clean up the current icon that we extracted. + hIcon=(HICON)SendDlgItemMessage(hDlg, ID_CURRENTICON + , STM_GETICON, 0, 0L); + DestroyIcon(hIcon); + + //Clean up the default icon + DestroyIcon(lpCI->hDefIcon); + + // Remove the prop set on our parent + RemoveProp(lpCI->lpOCI->hWndOwner, PROP_HWND_CHGICONDLG); + + if (NULL==hMetaPict) + SendMessage(hDlg, uMsgEndDialog, OLEUI_FALSE, 0L); + + OleUIMetafilePictIconFree(lpCI->lpOCI->hMetaPict); + lpCI->lpOCI->hMetaPict=hMetaPict; + + lpCI->lpOCI->dwFlags = lpCI->dwFlags; + + SendMessage(hDlg, uMsgEndDialog, OLEUI_OK, 0L); + break; + + + case IDCANCEL: + //Clean up the current icon that we extracted. + hIcon=(HICON)SendDlgItemMessage(hDlg, ID_CURRENTICON + , STM_GETICON, 0, 0L); + DestroyIcon(hIcon); + + //Clean up the default icon + DestroyIcon(lpCI->hDefIcon); + + // Remove the prop set on our parent + RemoveProp(lpCI->lpOCI->hWndOwner, PROP_HWND_CHGICONDLG); + + //We leave hMetaPict intact on Cancel; caller's responsibility + SendMessage(hDlg, uMsgEndDialog, OLEUI_CANCEL, 0L); + break; + + + case ID_OLEUIHELP: + PostMessage(lpCI->lpOCI->hWndOwner, uMsgHelp, + (WPARAM)hDlg, MAKELPARAM(IDD_CHANGEICON, 0)); + break; + } + break; + + default: + { + if (lpCI && iMsg == lpCI->nBrowseHelpID) { + PostMessage(lpCI->lpOCI->hWndOwner, uMsgHelp, + (WPARAM)hDlg, MAKELPARAM(IDD_CHANGEICONBROWSE, 0)); + } + } + break; + } + return FALSE; + } + + + + +/* + * FChangeIconInit + * + * Purpose: + * WM_INITIDIALOG handler for the Change Icon dialog box. + * + * Parameters: + * hDlg HWND of the dialog + * wParam WPARAM of the message + * lParam LPARAM of the message + * + * Return Value: + * BOOL Value to return for WM_INITDIALOG. + */ + +BOOL FChangeIconInit(HWND hDlg, WPARAM wParam, LPARAM lParam) + { + LPCHANGEICON lpCI; + LPOLEUICHANGEICON lpOCI; + HFONT hFont; + HWND hList; + UINT cyList; + RECT rc, rcG; + UINT uID; + + //1. Copy the structure at lParam into our instance memory. + lpCI=(LPCHANGEICON)LpvStandardInit(hDlg, sizeof(CHANGEICON), TRUE, &hFont); + + //PvStandardInit send a termination to us already. + if (NULL==lpCI) + return FALSE; + + //Save the original pointer and copy necessary information. + lpOCI=(LPOLEUICHANGEICON)lParam; + + lpCI->lpOCI =lpOCI; + lpCI->dwFlags=lpOCI->dwFlags; + + //Go extract the icon source from the metafile. + OleUIMetafilePictExtractIconSource(lpOCI->hMetaPict, lpCI->szFile, &lpCI->iIcon); + + //Go extract the icon and the label from the metafile + OleUIMetafilePictExtractLabel(lpOCI->hMetaPict, lpCI->szLabel, OLEUI_CCHLABELMAX_SIZE, NULL); + lpCI->hCurIcon=OleUIMetafilePictExtractIcon(lpOCI->hMetaPict); + + //2. If we got a font, send it to the necessary controls. + if (NULL!=hFont) + { + SendDlgItemMessage(hDlg, ID_RESULTLABEL, WM_SETFONT + , (WPARAM)hFont, 0L); + } + + + //3. Show or hide the help button + if (!(lpCI->dwFlags & CIF_SHOWHELP)) + StandardShowDlgItem(hDlg, ID_OLEUIHELP, SW_HIDE); + + + /* + * 4. Set text limits and initial control values. If we're given + * an intial label we set it in the edit and static controls. + * If we don't, then we copy the default contents of the static + * control into the edit control, meaning that only the default + * static control string need be localized. + */ + + SendDlgItemMessage(hDlg, ID_LABELEDIT, EM_LIMITTEXT, OLEUI_CCHLABELMAX, 0L); + SendDlgItemMessage(hDlg, ID_FROMFILEEDIT, EM_LIMITTEXT, OLEUI_CCHPATHMAX, 0L); + SetDlgItemText(hDlg, ID_FROMFILEEDIT, lpCI->szFile); + + //Copy the label text into the edit and static controls. + SetDlgItemText(hDlg, ID_LABELEDIT, lpCI->szLabel); + SetDlgItemText(hDlg, ID_RESULTLABEL, lpCI->szLabel); + + + lpCI->hDefIcon = NULL; + + if (lpCI->dwFlags & CIF_USEICONEXE) + { + lpCI->hDefIcon = ExtractIcon(ghInst, lpCI->lpOCI->szIconExe, 0); + + if (NULL != lpCI->hDefIcon) + { + lstrcpy(lpCI->szDefIconFile, lpCI->lpOCI->szIconExe); + lpCI->iDefIcon = 0; + } + } + + + if (NULL == lpCI->hDefIcon) + { + HGLOBAL hMetaPict; + +#ifdef OLE201 + hMetaPict = GetIconOfClass(ghInst, + &lpCI->lpOCI->clsid, + NULL, + TRUE); +#endif + + lpCI->hDefIcon = OleUIMetafilePictExtractIcon(hMetaPict); + + OleUIMetafilePictExtractIconSource(hMetaPict, + lpCI->szDefIconFile, + &lpCI->iDefIcon); + + OleUIMetafilePictIconFree(hMetaPict); + } + + + //Initialize all the icon displays. + SendDlgItemMessage(hDlg, ID_CURRENTICON, STM_SETICON + , (WPARAM)lpCI->hCurIcon, 0L); + SendDlgItemMessage(hDlg, ID_DEFAULTICON, STM_SETICON + , (WPARAM)lpCI->hDefIcon, 0L); + SendDlgItemMessage(hDlg, ID_RESULTICON, STM_SETICON + , (WPARAM)lpCI->hCurIcon, 0L); + + + /* + * 5. Since we cannot predict the size of icons on any display, + * we have to resize the icon listbox to the size of an icon + * (plus padding), a scrollbar, and two borders (top & bottom). + */ + cyList=GetSystemMetrics(SM_CYICON)+GetSystemMetrics(SM_CYHSCROLL) + +GetSystemMetrics(SM_CYBORDER)*2+CYICONPAD; + + hList=GetDlgItem(hDlg, ID_ICONLIST); + GetClientRect(hList, &rc); + SetWindowPos(hList, NULL, 0, 0, rc.right, cyList + , SWP_NOMOVE | SWP_NOZORDER); + + //Set the columns in this multi-column listbox to hold one icon + SendMessage(hList, LB_SETCOLUMNWIDTH + , GetSystemMetrics(SM_CXICON)+CXICONPAD,0L); + + /* + * 5a. If the listbox expanded below the group box, then size + * the groupbox down, move the label static and exit controls + * down, and expand the entire dialog appropriately. + */ + + GetWindowRect(hList, &rc); + GetWindowRect(GetDlgItem(hDlg, ID_GROUP), &rcG); + + if (rc.bottom > rcG.bottom) + { + //Calculate amount to move things down. + cyList=(rcG.bottom-rcG.top)-(rc.bottom-rc.top-cyList); + + //Expand the group box. + rcG.right -=rcG.left; + rcG.bottom-=rcG.top; + SetWindowPos(GetDlgItem(hDlg, ID_GROUP), NULL, 0, 0 + , rcG.right, rcG.bottom+cyList + , SWP_NOMOVE | SWP_NOZORDER); + + //Expand the dialog box. + GetClientRect(hDlg, &rc); + SetWindowPos(hDlg, NULL, 0, 0, rc.right, rc.bottom+cyList + , SWP_NOMOVE | SWP_NOZORDER); + + //Move the label and edit controls down. + GetClientRect(GetDlgItem(hDlg, ID_LABEL), &rc); + SetWindowPos(GetDlgItem(hDlg, ID_LABEL), NULL, 0, cyList + , rc.right, rc.bottom, SWP_NOSIZE | SWP_NOZORDER); + + GetClientRect(GetDlgItem(hDlg, ID_LABELEDIT), &rc); + SetWindowPos(GetDlgItem(hDlg, ID_LABELEDIT), NULL, 0, cyList + , rc.right, rc.bottom, SWP_NOSIZE | SWP_NOZORDER); + } + + + /* + * 6. Select Current, Default, or From File radiobuttons appropriately. + * The CheckRadioButton call sends WM_COMMANDs which handle + * other actions. Note that if we check From File, which + * takes an icon from the list, we better fill the list. + * This will also fill the list even if default is selected. + */ + + if (0!=UFillIconList(hDlg, ID_ICONLIST, lpCI->szFile)) + { + //If szFile worked, then select the source icon in the listbox. + SendDlgItemMessage(hDlg, ID_ICONLIST, LB_SETCURSEL, lpCI->iIcon, 0L); + } + + + if (lpCI->dwFlags & CIF_SELECTCURRENT) + CheckRadioButton(hDlg, ID_CURRENT, ID_FROMFILE, ID_CURRENT); + else + { + uID=(lpCI->dwFlags & CIF_SELECTFROMFILE) ? ID_FROMFILE : ID_DEFAULT; + CheckRadioButton(hDlg, ID_CURRENT, ID_FROMFILE, uID); + } + + //7. Give our parent window access to our hDlg (via a special SetProp). + // The PasteSpecial dialog may need to force our dialog down if the + // clipboard contents change underneath it. if so it will send + // us a IDCANCEL command. + SetProp(lpCI->lpOCI->hWndOwner, PROP_HWND_CHGICONDLG, hDlg); + + lpCI->nBrowseHelpID = RegisterWindowMessage(HELPMSGSTRING); + + //8. Call the hook with lCustData in lParam + UStandardHook(lpCI, hDlg, WM_INITDIALOG, wParam, lpOCI->lCustData); + return TRUE; + } + + + + + +/* + * UFillIconList + * + * Purpose: + * Given a listbox and a filename, attempts to open that file and + * read all the icons that exist therein, adding them to the listbox + * hList as owner-draw items. If the file does not exist or has no + * icons, then you get no icons and an appropriate warning message. + * + * Parameters: + * hDlg HWND of the dialog containing the listbox. + * idList UINT identifier of the listbox to fill. + * pszFile LPSTR of the file from which to extract icons. + * + * Return Value: + * UINT Number of items added to the listbox. 0 on failure. + */ + +UINT UFillIconList(HWND hDlg, UINT idList, LPTSTR pszFile) + { + HWND hList; + UINT i; + UINT cIcons=0; + HCURSOR hCur; + HICON hIcon; + OFSTRUCT of; + + if (NULL==hDlg || !IsWindow(hDlg) || NULL==pszFile) + return 0; + + hList=GetDlgItem(hDlg, idList); + + if (NULL==hList) + return 0; + + //Clean out the listbox. + SendMessage(hList, LB_RESETCONTENT, 0, 0L); + + //If we have an empty string, just exit leaving the listbox empty as well + if (0==lstrlen(pszFile)) + return 0; + + //Turn on the hourglass + hCur=HourGlassOn(); + + //Check if the file is valid. + if (HFILE_ERROR!=DoesFileExist(pszFile, &of)) + { + #ifdef EXTRACTICONWORKS + //Get the icon count for this file. + cIcons=(UINT)ExtractIcon(ghInst, pszFile, (UINT)-1); + #else + /* + * ExtractIcon in Windows 3.1 with -1 eats a selector, leaving an + * extra global memory object around for this applciation. Since + * changing icons may happen very often with all OLE apps in + * the system, we have to work around it. So we'll say we + * have lots of icons and just call ExtractIcon until it + * fails. We check if there's any around by trying to get + * the first one. + */ + cIcons=0xFFFF; + + hIcon=ExtractIcon(ghInst, pszFile, 0); + + //Fake a failure with cIcons=0, or cleanup hIcon from this test. + if (32 > (UINT)hIcon) + cIcons=0; + else + DestroyIcon(hIcon); + #endif + + if (0!=cIcons) + { + SendMessage(hList, WM_SETREDRAW, FALSE, 0L); + + for (i=0; iitemID < 0) + return FALSE; + + /* + * For selection or draw entire case we just draw the entire item all + * over again. For focus cases, we only call DrawFocusRect. + */ + + if (lpDI->itemAction & (ODA_SELECT | ODA_DRAWENTIRE)) + { + //Clear background and draw the icon. + if (lpDI->itemState & ODS_SELECTED) + cr=SetBkColor(lpDI->hDC, GetSysColor(COLOR_HIGHLIGHT)); + else + cr=SetBkColor(lpDI->hDC, GetSysColor(COLOR_WINDOW)); + + //Draw a cheap rectangle. + ExtTextOut(lpDI->hDC, 0, 0, ETO_OPAQUE, &lpDI->rcItem + , NULL, 0, NULL); + + DrawIcon(lpDI->hDC, lpDI->rcItem.left+(CXICONPAD/2) + , lpDI->rcItem.top+(CYICONPAD/2) + , (HICON)LOWORD(lpDI->itemData)); + + //Restore original background for DrawFocusRect + SetBkColor(lpDI->hDC, cr); + } + + //Always change focus on the focus action. + if (lpDI->itemAction & ODA_FOCUS || lpDI->itemState & ODS_FOCUS) + DrawFocusRect(lpDI->hDC, &lpDI->rcItem); + + return TRUE; + } + + + + + +/* + * UpdateResultIcon + * + * Purpose: + * Updates the result icon using the current icon in the default display + * or the icon listbox depending on fFromDefault. + * + * Parameters: + * lpCI LPCHANGEICON containing dialog flags. + * hDlg HWND of the dialog + * uID UINT identifying the radiobutton selected. + * + * Return Value: + * None + */ + +void UpdateResultIcon(LPCHANGEICON lpCI, HWND hDlg, UINT uID) + { + UINT iSel; + LONG lTemp=LB_ERR; + + lpCI->dwFlags &= ~(CIF_SELECTCURRENT | CIF_SELECTDEFAULT | CIF_SELECTFROMFILE); + + switch (uID) + { + case ID_CURRENT: + lTemp=SendDlgItemMessage(hDlg, ID_CURRENTICON, STM_GETICON, 0, 0L); + lpCI->dwFlags |= CIF_SELECTCURRENT; + break; + + case ID_DEFAULT: + lTemp=SendDlgItemMessage(hDlg, ID_DEFAULTICON, STM_GETICON, 0, 0L); + lpCI->dwFlags |= CIF_SELECTDEFAULT; + break; + + case ID_FROMFILE: + //Get the selected icon from the list and place it in the result + lpCI->dwFlags |= CIF_SELECTFROMFILE; + + iSel=(UINT)SendDlgItemMessage(hDlg, ID_ICONLIST, LB_GETCURSEL, 0, 0L); + if ((UINT)LB_ERR==iSel) + lTemp=SendDlgItemMessage(hDlg, ID_DEFAULTICON, STM_GETICON, 0, 0L); + else + SendDlgItemMessage(hDlg, ID_ICONLIST, LB_GETTEXT, iSel + , (LPARAM)(LPLONG)&lTemp); + + break; + } + + if ((LONG)LB_ERR!=lTemp) + SendDlgItemMessage(hDlg, ID_RESULTICON, STM_SETICON, LOWORD(lTemp), 0L); + return; + } + + diff --git a/private/oleutest/letest/ole2ui/icon.dlg b/private/oleutest/letest/ole2ui/icon.dlg new file mode 100644 index 000000000..43a2f274c --- /dev/null +++ b/private/oleutest/letest/ole2ui/icon.dlg @@ -0,0 +1,48 @@ +// DLGINCLUDE RCDATA DISCARDABLE +// BEGIN +// "OLE2UI.H\0" +// END + + +IDD_CHANGEICON DIALOG 18, 18, 261, 152 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Change Icon" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Icon", ID_GROUP, 4, 6, 180, 124 + CONTROL "&Current", ID_CURRENT, "Button", BS_AUTORADIOBUTTON | + WS_GROUP , 10, 19, 46, 10 + + CONTROL "&Default", ID_DEFAULT, "Button", BS_AUTORADIOBUTTON, + 10, 44, 46, 10 + + CONTROL "&From File:", ID_FROMFILE, "Button", BS_AUTORADIOBUTTON, + 10, 68, 46, 10 + + ICON "", ID_CURRENTICON, 58, 15, 18, 20 + + ICON "", ID_DEFAULTICON, 58, 40, 18, 20 + + EDITTEXT ID_FROMFILEEDIT, 58, 68, 119, 12, ES_LOWERCASE | + ES_AUTOHSCROLL | WS_GROUP | ES_OEMCONVERT + + LISTBOX ID_ICONLIST, 58, 84, 119, 40, LBS_OWNERDRAWFIXED | + LBS_NOINTEGRALHEIGHT | LBS_MULTICOLUMN | WS_HSCROLL | + WS_TABSTOP + + LTEXT "&Label:", ID_LABEL, 6, 138, 32, 8 + + EDITTEXT ID_LABELEDIT, 38, 136, 146, 12, ES_AUTOHSCROLL + + DEFPUSHBUTTON "OK", IDOK, 189, 6, 66, 14 + + PUSHBUTTON "Cancel", IDCANCEL, 189, 23, 66, 14 + + PUSHBUTTON "&Browse...", ID_BROWSE, 189, 41, 66, 14 + + PUSHBUTTON "&Help", ID_OLEUIHELP, 189, 59, 66, 14 + + CTEXT "", ID_RESULTLABEL, 193, 114, 63, 24 + ICON "", ID_RESULTICON, 214, 90, 18, 20 +END + diff --git a/private/oleutest/letest/ole2ui/icon.h b/private/oleutest/letest/ole2ui/icon.h new file mode 100644 index 000000000..512155949 --- /dev/null +++ b/private/oleutest/letest/ole2ui/icon.h @@ -0,0 +1,59 @@ +/* + * ICON.H + * + * Internal definitions, structures, and function prototypes for the + * OLE 2.0 UI Change Icon dialog. + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + + +#ifndef _ICON_H_ +#define _ICON_H_ + +#ifndef RC_INVOKED +#pragma message ("INCLUDING ICON.H from " __FILE__) +#endif /* RC_INVOKED */ + +#define CXICONPAD 12 +#define CYICONPAD 4 + +// Property used by ChangeIcon dialog to give its parent window access to +// its hDlg. The PasteSpecial dialog may need to force the ChgIcon dialog +// down if the clipboard contents change underneath it. if so it will send +// a IDCANCEL command to the ChangeIcon dialog. +#define PROP_HWND_CHGICONDLG TEXT("HWND_CIDLG") + +//Internally used structure +typedef struct tagCHANGEICON + { + LPOLEUICHANGEICON lpOCI; //Original structure passed. + + /* + * What we store extra in this structure besides the original caller's + * pointer are those fields that we need to modify during the life of + * the dialog but that we don't want to change in the original structure + * until the user presses OK. + */ + DWORD dwFlags; + HICON hCurIcon; + TCHAR szLabel[OLEUI_CCHLABELMAX+1]; + TCHAR szFile[OLEUI_CCHPATHMAX]; + UINT iIcon; + HICON hDefIcon; + TCHAR szDefIconFile[OLEUI_CCHPATHMAX]; + UINT iDefIcon; + UINT nBrowseHelpID; // Help ID callback for Browse dlg + } CHANGEICON, *PCHANGEICON, FAR *LPCHANGEICON; + + +//Internal function prototypes +//ICON.C +BOOL CALLBACK EXPORT ChangeIconDialogProc(HWND, UINT, WPARAM, LPARAM); +BOOL FChangeIconInit(HWND, WPARAM, LPARAM); +UINT UFillIconList(HWND, UINT, LPTSTR); +BOOL FDrawListIcon(LPDRAWITEMSTRUCT); +void UpdateResultIcon(LPCHANGEICON, HWND, UINT); + + +#endif //_ICON_H_ diff --git a/private/oleutest/letest/ole2ui/iconbox.c b/private/oleutest/letest/ole2ui/iconbox.c new file mode 100644 index 000000000..8422f5dcc --- /dev/null +++ b/private/oleutest/letest/ole2ui/iconbox.c @@ -0,0 +1,253 @@ +/* + * ICONBOX.C + * + * Implemenatation of an IconBox control for OLE 2.0 UI dialogs that we'll + * use wherever a dialog needs an icon/label display. Through the control's + * interface we can change the image or control label visibility. + * + * The IconBox discusses images in CF_METAFILEPICT format. When drawing + * such a metafile, the entire aspect is centered in the IconBox, so long + * labels are chopped at either end. + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + + +#define STRICT 1 +#include "ole2ui.h" +#include "iconbox.h" + + +//Flag indicating if we've registered the class +static BOOL fRegistered=FALSE; + + +/* + * FIconBoxInitialize + * + * Purpose: + * Registers the IconBox control class. + * + * Parameters: + * hInst HINSTANCE instance of the DLL. + * + * hPrevInst HINSTANCE of the previous instance. Used to + * determine whether to register window classes or not. + * + * lpszClassName LPSTR containing the class name to register the + * IconBox control class with. + * + * Return Value: + * BOOL TRUE if all initialization succeeded, FALSE otherwise. + */ + +BOOL FIconBoxInitialize(HINSTANCE hInst, HINSTANCE hPrevInst, LPTSTR lpszClassName) + { + WNDCLASS wc; + + // Only register class if we're the first instance + if (hPrevInst) + fRegistered = TRUE; + else + { + + // Static flag fRegistered guards against calling this function more + // than once + if (!fRegistered) + { + wc.lpfnWndProc =IconBoxWndProc; + wc.cbClsExtra =0; + wc.cbWndExtra =CBICONBOXWNDEXTRA; + wc.hInstance =hInst; + wc.hIcon =NULL; + wc.hCursor =LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground =(HBRUSH)NULL; + wc.lpszMenuName =NULL; + wc.lpszClassName =lpszClassName; + wc.style =CS_GLOBALCLASS | CS_VREDRAW | CS_HREDRAW; + + fRegistered=RegisterClass(&wc); + } + } + + return fRegistered; +} + + +/* + * IconBoxUninitialize + * + * Purpose: + * Cleans up anything done in FIconBoxInitialize. Currently there is + * nothing, but we do this for symmetry. + * + * Parameters: + * None + * + * Return Value: + * None + */ + +void IconBoxUninitialize(void) + { + //Nothing to do. + return; + } + + + + + + +/* + * IconBoxWndProc + * + * Purpose: + * Window Procedure for the IconBox custom control. Only handles + * WM_CREATE, WM_PAINT, and private messages to manipulate the image. + * + * Parameters: + * Standard + * + * Return Value: + * Standard + */ + +LONG CALLBACK EXPORT IconBoxWndProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam) + { + HGLOBAL hMF=NULL; + PAINTSTRUCT ps; + HDC hDC; + RECT rc; + + + //Handle standard Windows messages. + switch (iMsg) + { + case WM_CREATE: + SetWindowLong(hWnd, IBWW_HIMAGE, 0); + SetWindowWord(hWnd, IBWW_FLABEL, TRUE); + return 0L; + + + case WM_ERASEBKGND: + { + + HBRUSH hBrush; + RECT Rect; +#if defined( WIN32 ) + POINT point; +#endif + + GetClientRect(hWnd, &Rect); +#if defined( WIN32 ) + hBrush = (HBRUSH)SendMessage(GetParent(hWnd), + WM_CTLCOLORDLG, + wParam, + (LPARAM)GetParent(hWnd)); +#else + hBrush = (HBRUSH)SendMessage(GetParent(hWnd), + WM_CTLCOLOR, + wParam, + MAKELPARAM(GetParent(hWnd), CTLCOLOR_DLG)); +#endif + + + if (!hBrush) + return FALSE; + + UnrealizeObject(hBrush); + +#if defined( WIN32 ) + SetBrushOrgEx((HDC)wParam, 0, 0, &point); +#else + SetBrushOrg((HDC)wParam, 0, 0); +#endif + + FillRect((HDC)wParam, &Rect, hBrush); + + return TRUE; + } + + + case WM_PAINT: + hMF=(HGLOBAL)GetWindowLong(hWnd, IBWW_HIMAGE); + + //BeginPaint and EndPaint clear us even if hMF is NULL. + hDC=BeginPaint(hWnd, &ps); + + if (NULL!=hMF) + { + BOOL fLabel; + + //Now we get to paint the metafile, centered in our rect. + GetClientRect(hWnd, &rc); + + /* + * If we're doing icon only, then place the metafile + * at the center of our box minus half the icon width. + * Top is top. + */ + + fLabel=GetWindowWord(hWnd, IBWW_FLABEL); + + + //Go draw where we decided to place it. + OleUIMetafilePictIconDraw(hDC, &rc, hMF, !fLabel); + } + + EndPaint(hWnd, &ps); + break; + + + case IBXM_IMAGESET: + /* + * wParam contains the new handle. + * lParam is a flag to delete the old or not. + */ + hMF=(HGLOBAL)SetWindowLong(hWnd, IBWW_HIMAGE, wParam); + InvalidateRect(hWnd, NULL, TRUE); + UpdateWindow(hWnd); + + //Delete the old handle if requested + if (0L!=lParam) + { + OleUIMetafilePictIconFree(hMF); + hMF=NULL; + } + + return (LONG)(UINT)hMF; + + + case IBXM_IMAGEGET: + //Return the current index. + hMF=(HGLOBAL)GetWindowLong(hWnd, IBWW_HIMAGE); + return (LONG)(UINT)hMF; + + + case IBXM_IMAGEFREE: + //Free up whatever we're holding. + hMF=(HGLOBAL)GetWindowLong(hWnd, IBWW_HIMAGE); + OleUIMetafilePictIconFree(hMF); + return 1L; + + + case IBXM_LABELENABLE: + //wParam has the new flag, returns the previous flag. + return (LONG)SetWindowWord(hWnd, IBWW_FLABEL, (WORD)wParam); + + + default: + return DefWindowProc(hWnd, iMsg, wParam, lParam); + } + + return 0L; + } + + + + + + + + diff --git a/private/oleutest/letest/ole2ui/iconbox.h b/private/oleutest/letest/ole2ui/iconbox.h new file mode 100644 index 000000000..057b59e75 --- /dev/null +++ b/private/oleutest/letest/ole2ui/iconbox.h @@ -0,0 +1,31 @@ +/* + * ICONBOX.H + * + * Structures and definitions for the IconBox control. + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + + +#ifndef _ICONBOX_H_ +#define _ICONBOX_H_ + +//Function prototypes +BOOL FIconBoxInitialize(HINSTANCE, HINSTANCE, LPTSTR); +void IconBoxUninitialize(void); +LONG CALLBACK EXPORT IconBoxWndProc(HWND, UINT, WPARAM, LPARAM); + + +//Window extra bytes contain the bitmap index we deal with currently. +#define CBICONBOXWNDEXTRA (sizeof(HGLOBAL)+sizeof(BOOL)) +#define IBWW_HIMAGE 0 +#define IBWW_FLABEL (sizeof(HGLOBAL)) + +//Control messages +#define IBXM_IMAGESET (WM_USER+0) +#define IBXM_IMAGEGET (WM_USER+1) +#define IBXM_IMAGEFREE (WM_USER+2) +#define IBXM_LABELENABLE (WM_USER+3) + + +#endif //_ICONBOX_H_ diff --git a/private/oleutest/letest/ole2ui/insobj.c b/private/oleutest/letest/ole2ui/insobj.c new file mode 100644 index 000000000..53fa094c9 --- /dev/null +++ b/private/oleutest/letest/ole2ui/insobj.c @@ -0,0 +1,1724 @@ +/* + * INSOBJ.C + * + * Implements the OleUIInsertObject function which invokes the complete + * Insert Object dialog. Makes use of the OleChangeIcon function in + * ICON.C. + * + * Copyright (c)1993 Microsoft Corporation, All Rights Reserved + */ + +#define STRICT 1 +#include "ole2ui.h" +#include +#include +#include +#include +#include +#include +#include "common.h" +#include "utility.h" +#include "icon.h" +#include "insobj.h" +#include "resimage.h" +#include "iconbox.h" +#include "geticon.h" + +#define IS_FILENAME_DELIM(c) ( (c) == TEXT('\\') || (c) == TEXT('/') || (c) == TEXT(':') ) + +/* + * OleUIInsertObject + * + * Purpose: + * Invokes the standard OLE Insert Object dialog box allowing the + * user to select an object source and classname as well as the option + * to display the object as itself or as an icon. + * + * Parameters: + * lpIO LPOLEUIINSERTOBJECT pointing to the in-out structure + * for this dialog. + * + * Return Value: + * UINT OLEUI_SUCCESS or OLEUI_OK if all is well, otherwise + * an error value. + */ + +STDAPI_(UINT) OleUIInsertObject(LPOLEUIINSERTOBJECT lpIO) + { + UINT uRet; + HGLOBAL hMemDlg=NULL; + HRESULT hrErr; + + uRet=UStandardValidation((LPOLEUISTANDARD)lpIO, sizeof(OLEUIINSERTOBJECT) + , &hMemDlg); + + if (OLEUI_SUCCESS!=uRet) + return uRet; + + //Now we can do Insert Object specific validation. + + + // NULL is NOT valid for lpszFile + if ( (NULL == lpIO->lpszFile) + || (IsBadReadPtr(lpIO->lpszFile, lpIO->cchFile)) + || (IsBadWritePtr(lpIO->lpszFile, lpIO->cchFile)) ) + uRet=OLEUI_IOERR_LPSZFILEINVALID; + + if (NULL != lpIO->lpszFile + && (lpIO->cchFile <= 0 || lpIO->cchFile > OLEUI_CCHPATHMAX_SIZE)) + uRet=OLEUI_IOERR_CCHFILEINVALID; + + if (0!=lpIO->cClsidExclude) + { + if (NULL!=lpIO->lpClsidExclude && IsBadReadPtr(lpIO->lpClsidExclude + , lpIO->cClsidExclude*sizeof(CLSID))) + uRet=OLEUI_IOERR_LPCLSIDEXCLUDEINVALID; + } + + //If we have flags to create any object, validate necessary data. + if (lpIO->dwFlags & (IOF_CREATENEWOBJECT | IOF_CREATEFILEOBJECT | IOF_CREATELINKOBJECT)) + { + if (NULL!=lpIO->lpFormatEtc + && IsBadReadPtr(lpIO->lpFormatEtc, sizeof(FORMATETC))) + uRet=OLEUI_IOERR_LPFORMATETCINVALID; + + if (NULL!=lpIO->ppvObj && IsBadWritePtr(lpIO->ppvObj, sizeof(LPVOID))) + uRet=OLEUI_IOERR_PPVOBJINVALID; + + if (NULL!=lpIO->lpIOleClientSite + && IsBadReadPtr(lpIO->lpIOleClientSite->lpVtbl, sizeof(IOleClientSiteVtbl))) + uRet=OLEUI_IOERR_LPIOLECLIENTSITEINVALID; + + if (NULL!=lpIO->lpIStorage + && IsBadReadPtr(lpIO->lpIStorage->lpVtbl, sizeof(IStorageVtbl))) + uRet=OLEUI_IOERR_LPISTORAGEINVALID; + } + + if (OLEUI_ERR_STANDARDMIN <= uRet) + { + if (NULL!=hMemDlg) + FreeResource(hMemDlg); + + return uRet; + } + + //Now that we've validated everything, we can invoke the dialog. + uRet=UStandardInvocation(InsertObjectDialogProc, (LPOLEUISTANDARD)lpIO + , hMemDlg, MAKEINTRESOURCE(IDD_INSERTOBJECT)); + + + //Stop here if we cancelled or had an error. + if (OLEUI_SUCCESS !=uRet && OLEUI_OK!=uRet) + return uRet; + + + /* + * If any of the flags specify that we're to create objects on return + * from this dialog, then do so. If we encounter an error in this + * processing, we return OLEUI_IOERR_SCODEHASERROR. Since the + * three select flags are mutually exclusive, we don't have to + * if...else here, just if each case (keeps things cleaner that way). + */ + + lpIO->sc=S_OK; + + //Check if Create New was selected and we have IOF_CREATENEWOBJECT + if ((lpIO->dwFlags & IOF_SELECTCREATENEW) && (lpIO->dwFlags & IOF_CREATENEWOBJECT)) + { + hrErr=OleCreate(&lpIO->clsid, &lpIO->iid, lpIO->oleRender + , lpIO->lpFormatEtc, lpIO->lpIOleClientSite, lpIO->lpIStorage + , lpIO->ppvObj); + lpIO->sc = GetScode(hrErr); + } + + //Try Create From File + if ((lpIO->dwFlags & IOF_SELECTCREATEFROMFILE)) + { + if (!(lpIO->dwFlags & IOF_CHECKLINK) && (lpIO->dwFlags & IOF_CREATEFILEOBJECT)) + { + hrErr=OleCreateFromFileA(&CLSID_NULL, lpIO->lpszFile, &lpIO->iid + , lpIO->oleRender, lpIO->lpFormatEtc, lpIO->lpIOleClientSite + , lpIO->lpIStorage, lpIO->ppvObj); + lpIO->sc = GetScode(hrErr); + } + + if ((lpIO->dwFlags & IOF_CHECKLINK) && (lpIO->dwFlags & IOF_CREATELINKOBJECT)) + { + hrErr=OleCreateLinkToFileA(lpIO->lpszFile, &lpIO->iid + , lpIO->oleRender, lpIO->lpFormatEtc, lpIO->lpIOleClientSite + , lpIO->lpIStorage, lpIO->ppvObj); + lpIO->sc = GetScode(hrErr); + } + } + + //If we tried but failed a create option, then return the appropriate error + if (S_OK!=lpIO->sc) + uRet=OLEUI_IOERR_SCODEHASERROR; + + return uRet; + } + + + + + +/* + * InsertObjectDialogProc + * + * Purpose: + * Implements the OLE Insert Object dialog as invoked through the + * OleUIInsertObject function. + */ + +BOOL CALLBACK EXPORT InsertObjectDialogProc(HWND hDlg, UINT iMsg + , WPARAM wParam, LPARAM lParam) + { + LPOLEUIINSERTOBJECT lpOIO; + LPINSERTOBJECT lpIO; + OLEUICHANGEICON ci; + UINT i; + BOOL fCheck=FALSE; + UINT uRet=0; + + //Declare Win16/Win32 compatible WM_COMMAND parameters. + COMMANDPARAMS(wID, wCode, hWndMsg); + + //This will fail under WM_INITDIALOG, where we allocate it. + lpIO=(LPINSERTOBJECT)LpvStandardEntry(hDlg, iMsg, wParam, lParam, &uRet); + + //If the hook processed the message, we're done. + if (0!=uRet) + return (BOOL)uRet; + + //Process help message from Change Icon + if (iMsg==uMsgHelp) + { + PostMessage(lpIO->lpOIO->hWndOwner, uMsgHelp, wParam, lParam); + return FALSE; + } + + //Process the temination message + if (iMsg==uMsgEndDialog) + { + InsertObjectCleanup(hDlg); + StandardCleanup(lpIO, hDlg); + EndDialog(hDlg, wParam); + return TRUE; + } + + switch (iMsg) + { + case WM_INITDIALOG: + return FInsertObjectInit(hDlg, wParam, lParam); + + case WM_COMMAND: + switch (wID) + { + case ID_IO_CREATENEW: + FToggleObjectSource(hDlg, lpIO, IOF_SELECTCREATENEW); + break; + + case ID_IO_CREATEFROMFILE: + FToggleObjectSource(hDlg, lpIO, IOF_SELECTCREATEFROMFILE); + break; + + case ID_IO_LINKFILE: + fCheck=IsDlgButtonChecked(hDlg, wID); + + if (fCheck) + lpIO->dwFlags |=IOF_CHECKLINK; + else + lpIO->dwFlags &=~IOF_CHECKLINK; + + //Results change here, so be sure to update it. + SetInsertObjectResults(hDlg, lpIO); + UpdateClassIcon(hDlg, lpIO, NULL); + break; + + case ID_IO_OBJECTTYPELIST: + switch (wCode) + { + case LBN_SELCHANGE: + UpdateClassIcon(hDlg, lpIO, hWndMsg); + SetInsertObjectResults(hDlg, lpIO); + break; + + case LBN_DBLCLK: + //Same as pressing OK. + SendCommand(hDlg, IDOK, BN_CLICKED, hWndMsg); + break; + } + break; + + + case ID_IO_FILEDISPLAY: + //If there are characters, enable OK and Display As Icon + if (EN_CHANGE==wCode) + { + lpIO->fFileDirty = TRUE; + lpIO->fFileValid = FALSE; + + lpIO->fFileSelected= + (0L!=SendMessage(hWndMsg, EM_LINELENGTH, 0, 0L)); + EnableWindow(GetDlgItem(hDlg, ID_IO_LINKFILE), lpIO->fFileSelected); + EnableWindow(GetDlgItem(hDlg, ID_IO_DISPLAYASICON), lpIO->fFileSelected); + EnableWindow(GetDlgItem(hDlg, ID_IO_CHANGEICON), lpIO->fFileSelected); + EnableWindow(GetDlgItem(hDlg, IDOK), lpIO->fFileSelected); + } + + if (EN_KILLFOCUS==wCode && NULL!=lpIO) + { + if (FValidateInsertFile(hDlg,FALSE,&lpIO->nErrCode)) { + lpIO->fFileDirty = FALSE; + lpIO->fFileValid = TRUE; + UpdateClassIcon(hDlg, lpIO, NULL); + UpdateClassType(hDlg, lpIO, TRUE); + } else { + lpIO->fFileDirty = FALSE; + lpIO->fFileValid = FALSE; + UpdateClassType(hDlg, lpIO, FALSE); + } + } + break; + + + case ID_IO_DISPLAYASICON: + fCheck=IsDlgButtonChecked(hDlg, wID); + EnableWindow(GetDlgItem(hDlg, ID_IO_CHANGEICON), fCheck); + + if (fCheck) + lpIO->dwFlags |=IOF_CHECKDISPLAYASICON; + else + lpIO->dwFlags &=~IOF_CHECKDISPLAYASICON; + + //Update the internal flag based on this checking + if (lpIO->dwFlags & IOF_SELECTCREATENEW) + lpIO->fAsIconNew=fCheck; + else + lpIO->fAsIconFile=fCheck; + + //Re-read the class icon on Display checked + if (fCheck) + { + if (lpIO->dwFlags & IOF_SELECTCREATEFROMFILE) + { + if (FValidateInsertFile(hDlg, TRUE,&lpIO->nErrCode)) + { + lpIO->fFileDirty = FALSE; + lpIO->fFileValid = TRUE; + UpdateClassIcon(hDlg, lpIO, + GetDlgItem(hDlg, ID_IO_OBJECTTYPELIST)); + + UpdateClassType(hDlg, lpIO, TRUE); + } + + else + { + HWND hWndEC; + + lpIO->fAsIconFile= FALSE; + lpIO->fFileDirty = FALSE; + lpIO->fFileValid = FALSE; + SendDlgItemMessage(hDlg, ID_IO_ICONDISPLAY, IBXM_IMAGESET, 0, 0L); + UpdateClassType(hDlg, lpIO, FALSE); + + lpIO->dwFlags &=~IOF_CHECKDISPLAYASICON; + CheckDlgButton(hDlg, ID_IO_DISPLAYASICON, 0); + + hWndEC = GetDlgItem(hDlg, ID_IO_FILEDISPLAY); + SetFocus(hWndEC); + SendMessage(hWndEC, EM_SETSEL, 0, MAKELPARAM(0, (WORD)-1)); + return TRUE; + } + } + else + UpdateClassIcon(hDlg, lpIO, + GetDlgItem(hDlg, ID_IO_OBJECTTYPELIST)); + } + + + //Results change here, so be sure to update it. + SetInsertObjectResults(hDlg, lpIO); + + + /* + * Show or hide controls as appropriate. Do the icon + * display last because it will take some time to repaint. + * If we do it first then the dialog looks too sluggish. + */ + i=(fCheck) ? SW_SHOWNORMAL : SW_HIDE; + StandardShowDlgItem(hDlg, ID_IO_CHANGEICON, i); + StandardShowDlgItem(hDlg, ID_IO_ICONDISPLAY, i); + + break; + + + case ID_IO_CHANGEICON: + { + + LPMALLOC pIMalloc; + HWND hList; + LPTSTR pszString, pszCLSID; + + int iCurSel; + + // if we're in SELECTCREATEFROMFILE mode, then we need to Validate + // the contents of the edit control first. + + if (lpIO->dwFlags & IOF_SELECTCREATEFROMFILE) + { + if ( lpIO->fFileDirty + && !FValidateInsertFile(hDlg, TRUE, &lpIO->nErrCode) ) + { + HWND hWndEC; + + lpIO->fFileDirty = TRUE; + hWndEC = GetDlgItem(hDlg, ID_IO_FILEDISPLAY); + SetFocus(hWndEC); + SendMessage(hWndEC, EM_SETSEL, 0, MAKELPARAM(0, (WORD)-1)); + return TRUE; + } + else + lpIO->fFileDirty = FALSE; + } + + + + //Initialize the structure for the hook. + _fmemset((LPOLEUICHANGEICON)&ci, 0, sizeof(ci)); + + ci.hMetaPict=(HGLOBAL)SendDlgItemMessage(hDlg + , ID_IO_ICONDISPLAY, IBXM_IMAGEGET, 0, 0L); + + ci.cbStruct =sizeof(ci); + ci.hWndOwner=hDlg; + ci.dwFlags =CIF_SELECTCURRENT; + + if (lpIO->dwFlags & IOF_SHOWHELP) + ci.dwFlags |= CIF_SHOWHELP; + + + + + if (lpIO->dwFlags & IOF_SELECTCREATENEW) + { + // Initialize clsid... + if (NOERROR != CoGetMalloc(MEMCTX_TASK, &pIMalloc)) + return FALSE; + + pszString = (LPTSTR)pIMalloc->lpVtbl->Alloc(pIMalloc, + OLEUI_CCHKEYMAX_SIZE + + OLEUI_CCHCLSIDSTRING_SIZE); + + + hList = GetDlgItem(hDlg, ID_IO_OBJECTTYPELIST); + iCurSel = (int)SendMessage(hList, LB_GETCURSEL, 0, 0L); + SendMessage(hList, LB_GETTEXT, iCurSel, (LONG)pszString); + + pszCLSID = PointerToNthField(pszString, 2, TEXT('\t')); + + CLSIDFromStringA((LPTSTR)pszCLSID, (LPCLSID)&(ci.clsid)); + + pIMalloc->lpVtbl->Free(pIMalloc, (LPVOID)pszString); + pIMalloc->lpVtbl->Release(pIMalloc); + } + else // IOF_SELECTCREATEFROMFILE + { + + TCHAR szFileName[OLEUI_CCHPATHMAX]; + + GetDlgItemText(hDlg, ID_IO_FILEDISPLAY, (LPTSTR)szFileName, OLEUI_CCHPATHMAX); + + if (NOERROR != GetClassFileA(szFileName, (LPCLSID)&(ci.clsid))) + { + LPTSTR lpszExtension; + int istrlen; + + istrlen = lstrlen(szFileName); + + lpszExtension = (LPTSTR)szFileName + istrlen -1; + + while ( (lpszExtension > szFileName) && + (*lpszExtension != TEXT('.')) ) + lpszExtension--; + + GetAssociatedExecutable(lpszExtension, (LPTSTR)ci.szIconExe); + ci.cchIconExe = lstrlen(ci.szIconExe); + ci.dwFlags |= CIF_USEICONEXE; + + } + } + + + //Let the hook in to customize Change Icon if desired. + uRet=UStandardHook(lpIO, hDlg, uMsgChangeIcon + , 0, (LONG)(LPTSTR)&ci); + + if (0==uRet) + uRet=(UINT)(OLEUI_OK==OleUIChangeIcon(&ci)); + + //Update the display and itemdata if necessary. + if (0!=uRet) + { + + /* + * OleUIChangeIcon will have already freed our + * current hMetaPict that we passed in when OK is + * pressed in that dialog. So we use 0L as lParam + * here so the IconBox doesn't try to free the + * metafilepict again. + */ + SendDlgItemMessage(hDlg, ID_IO_ICONDISPLAY, IBXM_IMAGESET + , (WPARAM)ci.hMetaPict, 0L); + + if (lpIO->dwFlags & IOF_SELECTCREATENEW) + SendMessage(hList, LB_SETITEMDATA, iCurSel, ci.hMetaPict); + } + } + break; + + + case ID_IO_FILE: + { + /* + * To allow the hook to customize the browse dialog, we + * send OLEUI_MSG_BROWSE. If the hook returns FALSE + * we use the default, otherwise we trust that it retrieved + * a filename for us. This mechanism prevents hooks from + * trapping ID_IO_BROWSE to customize the dialog and from + * trying to figure out what we do after we have the name. + */ + + TCHAR szTemp[OLEUI_CCHPATHMAX]; + TCHAR szInitialDir[OLEUI_CCHPATHMAX]; + DWORD dwOfnFlags; + int nChars; + BOOL fUseInitialDir = FALSE; + + + nChars = GetDlgItemText(hDlg, ID_IO_FILEDISPLAY, (LPTSTR)szTemp, OLEUI_CCHPATHMAX); + + if (FValidateInsertFile(hDlg, FALSE, &lpIO->nErrCode)) + { + + int istrlen; + + GetFileTitle((LPTSTR)szTemp, lpIO->szFile, OLEUI_CCHPATHMAX); + + istrlen = lstrlen(lpIO->szFile); + + LSTRCPYN((LPTSTR)szInitialDir, szTemp, nChars - istrlen); + fUseInitialDir = TRUE; + + } + else // file name isn't valid...lop off end of szTemp to get a + // valid directory + { +#if defined( WIN32 ) + TCHAR szBuffer[OLEUI_CCHPATHMAX]; + DWORD Attribs; + + LSTRCPYN(szBuffer, szTemp, OLEUI_CCHPATHMAX-1); + szBuffer[OLEUI_CCHPATHMAX-1] = TEXT('\0'); + + if (TEXT('\\') == szBuffer[nChars-1]) + szBuffer[nChars-1] = TEXT('\0'); + + Attribs = GetFileAttributes(szBuffer); + if (Attribs != 0xffffffff && + (Attribs & FILE_ATTRIBUTE_DIRECTORY) ) + { + lstrcpy(szInitialDir, (LPTSTR)szBuffer); + fUseInitialDir = TRUE; + } +#else + static TCHAR szBuffer[OLEUI_CCHPATHMAX]; + static int attrib ; + + LSTRCPYN(szBuffer, szTemp, OLEUI_CCHPATHMAX-1); + szBuffer[OLEUI_CCHPATHMAX-1] = TEXT('\0'); + + AnsiToOem(szBuffer, szBuffer); +#if defined( OBSOLETE ) // fix bug# 3575 + if (TEXT('\\') == szBuffer[nChars-1]) + szBuffer[nChars-1] = TEXT('\0'); + + if(0 == _dos_getfileattr(szBuffer, &attrib)) +#endif // OBSOLETE + { + lstrcpy(szInitialDir, (LPTSTR)szBuffer); + fUseInitialDir = TRUE; + } +#endif + *lpIO->szFile = TEXT('\0'); + } + + uRet=UStandardHook(lpIO, hDlg, uMsgBrowse + , OLEUI_CCHPATHMAX_SIZE, (LPARAM)(LPSTR)lpIO->szFile); + + dwOfnFlags = OFN_FILEMUSTEXIST; + + if (lpIO->lpOIO->dwFlags & IOF_SHOWHELP) + dwOfnFlags |= OFN_SHOWHELP; + + if (0==uRet) + uRet=(UINT)Browse(hDlg, + lpIO->szFile, + fUseInitialDir ? (LPTSTR)szInitialDir : NULL, + OLEUI_CCHPATHMAX_SIZE, + IDS_FILTERS, + dwOfnFlags); + + //Only update if the file changed. + if (0!=uRet && 0!=lstrcmpi(szTemp, lpIO->szFile)) + { + SetDlgItemText(hDlg, ID_IO_FILEDISPLAY, lpIO->szFile); + lpIO->fFileSelected=TRUE; + + if (FValidateInsertFile(hDlg, TRUE, &lpIO->nErrCode)) + { + lpIO->fFileDirty = FALSE; + lpIO->fFileValid = TRUE; + UpdateClassIcon(hDlg, lpIO, NULL); + UpdateClassType(hDlg, lpIO, TRUE); + // auto set OK to be default button if valid file + SendMessage(hDlg, DM_SETDEFID, + (WPARAM)GetDlgItem(hDlg, IDOK), 0L); + SetFocus(GetDlgItem(hDlg, IDOK)); + } + else // filename is invalid - set focus back to ec + { + HWND hWnd; + + lpIO->fFileDirty = FALSE; + lpIO->fFileValid = FALSE; + hWnd = GetDlgItem(hDlg, ID_IO_FILEDISPLAY); + SetFocus(hWnd); + SendMessage(hWnd, EM_SETSEL, 0, MAKELPARAM(0, (WORD)-1)); + } + + //Once we have a file, Display As Icon is always enabled + EnableWindow(GetDlgItem(hDlg, ID_IO_DISPLAYASICON), TRUE); + + //As well as OK + EnableWindow(GetDlgItem(hDlg, IDOK), TRUE); + + } + } + break; + + + case IDOK: + { + HWND hListBox; + WORD iCurSel; + TCHAR szBuffer[OLEUI_CCHKEYMAX + OLEUI_CCHCLSIDSTRING]; + LPTSTR lpszCLSID; + + if ((HWND)(LOWORD(lParam)) != GetFocus()) + SetFocus((HWND)(LOWORD(lParam))); + + + + // If the file name is clean (already validated), or + // if Create New is selected, then we can skip this part. + + if ( (lpIO->dwFlags & IOF_SELECTCREATEFROMFILE) + && (TRUE == lpIO->fFileDirty) ) + { + + if (FValidateInsertFile(hDlg, TRUE, &lpIO->nErrCode)) + { + lpIO->fFileDirty = FALSE; + lpIO->fFileValid = TRUE; + UpdateClassIcon(hDlg, lpIO, NULL); + UpdateClassType(hDlg, lpIO, TRUE); + } + else // filename is invalid - set focus back to ec + { + HWND hWnd; + + lpIO->fFileDirty = FALSE; + lpIO->fFileValid = FALSE; + hWnd = GetDlgItem(hDlg, ID_IO_FILEDISPLAY); + SetFocus(hWnd); + SendMessage(hWnd, EM_SETSEL, 0, MAKELPARAM(0, (WORD)-1)); + UpdateClassType(hDlg, lpIO, FALSE); + } + + return TRUE; // eat this message + } + else if ( (lpIO->dwFlags & IOF_SELECTCREATEFROMFILE) + && (FALSE == lpIO->fFileValid) ) + { + // filename is invalid - set focus back to ec + HWND hWnd; + TCHAR szFile[OLEUI_CCHPATHMAX]; + + if (0!=GetDlgItemText(hDlg, ID_IO_FILEDISPLAY, + szFile, OLEUI_CCHPATHMAX)) + { + OpenFileError(hDlg, lpIO->nErrCode, szFile); + } + lpIO->fFileDirty = FALSE; + lpIO->fFileValid = FALSE; + hWnd = GetDlgItem(hDlg, ID_IO_FILEDISPLAY); + SetFocus(hWnd); + SendMessage(hWnd, EM_SETSEL, 0, MAKELPARAM(0, (WORD)-1)); + UpdateClassType(hDlg, lpIO, FALSE); + return TRUE; // eat this message + } + + //Copy the necessary information back to the original struct + lpOIO=lpIO->lpOIO; + lpOIO->dwFlags=lpIO->dwFlags; + + if (lpIO->dwFlags & IOF_SELECTCREATENEW) + { + hListBox=GetDlgItem(hDlg, ID_IO_OBJECTTYPELIST); + iCurSel=(WORD)SendMessage(hListBox, LB_GETCURSEL, 0, 0); + + if (lpIO->dwFlags & IOF_CHECKDISPLAYASICON) + { + lpOIO->hMetaPict=(HGLOBAL)SendMessage(hListBox, + LB_GETITEMDATA, iCurSel, 0L); + + /* + * Set the item data to 0 here so that the cleanup + * code doesn't delete the metafile. + */ + SendMessage(hListBox, LB_SETITEMDATA, iCurSel, 0L); + } + else + lpOIO->hMetaPict = (HGLOBAL)NULL; + + SendMessage(hListBox, LB_GETTEXT, iCurSel + , (LPARAM)(LPTSTR)szBuffer); + + lpszCLSID=PointerToNthField((LPTSTR)szBuffer, 2, TEXT('\t')); + CLSIDFromStringA(lpszCLSID, &lpOIO->clsid); + + } + else // IOF_SELECTCREATEFROMFILE + { + if (lpIO->dwFlags & IOF_CHECKDISPLAYASICON) + { + // get metafile here + lpOIO->hMetaPict = (HGLOBAL)SendDlgItemMessage(hDlg, + ID_IO_ICONDISPLAY, + IBXM_IMAGEGET, + 0, 0L); + + + } + else + lpOIO->hMetaPict = (HGLOBAL)NULL; + + } + + GetDlgItemText(hDlg, ID_IO_FILEDISPLAY, + lpIO->szFile, lpOIO->cchFile); + + LSTRCPYN(lpOIO->lpszFile, lpIO->szFile, lpOIO->cchFile); + + SendMessage(hDlg, uMsgEndDialog, OLEUI_OK, 0L); + } + break; + + case IDCANCEL: + SendMessage(hDlg, uMsgEndDialog, OLEUI_CANCEL, 0L); + break; + + case ID_OLEUIHELP: + PostMessage(lpIO->lpOIO->hWndOwner, uMsgHelp + , (WPARAM)hDlg, MAKELPARAM(IDD_INSERTOBJECT, 0)); + break; + } + break; + + default: + { + if (lpIO && iMsg == lpIO->nBrowseHelpID) { + PostMessage(lpIO->lpOIO->hWndOwner, uMsgHelp, + (WPARAM)hDlg, MAKELPARAM(IDD_INSERTFILEBROWSE, 0)); + } + } + break; + } + + return FALSE; + } + + + + +/* + * FInsertObjectInit + * + * Purpose: + * WM_INITIDIALOG handler for the Insert Object dialog box. + * + * Parameters: + * hDlg HWND of the dialog + * wParam WPARAM of the message + * lParam LPARAM of the message + * + * Return Value: + * BOOL Value to return for WM_INITDIALOG. + */ + +BOOL FInsertObjectInit(HWND hDlg, WPARAM wParam, LPARAM lParam) + { + LPOLEUIINSERTOBJECT lpOIO; + LPINSERTOBJECT lpIO; + RECT rc; + DWORD dw; + HFONT hFont; + HWND hList; + UINT u; + BOOL fCheck; + CHAR *pch; // pointer to current working directory + // ANSI string (to use with _getcwd) + + //1. Copy the structure at lParam into our instance memory. + lpIO=(LPINSERTOBJECT)LpvStandardInit(hDlg, sizeof(INSERTOBJECT), TRUE, &hFont); + + //PvStandardInit send a termination to us already. + if (NULL==lpIO) + return FALSE; + + lpOIO=(LPOLEUIINSERTOBJECT)lParam; + + //2. Save the original pointer and copy necessary information. + lpIO->lpOIO =lpOIO; + lpIO->dwFlags=lpOIO->dwFlags; + lpIO->clsid =lpOIO->clsid; + + if ( (lpOIO->lpszFile) && (TEXT('\0') != *lpOIO->lpszFile) ) + LSTRCPYN((LPTSTR)lpIO->szFile, lpOIO->lpszFile, OLEUI_CCHPATHMAX); + else + *(lpIO->szFile) = TEXT('\0'); + + lpIO->hMetaPictFile = (HGLOBAL)NULL; + + //3. If we got a font, send it to the necessary controls. + if (NULL!=hFont) + { + SendDlgItemMessage(hDlg, ID_IO_RESULTTEXT, WM_SETFONT, (WPARAM)hFont, 0L); + SendDlgItemMessage(hDlg, ID_IO_FILETYPE, WM_SETFONT, (WPARAM)hFont, 0L); + } + + + //4. Fill the Object Type listbox with entries from the reg DB. + hList=GetDlgItem(hDlg, ID_IO_OBJECTTYPELIST); + UFillClassList(hList, lpOIO->cClsidExclude, lpOIO->lpClsidExclude + , (BOOL)(lpOIO->dwFlags & IOF_VERIFYSERVERSEXIST)); + + //Set the tab width in the list to push all the tabs off the side. + GetClientRect(hList, &rc); + dw=GetDialogBaseUnits(); + rc.right =(8*rc.right)/LOWORD(dw); //Convert pixels to 2x dlg units. + SendMessage(hList, LB_SETTABSTOPS, 1, (LPARAM)(LPINT)&rc.right); + + + //5. Initilize the file name display to cwd if we don't have any name. + if (TEXT('\0') == *(lpIO->szFile)) + { + TCHAR tch[OLEUI_CCHPATHMAX]; + + pch=_getcwd(NULL, OLEUI_CCHPATHMAX); + if (*(pch+strlen(pch)-1) != '\\') + strcat(pch, "\\"); // put slash on end of cwd +#ifdef UNICODE + mbstowcs(tch, pch, OLEUI_CCHPATHMAX); +#else + strcpy(tch, pch); +#endif + SetDlgItemText(hDlg, ID_IO_FILEDISPLAY, tch); + lpIO->fFileDirty = TRUE; // cwd is not a valid filename + #ifndef __TURBOC__ + free(pch); + #endif + } + else + { + SetDlgItemText(hDlg, ID_IO_FILEDISPLAY, lpIO->szFile); + + if (FValidateInsertFile(hDlg, FALSE, &lpIO->nErrCode)) + lpIO->fFileDirty = FALSE; + else + lpIO->fFileDirty = TRUE; + } + + + //6. Initialize the selected type radiobutton. + if (lpIO->dwFlags & IOF_SELECTCREATENEW) + { + StandardShowDlgItem(hDlg, ID_IO_FILETEXT, SW_HIDE); + StandardShowDlgItem(hDlg, ID_IO_FILETYPE, SW_HIDE); + StandardShowDlgItem(hDlg, ID_IO_FILEDISPLAY, SW_HIDE); + StandardShowDlgItem(hDlg, ID_IO_FILE, SW_HIDE); + StandardShowDlgItem(hDlg, ID_IO_LINKFILE, SW_HIDE); + + CheckRadioButton(hDlg, ID_IO_CREATENEW, ID_IO_CREATEFROMFILE, ID_IO_CREATENEW); + + lpIO->fAsIconNew=(0L!=(lpIO->dwFlags & IOF_CHECKDISPLAYASICON)); + SetFocus(hList); + } + else + { + /* + * Use pszType as the initial File. If there's no initial + * file then we have to remove any check from Display As + * Icon. We also check Link if so indicated for this option. + */ + StandardShowDlgItem(hDlg, ID_IO_OBJECTTYPELIST, SW_HIDE); + StandardShowDlgItem(hDlg, ID_IO_OBJECTTYPETEXT, SW_HIDE); + + // Don't preselect display as icon if the filename isn't valid + if (TRUE == lpIO->fFileDirty) + lpIO->dwFlags &= ~(IOF_CHECKDISPLAYASICON); + + if (IOF_DISABLELINK & lpIO->dwFlags) + StandardShowDlgItem(hDlg, ID_IO_LINKFILE, SW_HIDE); + else + { + CheckDlgButton(hDlg, ID_IO_LINKFILE + , (BOOL)(0L!=(lpIO->dwFlags & IOF_CHECKLINK))); + } + + CheckRadioButton(hDlg, ID_IO_CREATENEW, ID_IO_CREATEFROMFILE, ID_IO_CREATEFROMFILE); + + lpIO->fAsIconFile=(0L!=(lpIO->dwFlags & IOF_CHECKDISPLAYASICON)); + SetFocus(GetDlgItem(hDlg, ID_IO_FILEDISPLAY)); + } + + + //7. Initialize the Display as Icon state + fCheck=(BOOL)(lpIO->dwFlags & IOF_CHECKDISPLAYASICON); + u=fCheck ? SW_SHOWNORMAL : SW_HIDE; + + StandardShowDlgItem(hDlg, ID_IO_CHANGEICON, u); + StandardShowDlgItem(hDlg, ID_IO_ICONDISPLAY, u); + + CheckDlgButton(hDlg, ID_IO_DISPLAYASICON, fCheck); + + + //8. Show or hide the help button + if (!(lpIO->dwFlags & IOF_SHOWHELP)) + StandardShowDlgItem(hDlg, ID_OLEUIHELP, SW_HIDE); + + + //9. Initialize the result display + UpdateClassIcon(hDlg, lpIO, GetDlgItem(hDlg, ID_IO_OBJECTTYPELIST)); + SetInsertObjectResults(hDlg, lpIO); + + //10. Change the caption + if (NULL!=lpOIO->lpszCaption) + SetWindowText(hDlg, lpOIO->lpszCaption); + + //11. Hide all DisplayAsIcon related controls if it should be disabled + if ( lpIO->dwFlags & IOF_DISABLEDISPLAYASICON ) { + StandardShowDlgItem(hDlg, ID_IO_DISPLAYASICON, SW_HIDE); + StandardShowDlgItem(hDlg, ID_IO_CHANGEICON, SW_HIDE); + StandardShowDlgItem(hDlg, ID_IO_ICONDISPLAY, SW_HIDE); + } + + lpIO->nBrowseHelpID = RegisterWindowMessage(HELPMSGSTRING); + + //All Done: call the hook with lCustData + UStandardHook(lpIO, hDlg, WM_INITDIALOG, wParam, lpOIO->lCustData); + + /* + * We either set focus to the listbox or the edit control. In either + * case we don't want Windows to do any SetFocus, so we return FALSE. + */ + return FALSE; + } + + + + + + +/* + * UFillClassList + * + * Purpose: + * Enumerates available OLE object classes from the registration + * database and fills a listbox with those names. + * + * Note that this function removes any prior contents of the listbox. + * + * Parameters: + * hList HWND to the listbox to fill. + * cIDEx UINT number of CLSIDs to exclude in lpIDEx + * lpIDEx LPCLSID to CLSIDs to leave out of the listbox. + * fVerify BOOL indicating if we are to validate existence of + * servers before putting them in the list. + * + * Return Value: + * UINT Number of strings added to the listbox, -1 on failure. + */ + +UINT UFillClassList(HWND hList, UINT cIDEx, LPCLSID lpIDEx, BOOL fVerify) + { + DWORD dw; + UINT cStrings=0; + UINT i; + UINT cch; + HKEY hKey; + LONG lRet; + HFILE hFile; + OFSTRUCT of; + BOOL fExclude; + LPMALLOC pIMalloc; + LPTSTR pszExec; + LPTSTR pszClass; + LPTSTR pszKey; + LPTSTR pszID; + CLSID clsid; + + //Get some work buffers + if (NOERROR!=CoGetMalloc(MEMCTX_TASK, &pIMalloc)) + return (UINT)-1; + + pszExec=(LPTSTR)pIMalloc->lpVtbl->Alloc(pIMalloc, OLEUI_CCHKEYMAX_SIZE*4); + + if (NULL==pszExec) + { + pIMalloc->lpVtbl->Release(pIMalloc); + return (UINT)-1; + } + + pszClass=pszExec+OLEUI_CCHKEYMAX; + pszKey=pszClass+OLEUI_CCHKEYMAX; + pszID=pszKey+OLEUI_CCHKEYMAX; + + //Open up the root key. + lRet=RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hKey); + + if ((LONG)ERROR_SUCCESS!=lRet) + { + pIMalloc->lpVtbl->Free(pIMalloc, (LPVOID)pszExec); + pIMalloc->lpVtbl->Release(pIMalloc); + return (UINT)-1; + } + + //Clean out the existing strings. + SendMessage(hList, LB_RESETCONTENT, 0, 0L); + + cStrings=0; + + while (TRUE) + { + lRet=RegEnumKey(hKey, cStrings++, pszClass, OLEUI_CCHKEYMAX_SIZE); + + if ((LONG)ERROR_SUCCESS!=lRet) + break; + + //Cheat on lstrcat by using lstrcpy after this string, saving time + cch=lstrlen(pszClass); + + // Check for \NotInsertable. if this is found then this overrides + // all other keys; this class will NOT be added to the InsertObject + // list. + + lstrcpy(pszClass+cch, TEXT("\\NotInsertable")); + + dw=OLEUI_CCHKEYMAX_SIZE; + lRet=RegQueryValue(hKey, pszClass, pszKey, &dw); + + if ((LONG)ERROR_SUCCESS==lRet) + continue; // NotInsertable IS found--skip this class + + //Check for a \protocol\StdFileEditing\server entry. + lstrcpy(pszClass+cch, TEXT("\\protocol\\StdFileEditing\\server")); + + dw=OLEUI_CCHKEYMAX_SIZE; + lRet=RegQueryValue(hKey, pszClass, pszKey, &dw); + + if ((LONG)ERROR_SUCCESS==lRet) + { + /* + * Check if the EXE actually exists. By default we don't do this + * to bring up the dialog faster. If an application wants to be + * stringent, they can provide IOF_VERIFYSERVERSEXIST. + */ + + hFile = !HFILE_ERROR; + + if (fVerify) + hFile=DoesFileExist(pszKey, &of); + + if (HFILE_ERROR!=hFile) + { + dw=OLEUI_CCHKEYMAX_SIZE; + *(pszClass+cch)=0; // set back to rootkey + // Get full user type name + lRet=RegQueryValue(hKey, pszClass, pszKey, &dw); + + if ((LONG)ERROR_SUCCESS!=lRet) + continue; // error getting type name--skip this class + + //Tell the code below to get the string for us. + pszID=NULL; + } + } + else + { + /* + * No \protocol\StdFileEditing\server entry. Look to see if + * there's an Insertable entry. If there is, then use the + * Clsid to look at CLSID\clsid\LocalServer and \InprocServer + */ + + lstrcpy(pszClass+cch, TEXT("\\Insertable")); + + dw=OLEUI_CCHKEYMAX_SIZE; + lRet=RegQueryValue(hKey, pszClass, pszKey, &dw); + + if ((LONG)ERROR_SUCCESS!=lRet) + continue; // Insertable NOT found--skip this class + + //Get memory for pszID + pszID=pIMalloc->lpVtbl->Alloc(pIMalloc, OLEUI_CCHKEYMAX_SIZE); + + if (NULL==pszID) + continue; + + *(pszClass+cch)=0; // set back to rootkey + lstrcat(pszClass+cch, TEXT("\\CLSID")); + + dw=OLEUI_CCHKEYMAX_SIZE; + lRet=RegQueryValue(hKey, pszClass, pszID, &dw); + + if ((LONG)ERROR_SUCCESS!=lRet) + continue; // CLSID subkey not found + + lstrcpy(pszExec, TEXT("CLSID\\")); + lstrcat(pszExec, pszID); + + //CLSID\ is 6, dw contains pszID length. + cch=6+(UINT)dw; + + lstrcpy(pszExec+cch, TEXT("\\LocalServer")); + dw=OLEUI_CCHKEYMAX_SIZE; + lRet=RegQueryValue(hKey, pszExec, pszKey, &dw); + + if ((LONG)ERROR_SUCCESS!=lRet) + { + //Try InprocServer + lstrcpy(pszExec+cch, TEXT("\\InProcServer")); + dw=OLEUI_CCHKEYMAX_SIZE; + lRet=RegQueryValue(hKey, pszExec, pszKey, &dw); + + if ((LONG)ERROR_SUCCESS!=lRet) + continue; + } + + if (fVerify) + { + if (HFILE_ERROR==DoesFileExist(pszKey, &of)) + continue; + } + + dw=OLEUI_CCHKEYMAX_SIZE; + lRet=RegQueryValue(hKey, pszExec, pszKey, &dw); + *(pszExec+cch)=0; //Remove \\*Server + + if ((LONG)ERROR_SUCCESS!=lRet) + continue; + } + + //Get CLSID to add to listbox. + if (NULL==pszID) + { + CLSIDFromProgIDA(pszClass, &clsid); + StringFromCLSIDA(&clsid, &pszID); + } + else + CLSIDFromStringA(pszID, &clsid); + + //Check if this CLSID is in the exclusion list. + fExclude=FALSE; + + for (i=0; i < cIDEx; i++) + { + if (IsEqualCLSID(&clsid, (LPCLSID)(lpIDEx+i))) + { + fExclude=TRUE; + break; + } + } + + if (fExclude) + continue; + + //We go through all the conditions, add the string. + lstrcat(pszKey, TEXT("\t")); + + // only add to listbox if not a duplicate + if (LB_ERR==SendMessage(hList,LB_FINDSTRING,0,(LPARAM)pszKey)) { + lstrcat(pszKey, pszID); + SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)pszKey); + } + + //We always allocated this regardless of the path + pIMalloc->lpVtbl->Free(pIMalloc, (LPVOID)pszID); + } + + + //Select the first item by default + SendMessage(hList, LB_SETCURSEL, 0, 0L); + RegCloseKey(hKey); + + pIMalloc->lpVtbl->Free(pIMalloc, (LPVOID)pszExec); + pIMalloc->lpVtbl->Release(pIMalloc); + + return cStrings; + } + + + + + +/* + * FToggleObjectSource + * + * Purpose: + * Handles enabling, disabling, showing, and flag manipulation when the + * user changes between Create New, Insert File, and Link File in the + * Insert Object dialog. + * + * Parameters: + * hDlg HWND of the dialog + * lpIO LPINSERTOBJECT pointing to the dialog structure + * dwOption DWORD flag indicating the option just selected: + * IOF_SELECTCREATENEW or IOF_SELECTCREATEFROMFILE + * + * Return Value: + * BOOL TRUE if the option was already selected, FALSE otherwise. + */ + +BOOL FToggleObjectSource(HWND hDlg, LPINSERTOBJECT lpIO, DWORD dwOption) + { + BOOL fTemp; + UINT uTemp; + DWORD dwTemp; + int i; + + //Skip all of this if we're already selected. + if (lpIO->dwFlags & dwOption) + return TRUE; + + + // if we're switching from "from file" to "create new" and we've got + // an icon for "from file", then we need to save it so that we can + // show it if the user reselects "from file". + + if ( (IOF_SELECTCREATENEW == dwOption) && + (lpIO->dwFlags & IOF_CHECKDISPLAYASICON) ) + lpIO->hMetaPictFile = (HGLOBAL)SendDlgItemMessage(hDlg, ID_IO_ICONDISPLAY, IBXM_IMAGEGET, 0, 0L); + + /* + * 1. Change the Display As Icon checked state to reflect the + * selection for this option, stored in the fAsIcon* flags. + */ + fTemp=(IOF_SELECTCREATENEW==dwOption) ? lpIO->fAsIconNew : lpIO->fAsIconFile; + + if (fTemp) + lpIO->dwFlags |=IOF_CHECKDISPLAYASICON; + else + lpIO->dwFlags &=~IOF_CHECKDISPLAYASICON; + + CheckDlgButton(hDlg, ID_IO_DISPLAYASICON + , (BOOL)(0L!=(lpIO->dwFlags & IOF_CHECKDISPLAYASICON))); + + EnableWindow(GetDlgItem(hDlg, ID_IO_CHANGEICON), fTemp); + + /* + * 2. Display Icon: Enabled on Create New or on Create from File if + * there is a selected file. + */ + fTemp=(IOF_SELECTCREATENEW==dwOption) ? TRUE : lpIO->fFileSelected; + EnableWindow(GetDlgItem(hDlg, ID_IO_DISPLAYASICON), fTemp); + + //OK and Link follow the same enabling as Display As Icon. + EnableWindow(GetDlgItem(hDlg, IDOK), fTemp); + EnableWindow(GetDlgItem(hDlg, ID_IO_LINKFILE), fTemp); + + //3. Enable Browse... when Create from File is selected. + fTemp=(IOF_SELECTCREATENEW==dwOption); + EnableWindow(GetDlgItem(hDlg, ID_IO_FILE), !fTemp); + EnableWindow(GetDlgItem(hDlg, ID_IO_FILEDISPLAY), !fTemp); + + /* + * 4. Switch between Object Type listbox on Create New and + * file buttons on others. + */ + uTemp=(fTemp) ? SW_SHOWNORMAL : SW_HIDE; + StandardShowDlgItem(hDlg, ID_IO_OBJECTTYPELIST, uTemp); + StandardShowDlgItem(hDlg, ID_IO_OBJECTTYPETEXT, uTemp); + + uTemp=(fTemp) ? SW_HIDE : SW_SHOWNORMAL; + StandardShowDlgItem(hDlg, ID_IO_FILETEXT, uTemp); + StandardShowDlgItem(hDlg, ID_IO_FILETYPE, uTemp); + StandardShowDlgItem(hDlg, ID_IO_FILEDISPLAY, uTemp); + StandardShowDlgItem(hDlg, ID_IO_FILE, uTemp); + + //Link is always hidden if IOF_DISABLELINK is set. + if (IOF_DISABLELINK & lpIO->dwFlags) + uTemp=SW_HIDE; + + StandardShowDlgItem(hDlg, ID_IO_LINKFILE, uTemp); //last use of uTemp + + + //5. Clear out existing any flags selection and set the new one + dwTemp=IOF_SELECTCREATENEW | IOF_SELECTCREATEFROMFILE; + lpIO->dwFlags=(lpIO->dwFlags & ~dwTemp) | dwOption; + + + /* + * Show or hide controls as appropriate. Do the icon + * display last because it will take some time to repaint. + * If we do it first then the dialog looks too sluggish. + */ + + i=(lpIO->dwFlags & IOF_CHECKDISPLAYASICON) ? SW_SHOWNORMAL : SW_HIDE; + StandardShowDlgItem(hDlg, ID_IO_CHANGEICON, i); + StandardShowDlgItem(hDlg, ID_IO_ICONDISPLAY, i); + + + //6.Change result display + SetInsertObjectResults(hDlg, lpIO); + + /* + * 7. For Create New, twiddle the listbox to think we selected it + * so it updates the icon from the object type. set the focus + * to the list box. + * + * For Insert or Link file, set the focus to the filename button + * and update the icon if necessary. + */ + if (fTemp) { + UpdateClassIcon(hDlg, lpIO, GetDlgItem(hDlg, ID_IO_OBJECTTYPELIST)); + SetFocus(GetDlgItem(hDlg, ID_IO_OBJECTTYPELIST)); + } + else + { + if (lpIO->fAsIconFile && (NULL != lpIO->hMetaPictFile) ) + { + SendDlgItemMessage(hDlg, ID_IO_ICONDISPLAY, IBXM_IMAGESET, (WPARAM)lpIO->hMetaPictFile, 0L); + lpIO->hMetaPictFile = 0; + } + else + UpdateClassIcon(hDlg, lpIO, NULL); + + SetFocus(GetDlgItem(hDlg, ID_IO_FILE)); + } + + return FALSE; + } + + +/* + * UpdateClassType + * + * Purpose: + * Updates static text control to reflect current file type. Assumes + * a valid filename. + * + * Parameters + * hDlg HWND of the dialog box. + * lpIO LPINSERTOBJECT pointing to the dialog structure + * fSet TRUE to set the text, FALSE to explicitly clear it + * + * Return Value: + * None + */ + +void UpdateClassType(HWND hDlg, LPINSERTOBJECT lpIO, BOOL fSet) +{ + + CLSID clsid; + TCHAR szFileName[OLEUI_CCHPATHMAX]; + TCHAR szFileType[OLEUI_CCHLABELMAX]; + + *szFileType = TEXT('\0'); + + if (fSet) + { + GetDlgItemText(hDlg, ID_IO_FILEDISPLAY, (LPTSTR)szFileName, OLEUI_CCHPATHMAX); + + if (NOERROR == GetClassFileA(szFileName, &clsid) ) + OleStdGetUserTypeOfClass(&clsid, szFileType, OLEUI_CCHLABELMAX_SIZE, NULL); + + } + + SetDlgItemText(hDlg, ID_IO_FILETYPE, (LPTSTR)szFileType); + + return; +} + + +/* + * UpdateClassIcon + * + * Purpose: + * Handles LBN_SELCHANGE for the Object Type listbox. On a selection + * change, we extract an icon from the server handling the currently + * selected object type using the utility function HIconFromClass. + * Note that we depend on the behavior of FillClassList to stuff the + * object class after a tab in the listbox string that we hide from + * view (see WM_INITDIALOG). + * + * Parameters + * hDlg HWND of the dialog box. + * lpIO LPINSERTOBJECT pointing to the dialog structure + * hList HWND of the Object Type listbox. + * + * Return Value: + * None + */ + +void UpdateClassIcon(HWND hDlg, LPINSERTOBJECT lpIO, HWND hList) + { + UINT iSel; + DWORD cb; + LPMALLOC pIMalloc; + LPTSTR pszName, pszCLSID, pszTemp; + HGLOBAL hMetaPict; + + LRESULT dwRet; + + + //If Display as Icon is not selected, exit + if (!(lpIO->dwFlags & IOF_CHECKDISPLAYASICON)) + return; + + /* + * When we change object type selection, get the new icon for that + * type into our structure and update it in the display. We use the + * class in the listbox when Create New is selected or the association + * with the extension in Create From File. + */ + + if (lpIO->dwFlags & IOF_SELECTCREATENEW) + { + iSel=(UINT)SendMessage(hList, LB_GETCURSEL, 0, 0L); + + if (LB_ERR==(int)iSel) + return; + + //Check to see if we've already got the hMetaPict for this item + dwRet=SendMessage(hList, LB_GETITEMDATA, (WPARAM)iSel, 0L); + + hMetaPict=(HGLOBAL)(UINT)dwRet; + + if (hMetaPict) + { + //Yep, we've already got it, so just display it and return. + SendDlgItemMessage(hDlg, ID_IO_ICONDISPLAY, IBXM_IMAGESET, (WPARAM)hMetaPict, 0L); + return; + } + + iSel=(UINT)SendMessage(hList, LB_GETCURSEL, 0, 0L); + + if (LB_ERR==(int)iSel) + return; + + //Allocate a string to hold the entire listbox string + cb=SendMessage(hList, LB_GETTEXTLEN, iSel, 0L); + } + else + cb=OLEUI_CCHPATHMAX_SIZE; + + if (NOERROR!=CoGetMalloc(MEMCTX_TASK, &pIMalloc)) + return; + + pszName=(LPTSTR)pIMalloc->lpVtbl->Alloc(pIMalloc, cb+1*sizeof(TCHAR) ); + + if (NULL==pszName) + { + pIMalloc->lpVtbl->Release(pIMalloc); + return; + } + + *pszName=0; + + //Get the clsid we want. + if (lpIO->dwFlags & IOF_SELECTCREATENEW) + { + //Grab the classname string from the list + SendMessage(hList, LB_GETTEXT, iSel, (LONG)pszName); + + //Set pointer to CLSID (string) + pszCLSID=PointerToNthField(pszName, 2, TEXT('\t')); + + //Null terminate pszName string +#ifdef WIN32 + // AnsiPrev is obsolete in Win32 + pszTemp=CharPrev((LPCTSTR) pszName,(LPCTSTR) pszCLSID); +#else + pszTemp=AnsiPrev((LPCTSTR) pszName,(LPCTSTR) pszCLSID); +#endif + *pszTemp=TEXT('\0'); + CLSIDFromStringA(pszCLSID, &lpIO->clsid); + +#ifdef OLE201 + hMetaPict = GetIconOfClass(ghInst, &lpIO->clsid, NULL, TRUE); +#endif + } + + else + { + //Get the class from the filename + GetDlgItemText(hDlg, ID_IO_FILEDISPLAY, pszName, OLEUI_CCHPATHMAX); + +#ifdef OLE201 + + hMetaPict = OleGetIconOfFileA(pszName, + lpIO->dwFlags & IOF_CHECKLINK ? TRUE : FALSE); + +#endif + + } + + //Replace the current display with this new one. + SendDlgItemMessage(hDlg, ID_IO_ICONDISPLAY, IBXM_IMAGESET, (WPARAM)hMetaPict, 0L); + + //Enable or disable "Change Icon" button depending on whether + //we've got a valid filename or not. + EnableWindow(GetDlgItem(hDlg, ID_IO_CHANGEICON), hMetaPict ? TRUE : FALSE); + + //Save the hMetaPict so that we won't have to re-create + if (lpIO->dwFlags & IOF_SELECTCREATENEW) + SendMessage(hList, LB_SETITEMDATA, (WPARAM)iSel, hMetaPict); + + pIMalloc->lpVtbl->Free(pIMalloc, (LPVOID)pszName); + pIMalloc->lpVtbl->Release(pIMalloc); + return; + } + + + + +/* + * SetInsertObjectResults + * + * Purpose: + * Centralizes setting of the Result and icon displays in the Insert Object + * dialog. Handles loading the appropriate string from the module's + * resources and setting the text, displaying the proper result picture, + * and showing the proper icon. + * + * Parameters: + * hDlg HWND of the dialog box so we can access controls. + * lpIO LPINSERTOBJECT in which we assume that the + * current radiobutton and Display as Icon selections + * are set. We use the state of those variables to + * determine which string we use. + * + * Return Value: + * None + */ + +void SetInsertObjectResults(HWND hDlg, LPINSERTOBJECT lpIO) + { + LPTSTR pszT, psz1, psz2, psz3, psz4, pszTemp; + UINT i, iString1, iString2, iImage, cch; + LPMALLOC pIMalloc; + BOOL fAsIcon; + + /* + * We need scratch memory for loading the stringtable string, loading + * the object type from the listbox, and constructing the final string. + * We therefore allocate three buffers as large as the maximum message + * length (512) plus the object type, guaranteeing that we have enough + * in all cases. + */ + i=(UINT)SendDlgItemMessage(hDlg, ID_IO_OBJECTTYPELIST, LB_GETCURSEL, 0, 0L); + cch=512+ + (UINT)SendDlgItemMessage(hDlg, ID_IO_OBJECTTYPELIST, LB_GETTEXTLEN, i, 0L); + + if (NOERROR!=CoGetMalloc(MEMCTX_TASK, &pIMalloc)) + return; + + pszTemp=(LPTSTR)pIMalloc->lpVtbl->Alloc(pIMalloc, (DWORD)(4*cch*sizeof(TCHAR))); + + if (NULL==pszTemp) + { + pIMalloc->lpVtbl->Release(pIMalloc); + return; + } + + psz1=pszTemp; + psz2=psz1+cch; + psz3=psz2+cch; + psz4=psz3+cch; + + fAsIcon=(0L!=(lpIO->dwFlags & IOF_CHECKDISPLAYASICON)); + + if (lpIO->dwFlags & IOF_SELECTCREATENEW) + { + iString1 = fAsIcon ? IDS_IORESULTNEWICON : IDS_IORESULTNEW; + iString2 = 0; + iImage = fAsIcon ? RESULTIMAGE_EMBEDICON : RESULTIMAGE_EMBED; + } + + if (lpIO->dwFlags & IOF_SELECTCREATEFROMFILE) + { + //Pay attention to Link checkbox + if (lpIO->dwFlags & IOF_CHECKLINK) + { + iString1 = fAsIcon ? IDS_IORESULTLINKFILEICON1 : IDS_IORESULTLINKFILE1; + iString2 = fAsIcon ? IDS_IORESULTLINKFILEICON2 : IDS_IORESULTLINKFILE2; + iImage =fAsIcon ? RESULTIMAGE_LINKICON : RESULTIMAGE_LINK; + } + else + { + iString1 = IDS_IORESULTFROMFILE1; + iString2 = fAsIcon ? IDS_IORESULTFROMFILEICON2 : IDS_IORESULTFROMFILE2; + iImage =fAsIcon ? RESULTIMAGE_EMBEDICON : RESULTIMAGE_EMBED; + } + } + + //Default is an empty string. + *psz1=0; + + if (0!=LoadString(ghInst, iString1, psz1, cch)) + { + + // Load second string, if necessary + if ( (0 != iString2) + && (0 != LoadString(ghInst, iString2, psz4, cch)) ) + { + lstrcat(psz1, psz4); // concatenate strings together. + } + + + + //In Create New, do the extra step of inserting the object type string + if (lpIO->dwFlags & IOF_SELECTCREATENEW) + { + SendDlgItemMessage(hDlg, ID_IO_OBJECTTYPELIST, LB_GETTEXT + , i, (LONG)psz2); + + //Null terminate at any tab (before the classname) + pszT=psz2; + while (TEXT('\t')!=*pszT && 0!=*pszT) + pszT++; + *pszT=0; + + //Build the string and point psz1 to it. + wsprintf(psz3, psz1, psz2); + psz1=psz3; + } + } + + //If LoadString failed, we simply clear out the results (*psz1=0 above) + SetDlgItemText(hDlg, ID_IO_RESULTTEXT, psz1); + + //Go change the image and Presto! There you have it. + SendDlgItemMessage(hDlg, ID_IO_RESULTIMAGE, RIM_IMAGESET, iImage, 0L); + + pIMalloc->lpVtbl->Free(pIMalloc, (LPVOID)pszTemp); + pIMalloc->lpVtbl->Release(pIMalloc); + return; + } + + + +/* + * FValidateInsertFile + * + * Purpose: + * Given a possibly partial pathname from the file edit control, + * attempt to locate the file and if found, store the full path + * in the edit control ID_IO_FILEDISPLAY. + * + * Parameters: + * hDlg HWND of the dialog box. + * fTellUser BOOL TRUE if function should tell user, FALSE if + * function should validate silently. + * + * Return Value: + * BOOL TRUE if the file is acceptable, FALSE otherwise. + */ + +BOOL FValidateInsertFile(HWND hDlg, BOOL fTellUser, UINT FAR* lpnErrCode) + { + OFSTRUCT of; + HFILE hFile; + TCHAR szFile[OLEUI_CCHPATHMAX]; + + *lpnErrCode = 0; + /* + * To validate we attempt OpenFile on the string. If OpenFile + * fails then we display an error. If not, OpenFile will store + * the complete path to that file in the OFSTRUCT which we can + * then stuff in the edit control. + */ + + if (0==GetDlgItemText(hDlg, ID_IO_FILEDISPLAY, szFile, OLEUI_CCHPATHMAX)) + return FALSE; // #4569 : return FALSE when there is no text in ctl + + hFile=DoesFileExist(szFile, &of); + + // if file is currently open (ie. sharing violation) OleCreateFromFile + // and OleCreateLinkToFile can still succeed; do not consider it an + // error. + if (HFILE_ERROR==hFile && 0x0020/*sharing violation*/!=of.nErrCode) + { + *lpnErrCode = of.nErrCode; + if (fTellUser) + OpenFileError(hDlg, of.nErrCode, szFile); + return FALSE; + } + + //OFSTRUCT contains an OEM name, not ANSI as we need for the edit box. + OemToAnsi(of.szPathName, of.szPathName); + + SetDlgItemText(hDlg, ID_IO_FILEDISPLAY, of.szPathName); + return TRUE; + } + + +/* + * InsertObjectCleanup + * + * Purpose: + * Clears cached icon metafiles from those stored in the listbox. + * + * Parameters: + * hDlg HWND of the dialog. + * + * Return Value: + * None + */ + +void InsertObjectCleanup(HWND hDlg) + { + HWND hList; + UINT iItems; + HGLOBAL hMetaPict; + LRESULT dwRet; + UINT i; + + hList=GetDlgItem(hDlg, ID_IO_OBJECTTYPELIST); + iItems=(UINT)SendMessage(hList, LB_GETCOUNT, 0, 0L); + + for (i=0; i < iItems; i++) + { + dwRet=SendMessage(hList, LB_GETITEMDATA, (WPARAM)i, 0L); + + //Cast of LRESULT to UINT to HGLOBAL portable to Win32. + hMetaPict=(HGLOBAL)(UINT)dwRet; + + if (hMetaPict) + OleUIMetafilePictIconFree(hMetaPict); + } + + return; + } diff --git a/private/oleutest/letest/ole2ui/insobj.dlg b/private/oleutest/letest/ole2ui/insobj.dlg new file mode 100644 index 000000000..2f81811a0 --- /dev/null +++ b/private/oleutest/letest/ole2ui/insobj.dlg @@ -0,0 +1,51 @@ +//DLGINCLUDE RCDATA DISCARDABLE +//BEGIN +// "OLE2UI.H\0" +//END + +IDD_INSERTOBJECT DIALOG 6, 18, 291, 150 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Insert Object" +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "Create &New", ID_IO_CREATENEW, "Button", + BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP, 6, 18, 67, 10 + + CONTROL "Create from &File", ID_IO_CREATEFROMFILE, "Button", + BS_AUTORADIOBUTTON | WS_TABSTOP, 6, 36, 67, 10 + + LTEXT "Object &Type:", ID_IO_OBJECTTYPETEXT, 84, 4, 110, 8 + + LISTBOX ID_IO_OBJECTTYPELIST, 82, 16, 132, 73, LBS_SORT | + LBS_USETABSTOPS | WS_VSCROLL | WS_GROUP | WS_TABSTOP + + LTEXT "Fil&e:", ID_IO_FILETEXT, 82, 24, 20, 8 + LTEXT "", ID_IO_FILETYPE, 120, 24, 80, 8 + + EDITTEXT ID_IO_FILEDISPLAY, 82, 34, 132, 12, ES_AUTOHSCROLL | ES_LOWERCASE | ES_OEMCONVERT + + PUSHBUTTON "&Browse...", ID_IO_FILE, 82, 50, 48, 14 + + CONTROL "&Link", ID_IO_LINKFILE, "Button", BS_AUTOCHECKBOX | + WS_TABSTOP, 140, 52, 40, 10 + + DEFPUSHBUTTON "OK", IDOK, 222, 6, 66, 14, WS_GROUP + + PUSHBUTTON "Cancel", IDCANCEL, 222, 24, 66, 14 + + PUSHBUTTON "&Help", ID_OLEUIHELP, 222, 42, 66, 14 + + CONTROL "&Display As Icon", ID_IO_DISPLAYASICON, "Button", + BS_AUTOCHECKBOX | WS_TABSTOP, 222, 64, 66, 10 + + CONTROL "", ID_IO_ICONDISPLAY, SZCLASSICONBOX, 0, 220, 80, 66, 46 + + PUSHBUTTON "Change &Icon...", ID_IO_CHANGEICON, 222, 127, 66, 14 + + GROUPBOX "Result", ID_STATIC, 6, 96, 210, 47, WS_GROUP + +// CONTROL "", ID_IO_RESULTIMAGE, SZCLASSRESULTIMAGE, 0, 10, 106, 42, 34 + + LTEXT "Result", ID_IO_RESULTTEXT, 56, 106, 156, 32, SS_NOPREFIX | + NOT WS_GROUP +END diff --git a/private/oleutest/letest/ole2ui/insobj.h b/private/oleutest/letest/ole2ui/insobj.h new file mode 100644 index 000000000..1958d7f4f --- /dev/null +++ b/private/oleutest/letest/ole2ui/insobj.h @@ -0,0 +1,52 @@ +/* + * INSOBJ.H + * + * Internal definitions, structures, and function prototypes for the + * OLE 2.0 UI Insert Object dialog. + * + * Copyright (c)1993 Microsoft Corporation, All Rights Reserved + */ + + +#ifndef _INSOBJ_H_ +#define _INSOBJ_H_ + +//Internally used structure +typedef struct tagINSERTOBJECT + { + LPOLEUIINSERTOBJECT lpOIO; //Original structure passed. + + /* + * What we store extra in this structure besides the original caller's + * pointer are those fields that we need to modify during the life of + * the dialog but that we don't want to change in the original structure + * until the user presses OK. + */ + DWORD dwFlags; + CLSID clsid; + TCHAR szFile[OLEUI_CCHPATHMAX]; + BOOL fFileSelected; //Enables Display As Icon for links + BOOL fAsIconNew; + BOOL fAsIconFile; + BOOL fFileDirty; + BOOL fFileValid; + UINT nErrCode; + HGLOBAL hMetaPictFile; + UINT nBrowseHelpID; // Help ID callback for Browse dlg + } INSERTOBJECT, *PINSERTOBJECT, FAR *LPINSERTOBJECT; + + + +//Internal function prototypes +//INSOBJ.C +BOOL CALLBACK EXPORT InsertObjectDialogProc(HWND, UINT, WPARAM, LPARAM); +BOOL FInsertObjectInit(HWND, WPARAM, LPARAM); +UINT UFillClassList(HWND, UINT, LPCLSID, BOOL); +BOOL FToggleObjectSource(HWND, LPINSERTOBJECT, DWORD); +void UpdateClassIcon(HWND, LPINSERTOBJECT, HWND); +void UpdateClassType(HWND, LPINSERTOBJECT, BOOL); +void SetInsertObjectResults(HWND, LPINSERTOBJECT); +BOOL FValidateInsertFile(HWND, BOOL, UINT FAR*); +void InsertObjectCleanup(HWND); + +#endif //_INSOBJ_H_ diff --git a/private/oleutest/letest/ole2ui/links.c b/private/oleutest/letest/ole2ui/links.c new file mode 100644 index 000000000..88c552754 --- /dev/null +++ b/private/oleutest/letest/ole2ui/links.c @@ -0,0 +1,2146 @@ +/* + * links.c + * + * Implements the OleUIEditLinks function which invokes the complete + * Edit Links dialog. + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + +#define STRICT 1 + +#include "ole2ui.h" +#include "common.h" +#include "edlinks.h" +#include "utility.h" +#include +#include +#include + +OLEDBGDATA + +/* +* OleUIEditLinks +* +* Purpose: +* Invokes the standard OLE Edit Links dialog box allowing the user +* to manipulate ole links (delete, update, change source, etc). +* +* Parameters: +* lpEL LPOLEUIEditLinks pointing to the in-out structure +* for this dialog. +* +* Return Value: +* UINT One of the following codes, indicating success or error: +* OLEUI_SUCCESS Success +* OLEUI_ERR_STRUCTSIZE The dwStructSize value is wrong +*/ + +STDAPI_(UINT) OleUIEditLinks(LPOLEUIEDITLINKS lpEL) +{ + UINT uRet; + HGLOBAL hMemDlg=NULL; + + uRet=UStandardValidation((LPOLEUISTANDARD)lpEL, sizeof(OLEUIEDITLINKS) + , &hMemDlg); + + if (OLEUI_SUCCESS!=uRet) + return uRet; + + /* + * PERFORM ANY STRUCTURE-SPECIFIC VALIDATION HERE! + * ON FAILURE: + * { + * if (NULL!=hMemDlg) + * FreeResource(hMemDlg) + * + * return OLEUI_ERR_ + * } + */ + + //Now that we've validated everything, we can invoke the dialog. + uRet=UStandardInvocation(EditLinksDialogProc, (LPOLEUISTANDARD)lpEL, + hMemDlg, MAKEINTRESOURCE(IDD_EDITLINKS)); + + /* + * IF YOU ARE CREATING ANYTHING BASED ON THE RESULTS, DO IT HERE. + */ + + + return uRet; +} + + + +/* +* EditLinksDialogProc +* +* Purpose: +* Implements the OLE Edit Links dialog as invoked through the +* OleUIEditLinks function. +* +* Parameters: +* Standard +* +* Return Value: +* Standard +*/ + +BOOL CALLBACK EXPORT EditLinksDialogProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam) +{ + LPEDITLINKS lpEL = NULL; + BOOL fHook=FALSE; + UINT uRet=0; + HRESULT hErr; + static int nColPos[3]; + + //Declare Win16/Win32 compatible WM_COMMAND parameters. + COMMANDPARAMS(wID, wCode, hWndMsg); + + //This will fail under WM_INITDIALOG, where we allocate it. + lpEL=(LPEDITLINKS)LpvStandardEntry(hDlg, iMsg, wParam, lParam, &uRet); + + //If the hook processed the message, we're done. + if (0!=uRet) + return (BOOL)uRet; + + // Process help message from secondary dialog + if (iMsg == uMsgHelp) { + + PostMessage(lpEL->lpOEL->hWndOwner, uMsgHelp, wParam, lParam); + return FALSE; + + } + + + //Process the temination message + if (iMsg==uMsgEndDialog) { + + //Free any specific allocations before calling StandardCleanup + + StandardCleanup(lpEL, hDlg); + + EndDialog(hDlg, wParam); + return TRUE; + } + + switch (iMsg) { + static int nHeightLine = -1; + static int nMaxCharWidth = -1; + + case WM_INITDIALOG: + { + RECT rc; + int nStart; + + /* calculate the column positions relative to the listbox */ + GetWindowRect(GetDlgItem(hDlg, ID_EL_LINKSLISTBOX), (LPRECT)&rc); + nStart = rc.left; + GetWindowRect(GetDlgItem(hDlg, ID_EL_COL1), (LPRECT)&rc); + nColPos[0] = rc.left - nStart; + GetWindowRect(GetDlgItem(hDlg, ID_EL_COL2), (LPRECT)&rc); + nColPos[1] = rc.left - nStart; + GetWindowRect(GetDlgItem(hDlg, ID_EL_COL3), (LPRECT)&rc); + nColPos[2] = rc.left - nStart; + + return FEditLinksInit(hDlg, wParam, lParam); + } + break; + + case WM_MEASUREITEM: + { + LPMEASUREITEMSTRUCT lpMIS; + + lpMIS = (LPMEASUREITEMSTRUCT)lParam; + + if (nHeightLine == -1) { + HFONT hFont; + HDC hDC; + TEXTMETRIC tm; + + /* Attempt to get font dialog. If that fails, + use system font + */ + + hFont = (HANDLE)(UINT)SendMessage(hDlg, WM_GETFONT, 0, 0L); + + if (hFont == NULL) + hFont = GetStockObject(SYSTEM_FONT); + + hDC = GetDC(hDlg); + hFont = SelectObject(hDC, hFont); + + GetTextMetrics(hDC, &tm); + nHeightLine = tm.tmHeight; + nMaxCharWidth = tm.tmMaxCharWidth; + + ReleaseDC(hDlg, hDC); + } + + lpMIS->itemHeight = nHeightLine; + } + break; + + case WM_DRAWITEM: + { + LPDRAWITEMSTRUCT lpDIS; + COLORREF crText; + LPLINKINFO lpLI; + HBRUSH hbr; + int nOldBkMode; + TCHAR tsz[OLEUI_CCHPATHMAX]; + LPTSTR lpsz; + RECT rcClip; + + lpDIS = (LPDRAWITEMSTRUCT)lParam; + lpLI = (LPLINKINFO)lpDIS->itemData; + + if ((int)lpDIS->itemID < 0) + break; + + if ((ODA_DRAWENTIRE | ODA_SELECT) & lpDIS->itemAction) { + + if (ODS_SELECTED & lpDIS->itemState) { + /*Get proper txt colors */ + crText = SetTextColor(lpDIS->hDC, + GetSysColor(COLOR_HIGHLIGHTTEXT)); + hbr = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT)); + lpLI->fIsSelected = TRUE; + } + else { + hbr = CreateSolidBrush(GetSysColor(COLOR_WINDOW)); + lpLI->fIsSelected = FALSE; + } + + FillRect(lpDIS->hDC, &lpDIS->rcItem, hbr); + DeleteObject(hbr); + + nOldBkMode = SetBkMode(lpDIS->hDC, TRANSPARENT); + + if (lpLI->lpszDisplayName) { + lstrcpy((LPTSTR)tsz, lpLI->lpszDisplayName); + lpsz = ChopText( + lpDIS->hwndItem, + nColPos[1] - nColPos[0] + - (nMaxCharWidth > 0 ? nMaxCharWidth : 5), + tsz + ); + rcClip.left = lpDIS->rcItem.left + nColPos[0]; + rcClip.top = lpDIS->rcItem.top; + rcClip.right = lpDIS->rcItem.left + nColPos[1] + - (nMaxCharWidth > 0 ? nMaxCharWidth : 5); + rcClip.bottom = lpDIS->rcItem.bottom; + ExtTextOut( + lpDIS->hDC, + rcClip.left, + rcClip.top, + ETO_CLIPPED, + (LPRECT)&rcClip, + lpsz, + lstrlen(lpsz), + NULL + ); + } + if (lpLI->lpszShortLinkType) { + rcClip.left = lpDIS->rcItem.left + nColPos[1]; + rcClip.top = lpDIS->rcItem.top; + rcClip.right = lpDIS->rcItem.left + nColPos[2] + - (nMaxCharWidth > 0 ? nMaxCharWidth : 5); + + rcClip.bottom = lpDIS->rcItem.bottom; + ExtTextOut( + lpDIS->hDC, + rcClip.left, + rcClip.top, + ETO_CLIPPED, + (LPRECT)&rcClip, + lpLI->lpszShortLinkType, + lstrlen(lpLI->lpszShortLinkType), + NULL + ); + } + if (lpLI->lpszAMX) { + rcClip.left = lpDIS->rcItem.left + nColPos[2]; + rcClip.top = lpDIS->rcItem.top; + rcClip.right = lpDIS->rcItem.right; + rcClip.bottom = lpDIS->rcItem.bottom; + ExtTextOut( + lpDIS->hDC, + rcClip.left, + rcClip.top, + ETO_CLIPPED, + (LPRECT)&rcClip, + lpLI->lpszAMX, + lstrlen(lpLI->lpszAMX), + NULL + ); + } + + SetBkMode(lpDIS->hDC, nOldBkMode); + + // restore orig colors if we changed them + if (ODS_SELECTED & lpDIS->itemState) + SetTextColor(lpDIS->hDC, crText); + + } + + InitControls(hDlg, lpEL); + + if (ODA_FOCUS & lpDIS->itemAction) + DrawFocusRect(lpDIS->hDC, &lpDIS->rcItem); + + } + return TRUE; + + + case WM_DELETEITEM: + { + UINT idCtl; + LPDELETEITEMSTRUCT lpDIS; + LPLINKINFO lpLI; + + lpDIS = (LPDELETEITEMSTRUCT)lParam; + idCtl = wParam; + lpLI = (LPLINKINFO)lpDIS->itemData; + + if (lpLI->lpszDisplayName) + OleStdFree((LPVOID)lpLI->lpszDisplayName); + if (lpLI->lpszShortLinkType) + OleStdFree((LPVOID)lpLI->lpszShortLinkType); + if (lpLI->lpszFullLinkType) + OleStdFree((LPVOID)lpLI->lpszFullLinkType); + + /* The ChangeSource processing reuses allocated space for + ** links that have been modified. + */ + // Don't free the LINKINFO for the changed links + if (lpLI->fDontFree) + lpLI->fDontFree = FALSE; + else { + if (lpLI->lpszAMX) + OleStdFree((LPVOID)lpLI->lpszAMX); + OleStdFree((LPVOID)lpLI); + } + + return TRUE; + } + + case WM_COMPAREITEM: + { + LPCOMPAREITEMSTRUCT lpCIS = (LPCOMPAREITEMSTRUCT)lParam; + LPLINKINFO lpLI1 = (LPLINKINFO)lpCIS->itemData1; + LPLINKINFO lpLI2 = (LPLINKINFO)lpCIS->itemData2; + + // Sort list entries by DisplayName + return lstrcmp(lpLI1->lpszDisplayName,lpLI2->lpszDisplayName); + } + + case WM_COMMAND: + switch (wID) { + + case ID_EL_CHANGESOURCE: + { + BOOL fRet = FALSE; + + /* This will bring up the file open dlg with one + edit field containing the whole link name. The file part + will (eventually) be highlighted to indicate where the + file part is. We need to hook on OK here to be able to + send the changed string to the Parse function */ + + fRet = Container_ChangeSource(hDlg, lpEL); + if (!fRet) + PopupMessage(hDlg, IDS_LINKS, IDS_FAILED, + MB_ICONEXCLAMATION | MB_OK); + InitControls(hDlg, lpEL); + } + break; + + case ID_EL_AUTOMATIC: + { + /* This is available for single or multi-select. There is + a flag in the structure that is set initially indicating + whether the link is auto or manual so that we need not + query the link each time we want to find out. + + This command will make the link automatic if not already. + It will have no effect on links already set to auto. + */ + // turn the button ON + + CheckDlgButton(hDlg, ID_EL_AUTOMATIC, 1); + CheckDlgButton(hDlg, ID_EL_MANUAL, 0); + + hErr = Container_AutomaticManual(hDlg, TRUE, lpEL); + if (hErr != NOERROR) + PopupMessage(hDlg, IDS_LINKS, IDS_FAILED, + MB_ICONEXCLAMATION | MB_OK); + + InitControls(hDlg, lpEL); + } + break; + + case ID_EL_MANUAL: + { + /* Same rules apply here as they do to auto link. + Additional note - just because something is changed does + not mean that it updates at the moment. It simply + reflects what kind of updating it does while it lives in + the document. + */ + // turn the button ON + + CheckDlgButton(hDlg, ID_EL_MANUAL, 1); + CheckDlgButton(hDlg, ID_EL_AUTOMATIC, 0); + + hErr = Container_AutomaticManual(hDlg, FALSE, lpEL); + if (hErr != NOERROR) + PopupMessage(hDlg, IDS_LINKS, IDS_FAILED, + MB_ICONEXCLAMATION | MB_OK); + + InitControls(hDlg, lpEL); + } + break; + + case ID_EL_CANCELLINK: + { + /* This is Break Link now in the dlg. This sets the + moniker to null, thereby effectively breaking the link. + The object still has its data effective at the time of + breaking, but becomes a static object. + *****It will need to be deleted from the listbox + */ + + CancelLink(hDlg,lpEL); + InitControls(hDlg, lpEL); + } + break; + + case ID_EL_UPDATENOW: + { + /* This forces an immediate update of the selected + links. This will start the server etc, so this is a very + expensive operation. + */ + hErr = Container_UpdateNow(hDlg, lpEL); + InitControls(hDlg, lpEL); + } + break; + + case ID_EL_OPENSOURCE: + { + /* This will only work on single selection. It makes no + sense to open multiple sources at the same time, since + the one opened will try to show itself and become the + primary operating target, so to speak. Button is greyed + if multi select. + + Here we do not add the break because we want to exit the + dlg in this case. + */ + hErr = Container_OpenSource(hDlg, lpEL); + if (hErr != NOERROR) { + InitControls(hDlg, lpEL); + break; // don't close dialog + } + } // fall through + + case ID_EL_CLOSE: + { + /* The user is finished with their editing - they now + return to their container document. + + */ + SendMessage(hDlg, uMsgEndDialog, OLEUI_OK, 0L); + } + break; + + case IDCANCEL: + { + /* This changes to CLOSE after the user does even ONE + thing in the dlg. Nothing can really effectively be undone. + */ + SendMessage(hDlg, uMsgEndDialog, OLEUI_CANCEL, 0L); + } + break; + + case ID_OLEUIHELP: + { + PostMessage(lpEL->lpOEL->hWndOwner, uMsgHelp + , (WPARAM)hDlg, MAKELPARAM(IDD_EDITLINKS, 0)); + break; + } + break; + } + break; + + default: + { + if (lpEL && iMsg == lpEL->nChgSrcHelpID) { + PostMessage(lpEL->lpOEL->hWndOwner, uMsgHelp, + (WPARAM)hDlg, MAKELPARAM(IDD_CHANGESOURCE, 0)); + } + } + break; + } + + return FALSE; +} + + +/* + * FEditLinksInit + * + * Purpose: + * WM_INITIDIALOG handler for the Edit Links dialog box. + * + * + * Parameters: + * hDlg HWND of the dialog + * wParam WPARAM of the message + * lParam LPARAM of the message + * + * Return Value: + * BOOL Value to return for WM_INITDIALOG. + */ + +BOOL FEditLinksInit(HWND hDlg, WPARAM wParam, LPARAM lParam) +{ + LPEDITLINKS lpEL; + LPOLEUIEDITLINKS lpOEL; + HFONT hFont; + BOOL fDlgItem = FALSE; + DWORD dwLink = 0; + ULONG cLinks; + LPOLEUILINKCONTAINER lpOleUILinkCntr; + int n; + HWND hListBox = GetDlgItem(hDlg, ID_EL_LINKSLISTBOX); + + + + //1. Copy the structure at lParam into our instance memory. + lpEL = (LPEDITLINKS)LpvStandardInit(hDlg, sizeof(OLEUIEDITLINKS), TRUE, + &hFont); + + //PvStandardInit send a termination to us already. + if (NULL==lpEL) + return FALSE; + + lpOEL=(LPOLEUIEDITLINKS)lParam; + + lpEL->lpOEL=lpOEL; + + lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer; + + cLinks = LoadLinkLB(hListBox, lpOleUILinkCntr); + if (cLinks < 0) + return FALSE; + + fDlgItem = (BOOL)cLinks; + lpEL->fItemsExist = (BOOL)cLinks; + + + InitControls(hDlg, lpEL); + + //Copy other information from lpOEL that we might modify. + + //2. If we got a font, send it to the necessary controls. + if (NULL != hFont) { + // Do this for as many controls as you need it for. + // SendDlgItemMessage(hDlg, ID_, WM_SETFONT, (WPARAM)hFont, 0L); + } + + + //3. Show or hide the help button + if (!(lpEL->lpOEL->dwFlags & ELF_SHOWHELP)) + StandardShowDlgItem(hDlg, ID_OLEUIHELP, SW_HIDE); + + /* + * PERFORM OTHER INITIALIZATION HERE. ON ANY LoadString + * FAILURE POST OLEUI_MSG_ENDDIALOG WITH OLEUI_ERR_LOADSTRING. + */ + + //4. If requested disable UpdateNow button + if ((lpEL->lpOEL->dwFlags & ELF_DISABLEUPDATENOW)) + StandardShowDlgItem(hDlg, ID_EL_UPDATENOW, SW_HIDE); + + //5. If requested disable OpenSource button + if ((lpEL->lpOEL->dwFlags & ELF_DISABLEOPENSOURCE)) + StandardShowDlgItem(hDlg, ID_EL_OPENSOURCE, SW_HIDE); + + //6. If requested disable UpdateNow button + if ((lpEL->lpOEL->dwFlags & ELF_DISABLECHANGESOURCE)) + StandardShowDlgItem(hDlg, ID_EL_CHANGESOURCE, SW_HIDE); + + //7. If requested disable CancelLink button + if ((lpEL->lpOEL->dwFlags & ELF_DISABLECANCELLINK)) + StandardShowDlgItem(hDlg, ID_EL_CANCELLINK, SW_HIDE); + + //8. Load 'Close' string used to rename Cancel button + n = LoadString(ghInst, IDS_CLOSE, lpEL->szClose, sizeof(lpEL->szClose)/sizeof(TCHAR)); + if (!n) + { + PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_LOADSTRING, 0L); + return FALSE; + } + + if (cLinks > 0) + SetFocus(hListBox); + else + SetFocus(GetDlgItem(hDlg, IDCANCEL)); + + lpEL->nChgSrcHelpID = RegisterWindowMessage(HELPMSGSTRING); + + //n. Call the hook with lCustData in lParam + UStandardHook(lpEL, hDlg, WM_INITDIALOG, wParam, lpOEL->lCustData); + + return FALSE; +} + + + +/* + * ChangeSourceHook + * + * Purpose: + * Hooks the ChangeSource dialog to attempt to validate link source changes + * specified by the user. + * + * Parameters: + * hDlg HWND of the dialog + * uMsg UINT Message + * wParam WPARAM of the message + * lParam LPARAM of the message + * + * Return Value: + * UNIT Zero = Do default processing; + * Non Zero = Don't do default processing. + */ + +UINT CALLBACK EXPORT ChangeSourceHook(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + LPCHANGESOURCEHOOKDATA lpCshData = NULL; + LPLINKINFO lpLI = NULL; + LPEDITLINKS lpEL = NULL; + LPOLEUILINKCONTAINER lpOleUILinkCntr; + HRESULT hErr; + UINT uRet; + ULONG ulChEaten; + HGLOBAL gh; + + //This will fail under WM_INITDIALOG, where we allocate it. + if (NULL!=(gh = GetProp(hDlg, STRUCTUREPROP))) + { + // gh was locked previously, lock and unlock to get lpv + lpCshData=(LPCHANGESOURCEHOOKDATA)GlobalLock(gh); + GlobalUnlock(gh); + if (lpCshData) + { + lpLI = lpCshData->lpOCshData->lpLI; + lpEL = lpCshData->lpOCshData->lpEL; + } + } + + //Process the temination message + if (uMsg==uMsgEndDialog) + { + if (NULL!=(gh = RemoveProp(hDlg, STRUCTUREPROP))) + { + GlobalUnlock(gh); + GlobalFree(gh); + } + return TRUE; + } + + // User pressed the OK button + if (uMsg == uMsgFileOKString) { + lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer; + + /* NOTE: trigger the focus lost of the edit control. This is + ** not necessary if the user click OK with the mouse but is + ** needed when the user just press . If the mouse was + ** used, no extra is done as the MODIFY flag of the edit control + ** has been cleared. + */ + SendMessage(hDlg, WM_COMMAND, edt1, + MAKELPARAM(GetDlgItem(hDlg, edt1), EN_KILLFOCUS)); + if (lpCshData->bItemNameStored) { + lpCshData->nFileLength = lstrlen((LPTSTR)lpCshData->szEdit) - + lstrlen((LPTSTR)lpCshData->szItemName); + } + else { + lpCshData->nFileLength = lstrlen((LPTSTR)lpCshData->szEdit); + } + + // Try to validate link source change + OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::SetLinkSource called\r\n")); + hErr = lpOleUILinkCntr->lpVtbl->SetLinkSource( + lpOleUILinkCntr, + lpLI->dwLink, + (LPTSTR)lpCshData->szEdit, + (ULONG)lpCshData->nFileLength, + &ulChEaten, + TRUE + ); + OLEDBG_END2 + + // Link source change not validated + if (hErr != NOERROR) { + uRet =PopupMessage(hDlg, IDS_CHANGESOURCE, IDS_INVALIDSOURCE, + MB_ICONQUESTION | MB_YESNO); + + if (uRet == IDYES) { + /* User wants to correct invalid link. Set the edit + ** control selection to the invalid part of the contents. + */ + SetFocus(GetDlgItem(hDlg, edt1)); + SendDlgItemMessage(hDlg, edt1, EM_SETSEL, 0, + MAKELPARAM(ulChEaten, -1)); + return 1; // Don't close ChangeSource dialog + } + else { + /* User does not want to correct invalid link. So set + ** the link source but don't validate the link. + */ + OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::SetLinkSource called\r\n")); + hErr = lpOleUILinkCntr->lpVtbl->SetLinkSource( + lpOleUILinkCntr, + lpLI->dwLink, + (LPTSTR)lpCshData->szEdit, + (ULONG)lpCshData->nFileLength, + &ulChEaten, + FALSE + ); + OLEDBG_END2 + lpCshData->fValidLink = FALSE; + } + } + else { // Link source change validated + lpCshData->fValidLink = TRUE; + } + + if (lpCshData->bItemNameStored && lpCshData->bFileNameStored) { + HWND hListBox = GetDlgItem(lpCshData->lpOfn->hwndOwner, ID_EL_LINKSLISTBOX); + + DiffPrefix( + lpLI->lpszDisplayName, + (LPTSTR)lpCshData->szEdit, + (TCHAR FAR* FAR*)&lpCshData->lpszFrom, + (TCHAR FAR* FAR*)&lpCshData->lpszTo + ); + + /* we keep the strings if there is a difference between the + ** lpszFrom and lpszTo strings AND if the change is only + ** in the file portion otherwise free them and other + ** links won't be compared. + */ + if ( (lstrcmp(lpCshData->lpszTo, lpCshData->lpszFrom)==0) + || (lstrlen(lpCshData->lpszTo)>lpCshData->nFileLength)) { + if (lpCshData->lpszFrom) { + OleStdFree(lpCshData->lpszFrom); + lpCshData->lpszFrom = NULL; + } + if (lpCshData->lpszTo) { + OleStdFree(lpCshData->lpszTo); + lpCshData->lpszTo = NULL; + } + } + } + + // Copy OUT results to original structure + lpCshData->lpOCshData->lpszFrom = lpCshData->lpszFrom; + lpCshData->lpOCshData->lpszTo = lpCshData->lpszTo; + lpCshData->lpOCshData->fValidLink = lpCshData->fValidLink; + + SendMessage(hDlg, uMsgEndDialog, 0, 0L); // do cleanup + return 0; // Close ChangeSource dialog + } + + switch (uMsg) { + case WM_INITDIALOG: + { + LPOPENFILENAME lpOfn = (LPOPENFILENAME)lParam; + LPOLEUICHANGESOURCEHOOKDATA lpOCshData = + (LPOLEUICHANGESOURCEHOOKDATA)lpOfn->lCustData; + + gh=GlobalAlloc( + GMEM_MOVEABLE|GMEM_ZEROINIT,sizeof(CHANGESOURCEHOOKDATA)); + if (NULL==gh) + { + // Memory allocation error; fail to bring up dialog + PostMessage(hDlg, uMsgEndDialog, 0, 0L); + return 0; + } + lpCshData = GlobalLock(gh); + SetProp(hDlg, STRUCTUREPROP, gh); + + lpCshData->lpOCshData = lpOCshData; + lpCshData->lpOfn = lpOfn; + lpLI = lpCshData->lpOCshData->lpLI; + + lpCshData->bFileNameStored = TRUE; + lpCshData->bItemNameStored = TRUE; + lpCshData->nFileLength = (int)lpLI->clenFileName; + if (lpLI->lpszDisplayName) { + LSTRCPYN((LPTSTR)lpCshData->szFileName, lpLI->lpszDisplayName, + lpCshData->nFileLength + 1); + lstrcpy((LPTSTR)lpCshData->szEdit, lpLI->lpszDisplayName); + } else { + lpCshData->szFileName[0] = TEXT('\0'); + lpCshData->szEdit[0] = TEXT('\0'); + } + if (lpLI->lpszItemName) + lstrcpy((LPTSTR)lpCshData->szItemName, lpLI->lpszItemName); + else + lpCshData->szItemName[0] = TEXT('\0'); + + return 0; + } + + case WM_COMMAND: + + // User pressed the CANCEL button + if (wParam == IDCANCEL) + { + if (lpCshData->lpszFrom) + { + OleStdFree(lpCshData->lpszFrom); + lpCshData->lpszFrom = NULL; + } + if (lpCshData->lpszTo) + { + OleStdFree(lpCshData->lpszTo); + lpCshData->lpszTo = NULL; + } + + // Copy OUT results to original structure + lpCshData->lpOCshData->lpszFrom = NULL; + lpCshData->lpOCshData->lpszTo = NULL; + lpCshData->lpOCshData->fValidLink = FALSE; + + SendMessage(hDlg, uMsgEndDialog, 0, 0L); // do cleanup + return 0; // Close ChangeSource dialog + } + + if ((wParam == lst1) && + (HIWORD(lParam) == LBN_SELCHANGE)) { + + int nIndex; + HWND hListBox = (HWND)LOWORD(lParam); + static TCHAR szFileNameBuf[OLEUI_CCHPATHMAX]; + static TCHAR szEditBuf[OLEUI_CCHPATHMAX]; + + nIndex = (int)SendMessage(hListBox, LB_GETCURSEL, 0, 0L); + SendMessage(hListBox, LB_GETTEXT, + (WPARAM)nIndex, (LPARAM)(LPTSTR)szFileNameBuf); + + /* need to build the full path filename for the moniker */ +#ifdef WIN32 + CharToOem(szFileNameBuf, szFileNameBuf); +#else + AnsiToOem(szFileNameBuf, szFileNameBuf); +#endif + _fullpath(szEditBuf, szFileNameBuf, sizeof(szEditBuf)); +#ifdef WIN32 + OemToChar(szEditBuf, szEditBuf); +#else + OemToAnsi(szEditBuf, szEditBuf); +#endif + + /* convert filename to lower case as it appears in the + ** listbox + */ +#ifdef WIN32 + CharLower(szEditBuf); +#else + AnsiLower(szEditBuf); +#endif + LSTRCPYN((LPTSTR)lpCshData->szEdit, (LPTSTR)szEditBuf, + sizeof(lpCshData->szEdit) / sizeof(TCHAR)); + LSTRCPYN((LPTSTR)lpCshData->szFileName, + (LPTSTR)lpCshData->szEdit, + sizeof(lpCshData->szFileName) / sizeof(TCHAR) ); + lpCshData->nFileLength = lstrlen((LPTSTR)lpCshData->szEdit); + if (lpCshData->bItemNameStored) + lstrcat((LPTSTR)lpCshData->szEdit, lpCshData->szItemName); + + SetDlgItemText(hDlg, edt1, (LPTSTR)lpCshData->szEdit); + lpCshData->nEditLength = lstrlen((LPTSTR)lpCshData->szEdit); + lpCshData->bFileNameStored = TRUE; + + return 1; + } + + if ((wParam == lst2) && + (HIWORD(lParam) == LBN_SELCHANGE)) { + + if (lpCshData->bItemNameStored) + SetDlgItemText(hDlg, edt1, (LPTSTR)lpCshData->szItemName); + + return 1; + } + + if ((wParam == cmb2) && + (HIWORD(lParam) == CBN_SELCHANGE)) { + + if (lpCshData->bItemNameStored) + SetDlgItemText(hDlg, edt1, (LPTSTR)lpCshData->szItemName); + + return 1; + } + + if (wParam == edt1) { + HWND hEdit = (HWND)LOWORD(lParam); + + switch (HIWORD(lParam)) { + case EN_SETFOCUS: + SendMessage(hEdit, EM_SETSEL, 0, + MAKELPARAM(0, lpCshData->nFileLength)); + return 1; + + case EN_KILLFOCUS: + if (SendMessage(hEdit, EM_GETMODIFY, 0, 0L)) { + TCHAR szTmp[OLEUI_CCHPATHMAX]; + int nItemLength = lstrlen((LPTSTR)lpCshData->szItemName); + + *(LPWORD)lpCshData->szEdit = sizeof(lpCshData->szEdit)/ + sizeof(TCHAR) - 1; + lpCshData->nEditLength = (int)SendMessage(hEdit, + EM_GETLINE, 0, (LPARAM)(LPTSTR)lpCshData->szEdit); + lpCshData->szEdit[lpCshData->nEditLength] = TEXT('\0'); + LSTRCPYN((LPTSTR)szTmp, (LPTSTR)lpCshData->szEdit, + lpCshData->nFileLength + 1); + + if (lpCshData->bFileNameStored && + !lstrcmp((LPTSTR)lpCshData->szFileName, (LPTSTR)szTmp)) { + lstrcpy((LPTSTR)lpCshData->szItemName, + (LPTSTR)lpCshData->szEdit + lpCshData->nFileLength); + lpCshData->bItemNameStored = TRUE; + } + else if (lpCshData->bItemNameStored && + !lstrcmp((LPTSTR)lpCshData->szItemName, + (LPTSTR)lpCshData->szEdit + + lpCshData->nEditLength - + nItemLength)) { + if (lpCshData->nEditLength==nItemLength) { + + lpCshData->bFileNameStored = FALSE; + } else { + LSTRCPYN((LPTSTR)lpCshData->szFileName, + (LPTSTR)lpCshData->szEdit, + lpCshData->nEditLength - + nItemLength+1); + lpCshData->bFileNameStored = TRUE; + } + } + else { + lpCshData->bItemNameStored = FALSE; + lpCshData->bFileNameStored = FALSE; + } + + SendMessage(hEdit, EM_SETMODIFY, FALSE, 0L); + } + return 0; + } + } + return 0; + + default: + return 0; + } +} + + +/* +* ChangeSource +* +* Purpose: +* Displays the standard GetOpenFileName dialog with a customized template and +* hook. +* +* Parameters: +* hWndOwner HWND owning the dialog +* lpszFile LPSTR specifying the initial file. If there is no +* initial file the first character of this string should +* be a null. +* cchFile UINT length of pszFile +* iFilterString UINT index into the stringtable for the filter string. +* lpfnBrowseHook COMMDLGHOOKPROC hook to process link source information when user +* presses OK +* lpCshData LPCHANGESOURCEHOOKDATA custom data that is accessible to the hook +* +* Return Value: +* BOOL TRUE if the user selected a file and pressed OK. +* FALSE otherwise, such as on pressing Cancel. +*/ + +BOOL WINAPI ChangeSource( + HWND hWndOwner, + LPTSTR lpszFile, + UINT cchFile, + UINT iFilterString, + COMMDLGHOOKPROC lpfnBrowseHook, + LPOLEUICHANGESOURCEHOOKDATA lpCshData +) +{ + UINT cch; + TCHAR szFilters[OLEUI_CCHPATHMAX]; + TCHAR szDir[OLEUI_CCHPATHMAX]; + TCHAR szTitle[OLEUI_CCHPATHMAX]; + OPENFILENAME ofn; + BOOL fStatus; + LPTSTR lpszFileBuffer; + + if (NULL==lpszFile || 0==cchFile) + return FALSE; + + lpszFileBuffer = (LPTSTR)OleStdMalloc(cchFile * sizeof(TCHAR)); + if (!lpszFileBuffer) + return FALSE; + + lstrcpy(lpszFileBuffer, lpszFile); + + // Get filters + if (0!=iFilterString) + cch = LoadString(ghInst, iFilterString, (LPTSTR)szFilters, + OLEUI_CCHPATHMAX); + else + { + szFilters[0]=0; + cch=1; + } + if (0==cch) { + fStatus = FALSE; + goto cleanup; + } + + ReplaceCharWithNull(szFilters, szFilters[cch-1]); + + LSTRCPYN((LPTSTR)szDir, lpszFile, OLEUI_CCHPATHMAX); + for (cch = lstrlen((LPTSTR)szDir) - 1; cch >= 0; cch--) + { + if ((szDir[cch]==TEXT('\\')) || (szDir[cch]==TEXT(':')) || (szDir[cch]==TEXT('/'))) + break; + } + if (cch < 0) + cch = 0; + + szDir[cch] = TEXT('\0'); + + LoadString(ghInst, IDS_CHANGESOURCE, (LPTSTR)szTitle, OLEUI_CCHPATHMAX); + _fmemset((LPOPENFILENAME)&ofn, 0, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = hWndOwner; + ofn.lpstrFile = lpszFileBuffer; + ofn.nMaxFile = cchFile; + ofn.lpstrFilter = (LPTSTR)szFilters; + ofn.nFilterIndex = 1; + ofn.lpstrTitle = (LPTSTR)szTitle; + ofn.lpstrInitialDir = (LPTSTR)szDir; + ofn.lpTemplateName = MAKEINTRESOURCE(IDD_FILEOPEN); + ofn.lpfnHook = lpfnBrowseHook; + ofn.hInstance = ghInst; + ofn.lCustData = (LPARAM)lpCshData; + ofn.Flags = OFN_NOVALIDATE | OFN_HIDEREADONLY | + OFN_ENABLETEMPLATE | OFN_ENABLEHOOK; + + // Only show help button if edit links dialog shows it. + if (lpCshData->lpEL->lpOEL->dwFlags & ELF_SHOWHELP) + ofn.Flags |= OFN_SHOWHELP; + + fStatus = GetOpenFileName((LPOPENFILENAME)&ofn); + +cleanup: + OleStdFree((LPVOID)lpszFileBuffer); + return fStatus; + +} + +/* +* Container_ChangeSource +* +* Purpose: +* Tunnel to File Open type dlg and allow user to select new file +* for file based monikers, OR to change the whole moniker to what +* the user types into the editable field. +* +* Parameters: +* hDlg HWND of the dialog +* LPEDITLINKS Pointer to EditLinks structure (contains all nec. +* info) +* +* Return Value: +* BOOL for now, because we are not using any ole functions +* to return an HRESULT. +* HRESULT HRESULT value indicating success or failure of +* changing the moniker value +*/ + +BOOL Container_ChangeSource(HWND hDlg, LPEDITLINKS lpEL) +{ + UINT uRet; + int cSelItems; + int FAR* rgIndex; + int i = 0; + LPLINKINFO lpLI; + HWND hListBox = GetDlgItem(hDlg, ID_EL_LINKSLISTBOX); + LPOLEUILINKCONTAINER lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer; + OLEUICHANGESOURCEHOOKDATA cshData; // Data that needs to be accessed + // by the ChangeSource dialog hook + + cSelItems = GetSelectedItems(hListBox, &rgIndex); + + if (cSelItems < 0) + return FALSE; + + if (!cSelItems) + return TRUE; + + if (!lpEL->fClose) { + SetWindowText(GetDlgItem(hDlg, IDCANCEL), (LPTSTR)lpEL->szClose); + lpEL->fClose = TRUE; + } + + _fmemset((LPOLEUICHANGESOURCEHOOKDATA)&cshData, 0, sizeof(cshData)); + cshData.cbStruct=sizeof(cshData); + cshData.hWndOwner=hDlg; + cshData.lpEL = (LPEDITLINKS)lpEL; + cshData.lpszFrom = NULL; + cshData.lpszTo = NULL; + + for (i = cSelItems-1; i >=0; i--) { + SendMessage(hListBox, LB_GETTEXT, rgIndex[i], + (LPARAM) (LPLINKINFO FAR*) &lpLI); + + uRet = UStandardHook(lpEL, hDlg, uMsgBrowse, + OLEUI_CCHPATHMAX_SIZE, (LONG)(LPTSTR)lpLI->lpszDisplayName); + + if (!uRet) { + cshData.lpLI = lpLI; + /* Bring up the ChangeSource dialog after hooking it so + ** that the user specified link source is verified + ** when OK is pressed. + */ + uRet = (UINT)ChangeSource(hDlg, lpLI->lpszDisplayName, + OLEUI_CCHPATHMAX, IDS_FILTERS, ChangeSourceHook, + &cshData); + } + + /* If Cancel is pressed in any ChangeSource dialog, stop + ** the ChangeSource processing for all links. + */ + if (!uRet) { + if (rgIndex) + OleStdFree(rgIndex); + return TRUE; + } + + UpdateLinkLBItem(hListBox, rgIndex[i], lpEL, TRUE); + + if (cshData.lpszFrom && cshData.lpszTo) { + ChangeAllLinks(hListBox, lpOleUILinkCntr, cshData.lpszFrom, + cshData.lpszTo); + OleStdFree(cshData.lpszFrom); + OleStdFree(cshData.lpszTo); + } + + } // end FOR + + + if (rgIndex) + OleStdFree(rgIndex); + + return TRUE; + +} + + +/* +* Container_AutomaticManual +* +* Purpose: +* To change the selected moniker to manual or automatic update. +* +* Parameters: +* hDlg HWND of the dialog +* FAutoMan Flag indicating AUTO (TRUE/1) or MANUAL(FALSE/0) +* LPEDITLINKS Pointer to EditLinks structure (contains all nec. +* info) +* * this may change - don't know how the linked list +* * of multi-selected items will work. +* Return Value: +* HRESULT HRESULT value indicating success or failure of +* changing the moniker value +*/ + +HRESULT Container_AutomaticManual(HWND hDlg, BOOL fAutoMan, LPEDITLINKS lpEL) +{ + + HRESULT hErr = NOERROR; + int cSelItems; + int FAR* rgIndex; + int i = 0; + LPLINKINFO lpLI; + LPOLEUILINKCONTAINER lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer; + HWND hListBox = GetDlgItem(hDlg, ID_EL_LINKSLISTBOX); + BOOL bUpdate = FALSE; + + OleDbgAssert(lpOleUILinkCntr); + + /* Change so looks at flag in structure. Only update those that + need to be updated. Make sure to change flag if status changes. + */ + + cSelItems = GetSelectedItems(hListBox, &rgIndex); + + if (cSelItems < 0) + return ResultFromScode(E_FAIL); + + if (!cSelItems) + return NOERROR; + + if (!lpEL->fClose) + SetDlgItemText(hDlg, IDCANCEL, (LPTSTR)lpEL->szClose); + + for (i = 0; i < cSelItems; i++) { + SendMessage(hListBox, LB_GETTEXT, (WPARAM)rgIndex[i], + (LPARAM) (LPLINKINFO FAR*) &lpLI); + + if (fAutoMan) { // If switching to AUTOMATIC + if (!lpLI->fIsAuto) { // Only change MANUAL links + OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::SetLinkUpdateOptions called\r\n")); + hErr=lpOleUILinkCntr->lpVtbl->SetLinkUpdateOptions( + lpOleUILinkCntr, + lpLI->dwLink, + OLEUPDATE_ALWAYS + ); + OLEDBG_END2 + + lpLI->fIsAuto=TRUE; + lpLI->fIsMarked = TRUE; + bUpdate = TRUE; + } + } + else { // If switching to MANUAL + if (lpLI->fIsAuto) { // Only do AUTOMATIC Links + OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::SetLinkUpdateOptions called\r\n")); + hErr=lpOleUILinkCntr->lpVtbl->SetLinkUpdateOptions( + lpOleUILinkCntr, + lpLI->dwLink, + OLEUPDATE_ONCALL + ); + OLEDBG_END2 + + lpLI->fIsAuto = FALSE; + lpLI->fIsMarked = TRUE; + bUpdate = TRUE; + } + } + + if (hErr != NOERROR) { + OleDbgOutHResult(TEXT("WARNING: IOleUILinkContainer::SetLinkUpdateOptions returned"),hErr); + break; + } + + } + + if (bUpdate) + RefreshLinkLB(hListBox, lpOleUILinkCntr); + + if (rgIndex) + OleStdFree((LPVOID)rgIndex); + + return hErr; +} + + +HRESULT CancelLink(HWND hDlg, LPEDITLINKS lpEL) +{ + HRESULT hErr; + LPMONIKER lpmk; + int cSelItems; + int FAR* rgIndex; + int i = 0; + LPLINKINFO lpLI; + LPOLEUILINKCONTAINER lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer; + HWND hListBox = GetDlgItem(hDlg, ID_EL_LINKSLISTBOX); + BOOL bUpdate = FALSE; + + OleDbgAssert(lpOleUILinkCntr); + + lpmk = NULL; + + cSelItems = GetSelectedItems(hListBox, &rgIndex); + + if (cSelItems < 0) + return ResultFromScode(E_FAIL); + + if (!cSelItems) + return NOERROR; + + if (!lpEL->fClose) { + SetWindowText(GetDlgItem(hDlg, IDCANCEL), (LPTSTR)lpEL->szClose); + lpEL->fClose = TRUE; + } + + for (i = 0; i < cSelItems; i++) { + SendMessage(hListBox, LB_GETTEXT, (WPARAM)rgIndex[i], + (LPARAM)(LPLINKINFO FAR*) &lpLI); + + OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::CancelLink called\r\n")); + hErr = lpOleUILinkCntr->lpVtbl->CancelLink( + lpOleUILinkCntr, + lpLI->dwLink + ); + OLEDBG_END2 + + if (hErr != NOERROR) { + OleDbgOutHResult(TEXT("WARNING: IOleUILinkContainer::CancelLink returned"),hErr); + lpLI->fIsMarked = TRUE; + bUpdate = TRUE; + } + else + // Delete links that we make null from listbox + SendMessage(hListBox, LB_DELETESTRING, (WPARAM) rgIndex[i], 0L); + + } + + if (bUpdate) + RefreshLinkLB(hListBox, lpOleUILinkCntr); + + if (rgIndex) + OleStdFree((LPVOID)rgIndex); + + return hErr; + +} + + +/* + * Container_UpdateNow + * + * Purpose: + * Immediately force an update for all (manual) links + * + * Parameters: + * hDlg HWND of the dialog + * LPEDITLINKS Pointer to EditLinks structure (contains all nec. info) + * * this may change - don't know how the linked list + * * of multi-selected items will work. + * Return Value: + * HRESULT HRESULT value indicating success or failure of + * changing the moniker value + */ + +HRESULT Container_UpdateNow(HWND hDlg, LPEDITLINKS lpEL) +{ + HRESULT hErr; + LPLINKINFO lpLI; + int cSelItems; + int FAR* rgIndex; + int i = 0; + LPOLEUILINKCONTAINER lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer; + HWND hListBox = GetDlgItem(hDlg, ID_EL_LINKSLISTBOX); + BOOL bUpdate = FALSE; + + OleDbgAssert(lpOleUILinkCntr); + + cSelItems = GetSelectedItems(hListBox, &rgIndex); + + if (cSelItems < 0) + return ResultFromScode(E_FAIL); + + if (!cSelItems) + return NOERROR; + + if (!lpEL->fClose) { + SetWindowText(GetDlgItem(hDlg, IDCANCEL), (LPTSTR)lpEL->szClose); + lpEL->fClose = TRUE; + } + + for (i = 0; i < cSelItems; i++) { + SendMessage(hListBox, LB_GETTEXT, + (WPARAM)rgIndex[i], (LPARAM)(LPLINKINFO FAR*)&lpLI); + + OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::UpdateLink called\r\n")); + hErr = lpOleUILinkCntr->lpVtbl->UpdateLink( + lpOleUILinkCntr, + lpLI->dwLink, + TRUE, + FALSE + ); + OLEDBG_END2 + bUpdate = TRUE; + lpLI->fIsMarked = TRUE; + + if (hErr != NOERROR) { + OleDbgOutHResult(TEXT("WARNING: IOleUILinkContainer::UpdateLink returned"),hErr); + break; + } + + } + + if (bUpdate) + RefreshLinkLB(hListBox, lpOleUILinkCntr); + + if (rgIndex) + OleStdFree((LPVOID)rgIndex); + + return hErr; + +} + +/* + * Container_OpenSource + * + * Purpose: + * Immediately force an update for all (manual) links + * + * Parameters: + * hDlg HWND of the dialog + * LPEDITLINKS Pointer to EditLinks structure (contains all nec. + * info) + * + * Return Value: + * HRESULT HRESULT value indicating success or failure of + * changing the moniker value + */ + +HRESULT Container_OpenSource(HWND hDlg, LPEDITLINKS lpEL) +{ + HRESULT hErr; + int cSelItems; + int FAR* rgIndex; + LPLINKINFO lpLI; + RECT rcPosRect; + LPOLEUILINKCONTAINER lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer; + HWND hListBox = GetDlgItem(hDlg, ID_EL_LINKSLISTBOX); + + OleDbgAssert(lpOleUILinkCntr); + + rcPosRect.top = 0; + rcPosRect.left = 0; + rcPosRect.right = 0; + rcPosRect.bottom = 0; + + cSelItems = GetSelectedItems(hListBox, &rgIndex); + + if (cSelItems < 0) + return ResultFromScode(E_FAIL); + + if (cSelItems != 1) // can't open source for multiple items + return NOERROR; + + if (!lpEL->fClose) { + SetWindowText(GetDlgItem(hDlg, IDCANCEL), (LPTSTR)lpEL->szClose); + lpEL->fClose = TRUE; + } + + SendMessage(hListBox, LB_GETTEXT, (WPARAM)rgIndex[0], + (LPARAM)(LPLINKINFO FAR*)&lpLI); + + OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::OpenLinkSource called\r\n")); + hErr = lpOleUILinkCntr->lpVtbl->OpenLinkSource( + lpOleUILinkCntr, + lpLI->dwLink + ); + OLEDBG_END2 + + UpdateLinkLBItem(hListBox, rgIndex[0], lpEL, TRUE); + if (hErr != NOERROR) + OleDbgOutHResult(TEXT("WARNING: IOleUILinkContainer::OpenLinkSource returned"),hErr); + + if (rgIndex) + OleStdFree((LPVOID)rgIndex); + + return hErr; +} + + + +/* AddLinkLBItem +** ------------- +** +** Add the item pointed to by lpLI to the Link ListBox and return +** the index of it in the ListBox +*/ +int AddLinkLBItem(HWND hListBox, LPOLEUILINKCONTAINER lpOleUILinkCntr, LPLINKINFO lpLI, BOOL fGetSelected) +{ + HRESULT hErr; + DWORD dwUpdateOpt; + int nIndex; + + OleDbgAssert(lpOleUILinkCntr && hListBox && lpLI); + + lpLI->fDontFree = FALSE; + + OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::GetLinkSource called\r\n")); + hErr = lpOleUILinkCntr->lpVtbl->GetLinkSource( + lpOleUILinkCntr, + lpLI->dwLink, + (LPTSTR FAR*)&lpLI->lpszDisplayName, + (ULONG FAR*)&lpLI->clenFileName, + (LPTSTR FAR*)&lpLI->lpszFullLinkType, + (LPTSTR FAR*)&lpLI->lpszShortLinkType, + (BOOL FAR*)&lpLI->fSourceAvailable, + fGetSelected ? (BOOL FAR*)&lpLI->fIsSelected : NULL + ); + OLEDBG_END2 + + if (hErr != NOERROR) { + OleDbgOutHResult(TEXT("WARNING: IOleUILinkContainer::GetLinkSource returned"),hErr); + PopupMessage(hListBox, IDS_LINKS, IDS_ERR_GETLINKSOURCE, + MB_ICONEXCLAMATION | MB_OK); + + goto cleanup; + } + + OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::GetLinkUpdateOptions called\r\n")); + hErr=lpOleUILinkCntr->lpVtbl->GetLinkUpdateOptions( + lpOleUILinkCntr, + lpLI->dwLink, + (LPDWORD)&dwUpdateOpt + ); + OLEDBG_END2 + + + if (hErr != NOERROR) { + OleDbgOutHResult(TEXT("WARNING: IOleUILinkContainer::GetLinkUpdateOptions returned"),hErr); + PopupMessage(hListBox, IDS_LINKS, IDS_ERR_GETLINKUPDATEOPTIONS, + MB_ICONEXCLAMATION | MB_OK); + + goto cleanup; + } + + if (lpLI->fSourceAvailable) { + if (dwUpdateOpt == OLEUPDATE_ALWAYS) { + lpLI->fIsAuto = TRUE; + LoadString(ghInst, IDS_LINK_AUTO, lpLI->lpszAMX, + (int)OleStdGetSize((LPVOID)lpLI->lpszAMX)); + } + else { + lpLI->fIsAuto = FALSE; + LoadString(ghInst, IDS_LINK_MANUAL, lpLI->lpszAMX, + (int)OleStdGetSize((LPVOID)lpLI->lpszAMX)); + } + } + else + LoadString(ghInst, IDS_LINK_UNKNOWN, lpLI->lpszAMX, + (int)OleStdGetSize((LPVOID)lpLI->lpszAMX)); + + BreakString(lpLI); + + nIndex = (int)SendMessage(hListBox, LB_ADDSTRING, (WPARAM)0, + (LPARAM)(DWORD)lpLI); + + if (nIndex == LB_ERR) { + PopupMessage(hListBox, IDS_LINKS, IDS_ERR_ADDSTRING, + MB_ICONEXCLAMATION | MB_OK); + + goto cleanup; + } + + return nIndex; + +cleanup: + if (lpLI->lpszDisplayName) + OleStdFree((LPVOID)lpLI->lpszDisplayName); + + if (lpLI->lpszShortLinkType) + OleStdFree((LPVOID)lpLI->lpszShortLinkType); + + if (lpLI->lpszFullLinkType) + OleStdFree((LPVOID)lpLI->lpszFullLinkType); + + return -1; +} + + +/* BreakString + * ----------- + * + * Purpose: + * Break the lpszDisplayName into various parts + * + * Parameters: + * lpLI pointer to LINKINFO structure + * + * Returns: + * + */ +VOID BreakString(LPLINKINFO lpLI) +{ + LPTSTR lpsz; + + if (!lpLI->clenFileName || + (lstrlen(lpLI->lpszDisplayName)==(int)lpLI->clenFileName)) { + + lpLI->lpszItemName = NULL; + } + else { + lpLI->lpszItemName = lpLI->lpszDisplayName + lpLI->clenFileName; + } + + // search from last character of filename + lpsz = lpLI->lpszDisplayName + lstrlen(lpLI->lpszDisplayName); + while (lpsz > lpLI->lpszDisplayName) { +#ifdef WIN32 + // AnsiPrev is obsolete in Win32 + lpsz = CharPrev(lpLI->lpszDisplayName, lpsz); +#else + lpsz = AnsiPrev(lpLI->lpszDisplayName, lpsz); +#endif + if ((*lpsz == TEXT('\\')) || (*lpsz == TEXT('/')) || (*lpsz == TEXT(':'))) + break; + } + + if (lpsz == lpLI->lpszDisplayName) + lpLI->lpszShortFileName = lpsz; + else +#ifdef WIN32 + // AnsiNext is obsolete in Win32 + lpLI->lpszShortFileName = CharNext(lpsz); +#else + lpLI->lpszShortFileName = AnsiNext(lpsz); +#endif +} + + +/* GetSelectedItems + * ---------------- + * + * Purpose: + * Retrieve the indices of the selected items in the listbox + * Note that *lprgIndex needed to be free after using the function + * + * Parameters: + * hListBox window handle of listbox + * lprgIndex pointer to an integer array to receive the indices + * must be freed afterwards + * + * Returns: + * number of indices retrieved, -1 if error + */ +int GetSelectedItems(HWND hListBox, int FAR* FAR* lprgIndex) +{ + DWORD cSelItems; + DWORD cCheckItems; + + *lprgIndex = NULL; + + cSelItems = SendMessage(hListBox, LB_GETSELCOUNT, 0, 0L); + if (cSelItems < 0) // error + return (int)cSelItems; + + if (!cSelItems) + return 0; + + *lprgIndex = (int FAR*)OleStdMalloc((int)cSelItems * sizeof(int)); + + cCheckItems = SendMessage(hListBox, LB_GETSELITEMS, + (WPARAM) cSelItems, (LPARAM) (int FAR*) *lprgIndex); + + if (cCheckItems == cSelItems) + return (int)cSelItems; + else { + if (*lprgIndex) + OleStdFree((LPVOID)*lprgIndex); + *lprgIndex = NULL; + return 0; + } +} + + +/* InitControls + * ------------ + * + * Purpose: + * Initialize the state of the Auto/Manual button, Link source/type + * static field, etc in the dialogs according to the selection in the + * listbox + * + * Parameters: + * hDlg handle to the dialog window + */ +VOID InitControls(HWND hDlg, LPEDITLINKS lpEL) +{ + int cSelItems; + HWND hListBox; + int i; + int FAR* rgIndex; + LPLINKINFO lpLI; + LPTSTR lpszType = NULL; + LPTSTR lpszSource = NULL; + int cAuto = 0; + int cManual = 0; + BOOL bSameType = TRUE; + BOOL bSameSource = TRUE; + TCHAR tsz[OLEUI_CCHPATHMAX]; + LPTSTR lpsz; + + + hListBox = GetDlgItem(hDlg, ID_EL_LINKSLISTBOX); + + cSelItems = GetSelectedItems(hListBox, &rgIndex); + if (cSelItems < 0) + return; + + EnableWindow(GetDlgItem(hDlg, ID_EL_AUTOMATIC), (BOOL)cSelItems); + EnableWindow(GetDlgItem(hDlg, ID_EL_MANUAL), (BOOL)cSelItems); + if (lpEL && !(lpEL->lpOEL->dwFlags & ELF_DISABLECANCELLINK)) + EnableWindow(GetDlgItem(hDlg, ID_EL_CANCELLINK), (BOOL)cSelItems); + if (lpEL && !(lpEL->lpOEL->dwFlags & ELF_DISABLEOPENSOURCE)) + EnableWindow(GetDlgItem(hDlg, ID_EL_OPENSOURCE), cSelItems == 1); + if (lpEL && !(lpEL->lpOEL->dwFlags & ELF_DISABLECHANGESOURCE)) + EnableWindow(GetDlgItem(hDlg, ID_EL_CHANGESOURCE), cSelItems == 1); + if (lpEL && !(lpEL->lpOEL->dwFlags & ELF_DISABLEUPDATENOW)) + EnableWindow(GetDlgItem(hDlg, ID_EL_UPDATENOW), (BOOL)cSelItems); + + for (i = 0; i < cSelItems; i++) { + SendDlgItemMessage( + hDlg, + ID_EL_LINKSLISTBOX, + LB_GETTEXT, + (WPARAM)rgIndex[i], + (LPARAM)(LPLINKINFO FAR*)&lpLI); + + if (lpszSource && lpLI->lpszDisplayName) { + if (bSameSource && lstrcmp(lpszSource, lpLI->lpszDisplayName)) { + bSameSource = FALSE; + } + } + else + lpszSource = lpLI->lpszDisplayName; + + if (lpszType && lpLI->lpszFullLinkType) { + if (bSameType && lstrcmp(lpszType, lpLI->lpszFullLinkType)) { + bSameType = FALSE; + } + } + else + lpszType = lpLI->lpszFullLinkType; + + if (lpLI->fIsAuto) + cAuto++; + else + cManual++; + } + + CheckDlgButton(hDlg, ID_EL_AUTOMATIC, cAuto && !cManual); + CheckDlgButton(hDlg, ID_EL_MANUAL, !cAuto && cManual); + + /* fill full source in static text box + ** below list + */ + if (!bSameSource || !lpszSource) + lpszSource = szNULL; + lstrcpy((LPTSTR)tsz, lpszSource); + lpsz = ChopText(GetDlgItem(hDlg, ID_EL_LINKSOURCE), 0, tsz); + SetDlgItemText(hDlg, ID_EL_LINKSOURCE, lpsz); + + /* fill full link type name in static + ** "type" text box + */ + if (!bSameType || !lpszType) + lpszType = szNULL; + SetDlgItemText(hDlg, ID_EL_LINKTYPE, lpszType); + + if (rgIndex) + OleStdFree((LPVOID)rgIndex); +} + + +/* UpdateLinkLBItem + * ----------------- + * + * Purpose: + * Update the linkinfo struct in the listbox to reflect the changes + * made by the last operation. It is done simply by removing the item + * from the listbox and add it back. + * + * Parameters: + * hListBox handle of listbox + * nIndex index of listbox item + * lpEL pointer to editlinks structure + * bSelect select the item or not after update + */ +VOID UpdateLinkLBItem(HWND hListBox, int nIndex, LPEDITLINKS lpEL, BOOL bSelect) +{ + LPLINKINFO lpLI; + DWORD dwErr; + LPOLEUILINKCONTAINER lpOleUILinkCntr; + + if (!hListBox || (nIndex < 0) || !lpEL) + return; + + lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer; + + dwErr = SendMessage(hListBox, LB_GETTEXT, nIndex, + (LPARAM)(LPLINKINFO FAR*) &lpLI); + + if ((dwErr == LB_ERR) || !lpLI) + return; + + /* Don't free the data associated with this listbox item + ** because we are going to reuse the allocated space for + ** the modified link. WM_DELETEITEM processing in the + ** dialog checks this flag before deleting data + ** associcated with list item. + */ + lpLI->fDontFree = TRUE; + SendMessage(hListBox, LB_DELETESTRING, nIndex, 0L); + + nIndex = AddLinkLBItem(hListBox, lpOleUILinkCntr, lpLI, FALSE); + if (bSelect) { + SendMessage(hListBox, LB_SETSEL, (WPARAM)TRUE, MAKELPARAM(nIndex, 0)); + SendMessage(hListBox, LB_SETCARETINDEX, (WPARAM)nIndex, MAKELPARAM(TRUE, 0)); + } +} + + + +/* DiffPrefix + * ---------- + * + * Purpose: + * Compare (case-insensitive) two strings and return the prefixes of the + * the strings formed by removing the common suffix string from them. + * Integrity of tokens (directory name, filename and object names) are + * preserved. Note that the prefixes are converted to upper case + * characters. + * + * Parameters: + * lpsz1 string 1 + * lpsz2 string 2 + * lplpszPrefix1 prefix of string 1 + * lplpszPrefix2 prefix of string 2 + * + * Returns: + * + */ +VOID DiffPrefix(LPCTSTR lpsz1, LPCTSTR lpsz2, TCHAR FAR* FAR* lplpszPrefix1, TCHAR FAR* FAR* lplpszPrefix2) +{ + LPTSTR lpstr1; + LPTSTR lpstr2; + + OleDbgAssert(lpsz1 && lpsz2 && *lpsz1 && *lpsz2 && lplpszPrefix1 && + lplpszPrefix2); + + *lplpszPrefix1 = NULL; + *lplpszPrefix2 = NULL; +#ifdef WIN32 + *lplpszPrefix1 = OleStdMalloc((lstrlen(lpsz1)+1) * sizeof(TCHAR)); +#else + *lplpszPrefix1 = OleStdMalloc((lstrlen(lpsz1)+1) * sizeof(BYTE)); +#endif + if (!*lplpszPrefix1) + return; + +#ifdef WIN32 + *lplpszPrefix2 = OleStdMalloc((lstrlen(lpsz2)+1) * sizeof(TCHAR)); +#else + *lplpszPrefix2 = OleStdMalloc((lstrlen(lpsz2)+1) * sizeof(BYTE)); +#endif + if (!*lplpszPrefix2) { + OleStdFree(*lplpszPrefix1); + *lplpszPrefix1 = NULL; + return; + } + + lstrcpy(*lplpszPrefix1, lpsz1); + lstrcpy(*lplpszPrefix2, lpsz2); +// AnsiLower(*lplpszPrefix1); +// AnsiLower(*lplpszPrefix2); + + lpstr1 = *lplpszPrefix1 + lstrlen(*lplpszPrefix1); + lpstr2 = *lplpszPrefix2 + lstrlen(*lplpszPrefix2); + + while ((lpstr1>*lplpszPrefix1) && (lpstr2>*lplpszPrefix2)) { +#ifdef WIN32 + lpstr1 = CharPrev(*lplpszPrefix1, lpstr1); + lpstr2 = CharPrev(*lplpszPrefix2, lpstr2); +#else + lpstr1 = AnsiPrev(*lplpszPrefix1, lpstr1); + lpstr2 = AnsiPrev(*lplpszPrefix2, lpstr2); +#endif + if (*lpstr1 != *lpstr2) { +#ifdef WIN32 + // AnsiNext is obsolete in Win32 + lpstr1 = CharNext(lpstr1); + lpstr2 = CharNext(lpstr2); +#else + lpstr1 = AnsiNext(lpstr1); + lpstr2 = AnsiNext(lpstr2); +#endif + break; + } + } + + for (; *lpstr1 && *lpstr1!=TEXT('\\') && *lpstr1!=TEXT('!'); +#ifdef WIN32 + lpstr1=CharNext(lpstr1)); +#else + lpstr1=AnsiNext(lpstr1)); +#endif + for (; *lpstr2 && *lpstr2!=TEXT('\\') && *lpstr2!=TEXT('!'); +#ifdef WIN32 + lpstr2=CharNext(lpstr2)); +#else + lpstr2=AnsiNext(lpstr2)); +#endif + + *lpstr1 = TEXT('\0'); + *lpstr2 = TEXT('\0'); +} + + +/* PopupMessage + * ------------ + * + * Purpose: + * Popup s messagebox and get some response from the user. It is the same + * as MessageBox() except that the title and message string are loaded + * from the resource file. + * + * Parameters: + * hwndParent parent window of message box + * idTitle id of title string + * idMessage id of message string + * fuStyle style of message box + */ +int PopupMessage(HWND hwndParent, UINT idTitle, UINT idMessage, UINT fuStyle) +{ + TCHAR szTitle[256]; + TCHAR szMsg[256]; + + LoadString(ghInst, idTitle, (LPTSTR)szTitle, sizeof(szTitle)/sizeof(TCHAR)); + LoadString(ghInst, idMessage, (LPTSTR)szMsg, sizeof(szMsg)/sizeof(TCHAR)); + return MessageBox(hwndParent, szMsg, szTitle, fuStyle); +} + + +/* ChangeAllLinks + * -------------- + * + * Purpose: + * Enumerate all the links in the listbox and change those starting + * with lpszFrom to lpszTo. + * + * Parameters: + * hListBox window handle of + * lpOleUILinkCntr pointer to OleUI Link Container + * lpszFrom prefix for matching + * lpszTo prefix to substitution + * + * Returns: + */ +VOID ChangeAllLinks(HWND hListBox, LPOLEUILINKCONTAINER lpOleUILinkCntr, LPTSTR lpszFrom, LPTSTR lpszTo) +{ + int cItems; + int nIndex; + int cFrom; + LPLINKINFO lpLI; + LPTSTR szTmp[OLEUI_CCHPATHMAX]; + BOOL bFound; + + cFrom = lstrlen(lpszFrom); + + cItems = (int)SendMessage(hListBox, LB_GETCOUNT, 0, 0L); + OleDbgAssert(cItems >= 0); + + bFound = FALSE; + + OleDbgPrint(3, TEXT("From : "), lpszFrom, 0); + OleDbgPrint(3, TEXT(""), TEXT("\r\n"), 0); + OleDbgPrint(3, TEXT("To : "), lpszTo, 0); + OleDbgPrint(3, TEXT(""), TEXT("\r\n"), 0); + + for (nIndex=0; nIndexfIsMarked = FALSE; + + /* if the corresponding position for the end of lpszFrom in the + ** display name is not a separator. We stop comparing this + ** link. + */ + if (!*(lpLI->lpszDisplayName + cFrom) || + (*(lpLI->lpszDisplayName + cFrom) == TEXT('\\')) || + (*(lpLI->lpszDisplayName + cFrom) == TEXT('!'))) { + + LSTRCPYN((LPTSTR)szTmp, lpLI->lpszDisplayName, cFrom + 1); + if (!lstrcmp((LPTSTR)szTmp, lpszFrom)) { + HRESULT hErr; + int nFileLength; + ULONG ulDummy; + + if (!bFound) { + TCHAR szTitle[256]; + TCHAR szMsg[256]; + TCHAR szBuf[256]; + int uRet; + + LoadString(ghInst, IDS_CHANGESOURCE, (LPTSTR)szTitle, + sizeof(szTitle)/sizeof(TCHAR)); + LoadString(ghInst, IDS_CHANGEADDITIONALLINKS, + (LPTSTR)szMsg, sizeof(szMsg)/sizeof(TCHAR)); + wsprintf((LPTSTR)szBuf, (LPTSTR)szMsg, lpszFrom); + uRet = MessageBox(hListBox, (LPTSTR)szBuf, (LPTSTR)szTitle, + MB_ICONQUESTION | MB_YESNO); + if (uRet == IDYES) + bFound = TRUE; + else + return; // exit function + } + + lstrcpy((LPTSTR)szTmp, lpszTo); + lstrcat((LPTSTR)szTmp, lpLI->lpszDisplayName + cFrom); + nFileLength = lstrlen((LPTSTR)szTmp) - + (lpLI->lpszItemName ? lstrlen(lpLI->lpszItemName) : 0); + + + hErr = lpOleUILinkCntr->lpVtbl->SetLinkSource( + lpOleUILinkCntr, + lpLI->dwLink, + (LPTSTR)szTmp, + (ULONG)nFileLength, + (ULONG FAR*)&ulDummy, + TRUE + ); + if (hErr != NOERROR) + lpOleUILinkCntr->lpVtbl->SetLinkSource( + lpOleUILinkCntr, + lpLI->dwLink, + (LPTSTR)szTmp, + (ULONG)nFileLength, + (ULONG FAR*)&ulDummy, + FALSE + ); + lpLI->fIsMarked = TRUE; + } + } + } + + /* have to do the refreshing after processing all links, otherwise + ** the item positions will change during the process as the + ** listbox stores items in order + */ + if (bFound) + RefreshLinkLB(hListBox, lpOleUILinkCntr); +} + + + +/* LoadLinkLB + * ---------- + * + * Purpose: + * Enumerate all links from the Link Container and build up the Link + * ListBox + * + * Parameters: + * hListBox window handle of + * lpOleUILinkCntr pointer to OleUI Link Container + * lpszFrom prefix for matching + * lpszTo prefix to substitution + * + * Returns: + * number of link items loaded, -1 if error + */ +int LoadLinkLB(HWND hListBox, LPOLEUILINKCONTAINER lpOleUILinkCntr) +{ + DWORD dwLink = 0; + LPLINKINFO lpLI; + int nIndex; + int cLinks; + + cLinks = 0; + + while ((dwLink = lpOleUILinkCntr->lpVtbl->GetNextLink(lpOleUILinkCntr, + dwLink)) != 0) { + lpLI = (LPLINKINFO)OleStdMalloc(sizeof(LINKINFO)); + if (NULL == lpLI) + return -1; + + lpLI->fIsMarked = FALSE; + lpLI->fIsSelected = FALSE; + lpLI->fDontFree = FALSE; + +#ifdef WIN32 + lpLI->lpszAMX = (LPTSTR)OleStdMalloc((LINKTYPELEN+1)*sizeof(TCHAR)); +#else + lpLI->lpszAMX = (LPTSTR)OleStdMalloc((LINKTYPELEN+1)*sizeof(BYTE)); +#endif + + lpLI->dwLink = dwLink; + cLinks++; + if ((nIndex = AddLinkLBItem(hListBox,lpOleUILinkCntr,lpLI,TRUE)) < 0) + // can't load list box + return -1; + + if (lpLI->fIsSelected) { + SendMessage(hListBox, LB_SETSEL, TRUE, MAKELPARAM(nIndex, 0)); + } + } + if (SendMessage(hListBox,LB_GETSELITEMS,(WPARAM)1,(LPARAM)(int FAR*)&nIndex)) + SendMessage(hListBox, LB_SETCARETINDEX, (WPARAM)nIndex, MAKELPARAM(TRUE, 0)); + + return cLinks; +} + + +/* RefreshLinkLB + * ------------- + * + * Purpose: + * Enumerate all items in the links listbox and update those with + * fIsMarked set. + * Note that this is a time consuming routine as it keeps iterating + * all items in the listbox until all of them are unmarked. + * + * Parameters: + * hListBox window handle of listbox + * lpOleUILinkCntr pointer to OleUI Link Container + * + * Returns: + * + */ +VOID RefreshLinkLB(HWND hListBox, LPOLEUILINKCONTAINER lpOleUILinkCntr) +{ + int cItems; + int nIndex; + LPLINKINFO lpLI; + BOOL bStop; + + OleDbgAssert(hListBox); + + cItems = (int)SendMessage(hListBox, LB_GETCOUNT, 0, 0L); + OleDbgAssert(cItems >= 0); + + do { + bStop = TRUE; + for (nIndex=0; nIndexfIsMarked) { + lpLI->fIsMarked = FALSE; + lpLI->fDontFree = TRUE; + + SendMessage(hListBox, LB_DELETESTRING, nIndex, 0L); + nIndex=AddLinkLBItem(hListBox, lpOleUILinkCntr, lpLI, FALSE); + if (lpLI->fIsSelected) { + SendMessage(hListBox, LB_SETSEL, (WPARAM)TRUE, + MAKELPARAM(nIndex, 0)); + SendMessage(hListBox, LB_SETCARETINDEX, (WPARAM)nIndex, + MAKELPARAM(TRUE, 0)); + } + bStop = FALSE; + break; + } + } + } while (!bStop); +} + + diff --git a/private/oleutest/letest/ole2ui/links.dlg b/private/oleutest/letest/ole2ui/links.dlg new file mode 100644 index 000000000..6bc8d7258 --- /dev/null +++ b/private/oleutest/letest/ole2ui/links.dlg @@ -0,0 +1,35 @@ +// DLGINCLUDE RCDATA DISCARDABLE +// BEGIN +// "OLE2UI.H\0" +// END + +IDD_EDITLINKS DIALOG 9, 25, 320, 158 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Links" +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "&Links:", ID_EL_COL1, 11, 11, 26, 8 + LTEXT "Type", ID_EL_COL2, 137, 12, 20, 8 + LTEXT "Update", ID_EL_COL3, 201, 12, 25, 8 + LISTBOX ID_EL_LINKSLISTBOX, 11, 23, 229, 81, LBS_OWNERDRAWFIXED + | LBS_EXTENDEDSEL | WS_VSCROLL | LBS_USETABSTOPS + | WS_TABSTOP | LBS_SORT | LBS_NOTIFY + DEFPUSHBUTTON "Cancel", IDCANCEL, 249, 11, 66, 14 + PUSHBUTTON "&Update Now", ID_EL_UPDATENOW, 249, 34, 66, 14 + PUSHBUTTON "&Open Source", ID_EL_OPENSOURCE, 249, 54, 66, 14, + WS_GROUP + PUSHBUTTON "&Change Source...", ID_EL_CHANGESOURCE, 249, 73, 66, 14, + WS_GROUP + PUSHBUTTON "&Break Link", ID_EL_CANCELLINK, 249, 96, 66, 14 + PUSHBUTTON "&Help", ID_OLEUIHELP, 249, 136, 66, 14 + CONTROL "&Automatic", ID_EL_AUTOMATIC, "Button", + BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP, 61, 138, 65, + 10 + CONTROL "&Manual", ID_EL_MANUAL, "Button", BS_AUTORADIOBUTTON, + 130, 138, 39, 10 + LTEXT "Source:", 219, 9, 113, 30, 8 + LTEXT "Type:", 220, 9, 125, 20, 8 + LTEXT "Update:", ID_EL_UPDATE, 9, 139, 32, 8 + LTEXT "", ID_EL_LINKSOURCE, 45, 113, 195, 8, SS_NOPREFIX + LTEXT "", ID_EL_LINKTYPE, 45, 125, 195, 8, SS_NOPREFIX +END diff --git a/private/oleutest/letest/ole2ui/makefile b/private/oleutest/letest/ole2ui/makefile new file mode 100644 index 000000000..21eedcbe0 --- /dev/null +++ b/private/oleutest/letest/ole2ui/makefile @@ -0,0 +1,12 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!ifdef NTMAKEENV +all: + echo $(BUILDMSG) +clean: all +!else +!INCLUDE $(NTMAKEENV)\makefile.def +!endif diff --git a/private/oleutest/letest/ole2ui/makefile.32 b/private/oleutest/letest/ole2ui/makefile.32 new file mode 100644 index 000000000..e69bb6ff8 --- /dev/null +++ b/private/oleutest/letest/ole2ui/makefile.32 @@ -0,0 +1,590 @@ +########################################################################## +# +# Makefile for OUTLUI.DLL +# +# Usage: NMAKE (builds DEBUG library) +# or: NMAKE RELEASE=1 (builds RELEASE library -- no debug symbols) +# or: NMAKE clean (erase all compiled files) +# +# Environment variables: +# DEVROOT_DIR= (root dir for sample code development) +# +########################################################################## + +LIBNAME = outlui + +!ifndef DEVROOT_DIR +!error You must define DEVROOT_DIR (ole20 sub-tree) +!endif +!ifndef INCLUDE +!error You must define INCLUDE (non ole20 include files) +!endif +!ifndef LIB +!error You must deinfe LIB (non ole20 libraries) +!endif +!ifndef OLEBUILD +OLEBUILD=NT +!endif + +OLE2_H=$(DEVROOT_DIR)\h +OLE2_LIB=$(DEVROOT_DIR)\lib + +!ifndef SAMPLE_DIR +SAMPLE_DIR = $(DEVROOT_DIR)\samples +!endif +SRC_DIR = $(SAMPLE_DIR)\$(APP) + +MAKEFILE = makefile.32 + +# ============================================================================ +# File: M A K E F I L E +# +# NMAKE description file for the OLE2.0 User Interface DLL +# +# Copyright (C) Microsoft Corporation, 1992-1993. All Rights Reserved. +# Microsoft Confidential. +# ============================================================================ + +# ---------------------------------------------------------------------------- +# U I M A K E . I N I +# ---------------------------------------------------------------------------- + + +!if "$(OLEBUILD)" == "DOS" || "$(OLEBUILD)" == "" +DOS=1 +!endif + +!if "$(OLEBUILD)" == "NT" +NT=1 + +!if "$(MACHINE)" == "i386" || "$(MACHINE)" == "" +MACHINE = i386 +MACHINE_D = _X86_ +MACHINE_CC = cl386 +!endif + +!if "$(MACHINE)" == "MIPS" +MACHINE = mips +MACHINE_D = _MIPS_ +MACHINE_CC = cc +!endif + +!endif + +!include "uimake.ini" + +!ifndef LANG +LANG=USA +!endif + +!ifndef BUILD +BUILD=dll +!endif + +GOAL: MAKEINI + nmake -f $(MAKEFILE) PRELUDE SETFLAGS $(LIBNAME).$(BUILD) + + +MAKEINI: + nmake -f $(MAKEFILE) LIBNAME=$(LIBNAME) LANG=$(LANG) BUILD=$(BUILD) RESOURCE=RESOUCE REL_DIR=$(OLEREL_DIR) DEBUG + + +!if "$(INSTALL_DIR)"=="" +INSTALL_DIR = $(REL_DIR) +!endif + +#use src/tok pairs to build if localized version +!if ("$(LANG)"!="USA") && ("$(LANG)"!="usa") +SRCTOK=1 +!endif + +# ---------------------------------------------------------------------------- +# O B J E C T F I L E L I S T +# ---------------------------------------------------------------------------- + +UI_COBJS = \ + D^\busy.obj\ + D^\common.obj\ + D^\convert.obj\ + D^\dbgutil.obj\ + D^\drawicon.obj\ + D^\hatch.obj\ + D^\icon.obj\ + D^\iconbox.obj\ + D^\insobj.obj\ + D^\links.obj\ + D^\msgfiltr.obj\ + D^\enumfetc.obj\ + D^\objfdbk.obj\ + D^\ole2ui.obj\ + D^\olestd.obj\ + D^\targtdev.obj\ + D^\oleutl.obj\ + D^\pastespl.obj\ + D^\regdb.obj\ + D^\resimage.obj\ + D^\utility.obj\ + +UI_NOPCOBJS = \ + D^\geticon.obj\ + +UI_DLLOBJS = \ + D^\dllfuncs.obj\ + +PRECOMPOBJ=$(O)precomp.obj + +PRECOMP=$(O)precomp.pch + +# ---------------------------------------------------------------------------- +# R E S O U R C E L I S T +# ---------------------------------------------------------------------------- +RES = \ + busy.h \ + common.h \ + convert.h \ + edlinks.h \ + geticon.h \ + icon.h \ + iconbox.h \ + insobj.h \ + msgfiltr.h \ + enumfetc.h \ + ole2ui.h \ + pastespl.h \ + resimage.h \ + $(RESOURCE)\STATIC\default.ico \ + $(RESOURCE)\STATIC\bang.ico \ + $(RESOURCE)\STATIC\egares.bmp \ + $(RESOURCE)\STATIC\hivgares.bmp \ + $(RESOURCE)\STATIC\vgares.bmp \ + $(RESOURCE)\$(LANG)\strings.rc \ + $(RESOURCE)\$(LANG)\busy.dlg \ + $(RESOURCE)\$(LANG)\convert.dlg \ + $(RESOURCE)\$(LANG)\fileopen.dlg \ + $(RESOURCE)\$(LANG)\icon.dlg \ + $(RESOURCE)\$(LANG)\insobj.dlg \ + $(RESOURCE)\$(LANG)\links.dlg \ + $(RESOURCE)\$(LANG)\pastespl.dlg \ + $(RESOURCE)\$(LANG)\prompt.dlg \ + $(RESOURCE)\ole2ui.rcv \ + $(RESOURCE)\$(LANG)\verlocal.h \ + +# ---------------------------------------------------------------------------- +# D E B U G S T A T I C L I B M A K E P A R A M E T E R S +# ---------------------------------------------------------------------------- +DEBUGLIB: + @echo Creating DEBUG LIB <nul] +!error Object subdirectory $(OBJ)\ could not be created +!endif +!if [if not exist $(OBJ)\NOPC\*. md $(OBJ)\NOPC > nul] +!error non-precompiled header object subdirectory $(OBJ)\NOPC\ could not be created +!endif + +#select language for version resource if localized version +!if ("$(LANG)"!="USA") && ("$(LANG)"!="usa") +RFLAGS=$(RFLAGS) -D VER_LOC +!endif + +!if ("$(LIBNAME)"=="PUBOLEUI") +RFLAGS=$(RFLAGS) -D PUBLISHER +!endif + +.SUFFIXES: .c .asm .obj .res .rc .def .bmp .ico .exe .dll .cod .str + +O=.\$(OBJ)^\ + +# ---------------------------------------------------------------------------- +# I N F E R E N C E R U L E S +# ---------------------------------------------------------------------------- +# compile C file without precompiled headers into object directory\NOPC +# dont compile c files etc for lcoalized builds. +!ifndef SRCTOK + +{}.c{$(O)NOPC\}.obj: + @echo °°°°°°°°°°°°°°°°°°°°°°°°° Compiling $(@B).c °°°°°°°°°°°°°°°°°°°°°°°°° +!ifdef DOS + SET CL=$(CFLAGS) + $(CC) -Fo$(O)NOPC\$(@B) $(@B).c +!else + $(CC) $(CFLAGS) -Fo$(O)NOPC\$(@B) $(@B).c +!endif + +# compile C file into object directory +{}.c{$(O)}.obj: + @echo °°°°°°°°°°°°°°°°°°°°°°°°° Compiling $(@B).c °°°°°°°°°°°°°°°°°°°°°°°°° +!ifdef DOS + SET CL=$(CFLAGS) -Yuole2ui.h -Fp$(O)precomp.pch + $(CC) -Fo$(O)$(@B) $(@B).c +!else + $(CC) $(CFLAGS) -Yuole2ui.h -Fp$(O)precomp.pch -Fo$(O)$(@B) $(@B).c +!endif + +!endif +#endif SRCTOK + +{}.rc{$(O)}.res: + @echo ²²²²²²²²²²²²²²²²²²² Resource Compiling $(@B).res ²²²²²²²²²²²²²²²²²²²² + $(RS) -I $(RESOURCE)\$(LANG);$(RESOURCE)\static;$(RESOURCE) -FO $(O)$(@B).res -R $(RFLAGS) $(@B).rc + -del $(LIBNAME).dll + +!ifndef SRCTOK +{}.c.cod: + @echo ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Making $(@B).cod ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ +!ifdef DOS + SET CL=$(CFLAGS) -f -Fc + $(CC) $(@B).c +!else + $(CC) $(CFLAGS) -f- -Fc $(@B).c +!endif +!endif +#endif SRCTOK + + +# rules for creating rc & dlg files for localized verisons from src/tok pairs +!ifdef SRCTOK + +$(RESOURCE)\$(LANG)\busy.dlg : $(RESOURCE)\$(LANG)\busy.tok $(RESOURCE)\src\busy.src + tok -q -f $*.tok $(RESOURCE)\src\$(@B).src > $@ + +$(RESOURCE)\$(LANG)\convert.dlg : $(RESOURCE)\$(LANG)\convert.tok $(RESOURCE)\src\convert.src + tok -q -f $*.tok $(RESOURCE)\src\$(@B).src > $@ + +$(RESOURCE)\$(LANG)\fileopen.dlg : $(RESOURCE)\$(LANG)\fileopen.tok $(RESOURCE)\src\fileopen.src + tok -q -f $*.tok $(RESOURCE)\src\$(@B).src > $@ + +$(RESOURCE)\$(LANG)\icon.dlg : $(RESOURCE)\$(LANG)\icon.tok $(RESOURCE)\src\icon.src + tok -q -f $*.tok $(RESOURCE)\src\$(@B).src > $@ + +$(RESOURCE)\$(LANG)\insobj.dlg : $(RESOURCE)\$(LANG)\insobj.tok $(RESOURCE)\src\insobj.src + tok -q -f $*.tok $(RESOURCE)\src\$(@B).src > $@ + +$(RESOURCE)\$(LANG)\links.dlg : $(RESOURCE)\$(LANG)\links.tok $(RESOURCE)\src\links.src + tok -q -f $*.tok $(RESOURCE)\src\$(@B).src > $@ + +$(RESOURCE)\$(LANG)\pastespl.dlg : $(RESOURCE)\$(LANG)\pastespl.tok $(RESOURCE)\src\pastespl.src + tok -q -f $*.tok $(RESOURCE)\src\$(@B).src > $@ + +$(RESOURCE)\$(LANG)\prompt.dlg : $(RESOURCE)\$(LANG)\prompt.tok $(RESOURCE)\src\prompt.src + tok -q -f $*.tok $(RESOURCE)\src\$(@B).src > $@ + +$(RESOURCE)\$(LANG)\strings.rc : $(RESOURCE)\$(LANG)\strings.tok $(RESOURCE)\src\strings.src + tok -q -f $*.tok $(RESOURCE)\src\$(@B).src > $@ +!endif + +# ---------------------------------------------------------------------------- +# D E P E N D F I L E C R E A T I O N +# ---------------------------------------------------------------------------- +UI_CFILE = $(UI_COBJS:.obj=.c) $(UI_DLLOBJS:.obj=.c) +UI_NOPCFILE = $(UI_NOPCOBJS:.obj=.c) +DEPEND: nul + @echo Making a NEW dependancy file. + mkdep -p $$(O) -s .obj $(UI_CFILE:D^\=) > tmp.tmp + sed "s/:/: $$(PRECOMP)/g" < tmp.tmp > depend + -del tmp.tmp + mkdep -p $$(O)NOPC\ -s .obj $(UI_NOPCFILE:D^\=) >> depend + mkdep -p $$(O) -s .pch precomp.c >> depend + +# ---------------------------------------------------------------------------- +# W E L C O M E B A N N E R +# ---------------------------------------------------------------------------- +PRELUDE: + @echo ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» + @echo º Makefile for UILibrary º + @echo ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ + @echo $(MSG) +!ifndef SRCTOK + set INCLUDE=$(OLEREL_DIR);$(INCLUDE) + set LIB=$(OLEREL_DIR);$(LIB) +!endif + +SETFLAGS: + set INCLUDE=$(INCLUDE);$(OLE2_H) + set LIB=$(LIB);$(OLE2_LIB) + + +# ---------------------------------------------------------------------------- +# G O A L T A R G E T S +# ---------------------------------------------------------------------------- +!include "depend" + +CLEAN: CleanUp GOAL + +CleanUp: MAKEINI + nmake -f $(MAKEFILE) SETFLAGS Delete + +Delete: + -echo y|del .\$(OBJ)\*.* + -del $(LIBNAME).dll + -del $(LIBNAME).lib + +!ifndef SRCTOK + +$(O)precomp.pch: precomp.c +!ifdef DOS + SET CL=$(CFLAGS) -Fp$(O)precomp.pch -Ycole2ui.h + $(CC) -Fo$(O)$(@B) precomp.c +!else + $(CC) $(CFLAGS) -Fp$(O)precomp.pch -Ycole2ui.h -Fo$(O)$(@B) precomp.c +!endif +!endif +#endif SRCTOK + +$(O)ole2ui.res: ole2ui.rc $(RES) + +ole2ui.rc : $(RESOURCE)\$(LANG)\strings.rc + +# +# Build .LIB static library +# + +$(LIBNAME).lib: $(LIBOBJS) $(PRECOMPOBJ) + -del $(O)$(LIBNAME).lib + lib @<< +$(O)$(LIBNAME).lib +y +$(PRECOMPOBJ: = +) $(LIBOBJS: = +) + +<< + copy $(O)$(LIBNAME).lib $(LIBNAME).lib + +# +# Build .DLL dynamic-link library +# + +!if "$(OLEBUILD)" == "NT" +!else +$(O)$(LIBNAME).lib: $(LIBOBJS) $(PRECOMPOBJS) + -del $(O)$(LIBNAME).lib + lib @<< +$(O)$(LIBNAME).lib +y +$(PRECOMPOBJ: = +) $(LIBOBJS: = +) + +<< +!endif + +!if "$(OLEBUILD)" == "NT" + +$(LIBNAME).dll: $(LIBNAME).d32 $(PRECOMPOBJS) $(LIBOBJS) $(DLLOBJS) $(O)ole2ui.res + @echo Linking ... + lib32 -out:$*.lib -def:$(LIBNAME).d32 -machine:$(MACHINE) $(LIBOBJS) $(DLLOBJS) + cvtres -$(MACHINE) $(O)ole2ui.res -o $*.rs + link32 $(LFLAGS) -entry:LibMain@12 @<<$(BUILD_DIR)\ole2util.lnk + $(LIBNAME).exp $(LIBOBJS) $(DLLOBJS) $(PRECOMPOBJ) $(UILIBS) $*.rs -out:$@ -map:$*.map -dll $(UILIBS) +<nul] != 0 +#!if [test -f uimake.ini] != 0 +LIBNAME= +MODEL=M +RESOURCE=RESOURCE +!ifndef REL_DIR +@echo REL_DIR not defined +REL_DIR=c:\ole2samp\release +!endif +!ifndef OLERELDIR +@echo OLEREL_DIR not defined +OLEREL_DIR=c:\ole2samp\release +!endif +GOAL: DEBUG +!else +!include "uimake.ini" +GOAL: PRELUDE $(LIBNAME).$(BUILD) +!endif + +!if "$(INSTALL_DIR)"=="" +INSTALL_DIR = $(REL_DIR) +!endif + +#use src/tok pairs to build if localized version +!if ("$(LANG)"!="USA") && ("$(LANG)"!="usa") +SRCTOK=1 +!endif +# ---------------------------------------------------------------------------- +# O B J E C T F I L E L I S T +# ---------------------------------------------------------------------------- + +UI_COBJS = \ + D^\ole2ui.obj\ + D^\busy.obj\ + D^\common.obj\ + D^\convert.obj\ + D^\dbgutil.obj\ + D^\drawicon.obj\ + D^\hatch.obj\ + D^\icon.obj\ + D^\iconbox.obj\ + D^\insobj.obj\ + D^\links.obj\ + D^\msgfiltr.obj\ + D^\enumfetc.obj\ + D^\enumstat.obj\ + D^\objfdbk.obj\ + D^\olestd.obj\ + D^\targtdev.obj\ + D^\oleutl.obj\ + D^\pastespl.obj\ + D^\regdb.obj\ + D^\resimage.obj\ + D^\utility.obj\ + +UI_NOPCOBJS = \ + D^\geticon.obj\ + D^\dballoc.obj\ + D^\suminfo.obj\ + D^\stdpal.obj\ + +UI_DLLOBJS = \ + D^\dllfuncs.obj\ + +PRECOMPOBJ= $(O)precomp.obj + +PRECOMP=$(O)precomp.pch + +# ---------------------------------------------------------------------------- +# R E S O U R C E L I S T +# ---------------------------------------------------------------------------- +RES = \ + busy.h \ + common.h \ + convert.h \ + edlinks.h \ + geticon.h \ + icon.h \ + iconbox.h \ + insobj.h \ + msgfiltr.h \ + enumfetc.h \ + ole2ui.h \ + pastespl.h \ + resimage.h \ + dballoc.h \ + suminfo.h \ + stdpal.h \ + $(RESOURCE)\STATIC\default.ico \ + $(RESOURCE)\STATIC\bang.ico \ + $(RESOURCE)\STATIC\egares.bmp \ + $(RESOURCE)\STATIC\hivgares.bmp \ + $(RESOURCE)\STATIC\vgares.bmp \ + $(RESOURCE)\$(LANG)\strings.rc \ + $(RESOURCE)\$(LANG)\busy.dlg \ + $(RESOURCE)\$(LANG)\convert.dlg \ + $(RESOURCE)\$(LANG)\fileopen.dlg \ + $(RESOURCE)\$(LANG)\icon.dlg \ + $(RESOURCE)\$(LANG)\insobj.dlg \ + $(RESOURCE)\$(LANG)\links.dlg \ + $(RESOURCE)\$(LANG)\pastespl.dlg \ + $(RESOURCE)\$(LANG)\prompt.dlg \ + $(RESOURCE)\ole2ui.rcv \ + $(RESOURCE)\$(LANG)\verlocal.h \ + +# ---------------------------------------------------------------------------- +# D E B U G S T A T I C L I B M A K E P A R A M E T E R S +# ---------------------------------------------------------------------------- +DEBUGLIB: DbgUI + +DbgUI: + @echo Creating DEBUG LIB <nul] +!error Object subdirectory $(OBJ)\ could not be created +!endif +!if [if not exist $(OBJ)\NOPC\*. md $(OBJ)\NOPC > nul] +!error non-precompiled header object subdirectory $(OBJ)\NOPC\ could not be created +!endif + +#select language for version resource if localized version +!if ("$(LANG)"!="USA") && ("$(LANG)"!="usa") +RFLAGS=$(RFLAGS) -D VER_LOC +!endif + +.SUFFIXES: .c .asm .obj .res .rc .def .bmp .ico .exe .dll .cod .str + +O=.\$(OBJ)^\ + +# ---------------------------------------------------------------------------- +# I N F E R E N C E R U L E S +# ---------------------------------------------------------------------------- +!ifndef SRCTOK + +# compile C file without precompiled headers into object directory\NOPC +# dont compile c files etc for lcoalized builds. +{}.c{$(O)NOPC\}.obj: + @echo °°°°°°°°°°°°°°°°°°°°°°°°° Compiling $(@B).c °°°°°°°°°°°°°°°°°°°°°°°°° +!ifdef DOS + SET CL=$(CFLAGS) + $(CC) -Fo$(O)NOPC\$(@B) $(@B).c +!else +!undef _FILE_ + $(CC) $(CFLAGS) -D_FILE_=\"$(*B).c\" -Fo$(O)NOPC\$(@B) $(@B).c +!endif + +# compile C file into object directory +{}.c{$(O)}.obj: + @echo °°°°°°°°°°°°°°°°°°°°°°°°° Compiling $(@B).c °°°°°°°°°°°°°°°°°°°°°°°°° +!ifdef DOS + SET CL=$(CFLAGS) -Yuole2ui.h -Fp$(O)precomp.pch + $(CC) -Fo$(O)$(@B) $(@B).c +!else +!undef _FILE_ +# $(CC) $(CFLAGS) -Yuole2ui.h -Fp$(O)precomp.pch -D_FILE_=\"$(*B).c\" -Fo$(O)$(@B) $(@B).c + $(CC) $(CFLAGS) -D_FILE_=\"$(*B).c\" -Fo$(O)$(@B) $(@B).c +!endif + +# compile CPP file without precompiled headers into object directory\NOPC +# dont compile cpp files etc for lcoalized builds. +{}.cpp{$(O)NOPC\}.obj: + @echo °°°°°°°°°°°°°°°°°°°°°°°°° Compiling $(@B).cpp °°°°°°°°°°°°°°°°°°°°°°°°° +!ifdef DOS + SET CL=$(CFLAGS) + $(CC) -Fo$(O)NOPC\$(@B) $(@B).cpp +!else +!undef _FILE_ + $(CC) $(CFLAGS) -D_FILE_=\"$(*B).cpp\" -Fo$(O)NOPC\$(@B) $(@B).cpp +!endif + +# compile CPP file into object directory +{}.cpp{$(O)}.obj: + @echo °°°°°°°°°°°°°°°°°°°°°°°°° Compiling $(@B).cpp °°°°°°°°°°°°°°°°°°°°°°°°° +!ifdef DOS + SET CL=$(CFLAGS) -Yuole2ui.h -Fp$(O)precomp.pch + $(CC) -Fo$(O)$(@B) $(@B).cpp +!else +!undef _FILE_ +# $(CC) $(CFLAGS) -Yuole2ui.h -Fp$(O)precomp.pch -D_FILE_=\"$(*B).cpp\" -Fo$(O)$(@B) $(@B).cpp + $(CC) $(CFLAGS) -D_FILE_=\"$(*B).cpp\" -Fo$(O)$(@B) $(@B).cpp +!endif + +!endif +#endif SRCTOK + +{}.rc{$(O)}.res: + @echo ²²²²²²²²²²²²²²²²²²² Resource Compiling $(@B).res ²²²²²²²²²²²²²²²²²²²² + $(RS) -I $(RESOURCE)\$(LANG);$(RESOURCE)\static;$(RESOURCE) -FO $(O)$(@B).res -DWIN32 -DUNICODE -R $(RFLAGS) $(@B).rc + -del $(LIBNAME).dll + +!ifndef SRCTOK +{}.c.cod: + @echo ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Making $(@B).cod ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ +!ifdef DOS + SET CL=$(CFLAGS) -f -Fc + $(CC) $(@B).c +!else +!undef _FILE_ + $(CC) $(CFLAGS) -f- -Fc -D_FILE_=\"$(*B).c\" $(@B).c +!endif +!endif + + +# rules for creating rc & dlg files for localized verisons from src/tok pairs +!ifdef SRCTOK + +$(RESOURCE)\$(LANG)\busy.dlg : $(RESOURCE)\$(LANG)\busy.tok $(RESOURCE)\src\busy.src + tok -q -f $*.tok $(RESOURCE)\src\$(@B).src > $@ + +$(RESOURCE)\$(LANG)\convert.dlg : $(RESOURCE)\$(LANG)\convert.tok $(RESOURCE)\src\convert.src + tok -q -f $*.tok $(RESOURCE)\src\$(@B).src > $@ + +$(RESOURCE)\$(LANG)\fileopen.dlg : $(RESOURCE)\$(LANG)\fileopen.tok $(RESOURCE)\src\fileopen.src + tok -q -f $*.tok $(RESOURCE)\src\$(@B).src > $@ + +$(RESOURCE)\$(LANG)\icon.dlg : $(RESOURCE)\$(LANG)\icon.tok $(RESOURCE)\src\icon.src + tok -q -f $*.tok $(RESOURCE)\src\$(@B).src > $@ + +$(RESOURCE)\$(LANG)\insobj.dlg : $(RESOURCE)\$(LANG)\insobj.tok $(RESOURCE)\src\insobj.src + tok -q -f $*.tok $(RESOURCE)\src\$(@B).src > $@ + +$(RESOURCE)\$(LANG)\links.dlg : $(RESOURCE)\$(LANG)\links.tok $(RESOURCE)\src\links.src + tok -q -f $*.tok $(RESOURCE)\src\$(@B).src > $@ + +$(RESOURCE)\$(LANG)\pastespl.dlg : $(RESOURCE)\$(LANG)\pastespl.tok $(RESOURCE)\src\pastespl.src + tok -q -f $*.tok $(RESOURCE)\src\$(@B).src > $@ + +$(RESOURCE)\$(LANG)\prompt.dlg : $(RESOURCE)\$(LANG)\prompt.tok $(RESOURCE)\src\prompt.src + tok -q -f $*.tok $(RESOURCE)\src\$(@B).src > $@ + +$(RESOURCE)\$(LANG)\strings.rc : $(RESOURCE)\$(LANG)\strings.tok $(RESOURCE)\src\strings.src + tok -q -f $*.tok $(RESOURCE)\src\$(@B).src > $@ +!endif + +# ---------------------------------------------------------------------------- +# D E P E N D F I L E C R E A T I O N +# ---------------------------------------------------------------------------- +UI_CFILE = $(UI_COBJS:.obj=.c) $(UI_DLLOBJS:.obj=.c) +UI_NOPCFILE = $(UI_NOPCOBJS:.obj=.c) +DEPEND: nul + @echo Making a NEW dependancy file. + mkdep -p $$(O) -s .obj $(UI_CFILE:D^\=) > tmp.tmp + sed "s/:/: $$(PRECOMP)/g" < tmp.tmp > depend + -del tmp.tmp + mkdep -p $$(O)NOPC\ -s .obj $(UI_NOPCFILE:D^\=) >> depend + mkdep -p $$(O) -s .pch precomp.c >> depend + +# ---------------------------------------------------------------------------- +# W E L C O M E B A N N E R +# ---------------------------------------------------------------------------- +PRELUDE: + @echo ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» + @echo º Makefile for UILibrary º + @echo ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ + @echo $(MSG) +!ifndef SRCTOK + set INCLUDE=$(OLEREL_DIR);$(INCLUDE) + set LIB=$(OLEREL_DIR);$(LIB) +!endif + + +# ---------------------------------------------------------------------------- +# G O A L T A R G E T S +# ---------------------------------------------------------------------------- +!include "depend" + +CLEAN: CleanUp GOAL +CleanUp: + -echo y|del .\$(OBJ)\*.* + -del $(LIBNAME).dll + -del $(LIBNAME).lib + +!ifndef SRCTOK + +$(O)precomp.pch: precomp.c +!ifdef DOS + SET CL=$(CFLAGS) -Fp$(O)precomp.pch -Ycole2ui.h + $(CC) -Fo$(O)$(@B) precomp.c +!else +!undef _FILE_ + @echo Precompiling Header Files.... + $(CC) $(CFLAGS) -Fp$(O)precomp.pch -Ycole2ui.h -D_FILE_=\"precomp.c\" -Fo$(O)$(@B) precomp.c +!endif +!endif + +$(O)ole2ui.res: ole2ui.rc $(RES) + +ole2ui.rc : $(RESOURCE)\$(LANG)\strings.rc + +# +# Build .LIB static library +# + +$(LIBNAME).lib: $(LIBOBJS) $(PRECOMPOBJ) + -del $(O)$(LIBNAME).lib + lib @<< +$(O)$(LIBNAME).lib +y +$(PRECOMPOBJ: = +) $(LIBOBJS: = +) + +<< + copy $(O)$(LIBNAME).lib $(LIBNAME).lib + +# +# Build .DLL dynamic-link library +# + +# HACK! +# XXXXX +# after echo LIBRARY $(LIBNAME) INITINSTANCE +$(O)$(LIBNAME).exe: $(LIBOBJS) $(PRECOMPOBJ) $(DLLOBJS) $(O)ole2ui.res defoleui.def + @echo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄį Linking UILibrary ®ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + -del $(LIBNAME).def + @echo Creating <<$(LIBNAME).def +LIBRARY ole2ui +DESCRIPTION 'OLE 2.0 UI Support Library.' +<> $(LIBNAME).def + $(LK) @<< +$(LFLAGS) +$(LIBOBJS: = ^ +) +$(DLLOBJS: = ^ +) +$(O)$(LIBNAME).res +$(UILIBS) +/DEF:$(LIBNAME).def +<nul] +!error Object subdirectory $(OBJ)\ could not be created +!endif +!if [if not exist $(OBJ)\NOPC\*. md $(OBJ)\NOPC > nul] +!error non-precompiled header object subdirectory $(OBJ)\NOPC\ could not be created +!endif + +# ---------------------------------------------------------------------------- +# I N F E R E N C E R U L E S +# ---------------------------------------------------------------------------- + +# compile C file without precompiled headers into object directory\NOPC +# dont compile c files etc for lcoalized builds. +{}.c{$(O)NOPC\}.obj: + @echo Are you compiling with OLE 2.01 ?????? + @echo °°°°°°°°°°°°°°°°°°°°°°°°° Compiling $(@B).c °°°°°°°°°°°°°°°°°°°°°°°°° +!ifdef DOS + SET CL=$(CFLAGS) + $(CC) -Fo$(O)NOPC\$(@B) $(@B).c +!else + $(CC) $(CFLAGS) -D_FILE_=\"$(*B).c\" -Fo$(O)NOPC\$(@B) $(@B).c +!endif + +# compile C file into object directory +{}.c{$(O)}.obj: + @echo °°°°°°°°°°°°°°°°°°°°°°°°° Compiling $(@B).c °°°°°°°°°°°°°°°°°°°°°°°°° +!ifdef DOS + SET CL=$(CFLAGS) -Yuole2ui.h -Fp$(O)precomp.pch + $(CC) -Fo$(O)$(@B) $(@B).c +!else + $(CC) $(CFLAGS) -Yuole2ui.h -Fp$(O)precomp.pch -D_FILE_=\"$(*B).c\" -Fo$(O)$(@B) $(@B).c +!endif + +# compile CPP file without precompiled headers into object directory\NOPC +# dont compile cpp files etc for lcoalized builds. +{}.cpp{$(O)NOPC\}.obj: + @echo °°°°°°°°°°°°°°°°°°°°°°°°° Compiling $(@B).cpp °°°°°°°°°°°°°°°°°°°°°°°°° +!ifdef DOS + SET CL=$(CFLAGS) + $(CC) -Fo$(O)NOPC\$(@B) $(@B).cpp +!else + $(CC) $(CFLAGS) -D_FILE_=\"$(*B).cpp\" -Fo$(O)NOPC\$(@B) $(@B).cpp +!endif + +# compile CPP file into object directory +{}.cpp{$(O)}.obj: + @echo °°°°°°°°°°°°°°°°°°°°°°°°° Compiling $(@B).cpp °°°°°°°°°°°°°°°°°°°°°°°°° +!ifdef DOS + SET CL=$(CFLAGS) -Yuole2ui.h -Fp$(O)precomp.pch + $(CC) -Fo$(O)$(@B) $(@B).cpp +!else + $(CC) $(CFLAGS) -Yuole2ui.h -Fp$(O)precomp.pch -D_FILE_=\"$(*B).cpp\" -Fo$(O)$(@B) $(@B).cpp +!endif + + +# ---------------------------------------------------------------------------- +# D E P E N D F I L E C R E A T I O N +# ---------------------------------------------------------------------------- +UI_CFILE = $(UI_COBJS:.obj=.c) $(UI_DLLOBJS:.obj=.c) +UI_NOPCFILE = $(UI_NOPCOBJS:.obj=.c) +DEPEND: nul + @echo Making a NEW dependancy file. + mkdep -p $$(O) -s .obj $(UI_CFILE:D^\=) > tmp.tmp + sed "s/:/: $$(PRECOMP)/g" < tmp.tmp > depend + -del tmp.tmp + mkdep -p $$(O)NOPC\ -s .obj $(UI_NOPCFILE:D^\=) >> depend + mkdep -p $$(O) -s .pch precomp.c >> depend + +# ---------------------------------------------------------------------------- +# W E L C O M E B A N N E R +# ---------------------------------------------------------------------------- +PRELUDE: + @echo ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» + @echo º Makefile for UILibrary º + @echo ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ + @echo $(MSG) +!ifndef SRCTOK + set INCLUDE=$(OLEINC_DIR);$(INCLUDE) + set LIB=$(OLELIB_DIR);$(LIB) +!endif + + +# ---------------------------------------------------------------------------- +# G O A L T A R G E T S +# ---------------------------------------------------------------------------- +!include "depend" + +CLEAN: CleanUp +CleanUp: + -echo y|del .\$(OBJ)\*.* + -echo y|del .\$(OBJ)\NOPC\*.* + -del $(LIBNAME).lib + +$(O)precomp.pch: precomp.c +!ifdef DOS + SET CL=$(CFLAGS) -Fp$(O)precomp.pch -Ycole2ui.h + $(CC) -Fo$(O)$(@B) precomp.c +!else + $(CC) $(CFLAGS) -Fp$(O)precomp.pch -Ycole2ui.h -D_FILE_=\"precomp.c\" -Fo$(O)$(@B) precomp.c +!endif + +# +# Build .LIB static library +# + +$(LIBNAME).lib: $(LIBOBJS) $(PRECOMPOBJ) + -del $(O)$(LIBNAME).lib +!ifdef WIN16 + lib @<< +$(O)$(LIBNAME).lib +y +$(PRECOMPOBJ: = +) $(LIBOBJS: = +) + +<< +!else + $(LINK) @<< +/OUT:$(O)$(LIBNAME).lib +/MACHINE:i386 +$(PRECOMPOBJ: = ) $(LIBOBJS: = ) $(UILIBS) + +<< +!endif + copy $(O)$(LIBNAME).lib $(LIBNAME).lib + + +# install built library and public header files to release directories +install: + copy $(LIBNAME).lib $(SAMPLIB_DIR) + copy ole2ui.h $(SAMPINC_DIR) + copy olestd.h $(SAMPINC_DIR) + copy msgfiltr.h $(SAMPINC_DIR) + copy enumfetc.h $(SAMPINC_DIR) + +# EOF ======================================================================== + \ No newline at end of file diff --git a/private/oleutest/letest/ole2ui/msgfiltr.c b/private/oleutest/letest/ole2ui/msgfiltr.c new file mode 100644 index 000000000..562dfb802 --- /dev/null +++ b/private/oleutest/letest/ole2ui/msgfiltr.c @@ -0,0 +1,809 @@ +/* + * MSGFILTR.C + * + * This file contains a standard implementation of IMessageFilter + * interface. + * This file is part of the OLE 2.0 User Interface support library. + * + * (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved + * + */ + + +#define STRICT 1 +#include "ole2ui.h" +#include "msgfiltr.h" + +OLEDBGDATA + + +typedef struct tagOLESTDMESSAGEFILTER { + IMessageFilterVtbl FAR* m_lpVtbl; + UINT m_cRef; + HWND m_hWndParent; + DWORD m_dwInComingCallStatus; // Status to return from + // HandleIncomingCall + HANDLEINCOMINGCALLBACKPROC m_lpfnHandleInComingCallback; + // Callback function + // to selectively handle + // interface method calls + BOOL m_fEnableBusyDialog; // enable RetryRejected + // Call dialog + BOOL m_fEnableNotRespondingDialog; // enable + // MessagePending dialog + MSGPENDINGPROC m_lpfnMessagePendingCallback; // MessagePending + // Callback function + LPFNOLEUIHOOK m_lpfnBusyDialogHookCallback; // Busy dialog hook + LPTSTR m_lpszAppName; // Name of application + // installing filter + HWND m_hWndBusyDialog; // HWND of busy dialog. Used + // to tear down dialog. + BOOL m_bUnblocking; + + }OLESTDMESSAGEFILTER, FAR* LPOLESTDMESSAGEFILTER; + +/* interface IMessageFilter implementation */ +STDMETHODIMP OleStdMsgFilter_QueryInterface( + LPMESSAGEFILTER lpThis, REFIID riid, LPVOID FAR* ppvObj); +STDMETHODIMP_(ULONG) OleStdMsgFilter_AddRef(LPMESSAGEFILTER lpThis); +STDMETHODIMP_(ULONG) OleStdMsgFilter_Release(LPMESSAGEFILTER lpThis); +STDMETHODIMP_(DWORD) OleStdMsgFilter_HandleInComingCall ( + LPMESSAGEFILTER lpThis, + DWORD dwCallType, + HTASK htaskCaller, + DWORD dwTickCount, +#ifdef WIN32 + LPINTERFACEINFO dwReserved +#else + DWORD dwReserved +#endif +); +STDMETHODIMP_(DWORD) OleStdMsgFilter_RetryRejectedCall ( + LPMESSAGEFILTER lpThis, + HTASK htaskCallee, + DWORD dwTickCount, + DWORD dwRejectType +); +STDMETHODIMP_(DWORD) OleStdMsgFilter_MessagePending ( + LPMESSAGEFILTER lpThis, + HTASK htaskCallee, + DWORD dwTickCount, + DWORD dwPendingType +); + + +static IMessageFilterVtbl g_OleStdMessageFilterVtbl = { + OleStdMsgFilter_QueryInterface, + OleStdMsgFilter_AddRef, + OleStdMsgFilter_Release, + OleStdMsgFilter_HandleInComingCall, + OleStdMsgFilter_RetryRejectedCall, + OleStdMsgFilter_MessagePending +}; + + +/* GetTopWindowInWindowsTask +** ------------------------- +** Get the top most window that has focus in the given task to be +** used as the parent for the busy dialog. we do this to handle the +** case where a dialog window is currently up when we need to give +** the busy dialog. if we use the current assigned parent window +** (which typically will be the frame window of the app), then the +** busy dialog will not be modal to the current active dialog +** window. +*/ +static HWND GetTopWindowInWindowsTask(HWND hwnd) +{ + HWND hwndActive = GetActiveWindow(); + if (!hwndActive) + return hwnd; + + if (GetWindowTask(hwnd) == GetWindowTask(hwndActive)) + return hwndActive; + else + return hwnd; +} + +STDAPI_(LPMESSAGEFILTER) OleStdMsgFilter_Create( + HWND hWndParent, + LPTSTR szAppName, + MSGPENDINGPROC lpfnCallback, + LPFNOLEUIHOOK lpfnOleUIHook // Busy dialog hook callback +) +{ + LPOLESTDMESSAGEFILTER lpStdMsgFilter; + LPMALLOC lpMalloc; + + if (CoGetMalloc(MEMCTX_TASK, (LPMALLOC FAR*)&lpMalloc) != NOERROR) + return NULL; + + lpStdMsgFilter = (LPOLESTDMESSAGEFILTER)lpMalloc->lpVtbl->Alloc( + lpMalloc, (sizeof(OLESTDMESSAGEFILTER))); + lpMalloc->lpVtbl->Release(lpMalloc); + if (! lpStdMsgFilter) return NULL; + + lpStdMsgFilter->m_lpVtbl = &g_OleStdMessageFilterVtbl; + lpStdMsgFilter->m_cRef = 1; + lpStdMsgFilter->m_hWndParent = hWndParent; + lpStdMsgFilter->m_dwInComingCallStatus = SERVERCALL_ISHANDLED; + lpStdMsgFilter->m_lpfnHandleInComingCallback = NULL; + lpStdMsgFilter->m_fEnableBusyDialog = TRUE; + lpStdMsgFilter->m_fEnableNotRespondingDialog = TRUE; + lpStdMsgFilter->m_lpszAppName = szAppName; + lpStdMsgFilter->m_lpfnMessagePendingCallback = lpfnCallback; + lpStdMsgFilter->m_lpfnBusyDialogHookCallback = lpfnOleUIHook; + lpStdMsgFilter->m_hWndBusyDialog = NULL; + lpStdMsgFilter->m_bUnblocking = FALSE; + + return (LPMESSAGEFILTER)lpStdMsgFilter; +} + + +/* OleStdMsgFilter_SetInComingStatus +** --------------------------------- +** This is a private function that allows the caller to control what +** value is returned from the IMessageFilter::HandleInComing method. +** +** if a HandleInComingCallbackProc is installed by a call to +** OleStdMsgFilter_SetHandleInComingCallbackProc, then this +** overrides the dwIncomingCallStatus established by a call to +** OleStdMsgFilter_SetInComingStatus. Using +** OleStdMsgFilter_SetInComingStatus allows the app to reject or +** accept ALL in coming calls. Using a HandleInComingCallbackProc +** allows the app to selectively handle or reject particular method +** calls. +*/ + +STDAPI_(void) OleStdMsgFilter_SetInComingCallStatus( + LPMESSAGEFILTER lpThis, DWORD dwInComingCallStatus) +{ + LPOLESTDMESSAGEFILTER lpStdMsgFilter = (LPOLESTDMESSAGEFILTER)lpThis; + + if (!IsBadWritePtr((LPVOID)lpStdMsgFilter, sizeof(OLESTDMESSAGEFILTER))) + lpStdMsgFilter->m_dwInComingCallStatus = dwInComingCallStatus; + else + OleDbgAssert( + TEXT("OleStdMsgFilter_SetIncomingCallStatus: Invalid IMessageFilter*")); + +#if defined( _DEBUG ) + { + TCHAR szBuf[80]; + TCHAR *szReturn; + + switch(dwInComingCallStatus) { + case SERVERCALL_ISHANDLED: + szReturn = TEXT("SERVERCALL_ISHANDLED"); + break; + case SERVERCALL_REJECTED: + szReturn = TEXT("SERVERCALL_REJECTED"); + break; + case SERVERCALL_RETRYLATER: + szReturn = TEXT("SERVERCALL_RETRYLATER"); + break; + default: + szReturn = TEXT("** ERROR: UNKNOWN **"); + break; + } + wsprintf( + szBuf, + TEXT("OleStdMsgFilter_SetInComingCallStatus: Status set to %s.\r\n"), + (LPTSTR)szReturn + ); + OleDbgOut3(szBuf); + } +#endif + +} + + +/* OleStdMsgFilter_SetHandleInComingCallbackProc +** --------------------------------------------- +** This is a private function that allows the caller to install (or +** de-install) a special callback function to selectively +** handle/reject specific incoming method calls on particular +** interfaces. +** +** if a HandleInComingCallbackProc is installed by a call to +** OleStdMsgFilter_SetHandleInComingCallbackProc, then this +** overrides the dwIncomingCallStatus established by a call to +** OleStdMsgFilter_SetInComingStatus. Using +** OleStdMsgFilter_SetInComingStatus allows the app to reject or +** accept ALL in coming calls. Using a HandleInComingCallbackProc +** allows the app to selectively handle or reject particular method +** calls. +** +** to de-install the HandleInComingCallbackProc, call +** OleStdMsgFilter_SetHandleInComingCallbackProc(NULL); +** +** Returns previous callback proc in effect. +*/ + +STDAPI_(HANDLEINCOMINGCALLBACKPROC) + OleStdMsgFilter_SetHandleInComingCallbackProc( + LPMESSAGEFILTER lpThis, + HANDLEINCOMINGCALLBACKPROC lpfnHandleInComingCallback) +{ + LPOLESTDMESSAGEFILTER lpStdMsgFilter = (LPOLESTDMESSAGEFILTER)lpThis; + HANDLEINCOMINGCALLBACKPROC lpfnPrevCallback = + lpStdMsgFilter->m_lpfnHandleInComingCallback; + + if (!IsBadWritePtr((LPVOID)lpStdMsgFilter, sizeof(OLESTDMESSAGEFILTER))) { + lpStdMsgFilter->m_lpfnHandleInComingCallback = + lpfnHandleInComingCallback; + } else { + OleDbgAssert( + TEXT("OleStdMsgFilter_SetIncomingCallStatus: Invalid IMessageFilter*")); + } + +#if defined( _DEBUG ) + { + if (lpfnHandleInComingCallback) + OleDbgOut3( + TEXT("OleStdMsgFilter_SetHandleInComingCallbackProc SET\r\n")); + else + OleDbgOut3( + TEXT("OleStdMsgFilter_SetHandleInComingCallbackProc CLEARED\r\n")); + + } +#endif // _DEBUG + + return lpfnPrevCallback; +} + + +/* OleStdMsgFilter_GetInComingStatus +** --------------------------------- +** This is a private function that returns the current +** incoming call status. Can be used to disable/enable options +** in the calling application. +** +** Returns: one of +** +** SERVERCALL_ISHANDLED +** SERVERCALL_REJECTED +** SERVERCALL_RETRYLATER +** or -1 for ERROR +** +*/ + +STDAPI_(DWORD) OleStdMsgFilter_GetInComingCallStatus( + LPMESSAGEFILTER lpThis) +{ + LPOLESTDMESSAGEFILTER lpStdMsgFilter = (LPOLESTDMESSAGEFILTER)lpThis; + DWORD dwReturn; + + if (!IsBadReadPtr((LPVOID)lpStdMsgFilter, sizeof(OLESTDMESSAGEFILTER))) + dwReturn = lpStdMsgFilter->m_dwInComingCallStatus; + else + { + OleDbgAssert( + TEXT("OleStdMsgFilter_GetIncomingCallStatus: Invalid IMessageFilter*")); + dwReturn = (DWORD)-1; + } + +#if defined( _DEBUG ) + { + TCHAR szBuf[80]; + TCHAR *szReturn; + + switch(dwReturn) { + case SERVERCALL_ISHANDLED: + szReturn = TEXT("SERVERCALL_ISHANDLED"); + break; + case SERVERCALL_REJECTED: + szReturn = TEXT("SERVERCALL_REJECTED"); + break; + case SERVERCALL_RETRYLATER: + szReturn = TEXT("SERVERCALL_RETRYLATER"); + break; + default: + szReturn = TEXT("-1"); + break; + } + wsprintf( + szBuf, + TEXT("OleStdMsgFilter_GetInComingCallStatus returns %s.\r\n"), + (LPTSTR)szReturn + ); + OleDbgOut3(szBuf); + } +#endif + + return dwReturn; +} + + +/* OleStdMsgFilter_EnableBusyDialog +** -------------------------------- +** This function allows the caller to control whether +** the busy dialog is enabled. this is the dialog put up when +** IMessageFilter::RetryRejectedCall is called because the server +** responded SERVERCALL_RETRYLATER or SERVERCALL_REJECTED. +** +** if the busy dialog is NOT enabled, then the rejected call is +** immediately canceled WITHOUT prompting the user. in this situation +** OleStdMsgFilter_RetryRejectedCall always retuns +** OLESTDCANCELRETRY canceling the outgoing LRPC call. +** If the busy dialog is enabled, then the user is given the choice +** of whether to retry, switch to, or cancel. +** +** Returns previous dialog enable state +*/ + +STDAPI_(BOOL) OleStdMsgFilter_EnableBusyDialog( + LPMESSAGEFILTER lpThis, BOOL fEnable) +{ + LPOLESTDMESSAGEFILTER lpStdMsgFilter = (LPOLESTDMESSAGEFILTER)lpThis; + BOOL fPrevEnable = lpStdMsgFilter->m_fEnableBusyDialog; + + if (!IsBadWritePtr((LPVOID)lpStdMsgFilter, sizeof(OLESTDMESSAGEFILTER))) + lpStdMsgFilter->m_fEnableBusyDialog = fEnable; + else + OleDbgAssert( + TEXT("OleStdMsgFilter_EnableBusyDialog: Invalid IMessageFilter*")); + +#if defined( _DEBUG ) + { + TCHAR szBuf[80]; + wsprintf( + szBuf, + TEXT("OleStdMsgFilter_EnableBusyDialog: Dialog is %s.\r\n"), + fEnable ? (LPTSTR) TEXT("ENABLED") : (LPTSTR) TEXT("DISABLED") + ); + OleDbgOut3(szBuf); + } +#endif + + return fPrevEnable; +} + + +/* OleStdMsgFilter_EnableNotRespondingDialog +** ----------------------------------------- +** This function allows the caller to control whether +** the app "NotResponding" (Blocked) dialog is enabled. this is the +** dialog put up when IMessageFilter::MessagePending is called. +** If the NotResponding dialog is enabled, then the user is given +** the choice of whether to retry or switch to, but NOT to cancel. +** +** Returns previous dialog enable state +*/ + +STDAPI_(BOOL) OleStdMsgFilter_EnableNotRespondingDialog( + LPMESSAGEFILTER lpThis, BOOL fEnable) +{ + LPOLESTDMESSAGEFILTER lpStdMsgFilter = (LPOLESTDMESSAGEFILTER)lpThis; + BOOL fPrevEnable = lpStdMsgFilter->m_fEnableNotRespondingDialog; + + if (!IsBadWritePtr((LPVOID)lpStdMsgFilter, sizeof(OLESTDMESSAGEFILTER))) + lpStdMsgFilter->m_fEnableNotRespondingDialog = fEnable; + else + OleDbgAssert( + TEXT("OleStdMsgFilter_EnableNotRespondingDialog: Invalid IMessageFilter*")); + +#if defined( _DEBUG ) + { + TCHAR szBuf[80]; + wsprintf( + szBuf, + TEXT("OleStdMsgFilter_EnableNotRespondingDialog: Dialog is %s.\r\n"), + fEnable ? (LPTSTR) TEXT("ENABLED") : (LPTSTR) TEXT("DISABLED") + ); + OleDbgOut3(szBuf); + } +#endif + + return fPrevEnable; +} + + +/* OleStdMsgFilter_SetParentWindow +** ------------------------------- +** This function allows caller to set which window will be used as +** the parent for the busy dialog. +** +** OLE2NOTE: it would be inportant for an in-place active server to +** reset this to its current in-place frame window when in-place +** activated. if the hWndParent is set to NULL then the dialogs will +** be parented to the desktop. +** +** Returns: previous parent window +*/ + +STDAPI_(HWND) OleStdMsgFilter_SetParentWindow( + LPMESSAGEFILTER lpThis, HWND hWndParent) +{ + LPOLESTDMESSAGEFILTER lpStdMsgFilter = (LPOLESTDMESSAGEFILTER)lpThis; + HWND hWndPrev = lpStdMsgFilter->m_hWndParent; + + lpStdMsgFilter->m_hWndParent = hWndParent; + return hWndPrev; +} + + +STDMETHODIMP OleStdMsgFilter_QueryInterface( + LPMESSAGEFILTER lpThis, REFIID riid, LPVOID FAR* ppvObj) +{ + LPOLESTDMESSAGEFILTER lpStdMsgFilter = (LPOLESTDMESSAGEFILTER)lpThis; + SCODE scode; + + /* Two interfaces supported: IUnknown, IMessageFilter + */ + + if (IsEqualIID(riid, &IID_IMessageFilter) || IsEqualIID(riid, &IID_IUnknown)) { + lpStdMsgFilter->m_cRef++; // A pointer to this object is returned + *ppvObj = lpThis; + scode = S_OK; + } + else { // unsupported interface + *ppvObj = NULL; + scode = E_NOINTERFACE; + } + + return ResultFromScode(scode); +} + + +STDMETHODIMP_(ULONG) OleStdMsgFilter_AddRef(LPMESSAGEFILTER lpThis) +{ + LPOLESTDMESSAGEFILTER lpStdMsgFilter = (LPOLESTDMESSAGEFILTER)lpThis; + return ++lpStdMsgFilter->m_cRef; +} + +STDMETHODIMP_(ULONG) OleStdMsgFilter_Release(LPMESSAGEFILTER lpThis) +{ + LPOLESTDMESSAGEFILTER lpStdMsgFilter = (LPOLESTDMESSAGEFILTER)lpThis; + LPMALLOC lpMalloc; + + if (--lpStdMsgFilter->m_cRef != 0) // Still used by others + return lpStdMsgFilter->m_cRef; + + // Free storage + if (CoGetMalloc(MEMCTX_TASK, (LPMALLOC FAR*)&lpMalloc) != NOERROR) + return (ULONG)0; + + lpMalloc->lpVtbl->Free(lpMalloc, lpStdMsgFilter); + lpMalloc->lpVtbl->Release(lpMalloc); + return (ULONG)0; +} + + +STDMETHODIMP_(DWORD) OleStdMsgFilter_HandleInComingCall ( + LPMESSAGEFILTER lpThis, + DWORD dwCallType, + HTASK htaskCaller, + DWORD dwTickCount, +#ifdef WIN32 + LPINTERFACEINFO dwReserved +#else + DWORD dwReserved +#endif +) +{ + LPOLESTDMESSAGEFILTER lpStdMsgFilter = (LPOLESTDMESSAGEFILTER)lpThis; + + /* if a HandleInComingCallbackProc is in effect, then this + ** overrides dwIncomingCallStatus established by a call to + ** OleStdMsgFilter_SetInComingStatus. we will call this + ** callback to allow the app to selectively handle or reject + ** incoming method calls. the LPINTERFACEINFO parameter + ** describes which method is being called. + */ + if (lpStdMsgFilter->m_lpfnHandleInComingCallback && + !IsBadCodePtr((FARPROC)lpStdMsgFilter->m_lpfnHandleInComingCallback)){ + return lpStdMsgFilter->m_lpfnHandleInComingCallback( + dwCallType, + htaskCaller, + dwTickCount, + dwReserved + ); + } + + switch (dwCallType) { + case CALLTYPE_TOPLEVEL: + /* OLE2NOTE: we currently have NO pending outgoing call and + ** there is a new toplevel incoming call. + ** this call may be rejected. + */ + return lpStdMsgFilter->m_dwInComingCallStatus; + + case CALLTYPE_TOPLEVEL_CALLPENDING: + /* OLE2NOTE: we currently HAVE a pending outgoing call and + ** there is a new toplevel incoming call. + ** this call may be rejected. + */ + return lpStdMsgFilter->m_dwInComingCallStatus; + + case CALLTYPE_NESTED: + /* OLE2NOTE: we currently HAVE a pending outgoing call and + ** there callback on behalf of the previous outgoing + ** call. this type of call should ALWAYS be handled. + */ + return SERVERCALL_ISHANDLED; + + case CALLTYPE_ASYNC: + /* OLE2NOTE: we currently have NO pending outgoing call and + ** there is a new asyncronis incoming call. + ** this call can NEVER be rejected. OLE actually ignores + ** the return code in this case and always allows the + ** call through. + */ + return SERVERCALL_ISHANDLED; // value returned does not matter + + case CALLTYPE_ASYNC_CALLPENDING: + /* OLE2NOTE: we currently HAVE a pending outgoing call and + ** there is a new asyncronis incoming call. + ** this call can NEVER be rejected. OLE ignore the + ** return code in this case. + */ + return SERVERCALL_ISHANDLED; // value returned does not + + default: + OleDbgAssert( + TEXT("OleStdMsgFilter_HandleInComingCall: Invalid CALLTYPE")); + return lpStdMsgFilter->m_dwInComingCallStatus; + } +} + +STDMETHODIMP_(DWORD) OleStdMsgFilter_RetryRejectedCall ( + LPMESSAGEFILTER lpThis, + HTASK htaskCallee, + DWORD dwTickCount, + DWORD dwRejectType +) +{ + LPOLESTDMESSAGEFILTER lpStdMsgFilter = (LPOLESTDMESSAGEFILTER)lpThis; + DWORD dwRet = 0; + UINT uRet; +#if defined( _DEBUG ) + TCHAR szBuf[80]; +#endif + OLEDBG_BEGIN2(TEXT("OleStdMsgFilter_RetryRejectedCall\r\n")) + + /* OLE2NOTE: we should only put up the application busy dialog when + ** the callee has responded SERVERCALL_RETRYLATER. if the + ** dwRejectType is SERVERCALL_REJECTED then there is something + ** seriously wrong with the callee (perhaps a severe low memory + ** situation). we don't want to even try to "Switch To" this app + ** or even try to "Retry". + */ + if (dwRejectType == SERVERCALL_RETRYLATER && + lpStdMsgFilter->m_fEnableBusyDialog) { + + OLEUIBUSY bz; + + /* OLE2NOTE: we do not want to put up the Busy dialog immediately + ** the when an app says RETRYLATER. we should continue retrying + ** for a while in case the app can un-busy itself in a + ** reasonable amount of time. + */ + if (dwTickCount <= (DWORD)OLESTDRETRYDELAY) { + dwRet = 500; // Retry after .5 sec + OLEDBG_END2 + return dwRet; + } + + /* + ** Set up structure for calling OLEUIBUSY dialog + */ + + bz.cbStruct = sizeof(OLEUIBUSY); + bz.dwFlags = 0L; + bz.hWndOwner =GetTopWindowInWindowsTask(lpStdMsgFilter->m_hWndParent); + bz.lpszCaption = lpStdMsgFilter->m_lpszAppName; + bz.lpfnHook = lpStdMsgFilter->m_lpfnBusyDialogHookCallback; + bz.lCustData = 0; + bz.hInstance = NULL; + bz.lpszTemplate = NULL; + bz.hResource = 0; + bz.hTask = htaskCallee; + bz.lphWndDialog = NULL; // We don't need the hDlg for this call + + uRet = OleUIBusy(&bz); + + switch (uRet) { + case OLEUI_BZ_RETRYSELECTED: + dwRet = 0; // Retry immediately + break; + + case OLEUI_CANCEL: + dwRet = OLESTDCANCELRETRY; // Cancel pending outgoing call + break; + + case OLEUI_BZERR_HTASKINVALID: + // Htask was invalid, return OLESTDRETRYDELAY anyway + dwRet = OLESTDRETRYDELAY; // Retry after msec + +#if defined( _DEBUG ) + wsprintf( + szBuf, + TEXT("OleStdMsgFilter_RetryRejectedCall, HTASK 0x%x invalid\r\n"), + htaskCallee + ); + OleDbgOut3(szBuf); +#endif + break; + } + } else { + dwRet = OLESTDCANCELRETRY; // Cancel pending outgoing call + } + +#if defined( _DEBUG ) + wsprintf(szBuf, + TEXT("OleStdMsgFilter_RetryRejectedCall returns %d\r\n"), + dwRet); + OleDbgOut3(szBuf); +#endif + + OLEDBG_END2 + return dwRet; +} + + + +/* a significant message is consider a mouse click or keyboard input. */ +#define IS_SIGNIFICANT_MSG(lpmsg) \ + ( \ + (PeekMessage((lpmsg), NULL, WM_LBUTTONDOWN, WM_LBUTTONDOWN, \ + PM_NOREMOVE | PM_NOYIELD)) \ + || (PeekMessage((lpmsg), NULL, WM_LBUTTONDBLCLK, WM_LBUTTONDBLCLK, \ + PM_NOREMOVE | PM_NOYIELD)) \ + || (PeekMessage((lpmsg), NULL, WM_NCLBUTTONDOWN, WM_NCLBUTTONDOWN, \ + PM_NOREMOVE | PM_NOYIELD)) \ + || (PeekMessage((lpmsg), NULL, WM_NCLBUTTONDBLCLK, WM_NCLBUTTONDBLCLK, \ + PM_NOREMOVE | PM_NOYIELD)) \ + || (PeekMessage((lpmsg), NULL, WM_KEYDOWN, WM_KEYDOWN, \ + PM_NOREMOVE | PM_NOYIELD)) \ + || (PeekMessage((lpmsg), NULL, WM_SYSKEYDOWN, WM_SYSKEYDOWN, \ + PM_NOREMOVE | PM_NOYIELD)) \ + ) + +STDMETHODIMP_(DWORD) OleStdMsgFilter_MessagePending ( + LPMESSAGEFILTER lpThis, + HTASK htaskCallee, + DWORD dwTickCount, + DWORD dwPendingType +) +{ + LPOLESTDMESSAGEFILTER lpStdMsgFilter = (LPOLESTDMESSAGEFILTER)lpThis; + DWORD dwReturn = PENDINGMSG_WAITDEFPROCESS; + MSG msg; + BOOL fIsSignificantMsg = IS_SIGNIFICANT_MSG(&msg); + UINT uRet; + +#if defined( _DEBUG ) + TCHAR szBuf[128]; + wsprintf( + szBuf, + TEXT("OleStdMsgFilter_MessagePending, dwTickCount = 0x%lX\r\n"), + (DWORD)dwTickCount + ); + OleDbgOut4(szBuf); +#endif + + /* OLE2NOTE: If our tick count for this call exceeds our standard retry + ** delay, then we need to put up the dialog. We will only + ** consider putting up the dialog if the user has issued a + ** "significant" event (ie. mouse click or keyboard event). a + ** simple mouse move should NOT trigger this dialog. + ** Since our call to + ** OleUIBusy below enters a DialogBox() message loop, there's a + ** possibility that another call will be initiated during the dialog, + ** and this procedure will be re-entered. Just so we don't put up + ** two dialogs at a time, we use the m_bUnblocking varable + ** to keep track of this situation. + */ + + if (dwTickCount > (DWORD)OLESTDRETRYDELAY && fIsSignificantMsg + && !lpStdMsgFilter->m_bUnblocking) + { + + if (lpStdMsgFilter->m_fEnableNotRespondingDialog) + { + OLEUIBUSY bz; + + lpStdMsgFilter->m_bUnblocking = TRUE; + + // Eat messages in our queue that we do NOT want to be dispatched + while (PeekMessage(&msg, NULL, WM_CLOSE, WM_CLOSE, PM_REMOVE | PM_NOYIELD)); + + /* Set up structure for calling OLEUIBUSY dialog, + ** using the "not responding" variety + */ + + bz.cbStruct = sizeof(OLEUIBUSY); + bz.dwFlags = BZ_NOTRESPONDINGDIALOG; + bz.hWndOwner =GetTopWindowInWindowsTask(lpStdMsgFilter->m_hWndParent); + bz.lpszCaption = lpStdMsgFilter->m_lpszAppName; + bz.lpfnHook = lpStdMsgFilter->m_lpfnBusyDialogHookCallback; + bz.lCustData = 0; + bz.hInstance = NULL; + bz.lpszTemplate = NULL; + bz.hResource = 0; + bz.hTask = htaskCallee; + + /* Set up the address to the hWnd in our MsgFilter structure. The + ** call to OleUIBusy will fill this in with the hWnd of the busy + ** dialog box + */ + + bz.lphWndDialog = (HWND FAR *)&(lpStdMsgFilter->m_hWndBusyDialog); + uRet = OleUIBusy(&bz); + + lpStdMsgFilter->m_bUnblocking = FALSE; + + return PENDINGMSG_WAITNOPROCESS; + } +#if defined( _DEBUG ) + else { + OleDbgOut3(TEXT("OleStdMsgFilter_MessagePending: BLOCKED but dialog Disabled\r\n")); + } +#endif + } + + /* If we're already unblocking, we're being re-entered. Don't + ** process message + */ + + if (lpStdMsgFilter->m_bUnblocking) + return PENDINGMSG_WAITDEFPROCESS; + + /* OLE2NOTE: If we have a callback function set up, call it with the + ** current message. If not, tell OLE LPRC mechanism to automatically + ** handle all messages. + */ + if (lpStdMsgFilter->m_lpfnMessagePendingCallback && + !IsBadCodePtr((FARPROC)lpStdMsgFilter->m_lpfnMessagePendingCallback)){ + MSG msg; + + /* OLE2NOTE: the app provided a MessagePendingCallback + ** function. we will PeekMessage for the first message in + ** the queue and pass it to the app. the app in its callback + ** function can decide to Dispatch this message or it can + ** PeekMessage on its own giving particular message filter + ** criteria. if the app returns TRUE then we return + ** PENDINGMSG_WAITNOPROCESS to OLE telling OLE to leave the + ** message in the queue. If the app returns FALSE, then we + ** return PENDINGMSG_WAITDEFPROCESS to OLE telling OLE to do + ** its default processing with the message. by default OLE + ** dispatches system messages and eats other messages and + ** beeps. + */ + if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE | PM_NOYIELD)) { + + if (lpStdMsgFilter->m_lpfnMessagePendingCallback(&msg)) { + /* TRUE return means that the app processed message. + ** + ** NOTE: (CHANGE FROM OLE2.0 VERSION) we leave it up to + ** the callback routine to remove the message if it + ** wants. + */ + dwReturn = PENDINGMSG_WAITNOPROCESS; + } else { + /* FALSE means that the app did not process the + ** message. we will let OLE take its + ** default action. + ** + ** NOTE: (CHANGE FROM OLE2.0 VERSION) we used to return + ** PENDINGMSG_WAITNOPROCESS to leave the message in + ** the queue; now we return PENDINGMSG_WAITDEFPROCESS + ** to let OLE do default processing. + */ + dwReturn = PENDINGMSG_WAITDEFPROCESS; + +#if defined( _DEBUG ) + wsprintf( + szBuf, + TEXT("Message (0x%x) (wParam=0x%x, lParam=0x%lx) using WAITDEFPROCESS while blocked\r\n"), + msg.message, + msg.lParam, + msg.wParam + ); + OleDbgOut2(szBuf); +#endif // _DEBUG + } + } + } + + return dwReturn; +} diff --git a/private/oleutest/letest/ole2ui/msgfiltr.h b/private/oleutest/letest/ole2ui/msgfiltr.h new file mode 100644 index 000000000..a542d5294 --- /dev/null +++ b/private/oleutest/letest/ole2ui/msgfiltr.h @@ -0,0 +1,64 @@ +/************************************************************************* +** +** OLE 2 Utility Code +** +** msgfiltr.h +** +** This file contains Private definitions, structures, types, and +** function prototypes for the OleStdMessageFilter implementation of +** the IMessageFilter interface. +** This file is part of the OLE 2.0 User Interface support library. +** +** (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved +** +*************************************************************************/ + +#if !defined( _MSGFILTR_H_ ) +#define _MSGFILTR_H_ + +#ifndef RC_INVOKED +#pragma message ("INCLUDING MSGFILTR.H from " __FILE__) +#endif /* RC_INVOKED */ + +// Message Pending callback procedure +typedef BOOL (CALLBACK* MSGPENDINGPROC)(MSG FAR *); + +// HandleInComingCall callback procedure +typedef DWORD (CALLBACK* HANDLEINCOMINGCALLBACKPROC) + ( + DWORD dwCallType, + HTASK htaskCaller, + DWORD dwTickCount, + LPINTERFACEINFO lpInterfaceInfo + ); + +/* PUBLIC FUNCTIONS */ +STDAPI_(LPMESSAGEFILTER) OleStdMsgFilter_Create( + HWND hWndParent, + LPTSTR szAppName, + MSGPENDINGPROC lpfnCallback, + LPFNOLEUIHOOK lpfnOleUIHook // Busy dialog hook callback +); + +STDAPI_(void) OleStdMsgFilter_SetInComingCallStatus( + LPMESSAGEFILTER lpThis, DWORD dwInComingCallStatus); + +STDAPI_(DWORD) OleStdMsgFilter_GetInComingCallStatus( + LPMESSAGEFILTER lpThis); + +STDAPI_(HANDLEINCOMINGCALLBACKPROC) + OleStdMsgFilter_SetHandleInComingCallbackProc( + LPMESSAGEFILTER lpThis, + HANDLEINCOMINGCALLBACKPROC lpfnHandleInComingCallback); + +STDAPI_(BOOL) OleStdMsgFilter_EnableBusyDialog( + LPMESSAGEFILTER lpThis, BOOL fEnable); + +STDAPI_(BOOL) OleStdMsgFilter_EnableNotRespondingDialog( + LPMESSAGEFILTER lpThis, BOOL fEnable); + +STDAPI_(HWND) OleStdMsgFilter_SetParentWindow( + LPMESSAGEFILTER lpThis, HWND hWndParent); + + +#endif // _MSGFILTR_H_ diff --git a/private/oleutest/letest/ole2ui/objfdbk.c b/private/oleutest/letest/ole2ui/objfdbk.c new file mode 100644 index 000000000..65e30f907 --- /dev/null +++ b/private/oleutest/letest/ole2ui/objfdbk.c @@ -0,0 +1,246 @@ +/* + * OBJFDBK.C + * + * Miscellaneous API's to generate UI feedback effects for OLE objects. This + * is part of the OLE 2.0 User Interface Support Library. + * The following feedback effects are supported: + * 1. Object selection handles (OleUIDrawHandles) + * 2. Open Object window shading (OleUIDrawShading) + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + +#define STRICT 1 +#include "ole2ui.h" + +static void DrawHandle(HDC hdc, int x, int y, UINT cSize, BOOL bInvert, BOOL fDraw); + +/* + * OleUIDrawHandles + * + * Purpose: + * Draw handles or/and boundary around Container Object when selected + * + * Parameters: + * lpRect Dimensions of Container Object + * hdc HDC of Container Object (MM_TEXT mapping mode) + * dwFlags- + * Exclusive flags + * OLEUI_HANDLES_INSIDE Draw handles on inside of rect + * OLEUI_HANDLES_OUTSIDE Draw handles on outside of rect + * Optional flags + * OLEUI_HANDLES_NOBORDER Draw handles only, no rect + * OLEUI_HANDLES_USEINVERSE + * use invert for handles and rect, o.t. use COLOR_WINDOWTEXT + * cSize size of handle box + * fDraw Draw if TRUE, erase if FALSE + * + * Return Value: null + * + */ +STDAPI_(void) OleUIDrawHandles( + LPRECT lpRect, + HDC hdc, + DWORD dwFlags, + UINT cSize, + BOOL fDraw +) +{ + HBRUSH hbr; + RECT rc; + int bkmodeOld; + BOOL bInvert = (BOOL) (dwFlags & OLEUI_HANDLES_USEINVERSE); + + CopyRect((LPRECT)&rc, lpRect); + + bkmodeOld = SetBkMode(hdc, TRANSPARENT); + + if (dwFlags & OLEUI_HANDLES_OUTSIDE) + InflateRect((LPRECT)&rc, cSize - 1, cSize - 1); + + // Draw the handles inside the rectangle boundary + DrawHandle(hdc, rc.left, rc.top, cSize, bInvert, fDraw); + DrawHandle(hdc, rc.left, rc.top+(rc.bottom-rc.top-cSize)/2, cSize, bInvert, fDraw); + DrawHandle(hdc, rc.left, rc.bottom-cSize, cSize, bInvert, fDraw); + DrawHandle(hdc, rc.left+(rc.right-rc.left-cSize)/2, rc.top, cSize, bInvert, fDraw); + DrawHandle(hdc, rc.left+(rc.right-rc.left-cSize)/2, rc.bottom-cSize, cSize, bInvert, fDraw); + DrawHandle(hdc, rc.right-cSize, rc.top, cSize, bInvert, fDraw); + DrawHandle(hdc, rc.right-cSize, rc.top+(rc.bottom-rc.top-cSize)/2, cSize, bInvert, fDraw); + DrawHandle(hdc, rc.right-cSize, rc.bottom-cSize, cSize, bInvert, fDraw); + + if (!(dwFlags & OLEUI_HANDLES_NOBORDER)) { + if (fDraw) + hbr = GetStockObject(BLACK_BRUSH); + else + hbr = GetStockObject(WHITE_BRUSH); + + FrameRect(hdc, lpRect, hbr); + } + + SetBkMode(hdc, bkmodeOld); +} + + + +/* + * DrawHandle + * + * Purpose: + * Draw a handle box at the specified coordinate + * + * Parameters: + * hdc HDC to be drawn into + * x, y upper left corner coordinate of the handle box + * cSize size of handle box + * bInvert use InvertRect() if TRUE, otherwise use Rectangle() + * fDraw Draw if TRUE, erase if FALSE, ignored if bInvert is TRUE + * + * Return Value: null + * + */ +static void DrawHandle(HDC hdc, int x, int y, UINT cSize, BOOL bInvert, BOOL fDraw) +{ + HBRUSH hbr; + HBRUSH hbrOld; + HPEN hpen; + HPEN hpenOld; + RECT rc; + + + if (!bInvert) { + if (fDraw) { + hpen = GetStockObject(BLACK_PEN); + hbr = GetStockObject(BLACK_BRUSH); + } else { + hpen = GetStockObject(WHITE_PEN); + hbr = GetStockObject(WHITE_PEN); + } + + hpenOld = SelectObject(hdc, hpen); + hbrOld = SelectObject(hdc, hbr); + Rectangle(hdc, x, y, x+cSize, y+cSize); + SelectObject(hdc, hpenOld); + SelectObject(hdc, hbrOld); + } + else { + rc.left = x; + rc.top = y; + rc.right = x + cSize; + rc.bottom = y + cSize; + InvertRect(hdc, (LPRECT)&rc); + } +} + + +/* + * OleUIDrawShading + * + * Purpose: + * Shade the object when it is in in-place editing. Borders are drawn + * on the Object rectangle. The right and bottom edge of the rectangle + * are excluded in the drawing. + * + * Parameters: + * lpRect Dimensions of Container Object + * hdc HDC for drawing + * dwFlags- + * Exclusive flags + * OLEUI_SHADE_FULLRECT Shade the whole rectangle + * OLEUI_SHADE_BORDERIN Shade cWidth pixels inside rect + * OLEUI_SHADE_BORDEROUT Shade cWidth pixels outside rect + * Optional flags + * OLEUI_SHADE_USEINVERSE + * use PATINVERT instead of the hex value + * cWidth width of border in pixel + * + * Return Value: null + * + */ +STDAPI_(void) OleUIDrawShading(LPRECT lpRect, HDC hdc, DWORD dwFlags, UINT cWidth) +{ + HBRUSH hbr; + HBRUSH hbrOld; + HBITMAP hbm; + RECT rc; + WORD wHatchBmp[] = {0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44, 0x88}; + COLORREF cvText; + COLORREF cvBk; + + hbm = CreateBitmap(8, 8, 1, 1, wHatchBmp); + hbr = CreatePatternBrush(hbm); + hbrOld = SelectObject(hdc, hbr); + + rc = *lpRect; + + if (dwFlags == OLEUI_SHADE_FULLRECT) { + cvText = SetTextColor(hdc, RGB(255, 255, 255)); + cvBk = SetBkColor(hdc, RGB(0, 0, 0)); + PatBlt(hdc, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, + 0x00A000C9L /* DPa */ ); + + } else { // either inside or outside rect + + if (dwFlags == OLEUI_SHADE_BORDEROUT) + InflateRect((LPRECT)&rc, cWidth - 1, cWidth - 1); + + cvText = SetTextColor(hdc, RGB(255, 255, 255)); + cvBk = SetBkColor(hdc, RGB(0, 0, 0)); + PatBlt(hdc, rc.left, rc.top, rc.right - rc.left, + cWidth, 0x00A000C9L /* DPa */); + PatBlt(hdc, rc.left, rc.top, cWidth, rc.bottom - rc.top, + 0x00A000C9L /* DPa */); + PatBlt(hdc, rc.right - cWidth, rc.top, cWidth, + rc.bottom - rc.top, 0x00A000C9L /* DPa */); + PatBlt(hdc, rc.left, rc.bottom - cWidth, rc.right-rc.left, + cWidth, 0x00A000C9L /* DPa */); + } + + SetTextColor(hdc, cvText); + SetBkColor(hdc, cvBk); + SelectObject(hdc, hbrOld); + DeleteObject(hbr); + DeleteObject(hbm); +} + + +/* + * OleUIShowObject + * + * Purpose: + * Draw the ShowObject effect around the object + * + * Parameters: + * lprc rectangle for drawing + * hdc HDC for drawing + * fIsLink linked object (TRUE) or embedding object (FALSE) + * + * Return Value: null + * + */ +STDAPI_(void) OleUIShowObject(LPCRECT lprc, HDC hdc, BOOL fIsLink) +{ + HPEN hpen; + HPEN hpenOld; + HBRUSH hbrOld; + + if (!lprc || !hdc) + return; + + hpen = fIsLink ? CreatePen(PS_DASH, 1, RGB(0,0,0)) : + GetStockObject(BLACK_PEN); + + if (!hpen) + return; + + hpenOld = SelectObject(hdc, hpen); + hbrOld = SelectObject(hdc, GetStockObject(NULL_BRUSH)); + + Rectangle(hdc, lprc->left, lprc->top, lprc->right, lprc->bottom); + + SelectObject(hdc, hpenOld); + SelectObject(hdc, hbrOld); + + if (fIsLink) + DeleteObject(hpen); + +} diff --git a/private/oleutest/letest/ole2ui/ole2ui.c b/private/oleutest/letest/ole2ui/ole2ui.c new file mode 100644 index 000000000..fd1fc57bc --- /dev/null +++ b/private/oleutest/letest/ole2ui/ole2ui.c @@ -0,0 +1,971 @@ +/* + * OLE2UI.C + * + * Contains initialization routines and miscellaneous API implementations for + * the OLE 2.0 User Interface Support Library. + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + +#define STRICT 1 + +#include "ole2ui.h" +#include "common.h" +#include "utility.h" +#include "resimage.h" +#include "iconbox.h" +#include + +#define WINDLL 1 // make far pointer version of stdargs.h +#include + +// NOTE: If this code is being compiled for a DLL, then we need to define +// our OLE2UI debug symbols here (with the OLEDBGDATA_MAIN macro). If we're +// compiling for a static LIB, then the application we link to must +// define these symbols -- we just need to make an external reference here +// (with the macro OLEDBGDATA). + +#ifdef DLL_VER +OLEDBGDATA_MAIN(TEXT("OLE2UI")) +#else +OLEDBGDATA +#endif + +//The DLL instance handle shared amongst all dialogs. +HINSTANCE ghInst; + +//Registered messages for use with all the dialogs, registered in LibMain +UINT uMsgHelp=0; +UINT uMsgEndDialog=0; +UINT uMsgBrowse=0; +UINT uMsgChangeIcon=0; +UINT uMsgFileOKString=0; +UINT uMsgCloseBusyDlg=0; + +//Clipboard formats used by PasteSpecial +UINT cfObjectDescriptor; +UINT cfLinkSrcDescriptor; +UINT cfEmbedSource; +UINT cfEmbeddedObject; +UINT cfLinkSource; +UINT cfOwnerLink; +UINT cfFileName; + +// local function prototypes +BOOL CALLBACK EXPORT PromptUserDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam); +BOOL CALLBACK EXPORT UpdateLinksDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam); + + +// local definition +#define WM_U_UPDATELINK WM_USER + + +// local structure definition +typedef struct tagUPDATELINKS +{ + LPOLEUILINKCONTAINER lpOleUILinkCntr; // pointer to Link Container + UINT cLinks; // total number of links + UINT cUpdated; // number of links updated + DWORD dwLink; // pointer to link + BOOL fError; // error flag + LPTSTR lpszTitle; // caption for dialog box +} UPDATELINKS, *PUPDATELINKS, FAR *LPUPDATELINKS; + + +/* + * OleUIInitialize + * + * NOTE: This function should only be called by your application IF it is + * using the static-link version of this library. If the DLL version is + * being used, this function is automatically called from the OLE2UI DLL's + * LibMain. + * + * Purpose: + * Initializes the OLE UI Library. Registers the OLE clipboard formats + * used in the Paste Special dialog, registers private custom window + * messages, and registers window classes of the "Result Image" + * and "Icon Box" custom controls used in the UI dialogs. + * + * Parameters: + * + * hInstance HINSTANCE of the module where the UI library resources + * and Dialog Procedures are contained. If you are calling + * this function yourself, this should be the instance handle + * of your application. + * + * hPrevInst HINSTANCE of the previous application instance. + * This is the parameter passed in to your WinMain. For + * the DLL version, this should always be set to zero (for + * WIN16 DLLs). + * + * lpszClassIconBox + * LPTSTR containing the name you assigned to the symbol + * SZCLASSICONBOX (this symbol is defined in UICLASS.H + * which is generated in the MAKEFILE). + * + * This name is used as the window class name + * when registering the IconBox custom control used in the + * UI dialogs. In order to handle mutliple apps running + * with this library, you must make this name unique to your + * application. + * + * For the DLL version: Do NOT call this function directly + * from your application, it is called automatically from + * the DLL's LibMain. + * + * For the static library version: This should be set to + * the symbol SZCLASSICONBOX. This symbol is defined in + * UICLASS.H. + * + * lpszClassResImage + * LPTSTR containing the name you assigned to the symbol + * SZCLASSRESULTIMAGE. See the description of + * lpszClassIconBox above for more info. + * + * Return Value: + * BOOL TRUE if initialization was successful. + * FALSE if either the "Magic Number" did not verify, or one of + * the window classes could not be registered. If the + * "Magic Number" did not verify, then the resources + * in your module are of a different version than the + * ones you compiled with. + */ + +STDAPI_(BOOL) OleUIInitialize(HINSTANCE hInstance, + HINSTANCE hPrevInst, + LPTSTR lpszClassIconBox, + LPTSTR lpszClassResImage) +{ + HRSRC hr; + HGLOBAL hg; + LPWORD lpdata; + + OleDbgOut1(TEXT("OleUIInitialize called.\r\n")); + ghInst=hInstance; + + // Verify that we have the correct resources added to our application + // by checking the "VERIFICATION" resource with the magic number we've + // compiled into our app. + + OutputDebugString(TEXT("Entering OleUIInitialize\n")); + + if ((hr = FindResource(hInstance, TEXT("VERIFICATION"), RT_RCDATA)) == NULL) + goto ResourceLoadError; + + if ((hg = LoadResource(hInstance, hr)) == NULL) + goto ResourceLoadError; + + if ((lpdata = (LPWORD)LockResource(hg)) == NULL) + goto ResourceLockError; + + if ((WORD)*lpdata != (WORD)OLEUI_VERSION_MAGIC) + goto ResourceReadError; + + // OK, resource versions match. Contine on. + UnlockResource(hg); + FreeResource(hg); + OleDbgOut1(TEXT("OleUIInitialize: Resource magic number verified.\r\n")); + + // Register messages we need for the dialogs. If + uMsgHelp =RegisterWindowMessage(SZOLEUI_MSG_HELP); + uMsgEndDialog =RegisterWindowMessage(SZOLEUI_MSG_ENDDIALOG); + uMsgBrowse =RegisterWindowMessage(SZOLEUI_MSG_BROWSE); + uMsgChangeIcon=RegisterWindowMessage(SZOLEUI_MSG_CHANGEICON); + uMsgFileOKString = RegisterWindowMessage(FILEOKSTRING); + uMsgCloseBusyDlg = RegisterWindowMessage(SZOLEUI_MSG_CLOSEBUSYDIALOG); + + // Register Clipboard Formats used by PasteSpecial dialog. + cfObjectDescriptor = RegisterClipboardFormat(CF_OBJECTDESCRIPTOR); + cfLinkSrcDescriptor= RegisterClipboardFormat(CF_LINKSRCDESCRIPTOR); + cfEmbedSource = RegisterClipboardFormat(CF_EMBEDSOURCE); + cfEmbeddedObject = RegisterClipboardFormat(CF_EMBEDDEDOBJECT); + cfLinkSource = RegisterClipboardFormat(CF_LINKSOURCE); + cfOwnerLink = RegisterClipboardFormat(CF_OWNERLINK); + cfFileName = RegisterClipboardFormat(CF_FILENAME); + + if (!FResultImageInitialize(hInstance, hPrevInst, lpszClassResImage)) + { + OleDbgOut1(TEXT("OleUIInitialize: FResultImageInitialize failed. Terminating.\r\n")); + return 0; + } + + if (!FIconBoxInitialize(hInstance, hPrevInst, lpszClassIconBox)) + { + OleDbgOut1(TEXT("OleUIInitialize: FIconBoxInitialize failed. Terminating.\r\n")); + return 0; + } + + return TRUE; + +ResourceLoadError: + OleDbgOut1(TEXT("OleUIInitialize: ERROR - Unable to find version verification resource.\r\n")); + return FALSE; + +ResourceLockError: + OleDbgOut1(TEXT("OleUIInitialize: ERROR - Unable to lock version verification resource.\r\n")); + FreeResource(hg); + return FALSE; + +ResourceReadError: + OleDbgOut1(TEXT("OleUIInitialize: ERROR - Version verification values did not compare.\r\n")); + + {TCHAR buf[255]; + wsprintf(buf, TEXT("resource read 0x%X, my value is 0x%X\n"), (WORD)*lpdata, (WORD)OLEUI_VERSION_MAGIC); + OutputDebugString(buf); + } + + UnlockResource(hg); + FreeResource(hg); + return FALSE; +} + + +/* + * OleUIUnInitialize + * + * NOTE: This function should only be called by your application IF it is using + * the static-link version of this library. If the DLL version is being used, + * this function is automatically called from the DLL's LibMain. + * + * Purpose: + * Uninitializes OLE UI libraries. Deletes any resources allocated by the + * library. + * + * Return Value: + * BOOL TRUE if successful, FALSE if not. Current implementation always + * returns TRUE. + */ + + +STDAPI_(BOOL) OleUIUnInitialize() +{ + IconBoxUninitialize(); + ResultImageUninitialize(); + + return TRUE; +} + + +/* + * OleUIAddVerbMenu + * + * Purpose: + * Add the Verb menu for the specified object to the given menu. If the + * object has one verb, we directly add the verb to the given menu. If + * the object has multiple verbs we create a cascading sub-menu. + * + * Parameters: + * lpObj LPOLEOBJECT pointing to the selected object. If this + * is NULL, then we create a default disabled menu item. + * + * lpszShortType LPTSTR with short type name (AuxName==2) corresponding + * to the lpOleObj. if the string is NOT known, then NULL + * may be passed. if NULL is passed, then + * IOleObject::GetUserType will be called to retrieve it. + * if the caller has the string handy, then it is faster + * to pass it in. + * + * hMenu HMENU in which to make modifications. + * + * uPos Position of the menu item + * + * uIDVerbMin UINT ID value at which to start the verbs. + * verb_0 = wIDMVerbMin + verb_0 + * verb_1 = wIDMVerbMin + verb_1 + * verb_2 = wIDMVerbMin + verb_2 + * etc. + * uIDVerbMax UINT maximum ID value allowed for object verbs. + * if uIDVerbMax==0 then any ID value is allowed + * + * bAddConvert BOOL specifying whether or not to add a "Convert" item + * to the bottom of the menu (with a separator). + * + * idConvert UINT ID value to use for the Convert menu item, if + * bAddConvert is TRUE. + * + * lphMenu HMENU FAR * of the cascading verb menu if it's created. + * If there is only one verb, this will be filled with NULL. + * + * + * Return Value: + * BOOL TRUE if lpObj was valid and we added at least one verb + * to the menu. FALSE if lpObj was NULL and we created + * a disabled default menu item + */ + +STDAPI_(BOOL) OleUIAddVerbMenu(LPOLEOBJECT lpOleObj, + LPTSTR lpszShortType, + HMENU hMenu, + UINT uPos, + UINT uIDVerbMin, + UINT uIDVerbMax, + BOOL bAddConvert, + UINT idConvert, + HMENU FAR *lphMenu) +{ + LPPERSISTSTORAGE lpPS=NULL; + LPENUMOLEVERB lpEnumOleVerb = NULL; + OLEVERB oleverb; + LPUNKNOWN lpUnk; + LPTSTR lpszShortTypeName = lpszShortType; + LPTSTR lpszVerbName = NULL; + HRESULT hrErr; + BOOL fStatus; + BOOL fIsLink = FALSE; + BOOL fResult = TRUE; + BOOL fAddConvertItem = FALSE; + int cVerbs = 0; + UINT uFlags = MF_BYPOSITION; + static BOOL fFirstTime = TRUE; + static TCHAR szBuffer[OLEUI_OBJECTMENUMAX]; + static TCHAR szNoObjectCmd[OLEUI_OBJECTMENUMAX]; + static TCHAR szObjectCmd1Verb[OLEUI_OBJECTMENUMAX]; + static TCHAR szLinkCmd1Verb[OLEUI_OBJECTMENUMAX]; + static TCHAR szObjectCmdNVerb[OLEUI_OBJECTMENUMAX]; + static TCHAR szLinkCmdNVerb[OLEUI_OBJECTMENUMAX]; + static TCHAR szUnknown[OLEUI_OBJECTMENUMAX]; + static TCHAR szEdit[OLEUI_OBJECTMENUMAX]; + static TCHAR szConvert[OLEUI_OBJECTMENUMAX]; + + *lphMenu=NULL; + + // Set fAddConvertItem flag + if (bAddConvert & (idConvert != 0)) + fAddConvertItem = TRUE; + + // only need to load the strings the 1st time + if (fFirstTime) { + if (0 == LoadString(ghInst, IDS_OLE2UIEDITNOOBJCMD, + (LPTSTR)szNoObjectCmd, OLEUI_OBJECTMENUMAX)) + return FALSE; + if (0 == LoadString(ghInst, IDS_OLE2UIEDITLINKCMD_1VERB, + (LPTSTR)szLinkCmd1Verb, OLEUI_OBJECTMENUMAX)) + return FALSE; + if (0 == LoadString(ghInst, IDS_OLE2UIEDITOBJECTCMD_1VERB, + (LPTSTR)szObjectCmd1Verb, OLEUI_OBJECTMENUMAX)) + return FALSE; + + if (0 == LoadString(ghInst, IDS_OLE2UIEDITLINKCMD_NVERB, + (LPTSTR)szLinkCmdNVerb, OLEUI_OBJECTMENUMAX)) + return FALSE; + if (0 == LoadString(ghInst, IDS_OLE2UIEDITOBJECTCMD_NVERB, + (LPTSTR)szObjectCmdNVerb, OLEUI_OBJECTMENUMAX)) + return FALSE; + + if (0 == LoadString(ghInst, IDS_OLE2UIUNKNOWN, + (LPTSTR)szUnknown, OLEUI_OBJECTMENUMAX)) + return FALSE; + + if (0 == LoadString(ghInst, IDS_OLE2UIEDIT, + (LPTSTR)szEdit, OLEUI_OBJECTMENUMAX)) + return FALSE; + + if ( (0 == LoadString(ghInst, IDS_OLE2UICONVERT, + (LPTSTR)szConvert, OLEUI_OBJECTMENUMAX)) && fAddConvertItem) + return FALSE; + + fFirstTime = FALSE; + } + + // Delete whatever menu may happen to be here already. + DeleteMenu(hMenu, uPos, uFlags); + + if (!lpOleObj) + goto AVMError; + + if (! lpszShortTypeName) { + // get the Short form of the user type name for the menu + OLEDBG_BEGIN2(TEXT("IOleObject::GetUserType called\r\n")) + hrErr = CallIOleObjectGetUserTypeA( + lpOleObj, + USERCLASSTYPE_SHORT, + (LPTSTR FAR*)&lpszShortTypeName + ); + OLEDBG_END2 + + if (NOERROR != hrErr) { + OleDbgOutHResult(TEXT("IOleObject::GetUserType returned"), hrErr); + } + } + + // check if the object is a link (it is a link if it support IOleLink) + hrErr = lpOleObj->lpVtbl->QueryInterface( + lpOleObj, + &IID_IOleLink, + (LPVOID FAR*)&lpUnk + ); + if (NOERROR == hrErr) { + fIsLink = TRUE; + OleStdRelease(lpUnk); + } + + // Get the verb enumerator from the OLE object + OLEDBG_BEGIN2(TEXT("IOleObject::EnumVerbs called\r\n")) + hrErr = lpOleObj->lpVtbl->EnumVerbs( + lpOleObj, + (LPENUMOLEVERB FAR*)&lpEnumOleVerb + ); + OLEDBG_END2 + + if (NOERROR != hrErr) { + OleDbgOutHResult(TEXT("IOleObject::EnumVerbs returned"), hrErr); + } + + if (!(*lphMenu = CreatePopupMenu())) + goto AVMError; + + // loop through all verbs + while (lpEnumOleVerb != NULL) { // forever + hrErr = lpEnumOleVerb->lpVtbl->Next( + lpEnumOleVerb, + 1, + (LPOLEVERB)&oleverb, + NULL + ); + if (NOERROR != hrErr) + break; // DONE! no more verbs + + /* OLE2NOTE: negative verb numbers and verbs that do not + ** indicate ONCONTAINERMENU should NOT be put on the verb menu + */ + if (oleverb.lVerb < 0 || + ! (oleverb.grfAttribs & OLEVERBATTRIB_ONCONTAINERMENU)) { + + /* OLE2NOTE: we must still free the verb name string */ + if (oleverb.lpszVerbName) + OleStdFree(oleverb.lpszVerbName); + continue; + } + + // we must free the previous verb name string + if (lpszVerbName) + OleStdFreeString(lpszVerbName, NULL); + + CopyAndFreeOLESTR(oleverb.lpszVerbName, &lpszVerbName); + + if ( 0 == uIDVerbMax || + (uIDVerbMax >= uIDVerbMin+(UINT)oleverb.lVerb) ) { + fStatus = InsertMenu( + *lphMenu, + (UINT)-1, + MF_BYPOSITION | (UINT)oleverb.fuFlags, + uIDVerbMin+(UINT)oleverb.lVerb, + (LPTSTR)lpszVerbName + ); + if (! fStatus) + goto AVMError; + + cVerbs++; + } + } + + // Add the separator and "Convert" menu item. + if (fAddConvertItem) { + + if (0 == cVerbs) { + LPTSTR lpsz; + + // if object has no verbs, then use "Convert" as the obj's verb + lpsz = lpszVerbName = OleStdCopyString(szConvert, NULL); + uIDVerbMin = idConvert; + + // remove "..." from "Convert..." string; it will be added later + if (lpsz) { + while(*lpsz && *lpsz != TEXT('.')) + lpsz++; + *lpsz = TEXT('\0'); + } + } + + if (cVerbs > 0) { + fStatus = InsertMenu(*lphMenu, + (UINT)-1, + MF_BYPOSITION | MF_SEPARATOR, + (UINT)0, + (LPCTSTR)NULL); + if (! fStatus) + goto AVMError; + } + + /* add convert menu */ + fStatus = InsertMenu(*lphMenu, + (UINT)-1, + MF_BYPOSITION, + idConvert, + (LPCTSTR)szConvert); + if (! fStatus) + goto AVMError; + + cVerbs++; + } + + + /* + * Build the appropriate menu based on the number of verbs found + * + * NOTE: Localized verb menus may require a different format. + * to assist in localization of the single verb case, the + * szLinkCmd1Verb and szObjectCmd1Verb format strings start + * with either a '0' (note: NOT '\0'!) or a '1': + * leading '0' -- verb type + * leading '1' -- type verb + */ + + if (cVerbs == 0) { + + // there are NO verbs (not even Convert...). set the menu to be + // " &Object/Link" and gray it out. + wsprintf( + szBuffer, + (fIsLink ? (LPTSTR)szLinkCmdNVerb:(LPTSTR)szObjectCmdNVerb), + (lpszShortTypeName ? lpszShortTypeName : (LPTSTR) TEXT("")) + ); + uFlags |= MF_GRAYED; + +#if defined( OBSOLETE ) + //No verbs. Create a default using Edit as the verb. + LPTSTR lpsz = (fIsLink ? szLinkCmd1Verb : szObjectCmd1Verb); + + if (*lpsz == TEXT('0')) { + wsprintf(szBuffer, lpsz+1, (LPSTR)szEdit, + (lpszShortTypeName ? lpszShortTypeName : (LPTSTR) TEXT("")) + ); + } + else { + wsprintf(szBuffer, lpsz+1, + (lpszShortTypeName ? lpszShortTypeName : (LPTSTR) TEXT("")), + (LPTSTR)szEdit + ); + } +#endif + + fResult = FALSE; + DestroyMenu(*lphMenu); + *lphMenu = NULL; + + } + else if (cVerbs == 1) { + //One verb without Convert, one item. + LPTSTR lpsz = (fIsLink ? szLinkCmd1Verb : szObjectCmd1Verb); + + if (*lpsz == TEXT('0')) { + wsprintf(szBuffer, lpsz+1, lpszVerbName, + (lpszShortTypeName ? lpszShortTypeName : (LPTSTR) TEXT("")) + ); + } + else { + wsprintf(szBuffer, lpsz+1, + (lpszShortTypeName ? lpszShortTypeName : (LPTSTR) TEXT("")), + lpszVerbName + ); + } + + // if only "verb" is "Convert..." then append the ellipses + if (fAddConvertItem) + lstrcat(szBuffer, TEXT("...")); + + DestroyMenu(*lphMenu); + *lphMenu=NULL; + } + else { + + //Multiple verbs or one verb with Convert, add the cascading menu + wsprintf( + szBuffer, + (fIsLink ? (LPTSTR)szLinkCmdNVerb:(LPTSTR)szObjectCmdNVerb), + (lpszShortTypeName ? lpszShortTypeName : (LPTSTR) TEXT("")) + ); + uFlags |= MF_ENABLED | MF_POPUP; + uIDVerbMin=(UINT)*lphMenu; + } + + if (!InsertMenu(hMenu, uPos, uFlags, uIDVerbMin, (LPTSTR)szBuffer)) + +AVMError: + { + InsertMenu(hMenu, uPos, MF_GRAYED | uFlags, + uIDVerbMin, (LPTSTR)szNoObjectCmd); +#if defined( OBSOLETE ) + HMENU hmenuDummy = CreatePopupMenu(); + + InsertMenu(hMenu, uPos, MF_GRAYED | MF_POPUP | uFlags, + (UINT)hmenuDummy, (LPTSTR)szNoObjectCmd); +#endif + fResult = FALSE; + } + + if (lpszVerbName) + OleStdFreeString(lpszVerbName, NULL); + if (!lpszShortType && lpszShortTypeName) + OleStdFreeString(lpszShortTypeName, NULL); + if (lpEnumOleVerb) + lpEnumOleVerb->lpVtbl->Release(lpEnumOleVerb); + return fResult; +} + + +/* PromptUserDlgProc + * ----------------- + * + * Purpose: + * Dialog procedure used by OleUIPromptUser(). Returns when a button is + * clicked in the dialog box and the button id is return. + * + * Parameters: + * hDlg + * iMsg + * wParam + * lParam + * + * Returns: + * + */ +BOOL CALLBACK EXPORT PromptUserDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam) +{ + switch (iMsg) { + case WM_INITDIALOG: + { + LPTSTR lpszTitle; + TCHAR szBuf[256]; + TCHAR szFormat[256]; + va_list *parglist; + + if (!lParam) { + EndDialog(hDlg, -1); + return FALSE; + } + + // + // lParam is really a va_list *. We called va_start and va_end in + // the function that calls this. + // + + parglist = (va_list *) lParam; + + lpszTitle = va_arg(*parglist, LPTSTR); + SetWindowText(hDlg, lpszTitle); + + GetDlgItemText(hDlg, ID_PU_TEXT,(LPTSTR)szFormat,sizeof(szFormat)/sizeof(TCHAR)); + wvsprintf((LPTSTR)szBuf, (LPTSTR)szFormat, *parglist); + + + SetDlgItemText(hDlg, ID_PU_TEXT, (LPTSTR)szBuf); + return TRUE; + } + case WM_COMMAND: + EndDialog(hDlg, wParam); + return TRUE; + + default: + return FALSE; + } +} + + +/* OleUIPromptUser + * --------------- + * + * Purpose: + * Popup a dialog box with the specified template and returned the + * response (button id) from the user. + * + * Parameters: + * nTemplate resource number of the dialog + * hwndParent parent of the dialog box + * ... title of the dialog box followed by argument list + * for the format string in the static control + * (ID_PU_TEXT) of the dialog box. + * The caller has to make sure that the correct number + * and type of argument are passed in. + * + * Returns: + * button id selected by the user (template dependent) + * + * Comments: + * the following message dialog boxes are supported: + * + * IDD_LINKSOURCEUNAVAILABLE -- Link source is unavailable + * VARARG Parameters: + * None. + * Used for the following error codes: + * OLE_E_CANT_BINDTOSOURCE + * STG_E_PATHNOTFOUND + * (sc >= MK_E_FIRST) && (sc <= MK_E_LAST) -- any Moniker error + * any unknown error if object is a link + * + * IDD_SERVERNOTFOUND -- server registered but NOT found + * VARARG Parameters: + * LPSTR lpszUserType -- user type name of object + * Used for the following error codes: + * CO_E_APPNOTFOUND + * CO_E_APPDIDNTREG + * any unknown error if object is an embedded object + * + * IDD_SERVERNOTREG -- server NOT registered + * VARARG Parameters: + * LPSTR lpszUserType -- user type name of object + * Used for the following error codes: + * REGDB_E_CLASSNOTREG + * OLE_E_STATIC -- static object with no server registered + * + * IDD_LINKTYPECHANGED -- class of link source changed since last binding + * VARARG Parameters: + * LPSTR lpszUserType -- user type name of ole link source + * Used for the following error codes: + * OLE_E_CLASSDIFF + * + * IDD_LINKTYPECHANGED -- class of link source changed since last binding + * VARARG Parameters: + * LPSTR lpszUserType -- user type name of ole link source + * Used for the following error codes: + * OLE_E_CLASSDIFF + * + * IDD_OUTOFMEMORY -- out of memory + * VARARG Parameters: + * None. + * Used for the following error codes: + * E_OUTOFMEMORY + * + */ +int EXPORT FAR CDECL OleUIPromptUser(int nTemplate, HWND hwndParent, ...) +{ + int nRet; + va_list arglist; + LPARAM lParam; + + // + // We want to pass the variable list of arguments to PrompUserDlgProc, + // but we can't just pass arglist because arglist is not always the + // same size as an LPARAM (e.g. on Alpha va_list is a structure). + // So, we pass the a pointer to the arglist instead. + // + + va_start(arglist, hwndParent); + lParam = (LPARAM) &arglist; + + nRet = DialogBoxParam(ghInst, MAKEINTRESOURCE(nTemplate), hwndParent, + PromptUserDlgProc, lParam); + + va_end(arglist); + + return nRet; +} + + + +/* UpdateLinksDlgProc + * ------------------ + * + * Purpose: + * Dialog procedure used by OleUIUpdateLinks(). It will enumerate all + * all links in the container and updates all automatic links. + * Returns when the Stop Button is clicked in the dialog box or when all + * links are updated + * + * Parameters: + * hDlg + * iMsg + * wParam + * lParam pointer to the UPDATELINKS structure + * + * Returns: + * + */ +BOOL CALLBACK EXPORT UpdateLinksDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam) +{ + LPUPDATELINKS FAR* lplpUL = NULL; + HANDLE gh; + static BOOL fAbort = FALSE; + + //Process the temination message + if (iMsg==uMsgEndDialog) + { + gh = RemoveProp(hDlg, STRUCTUREPROP); + if (NULL!=gh) { + GlobalUnlock(gh); + GlobalFree(gh); + } + EndDialog(hDlg, wParam); + return TRUE; + } + + switch (iMsg) { + case WM_INITDIALOG: + { + gh=GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,sizeof(LPUPDATELINKS)); + SetProp(hDlg, STRUCTUREPROP, gh); + + if (NULL==gh) + { + PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_GLOBALMEMALLOC,0L); + return FALSE; + } + + fAbort = FALSE; + lplpUL = (LPUPDATELINKS FAR*)GlobalLock(gh); + + if (lplpUL) { + *lplpUL = (LPUPDATELINKS)lParam; + SetWindowText(hDlg, (*lplpUL)->lpszTitle); + SetTimer(hDlg, 1, UPDATELINKS_STARTDELAY, NULL); + return TRUE; + } else { + PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_GLOBALMEMALLOC,0L); + return FALSE; + } + } + + case WM_TIMER: + KillTimer(hDlg, 1); + gh = GetProp(hDlg, STRUCTUREPROP); + + if (NULL!=gh) { + // gh was locked previously, lock and unlock to get lplpUL + lplpUL = GlobalLock(gh); + GlobalUnlock(gh); + } + if (! fAbort && lplpUL) + PostMessage(hDlg, WM_U_UPDATELINK, 0, (LPARAM)(*lplpUL)); + else + PostMessage(hDlg,uMsgEndDialog,OLEUI_CANCEL,0L); + + return 0; + + case WM_COMMAND: // Stop button + fAbort = TRUE; + SendMessage(hDlg, uMsgEndDialog, OLEUI_OK, 0L); + return TRUE; + + case WM_U_UPDATELINK: + { + HRESULT hErr; + int nPercent; + RECT rc; + TCHAR szPercent[5]; // 0% to 100% + HBRUSH hbr; + HDC hDC; + HWND hwndMeter; + MSG msg; + DWORD dwUpdateOpt; + LPUPDATELINKS lpUL = (LPUPDATELINKS)lParam; + + lpUL->dwLink=lpUL->lpOleUILinkCntr->lpVtbl->GetNextLink( + lpUL->lpOleUILinkCntr, + lpUL->dwLink + ); + + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { + if (! IsDialogMessage(hDlg, &msg)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + if (fAbort) + return FALSE; + + if (!lpUL->dwLink) { // all links processed + SendMessage(hDlg, uMsgEndDialog, OLEUI_OK, 0L); + return TRUE; + } + + hErr = lpUL->lpOleUILinkCntr->lpVtbl->GetLinkUpdateOptions( + lpUL->lpOleUILinkCntr, + lpUL->dwLink, + (LPDWORD)&dwUpdateOpt + ); + + if ((hErr == NOERROR) && (dwUpdateOpt == OLEUPDATE_ALWAYS)) { + + hErr = lpUL->lpOleUILinkCntr->lpVtbl->UpdateLink( + lpUL->lpOleUILinkCntr, + lpUL->dwLink, + FALSE, // fMessage + FALSE // ignored + ); + lpUL->fError |= (hErr != NOERROR); + lpUL->cUpdated++; + + nPercent = lpUL->cUpdated * 100 / lpUL->cLinks; + if (nPercent <= 100) { // do NOT advance % beyond 100% + // update percentage + wsprintf((LPTSTR)szPercent, TEXT("%d%%"), nPercent); + SetDlgItemText(hDlg, ID_PU_PERCENT, (LPTSTR)szPercent); + + // update indicator + hwndMeter = GetDlgItem(hDlg, ID_PU_METER); + GetClientRect(hwndMeter, (LPRECT)&rc); + InflateRect((LPRECT)&rc, -1, -1); + rc.right = (rc.right - rc.left) * nPercent / 100 + rc.left; + hbr = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT)); + if (hbr) { + hDC = GetDC(hwndMeter); + if (hDC) { + FillRect(hDC, (LPRECT)&rc, hbr); + ReleaseDC(hwndMeter, hDC); + } + DeleteObject(hbr); + } + } + } + + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { + if (! IsDialogMessage(hDlg, &msg)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + PostMessage(hDlg, WM_U_UPDATELINK, 0, lParam); + + return TRUE; + } + + default: + return FALSE; + } +} + + +/* OleUIUpdateLink + * --------------- + * + * Purpose: + * Update all links in the Link Container and popup a dialog box which + * shows the progress of the updating. + * The process is stopped when the user press Stop button or when all + * links are processed. + * + * Parameters: + * lpOleUILinkCntr pointer to Link Container + * hwndParent parent window of the dialog + * lpszTitle title of the dialog box + * cLinks total number of links + * + * Returns: + * TRUE all links updated successfully + * FALSE otherwise + */ +STDAPI_(BOOL) OleUIUpdateLinks(LPOLEUILINKCONTAINER lpOleUILinkCntr, HWND hwndParent, LPTSTR lpszTitle, int cLinks) +{ + LPUPDATELINKS lpUL = (LPUPDATELINKS)OleStdMalloc(sizeof(UPDATELINKS)); + BOOL fError; + + OleDbgAssert(lpOleUILinkCntr && hwndParent && lpszTitle && (cLinks>0)); + OleDbgAssert(lpUL); + + lpUL->lpOleUILinkCntr = lpOleUILinkCntr; + lpUL->cLinks = cLinks; + lpUL->cUpdated = 0; + lpUL->dwLink = 0; + lpUL->fError = FALSE; + lpUL->lpszTitle = lpszTitle; + + DialogBoxParam(ghInst, MAKEINTRESOURCE(IDD_UPDATELINKS), + hwndParent, UpdateLinksDlgProc, (LPARAM)lpUL); + + fError = lpUL->fError; + OleStdFree((LPVOID)lpUL); + + return !fError; +} diff --git a/private/oleutest/letest/ole2ui/ole2ui.h b/private/oleutest/letest/ole2ui/ole2ui.h new file mode 100644 index 000000000..9990c79e0 --- /dev/null +++ b/private/oleutest/letest/ole2ui/ole2ui.h @@ -0,0 +1,958 @@ +/* + * OLE2UI.H + * + * Published definitions, structures, types, and function prototypes for the + * OLE 2.0 User Interface support library. + * + * Copyright (c)1993 Microsoft Corporation, All Rights Reserved + */ + + +#ifndef _OLE2UI_H_ +#define _OLE2UI_H_ + +#undef UNICODE +#undef _UNICODE + +#if DBG == 1 +// Lazy way to avoid going through all the files and changing to the +// new standard. +#define _DEBUG 1 +#endif // DBG == 1 + +#ifndef RC_INVOKED +#pragma message ("Including OLE2UI.H from " __FILE__) +#endif //RC_INVOKED + +// Macro to ensure strings to be UNICODEd in OLE +#ifdef UNICODE + #define OLETEXT(quote) TEXT(quote) +#else + #define OLETEXT(quote) L##quote +#endif + +#if !defined(__cplusplus) && !defined( __TURBOC__) +// #define NONAMELESSUNION // use strict ANSI standard (for DVOBJ.H) +#endif + +#ifndef INC_OLE2 + #define INC_OLE2 +#endif +#include +#include +#include +#include +#include //For fileopen dlg; standard include +#include "olestd.h" +#include + +#ifdef __TURBOC__ +#define _getcwd getcwd +#define _itoa itoa +#define __max max +#define _find_t find_t +#endif // __TURBOC__ + +#ifdef WIN32 + #define _fmemset memset + #define _fmemcpy memcpy + #define _fmemcmp memcmp + + #ifdef UNICODE + // UNICODE stuff + #define _fstrcpy wcscpy + #define _fstrlen wcslen + #define _fstrrchr wcschr + #define _fstrtok wcstok + + #define _fstrchr wcscpy + #define _fstrcpy wcscpy + + // BUGBUG32: isspace function does not seem to work properly + // + // XXXXX + // create a wide character image to match the ANSI isspace + #undef isspace + #undef iswspace + #define iswspace(j) (j==TEXT(' ') || j==TEXT('\t') || j==TEXT('\n')) + #define isspace(j) (j==' ' || j=='\t' || j=='\n') + + #else + // Win32 doesn't support the following _fstrxxx functions + #define _fstrcpy strcpy + #define _fstrlen strlen + #define _fstrrchr strrchr + #define _fstrtok strtok + + #define _fstrchr strchr + #define _fstrcpy strcpy + + #endif // UNICODE + +#endif // WIN32 + +#if !defined( EXPORT ) +#ifdef WIN32 +#define EXPORT +#else +#define EXPORT __export +#endif // WIN32 +#endif // !EXPORT + +/* + * Initialization / Uninitialization routines. OleUIInitialize + * must be called prior to using any functions in OLE2UI, and OleUIUnInitialize + * must be called before you app shuts down and when you are done using the + * library. + * + * NOTE: If you are using the DLL version of this library, these functions + * are automatically called in the DLL's LibMain and WEP, so you should + * not call them directly from your application. + */ + +// Backward compatibility with older library +#define OleUIUninitialize OleUIUnInitialize + +STDAPI_(BOOL) OleUIInitialize(HINSTANCE hInstance, + HINSTANCE hPrevInst, + LPTSTR lpszClassIconBox, + LPTSTR lpszClassResImage); +STDAPI_(BOOL) OleUIUninitialize(void); + +//Dialog Identifiers as passed in Help messages to identify the source. +#define IDD_INSERTOBJECT 1000 +#define IDD_CHANGEICON 1001 +#define IDD_CONVERT 1002 +#define IDD_PASTESPECIAL 1003 +#define IDD_EDITLINKS 1004 +#define IDD_FILEOPEN 1005 +#define IDD_BUSY 1006 +#define IDD_UPDATELINKS 1007 +#define IDD_CANNOTUPDATELINK 1008 +#define IDD_CHANGESOURCE 1009 +#define IDD_INSERTFILEBROWSE 1010 +#define IDD_CHANGEICONBROWSE 1011 + +// The following Dialogs are message dialogs used by OleUIPromptUser API +#define IDD_LINKSOURCEUNAVAILABLE 1020 +#define IDD_SERVERNOTREG 1021 +#define IDD_LINKTYPECHANGED 1022 +#define IDD_SERVERNOTFOUND 1023 +#define IDD_OUTOFMEMORY 1024 + +// Stringtable identifers +#define IDS_OLE2UIUNKNOWN 300 +#define IDS_OLE2UILINK 301 +#define IDS_OLE2UIOBJECT 302 +#define IDS_OLE2UIEDIT 303 +#define IDS_OLE2UICONVERT 304 +#define IDS_OLE2UIEDITLINKCMD_1VERB 305 +#define IDS_OLE2UIEDITOBJECTCMD_1VERB 306 +#define IDS_OLE2UIEDITLINKCMD_NVERB 307 +#define IDS_OLE2UIEDITOBJECTCMD_NVERB 308 +#define IDS_OLE2UIEDITNOOBJCMD 309 +// def. icon label (usu. "Document") +#define IDS_DEFICONLABEL 310 +#define IDS_OLE2UIPASTELINKEDTYPE 311 + + +#define IDS_FILTERS 64 +#define IDS_ICONFILTERS 65 +#define IDS_BROWSE 66 + +//Resource identifiers for bitmaps +#define IDB_RESULTSEGA 10 +#define IDB_RESULTSVGA 11 +#define IDB_RESULTSHIRESVGA 12 + + +//Missing from windows.h +#ifndef PVOID +typedef VOID *PVOID; +#endif + + +//Hook type used in all structures. +typedef UINT (CALLBACK *LPFNOLEUIHOOK)(HWND, UINT, WPARAM, LPARAM); + + +//Strings for registered messages +#define SZOLEUI_MSG_HELP TEXT("OLEUI_MSG_HELP") +#define SZOLEUI_MSG_ENDDIALOG TEXT("OLEUI_MSG_ENDDIALOG") +#define SZOLEUI_MSG_BROWSE TEXT("OLEUI_MSG_BROWSE") +#define SZOLEUI_MSG_CHANGEICON TEXT("OLEUI_MSG_CHANGEICON") +#define SZOLEUI_MSG_CLOSEBUSYDIALOG TEXT("OLEUI_MSG_CLOSEBUSYDIALOG") +#define SZOLEUI_MSG_FILEOKSTRING TEXT("OLEUI_MSG_FILEOKSTRING") + +//Standard error definitions +#define OLEUI_FALSE 0 +#define OLEUI_SUCCESS 1 //No error, same as OLEUI_OK +#define OLEUI_OK 1 //OK button pressed +#define OLEUI_CANCEL 2 //Cancel button pressed + +#define OLEUI_ERR_STANDARDMIN 100 +#define OLEUI_ERR_STRUCTURENULL 101 //Standard field validation +#define OLEUI_ERR_STRUCTUREINVALID 102 +#define OLEUI_ERR_CBSTRUCTINCORRECT 103 +#define OLEUI_ERR_HWNDOWNERINVALID 104 +#define OLEUI_ERR_LPSZCAPTIONINVALID 105 +#define OLEUI_ERR_LPFNHOOKINVALID 106 +#define OLEUI_ERR_HINSTANCEINVALID 107 +#define OLEUI_ERR_LPSZTEMPLATEINVALID 108 +#define OLEUI_ERR_HRESOURCEINVALID 109 + +#define OLEUI_ERR_FINDTEMPLATEFAILURE 110 //Initialization errors +#define OLEUI_ERR_LOADTEMPLATEFAILURE 111 +#define OLEUI_ERR_DIALOGFAILURE 112 +#define OLEUI_ERR_LOCALMEMALLOC 113 +#define OLEUI_ERR_GLOBALMEMALLOC 114 +#define OLEUI_ERR_LOADSTRING 115 + +#define OLEUI_ERR_STANDARDMAX 116 //Start here for specific errors. + + + +//Help Button Identifier +#define ID_OLEUIHELP 99 + +// Help button for fileopen.dlg (need this for resizing) 1038 is pshHelp +#undef IDHELP +#define IDHELP 1038 + +// Static text control (use this instead of -1 so things work correctly for +// localization +#define ID_STATIC 98 + +/****************** + * The followings are defined in the fashion that the first + * definition is the number of CHARACTERS, while the second one (XXX_SIZE) + * is the number of bytes. The number of bytes definition is needed for + * UNICODE handling purpose. + * Also, please note the prefix of variables cch means that it is the + * count of characters and cb means the count of bytes. + ******************/ + +//Maximum key size we read from the RegDB. +#define OLEUI_CCHKEYMAX 256 // make any changes to this in geticon.c too +#define OLEUI_CCHKEYMAX_SIZE OLEUI_CCHKEYMAX*sizeof(TCHAR) // # of bytes + +//Maximum verb length and length of Object menu +#define OLEUI_CCHVERBMAX 32 +#define OLEUI_CCHVERBMAX_SIZE OLEUI_CCHVERBMAX*sizeof(TCHAR) // # of bytes +#define OLEUI_OBJECTMENUMAX 256 +#define OLEUI_OBJECTMENUMAX_SIZE OLEUI_OBJECTMENUMAX*sizeof(TCHAR) // # of bytes + +//Maximum MS-DOS pathname. +#define OLEUI_CCHPATHMAX 256 // make any changes to this in geticon.c too +#define OLEUI_CCHPATHMAX_SIZE OLEUI_CCHPATHMAX*sizeof(TCHAR) // # of bytes +#define OLEUI_CCHFILEMAX 13 +#define OLEUI_CCHFILEMAX_SIZE OLEUI_CCHFILEMAX*sizeof(TCHAR) // # of bytes + +//Icon label length +#define OLEUI_CCHLABELMAX 40 // make any changes to this in geticon.c too +#define OLEUI_CCHLABELMAX_SIZE OLEUI_CCHLABELMAX*sizeof(TCHAR) // # of bytes + +//Length of the CLSID string +#define OLEUI_CCHCLSIDSTRING 39 +#define OLEUI_CCHCLSIDSTRING_SIZE OLEUI_CCHCLSIDSTRING*sizeof(TCHAR) // # of bytes + + +/* + * What follows here are first function prototypes for general utility + * functions, then sections laid out by dialog. Each dialog section + * defines the dialog structure, the API prototype, flags for the dwFlags + * field, the dialog-specific error values, and dialog control IDs (for + * hooks and custom templates. + */ + + +//Miscellaneous utility functions. +STDAPI_(BOOL) OleUIAddVerbMenu(LPOLEOBJECT lpOleObj, + LPTSTR lpszShortType, + HMENU hMenu, + UINT uPos, + UINT uIDVerbMin, + UINT uIDVerbMax, + BOOL bAddConvert, + UINT idConvert, + HMENU FAR *lphMenu); + +//Metafile utility functions +#ifndef WIN32 +STDAPI_(HGLOBAL) OleUIMetafilePictFromIconAndLabel(HICON, LPTSTR, LPTSTR, UINT); +#endif +STDAPI_(void) OleUIMetafilePictIconFree(HGLOBAL); +STDAPI_(BOOL) OleUIMetafilePictIconDraw(HDC, LPRECT, HGLOBAL, BOOL); +STDAPI_(UINT) OleUIMetafilePictExtractLabel(HGLOBAL, LPTSTR, UINT, LPDWORD); +STDAPI_(HICON) OleUIMetafilePictExtractIcon(HGLOBAL); +STDAPI_(BOOL) OleUIMetafilePictExtractIconSource(HGLOBAL,LPTSTR,UINT FAR *); + + + + + +/************************************************************************* +** INSERT OBJECT DIALOG +*************************************************************************/ + + +typedef struct tagOLEUIINSERTOBJECT + { + //These IN fields are standard across all OLEUI dialog functions. + DWORD cbStruct; //Structure Size + DWORD dwFlags; //IN-OUT: Flags + HWND hWndOwner; //Owning window + LPCTSTR lpszCaption; //Dialog caption bar contents + LPFNOLEUIHOOK lpfnHook; //Hook callback + LPARAM lCustData; //Custom data to pass to hook + HINSTANCE hInstance; //Instance for customized template name + LPCTSTR lpszTemplate; //Customized template name + HRSRC hResource; //Customized template handle + + //Specifics for OLEUIINSERTOBJECT. All are IN-OUT unless otherwise spec. + CLSID clsid; //Return space for class ID + LPTSTR lpszFile; //Filename for inserts or links + UINT cchFile; //Size of lpszFile buffer: OLEUI_CCHPATHMAX + UINT cClsidExclude; //IN only: CLSIDs in lpClsidExclude + LPCLSID lpClsidExclude; //List of CLSIDs to exclude from listing. + + //Specific to create objects if flags say so + IID iid; //Requested interface on creation. + DWORD oleRender; //Rendering option + LPFORMATETC lpFormatEtc; //Desired format + LPOLECLIENTSITE lpIOleClientSite; //Site to be use for the object. + LPSTORAGE lpIStorage; //Storage used for the object + LPVOID FAR *ppvObj; //Where the object is returned. + SCODE sc; //Result of creation calls. + HGLOBAL hMetaPict; //OUT: METAFILEPICT containing iconic aspect. + //IFF we couldn't stuff it in the cache. + } OLEUIINSERTOBJECT, *POLEUIINSERTOBJECT, FAR *LPOLEUIINSERTOBJECT; + +//API prototype +STDAPI_(UINT) OleUIInsertObject(LPOLEUIINSERTOBJECT); + + +//Insert Object flags +#define IOF_SHOWHELP 0x00000001L +#define IOF_SELECTCREATENEW 0x00000002L +#define IOF_SELECTCREATEFROMFILE 0x00000004L +#define IOF_CHECKLINK 0x00000008L +#define IOF_CHECKDISPLAYASICON 0x00000010L +#define IOF_CREATENEWOBJECT 0x00000020L +#define IOF_CREATEFILEOBJECT 0x00000040L +#define IOF_CREATELINKOBJECT 0x00000080L +#define IOF_DISABLELINK 0x00000100L +#define IOF_VERIFYSERVERSEXIST 0x00000200L +#define IOF_DISABLEDISPLAYASICON 0x00000400L + + +//Insert Object specific error codes +#define OLEUI_IOERR_LPSZFILEINVALID (OLEUI_ERR_STANDARDMAX+0) +#define OLEUI_IOERR_LPSZLABELINVALID (OLEUI_ERR_STANDARDMAX+1) +#define OLEUI_IOERR_HICONINVALID (OLEUI_ERR_STANDARDMAX+2) +#define OLEUI_IOERR_LPFORMATETCINVALID (OLEUI_ERR_STANDARDMAX+3) +#define OLEUI_IOERR_PPVOBJINVALID (OLEUI_ERR_STANDARDMAX+4) +#define OLEUI_IOERR_LPIOLECLIENTSITEINVALID (OLEUI_ERR_STANDARDMAX+5) +#define OLEUI_IOERR_LPISTORAGEINVALID (OLEUI_ERR_STANDARDMAX+6) +#define OLEUI_IOERR_SCODEHASERROR (OLEUI_ERR_STANDARDMAX+7) +#define OLEUI_IOERR_LPCLSIDEXCLUDEINVALID (OLEUI_ERR_STANDARDMAX+8) +#define OLEUI_IOERR_CCHFILEINVALID (OLEUI_ERR_STANDARDMAX+9) + + +//Insert Object Dialog identifiers +#define ID_IO_CREATENEW 2100 +#define ID_IO_CREATEFROMFILE 2101 +#define ID_IO_LINKFILE 2102 +#define ID_IO_OBJECTTYPELIST 2103 +#define ID_IO_DISPLAYASICON 2104 +#define ID_IO_CHANGEICON 2105 +#define ID_IO_FILE 2106 +#define ID_IO_FILEDISPLAY 2107 +#define ID_IO_RESULTIMAGE 2108 +#define ID_IO_RESULTTEXT 2109 +#define ID_IO_ICONDISPLAY 2110 +#define ID_IO_OBJECTTYPETEXT 2111 +#define ID_IO_FILETEXT 2112 +#define ID_IO_FILETYPE 2113 + +// Strings in OLE2UI resources +#define IDS_IORESULTNEW 256 +#define IDS_IORESULTNEWICON 257 +#define IDS_IORESULTFROMFILE1 258 +#define IDS_IORESULTFROMFILE2 259 +#define IDS_IORESULTFROMFILEICON2 260 +#define IDS_IORESULTLINKFILE1 261 +#define IDS_IORESULTLINKFILE2 262 +#define IDS_IORESULTLINKFILEICON1 263 +#define IDS_IORESULTLINKFILEICON2 264 + +/************************************************************************* +** PASTE SPECIAL DIALOG +*************************************************************************/ + +// Maximum number of link types +#define PS_MAXLINKTYPES 8 + +//NOTE: OLEUIPASTEENTRY and OLEUIPASTEFLAG structs are defined in OLESTD.H + +typedef struct tagOLEUIPASTESPECIAL + { + //These IN fields are standard across all OLEUI dialog functions. + DWORD cbStruct; //Structure Size + DWORD dwFlags; //IN-OUT: Flags + HWND hWndOwner; //Owning window + LPCTSTR lpszCaption; //Dialog caption bar contents + LPFNOLEUIHOOK lpfnHook; //Hook callback + LPARAM lCustData; //Custom data to pass to hook + HINSTANCE hInstance; //Instance for customized template name + LPCTSTR lpszTemplate; //Customized template name + HRSRC hResource; //Customized template handle + + //Specifics for OLEUIPASTESPECIAL. + + //IN fields + LPDATAOBJECT lpSrcDataObj; //Source IDataObject* (on the + // clipboard) for data to paste + + LPOLEUIPASTEENTRY arrPasteEntries; //OLEUIPASTEENTRY array which + // specifies acceptable formats. See + // OLEUIPASTEENTRY for more info. + int cPasteEntries; //No. of OLEUIPASTEENTRY array entries + + UINT FAR *arrLinkTypes; //List of link types that are + // acceptable. Link types are referred + // to using OLEUIPASTEFLAGS in + // arrPasteEntries + int cLinkTypes; //Number of link types + UINT cClsidExclude; //Number of CLSIDs in lpClsidExclude + LPCLSID lpClsidExclude; //List of CLSIDs to exclude from list. + + //OUT fields + int nSelectedIndex; //Index of arrPasteEntries[] that the + // user selected + BOOL fLink; //Indicates if Paste or Paste Link was + // selected by the user + HGLOBAL hMetaPict; //Handle to Metafile containing icon + // and icon title selected by the user + // Use the Metafile utility functions + // defined in this header to + // manipulate hMetaPict + SIZEL sizel; // size of object/link in its source + // if the display aspect chosen by + // the user matches the aspect + // displayed in the source. if + // different aspect is chosen then + // sizel.cx=sizel.cy=0 is returned. + // sizel displayed in source is + // retrieved from the + // ObjectDescriptor if fLink is FALSE + // LinkSrcDescriptor if fLink is TRUE + } OLEUIPASTESPECIAL, *POLEUIPASTESPECIAL, FAR *LPOLEUIPASTESPECIAL; + + +//API to bring up PasteSpecial dialog +STDAPI_(UINT) OleUIPasteSpecial(LPOLEUIPASTESPECIAL); + + +//Paste Special flags +// Show Help button. IN flag. +#define PSF_SHOWHELP 0x00000001L + +//Select Paste radio button at dialog startup. This is the default if +// PSF_SELECTPASTE or PSF_SELECTPASTELINK are not specified. Also specifies +// state of button on dialog termination. IN/OUT flag. +#define PSF_SELECTPASTE 0x00000002L + +//Select PasteLink radio button at dialog startup. Also specifies state of +// button on dialog termination. IN/OUT flag. +#define PSF_SELECTPASTELINK 0x00000004L + +//Specfies if DisplayAsIcon button was checked on dialog termination. OUT flag +#define PSF_CHECKDISPLAYASICON 0x00000008L +#define PSF_DISABLEDISPLAYASICON 0x00000010L + + +//Paste Special specific error codes +#define OLEUI_IOERR_SRCDATAOBJECTINVALID (OLEUI_ERR_STANDARDMAX+0) +#define OLEUI_IOERR_ARRPASTEENTRIESINVALID (OLEUI_ERR_STANDARDMAX+1) +#define OLEUI_IOERR_ARRLINKTYPESINVALID (OLEUI_ERR_STANDARDMAX+2) +#define OLEUI_PSERR_CLIPBOARDCHANGED (OLEUI_ERR_STANDARDMAX+3) + +//Paste Special Dialog identifiers +#define ID_PS_PASTE 500 +#define ID_PS_PASTELINK 501 +#define ID_PS_SOURCETEXT 502 +#define ID_PS_PASTELIST 503 +#define ID_PS_PASTELINKLIST 504 +#define ID_PS_DISPLAYLIST 505 +#define ID_PS_DISPLAYASICON 506 +#define ID_PS_ICONDISPLAY 507 +#define ID_PS_CHANGEICON 508 +#define ID_PS_RESULTIMAGE 509 +#define ID_PS_RESULTTEXT 510 +#define ID_PS_RESULTGROUP 511 +#define ID_PS_STXSOURCE 512 +#define ID_PS_STXAS 513 + +// Paste Special String IDs +#define IDS_PSPASTEDATA 400 +#define IDS_PSPASTEOBJECT 401 +#define IDS_PSPASTEOBJECTASICON 402 +#define IDS_PSPASTELINKDATA 403 +#define IDS_PSPASTELINKOBJECT 404 +#define IDS_PSPASTELINKOBJECTASICON 405 +#define IDS_PSNONOLE 406 +#define IDS_PSUNKNOWNTYPE 407 +#define IDS_PSUNKNOWNSRC 408 +#define IDS_PSUNKNOWNAPP 409 + + +/************************************************************************* +** EDIT LINKS DIALOG +*************************************************************************/ + + + +/* IOleUILinkContainer Interface +** ----------------------------- +** This interface must be implemented by container applications that +** want to use the EditLinks dialog. the EditLinks dialog calls back +** to the container app to perform the OLE functions to manipulate +** the links within the container. +*/ + +#define LPOLEUILINKCONTAINER IOleUILinkContainer FAR* + +#undef INTERFACE +#define INTERFACE IOleUILinkContainer + +DECLARE_INTERFACE_(IOleUILinkContainer, IUnknown) +{ + //*** IUnknown methods ***/ + STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + STDMETHOD_(DWORD,GetNextLink) (THIS_ DWORD dwLink) PURE; + STDMETHOD(SetLinkUpdateOptions) (THIS_ DWORD dwLink, DWORD dwUpdateOpt) PURE; + STDMETHOD(GetLinkUpdateOptions) (THIS_ DWORD dwLink, DWORD FAR* lpdwUpdateOpt) PURE; + STDMETHOD(SetLinkSource) (THIS_ + DWORD dwLink, + LPTSTR lpszDisplayName, + ULONG lenFileName, + ULONG FAR* pchEaten, + BOOL fValidateSource) PURE; + STDMETHOD(GetLinkSource) (THIS_ + DWORD dwLink, + LPTSTR FAR* lplpszDisplayName, + ULONG FAR* lplenFileName, + LPTSTR FAR* lplpszFullLinkType, + LPTSTR FAR* lplpszShortLinkType, + BOOL FAR* lpfSourceAvailable, + BOOL FAR* lpfIsSelected) PURE; + STDMETHOD(OpenLinkSource) (THIS_ DWORD dwLink) PURE; + STDMETHOD(UpdateLink) (THIS_ + DWORD dwLink, + BOOL fErrorMessage, + BOOL fErrorAction) PURE; + STDMETHOD(CancelLink) (THIS_ DWORD dwLink) PURE; +}; + + +typedef struct tagOLEUIEDITLINKS + { + //These IN fields are standard across all OLEUI dialog functions. + DWORD cbStruct; //Structure Size + DWORD dwFlags; //IN-OUT: Flags + HWND hWndOwner; //Owning window + LPCTSTR lpszCaption; //Dialog caption bar contents + LPFNOLEUIHOOK lpfnHook; //Hook callback + LPARAM lCustData; //Custom data to pass to hook + HINSTANCE hInstance; //Instance for customized template name + LPCTSTR lpszTemplate; //Customized template name + HRSRC hResource; //Customized template handle + + //Specifics for OLEUI. All are IN-OUT unless otherwise spec. + + LPOLEUILINKCONTAINER lpOleUILinkContainer; //IN: Interface to manipulate + //links in the container + } OLEUIEDITLINKS, *POLEUIEDITLINKS, FAR *LPOLEUIEDITLINKS; + + +//API Prototype +STDAPI_(UINT) OleUIEditLinks(LPOLEUIEDITLINKS); + + +// Edit Links flags +#define ELF_SHOWHELP 0x00000001L +#define ELF_DISABLEUPDATENOW 0x00000002L +#define ELF_DISABLEOPENSOURCE 0x00000004L +#define ELF_DISABLECHANGESOURCE 0x00000008L +#define ELF_DISABLECANCELLINK 0x00000010L + +// Edit Links Dialog identifiers +#define ID_EL_CHANGESOURCE 201 +#define ID_EL_AUTOMATIC 202 +#define ID_EL_CLOSE 208 +#define ID_EL_CANCELLINK 209 +#define ID_EL_UPDATENOW 210 +#define ID_EL_OPENSOURCE 211 +#define ID_EL_MANUAL 212 +#define ID_EL_LINKSOURCE 216 +#define ID_EL_LINKTYPE 217 +#define ID_EL_UPDATE 218 +#define ID_EL_NULL -1 +#define ID_EL_LINKSLISTBOX 206 +#define ID_EL_COL1 220 +#define ID_EL_COL2 221 +#define ID_EL_COL3 222 + + + +/************************************************************************* +** CHANGE ICON DIALOG +*************************************************************************/ + +typedef struct tagOLEUICHANGEICON + { + //These IN fields are standard across all OLEUI dialog functions. + DWORD cbStruct; //Structure Size + DWORD dwFlags; //IN-OUT: Flags + HWND hWndOwner; //Owning window + LPCTSTR lpszCaption; //Dialog caption bar contents + LPFNOLEUIHOOK lpfnHook; //Hook callback + LPARAM lCustData; //Custom data to pass to hook + HINSTANCE hInstance; //Instance for customized template name + LPCTSTR lpszTemplate; //Customized template name + HRSRC hResource; //Customized template handle + + //Specifics for OLEUICHANGEICON. All are IN-OUT unless otherwise spec. + HGLOBAL hMetaPict; //Current and final image. Source of the + //icon is embedded in the metafile itself. + CLSID clsid; //IN only: class used to get Default icon + TCHAR szIconExe[OLEUI_CCHPATHMAX]; + int cchIconExe; + } OLEUICHANGEICON, *POLEUICHANGEICON, FAR *LPOLEUICHANGEICON; + + +//API prototype +STDAPI_(UINT) OleUIChangeIcon(LPOLEUICHANGEICON); + + +//Change Icon flags +#define CIF_SHOWHELP 0x00000001L +#define CIF_SELECTCURRENT 0x00000002L +#define CIF_SELECTDEFAULT 0x00000004L +#define CIF_SELECTFROMFILE 0x00000008L +#define CIF_USEICONEXE 0x0000000aL + + +//Change Icon specific error codes +#define OLEUI_CIERR_MUSTHAVECLSID (OLEUI_ERR_STANDARDMAX+0) +#define OLEUI_CIERR_MUSTHAVECURRENTMETAFILE (OLEUI_ERR_STANDARDMAX+1) +#define OLEUI_CIERR_SZICONEXEINVALID (OLEUI_ERR_STANDARDMAX+2) + + +//Change Icon Dialog identifiers +#define ID_GROUP 120 +#define ID_CURRENT 121 +#define ID_CURRENTICON 122 +#define ID_DEFAULT 123 +#define ID_DEFAULTICON 124 +#define ID_FROMFILE 125 +#define ID_FROMFILEEDIT 126 +#define ID_ICONLIST 127 +#define ID_LABEL 128 +#define ID_LABELEDIT 129 +#define ID_BROWSE 130 +#define ID_RESULTICON 132 +#define ID_RESULTLABEL 133 + +// Stringtable defines for Change Icon +#define IDS_CINOICONSINFILE 288 +#define IDS_CIINVALIDFILE 289 +#define IDS_CIFILEACCESS 290 +#define IDS_CIFILESHARE 291 +#define IDS_CIFILEOPENFAIL 292 + + + +/************************************************************************* +** CONVERT DIALOG +*************************************************************************/ + +typedef struct tagOLEUICONVERT + { + //These IN fields are standard across all OLEUI dialog functions. + DWORD cbStruct; //Structure Size + DWORD dwFlags; //IN-OUT: Flags + HWND hWndOwner; //Owning window + LPCTSTR lpszCaption; //Dialog caption bar contents + LPFNOLEUIHOOK lpfnHook; //Hook callback + LPARAM lCustData; //Custom data to pass to hook + HINSTANCE hInstance; //Instance for customized template name + LPCTSTR lpszTemplate; //Customized template name + HRSRC hResource; //Customized template handle + + //Specifics for OLEUICONVERT. All are IN-OUT unless otherwise spec. + CLSID clsid; //Class ID sent in to dialog: IN only + CLSID clsidConvertDefault; //Class ID to use as convert default: IN only + CLSID clsidActivateDefault; //Class ID to use as activate default: IN only + + CLSID clsidNew; //Selected Class ID: OUT only + DWORD dvAspect; //IN-OUT, either DVASPECT_CONTENT or + //DVASPECT_ICON + WORD wFormat; //Original data format + BOOL fIsLinkedObject; //IN only; true if object is linked + HGLOBAL hMetaPict; //IN-OUT: METAFILEPICT containing iconic aspect. + LPTSTR lpszUserType; //IN-OUT: user type name of original class. + // We'll do lookup if it's NULL. + // This gets freed on exit. + BOOL fObjectsIconChanged; // OUT; TRUE if ChangeIcon was called (and not cancelled) + LPTSTR lpszDefLabel; //IN-OUT: default label to use for icon. + // if NULL, the short user type name + // will be used. if the object is a + // link, the caller should pass the + // DisplayName of the link source + // This gets freed on exit. + + UINT cClsidExclude; //IN: No. of CLSIDs in lpClsidExclude + LPCLSID lpClsidExclude; //IN: List of CLSIDs to exclude from list + } OLEUICONVERT, *POLEUICONVERT, FAR *LPOLEUICONVERT; + + +//API prototype +STDAPI_(UINT) OleUIConvert(LPOLEUICONVERT); + +// Determine if there is at least one class that can Convert or ActivateAs +// the given clsid. +STDAPI_(BOOL) OleUICanConvertOrActivateAs( + REFCLSID rClsid, + BOOL fIsLinkedObject, + WORD wFormat +); + +//Convert Dialog flags + +// IN only: Shows "HELP" button +#define CF_SHOWHELPBUTTON 0x00000001L + +// IN only: lets you set the convert default object - the one that is +// selected as default in the convert listbox. +#define CF_SETCONVERTDEFAULT 0x00000002L + + +// IN only: lets you set the activate default object - the one that is +// selected as default in the activate listbox. + +#define CF_SETACTIVATEDEFAULT 0x00000004L + + +// IN/OUT: Selects the "Convert To" radio button, is set on exit if +// this button was selected +#define CF_SELECTCONVERTTO 0x00000008L + +// IN/OUT: Selects the "Activate As" radio button, is set on exit if +// this button was selected +#define CF_SELECTACTIVATEAS 0x00000010L +#define CF_DISABLEDISPLAYASICON 0x00000020L +#define CF_DISABLEACTIVATEAS 0x00000040L + + +//Convert specific error codes +#define OLEUI_CTERR_CLASSIDINVALID (OLEUI_ERR_STANDARDMAX+1) +#define OLEUI_CTERR_DVASPECTINVALID (OLEUI_ERR_STANDARDMAX+2) +#define OLEUI_CTERR_CBFORMATINVALID (OLEUI_ERR_STANDARDMAX+3) +#define OLEUI_CTERR_HMETAPICTINVALID (OLEUI_ERR_STANDARDMAX+4) +#define OLEUI_CTERR_STRINGINVALID (OLEUI_ERR_STANDARDMAX+5) + + +//Convert Dialog identifiers +#define IDCV_OBJECTTYPE 150 +#define IDCV_DISPLAYASICON 152 +#define IDCV_CHANGEICON 153 +#define IDCV_ACTIVATELIST 154 +#define IDCV_CONVERTTO 155 +#define IDCV_ACTIVATEAS 156 +#define IDCV_RESULTTEXT 157 +#define IDCV_CONVERTLIST 158 +#define IDCV_ICON 159 +#define IDCV_ICONLABEL1 160 +#define IDCV_ICONLABEL2 161 +#define IDCV_STXCURTYPE 162 +#define IDCV_GRPRESULT 163 +#define IDCV_STXCONVERTTO 164 + +// String IDs for Convert dialog +#define IDS_CVRESULTCONVERTLINK 500 +#define IDS_CVRESULTCONVERTTO 501 +#define IDS_CVRESULTNOCHANGE 502 +#define IDS_CVRESULTDISPLAYASICON 503 +#define IDS_CVRESULTACTIVATEAS 504 +#define IDS_CVRESULTACTIVATEDIFF 505 + + +/************************************************************************* +** BUSY DIALOG +*************************************************************************/ + +typedef struct tagOLEUIBUSY + { + //These IN fields are standard across all OLEUI dialog functions. + DWORD cbStruct; //Structure Size + DWORD dwFlags; //IN-OUT: Flags ** NOTE ** this dialog has no flags + HWND hWndOwner; //Owning window + LPCTSTR lpszCaption; //Dialog caption bar contents + LPFNOLEUIHOOK lpfnHook; //Hook callback + LPARAM lCustData; //Custom data to pass to hook + HINSTANCE hInstance; //Instance for customized template name + LPCTSTR lpszTemplate; //Customized template name + HRSRC hResource; //Customized template handle + + //Specifics for OLEUIBUSY. + HTASK hTask; //IN: HTask which is blocking + HWND FAR * lphWndDialog; //IN: Dialog's HWND is placed here + } OLEUIBUSY, *POLEUIBUSY, FAR *LPOLEUIBUSY; + +//API prototype +STDAPI_(UINT) OleUIBusy(LPOLEUIBUSY); + +// Flags for this dialog + +// IN only: Disables "Cancel" button +#define BZ_DISABLECANCELBUTTON 0x00000001L + +// IN only: Disables "Switch To..." button +#define BZ_DISABLESWITCHTOBUTTON 0x00000002L + +// IN only: Disables "Retry" button +#define BZ_DISABLERETRYBUTTON 0x00000004L + +// IN only: Generates a "Not Responding" dialog as opposed to the +// "Busy" dialog. The wording in the text is slightly different, and +// the "Cancel" button is grayed out if you set this flag. +#define BZ_NOTRESPONDINGDIALOG 0x00000008L + +// Busy specific error/return codes +#define OLEUI_BZERR_HTASKINVALID (OLEUI_ERR_STANDARDMAX+0) + +// SWITCHTOSELECTED is returned when user hit "switch to" +#define OLEUI_BZ_SWITCHTOSELECTED (OLEUI_ERR_STANDARDMAX+1) + +// RETRYSELECTED is returned when user hit "retry" +#define OLEUI_BZ_RETRYSELECTED (OLEUI_ERR_STANDARDMAX+2) + +// CALLUNBLOCKED is returned when call has been unblocked +#define OLEUI_BZ_CALLUNBLOCKED (OLEUI_ERR_STANDARDMAX+3) + +// Busy dialog identifiers +#define IDBZ_RETRY 600 +#define IDBZ_ICON 601 +#define IDBZ_MESSAGE1 602 +#define IDBZ_SWITCHTO 604 + +// Busy dialog stringtable defines +#define IDS_BZRESULTTEXTBUSY 601 +#define IDS_BZRESULTTEXTNOTRESPONDING 602 + +// Links dialog stringtable defines +#define IDS_LINK_AUTO 800 +#define IDS_LINK_MANUAL 801 +#define IDS_LINK_UNKNOWN 802 +#define IDS_LINKS 803 +#define IDS_FAILED 804 +#define IDS_CHANGESOURCE 805 +#define IDS_INVALIDSOURCE 806 +#define IDS_ERR_GETLINKSOURCE 807 +#define IDS_ERR_GETLINKUPDATEOPTIONS 808 +#define IDS_ERR_ADDSTRING 809 +#define IDS_CHANGEADDITIONALLINKS 810 +#define IDS_CLOSE 811 + + +/************************************************************************* +** PROMPT USER DIALOGS +*************************************************************************/ +#define ID_PU_LINKS 900 +#define ID_PU_TEXT 901 +#define ID_PU_CONVERT 902 +#define ID_PU_BROWSE 904 +#define ID_PU_METER 905 +#define ID_PU_PERCENT 906 +#define ID_PU_STOP 907 + +// used for -1 ids in dialogs: +#define ID_DUMMY 999 + +/* inside ole2ui.c */ +#ifdef __cplusplus +extern "C" +#endif +int EXPORT FAR CDECL OleUIPromptUser(int nTemplate, HWND hwndParent, ...); + +#define UPDATELINKS_STARTDELAY 2000 // Delay before 1st link updates + // to give the user a chance to + // dismiss the dialog before any + // links update. + +STDAPI_(BOOL) OleUIUpdateLinks( + LPOLEUILINKCONTAINER lpOleUILinkCntr, + HWND hwndParent, + LPTSTR lpszTitle, + int cLinks); + + +/************************************************************************* +** OLE OBJECT FEEDBACK EFFECTS +*************************************************************************/ + +#define OLEUI_HANDLES_USEINVERSE 0x00000001L +#define OLEUI_HANDLES_NOBORDER 0x00000002L +#define OLEUI_HANDLES_INSIDE 0x00000004L +#define OLEUI_HANDLES_OUTSIDE 0x00000008L + + +#define OLEUI_SHADE_FULLRECT 1 +#define OLEUI_SHADE_BORDERIN 2 +#define OLEUI_SHADE_BORDEROUT 3 + +/* objfdbk.c function prototypes */ +STDAPI_(void) OleUIDrawHandles(LPRECT lpRect, HDC hdc, DWORD dwFlags, UINT cSize, BOOL fDraw); +STDAPI_(void) OleUIDrawShading(LPRECT lpRect, HDC hdc, DWORD dwFlags, UINT cWidth); +STDAPI_(void) OleUIShowObject(LPCRECT lprc, HDC hdc, BOOL fIsLink); + + +/************************************************************************* +** Hatch window definitions and prototypes ** +*************************************************************************/ +#define DEFAULT_HATCHBORDER_WIDTH 4 + +STDAPI_(BOOL) RegisterHatchWindowClass(HINSTANCE hInst); +STDAPI_(HWND) CreateHatchWindow(HWND hWndParent, HINSTANCE hInst); +STDAPI_(UINT) GetHatchWidth(HWND hWndHatch); +STDAPI_(void) GetHatchRect(HWND hWndHatch, LPRECT lpHatchRect); +STDAPI_(void) SetHatchRect(HWND hWndHatch, LPRECT lprcHatchRect); +STDAPI_(void) SetHatchWindowSize( + HWND hWndHatch, + LPRECT lprcIPObjRect, + LPRECT lprcClipRect, + LPPOINT lpptOffset +); + + + +/************************************************************************* +** VERSION VERIFICATION INFORMATION +*************************************************************************/ + +// The following magic number is used to verify that the resources we bind +// to our EXE are the same "version" as the LIB (or DLL) file which +// contains these routines. This is not the same as the Version information +// resource that we place in OLE2UI.RC, this is a special ID that we will +// have compiled in to our EXE. Upon initialization of OLE2UI, we will +// look in our resources for an RCDATA called "VERIFICATION" (see OLE2UI.RC), +// and make sure that the magic number there equals the magic number below. + +#define OLEUI_VERSION_MAGIC 0x4D42 + +#endif //_OLE2UI_H_ diff --git a/private/oleutest/letest/ole2ui/ole2ui.mak b/private/oleutest/letest/ole2ui/ole2ui.mak new file mode 100644 index 000000000..f8308fa23 --- /dev/null +++ b/private/oleutest/letest/ole2ui/ole2ui.mak @@ -0,0 +1,272 @@ +# ============================================================================ +# File: OLE2UI.MAK +# +# NMAKE description file to build STATIC version of OLE2.0 User Interface LIB +# +# Copyright (C) Microsoft Corporation, 1992-1993. All Rights Reserved. +# ============================================================================ +# +# Usage Notes: +# ----------- +# +# This makefile is designed to be used in one step. This makefile does +# NOT use the file called UIMAKE.INI. This makefile builds the OLE2UI.LIB +# library. It is NOT necessary to build custom versions of the static +# library version of OLE2UI. Everyone can use the same OLE2UI.LIB library +# as built by this makefile. +# +# NMAKE -F OLE2UI.MAK +# +# +# The following lists a few of the settings in this makefile file which +# you might change, and what effect those changes might have. For a +# complete listing of all the available options and how they are used, +# see the makefile below. +# +# MODEL=[S|M|C|L] -- The memory model. +# +# ============================================================================ + + +# ---------------------------------------------------------------------------- +# U I M A K E . I N I +# ---------------------------------------------------------------------------- +DOS=1 + +# Make a static library called OLE2UI.LIB +DEBUG=0 +MODEL=M +RESOURCE=RESOURCE + +!ifndef REL_DIR +REL_DIR=c:\ole2samp\release +!endif +!ifndef OLERELDIR +OLEREL_DIR=c:\ole2samp\release +!endif + +!if "$(INSTALL_DIR)"=="" +INSTALL_DIR = $(REL_DIR) +!endif + +# ---------------------------------------------------------------------------- +# O B J E C T F I L E L I S T +# ---------------------------------------------------------------------------- + +UI_COBJS = \ + D^\busy.obj\ + D^\common.obj\ + D^\convert.obj\ + D^\dbgutil.obj\ + D^\drawicon.obj\ + D^\hatch.obj\ + D^\icon.obj\ + D^\iconbox.obj\ + D^\insobj.obj\ + D^\links.obj\ + D^\msgfiltr.obj\ + D^\enumfetc.obj\ + D^\enumstat.obj\ + D^\objfdbk.obj\ + D^\ole2ui.obj\ + D^\olestd.obj\ + D^\targtdev.obj\ + D^\oleutl.obj\ + D^\pastespl.obj\ + D^\regdb.obj\ + D^\resimage.obj\ + D^\utility.obj\ + +UI_NOPCOBJS = \ + D^\geticon.obj\ + D^\dballoc.obj\ + D^\suminfo.obj\ + D^\stdpal.obj\ + +PRECOMPOBJ= $(O)precomp.obj + +PRECOMP=$(O)precomp.pch + +!if ("$(DEBUG)"=="1") +MSG=DEBUG Static LIB Version +LIBNAME=$(MODEL)OLE2UID +CFLAGS=-c -Od -GA2s -W3 -Zpei -A$(MODEL) -D_DEBUG +RFLAGS=-D DEBUG +LFLAGS=/MAP:FULL /CO /LINE /NOD /NOE /SE:300 /NOPACKCODE +UILIBS=mlibcew libw ole2 storage shell commdlg toolhelp +CC=cl +AS=masm +RS=rc +LK=link +OBJ=DEBUGLIB +LIBOBJS = $(UI_COBJS:D^\=DEBUGLIB^\) $(UI_NOPCOBJS:D^\=DEBUGLIB\NOPC^\) + +!else + +MSG=RETAIL Static LIB Version +LIBNAME=$(MODEL)OLE2UI +CFLAGS=-c -Os -GA2s -W3 -Zpe -A$(MODEL) +RFLAGS= +LFLAGS=/MAP:FULL /LINE /NOD /NOE /SE:300 /NOPACKCODE +UILIBS=mlibcew libw ole2 storage shell commdlg toolhelp +CC=cl +AS=masm +RS=rc +LK=link +OBJ=RETAILIB +LIBOBJS = $(UI_COBJS:D^\=RETAILIB^\) $(UI_NOPCOBJS:D^\=RETAILIB\NOPC^\) + +!endif + +!if [if not exist $(OBJ)\*. md $(OBJ) >nul] +!error Object subdirectory $(OBJ)\ could not be created +!endif +!if [if not exist $(OBJ)\NOPC\*. md $(OBJ)\NOPC > nul] +!error non-precompiled header object subdirectory $(OBJ)\NOPC\ could not be created +!endif + +# ---------------------------------------------------------------------------- +# R E S O U R C E L I S T +# ---------------------------------------------------------------------------- +RES = \ + busy.h \ + common.h \ + convert.h \ + edlinks.h \ + geticon.h \ + icon.h \ + iconbox.h \ + insobj.h \ + msgfiltr.h \ + enumfetc.h \ + ole2ui.h \ + pastespl.h \ + resimage.h \ + dballoc.h \ + suminfo.h \ + stdpal.h \ + + +.SUFFIXES: .c .cpp .obj + +O=.\$(OBJ)^\ + +GOAL: PRELUDE $(LIBNAME).LIB + +# ---------------------------------------------------------------------------- +# I N F E R E N C E R U L E S +# ---------------------------------------------------------------------------- + +# compile C file without precompiled headers into object directory\NOPC +# dont compile c files etc for lcoalized builds. +{}.c{$(O)NOPC\}.obj: + @echo °°°°°°°°°°°°°°°°°°°°°°°°° Compiling $(@B).c °°°°°°°°°°°°°°°°°°°°°°°°° +!ifdef DOS + SET CL=$(CFLAGS) + $(CC) -Fo$(O)NOPC\$(@B) $(@B).c +!else + $(CC) $(CFLAGS) -D_FILE_=\"$(*B).c\" -Fo$(O)NOPC\$(@B) $(@B).c +!endif + +# compile C file into object directory +{}.c{$(O)}.obj: + @echo °°°°°°°°°°°°°°°°°°°°°°°°° Compiling $(@B).c °°°°°°°°°°°°°°°°°°°°°°°°° +!ifdef DOS + SET CL=$(CFLAGS) -Yuole2ui.h -Fp$(O)precomp.pch + $(CC) -Fo$(O)$(@B) $(@B).c +!else + $(CC) $(CFLAGS) -Yuole2ui.h -Fp$(O)precomp.pch -D_FILE_=\"$(*B).c\" -Fo$(O)$(@B) $(@B).c +!endif + +# compile CPP file without precompiled headers into object directory\NOPC +# dont compile cpp files etc for lcoalized builds. +{}.cpp{$(O)NOPC\}.obj: + @echo °°°°°°°°°°°°°°°°°°°°°°°°° Compiling $(@B).cpp °°°°°°°°°°°°°°°°°°°°°°°°° +!ifdef DOS + SET CL=$(CFLAGS) + $(CC) -Fo$(O)NOPC\$(@B) $(@B).cpp +!else + $(CC) $(CFLAGS) -D_FILE_=\"$(*B).cpp\" -Fo$(O)NOPC\$(@B) $(@B).cpp +!endif + +# compile CPP file into object directory +{}.cpp{$(O)}.obj: + @echo °°°°°°°°°°°°°°°°°°°°°°°°° Compiling $(@B).cpp °°°°°°°°°°°°°°°°°°°°°°°°° +!ifdef DOS + SET CL=$(CFLAGS) -Yuole2ui.h -Fp$(O)precomp.pch + $(CC) -Fo$(O)$(@B) $(@B).cpp +!else + $(CC) $(CFLAGS) -Yuole2ui.h -Fp$(O)precomp.pch -D_FILE_=\"$(*B).cpp\" -Fo$(O)$(@B) $(@B).cpp +!endif + + +# ---------------------------------------------------------------------------- +# D E P E N D F I L E C R E A T I O N +# ---------------------------------------------------------------------------- +UI_CFILE = $(UI_COBJS:.obj=.c) $(UI_DLLOBJS:.obj=.c) +UI_NOPCFILE = $(UI_NOPCOBJS:.obj=.c) +DEPEND: nul + @echo Making a NEW dependancy file. + mkdep -p $$(O) -s .obj $(UI_CFILE:D^\=) > tmp.tmp + sed "s/:/: $$(PRECOMP)/g" < tmp.tmp > depend + -del tmp.tmp + mkdep -p $$(O)NOPC\ -s .obj $(UI_NOPCFILE:D^\=) >> depend + mkdep -p $$(O) -s .pch precomp.c >> depend + +# ---------------------------------------------------------------------------- +# W E L C O M E B A N N E R +# ---------------------------------------------------------------------------- +PRELUDE: + @echo ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» + @echo º Makefile for UILibrary º + @echo ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ + @echo $(MSG) +!ifndef SRCTOK + set INCLUDE=$(OLEREL_DIR);$(INCLUDE) + set LIB=$(OLEREL_DIR);$(LIB) +!endif + + +# ---------------------------------------------------------------------------- +# G O A L T A R G E T S +# ---------------------------------------------------------------------------- +!include "depend" + +CLEAN: CleanUp GOAL +CleanUp: + -echo y|del .\$(OBJ)\*.* + -del $(LIBNAME).lib + +$(O)precomp.pch: precomp.c +!ifdef DOS + SET CL=$(CFLAGS) -Fp$(O)precomp.pch -Ycole2ui.h + $(CC) -Fo$(O)$(@B) precomp.c +!else + $(CC) $(CFLAGS) -Fp$(O)precomp.pch -Ycole2ui.h -D_FILE_=\"precomp.c\" -Fo$(O)$(@B) precomp.c +!endif + +# +# Build .LIB static library +# + +$(LIBNAME).lib: $(LIBOBJS) $(PRECOMPOBJ) + -del $(O)$(LIBNAME).lib + lib @<< +$(O)$(LIBNAME).lib +y +$(PRECOMPOBJ: = +) $(LIBOBJS: = +) + +<< + copy $(O)$(LIBNAME).lib $(LIBNAME).lib + + +# install built library to $(INSTALL_DIR) dir +install: + copy $(LIBNAME).lib $(INSTALL_DIR) + copy ole2ui.h $(INSTALL_DIR) + copy olestd.h $(INSTALL_DIR) + copy msgfiltr.h $(INSTALL_DIR) + copy enumfetc.h $(INSTALL_DIR) + copy uiclass.h $(INSTALL_DIR) + +# EOF ======================================================================== diff --git a/private/oleutest/letest/ole2ui/ole2ui.rc b/private/oleutest/letest/ole2ui/ole2ui.rc new file mode 100644 index 000000000..469608e3d --- /dev/null +++ b/private/oleutest/letest/ole2ui/ole2ui.rc @@ -0,0 +1,65 @@ +/* + * OLE2UI.RC + * + * Icon, menus, strings, and dialogs for the OLE 2.0 UI Support Library. + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + +#undef PURE + +//fix bug when building on daytona 567 +//BUGBUG: this is hacky, we need a better long term solution, the basic +//problem is that the rpc header file makes rc choke and die +#define __RPCNDR_H__ + +#include "ole2ui.h" + +#if defined( IBCLS ) +#define SZCLASSICONBOX IBCLS +#define SZCLASSRESULTIMAGE RICLS +#endif + +/* If "IBCLS" and "RICLS" are NOT defined as command line arguments to the + * RC command, then we assume there is a "uiclass.h" file which defines the + * two symbols "SZCLASSICONBOX" and "SZCLASSRESULTIMAGE". These need to be + * unique strings; they are normally built by composing the name of the + * "LIBNAME" or "APPNAME" with the strings "IBCls" and "RICls" + * respectively. + */ +#if !defined( SZCLASSICONBOX ) +#include "uiclass.h" +#endif + +//Default 'document' icon +//DefIcon ICON default.ico + +//Bitmaps for ResultImage control +IDB_RESULTSEGA BITMAP egares.bmp +IDB_RESULTSVGA BITMAP vgares.bmp +IDB_RESULTSHIRESVGA BITMAP hivgares.bmp + +// Version Verification Resource (see OLE2UI.H) +VERIFICATION RCDATA + BEGIN + OLEUI_VERSION_MAGIC + END + +//Include string tables here. +#include "strings.rc" + +//Include each dialog template here. +#include "insobj.dlg" +#include "icon.dlg" +#include "links.dlg" +#include "pastespl.dlg" +#include "busy.dlg" +#include "convert.dlg" +#include "fileopen.dlg" +#include "prompt.dlg" + +// Only include the version resource if we are compiling the DLL version +#ifdef DLL_VER +//Version Information +#include "OLE2UI.RCV" +#endif diff --git a/private/oleutest/letest/ole2ui/olestd.c b/private/oleutest/letest/ole2ui/olestd.c new file mode 100644 index 000000000..d41a42b8d --- /dev/null +++ b/private/oleutest/letest/ole2ui/olestd.c @@ -0,0 +1,3048 @@ +/************************************************************************* +** +** OLE 2 Standard Utilities +** +** olestd.c +** +** This file contains utilities that are useful for most standard +** OLE 2.0 compound document type applications. +** +** (c) Copyright Microsoft Corp. 1992 All Rights Reserved +** +*************************************************************************/ + +// #define NONAMELESSUNION // use strict ANSI standard (for DVOBJ.H) + +#define STRICT 1 +#include "ole2ui.h" +#include +#include +#include +#include "regdb.h" +#include "geticon.h" +#include "common.h" + +OLEDBGDATA + +static TCHAR szAssertMemAlloc[] = TEXT("CoGetMalloc failed"); + +static int IsCloseFormatEtc(FORMATETC FAR* pFetcLeft, FORMATETC FAR* pFetcRight); + + +/* OleStdSetupAdvises +** ------------------ +** Setup the standard View advise required by a standard, +** compound document-oriented container. Such a container relies on +** Ole to manage the presentation of the Ole object. The container +** call IViewObject::Draw to render (display) the object. +** +** This helper routine performs the following tasks: +** setup View advise +** Call IOleObject::SetHostNames +** Call OleSetContainedObject +** +** fCreate should be set to TRUE if the object is being created. if +** an existing object is being loaded, then fCreate should be FALSE. +** if it is a creation situation, then the ADVF_PRIMEFIRST flag is +** used when settinp up the IViewObject::Advise. This will result in +** the immediate sending of the initial picture. +** +** OLE2NOTE: the standard container does NOT need to set up an OLE +** Advise (IOleObject::Advise). this routine does NOT set up an OLE +** Advise (a previous version of this function used to setup this +** advise, but it was not useful). +*/ +STDAPI_(BOOL) OleStdSetupAdvises(LPOLEOBJECT lpOleObject, DWORD dwDrawAspect, + LPTSTR lpszContainerApp, LPTSTR lpszContainerObj, + LPADVISESINK lpAdviseSink, BOOL fCreate) +{ + LPVIEWOBJECT lpViewObject; + HRESULT hrErr; + BOOL fStatus = TRUE; +#if defined( SPECIAL_CONTAINER ) + DWORD dwTemp; +#endif + + hrErr = lpOleObject->lpVtbl->QueryInterface( + lpOleObject, + &IID_IViewObject, + (LPVOID FAR*)&lpViewObject + ); + + /* Setup View advise */ + if (hrErr == NOERROR) { + + OLEDBG_BEGIN2(TEXT("IViewObject::SetAdvise called\r\n")) + lpViewObject->lpVtbl->SetAdvise( + lpViewObject, + dwDrawAspect, + (fCreate ? ADVF_PRIMEFIRST : 0), + lpAdviseSink + ); + OLEDBG_END2 + + OleStdRelease((LPUNKNOWN)lpViewObject); + } else { + fStatus = FALSE; + } + +#if defined( SPECIAL_CONTAINER ) + /* Setup OLE advise. + ** OLE2NOTE: normally containers do NOT need to setup an OLE + ** advise. this advise connection is only useful for the OLE's + ** DefHandler and the OleLink object implementation. some + ** special container's might need to setup this advise for + ** programatic reasons. + ** + ** NOTE: this advise will be torn down automatically by the + ** server when we release the object, therefore we do not need + ** to store the connection id. + */ + OLEDBG_BEGIN2(TEXT("IOleObject::Advise called\r\n")) + hrErr = lpOleObject->lpVtbl->Advise( + lpOleObject, + lpAdviseSink, + (DWORD FAR*)&dwTemp + ); + OLEDBG_END2 + if (hrErr != NOERROR) fStatus = FALSE; +#endif + + /* Setup the host names for the OLE object. */ + OLEDBG_BEGIN2(TEXT("IOleObject::SetHostNames called\r\n")) + + hrErr = CallIOleObjectSetHostNamesA( + lpOleObject, + lpszContainerApp, + lpszContainerObj + ); + + OLEDBG_END2 + + if (hrErr != NOERROR) fStatus = FALSE; + + /* Inform the loadded object's handler/inproc-server that it is in + ** its embedding container's process. + */ + OLEDBG_BEGIN2(TEXT("OleSetContainedObject(TRUE) called\r\n")) + OleSetContainedObject((LPUNKNOWN)lpOleObject, TRUE); + OLEDBG_END2 + + return fStatus; +} + + +/* OleStdSwitchDisplayAspect +** ------------------------- +** Switch the currently cached display aspect between DVASPECT_ICON +** and DVASPECT_CONTENT. +** +** NOTE: when setting up icon aspect, any currently cached content +** cache is discarded and any advise connections for content aspect +** are broken. +** +** RETURNS: +** S_OK -- new display aspect setup successfully +** E_INVALIDARG -- IOleCache interface is NOT supported (this is +** required). +** -- any SCODE that can be returned by +** IOleCache::Cache method. +** NOTE: if an error occurs then the current display aspect and +** cache contents unchanged. +*/ +STDAPI OleStdSwitchDisplayAspect( + LPOLEOBJECT lpOleObj, + LPDWORD lpdwCurAspect, + DWORD dwNewAspect, + HGLOBAL hMetaPict, + BOOL fDeleteOldAspect, + BOOL fSetupViewAdvise, + LPADVISESINK lpAdviseSink, + BOOL FAR* lpfMustUpdate +) +{ + LPOLECACHE lpOleCache = NULL; + LPVIEWOBJECT lpViewObj = NULL; + LPENUMSTATDATA lpEnumStatData = NULL; + STATDATA StatData; + FORMATETC FmtEtc; + STGMEDIUM Medium; + DWORD dwAdvf; + DWORD dwNewConnection; + DWORD dwOldAspect = *lpdwCurAspect; + HRESULT hrErr; + + if (lpfMustUpdate) + *lpfMustUpdate = FALSE; + + lpOleCache = (LPOLECACHE)OleStdQueryInterface( + (LPUNKNOWN)lpOleObj,&IID_IOleCache); + + // if IOleCache* is NOT available, do nothing + if (! lpOleCache) + return ResultFromScode(E_INVALIDARG); + + // Setup new cache with the new aspect + FmtEtc.cfFormat = (CLIPFORMAT) NULL; // whatever is needed to draw + FmtEtc.ptd = NULL; + FmtEtc.dwAspect = dwNewAspect; + FmtEtc.lindex = -1; + FmtEtc.tymed = TYMED_NULL; + + /* OLE2NOTE: if we are setting up Icon aspect with a custom icon + ** then we do not want DataAdvise notifications to ever change + ** the contents of the data cache. thus we set up a NODATA + ** advise connection. otherwise we set up a standard DataAdvise + ** connection. + */ + if (dwNewAspect == DVASPECT_ICON && hMetaPict) + dwAdvf = ADVF_NODATA; + else + dwAdvf = ADVF_PRIMEFIRST; + + OLEDBG_BEGIN2(TEXT("IOleCache::Cache called\r\n")) + hrErr = lpOleCache->lpVtbl->Cache( + lpOleCache, + (LPFORMATETC)&FmtEtc, + dwAdvf, + (LPDWORD)&dwNewConnection + ); + OLEDBG_END2 + + if (! SUCCEEDED(hrErr)) { + OleDbgOutHResult(TEXT("IOleCache::Cache returned"), hrErr); + OleStdRelease((LPUNKNOWN)lpOleCache); + return hrErr; + } + + *lpdwCurAspect = dwNewAspect; + + /* OLE2NOTE: if we are setting up Icon aspect with a custom icon, + ** then stuff the icon into the cache. otherwise the cache must + ** be forced to be updated. set the *lpfMustUpdate flag to tell + ** caller to force the object to Run so that the cache will be + ** updated. + */ + if (dwNewAspect == DVASPECT_ICON && hMetaPict) { + + FmtEtc.cfFormat = CF_METAFILEPICT; + FmtEtc.ptd = NULL; + FmtEtc.dwAspect = DVASPECT_ICON; + FmtEtc.lindex = -1; + FmtEtc.tymed = TYMED_MFPICT; + + Medium.tymed = TYMED_MFPICT; + Medium.hGlobal = hMetaPict; + Medium.pUnkForRelease = NULL; + + OLEDBG_BEGIN2(TEXT("IOleCache::SetData called\r\n")) + hrErr = lpOleCache->lpVtbl->SetData( + lpOleCache, + (LPFORMATETC)&FmtEtc, + (LPSTGMEDIUM)&Medium, + FALSE /* fRelease */ + ); + OLEDBG_END2 + } else { + if (lpfMustUpdate) + *lpfMustUpdate = TRUE; + } + + if (fSetupViewAdvise && lpAdviseSink) { + /* OLE2NOTE: re-establish the ViewAdvise connection */ + lpViewObj = (LPVIEWOBJECT)OleStdQueryInterface( + (LPUNKNOWN)lpOleObj,&IID_IViewObject); + + if (lpViewObj) { + + OLEDBG_BEGIN2(TEXT("IViewObject::SetAdvise called\r\n")) + lpViewObj->lpVtbl->SetAdvise( + lpViewObj, + dwNewAspect, + 0, + lpAdviseSink + ); + OLEDBG_END2 + + OleStdRelease((LPUNKNOWN)lpViewObj); + } + } + + /* OLE2NOTE: remove any existing caches that are set up for the old + ** display aspect. It WOULD be possible to retain the caches set + ** up for the old aspect, but this would increase the storage + ** space required for the object and possibly require additional + ** overhead to maintain the unused cachaes. For these reasons the + ** strategy to delete the previous caches is prefered. if it is a + ** requirement to quickly switch between Icon and Content + ** display, then it would be better to keep both aspect caches. + */ + + if (fDeleteOldAspect) { + OLEDBG_BEGIN2(TEXT("IOleCache::EnumCache called\r\n")) + hrErr = lpOleCache->lpVtbl->EnumCache( + lpOleCache, + (LPENUMSTATDATA FAR*)&lpEnumStatData + ); + OLEDBG_END2 + + while(hrErr == NOERROR) { + hrErr = lpEnumStatData->lpVtbl->Next( + lpEnumStatData, + 1, + (LPSTATDATA)&StatData, + NULL + ); + if (hrErr != NOERROR) + break; // DONE! no more caches. + + if (StatData.formatetc.dwAspect == dwOldAspect) { + + // Remove previous cache with old aspect + OLEDBG_BEGIN2(TEXT("IOleCache::Uncache called\r\n")) + lpOleCache->lpVtbl->Uncache(lpOleCache,StatData.dwConnection); + OLEDBG_END2 + } + } + + if (lpEnumStatData) { + OleStdVerifyRelease( + (LPUNKNOWN)lpEnumStatData, + TEXT("OleStdSwitchDisplayAspect: Cache enumerator NOT released") + ); + } + } + + if (lpOleCache) + OleStdRelease((LPUNKNOWN)lpOleCache); + + return NOERROR; +} + + +/* OleStdSetIconInCache +** -------------------- +** SetData a new icon into the existing DVASPECT_ICON cache. +** +** RETURNS: +** HRESULT returned from IOleCache::SetData +*/ +STDAPI OleStdSetIconInCache(LPOLEOBJECT lpOleObj, HGLOBAL hMetaPict) +{ + LPOLECACHE lpOleCache = NULL; + FORMATETC FmtEtc; + STGMEDIUM Medium; + HRESULT hrErr; + + if (! hMetaPict) + return FALSE; // invalid icon + + lpOleCache = (LPOLECACHE)OleStdQueryInterface( + (LPUNKNOWN)lpOleObj,&IID_IOleCache); + if (! lpOleCache) + return FALSE; // if IOleCache* is NOT available, do nothing + + FmtEtc.cfFormat = CF_METAFILEPICT; + FmtEtc.ptd = NULL; + FmtEtc.dwAspect = DVASPECT_ICON; + FmtEtc.lindex = -1; + FmtEtc.tymed = TYMED_MFPICT; + + // stuff the icon into the cache. + Medium.tymed = TYMED_MFPICT; + Medium.hGlobal = hMetaPict; + Medium.pUnkForRelease = NULL; + + OLEDBG_BEGIN2(TEXT("IOleCache::SetData called\r\n")) + hrErr = lpOleCache->lpVtbl->SetData( + lpOleCache, + (LPFORMATETC)&FmtEtc, + (LPSTGMEDIUM)&Medium, + FALSE /* fRelease */ + ); + OLEDBG_END2 + + OleStdRelease((LPUNKNOWN)lpOleCache); + + return hrErr; +} + + + +/* OleStdDoConvert +** --------------- +** Do the container-side responsibilities for converting an object. +** This function would be used in conjunction with the OleUIConvert +** dialog. If the user selects to convert an object then the +** container must do the following: +** 1. unload the object. +** 2. write the NEW CLSID and NEW user type name +** string into the storage of the object, +** BUT write the OLD format tag. +** 3. force an update of the object to force the actual +** conversion of the data bits. +** +** This function takes care of step 2. +*/ +STDAPI OleStdDoConvert(LPSTORAGE lpStg, REFCLSID rClsidNew) +{ + HRESULT error; + CLSID clsidOld; + CLIPFORMAT cfOld; + LPTSTR lpszOld = NULL; + TCHAR szNew[OLEUI_CCHKEYMAX]; + + if ((error = ReadClassStg(lpStg, &clsidOld)) != NOERROR) { + clsidOld = CLSID_NULL; + goto errRtn; + } + + // read old fmt/old user type; sets out params to NULL on error + { + LPOLESTR polestr; + + error = ReadFmtUserTypeStg(lpStg, &cfOld, &polestr); + + CopyAndFreeOLESTR(polestr, &lpszOld); + } + + OleDbgAssert(error == NOERROR || (cfOld == 0 && lpszOld == NULL)); + + // get new user type name; if error, set to NULL string + if (OleStdGetUserTypeOfClass( + // (LPCLSID) + rClsidNew, szNew,sizeof(szNew),NULL /* hKey */) == 0) + szNew[0] = TEXT('\0'); + + // write class stg + if ((error = WriteClassStg(lpStg, rClsidNew)) != NOERROR) + goto errRtn; + + // write old fmt/new user type; +#ifdef UNICODE + if ((error = WriteFmtUserTypeStg(lpStg, cfOld, szNew)) != NOERROR) + goto errRewriteInfo; +#else + { + // Chicago OLE is using UNICODE, so we need to convert the string to + // UNICODE. + WCHAR szNewT[OLEUI_CCHKEYMAX]; + mbstowcs(szNewT, szNew, sizeof(szNew)); + if ((error = WriteFmtUserTypeStg(lpStg, cfOld, szNewT)) != NOERROR) + goto errRewriteInfo; + } +#endif + + // set convert bit + if ((error = SetConvertStg(lpStg, TRUE)) != NOERROR) + goto errRewriteInfo; + + goto okRtn; + +errRewriteInfo: + (void)WriteClassStg(lpStg, &clsidOld); + + (void)WriteFmtUserTypeStgA(lpStg, cfOld, lpszOld); + +errRtn: + +okRtn: + OleStdFreeString(lpszOld, NULL); + return error; +} + + +/* OleStdGetTreatAsFmtUserType +** --------------------------- +** Determine if the application should perform a TreatAs (ActivateAs +** object or emulation) operation for the object that is stored in +** the storage. +** +** if the CLSID written in the storage is not the same as the +** application's own CLSID (clsidApp), then a TreatAs operation +** should take place. if so determine the format the data should be +** written and the user type name of the object the app should +** emulate (ie. pretend to be). if this information is not written +** in the storage then it is looked up in the REGDB. if it can not +** be found in the REGDB, then the TreatAs operation can NOT be +** executed. +** +** RETURNS: TRUE -- if TreatAs should be performed. +** valid lpclsid, lplpszType, lpcfFmt to TreatAs are returned +** (NOTE: lplpszType must be freed by caller) +** FALSE -- NO TreatAs. lpszType will be NULL. +** lpclsid = CLSID_NULL; lplpszType = lpcfFmt = NULL; +*/ +STDAPI_(BOOL) OleStdGetTreatAsFmtUserType( + REFCLSID rclsidApp, + LPSTORAGE lpStg, + CLSID FAR* lpclsid, + CLIPFORMAT FAR* lpcfFmt, + LPTSTR FAR* lplpszType +) +{ + HRESULT hrErr; + HKEY hKey; + LONG lRet; + UINT lSize; + TCHAR szBuf[OLEUI_CCHKEYMAX]; + + *lpclsid = CLSID_NULL; + *lpcfFmt = 0; + *lplpszType = NULL; + + hrErr = ReadClassStg(lpStg, lpclsid); + if (hrErr == NOERROR && + ! IsEqualCLSID(lpclsid, &CLSID_NULL) && + ! IsEqualCLSID(lpclsid, rclsidApp)) { + + hrErr = ReadFmtUserTypeStgA(lpStg,(CLIPFORMAT FAR*)lpcfFmt, lplpszType); + + if (hrErr == NOERROR && lplpszType && *lpcfFmt != 0) + return TRUE; // Do TreatAs. info was in lpStg. + + /* read info from REGDB + ** *lpcfFmt = value of field: CLSID\{...}\DataFormats\DefaultFile + ** *lplpszType = value of field: CLSID\{...} + */ + //Open up the root key. + lRet=RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hKey); + if (lRet != (LONG)ERROR_SUCCESS) + return FALSE; + *lpcfFmt = OleStdGetDefaultFileFormatOfClass(lpclsid, hKey); + if (*lpcfFmt == 0) + return FALSE; + lSize = OleStdGetUserTypeOfClass(lpclsid,szBuf,sizeof(szBuf),hKey); + if (lSize == 0) + return FALSE; + *lplpszType = OleStdCopyString(szBuf, NULL); + } else { + return FALSE; // NO TreatAs + } +} + + + +/* OleStdDoTreatAsClass +** -------------------- +** Do the container-side responsibilities for "ActivateAs" (aka. +** TreatAs) for an object. +** This function would be used in conjunction with the OleUIConvert +** dialog. If the user selects to ActivateAs an object then the +** container must do the following: +** 1. unload ALL objects of the OLD class that app knows about +** 2. add the TreatAs tag in the registration database +** by calling CoTreatAsClass(). +** 3. lazily it can reload the objects; when the objects +** are reloaded the TreatAs will take effect. +** +** This function takes care of step 2. +*/ +STDAPI OleStdDoTreatAsClass(LPTSTR lpszUserType, REFCLSID rclsid, REFCLSID rclsidNew) +{ + HRESULT hrErr; + LPTSTR lpszCLSID = NULL; + LONG lRet; + HKEY hKey; + + OLEDBG_BEGIN2(TEXT("CoTreatAsClass called\r\n")) + hrErr = CoTreatAsClass(rclsid, rclsidNew); + OLEDBG_END2 + + if ((hrErr != NOERROR) && lpszUserType) { + lRet = RegOpenKey(HKEY_CLASSES_ROOT, (LPCTSTR) TEXT("CLSID"), + (HKEY FAR *)&hKey); + StringFromCLSIDA(rclsid, &lpszCLSID); + + RegSetValue(hKey, lpszCLSID, REG_SZ, lpszUserType, + lstrlen(lpszUserType)); + + if (lpszCLSID) + OleStdFreeString(lpszCLSID, NULL); + + hrErr = CoTreatAsClass(rclsid, rclsidNew); + RegCloseKey(hKey); + } + + return hrErr; +} + + + +/* OleStdIsOleLink +** --------------- +** Returns TRUE if the OleObject is infact an OLE link object. this +** checks if IOleLink interface is supported. if so, the object is a +** link, otherwise not. +*/ +STDAPI_(BOOL) OleStdIsOleLink(LPUNKNOWN lpUnk) +{ + LPOLELINK lpOleLink; + + lpOleLink = (LPOLELINK)OleStdQueryInterface(lpUnk, &IID_IOleLink); + + if (lpOleLink) { + OleStdRelease((LPUNKNOWN)lpOleLink); + return TRUE; + } else + return FALSE; +} + + +/* OleStdQueryInterface +** -------------------- +** Returns the desired interface pointer if exposed by the given object. +** Returns NULL if the interface is not available. +** eg.: +** lpDataObj = OleStdQueryInterface(lpOleObj, &IID_DataObject); +*/ +STDAPI_(LPUNKNOWN) OleStdQueryInterface(LPUNKNOWN lpUnk, REFIID riid) +{ + LPUNKNOWN lpInterface; + HRESULT hrErr; + + hrErr = lpUnk->lpVtbl->QueryInterface( + lpUnk, + riid, + (LPVOID FAR*)&lpInterface + ); + + if (hrErr == NOERROR) + return lpInterface; + else + return NULL; +} + + +/* OleStdGetData +** ------------- +** Retrieve data from an IDataObject in a specified format on a +** global memory block. This function ALWAYS returns a private copy +** of the data to the caller. if necessary a copy is made of the +** data (ie. if lpMedium->pUnkForRelease != NULL). The caller assumes +** ownership of the data block in all cases and must free the data +** when done with it. The caller may directly free the data handle +** returned (taking care whether it is a simple HGLOBAL or a HANDLE +** to a MetafilePict) or the caller may call +** ReleaseStgMedium(lpMedium). this OLE helper function will do the +** right thing. +** +** PARAMETERS: +** LPDATAOBJECT lpDataObj -- object on which GetData should be +** called. +** CLIPFORMAT cfFormat -- desired clipboard format (eg. CF_TEXT) +** DVTARGETDEVICE FAR* lpTargetDevice -- target device for which +** the data should be composed. This may +** be NULL. NULL can be used whenever the +** data format is insensitive to target +** device or when the caller does not care +** what device is used. +** LPSTGMEDIUM lpMedium -- ptr to STGMEDIUM struct. the +** resultant medium from the +** IDataObject::GetData call is +** returned. +** +** RETURNS: +** HGLOBAL -- global memory handle of retrieved data block. +** NULL -- if error. +*/ +STDAPI_(HGLOBAL) OleStdGetData( + LPDATAOBJECT lpDataObj, + CLIPFORMAT cfFormat, + DVTARGETDEVICE FAR* lpTargetDevice, + DWORD dwDrawAspect, + LPSTGMEDIUM lpMedium +) +{ + HRESULT hrErr; + FORMATETC formatetc; + HGLOBAL hGlobal = NULL; + HGLOBAL hCopy; + LPVOID lp; + + formatetc.cfFormat = cfFormat; + formatetc.ptd = lpTargetDevice; + formatetc.dwAspect = dwDrawAspect; + formatetc.lindex = -1; + + switch (cfFormat) { + case CF_METAFILEPICT: + formatetc.tymed = TYMED_MFPICT; + break; + + case CF_BITMAP: + formatetc.tymed = TYMED_GDI; + break; + + default: + formatetc.tymed = TYMED_HGLOBAL; + break; + } + + OLEDBG_BEGIN2(TEXT("IDataObject::GetData called\r\n")) + hrErr = lpDataObj->lpVtbl->GetData( + lpDataObj, + (LPFORMATETC)&formatetc, + lpMedium + ); + OLEDBG_END2 + + if (hrErr != NOERROR) + return NULL; + + if ((hGlobal = lpMedium->hGlobal) == NULL) + return NULL; + + // Check if hGlobal really points to valid memory + if ((lp = GlobalLock(hGlobal)) != NULL) { + if (IsBadReadPtr(lp, 1)) { + GlobalUnlock(hGlobal); + return NULL; // ERROR: memory is NOT valid + } + GlobalUnlock(hGlobal); + } + + if (hGlobal != NULL && lpMedium->pUnkForRelease != NULL) { + /* OLE2NOTE: the callee wants to retain ownership of the data. + ** this is indicated by passing a non-NULL pUnkForRelease. + ** thus, we will make a copy of the data and release the + ** callee's copy. + */ + + hCopy = OleDuplicateData(hGlobal, cfFormat, GHND|GMEM_SHARE); + ReleaseStgMedium(lpMedium); // release callee's copy of data + + hGlobal = hCopy; + lpMedium->hGlobal = hCopy; + lpMedium->pUnkForRelease = NULL; + } + return hGlobal; +} + + +/* OleStdMalloc +** ------------ +** allocate memory using the currently active IMalloc* allocator +*/ +STDAPI_(LPVOID) OleStdMalloc(ULONG ulSize) +{ + LPVOID pout; + LPMALLOC pmalloc; + + if (CoGetMalloc(MEMCTX_TASK, &pmalloc) != NOERROR) { + OleDbgAssertSz(0, szAssertMemAlloc); + return NULL; + } + + pout = (LPVOID)pmalloc->lpVtbl->Alloc(pmalloc, ulSize); + + if (pmalloc != NULL) { + ULONG refs = pmalloc->lpVtbl->Release(pmalloc); + } + + return pout; +} + + +/* OleStdRealloc +** ------------- +** re-allocate memory using the currently active IMalloc* allocator +*/ +STDAPI_(LPVOID) OleStdRealloc(LPVOID pmem, ULONG ulSize) +{ + LPVOID pout; + LPMALLOC pmalloc; + + if (CoGetMalloc(MEMCTX_TASK, &pmalloc) != NOERROR) { + OleDbgAssertSz(0, szAssertMemAlloc); + return NULL; + } + + pout = (LPVOID)pmalloc->lpVtbl->Realloc(pmalloc, pmem, ulSize); + + if (pmalloc != NULL) { + ULONG refs = pmalloc->lpVtbl->Release(pmalloc); + } + + return pout; +} + + +/* OleStdFree +** ---------- +** free memory using the currently active IMalloc* allocator +*/ +STDAPI_(void) OleStdFree(LPVOID pmem) +{ + LPMALLOC pmalloc; + + if (pmem == NULL) + return; + + if (CoGetMalloc(MEMCTX_TASK, &pmalloc) != NOERROR) { + OleDbgAssertSz(0, szAssertMemAlloc); + return; + } + + pmalloc->lpVtbl->Free(pmalloc, pmem); + + if (pmalloc != NULL) { + ULONG refs = pmalloc->lpVtbl->Release(pmalloc); + } +} + + +/* OleStdGetSize +** ------------- +** Get the size of a memory block that was allocated using the +** currently active IMalloc* allocator. +*/ +STDAPI_(ULONG) OleStdGetSize(LPVOID pmem) +{ + ULONG ulSize; + LPMALLOC pmalloc; + + if (CoGetMalloc(MEMCTX_TASK, &pmalloc) != NOERROR) { + OleDbgAssertSz(0, szAssertMemAlloc); + return (ULONG)-1; + } + + ulSize = pmalloc->lpVtbl->GetSize(pmalloc, pmem); + + if (pmalloc != NULL) { + ULONG refs = pmalloc->lpVtbl->Release(pmalloc); + } + + return ulSize; +} + + +/* OleStdFreeString +** ---------------- +** Free a string that was allocated with the currently active +** IMalloc* allocator. +** +** if the caller has the current IMalloc* handy, then it can be +** passed as a argument, otherwise this function will retrieve the +** active allocator and use it. +*/ +STDAPI_(void) OleStdFreeString(LPTSTR lpsz, LPMALLOC lpMalloc) +{ + BOOL fMustRelease = FALSE; + + if (! lpMalloc) { + if (CoGetMalloc(MEMCTX_TASK, &lpMalloc) != NOERROR) + return; + fMustRelease = TRUE; + } + + lpMalloc->lpVtbl->Free(lpMalloc, lpsz); + + if (fMustRelease) + lpMalloc->lpVtbl->Release(lpMalloc); +} + + +/* OleStdCopyString +** ---------------- +** Copy a string into memory allocated with the currently active +** IMalloc* allocator. +** +** if the caller has the current IMalloc* handy, then it can be +** passed as a argument, otherwise this function will retrieve the +** active allocator and use it. +*/ +STDAPI_(LPTSTR) OleStdCopyString(LPTSTR lpszSrc, LPMALLOC lpMalloc) +{ + LPTSTR lpszDest = NULL; + BOOL fMustRelease = FALSE; + UINT lSize = lstrlen(lpszSrc); + + if (! lpMalloc) { + if (CoGetMalloc(MEMCTX_TASK, &lpMalloc) != NOERROR) + return NULL; + fMustRelease = TRUE; + } + + lpszDest = lpMalloc->lpVtbl->Alloc(lpMalloc, (lSize+1)*sizeof(TCHAR)); + + if (lpszDest) + lstrcpy(lpszDest, lpszSrc); + + if (fMustRelease) + lpMalloc->lpVtbl->Release(lpMalloc); + return lpszDest; +} + + +/* + * OleStdCreateStorageOnHGlobal() + * + * Purpose: + * Create a memory based IStorage*. + * + * OLE2NOTE: if fDeleteOnRelease==TRUE, then the ILockBytes is created + * such that it will delete them memory on its last release. + * the IStorage on created on top of the ILockBytes in NOT + * created with STGM_DELETEONRELEASE. when the IStorage receives + * its last release, it will release the ILockBytes which will + * in turn free the memory. it is in fact an error to specify + * STGM_DELETEONRELEASE in this situation. + * + * Parameters: + * hGlobal -- handle to MEM_SHARE allocated memory. may be NULL and + * memory will be automatically allocated. + * fDeleteOnRelease -- controls if the memory is freed on the last release. + * grfMode -- flags passed to StgCreateDocfileOnILockBytes + * + * NOTE: if hGlobal is NULL, then a new IStorage is created and + * STGM_CREATE flag is passed to StgCreateDocfileOnILockBytes. + * if hGlobal is non-NULL, then it is assumed that the hGlobal already + * has an IStorage inside it and STGM_CONVERT flag is passed + * to StgCreateDocfileOnILockBytes. + * + * Return Value: + * SCODE - S_OK if successful + */ +STDAPI_(LPSTORAGE) OleStdCreateStorageOnHGlobal( + HANDLE hGlobal, + BOOL fDeleteOnRelease, + DWORD grfMode +) +{ + DWORD grfCreateMode=grfMode | (hGlobal==NULL ? STGM_CREATE:STGM_CONVERT); + HRESULT hrErr; + LPLOCKBYTES lpLockBytes = NULL; + DWORD reserved = 0; + LPSTORAGE lpStg = NULL; + + hrErr = CreateILockBytesOnHGlobal( + hGlobal, + fDeleteOnRelease, + (LPLOCKBYTES FAR*)&lpLockBytes + ); + if (hrErr != NOERROR) + return NULL; + + hrErr = StgCreateDocfileOnILockBytes( + lpLockBytes, + grfCreateMode, + reserved, + (LPSTORAGE FAR*)&lpStg + ); + if (hrErr != NOERROR) { + OleStdRelease((LPUNKNOWN)lpLockBytes); + return NULL; + } + return lpStg; +} + + + +/* + * OleStdCreateTempStorage() + * + * Purpose: + * Create a temporay IStorage* that will DeleteOnRelease. + * this can be either memory based or file based. + * + * Parameters: + * fUseMemory -- controls if memory-based or file-based stg is created + * grfMode -- storage mode flags + * + * Return Value: + * LPSTORAGE - if successful, NULL otherwise + */ +STDAPI_(LPSTORAGE) OleStdCreateTempStorage(BOOL fUseMemory, DWORD grfMode) +{ + LPSTORAGE lpstg; + HRESULT hrErr; + DWORD reserved = 0; + + if (fUseMemory) { + lpstg = OleStdCreateStorageOnHGlobal( + NULL, /* auto allocate */ + TRUE, /* delete on release */ + grfMode + ); + } else { + /* allocate a temp docfile that will delete on last release */ + hrErr = StgCreateDocfile( + NULL, + grfMode | STGM_DELETEONRELEASE | STGM_CREATE, + reserved, + &lpstg + ); + if (hrErr != NOERROR) + return NULL; + } + return lpstg; +} + + +/* OleStdGetOleObjectData +** ---------------------- +** Render CF_EMBEDSOURCE/CF_EMBEDDEDOBJECT data on an TYMED_ISTORAGE +** medium by asking the object to save into the storage. +** the object must support IPersistStorage. +** +** if lpMedium->tymed == TYMED_NULL, then a delete-on-release +** storage is allocated (either file-based or memory-base depending +** the value of fUseMemory). this is useful to support an +** IDataObject::GetData call where the callee must allocate the +** medium. +** +** if lpMedium->tymed == TYMED_ISTORAGE, then the data is writen +** into the passed in IStorage. this is useful to support an +** IDataObject::GetDataHere call where the caller has allocated his +** own IStorage. +*/ +STDAPI OleStdGetOleObjectData( + LPPERSISTSTORAGE lpPStg, + LPFORMATETC lpformatetc, + LPSTGMEDIUM lpMedium, + BOOL fUseMemory +) +{ + LPSTORAGE lpstg = NULL; + DWORD reserved = 0; + SCODE sc = S_OK; + HRESULT hrErr; + + lpMedium->pUnkForRelease = NULL; + + if (lpMedium->tymed == TYMED_NULL) { + + if (lpformatetc->tymed & TYMED_ISTORAGE) { + + /* allocate a temp docfile that will delete on last release */ + lpstg = OleStdCreateTempStorage( + TRUE /*fUseMemory*/, + STGM_READWRITE | STGM_TRANSACTED | STGM_SHARE_EXCLUSIVE + ); + if (!lpstg) + return ResultFromScode(E_OUTOFMEMORY); + + lpMedium->pstg = lpstg; + lpMedium->tymed = TYMED_ISTORAGE; + lpMedium->pUnkForRelease = NULL; + } else { + return ResultFromScode(DATA_E_FORMATETC); + } + } else if (lpMedium->tymed == TYMED_ISTORAGE) { + lpMedium->tymed = TYMED_ISTORAGE; + } else { + return ResultFromScode(DATA_E_FORMATETC); + } + + // OLE2NOTE: even if OleSave returns an error you should still call + // SaveCompleted. + + OLEDBG_BEGIN2(TEXT("OleSave called\r\n")) + hrErr = OleSave(lpPStg, lpMedium->pstg, FALSE /* fSameAsLoad */); + OLEDBG_END2 + + if (hrErr != NOERROR) { + OleDbgOutHResult(TEXT("WARNING: OleSave returned"), hrErr); + sc = GetScode(hrErr); + } + OLEDBG_BEGIN2(TEXT("IPersistStorage::SaveCompleted called\r\n")) + hrErr = lpPStg->lpVtbl->SaveCompleted(lpPStg, NULL); + OLEDBG_END2 + + if (hrErr != NOERROR) { + OleDbgOutHResult(TEXT("WARNING: SaveCompleted returned"),hrErr); + if (sc == S_OK) + sc = GetScode(hrErr); + } + + return ResultFromScode(sc); +} + + +STDAPI OleStdGetLinkSourceData( + LPMONIKER lpmk, + LPCLSID lpClsID, + LPFORMATETC lpformatetc, + LPSTGMEDIUM lpMedium +) +{ + LPSTREAM lpstm = NULL; + DWORD reserved = 0; + HRESULT hrErr; + + if (lpMedium->tymed == TYMED_NULL) { + if (lpformatetc->tymed & TYMED_ISTREAM) { + hrErr = CreateStreamOnHGlobal( + NULL, /* auto allocate */ + TRUE, /* delete on release */ + (LPSTREAM FAR*)&lpstm + ); + if (hrErr != NOERROR) { + lpMedium->pUnkForRelease = NULL; + return ResultFromScode(E_OUTOFMEMORY); + } + lpMedium->pstm = lpstm; + lpMedium->tymed = TYMED_ISTREAM; + lpMedium->pUnkForRelease = NULL; + } else { + lpMedium->pUnkForRelease = NULL; + return ResultFromScode(DATA_E_FORMATETC); + } + } else { + if (lpMedium->tymed == TYMED_ISTREAM) { + lpMedium->tymed = TYMED_ISTREAM; + lpMedium->pstm = lpMedium->pstm; + lpMedium->pUnkForRelease = NULL; + } else { + lpMedium->pUnkForRelease = NULL; + return ResultFromScode(DATA_E_FORMATETC); + } + } + + hrErr = OleSaveToStream((LPPERSISTSTREAM)lpmk, lpMedium->pstm); + if (hrErr != NOERROR) return hrErr; + return WriteClassStm(lpMedium->pstm, lpClsID); +} + +/* + * OleStdGetObjectDescriptorData + * + * Purpose: + * Fills and returns a OBJECTDESCRIPTOR structure. + * See OBJECTDESCRIPTOR for more information. + * + * Parameters: + * clsid CLSID CLSID of object being transferred + * dwDrawAspect DWORD Display Aspect of object + * sizel SIZEL Size of object in HIMETRIC + * pointl POINTL Offset from upper-left corner of object where mouse went + * down for drag. Meaningful only when drag-drop is used. + * dwStatus DWORD OLEMISC flags + * lpszFullUserTypeName LPSTR Full User Type Name + * lpszSrcOfCopy LPSTR Source of Copy + * + * Return Value: + * HBGLOBAL Handle to OBJECTDESCRIPTOR structure. + */ +STDAPI_(HGLOBAL) OleStdGetObjectDescriptorData( + CLSID clsid, + DWORD dwDrawAspect, + SIZEL sizel, + POINTL pointl, + DWORD dwStatus, + LPTSTR lpszFullUserTypeNameA, + LPTSTR lpszSrcOfCopyA +) +{ + HGLOBAL hMem = NULL; + IBindCtx FAR *pbc = NULL; + LPOBJECTDESCRIPTOR lpOD; + DWORD dwObjectDescSize, dwFullUserTypeNameLen, dwSrcOfCopyLen; + LPOLESTR lpszFullUserTypeName, + lpszSrcOfCopy; + + // convert out strings to UNICODE + + if( lpszSrcOfCopyA ) + { + lpszSrcOfCopy = CreateOLESTR(lpszSrcOfCopyA); + } + + lpszFullUserTypeName = CreateOLESTR(lpszFullUserTypeNameA); + + // Get the length of Full User Type Name; Add 1 for the null terminator + dwFullUserTypeNameLen = lpszFullUserTypeName ? wcslen(lpszFullUserTypeName)+1 : 0; + + // Get the Source of Copy string and it's length; Add 1 for the null terminator + if (lpszSrcOfCopy) + dwSrcOfCopyLen = wcslen(lpszSrcOfCopy)+1; + else { + // No src moniker so use user type name as source string. + lpszSrcOfCopy = lpszFullUserTypeName; + dwSrcOfCopyLen = dwFullUserTypeNameLen; + } + + // Allocate space for OBJECTDESCRIPTOR and the additional string data + dwObjectDescSize = sizeof(OBJECTDESCRIPTOR); + hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, dwObjectDescSize + + (dwFullUserTypeNameLen + dwSrcOfCopyLen)*sizeof(OLECHAR)); + if (NULL == hMem) + goto error; + + lpOD = (LPOBJECTDESCRIPTOR)GlobalLock(hMem); + + // Set the FullUserTypeName offset and copy the string + if (lpszFullUserTypeName) + { + lpOD->dwFullUserTypeName = dwObjectDescSize; + wcscpy((LPOLESTR)(((BYTE FAR *)lpOD)+lpOD->dwFullUserTypeName), + lpszFullUserTypeName); + } + else lpOD->dwFullUserTypeName = 0; // zero offset indicates that string is not present + + // Set the SrcOfCopy offset and copy the string + if (lpszSrcOfCopy) + { + lpOD->dwSrcOfCopy = dwObjectDescSize + + dwFullUserTypeNameLen*sizeof(OLECHAR); + wcscpy((LPOLESTR)(((BYTE FAR *)lpOD)+lpOD->dwSrcOfCopy), lpszSrcOfCopy); + } + else lpOD->dwSrcOfCopy = 0; // zero offset indicates that string is not present + + // Initialize the rest of the OBJECTDESCRIPTOR + lpOD->cbSize = dwObjectDescSize + + (dwFullUserTypeNameLen + dwSrcOfCopyLen)*sizeof(OLECHAR); + lpOD->clsid = clsid; + lpOD->dwDrawAspect = dwDrawAspect; + lpOD->sizel = sizel; + lpOD->pointl = pointl; + lpOD->dwStatus = dwStatus; + + GlobalUnlock(hMem); + + FREEOLESTR(lpszFullUserTypeName); + FREEOLESTR(lpszSrcOfCopy); + + return hMem; + +error: + if (hMem) + { + GlobalUnlock(hMem); + GlobalFree(hMem); + } + return NULL; +} + +/* + * OleStdGetObjectDescriptorDataFromOleObject + * + * Purpose: + * Fills and returns a OBJECTDESCRIPTOR structure. Information for the structure is + * obtained from an OLEOBJECT. + * See OBJECTDESCRIPTOR for more information. + * + * Parameters: + * lpOleObj LPOLEOBJECT OleObject from which ONJECTDESCRIPTOR info + * is obtained. + * lpszSrcOfCopy LPSTR string to identify source of copy. + * May be NULL in which case IOleObject::GetMoniker is called + * to get the moniker of the object. if the object is loaded + * as part of a data transfer document, then usually + * lpOleClientSite==NULL is passed to OleLoad when loading + * the object. in this case the IOleObject:GetMoniker call + * will always fail (it tries to call back to the object's + * client site). in this situation a non-NULL lpszSrcOfCopy + * parameter should be passed. + * dwDrawAspect DWORD Display Aspect of object + * pointl POINTL Offset from upper-left corner of object where + * mouse went down for drag. Meaningful only when drag-drop + * is used. + * lpSizelHim SIZEL (optional) If the object is being scaled in its + * container, then the container should pass the extents + * that it is using to display the object. + * May be NULL if the object is NOT being scaled. in this + * case, IViewObject2::GetExtent will be called to get the + * extents from the object. + * + * Return Value: + * HBGLOBAL Handle to OBJECTDESCRIPTOR structure. + */ + +STDAPI_(HGLOBAL) OleStdGetObjectDescriptorDataFromOleObject( + LPOLEOBJECT lpOleObj, + LPTSTR lpszSrcOfCopy, + DWORD dwDrawAspect, + POINTL pointl, + LPSIZEL lpSizelHim +) +{ + CLSID clsid; + LPTSTR lpszFullUserTypeName = NULL; + LPMONIKER lpSrcMonikerOfCopy = NULL; + HGLOBAL hObjDesc; + IBindCtx FAR *pbc = NULL; + HRESULT hrErr; + SIZEL sizelHim; + BOOL fFreeSrcOfCopy = FALSE; + LPOLELINK lpOleLink = (LPOLELINK) + OleStdQueryInterface((LPUNKNOWN)lpOleObj,&IID_IOleLink); + +#ifdef OLE201 + LPVIEWOBJECT2 lpViewObj2 = (LPVIEWOBJECT2) + OleStdQueryInterface((LPUNKNOWN)lpOleObj, &IID_IViewObject2); +#endif + + BOOL fIsLink = (lpOleLink ? TRUE : FALSE); + TCHAR szLinkedTypeFmt[80]; + LPTSTR lpszBuf = NULL; + DWORD dwStatus = 0; + + // Get CLSID + OLEDBG_BEGIN2(TEXT("IOleObject::GetUserClassID called\r\n")) + hrErr = lpOleObj->lpVtbl->GetUserClassID(lpOleObj, &clsid); + OLEDBG_END2 + if (hrErr != NOERROR) + clsid = CLSID_NULL; + + // Get FullUserTypeName + OLEDBG_BEGIN2(TEXT("IOleObject::GetUserType called\r\n")) + { + LPOLESTR polestr; + + hrErr = lpOleObj->lpVtbl->GetUserType( + lpOleObj, + USERCLASSTYPE_FULL, + &polestr + ); + + CopyAndFreeOLESTR(polestr, &lpszFullUserTypeName); + } + + OLEDBG_END2 + +// REVIEW: added IDS_OLE2UILINKEDTYPE to strings.rc + /* if object is a link, then expand usertypename to be "Linked %s" */ + if (fIsLink && lpszFullUserTypeName) { + if (0 == LoadString(ghInst, IDS_OLE2UIPASTELINKEDTYPE, + (LPTSTR)szLinkedTypeFmt, sizeof(szLinkedTypeFmt)/sizeof(TCHAR))) + lstrcpy(szLinkedTypeFmt, (LPTSTR) TEXT("Linked %s")); + lpszBuf = OleStdMalloc( + (lstrlen(lpszFullUserTypeName)+lstrlen(szLinkedTypeFmt)+1) * + sizeof(TCHAR)); + if (lpszBuf) { + wsprintf(lpszBuf, szLinkedTypeFmt, lpszFullUserTypeName); + OleStdFreeString(lpszFullUserTypeName, NULL); + lpszFullUserTypeName = lpszBuf; + } + } + + /* Get Source Of Copy + ** if the object is an embedding, then get the object's moniker + ** if the object is a link, then get the link source moniker + */ + if (fIsLink) { + + OLEDBG_BEGIN2(TEXT("IOleLink::GetSourceDisplayName called\r\n")) + + { + LPOLESTR polestr; + + hrErr = lpOleLink->lpVtbl->GetSourceDisplayName( + lpOleLink, &polestr ); + + CopyAndFreeOLESTR(polestr, &lpszSrcOfCopy); + } + OLEDBG_END2 + fFreeSrcOfCopy = TRUE; + + } else { + + if (lpszSrcOfCopy == NULL) { + OLEDBG_BEGIN2(TEXT("IOleObject::GetMoniker called\r\n")) + hrErr = lpOleObj->lpVtbl->GetMoniker( + lpOleObj, + OLEGETMONIKER_TEMPFORUSER, + OLEWHICHMK_OBJFULL, + (LPMONIKER FAR*)&lpSrcMonikerOfCopy + ); + OLEDBG_END2 + if (hrErr == NOERROR) + { +#ifdef OLE201 + CreateBindCtx(0, (LPBC FAR*)&pbc); +#endif + CallIMonikerGetDisplayNameA( + lpSrcMonikerOfCopy, pbc, NULL, &lpszSrcOfCopy); + + pbc->lpVtbl->Release(pbc); + fFreeSrcOfCopy = TRUE; + } + } + } + + // Get SIZEL + if (lpSizelHim) { + // Use extents passed by the caller + sizelHim = *lpSizelHim; + } else if (lpViewObj2) { + // Get the current extents from the object + OLEDBG_BEGIN2(TEXT("IViewObject2::GetExtent called\r\n")) + hrErr = lpViewObj2->lpVtbl->GetExtent( + lpViewObj2, + dwDrawAspect, + -1, /*lindex*/ + NULL, /*ptd*/ + (LPSIZEL)&sizelHim + ); + OLEDBG_END2 + if (hrErr != NOERROR) + sizelHim.cx = sizelHim.cy = 0; + } else { + sizelHim.cx = sizelHim.cy = 0; + } + + // Get DWSTATUS + OLEDBG_BEGIN2(TEXT("IOleObject::GetMiscStatus called\r\n")) + hrErr = lpOleObj->lpVtbl->GetMiscStatus( + lpOleObj, + dwDrawAspect, + &dwStatus + ); + OLEDBG_END2 + if (hrErr != NOERROR) + dwStatus = 0; + + // Get OBJECTDESCRIPTOR + hObjDesc = OleStdGetObjectDescriptorData( + clsid, + dwDrawAspect, + sizelHim, + pointl, + dwStatus, + lpszFullUserTypeName, + lpszSrcOfCopy + ); + if (! hObjDesc) + goto error; + + // Clean up + if (lpszFullUserTypeName) + OleStdFreeString(lpszFullUserTypeName, NULL); + if (fFreeSrcOfCopy && lpszSrcOfCopy) + OleStdFreeString(lpszSrcOfCopy, NULL); + if (lpSrcMonikerOfCopy) + OleStdRelease((LPUNKNOWN)lpSrcMonikerOfCopy); + if (lpOleLink) + OleStdRelease((LPUNKNOWN)lpOleLink); + if (lpViewObj2) + OleStdRelease((LPUNKNOWN)lpViewObj2); + + return hObjDesc; + +error: + if (lpszFullUserTypeName) + OleStdFreeString(lpszFullUserTypeName, NULL); + if (fFreeSrcOfCopy && lpszSrcOfCopy) + OleStdFreeString(lpszSrcOfCopy, NULL); + if (lpSrcMonikerOfCopy) + OleStdRelease((LPUNKNOWN)lpSrcMonikerOfCopy); + if (lpOleLink) + OleStdRelease((LPUNKNOWN)lpOleLink); + if (lpViewObj2) + OleStdRelease((LPUNKNOWN)lpViewObj2); + + return NULL; +} + +/* + * OleStdFillObjectDescriptorFromData + * + * Purpose: + * Fills and returns a OBJECTDESCRIPTOR structure. The source object will + * offer CF_OBJECTDESCRIPTOR if it is an OLE2 object, CF_OWNERLINK if it + * is an OLE1 object, or CF_FILENAME if it has been copied to the clipboard + * by FileManager. + * + * Parameters: + * lpDataObject LPDATAOBJECT Source object + * lpmedium LPSTGMEDIUM Storage medium + * lpcfFmt CLIPFORMAT FAR * Format offered by lpDataObject + * (OUT parameter) + * + * Return Value: + * HBGLOBAL Handle to OBJECTDESCRIPTOR structure. + */ + +STDAPI_(HGLOBAL) OleStdFillObjectDescriptorFromData( + LPDATAOBJECT lpDataObject, + LPSTGMEDIUM lpmedium, + CLIPFORMAT FAR* lpcfFmt +) +{ + CLSID clsid; + SIZEL sizelHim; + POINTL pointl; + LPTSTR lpsz, szFullUserTypeName, szSrcOfCopy, szClassName, szDocName, szItemName; + int nClassName, nDocName, nItemName, nFullUserTypeName; + LPTSTR szBuf = NULL; + HGLOBAL hMem = NULL; + HKEY hKey = NULL; + LPMALLOC pIMalloc = NULL; + DWORD dw = OLEUI_CCHKEYMAX_SIZE; + HGLOBAL hObjDesc; + HRESULT hrErr; + + + // GetData CF_OBJECTDESCRIPTOR format from the object on the clipboard. + // Only OLE 2 objects on the clipboard will offer CF_OBJECTDESCRIPTOR + if (hMem = OleStdGetData( + lpDataObject, + (CLIPFORMAT) cfObjectDescriptor, + NULL, + DVASPECT_CONTENT, + lpmedium)) + { + *lpcfFmt = cfObjectDescriptor; + return hMem; // Don't drop to clean up at the end of this function + } + // If CF_OBJECTDESCRIPTOR is not available, i.e. if this is not an OLE2 object, + // check if this is an OLE 1 object. OLE 1 objects will offer CF_OWNERLINK + else if (hMem = OleStdGetData( + lpDataObject, + (CLIPFORMAT) cfOwnerLink, + NULL, + DVASPECT_CONTENT, + lpmedium)) + { + *lpcfFmt = cfOwnerLink; + // CF_OWNERLINK contains null-terminated strings for class name, document name + // and item name with two null terminating characters at the end + szClassName = (LPTSTR)GlobalLock(hMem); + nClassName = lstrlen(szClassName); + szDocName = szClassName + nClassName + 1; + nDocName = lstrlen(szDocName); + szItemName = szDocName + nDocName + 1; + nItemName = lstrlen(szItemName); + + hrErr = CoGetMalloc(MEMCTX_TASK, &pIMalloc); + if (hrErr != NOERROR) + goto error; + + // Find FullUserTypeName from Registration database using class name + if (RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hKey) != ERROR_SUCCESS) + goto error; + + // Allocate space for szFullUserTypeName & szSrcOfCopy. Maximum length of FullUserTypeName + // is OLEUI_CCHKEYMAX_SIZE. SrcOfCopy is constructed by concatenating FullUserTypeName, Document + // Name and ItemName separated by spaces. + szBuf = (LPTSTR)pIMalloc->lpVtbl->Alloc(pIMalloc, + (DWORD)2*OLEUI_CCHKEYMAX_SIZE+ + (nDocName+nItemName+4)*sizeof(TCHAR)); + if (NULL == szBuf) + goto error; + szFullUserTypeName = szBuf; + szSrcOfCopy = szFullUserTypeName+OLEUI_CCHKEYMAX_SIZE+1; + + // Get FullUserTypeName + if (RegQueryValue(hKey, NULL, szFullUserTypeName, &dw) != ERROR_SUCCESS) + goto error; + + // Build up SrcOfCopy string from FullUserTypeName, DocumentName & ItemName + lpsz = szSrcOfCopy; + lstrcpy(lpsz, szFullUserTypeName); + nFullUserTypeName = lstrlen(szFullUserTypeName); + lpsz[nFullUserTypeName]= TEXT(' '); + lpsz += nFullUserTypeName+1; + lstrcpy(lpsz, szDocName); + lpsz[nDocName] = TEXT(' '); + lpsz += nDocName+1; + lstrcpy(lpsz, szItemName); + + sizelHim.cx = sizelHim.cy = 0; + pointl.x = pointl.y = 0; + + CLSIDFromProgIDA(szClassName, &clsid); + + hObjDesc = OleStdGetObjectDescriptorData( + clsid, + DVASPECT_CONTENT, + sizelHim, + pointl, + 0, + szFullUserTypeName, + szSrcOfCopy + ); + if (!hObjDesc) + goto error; + } + // Check if object is CF_FILENAME + else if (hMem = OleStdGetData( + lpDataObject, + (CLIPFORMAT) cfFileName, + NULL, + DVASPECT_CONTENT, + lpmedium)) + { + *lpcfFmt = cfFileName; + lpsz = (LPTSTR)GlobalLock(hMem); + + hrErr = GetClassFileA(lpsz, &clsid); + + /* OLE2NOTE: if the file does not have an OLE class + ** associated, then use the OLE 1 Packager as the class of + ** the object to be created. this is the behavior of + ** OleCreateFromData API + */ + if (hrErr != NOERROR) + CLSIDFromProgIDA("Package", &clsid); + sizelHim.cx = sizelHim.cy = 0; + pointl.x = pointl.y = 0; + + hrErr = CoGetMalloc(MEMCTX_TASK, &pIMalloc); + if (hrErr != NOERROR) + goto error; + szBuf = (LPTSTR)pIMalloc->lpVtbl->Alloc(pIMalloc, (DWORD)OLEUI_CCHKEYMAX_SIZE); + if (NULL == szBuf) + goto error; + + OleStdGetUserTypeOfClass(&clsid, szBuf, OLEUI_CCHKEYMAX_SIZE, NULL); + + hObjDesc = OleStdGetObjectDescriptorData( + clsid, + DVASPECT_CONTENT, + sizelHim, + pointl, + 0, + szBuf, + lpsz + ); + if (!hObjDesc) + goto error; + } + else goto error; + + // Clean up + if (szBuf) + pIMalloc->lpVtbl->Free(pIMalloc, (LPVOID)szBuf); + if (pIMalloc) + pIMalloc->lpVtbl->Release(pIMalloc); + if (hMem) + { + GlobalUnlock(hMem); + GlobalFree(hMem); + } + if (hKey) + RegCloseKey(hKey); + return hObjDesc; + +error: + if (szBuf) + pIMalloc->lpVtbl->Free(pIMalloc, (LPVOID)szBuf); + if (pIMalloc) + pIMalloc->lpVtbl->Release(pIMalloc); + if (hMem) + { + GlobalUnlock(hMem); + GlobalFree(hMem); + } + if (hKey) + RegCloseKey(hKey); + return NULL; +} + + +#if defined( OBSOLETE ) + +/************************************************************************* +** The following API's have been converted into macros: +** OleStdQueryOleObjectData +** OleStdQueryLinkSourceData +** OleStdQueryObjectDescriptorData +** OleStdQueryFormatMedium +** OleStdCopyMetafilePict +** OleStdGetDropEffect +** +** These macros are defined in olestd.h +*************************************************************************/ + +STDAPI OleStdQueryOleObjectData(LPFORMATETC lpformatetc) +{ + if (lpformatetc->tymed & TYMED_ISTORAGE) { + return NOERROR; + } else { + return ResultFromScode(DATA_E_FORMATETC); + } +} + + +STDAPI OleStdQueryLinkSourceData(LPFORMATETC lpformatetc) +{ + if (lpformatetc->tymed & TYMED_ISTREAM) { + return NOERROR; + } else { + return ResultFromScode(DATA_E_FORMATETC); + } +} + + +STDAPI OleStdQueryObjectDescriptorData(LPFORMATETC lpformatetc) +{ + if (lpformatetc->tymed & TYMED_HGLOBAL) { + return NOERROR; + } else { + return ResultFromScode(DATA_E_FORMATETC); + } +} + + +STDAPI OleStdQueryFormatMedium(LPFORMATETC lpformatetc, TYMED tymed) +{ + if (lpformatetc->tymed & tymed) { + return NOERROR; + } else { + return ResultFromScode(DATA_E_FORMATETC); + } +} + + +/* + * OleStdCopyMetafilePict() + * + * Purpose: + * Make an independent copy of a MetafilePict + * Parameters: + * + * Return Value: + * TRUE if successful, else FALSE. + */ +STDAPI_(BOOL) OleStdCopyMetafilePict(HANDLE hpictin, HANDLE FAR* phpictout) +{ + HANDLE hpictout; + LPMETAFILEPICT ppictin, ppictout; + + if (hpictin == NULL || phpictout == NULL) { + OleDbgAssert(hpictin == NULL || phpictout == NULL); + return FALSE; + } + + *phpictout = NULL; + + if ((ppictin = (LPMETAFILEPICT)GlobalLock(hpictin)) == NULL) { + return FALSE; + } + + hpictout = GlobalAlloc(GHND|GMEM_SHARE, sizeof(METAFILEPICT)); + + if (hpictout && (ppictout = (LPMETAFILEPICT)GlobalLock(hpictout))){ + ppictout->hMF = CopyMetaFile(ppictin->hMF, NULL); + ppictout->xExt = ppictin->xExt; + ppictout->yExt = ppictin->yExt; + ppictout->mm = ppictin->mm; + GlobalUnlock(hpictout); + } + + *phpictout = hpictout; + + return TRUE; + +} + + +/* OleStdGetDropEffect +** ------------------- +** +** Convert a keyboard state into a DROPEFFECT. +** +** returns the DROPEFFECT value derived from the key state. +** the following is the standard interpretation: +** no modifier -- Default Drop (NULL is returned) +** CTRL -- DROPEFFECT_COPY +** SHIFT -- DROPEFFECT_MOVE +** CTRL-SHIFT -- DROPEFFECT_LINK +** +** Default Drop: this depends on the type of the target application. +** this is re-interpretable by each target application. a typical +** interpretation is if the drag is local to the same document +** (which is source of the drag) then a MOVE operation is +** performed. if the drag is not local, then a COPY operation is +** performed. +*/ +STDAPI_(DWORD) OleStdGetDropEffect( DWORD grfKeyState ) +{ + + if (grfKeyState & MK_CONTROL) { + + if (grfKeyState & MK_SHIFT) + return DROPEFFECT_LINK; + else + return DROPEFFECT_COPY; + + } else if (grfKeyState & MK_SHIFT) + return DROPEFFECT_MOVE; + + return 0; // no modifier -- do default operation +} +#endif // OBSOLETE + + +/* + * OleStdGetMetafilePictFromOleObject() + * + * Purpose: + * Generate a MetafilePict by drawing the OLE object. + * Parameters: + * lpOleObj LPOLEOBJECT pointer to OLE Object + * dwDrawAspect DWORD Display Aspect of object + * lpSizelHim SIZEL (optional) If the object is being scaled in its + * container, then the container should pass the extents + * that it is using to display the object. + * May be NULL if the object is NOT being scaled. in this + * case, IViewObject2::GetExtent will be called to get the + * extents from the object. + * ptd TARGETDEVICE FAR* (optional) target device to render + * metafile for. May be NULL. + * + * Return Value: + * HANDLE -- handle of allocated METAFILEPICT + */ +STDAPI_(HANDLE) OleStdGetMetafilePictFromOleObject( + LPOLEOBJECT lpOleObj, + DWORD dwDrawAspect, + LPSIZEL lpSizelHim, + DVTARGETDEVICE FAR* ptd +) +{ + LPVIEWOBJECT2 lpViewObj2 = NULL; + HDC hDC; + HMETAFILE hmf; + HANDLE hMetaPict; + LPMETAFILEPICT lpPict; + RECT rcHim; + RECTL rclHim; + SIZEL sizelHim; + HRESULT hrErr; + SIZE size; + POINT point; + +#ifdef OLE201 + lpViewObj2 = (LPVIEWOBJECT2)OleStdQueryInterface( + (LPUNKNOWN)lpOleObj, &IID_IViewObject2); +#endif + + if (! lpViewObj2) + return NULL; + + // Get SIZEL + if (lpSizelHim) { + // Use extents passed by the caller + sizelHim = *lpSizelHim; + } else { + // Get the current extents from the object + OLEDBG_BEGIN2(TEXT("IViewObject2::GetExtent called\r\n")) + hrErr = lpViewObj2->lpVtbl->GetExtent( + lpViewObj2, + dwDrawAspect, + -1, /*lindex*/ + ptd, /*ptd*/ + (LPSIZEL)&sizelHim + ); + OLEDBG_END2 + if (hrErr != NOERROR) + sizelHim.cx = sizelHim.cy = 0; + } + + hDC = CreateMetaFile(NULL); + + rclHim.left = 0; + rclHim.top = 0; + rclHim.right = sizelHim.cx; + rclHim.bottom = sizelHim.cy; + + rcHim.left = (int)rclHim.left; + rcHim.top = (int)rclHim.top; + rcHim.right = (int)rclHim.right; + rcHim.bottom = (int)rclHim.bottom; + + SetWindowOrgEx(hDC, rcHim.left, rcHim.top, &point); + SetWindowExtEx(hDC, rcHim.right-rcHim.left, rcHim.bottom-rcHim.top,&size); + + OLEDBG_BEGIN2(TEXT("IViewObject::Draw called\r\n")) + hrErr = lpViewObj2->lpVtbl->Draw( + lpViewObj2, + dwDrawAspect, + -1, + NULL, + ptd, + NULL, + hDC, + (LPRECTL)&rclHim, + (LPRECTL)&rclHim, + NULL, + 0 + ); + OLEDBG_END2 + + OleStdRelease((LPUNKNOWN)lpViewObj2); + if (hrErr != NOERROR) { + OleDbgOutHResult(TEXT("IViewObject::Draw returned"), hrErr); + } + + hmf = CloseMetaFile(hDC); + + hMetaPict = GlobalAlloc(GHND|GMEM_SHARE, sizeof(METAFILEPICT)); + + if (hMetaPict && (lpPict = (LPMETAFILEPICT)GlobalLock(hMetaPict))){ + lpPict->hMF = hmf; + lpPict->xExt = (int)sizelHim.cx ; + lpPict->yExt = (int)sizelHim.cy ; + lpPict->mm = MM_ANISOTROPIC; + GlobalUnlock(hMetaPict); + } + + return hMetaPict; +} + + +/* Call Release on the object that is expected to go away. +** if the refcnt of the object did no go to 0 then give a debug message. +*/ +STDAPI_(ULONG) OleStdVerifyRelease(LPUNKNOWN lpUnk, LPTSTR lpszMsg) +{ + ULONG cRef; + + cRef = lpUnk->lpVtbl->Release(lpUnk); + +#if defined( _DEBUG ) + if (cRef != 0) { + TCHAR szBuf[80]; + if (lpszMsg) + MessageBox(NULL, lpszMsg, NULL, MB_ICONEXCLAMATION | MB_OK); + wsprintf( + (LPTSTR)szBuf, + TEXT("refcnt (%ld) != 0 after object (0x%lx) release\n"), + cRef, + lpUnk + ); + if (lpszMsg) + OleDbgOut1(lpszMsg); + OleDbgOut1((LPTSTR)szBuf); + OleDbgAssertSz(cRef == 0, (LPTSTR)szBuf); + } else { + TCHAR szBuf[80]; + wsprintf( + (LPTSTR)szBuf, + TEXT("refcnt = 0 after object (0x%lx) release\n"), lpUnk + ); + OleDbgOut4((LPTSTR)szBuf); + } +#endif + return cRef; +} + + +/* Call Release on the object that is NOT necessarily expected to go away. +*/ +STDAPI_(ULONG) OleStdRelease(LPUNKNOWN lpUnk) +{ + ULONG cRef; + + cRef = lpUnk->lpVtbl->Release(lpUnk); + +#if defined( _DEBUG ) + { + TCHAR szBuf[80]; + wsprintf( + (LPTSTR)szBuf, + TEXT("refcnt = %ld after object (0x%lx) release\n"), + cRef, + lpUnk + ); + OleDbgOut4((LPTSTR)szBuf); + } +#endif + return cRef; +} + + +/* OleStdInitVtbl +** -------------- +** +** Initialize an interface Vtbl to ensure that there are no NULL +** function pointers in the Vtbl. All entries in the Vtbl are +** set to a valid funtion pointer (OleStdNullMethod) that issues +** debug assert message (message box) and returns E_NOTIMPL if called. +** +** NOTE: this funtion does not initialize the Vtbl with usefull +** function pointers, only valid function pointers to avoid the +** horrible run-time crash when a call is made through the Vtbl with +** a NULL function pointer. this API is only necessary when +** initializing the Vtbl's in C. C++ guarantees that all interface +** functions (in C++ terms -- pure virtual functions) are implemented. +*/ + +STDAPI_(void) OleStdInitVtbl(LPVOID lpVtbl, UINT nSizeOfVtbl) +{ + LPVOID FAR* lpFuncPtrArr = (LPVOID FAR*)lpVtbl; + UINT nMethods = nSizeOfVtbl/sizeof(VOID FAR*); + UINT i; + + for (i = 0; i < nMethods; i++) { + lpFuncPtrArr[i] = OleStdNullMethod; + } +} + + +/* OleStdCheckVtbl +** --------------- +** +** Check if all entries in the Vtbl are properly initialized with +** valid function pointers. If any entries are either NULL or +** OleStdNullMethod, then this function returns FALSE. If compiled +** for _DEBUG this function reports which function pointers are +** invalid. +** +** RETURNS: TRUE if all entries in Vtbl are valid +** FALSE otherwise. +*/ + +STDAPI_(BOOL) OleStdCheckVtbl(LPVOID lpVtbl, UINT nSizeOfVtbl, LPTSTR lpszIface) +{ + LPVOID FAR* lpFuncPtrArr = (LPVOID FAR*)lpVtbl; + UINT nMethods = nSizeOfVtbl/sizeof(VOID FAR*); + UINT i; + BOOL fStatus = TRUE; + int nChar = 0; + + for (i = 0; i < nMethods; i++) { + if (lpFuncPtrArr[i] == NULL || lpFuncPtrArr[i] == OleStdNullMethod) { +#if defined( _DEBUG ) + TCHAR szBuf[256]; + wsprintf(szBuf, TEXT("%s::method# %d NOT valid!"), lpszIface, i); + OleDbgOut1((LPTSTR)szBuf); +#endif + fStatus = FALSE; + } + } + return fStatus; +} + + +/* OleStdNullMethod +** ---------------- +** Dummy method used by OleStdInitVtbl to initialize an interface +** Vtbl to ensure that there are no NULL function pointers in the +** Vtbl. All entries in the Vtbl are set to this function. this +** function issues a debug assert message (message box) and returns +** E_NOTIMPL if called. If all is done properly, this function will +** NEVER be called! +*/ +STDMETHODIMP OleStdNullMethod(LPUNKNOWN lpThis) +{ + MessageBox( + NULL, + TEXT("ERROR: INTERFACE METHOD NOT IMPLEMENTED!\r\n"), + NULL, + MB_SYSTEMMODAL | MB_ICONHAND | MB_OK + ); + + return ResultFromScode(E_NOTIMPL); +} + + + +static BOOL GetFileTimes(LPTSTR lpszFileName, FILETIME FAR* pfiletime) +{ +#ifdef WIN32 + WIN32_FIND_DATA fd; + HANDLE hFind; + hFind = FindFirstFile(lpszFileName,&fd); + if (hFind == NULL || hFind == INVALID_HANDLE_VALUE) { + return FALSE; + } + FindClose(hFind); + *pfiletime = fd.ftLastWriteTime; + return TRUE; +#else // !Win32 + static char sz[256]; + static struct _find_t fileinfo; + + LSTRCPYN((LPTSTR)sz, lpszFileName, sizeof(sz)-1); + sz[sizeof(sz)-1]= TEXT('\0'); + AnsiToOem(sz, sz); + return (_dos_findfirst(sz,_A_NORMAL|_A_HIDDEN|_A_SUBDIR|_A_SYSTEM, + (struct _find_t *)&fileinfo) == 0 && + CoDosDateTimeToFileTime(fileinfo.wr_date,fileinfo.wr_time,pfiletime)); +#endif // Win32 +} + + + +/* OleStdRegisterAsRunning +** ----------------------- +** Register a moniker in the RunningObjectTable. +** if there is an existing registration (*lpdwRegister!=NULL), then +** first revoke that registration. +** +** new dwRegister key is returned via *lpdwRegister parameter. +*/ +STDAPI_(void) OleStdRegisterAsRunning(LPUNKNOWN lpUnk, LPMONIKER lpmkFull, DWORD FAR* lpdwRegister) +{ + LPRUNNINGOBJECTTABLE lpROT; + HRESULT hrErr; + DWORD dwOldRegister = *lpdwRegister; + + OLEDBG_BEGIN2(TEXT("OleStdRegisterAsRunning\r\n")) + + OLEDBG_BEGIN2(TEXT("GetRunningObjectTable called\r\n")) + hrErr = GetRunningObjectTable(0,(LPRUNNINGOBJECTTABLE FAR*)&lpROT); + OLEDBG_END2 + + if (hrErr == NOERROR) { + + /* register as running if a valid moniker is passed + ** + ** OLE2NOTE: we deliberately register the new moniker BEFORE + ** revoking the old moniker just in case the object + ** currently has no external locks. if the object has no + ** locks then revoking it from the running object table will + ** cause the object's StubManager to initiate shutdown of + ** the object. + */ + if (lpmkFull) { + + OLEDBG_BEGIN2(TEXT("IRunningObjectTable::Register called\r\n")) + lpROT->lpVtbl->Register(lpROT, 0, lpUnk,lpmkFull,lpdwRegister); + OLEDBG_END2 + +#if defined(_DEBUG) + { + TCHAR szBuf[512]; + LPTSTR lpszDisplay; + LPBC lpbc; + +#ifdef OLE201 + CreateBindCtx(0, (LPBC FAR*)&lpbc); +#endif + + CallIMonikerGetDisplayNameA( + lpmkFull, + lpbc, + NULL, + &lpszDisplay + ); + OleStdRelease((LPUNKNOWN)lpbc); + wsprintf( + szBuf, + TEXT("Moniker '%s' REGISTERED as [0x%lx] in ROT\r\n"), + lpszDisplay, + *lpdwRegister + ); + OleDbgOut2(szBuf); + OleStdFreeString(lpszDisplay, NULL); + } +#endif // _DEBUG + + } + + // if already registered, revoke + if (dwOldRegister != 0) { + +#if defined(_DEBUG) + { + TCHAR szBuf[512]; + + wsprintf( + szBuf, + TEXT("Moniker [0x%lx] REVOKED from ROT\r\n"), + dwOldRegister + ); + OleDbgOut2(szBuf); + } +#endif // _DEBUG + + OLEDBG_BEGIN2(TEXT("IRunningObjectTable::Revoke called\r\n")) + lpROT->lpVtbl->Revoke(lpROT, dwOldRegister); + OLEDBG_END2 + } + + OleStdRelease((LPUNKNOWN)lpROT); + } else { + OleDbgAssertSz( + lpROT != NULL, + TEXT("OleStdRegisterAsRunning: GetRunningObjectTable FAILED\r\n") + ); + } + + OLEDBG_END2 +} + + + +/* OleStdRevokeAsRunning +** --------------------- +** Revoke a moniker from the RunningObjectTable if there is an +** existing registration (*lpdwRegister!=NULL). +** +** *lpdwRegister parameter will be set to NULL. +*/ +STDAPI_(void) OleStdRevokeAsRunning(DWORD FAR* lpdwRegister) +{ + LPRUNNINGOBJECTTABLE lpROT; + HRESULT hrErr; + + OLEDBG_BEGIN2(TEXT("OleStdRevokeAsRunning\r\n")) + + // if still registered, then revoke + if (*lpdwRegister != 0) { + + OLEDBG_BEGIN2(TEXT("GetRunningObjectTable called\r\n")) + hrErr = GetRunningObjectTable(0,(LPRUNNINGOBJECTTABLE FAR*)&lpROT); + OLEDBG_END2 + + if (hrErr == NOERROR) { + +#if defined(_DEBUG) + { + TCHAR szBuf[512]; + + wsprintf( + szBuf, + TEXT("Moniker [0x%lx] REVOKED from ROT\r\n"), + *lpdwRegister + ); + OleDbgOut2(szBuf); + } +#endif // _DEBUG + + OLEDBG_BEGIN2(TEXT("IRunningObjectTable::Revoke called\r\n")) + lpROT->lpVtbl->Revoke(lpROT, *lpdwRegister); + OLEDBG_END2 + + *lpdwRegister = 0; + + OleStdRelease((LPUNKNOWN)lpROT); + } else { + OleDbgAssertSz( + lpROT != NULL, + TEXT("OleStdRevokeAsRunning: GetRunningObjectTable FAILED\r\n") + ); + } + } + OLEDBG_END2 +} + + +/* OleStdNoteFileChangeTime +** ------------------------ +** Note the time a File-Based object has been saved in the +** RunningObjectTable. These change times are used as the basis for +** IOleObject::IsUpToDate. +** It is important to set the time of the file-based object +** following a save operation to exactly the time of the saved file. +** this helps IOleObject::IsUpToDate to give the correct answer +** after a file has been saved. +*/ +STDAPI_(void) OleStdNoteFileChangeTime(LPTSTR lpszFileName, DWORD dwRegister) +{ + if (dwRegister != 0) { + + LPRUNNINGOBJECTTABLE lprot; + FILETIME filetime; + + if (GetFileTimes(lpszFileName, &filetime) && + GetRunningObjectTable(0,&lprot) == NOERROR) + { + lprot->lpVtbl->NoteChangeTime( lprot, dwRegister, &filetime ); + lprot->lpVtbl->Release(lprot); + + OleDbgOut2(TEXT("IRunningObjectTable::NoteChangeTime called\r\n")); + } + } +} + + +/* OleStdNoteObjectChangeTime +** -------------------------- +** Set the last change time of an object that is registered in the +** RunningObjectTable. These change times are used as the basis for +** IOleObject::IsUpToDate. +** +** every time the object sends out a OnDataChange notification, it +** should update the Time of last change in the ROT. +** +** NOTE: this function set the change time to the current time. +*/ +STDAPI_(void) OleStdNoteObjectChangeTime(DWORD dwRegister) +{ + if (dwRegister != 0) { + + LPRUNNINGOBJECTTABLE lprot; + FILETIME filetime; + + if (GetRunningObjectTable(0,&lprot) == NOERROR) + { +#ifdef OLE201 + CoFileTimeNow( &filetime ); + lprot->lpVtbl->NoteChangeTime( lprot, dwRegister, &filetime ); +#endif + lprot->lpVtbl->Release(lprot); + + OleDbgOut2(TEXT("IRunningObjectTable::NoteChangeTime called\r\n")); + } + } +} + + +/* OleStdCreateTempFileMoniker +** --------------------------- +** return the next available FileMoniker that can be used as the +** name of an untitled document. +** the FileMoniker is built of the form: +** +** eg. "Outline1", "Outline2", etc. +** +** The RunningObjectTable (ROT) is consulted to determine if a +** FileMoniker is in use. If the name is in use then the number is +** incremented and the ROT is checked again. +** +** Parameters: +** LPSTR lpszPrefixString - prefix used to build the name +** UINT FAR* lpuUnique - (IN-OUT) last used number. +** this number is used to make the +** name unique. on entry, the input +** number is incremented. on output, +** the number used is returned. this +** number should be passed again +** unchanged on the next call. +** LPSTR lpszName - (OUT) buffer used to build string. +** caller must be sure buffer is large +** enough to hold the generated string. +** LPMONIKER FAR* lplpmk - (OUT) next unused FileMoniker +** +** Returns: +** void +** +** Comments: +** This function is similar in spirit to the Windows API +** CreateTempFileName. +*/ +STDAPI_(void) OleStdCreateTempFileMoniker( + LPTSTR lpszPrefixString, + UINT FAR* lpuUnique, + LPTSTR lpszName, + LPMONIKER FAR* lplpmk +) +{ + LPRUNNINGOBJECTTABLE lpROT = NULL; + UINT i = (lpuUnique != NULL ? *lpuUnique : 1); + HRESULT hrErr; + + wsprintf(lpszName, TEXT("%s%d"), lpszPrefixString, i++); + + CreateFileMonikerA(lpszName, lplpmk); + + + OLEDBG_BEGIN2(TEXT("GetRunningObjectTable called\r\n")) + hrErr = GetRunningObjectTable(0,(LPRUNNINGOBJECTTABLE FAR*)&lpROT); + OLEDBG_END2 + + if (hrErr == NOERROR) { + + while (1) { + if (! *lplpmk) + break; // failed to create FileMoniker + + OLEDBG_BEGIN2(TEXT("IRunningObjectTable::IsRunning called\r\n")) + hrErr = lpROT->lpVtbl->IsRunning(lpROT,*lplpmk); + OLEDBG_END2 + + if (hrErr != NOERROR) + break; // the Moniker is NOT running; found unused one! + + OleStdVerifyRelease( + (LPUNKNOWN)*lplpmk, + TEXT("OleStdCreateTempFileMoniker: Moniker NOT released") + ); + + wsprintf(lpszName, TEXT("%s%d"), lpszPrefixString, i++); + CreateFileMonikerA(lpszName, lplpmk); + } + + OleStdRelease((LPUNKNOWN)lpROT); + } + + if (lpuUnique != NULL) + *lpuUnique = i; +} + + +/* OleStdGetFirstMoniker +** --------------------- +** return the first piece of a moniker. +** +** NOTE: if the given moniker is not a generic composite moniker, +** then an AddRef'ed pointer to the given moniker is returned. +*/ +STDAPI_(LPMONIKER) OleStdGetFirstMoniker(LPMONIKER lpmk) +{ + LPMONIKER lpmkFirst = NULL; + LPENUMMONIKER lpenumMoniker; + DWORD dwMksys; + HRESULT hrErr; + + if (! lpmk) + return NULL; + + if (lpmk->lpVtbl->IsSystemMoniker(lpmk, (LPDWORD)&dwMksys) == NOERROR + && dwMksys == MKSYS_GENERICCOMPOSITE) { + + /* OLE2NOTE: the moniker is a GenericCompositeMoniker. + ** enumerate the moniker to pull off the first piece. + */ + + hrErr = lpmk->lpVtbl->Enum( + lpmk, + TRUE /* fForward */, + (LPENUMMONIKER FAR*)&lpenumMoniker + ); + if (hrErr != NOERROR) + return NULL; // ERROR: give up! + + hrErr = lpenumMoniker->lpVtbl->Next( + lpenumMoniker, + 1, + (LPMONIKER FAR*)&lpmkFirst, + NULL + ); + lpenumMoniker->lpVtbl->Release(lpenumMoniker); + return lpmkFirst; + + } else { + /* OLE2NOTE: the moniker is NOT a GenericCompositeMoniker. + ** return an AddRef'ed pointer to the input moniker. + */ + lpmk->lpVtbl->AddRef(lpmk); + return lpmk; + } +} + + +/* OleStdGetLenFilePrefixOfMoniker +** ------------------------------- +** if the first piece of the Moniker is a FileMoniker, then return +** the length of the filename string. +** +** lpmk pointer to moniker +** +** Returns +** 0 if moniker does NOT start with a FileMoniker +** uLen string length of filename prefix of the display name +** retrieved from the given (lpmk) moniker. +*/ +STDAPI_(ULONG) OleStdGetLenFilePrefixOfMoniker(LPMONIKER lpmk) +{ + LPMONIKER lpmkFirst = NULL; + DWORD dwMksys; + LPTSTR lpsz = NULL; + LPBC lpbc = NULL; + ULONG uLen = 0; + HRESULT hrErr; + + if (! lpmk) + return 0; + + lpmkFirst = OleStdGetFirstMoniker(lpmk); + if (lpmkFirst) { + if ( (lpmkFirst->lpVtbl->IsSystemMoniker( + lpmkFirst, (LPDWORD)&dwMksys) == NOERROR) + && dwMksys == MKSYS_FILEMONIKER) { + +#ifdef OLE201 + hrErr = CreateBindCtx(0, (LPBC FAR*)&lpbc); +#endif + if (hrErr == NOERROR) { + hrErr = CallIMonikerGetDisplayNameA(lpmkFirst, lpbc, NULL, + &lpsz); + + if (hrErr == NOERROR && lpsz != NULL) { + uLen = lstrlen(lpsz); + OleStdFreeString(lpsz, NULL); + } + OleStdRelease((LPUNKNOWN)lpbc); + } + } + lpmkFirst->lpVtbl->Release(lpmkFirst); + } + return uLen; +} + + +/* OleStdMkParseDisplayName +** Parse a string into a Moniker by calling the OLE API +** MkParseDisplayName. if the original link source class was an OLE1 +** class, then attempt the parsing assuming the same class applies. +** +** if the class of the previous link source was an OLE1 class, +** then first attempt to parse a string that it is qualified +** with the progID associated with the OLE1 class. this more +** closely matches the semantics of OLE1 where the class of +** link sources is not expected to change. prefixing the +** string with "@!" will force the +** parsing of the string to assume the file is of that +** class. +** NOTE: this trick of prepending the string with "@ +** only works for OLE1 classes. +** +** PARAMETERS: +** REFCLSID rClsid -- original class of link source. +** CLSID_NULL if class is unknown +** ... other parameters the same as MkParseDisplayName API ... +** +** RETURNS +** NOERROR if string parsed successfully +** else error code returned by MkParseDisplayName +*/ +STDAPI OleStdMkParseDisplayName( + REFCLSID rClsid, + LPBC lpbc, + LPTSTR lpszUserName, + ULONG FAR* lpchEaten, + LPMONIKER FAR* lplpmk +) +{ + HRESULT hrErr; + + if (!IsEqualCLSID(rClsid,&CLSID_NULL) && CoIsOle1Class(rClsid) && + lpszUserName[0] != '@') { + LPTSTR lpszBuf; + LPTSTR lpszProgID; + + // Prepend "@!" to the input string + ProgIDFromCLSIDA(rClsid, &lpszProgID); + + if (lpszProgID == NULL) + goto Cont1; + lpszBuf = OleStdMalloc( + ((ULONG)lstrlen(lpszUserName)+ +#ifdef UNICODE + // OLE in Win32 is always UNICODE + wcslen(lpszProgID) +#else + lstrlen(lpszProgID) +#endif + +3)*sizeof(TCHAR)); + if (lpszBuf == NULL) { + if (lpszProgID) + OleStdFree(lpszProgID); + goto Cont1; + } + + wsprintf(lpszBuf, TEXT("@%s!%s"), lpszProgID, lpszUserName); + + OLEDBG_BEGIN2(TEXT("MkParseDisplayName called\r\n")) + + hrErr = MkParseDisplayNameA(lpbc, lpszBuf, lpchEaten, lplpmk); + + OLEDBG_END2 + + if (lpszProgID) + OleStdFree(lpszProgID); + if (lpszBuf) + OleStdFree(lpszBuf); + + if (hrErr == NOERROR) + return NOERROR; + } + +Cont1: + OLEDBG_BEGIN2(TEXT("MkParseDisplayName called\r\n")) + + hrErr = MkParseDisplayNameA(lpbc, lpszUserName, lpchEaten, lplpmk); + + OLEDBG_END2 + + return hrErr; +} + + +/* + * OleStdMarkPasteEntryList + * + * Purpose: + * Mark each entry in the PasteEntryList if its format is available from + * the source IDataObject*. the dwScratchSpace field of each PasteEntry + * is set to TRUE if available, else FALSE. + * + * Parameters: + * LPOLEUIPASTEENTRY array of PasteEntry structures + * int count of elements in PasteEntry array + * LPDATAOBJECT source IDataObject* pointer + * + * Return Value: + * none + */ +STDAPI_(void) OleStdMarkPasteEntryList( + LPDATAOBJECT lpSrcDataObj, + LPOLEUIPASTEENTRY lpPriorityList, + int cEntries +) +{ + LPENUMFORMATETC lpEnumFmtEtc = NULL; + #define FORMATETC_MAX 20 + FORMATETC rgfmtetc[FORMATETC_MAX]; + int i; + HRESULT hrErr; + long j, cFetched; + + // Clear all marks + for (i = 0; i < cEntries; i++) { + lpPriorityList[i].dwScratchSpace = FALSE; + + if (! lpPriorityList[i].fmtetc.cfFormat) { + // caller wants this item always considered available + // (by specifying a NULL format) + lpPriorityList[i].dwScratchSpace = TRUE; + } else if (lpPriorityList[i].fmtetc.cfFormat == cfEmbeddedObject + || lpPriorityList[i].fmtetc.cfFormat == cfEmbedSource + || lpPriorityList[i].fmtetc.cfFormat == cfFileName) { + + // if there is an OLE object format, then handle it + // specially by calling OleQueryCreateFromData. the caller + // need only specify one object type format. + OLEDBG_BEGIN2(TEXT("OleQueryCreateFromData called\r\n")) + hrErr = OleQueryCreateFromData(lpSrcDataObj); + OLEDBG_END2 + if(NOERROR == hrErr) { + lpPriorityList[i].dwScratchSpace = TRUE; + } + } else if (lpPriorityList[i].fmtetc.cfFormat == cfLinkSource) { + + // if there is OLE 2.0 LinkSource format, then handle it + // specially by calling OleQueryLinkFromData. + OLEDBG_BEGIN2(TEXT("OleQueryLinkFromData called\r\n")) + hrErr = OleQueryLinkFromData(lpSrcDataObj); + OLEDBG_END2 + if(NOERROR == hrErr) { + lpPriorityList[i].dwScratchSpace = TRUE; + } + } + } + + OLEDBG_BEGIN2(TEXT("IDataObject::EnumFormatEtc called\r\n")) + hrErr = lpSrcDataObj->lpVtbl->EnumFormatEtc( + lpSrcDataObj, + DATADIR_GET, + (LPENUMFORMATETC FAR*)&lpEnumFmtEtc + ); + OLEDBG_END2 + + if (hrErr != NOERROR) + return; // unable to get format enumerator + + // Enumerate the formats offered by the source + // Loop over all formats offered by the source + cFetched = 0; + _fmemset(rgfmtetc,0,sizeof(rgfmtetc[FORMATETC_MAX]) ); + if (lpEnumFmtEtc->lpVtbl->Next( + lpEnumFmtEtc, FORMATETC_MAX, rgfmtetc, &cFetched) == NOERROR + || (cFetched > 0 && cFetched <= FORMATETC_MAX) ) + { + + for (j = 0; j < cFetched; j++) + { + for (i = 0; i < cEntries; i++) + { + if (! lpPriorityList[i].dwScratchSpace && + IsCloseFormatEtc(&rgfmtetc[j], &lpPriorityList[i].fmtetc)) + { + lpPriorityList[i].dwScratchSpace = TRUE; + } + } + } + } // endif + + // Clean up + if (lpEnumFmtEtc) + OleStdRelease((LPUNKNOWN)lpEnumFmtEtc); +} + + +/* OleStdGetPriorityClipboardFormat +** -------------------------------- +** +** Retrieve the first clipboard format in a list for which data +** exists in the source IDataObject*. +** +** Returns -1 if no acceptable match is found. +** index of first acceptable match in the priority list. +** +*/ +STDAPI_(int) OleStdGetPriorityClipboardFormat( + LPDATAOBJECT lpSrcDataObj, + LPOLEUIPASTEENTRY lpPriorityList, + int cEntries +) +{ + int i; + int nFmtEtc = -1; + + // Mark all entries that the Source provides + OleStdMarkPasteEntryList(lpSrcDataObj, lpPriorityList, cEntries); + + // Loop over the target's priority list of formats + for (i = 0; i < cEntries; i++) + { + if (lpPriorityList[i].dwFlags != OLEUIPASTE_PASTEONLY && + !(lpPriorityList[i].dwFlags & OLEUIPASTE_PASTE)) + continue; + + // get first marked entry + if (lpPriorityList[i].dwScratchSpace) { + nFmtEtc = i; + break; // Found priority format; DONE + } + } + + return nFmtEtc; +} + + +/* OleStdIsDuplicateFormat +** ----------------------- +** Returns TRUE if the lpFmtEtc->cfFormat is found in the array of +** FormatEtc structures. +*/ +STDAPI_(BOOL) OleStdIsDuplicateFormat( + LPFORMATETC lpFmtEtc, + LPFORMATETC arrFmtEtc, + int nFmtEtc +) +{ + int i; + + for (i = 0; i < nFmtEtc; i++) { + if (IsEqualFORMATETC((*lpFmtEtc), arrFmtEtc[i])) + return TRUE; + } + + return FALSE; +} + + +/* OleStdGetItemToken + * ------------------ + * + * LPTSTR lpszSrc - Pointer to a source string + * LPTSTR lpszDst - Pointer to destination buffer + * + * Will copy one token from the lpszSrc buffer to the lpszItem buffer. + * It considers all alpha-numeric and white space characters as valid + * characters for a token. the first non-valid character delimates the + * token. + * + * returns the number of charaters eaten. + */ +STDAPI_(ULONG) OleStdGetItemToken(LPTSTR lpszSrc, LPTSTR lpszDst, int nMaxChars) +{ + ULONG chEaten = 0L; + + // skip leading delimeter characters + while (*lpszSrc && --nMaxChars > 0 + && ((*lpszSrc==TEXT('/')) || (*lpszSrc==TEXT('\\')) || + (*lpszSrc==TEXT('!')) || (*lpszSrc==TEXT(':')))) { + *lpszSrc++; + chEaten++; + } + + // Extract token string (up to first delimeter char or EOS) + while (*lpszSrc && --nMaxChars > 0 + && !((*lpszSrc==TEXT('/')) || (*lpszSrc==TEXT('\\')) || + (*lpszSrc==TEXT('!')) || (*lpszSrc==TEXT(':')))) { + *lpszDst++ = *lpszSrc++; + chEaten++; + } + *lpszDst = TEXT('\0'); + return chEaten; +} + + +/************************************************************************* +** OleStdCreateRootStorage +** create a root level Storage given a filename that is compatible +** to be used by a top-level OLE container. if the filename +** specifies an existing file, then an error is returned. +** the root storage (Docfile) that is created by this function +** is suitable to be used to create child storages for embedings. +** (CreateChildStorage can be used to create child storages.) +** NOTE: the root-level storage is opened in transacted mode. +*************************************************************************/ + +STDAPI_(LPSTORAGE) OleStdCreateRootStorage(LPTSTR lpszStgName, DWORD grfMode) +{ + HRESULT hr; + DWORD grfCreateMode = STGM_READWRITE | STGM_TRANSACTED; + DWORD reserved = 0; + LPSTORAGE lpRootStg; + TCHAR szMsg[64]; + + // if temp file is being created, enable delete-on-release + if (! lpszStgName) + grfCreateMode |= STGM_DELETEONRELEASE; + + hr = StgCreateDocfileA( + lpszStgName, + grfMode | grfCreateMode, + reserved, + (LPSTORAGE FAR*)&lpRootStg + ); + + if (hr == NOERROR) + return lpRootStg; // existing file successfully opened + + OleDbgOutHResult(TEXT("StgCreateDocfile returned"), hr); + + if (0 == LoadString(ghInst, IDS_OLESTDNOCREATEFILE, (LPTSTR)szMsg, 64)) + return NULL; + + MessageBox(NULL, (LPTSTR)szMsg, NULL,MB_ICONEXCLAMATION | MB_OK); + return NULL; +} + + +/************************************************************************* +** OleStdOpenRootStorage +** open a root level Storage given a filename that is compatible +** to be used by a top-level OLE container. if the file does not +** exist then an error is returned. +** the root storage (Docfile) that is opened by this function +** is suitable to be used to create child storages for embedings. +** (CreateChildStorage can be used to create child storages.) +** NOTE: the root-level storage is opened in transacted mode. +*************************************************************************/ + +STDAPI_(LPSTORAGE) OleStdOpenRootStorage(LPTSTR lpszStgName, DWORD grfMode) +{ + HRESULT hr; + DWORD reserved = 0; + LPSTORAGE lpRootStg; + TCHAR szMsg[64]; + + if (lpszStgName) { + hr = StgOpenStorageA( + lpszStgName, + NULL, + grfMode | STGM_TRANSACTED, + NULL, + reserved, + (LPSTORAGE FAR*)&lpRootStg + ); + + if (hr == NOERROR) + return lpRootStg; // existing file successfully opened + + OleDbgOutHResult(TEXT("StgOpenStorage returned"), hr); + } + + if (0 == LoadString(ghInst, IDS_OLESTDNOOPENFILE, szMsg, 64)) + return NULL; + + MessageBox(NULL, (LPTSTR)szMsg, NULL,MB_ICONEXCLAMATION | MB_OK); + return NULL; +} + + +/************************************************************************* +** OpenOrCreateRootStorage +** open a root level Storage given a filename that is compatible +** to be used by a top-level OLE container. if the filename +** specifies an existing file, then it is open, otherwise a new file +** with the given name is created. +** the root storage (Docfile) that is created by this function +** is suitable to be used to create child storages for embedings. +** (CreateChildStorage can be used to create child storages.) +** NOTE: the root-level storage is opened in transacted mode. +*************************************************************************/ + +STDAPI_(LPSTORAGE) OleStdOpenOrCreateRootStorage(LPTSTR lpszStgName, DWORD grfMode) +{ + HRESULT hrErr; + SCODE sc; + DWORD reserved = 0; + LPSTORAGE lpRootStg; + TCHAR szMsg[64]; + + if (lpszStgName) { + + hrErr = StgOpenStorageA( + lpszStgName, + NULL, + grfMode | STGM_READWRITE | STGM_TRANSACTED, + NULL, + reserved, + (LPSTORAGE FAR*)&lpRootStg + ); + + if (hrErr == NOERROR) + return lpRootStg; // existing file successfully opened + + OleDbgOutHResult(TEXT("StgOpenStorage returned"), hrErr); + sc = GetScode(hrErr); + + if (sc!=STG_E_FILENOTFOUND && sc!=STG_E_FILEALREADYEXISTS) { + return NULL; + } + } + + /* if file did not already exist, try to create a new one */ + hrErr = StgCreateDocfileA( + lpszStgName, + grfMode | STGM_READWRITE | STGM_TRANSACTED, + reserved, + (LPSTORAGE FAR*)&lpRootStg + ); + + if (hrErr == NOERROR) + return lpRootStg; // existing file successfully opened + + OleDbgOutHResult(TEXT("StgCreateDocfile returned"), hrErr); + + if (0 == LoadString(ghInst, IDS_OLESTDNOCREATEFILE, (LPTSTR)szMsg, 64)) + return NULL; + + MessageBox(NULL, (LPTSTR)szMsg, NULL, MB_ICONEXCLAMATION | MB_OK); + return NULL; +} + + +/* +** OleStdCreateChildStorage +** create a child Storage inside the given lpStg that is compatible +** to be used by an embedded OLE object. the return value from this +** function can be passed to OleCreateXXX functions. +** NOTE: the child storage is opened in transacted mode. +*/ +STDAPI_(LPSTORAGE) OleStdCreateChildStorage(LPSTORAGE lpStg, LPTSTR lpszStgName) +{ + if (lpStg != NULL) { + LPSTORAGE lpChildStg; + DWORD grfMode = (STGM_READWRITE | STGM_TRANSACTED | + STGM_SHARE_EXCLUSIVE); + DWORD reserved = 0; + + HRESULT hrErr = CallIStorageCreateStorageA( + lpStg, + lpszStgName, + grfMode, + reserved, + reserved, + (LPSTORAGE FAR*)&lpChildStg + ); + + if (hrErr == NOERROR) + return lpChildStg; + + OleDbgOutHResult(TEXT("lpStg->lpVtbl->CreateStorage returned"), hrErr); + } + return NULL; +} + + +/* +** OleStdOpenChildStorage +** open a child Storage inside the given lpStg that is compatible +** to be used by an embedded OLE object. the return value from this +** function can be passed to OleLoad function. +** NOTE: the child storage is opened in transacted mode. +*/ +STDAPI_(LPSTORAGE) OleStdOpenChildStorage(LPSTORAGE lpStg, LPTSTR lpszStgName, DWORD grfMode) +{ + LPSTORAGE lpChildStg; + LPSTORAGE lpstgPriority = NULL; + DWORD reserved = 0; + HRESULT hrErr; + + if (lpStg != NULL) { + + hrErr = CallIStorageOpenStorageA( + lpStg, + lpszStgName, + lpstgPriority, + grfMode | STGM_TRANSACTED | STGM_SHARE_EXCLUSIVE, + NULL, + reserved, + (LPSTORAGE FAR*)&lpChildStg + ); + + if (hrErr == NOERROR) + return lpChildStg; + + OleDbgOutHResult(TEXT("lpStg->lpVtbl->OpenStorage returned"), hrErr); + } + return NULL; +} + + +/* OleStdCommitStorage +** ------------------- +** Commit the changes to the given IStorage*. This routine can be +** called on either a root-level storage as used by an OLE-Container +** or by a child storage as used by an embedded object. +** +** This routine first attempts to perform this commit in a safe +** manner. if this fails it then attempts to do the commit in a less +** robust manner (STGC_OVERWRITE). +*/ +STDAPI_(BOOL) OleStdCommitStorage(LPSTORAGE lpStg) +{ + HRESULT hrErr; + + // make the changes permanent + hrErr = lpStg->lpVtbl->Commit(lpStg, 0); + + if (GetScode(hrErr) == STG_E_MEDIUMFULL) { + // try to commit changes in less robust manner. + OleDbgOut(TEXT("Warning: commiting with STGC_OVERWRITE specified\n")); + hrErr = lpStg->lpVtbl->Commit(lpStg, STGC_OVERWRITE); + } + + if (hrErr != NOERROR) + { + TCHAR szMsg[64]; + + if (0 == LoadString(ghInst, IDS_OLESTDDISKFULL, (LPTSTR)szMsg, 64)) + return FALSE; + + MessageBox(NULL, (LPTSTR)szMsg, NULL, MB_ICONEXCLAMATION | MB_OK); + return FALSE; + } + else { + return TRUE; + } +} + + +/* OleStdDestroyAllElements +** ------------------------ +** Destroy all elements within an open storage. this is subject +** to the current transaction. +*/ +STDAPI OleStdDestroyAllElements(LPSTORAGE lpStg) +{ + IEnumSTATSTG FAR* lpEnum; + STATSTG sstg; + HRESULT hrErr; + + hrErr = lpStg->lpVtbl->EnumElements( + lpStg, 0, NULL, 0, (IEnumSTATSTG FAR* FAR*)&lpEnum); + + if (hrErr != NOERROR) + return hrErr; + + while (1) { + if (lpEnum->lpVtbl->Next(lpEnum, 1, &sstg, NULL) != NOERROR) + break; + lpStg->lpVtbl->DestroyElement(lpStg, sstg.pwcsName); + OleStdFree(sstg.pwcsName); + } + lpEnum->lpVtbl->Release(lpEnum); + return NOERROR; +} + +// returns 1 for a close match +// (all fields match exactly except the tymed which simply overlaps) +// 0 for no match + +int IsCloseFormatEtc(FORMATETC FAR* pFetcLeft, FORMATETC FAR* pFetcRight) +{ + if (pFetcLeft->cfFormat != pFetcRight->cfFormat) + return 0; + else if (!OleStdCompareTargetDevice (pFetcLeft->ptd, pFetcRight->ptd)) + return 0; + if (pFetcLeft->dwAspect != pFetcRight->dwAspect) + return 0; + return((pFetcLeft->tymed | pFetcRight->tymed) != 0); +} + + diff --git a/private/oleutest/letest/ole2ui/olestd.h b/private/oleutest/letest/ole2ui/olestd.h new file mode 100644 index 000000000..7ca92fcbf --- /dev/null +++ b/private/oleutest/letest/ole2ui/olestd.h @@ -0,0 +1,852 @@ +/************************************************************************* +** +** OLE 2.0 Standard Utilities +** +** olestd.h +** +** This file contains file contains data structure defintions, +** function prototypes, constants, etc. for the common OLE 2.0 +** utilities. +** These utilities include the following: +** Debuging Assert/Verify macros +** HIMETRIC conversion routines +** reference counting debug support +** OleStd API's for common compound-document app support +** +** (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved +** +*************************************************************************/ + +#if !defined( _OLESTD_H_ ) +#define _OLESTD_H_ + +#ifndef RC_INVOKED +#pragma message ("INCLUDING OLESTD.H from " __FILE__) +#endif /* RC_INVOKED */ + +#if defined( __TURBOC__ ) || defined( WIN32 ) +#define _based(a) +#endif + +#ifndef RC_INVOKED +#include // needed for filetime +#endif /* RC_INVOKED */ + +#include // needed for LPPRINTDLG +#include // needed for HKEY + +// String table defines... +#define IDS_OLESTDNOCREATEFILE 700 +#define IDS_OLESTDNOOPENFILE 701 +#define IDS_OLESTDDISKFULL 702 + + +/* + * Some C interface declaration stuff + */ + +#if ! defined(__cplusplus) +typedef struct tagINTERFACEIMPL { + IUnknownVtbl FAR* lpVtbl; + LPVOID lpBack; + int cRef; // interface specific ref count. +} INTERFACEIMPL, FAR* LPINTERFACEIMPL; + +#define INIT_INTERFACEIMPL(lpIFace, pVtbl, pBack) \ + ((lpIFace)->lpVtbl = pVtbl, \ + ((LPINTERFACEIMPL)(lpIFace))->lpBack = (LPVOID)pBack, \ + ((LPINTERFACEIMPL)(lpIFace))->cRef = 0 \ + ) + +#if defined( _DEBUG ) +#define OleDbgQueryInterfaceMethod(lpUnk) \ + ((lpUnk) != NULL ? ((LPINTERFACEIMPL)(lpUnk))->cRef++ : 0) +#define OleDbgAddRefMethod(lpThis, iface) \ + ((LPINTERFACEIMPL)(lpThis))->cRef++ + +#if _DEBUGLEVEL >= 2 +#define OleDbgReleaseMethod(lpThis, iface) \ + (--((LPINTERFACEIMPL)(lpThis))->cRef == 0 ? \ + OleDbgOut("\t" iface "* RELEASED (cRef == 0)\r\n"),1 : \ + (((LPINTERFACEIMPL)(lpThis))->cRef < 0) ? \ + ( \ + DebugBreak(), \ + OleDbgOut( \ + "\tERROR: " iface "* RELEASED TOO MANY TIMES\r\n") \ + ),1 : \ + 1) + +#else // if _DEBUGLEVEL < 2 +#define OleDbgReleaseMethod(lpThis, iface) \ + (--((LPINTERFACEIMPL)(lpThis))->cRef == 0 ? \ + 1 : \ + (((LPINTERFACEIMPL)(lpThis))->cRef < 0) ? \ + ( \ + OleDbgOut( \ + "\tERROR: " iface "* RELEASED TOO MANY TIMES\r\n") \ + ),1 : \ + 1) + +#endif // if _DEBUGLEVEL < 2 + +#else // ! defined (_DEBUG) + +#define OleDbgQueryInterfaceMethod(lpUnk) +#define OleDbgAddRefMethod(lpThis, iface) +#define OleDbgReleaseMethod(lpThis, iface) + +#endif // if defined( _DEBUG ) + +#endif // ! defined(__cplusplus) + +/* + * Some docfiles stuff + */ + +#define STGM_DFRALL (STGM_READWRITE | STGM_TRANSACTED | STGM_SHARE_DENY_WRITE) +#define STGM_DFALL (STGM_READWRITE | STGM_TRANSACTED | STGM_SHARE_EXCLUSIVE) +#define STGM_SALL (STGM_READWRITE | STGM_SHARE_EXCLUSIVE) + +/* + * Some moniker stuff + */ + +// Delimeter used to separate ItemMoniker pieces of a composite moniker +#if defined( _MAC ) +#define OLESTDDELIM ":" +#else +#define OLESTDDELIM TEXT("\\") +#endif + +/* + * Some Concurrency stuff + */ + +/* standard Delay (in msec) to wait before retrying an LRPC call. +** this value is returned from IMessageFilter::RetryRejectedCall +*/ +#define OLESTDRETRYDELAY (DWORD)5000 + +/* Cancel the pending outgoing LRPC call. +** this value is returned from IMessageFilter::RetryRejectedCall +*/ +#define OLESTDCANCELRETRY (DWORD)-1 + +/* + * Some Icon support stuff. + * + * The following API's are now OBSOLETE because equivalent API's have been + * added to the OLE2.DLL library + * GetIconOfFile superceeded by OleGetIconOfFile + * GetIconOfClass superceeded by OleGetIconOfClass + * OleUIMetafilePictFromIconAndLabel + * superceeded by OleMetafilePictFromIconAndLabel + * + * The following macros are defined for backward compatibility with previous + * versions of the OLE2UI library. It is recommended that the new Ole* API's + * should be used instead. + */ +#define GetIconOfFile(hInst, lpszFileName, fUseFileAsLabel) \ + OleGetIconOfFileA(lpszFileName, fUseFileAsLabel) + +#define GetIconOfClass(hInst, rclsid, lpszLabel, fUseTypeAsLabel) \ + OleGetIconOfClassA(rclsid, lpszLabel, fUseTypeAsLabel) + +#define OleUIMetafilePictFromIconAndLabel(hIcon,pszLabel,pszSourceFile,iIcon)\ + OleMetafilePictFromIconAndLabelA(hIcon, pszLabel, pszSourceFile, iIcon) + + +/* + * Some Clipboard Copy/Paste & Drag/Drop support stuff + */ + +//Macro to set all FormatEtc fields +#define SETFORMATETC(fe, cf, asp, td, med, li) \ + ((fe).cfFormat=cf, \ + (fe).dwAspect=asp, \ + (fe).ptd=td, \ + (fe).tymed=med, \ + (fe).lindex=li) + +//Macro to set interesting FormatEtc fields defaulting the others. +#define SETDEFAULTFORMATETC(fe, cf, med) \ + ((fe).cfFormat=cf, \ + (fe).dwAspect=DVASPECT_CONTENT, \ + (fe).ptd=NULL, \ + (fe).tymed=med, \ + (fe).lindex=-1) + +// Macro to test if two FormatEtc structures are an exact match +#define IsEqualFORMATETC(fe1, fe2) \ + (OleStdCompareFormatEtc(&(fe1), &(fe2))==0) + +// Clipboard format strings +#define CF_EMBEDSOURCE TEXT("Embed Source") +#define CF_EMBEDDEDOBJECT TEXT("Embedded Object") +#define CF_LINKSOURCE TEXT("Link Source") +#define CF_CUSTOMLINKSOURCE TEXT("Custom Link Source") +#define CF_OBJECTDESCRIPTOR TEXT("Object Descriptor") +#define CF_LINKSRCDESCRIPTOR TEXT("Link Source Descriptor") +#define CF_OWNERLINK TEXT("OwnerLink") +#define CF_FILENAME TEXT("FileName") + +#define OleStdQueryOleObjectData(lpformatetc) \ + (((lpformatetc)->tymed & TYMED_ISTORAGE) ? \ + NOERROR : ResultFromScode(DV_E_FORMATETC)) + +#define OleStdQueryLinkSourceData(lpformatetc) \ + (((lpformatetc)->tymed & TYMED_ISTREAM) ? \ + NOERROR : ResultFromScode(DV_E_FORMATETC)) + +#define OleStdQueryObjectDescriptorData(lpformatetc) \ + (((lpformatetc)->tymed & TYMED_HGLOBAL) ? \ + NOERROR : ResultFromScode(DV_E_FORMATETC)) + +#define OleStdQueryFormatMedium(lpformatetc, tymd) \ + (((lpformatetc)->tymed & tymd) ? \ + NOERROR : ResultFromScode(DV_E_FORMATETC)) + +// Make an independent copy of a MetafilePict +#define OleStdCopyMetafilePict(hpictin, phpictout) \ + (*(phpictout) = OleDuplicateData(hpictin,CF_METAFILEPICT,GHND|GMEM_SHARE)) + + +// REVIEW: these need to be added to OLE2.H +#if !defined( DD_DEFSCROLLINTERVAL ) +#define DD_DEFSCROLLINTERVAL 50 +#endif + +#if !defined( DD_DEFDRAGDELAY ) +#define DD_DEFDRAGDELAY 200 +#endif + +#if !defined( DD_DEFDRAGMINDIST ) +#define DD_DEFDRAGMINDIST 2 +#endif + + +/* OleStdGetDropEffect +** ------------------- +** +** Convert a keyboard state into a DROPEFFECT. +** +** returns the DROPEFFECT value derived from the key state. +** the following is the standard interpretation: +** no modifier -- Default Drop (NULL is returned) +** CTRL -- DROPEFFECT_COPY +** SHIFT -- DROPEFFECT_MOVE +** CTRL-SHIFT -- DROPEFFECT_LINK +** +** Default Drop: this depends on the type of the target application. +** this is re-interpretable by each target application. a typical +** interpretation is if the drag is local to the same document +** (which is source of the drag) then a MOVE operation is +** performed. if the drag is not local, then a COPY operation is +** performed. +*/ +#define OleStdGetDropEffect(grfKeyState) \ + ( (grfKeyState & MK_CONTROL) ? \ + ( (grfKeyState & MK_SHIFT) ? DROPEFFECT_LINK : DROPEFFECT_COPY ) : \ + ( (grfKeyState & MK_SHIFT) ? DROPEFFECT_MOVE : 0 ) ) + + +/* The OLEUIPASTEFLAG enumeration is used by the OLEUIPASTEENTRY structure. + * + * OLEUIPASTE_ENABLEICON If the container does not specify this flag for the entry in the + * OLEUIPASTEENTRY array passed as input to OleUIPasteSpecial, the DisplayAsIcon button will be + * unchecked and disabled when the the user selects the format that corresponds to the entry. + * + * OLEUIPASTE_PASTEONLY Indicates that the entry in the OLEUIPASTEENTRY array is valid for pasting only. + * OLEUIPASTE_PASTE Indicates that the entry in the OLEUIPASTEENTRY array is valid for pasting. It + * may also be valid for linking if any of the following linking flags are specified. + * + * If the entry in the OLEUIPASTEENTRY array is valid for linking, the following flags indicate which link + * types are acceptable by OR'ing together the appropriate OLEUIPASTE_LINKTYPE<#> values. + * These values correspond as follows to the array of link types passed to OleUIPasteSpecial: + * OLEUIPASTE_LINKTYPE1=arrLinkTypes[0] + * OLEUIPASTE_LINKTYPE2=arrLinkTypes[1] + * OLEUIPASTE_LINKTYPE3=arrLinkTypes[2] + * OLEUIPASTE_LINKTYPE4=arrLinkTypes[3] + * OLEUIPASTE_LINKTYPE5=arrLinkTypes[4] + * OLEUIPASTE_LINKTYPE6=arrLinkTypes[5] + * OLEUIPASTE_LINKTYPE7=arrLinkTypes[6] + * OLEUIPASTE_LINKTYPE8=arrLinkTypes[7] + * + * where, + * UINT arrLinkTypes[8] is an array of registered clipboard formats for linking. A maximium of 8 link + * types are allowed. + */ + +typedef enum tagOLEUIPASTEFLAG +{ + OLEUIPASTE_ENABLEICON = 2048, // enable display as icon + OLEUIPASTE_PASTEONLY = 0, + OLEUIPASTE_PASTE = 512, + OLEUIPASTE_LINKANYTYPE = 1024, + OLEUIPASTE_LINKTYPE1 = 1, + OLEUIPASTE_LINKTYPE2 = 2, + OLEUIPASTE_LINKTYPE3 = 4, + OLEUIPASTE_LINKTYPE4 = 8, + OLEUIPASTE_LINKTYPE5 = 16, + OLEUIPASTE_LINKTYPE6 = 32, + OLEUIPASTE_LINKTYPE7 = 64, + OLEUIPASTE_LINKTYPE8 = 128 +} OLEUIPASTEFLAG; + +/* + * PasteEntry structure + * -------------------- + * An array of OLEUIPASTEENTRY entries is specified for the PasteSpecial dialog + * box. Each entry includes a FORMATETC which specifies the formats that are + * acceptable, a string that is to represent the format in the dialog's list + * box, a string to customize the result text of the dialog and a set of flags + * from the OLEUIPASTEFLAG enumeration. The flags indicate if the entry is + * valid for pasting only, linking only or both pasting and linking. If the + * entry is valid for linking, the flags indicate which link types are + * acceptable by OR'ing together the appropriate OLEUIPASTE_LINKTYPE<#> values. + * These values correspond to the array of link types as follows: + * OLEUIPASTE_LINKTYPE1=arrLinkTypes[0] + * OLEUIPASTE_LINKTYPE2=arrLinkTypes[1] + * OLEUIPASTE_LINKTYPE3=arrLinkTypes[2] + * OLEUIPASTE_LINKTYPE4=arrLinkTypes[3] + * OLEUIPASTE_LINKTYPE5=arrLinkTypes[4] + * OLEUIPASTE_LINKTYPE6=arrLinkTypes[5] + * OLEUIPASTE_LINKTYPE7=arrLinkTypes[6] + * OLEUIPASTE_LINKTYPE8=arrLinkTypes[7] + * UINT arrLinkTypes[8]; is an array of registered clipboard formats + * for linking. A maximium of 8 link types are allowed. + */ + +typedef struct tagOLEUIPASTEENTRY +{ + FORMATETC fmtetc; // Format that is acceptable. The paste + // dialog checks if this format is + // offered by the object on the + // clipboard and if so offers it for + // selection to the user. + LPCTSTR lpstrFormatName; // String that represents the format to the user. Any %s + // in this string is replaced by the FullUserTypeName + // of the object on the clipboard and the resulting string + // is placed in the list box of the dialog. Atmost + // one %s is allowed. The presence or absence of %s indicates + // if the result text is to indicate that data is + // being pasted or that an object that can be activated by + // an application is being pasted. If %s is + // present, the result-text says that an object is being pasted. + // Otherwise it says that data is being pasted. + LPCTSTR lpstrResultText; // String to customize the result text of the dialog when + // the user selects the format correspoding to this + // entry. Any %s in this string is replaced by the the application + // name or FullUserTypeName of the object on + // the clipboard. Atmost one %s is allowed. + DWORD dwFlags; // Values from OLEUIPASTEFLAG enum + DWORD dwScratchSpace; // Scratch space available to be used + // by routines which loop through an + // IEnumFORMATETC* to mark if the + // PasteEntry format is available. + // this field CAN be left uninitialized. +} OLEUIPASTEENTRY, *POLEUIPASTEENTRY, FAR *LPOLEUIPASTEENTRY; + +#define OLESTDDROP_NONE 0 +#define OLESTDDROP_DEFAULT 1 +#define OLESTDDROP_NONDEFAULT 2 + + +/* + * Some misc stuff + */ + +#define EMBEDDINGFLAG "Embedding" // Cmd line switch for launching a srvr + +#define HIMETRIC_PER_INCH 2540 // number HIMETRIC units per inch +#define PTS_PER_INCH 72 // number points (font size) per inch + +#define MAP_PIX_TO_LOGHIM(x,ppli) MulDiv(HIMETRIC_PER_INCH, (x), (ppli)) +#define MAP_LOGHIM_TO_PIX(x,ppli) MulDiv((ppli), (x), HIMETRIC_PER_INCH) + +// Returns TRUE if all fields of the two Rect's are equal, else FALSE. +#define AreRectsEqual(lprc1, lprc2) \ + (((lprc1->top == lprc2->top) && \ + (lprc1->left == lprc2->left) && \ + (lprc1->right == lprc2->right) && \ + (lprc1->bottom == lprc2->bottom)) ? TRUE : FALSE) + +/* lstrcpyn is defined to be able to handle UNICODE string + * The third parameter here is the number of CHARACTERS that are + * to be copied. + */ +#define LSTRCPYN(lpdst, lpsrc, cch) \ +(\ + (lpdst)[(cch)-1] = '\0', \ + (cch>1 ? lstrcpyn(lpdst, lpsrc, (cch)-1) : 0)\ +) + + +/****** DEBUG Stuff *****************************************************/ + +#ifdef _DEBUG + +#if !defined( _DBGTRACE ) +#define _DEBUGLEVEL 2 +#else +#define _DEBUGLEVEL _DBGTRACE +#endif + + +#if defined( NOASSERT ) + +#define OLEDBGASSERTDATA +#define OleDbgAssert(a) +#define OleDbgAssertSz(a, b) +#define OleDbgVerify(a) +#define OleDbgVerifySz(a, b) + +#else // ! NOASSERT + +STDAPI FnAssert(LPSTR lpstrExpr, LPSTR lpstrMsg, LPSTR lpstrFileName, UINT iLine); + +#define OLEDBGASSERTDATA \ + static char _based(_segname("_CODE")) _szAssertFile[]= TEXT(__FILE__); + +#define OleDbgAssert(a) \ + (!(a) ? FnAssert(#a, NULL, _szAssertFile, __LINE__) : (HRESULT)1) + +#define OleDbgAssertSz(a, b) \ + (!(a) ? FnAssert(#a, b, _szAssertFile, __LINE__) : (HRESULT)1) + +#define OleDbgVerify(a) \ + OleDbgAssert(a) + +#define OleDbgVerifySz(a, b) \ + OleDbgAssertSz(a, b) + +#endif // ! NOASSERT + +#ifdef DLL_VER +#define OLEDBGDATA_MAIN(szPrefix) \ + TCHAR NEAR g_szDbgPrefix[] = szPrefix; \ + OLEDBGASSERTDATA +#define OLEDBGDATA \ + extern TCHAR NEAR g_szDbgPrefix[]; \ + OLEDBGASSERTDATA +#else +#define OLEDBGDATA_MAIN(szPrefix) \ + TCHAR g_szDbgPrefix[] = szPrefix; \ + OLEDBGASSERTDATA +#define OLEDBGDATA \ + extern TCHAR g_szDbgPrefix[]; \ + OLEDBGASSERTDATA +#endif + +#define OLEDBG_BEGIN(lpsz) \ + OleDbgPrintAlways(g_szDbgPrefix,lpsz,1); + +#define OLEDBG_END \ + OleDbgPrintAlways(g_szDbgPrefix,TEXT("End\r\n"),-1); + +#define OleDbgOut(lpsz) \ + OleDbgPrintAlways(g_szDbgPrefix,lpsz,0) + +#define OleDbgOutNoPrefix(lpsz) \ + OleDbgPrintAlways(TEXT(""),lpsz,0) + +#define OleDbgOutRefCnt(lpsz,lpObj,refcnt) \ + OleDbgPrintRefCntAlways(g_szDbgPrefix,lpsz,lpObj,(ULONG)refcnt) + +#define OleDbgOutRect(lpsz,lpRect) \ + OleDbgPrintRectAlways(g_szDbgPrefix,lpsz,lpRect) + +#define OleDbgOutHResult(lpsz,hr) \ + OleDbgPrintScodeAlways(g_szDbgPrefix,lpsz,GetScode(hr)) + +#define OleDbgOutScode(lpsz,sc) \ + OleDbgPrintScodeAlways(g_szDbgPrefix,lpsz,sc) + +#define OleDbgOut1(lpsz) \ + OleDbgPrint(1,g_szDbgPrefix,lpsz,0) + +#define OleDbgOutNoPrefix1(lpsz) \ + OleDbgPrint(1,TEXT(""),lpsz,0) + +#define OLEDBG_BEGIN1(lpsz) \ + OleDbgPrint(1,g_szDbgPrefix,lpsz,1); + +#define OLEDBG_END1 \ + OleDbgPrint(1,g_szDbgPrefix,TEXT("End\r\n"),-1); + +#define OleDbgOutRefCnt1(lpsz,lpObj,refcnt) \ + OleDbgPrintRefCnt(1,g_szDbgPrefix,lpsz,lpObj,(ULONG)refcnt) + +#define OleDbgOutRect1(lpsz,lpRect) \ + OleDbgPrintRect(1,g_szDbgPrefix,lpsz,lpRect) + +#define OleDbgOut2(lpsz) \ + OleDbgPrint(2,g_szDbgPrefix,lpsz,0) + +#define OleDbgOutNoPrefix2(lpsz) \ + OleDbgPrint(2,TEXT(""),lpsz,0) + +#define OLEDBG_BEGIN2(lpsz) \ + OleDbgPrint(2,g_szDbgPrefix,lpsz,1); + +#define OLEDBG_END2 \ + OleDbgPrint(2,g_szDbgPrefix, TEXT("End\r\n"),-1); + +#define OleDbgOutRefCnt2(lpsz,lpObj,refcnt) \ + OleDbgPrintRefCnt(2,g_szDbgPrefix,lpsz,lpObj,(ULONG)refcnt) + +#define OleDbgOutRect2(lpsz,lpRect) \ + OleDbgPrintRect(2,g_szDbgPrefix,lpsz,lpRect) + +#define OleDbgOut3(lpsz) \ + OleDbgPrint(3,g_szDbgPrefix,lpsz,0) + +#define OleDbgOutNoPrefix3(lpsz) \ + OleDbgPrint(3,TEXT(""),lpsz,0) + +#define OLEDBG_BEGIN3(lpsz) \ + OleDbgPrint(3,g_szDbgPrefix,lpsz,1); + +#define OLEDBG_END3 \ + OleDbgPrint(3,g_szDbgPrefix,TEXT("End\r\n"),-1); + +#define OleDbgOutRefCnt3(lpsz,lpObj,refcnt) \ + OleDbgPrintRefCnt(3,g_szDbgPrefix,lpsz,lpObj,(ULONG)refcnt) + +#define OleDbgOutRect3(lpsz,lpRect) \ + OleDbgPrintRect(3,g_szDbgPrefix,lpsz,lpRect) + +#define OleDbgOut4(lpsz) \ + OleDbgPrint(4,g_szDbgPrefix,lpsz,0) + +#define OleDbgOutNoPrefix4(lpsz) \ + OleDbgPrint(4,TEXT(""),lpsz,0) + +#define OLEDBG_BEGIN4(lpsz) \ + OleDbgPrint(4,g_szDbgPrefix,lpsz,1); + +#define OLEDBG_END4 \ + OleDbgPrint(4,g_szDbgPrefix,TEXT("End\r\n"),-1); + +#define OleDbgOutRefCnt4(lpsz,lpObj,refcnt) \ + OleDbgPrintRefCnt(4,g_szDbgPrefix,lpsz,lpObj,(ULONG)refcnt) + +#define OleDbgOutRect4(lpsz,lpRect) \ + OleDbgPrintRect(4,g_szDbgPrefix,lpsz,lpRect) + +#else // !_DEBUG + +#define OLEDBGDATA_MAIN(szPrefix) +#define OLEDBGDATA +#define OleDbgAssert(a) +#define OleDbgAssertSz(a, b) +#define OleDbgVerify(a) (a) +#define OleDbgVerifySz(a, b) (a) +#define OleDbgOutHResult(lpsz,hr) +#define OleDbgOutScode(lpsz,sc) +#define OLEDBG_BEGIN(lpsz) +#define OLEDBG_END +#define OleDbgOut(lpsz) +#define OleDbgOut1(lpsz) +#define OleDbgOut2(lpsz) +#define OleDbgOut3(lpsz) +#define OleDbgOut4(lpsz) +#define OleDbgOutNoPrefix(lpsz) +#define OleDbgOutNoPrefix1(lpsz) +#define OleDbgOutNoPrefix2(lpsz) +#define OleDbgOutNoPrefix3(lpsz) +#define OleDbgOutNoPrefix4(lpsz) +#define OLEDBG_BEGIN1(lpsz) +#define OLEDBG_BEGIN2(lpsz) +#define OLEDBG_BEGIN3(lpsz) +#define OLEDBG_BEGIN4(lpsz) +#define OLEDBG_END1 +#define OLEDBG_END2 +#define OLEDBG_END3 +#define OLEDBG_END4 +#define OleDbgOutRefCnt(lpsz,lpObj,refcnt) +#define OleDbgOutRefCnt1(lpsz,lpObj,refcnt) +#define OleDbgOutRefCnt2(lpsz,lpObj,refcnt) +#define OleDbgOutRefCnt3(lpsz,lpObj,refcnt) +#define OleDbgOutRefCnt4(lpsz,lpObj,refcnt) +#define OleDbgOutRect(lpsz,lpRect) +#define OleDbgOutRect1(lpsz,lpRect) +#define OleDbgOutRect2(lpsz,lpRect) +#define OleDbgOutRect3(lpsz,lpRect) +#define OleDbgOutRect4(lpsz,lpRect) + +#endif // _DEBUG + + +/************************************************************************* +** Function prototypes +*************************************************************************/ + + +//OLESTD.C +STDAPI_(int) SetDCToAnisotropic(HDC hDC, LPRECT lprcPhysical, LPRECT lprcLogical, LPRECT lprcWindowOld, LPRECT lprcViewportOld); +STDAPI_(int) SetDCToDrawInHimetricRect(HDC, LPRECT, LPRECT, LPRECT, LPRECT); +STDAPI_(int) ResetOrigDC(HDC, int, LPRECT, LPRECT); + +STDAPI_(int) XformWidthInHimetricToPixels(HDC, int); +STDAPI_(int) XformWidthInPixelsToHimetric(HDC, int); +STDAPI_(int) XformHeightInHimetricToPixels(HDC, int); +STDAPI_(int) XformHeightInPixelsToHimetric(HDC, int); + +STDAPI_(void) XformRectInPixelsToHimetric(HDC, LPRECT, LPRECT); +STDAPI_(void) XformRectInHimetricToPixels(HDC, LPRECT, LPRECT); +STDAPI_(void) XformSizeInPixelsToHimetric(HDC, LPSIZEL, LPSIZEL); +STDAPI_(void) XformSizeInHimetricToPixels(HDC, LPSIZEL, LPSIZEL); +STDAPI_(int) XformWidthInHimetricToPixels(HDC, int); +STDAPI_(int) XformWidthInPixelsToHimetric(HDC, int); +STDAPI_(int) XformHeightInHimetricToPixels(HDC, int); +STDAPI_(int) XformHeightInPixelsToHimetric(HDC, int); + +STDAPI_(void) ParseCmdLine(LPSTR, BOOL FAR *, LPSTR); + +STDAPI_(BOOL) OleStdIsOleLink(LPUNKNOWN lpUnk); +STDAPI_(LPUNKNOWN) OleStdQueryInterface(LPUNKNOWN lpUnk, REFIID riid); +STDAPI_(LPSTORAGE) OleStdCreateRootStorage(LPTSTR lpszStgName, DWORD grfMode); +STDAPI_(LPSTORAGE) OleStdOpenRootStorage(LPTSTR lpszStgName, DWORD grfMode); +STDAPI_(LPSTORAGE) OleStdOpenOrCreateRootStorage(LPTSTR lpszStgName, DWORD grfMode); +STDAPI_(LPSTORAGE) OleStdCreateChildStorage(LPSTORAGE lpStg, LPTSTR lpszStgName); +STDAPI_(LPSTORAGE) OleStdOpenChildStorage(LPSTORAGE lpStg, LPTSTR lpszStgName, DWORD grfMode); +STDAPI_(BOOL) OleStdCommitStorage(LPSTORAGE lpStg); +STDAPI OleStdDestroyAllElements(LPSTORAGE lpStg); + +STDAPI_(LPSTORAGE) OleStdCreateStorageOnHGlobal( + HANDLE hGlobal, + BOOL fDeleteOnRelease, + DWORD dwgrfMode +); +STDAPI_(LPSTORAGE) OleStdCreateTempStorage(BOOL fUseMemory, DWORD grfMode); +STDAPI OleStdDoConvert(LPSTORAGE lpStg, REFCLSID rClsidNew); +STDAPI_(BOOL) OleStdGetTreatAsFmtUserType( + REFCLSID rClsidApp, + LPSTORAGE lpStg, + CLSID FAR* lpclsid, + CLIPFORMAT FAR* lpcfFmt, + LPTSTR FAR* lplpszType +); +STDAPI OleStdDoTreatAsClass(LPTSTR lpszUserType, REFCLSID rclsid, REFCLSID rclsidNew); +STDAPI_(BOOL) OleStdSetupAdvises(LPOLEOBJECT lpOleObject, DWORD dwDrawAspect, + LPTSTR lpszContainerApp, LPTSTR lpszContainerObj, + LPADVISESINK lpAdviseSink, BOOL fCreate); +STDAPI OleStdSwitchDisplayAspect( + LPOLEOBJECT lpOleObj, + LPDWORD lpdwCurAspect, + DWORD dwNewAspect, + HGLOBAL hMetaPict, + BOOL fDeleteOldAspect, + BOOL fSetupViewAdvise, + LPADVISESINK lpAdviseSink, + BOOL FAR* lpfMustUpdate +); +STDAPI OleStdSetIconInCache(LPOLEOBJECT lpOleObj, HGLOBAL hMetaPict); +STDAPI_(HGLOBAL) OleStdGetData( + LPDATAOBJECT lpDataObj, + CLIPFORMAT cfFormat, + DVTARGETDEVICE FAR* lpTargetDevice, + DWORD dwAspect, + LPSTGMEDIUM lpMedium +); +STDAPI_(void) OleStdMarkPasteEntryList( + LPDATAOBJECT lpSrcDataObj, + LPOLEUIPASTEENTRY lpPriorityList, + int cEntries +); +STDAPI_(int) OleStdGetPriorityClipboardFormat( + LPDATAOBJECT lpSrcDataObj, + LPOLEUIPASTEENTRY lpPriorityList, + int cEntries +); +STDAPI_(BOOL) OleStdIsDuplicateFormat( + LPFORMATETC lpFmtEtc, + LPFORMATETC arrFmtEtc, + int nFmtEtc +); +STDAPI_(void) OleStdRegisterAsRunning(LPUNKNOWN lpUnk, LPMONIKER lpmkFull, DWORD FAR* lpdwRegister); +STDAPI_(void) OleStdRevokeAsRunning(DWORD FAR* lpdwRegister); +STDAPI_(void) OleStdNoteFileChangeTime(LPTSTR lpszFileName, DWORD dwRegister); +STDAPI_(void) OleStdNoteObjectChangeTime(DWORD dwRegister); +STDAPI OleStdGetOleObjectData( + LPPERSISTSTORAGE lpPStg, + LPFORMATETC lpformatetc, + LPSTGMEDIUM lpMedium, + BOOL fUseMemory +); +STDAPI OleStdGetLinkSourceData( + LPMONIKER lpmk, + LPCLSID lpClsID, + LPFORMATETC lpformatetc, + LPSTGMEDIUM lpMedium +); +STDAPI_(HGLOBAL) OleStdGetObjectDescriptorData( + CLSID clsid, + DWORD dwAspect, + SIZEL sizel, + POINTL pointl, + DWORD dwStatus, + LPTSTR lpszFullUserTypeName, + LPTSTR lpszSrcOfCopy +); +STDAPI_(HGLOBAL) OleStdGetObjectDescriptorDataFromOleObject( + LPOLEOBJECT lpOleObj, + LPTSTR lpszSrcOfCopy, + DWORD dwAspect, + POINTL pointl, + LPSIZEL lpSizelHim +); +STDAPI_(HGLOBAL) OleStdFillObjectDescriptorFromData( + LPDATAOBJECT lpDataObject, + LPSTGMEDIUM lpmedium, + CLIPFORMAT FAR* lpcfFmt +); +STDAPI_(HANDLE) OleStdGetMetafilePictFromOleObject( + LPOLEOBJECT lpOleObj, + DWORD dwDrawAspect, + LPSIZEL lpSizelHim, + DVTARGETDEVICE FAR* ptd +); + +STDAPI_(void) OleStdCreateTempFileMoniker(LPTSTR lpszPrefixString, UINT FAR* lpuUnique, LPTSTR lpszName, LPMONIKER FAR* lplpmk); +STDAPI_(LPMONIKER) OleStdGetFirstMoniker(LPMONIKER lpmk); +STDAPI_(ULONG) OleStdGetLenFilePrefixOfMoniker(LPMONIKER lpmk); +STDAPI OleStdMkParseDisplayName( + REFCLSID rClsid, + LPBC lpbc, + LPTSTR lpszUserName, + ULONG FAR* lpchEaten, + LPMONIKER FAR* lplpmk +); +STDAPI_(LPVOID) OleStdMalloc(ULONG ulSize); +STDAPI_(LPVOID) OleStdRealloc(LPVOID pmem, ULONG ulSize); +STDAPI_(void) OleStdFree(LPVOID pmem); +STDAPI_(ULONG) OleStdGetSize(LPVOID pmem); +STDAPI_(void) OleStdFreeString(LPTSTR lpsz, LPMALLOC lpMalloc); +STDAPI_(LPTSTR) OleStdCopyString(LPTSTR lpszSrc, LPMALLOC lpMalloc); +STDAPI_(ULONG) OleStdGetItemToken(LPTSTR lpszSrc, LPTSTR lpszDst,int nMaxChars); + +STDAPI_(UINT) OleStdIconLabelTextOut(HDC hDC, + HFONT hFont, + int nXStart, + int nYStart, + UINT fuOptions, + RECT FAR * lpRect, + LPTSTR lpszString, + UINT cchString, + int FAR * lpDX); + +// registration database query functions +STDAPI_(UINT) OleStdGetAuxUserType(REFCLSID rclsid, + WORD wAuxUserType, + LPTSTR lpszAuxUserType, + int cch, + HKEY hKey); + +STDAPI_(UINT) OleStdGetUserTypeOfClass(REFCLSID rclsid, + LPTSTR lpszUserType, + UINT cch, + HKEY hKey); + +STDAPI_(BOOL) OleStdGetMiscStatusOfClass(REFCLSID, HKEY, DWORD FAR *); +STDAPI_(CLIPFORMAT) OleStdGetDefaultFileFormatOfClass( + REFCLSID rclsid, + HKEY hKey +); + +STDAPI_(void) OleStdInitVtbl(LPVOID lpVtbl, UINT nSizeOfVtbl); +STDMETHODIMP OleStdNullMethod(LPUNKNOWN lpThis); +STDAPI_(BOOL) OleStdCheckVtbl(LPVOID lpVtbl, UINT nSizeOfVtbl, LPTSTR lpszIface); +STDAPI_(ULONG) OleStdVerifyRelease(LPUNKNOWN lpUnk, LPTSTR lpszMsg); +STDAPI_(ULONG) OleStdRelease(LPUNKNOWN lpUnk); + +STDAPI_(HDC) OleStdCreateDC(DVTARGETDEVICE FAR* ptd); +STDAPI_(HDC) OleStdCreateIC(DVTARGETDEVICE FAR* ptd); +STDAPI_(DVTARGETDEVICE FAR*) OleStdCreateTargetDevice(LPPRINTDLG lpPrintDlg); +STDAPI_(BOOL) OleStdDeleteTargetDevice(DVTARGETDEVICE FAR* ptd); +STDAPI_(DVTARGETDEVICE FAR*) OleStdCopyTargetDevice(DVTARGETDEVICE FAR* ptdSrc); +STDAPI_(BOOL) OleStdCopyFormatEtc(LPFORMATETC petcDest, LPFORMATETC petcSrc); +STDAPI_(int) OleStdCompareFormatEtc(FORMATETC FAR* pFetcLeft, FORMATETC FAR* pFetcRight); +STDAPI_(BOOL) OleStdCompareTargetDevice + (DVTARGETDEVICE FAR* ptdLeft, DVTARGETDEVICE FAR* ptdRight); + + +STDAPI_(void) OleDbgPrint( + int nDbgLvl, + LPTSTR lpszPrefix, + LPTSTR lpszMsg, + int nIndent +); +STDAPI_(void) OleDbgPrintAlways(LPTSTR lpszPrefix, LPTSTR lpszMsg, int nIndent); +STDAPI_(void) OleDbgSetDbgLevel(int nDbgLvl); +STDAPI_(int) OleDbgGetDbgLevel( void ); +STDAPI_(void) OleDbgIndent(int n); +STDAPI_(void) OleDbgPrintRefCnt( + int nDbgLvl, + LPTSTR lpszPrefix, + LPTSTR lpszMsg, + LPVOID lpObj, + ULONG refcnt +); +STDAPI_(void) OleDbgPrintRefCntAlways( + LPTSTR lpszPrefix, + LPTSTR lpszMsg, + LPVOID lpObj, + ULONG refcnt +); +STDAPI_(void) OleDbgPrintRect( + int nDbgLvl, + LPTSTR lpszPrefix, + LPTSTR lpszMsg, + LPRECT lpRect +); +STDAPI_(void) OleDbgPrintRectAlways( + LPTSTR lpszPrefix, + LPTSTR lpszMsg, + LPRECT lpRect +); +STDAPI_(void) OleDbgPrintScodeAlways(LPTSTR lpszPrefix, LPTSTR lpszMsg, SCODE sc); + +// debug implementation of the IMalloc interface. +STDAPI OleStdCreateDbAlloc(ULONG reserved, IMalloc FAR* FAR* ppmalloc); + + +STDAPI_(LPENUMFORMATETC) + OleStdEnumFmtEtc_Create(ULONG nCount, LPFORMATETC lpEtc); + +STDAPI_(LPENUMSTATDATA) + OleStdEnumStatData_Create(ULONG nCount, LPSTATDATA lpStat); + +STDAPI_(BOOL) + OleStdCopyStatData(LPSTATDATA pDest, LPSTATDATA pSrc); + +STDAPI_(HPALETTE) + OleStdCreateStandardPalette(void); + +#if defined( OBSOLETE ) + +/************************************************************************* +** The following API's have been converted into macros: +** OleStdQueryOleObjectData +** OleStdQueryLinkSourceData +** OleStdQueryObjectDescriptorData +** OleStdQueryFormatMedium +** OleStdCopyMetafilePict +** AreRectsEqual +** OleStdGetDropEffect +** +** These macros are defined above +*************************************************************************/ +STDAPI_(BOOL) AreRectsEqual(LPRECT lprc1, LPRECT lprc2); +STDAPI_(BOOL) OleStdCopyMetafilePict(HANDLE hpictin, HANDLE FAR* phpictout); +STDAPI OleStdQueryOleObjectData(LPFORMATETC lpformatetc); +STDAPI OleStdQueryLinkSourceData(LPFORMATETC lpformatetc); +STDAPI OleStdQueryObjectDescriptorData(LPFORMATETC lpformatetc); +STDAPI OleStdQueryFormatMedium(LPFORMATETC lpformatetc, TYMED tymed); +STDAPI_(DWORD) OleStdGetDropEffect ( DWORD grfKeyState ); +#endif // OBSOLETE + + +#endif // _OLESTD_H_ + diff --git a/private/oleutest/letest/ole2ui/olestr.c b/private/oleutest/letest/ole2ui/olestr.c new file mode 100644 index 000000000..e7e8e93fa --- /dev/null +++ b/private/oleutest/letest/ole2ui/olestr.c @@ -0,0 +1,32 @@ +void CopyAndFreeOLESTR(LPOLESTR polestr, char **ppszOut) +{ + // See if there is any work + if (polestr == NULL) + { + if (ppszOut != NULL) + { + // Output string requested so set it to NULL. + *ppszOut = NULL; + } + + return; + } + + // Get the public memory allocator + + if (pszOut) + { + // Copy of string converted to ANSI is requested + } + + // Free the original string +} + +LPOLESTR CreateOLESTR(char *pszIn) +{ + // Get the public memory allocator + + // Allocate the string + + // Convert the string +} diff --git a/private/oleutest/letest/ole2ui/olestr.h b/private/oleutest/letest/ole2ui/olestr.h new file mode 100644 index 000000000..a9c282930 --- /dev/null +++ b/private/oleutest/letest/ole2ui/olestr.h @@ -0,0 +1,21 @@ +#ifndef _OLESTR_H_ +#define _OLESTR_H_ + +void CopyAndFreeOLESTR(LPOLESTR polestr, char **pszOut); + +void CopyAndFreeSTR(LPSTR polestr, LPOLESTR *pszOut); + +LPOLESTR CreateOLESTR(const char *pszIn); +LPSTR CreateSTR(LPCOLESTR pszIn); + +#define CREATEOLESTR(x, y) LPOLESTR x = CreateOLESTR(y); + +#define CREATESTR(x, y) LPSTR x = CreateSTR(y); + +#define FREEOLESTR(x) CopyAndFreeOLESTR(x, NULL); + +#define FREESTR(x) CopyAndFreeSTR(x, NULL); + + + +#endif // _OLESTR_H_ diff --git a/private/oleutest/letest/ole2ui/olethunk.c b/private/oleutest/letest/ole2ui/olethunk.c new file mode 100644 index 000000000..a69c3102d --- /dev/null +++ b/private/oleutest/letest/ole2ui/olethunk.c @@ -0,0 +1,649 @@ +#include +#include +#include "olethunk.h" + +STDAPI_(LPVOID) OleStdMalloc(ULONG ulSize); + +STDAPI_(void) OleStdFree(LPVOID pmem); + + +STDAPI_(void) CopyAndFreeOLESTR(LPOLESTR polestr, LPSTR *ppszOut) +{ + // See if there is any work + if (polestr == NULL) + { + if (ppszOut != NULL) + { + // Output string requested so set it to NULL. + *ppszOut = NULL; + } + + return; + } + + if (ppszOut) + { + // Copy of string converted to ANSI is requested + int len = wcslen(polestr) + 1; + *ppszOut = OleStdMalloc(len); + + if (*ppszOut) + { + wcstombs(*ppszOut, polestr, len); + } + } + + // Free the original string + OleStdFree(polestr); +} + + + + +STDAPI_(void) CopyAndFreeSTR(LPSTR pstr, LPOLESTR *ppolestrOut) +{ + // See if there is any work + if (pstr == NULL) + { + if (ppolestrOut != NULL) + { + // Output string requested so set it to NULL. + *ppolestrOut = NULL; + } + + return; + } + + if (ppolestrOut) + { + // Copy of string converted to ANSI is requested + int len = strlen(pstr) + 1; + *ppolestrOut = OleStdMalloc(len * sizeof(WCHAR)); + + if (*ppolestrOut) + { + mbstowcs(*ppolestrOut, pstr, len); + } + } + + // Free the original string + OleStdFree(pstr); +} + + + +STDAPI_(LPOLESTR) CreateOLESTR(LPCSTR pszIn) +{ + // Return NULL if there was no string input + LPOLESTR polestr = NULL; + + if (pszIn != NULL) + { + // Calculate size of string to allocate + int len = strlen(pszIn) + 1; + + // Allocate the string + polestr = (LPOLESTR) OleStdMalloc(len * sizeof(OLECHAR)); + + // Convert the string + if (polestr) + { + mbstowcs(polestr, pszIn, len); + } + } + + return polestr; +} + + + +STDAPI_(LPSTR) CreateSTR(LPCOLESTR polestrIn) +{ + // Return NULL if there was no string input + LPSTR pstr = NULL; + + if (polestrIn != NULL) + { + // Calculate size of string to allocate + int len = wcslen(polestrIn) + 1; + + // Allocate the string + pstr = (PSTR) OleStdMalloc(len); + + // Convert the string + if (pstr) + { + wcstombs(pstr, polestrIn, len); + } + } + + return pstr; +} + + + + +STDAPI_(void) CLSIDFromStringA(LPSTR pszClass, LPCLSID pclsid) +{ + CREATEOLESTR(polestr, pszClass) + + CLSIDFromString(polestr, pclsid); + + FREEOLESTR(polestr) +} + + + +STDAPI CreateFileMonikerA(LPSTR lpszPathName, LPMONIKER FAR* ppmk) +{ + CREATEOLESTR(polestr, lpszPathName) + + HRESULT hr = CreateFileMoniker(polestr, ppmk); + + FREEOLESTR(polestr) + + return hr; +} + + + +STDAPI CreateItemMonikerA( + LPSTR lpszDelim, + LPSTR lpszItem, + LPMONIKER FAR* ppmk) +{ + CREATEOLESTR(polestrDelim, lpszDelim) + CREATEOLESTR(polestrItem, lpszItem) + + HRESULT hr = CreateItemMoniker(polestrDelim, polestrItem, ppmk); + + FREEOLESTR(polestrDelim) + FREEOLESTR(polestrItem) + + return hr; +} + + + +STDAPI_(HGLOBAL) OleGetIconOfClassA( + REFCLSID rclsid, + LPSTR lpszLabel, + BOOL fUseTypeAsLabel) +{ + CREATEOLESTR(polestr, lpszLabel) + + HGLOBAL hglobal = OleGetIconOfClass(rclsid, polestr, fUseTypeAsLabel); + + FREEOLESTR(polestr) + + return hglobal; +} + + + +STDAPI_(HGLOBAL) OleGetIconOfFileA(LPSTR lpszPath, BOOL fUseFileAsLabel) +{ + CREATEOLESTR(polestr, lpszPath) + + HGLOBAL hMetaPict = OleGetIconOfFile(polestr, fUseFileAsLabel); + + FREEOLESTR(polestr) + + return hMetaPict; +} + + + + +STDAPI_(HGLOBAL) OleMetafilePictFromIconAndLabelA( + HICON hIcon, + LPSTR lpszLabel, + LPSTR lpszSourceFile, + UINT iIconIndex) +{ + CREATEOLESTR(polestrLabel, lpszLabel) + CREATEOLESTR(polestrSourceFile, lpszSourceFile) + + HGLOBAL hglobal = OleMetafilePictFromIconAndLabel(hIcon, polestrLabel, + polestrSourceFile, iIconIndex); + + FREEOLESTR(polestrLabel) + FREEOLESTR(polestrSourceFile) + + return hglobal; +} + + + + +STDAPI GetClassFileA(LPCSTR szFilename, CLSID FAR* pclsid) +{ + CREATEOLESTR(polestr, szFilename) + + HRESULT hr = GetClassFile(polestr, pclsid); + + FREEOLESTR(polestr) + + return hr; +} + + + +STDAPI CLSIDFromProgIDA(LPCSTR lpszProgID, LPCLSID lpclsid) +{ + CREATEOLESTR(polestr, lpszProgID) + + HRESULT hr = CLSIDFromProgID(polestr, lpclsid); + + FREEOLESTR(polestr) + + return hr; +} + +STDAPI MkParseDisplayNameA( + LPBC pbc, + LPSTR szUserName, + ULONG FAR * pchEaten, + LPMONIKER FAR * ppmk) +{ + CREATEOLESTR(polestr, szUserName) + + HRESULT hr = MkParseDisplayName(pbc, polestr, pchEaten, ppmk); + + FREEOLESTR(polestr) + + return hr; +} + + + + +STDAPI OleCreateLinkToFileA( + LPCSTR lpszFileName, + REFIID riid, + DWORD renderopt, + LPFORMATETC lpFormatEtc, + LPOLECLIENTSITE pClientSite, + LPSTORAGE pStg, + LPVOID FAR* ppvObj) +{ + CREATEOLESTR(polestr, lpszFileName) + + HRESULT hr = OleCreateLinkToFile(polestr, riid, renderopt, lpFormatEtc, + pClientSite, pStg, ppvObj); + + FREEOLESTR(polestr) + + return hr; +} + + +STDAPI OleCreateFromFileA( + REFCLSID rclsid, + LPCSTR lpszFileName, + REFIID riid, + DWORD renderopt, + LPFORMATETC lpFormatEtc, + LPOLECLIENTSITE pClientSite, + LPSTORAGE pStg, + LPVOID FAR* ppvObj) +{ + CREATEOLESTR(polestr, lpszFileName) + + HRESULT hr = OleCreateFromFile(rclsid, polestr, riid, renderopt, + lpFormatEtc, pClientSite, pStg, ppvObj); + + FREEOLESTR(polestr) + + return hr; +} + + + +STDAPI OleRegGetUserTypeA( + REFCLSID clsid, + DWORD dwFormOfType, + LPSTR FAR* ppszUserType) +{ + LPOLESTR polestr; + + HRESULT hr = OleRegGetUserType(clsid, dwFormOfType, &polestr); + + CopyAndFreeOLESTR(polestr, ppszUserType); + + return hr; +} + + + +STDAPI ProgIDFromCLSIDA(REFCLSID clsid, LPSTR FAR* lplpszProgID) +{ + LPOLESTR polestr; + + HRESULT hr = ProgIDFromCLSID(clsid, &polestr); + + CopyAndFreeOLESTR(polestr, lplpszProgID); + + return hr; +} + + + +STDAPI ReadFmtUserTypeStgA( + LPSTORAGE pstg, + CLIPFORMAT FAR* pcf, + LPSTR FAR* lplpszUserType) +{ + LPOLESTR polestr; + + HRESULT hr = ReadFmtUserTypeStg(pstg, pcf, &polestr); + + CopyAndFreeOLESTR(polestr, lplpszUserType); + + return hr; +} + + + + + + +STDAPI StgCreateDocfileA( + LPCSTR lpszName, + DWORD grfMode, + DWORD reserved, + IStorage FAR * FAR *ppstgOpen) +{ + HRESULT hr; + LPOLESTR polestr = NULL; + + if (lpszName != NULL) + { + polestr = CreateOLESTR(lpszName); + } + + hr = StgCreateDocfile(polestr, grfMode, reserved, ppstgOpen); + + FREEOLESTR(polestr) + + return hr; +} + + + + +STDAPI StgOpenStorageA( + LPCSTR lpszName, + IStorage FAR *pstgPriority, + DWORD grfMode, + SNB snbExclude, + DWORD reserved, + IStorage FAR * FAR *ppstgOpen) +{ + CREATEOLESTR(polestr, lpszName) + + HRESULT hr = StgOpenStorage(polestr, pstgPriority, grfMode, snbExclude, + reserved, ppstgOpen); + + FREEOLESTR(polestr) + + return hr; +} + + + +STDAPI StgSetTimesA( + LPSTR lpszName, + FILETIME const FAR* pctime, + FILETIME const FAR* patime, + FILETIME const FAR* pmtime) +{ + CREATEOLESTR(polestr, lpszName) + + HRESULT hr = StgSetTimes(polestr, pctime, patime, pmtime); + + FREEOLESTR(polestr) + + return hr; +} + + + + +STDAPI_(void) StringFromCLSIDA(REFCLSID rclsid, LPSTR *lplpszCLSID) +{ + LPOLESTR polestr; + + StringFromCLSID(rclsid, &polestr); + + CopyAndFreeOLESTR(polestr, lplpszCLSID); +} + + +STDAPI WriteFmtUserTypeStgA( + LPSTORAGE lpStg, + CLIPFORMAT cf, + LPSTR lpszUserType) +{ + CREATEOLESTR(polestr, lpszUserType) + + HRESULT hr = WriteFmtUserTypeStg(lpStg, cf, polestr); + + FREEOLESTR(polestr) + + return hr; +} + + + + + + + +STDAPI CallIMonikerGetDisplayNameA( + LPMONIKER lpmk, + IBindCtx *pbc, + IMoniker *pmkToLeft, + LPSTR *ppszDisplayName) +{ + LPOLESTR polestr; + + HRESULT hr = lpmk->lpVtbl->GetDisplayName(lpmk, pbc, NULL, + &polestr); + + CopyAndFreeOLESTR(polestr, ppszDisplayName); + + return hr; +} + + + +STDAPI CallIOleInPlaceUIWindowSetActiveObjectA( + IOleInPlaceUIWindow FAR *lpthis, + IOleInPlaceActiveObject *pActiveObject, + LPCSTR pszObjName) +{ + CREATEOLESTR(polestr, pszObjName) + + HRESULT hr = lpthis->lpVtbl->SetActiveObject(lpthis, pActiveObject, + polestr); + + FREEOLESTR(polestr) + + return hr; +} + + + +STDAPI CallIOleInPlaceFrameSetStatusTextA( + IOleInPlaceFrame *poleinplc, + LPCSTR pszStatusText) +{ + CREATEOLESTR(polestr, pszStatusText) + + HRESULT hr = poleinplc->lpVtbl->SetStatusText(poleinplc, polestr); + + FREEOLESTR(polestr) + + return hr; +} + + + + +STDAPI CallIOleLinkGetSourceDisplayNameA( + IOleLink FAR *polelink, + LPSTR *ppszDisplayName) +{ + LPOLESTR polestr; + + HRESULT hr = polelink->lpVtbl->GetSourceDisplayName(polelink, &polestr); + + CopyAndFreeOLESTR(polestr, ppszDisplayName); + + return hr; +} + + + +STDAPI CallIOleLinkSetSourceDisplayNameA( + IOleLink FAR *polelink, + LPCSTR pszStatusText) +{ + CREATEOLESTR(polestr, pszStatusText) + + HRESULT hr = polelink->lpVtbl->SetSourceDisplayName(polelink, polestr); + + FREEOLESTR(polestr) + + return hr; +} + + + + + +STDAPI CallIOleObjectGetUserTypeA( + LPOLEOBJECT lpOleObject, + DWORD dwFormOfType, + LPSTR *ppszUserType) +{ + LPOLESTR polestr; + + HRESULT hr = lpOleObject->lpVtbl->GetUserType(lpOleObject, + dwFormOfType, &polestr); + + CopyAndFreeOLESTR(polestr, ppszUserType); + + return hr; +} + + + +STDAPI CallIOleObjectSetHostNamesA( + LPOLEOBJECT lpOleObject, + LPCSTR szContainerApp, + LPCSTR szContainerObj) +{ + CREATEOLESTR(polestrApp, szContainerApp) + CREATEOLESTR(polestrObj, szContainerObj) + + HRESULT hr = lpOleObject->lpVtbl->SetHostNames(lpOleObject, polestrApp, + polestrObj); + + FREEOLESTR(polestrApp) + FREEOLESTR(polestrObj) + + return hr; +} + +STDAPI CallIStorageDestroyElementA( + LPSTORAGE lpStg, + LPSTR pszName) +{ + CREATEOLESTR(polestr, pszName) + + HRESULT hr = lpStg->lpVtbl->DestroyElement(lpStg, polestr); + + FREEOLESTR(polestr) + + return hr; +} + + + +STDAPI CallIStorageCreateStorageA( + LPSTORAGE lpStg, + const char *pszName, + DWORD grfMode, + DWORD dwStgFmt, + DWORD reserved2, + IStorage **ppstg) +{ + CREATEOLESTR(polestr, pszName) + + HRESULT hr = lpStg->lpVtbl->CreateStorage(lpStg, polestr, grfMode, + dwStgFmt, reserved2, ppstg); + + FREEOLESTR(polestr) + + return hr; +} + + + +STDAPI CallIStorageOpenStorageA( + LPSTORAGE lpStg, + const char *pszName, + IStorage *pstgPriority, + DWORD grfMode, + SNB snbExclude, + DWORD reserved, + IStorage **ppstg) +{ + CREATEOLESTR(polestr, pszName) + + HRESULT hr = lpStg->lpVtbl->OpenStorage(lpStg, polestr, pstgPriority, + grfMode, snbExclude, reserved, ppstg); + + FREEOLESTR(polestr) + + return hr; +} + + +STDAPI CallIStorageCreateStreamA( + LPSTORAGE lpStg, + LPSTR pszName, + DWORD grfMode, + DWORD reserved1, + DWORD reserved2, + IStream **ppstm) +{ + CREATEOLESTR(polestr, pszName) + + HRESULT hr = lpStg->lpVtbl->CreateStream(lpStg, polestr, + grfMode, reserved1, reserved2, ppstm); + + FREEOLESTR(polestr) + + return hr; +} + +STDAPI CallIStorageOpenStreamA( + LPSTORAGE lpStg, + LPSTR pszName, + void *reserved1, + DWORD grfMode, + DWORD reserved2, + IStream **ppstm) +{ + CREATEOLESTR(polestr, pszName) + + HRESULT hr = lpStg->lpVtbl->OpenStream(lpStg, polestr, reserved1, + grfMode, reserved2, ppstm); + + FREEOLESTR(polestr) + + return hr; +} diff --git a/private/oleutest/letest/ole2ui/olethunk.h b/private/oleutest/letest/ole2ui/olethunk.h new file mode 100644 index 000000000..ed47a62da --- /dev/null +++ b/private/oleutest/letest/ole2ui/olethunk.h @@ -0,0 +1,193 @@ +#ifndef _OLETHUNK_H_ +#define _OLETHUNK_H_ + +// +// String Conversion Helpers +// +STDAPI_(void) CopyAndFreeOLESTR(LPOLESTR polestr, char **pszOut); + +STDAPI_(void) CopyAndFreeSTR(LPSTR polestr, LPOLESTR *pszOut); + +STDAPI_(LPOLESTR) CreateOLESTR(const char *pszIn); + +STDAPI_(LPSTR) CreateSTR(LPCOLESTR pszIn); + +#define CREATEOLESTR(x, y) LPOLESTR x = CreateOLESTR(y); + +#define CREATESTR(x, y) LPSTR x = CreateSTR(y); + +#define FREEOLESTR(x) CopyAndFreeOLESTR(x, NULL); + +#define FREESTR(x) CopyAndFreeSTR(x, NULL); + +// +// OLE API Thunks +// +STDAPI_(void) CLSIDFromStringA(LPSTR pszClass, LPCLSID pclsid); + +STDAPI CLSIDFromProgIDA(LPCSTR lpszProgID, LPCLSID lpclsid); + +STDAPI CreateFileMonikerA(LPSTR lpszPathName, LPMONIKER FAR* ppmk); + +STDAPI CreateItemMonikerA( + LPSTR lpszDelim, + LPSTR lpszItem, + LPMONIKER FAR* ppmk); + +STDAPI GetClassFileA(LPCSTR szFilename, CLSID FAR* pclsid); + +STDAPI MkParseDisplayNameA( + LPBC pbc, + LPSTR szUserName, + ULONG FAR * pchEaten, + LPMONIKER FAR * ppmk); + +STDAPI OleCreateFromFileA( + REFCLSID rclsid, + LPCSTR lpszFileName, + REFIID riid, + DWORD renderopt, + LPFORMATETC lpFormatEtc, + LPOLECLIENTSITE pClientSite, + LPSTORAGE pStg, + LPVOID FAR* ppvObj); + +STDAPI OleCreateLinkToFileA( + LPCSTR lpszFileName, + REFIID riid, + DWORD renderopt, + LPFORMATETC lpFormatEtc, + LPOLECLIENTSITE pClientSite, + LPSTORAGE pStg, + LPVOID FAR* ppvObj); + +STDAPI_(HGLOBAL) OleGetIconOfClassA( + REFCLSID rclsid, + LPSTR lpszLabel, + BOOL fUseTypeAsLabel); + +STDAPI_(HGLOBAL) OleGetIconOfFileA(LPSTR lpszPath, BOOL fUseFileAsLabel); + +STDAPI_(HGLOBAL) OleMetafilePictFromIconAndLabelA( + HICON hIcon, + LPSTR lpszLabel, + LPSTR lpszSourceFile, + UINT iIconIndex); + +STDAPI OleRegGetUserTypeA( + REFCLSID clsid, + DWORD dwFormOfType, + LPSTR FAR* pszUserType); + +STDAPI ProgIDFromCLSIDA(REFCLSID clsid, LPSTR FAR* lplpszProgID); + +STDAPI ReadFmtUserTypeStgA( + LPSTORAGE pstg, + CLIPFORMAT FAR* pcf, + LPSTR FAR* lplpszUserType); + +STDAPI StgCreateDocfileA( + LPCSTR pwcsName, + DWORD grfMode, + DWORD reserved, + IStorage FAR * FAR *ppstgOpen); + +STDAPI StgOpenStorageA( + LPCSTR pwcsName, + IStorage FAR *pstgPriority, + DWORD grfMode, + SNB snbExclude, + DWORD reserved, + IStorage FAR * FAR *ppstgOpen); + +STDAPI StgSetTimesA( + LPSTR lpszName, + FILETIME const FAR* pctime, + FILETIME const FAR* patime, + FILETIME const FAR* pmtime); + + +STDAPI_(void) StringFromCLSIDA(REFCLSID rclsid, LPSTR *lplpszCLSID); + +STDAPI WriteFmtUserTypeStgA( + LPSTORAGE pstg, + CLIPFORMAT cf, + LPSTR lpszUserType); + + + +// +// Method Thunks +// +STDAPI CallIMonikerGetDisplayNameA( + LPMONIKER lpmk, + IBindCtx *pbc, + IMoniker *pmkToLeft, + LPSTR *ppszDisplayName); + +STDAPI CallIOleLinkGetSourceDisplayNameA( + IOleLink FAR *polelink, + LPSTR *ppszDisplayName); + +STDAPI CallIOleLinkSetSourceDisplayNameA( + IOleLink FAR *polelink, + LPCSTR pszStatusText); + +STDAPI CallIOleInPlaceFrameSetStatusTextA( + IOleInPlaceFrame *poleinplc, + LPCSTR pszStatusText); + +STDAPI CallIOleInPlaceUIWindowSetActiveObjectA( + IOleInPlaceUIWindow FAR *lpthis, + IOleInPlaceActiveObject *pActiveObject, + LPCSTR pszObjName); + +STDAPI CallIOleObjectGetUserTypeA( + LPOLEOBJECT lpOleObject, + DWORD dwFormOfType, + LPSTR *pszUserType); + +STDAPI CallIOleObjectSetHostNamesA( + LPOLEOBJECT lpOleObject, + LPCSTR szContainerApp, + LPCSTR szContainerObj); + +STDAPI CallIStorageCreateStorageA( + LPSTORAGE lpStg, + const char *pwcsName, + DWORD grfMode, + DWORD dwStgFmt, + DWORD reserved2, + IStorage **ppstg); + +STDAPI CallIStorageDestroyElementA( + LPSTORAGE lpStg, + LPSTR pszName); + +STDAPI CallIStorageOpenStorageA( + LPSTORAGE lpStg, + const char *pszName, + IStorage *pstgPriority, + DWORD grfMode, + SNB snbExclude, + DWORD reserved, + IStorage **ppstg); + +STDAPI CallIStorageCreateStreamA( + LPSTORAGE lpStg, + LPSTR pszName, + DWORD grfMode, + DWORD reserved1, + DWORD reserved2, + IStream **ppstm); + +STDAPI CallIStorageOpenStreamA( + LPSTORAGE lpStg, + LPSTR pszName, + void *reserved1, + DWORD grfMode, + DWORD reserved2, + IStream **ppstm); + + +#endif // _OLETHUNK_H_ diff --git a/private/oleutest/letest/ole2ui/oleutl.c b/private/oleutest/letest/ole2ui/oleutl.c new file mode 100644 index 000000000..9c968cefd --- /dev/null +++ b/private/oleutest/letest/ole2ui/oleutl.c @@ -0,0 +1,660 @@ +/* + * OLEUTL.C + * + * Miscellaneous utility functions for OLE 2.0 Applications: + * + * Function Purpose + * ------------------------------------------------------------------- + * SetDCToDrawInHimetricRect Sets up an HIMETRIC mapping mode in a DC. + * ResetOrigDC Performs the opposite of + * SetDCToDrawInHimetricRect + * XformWidthInPixelsToHimetric Converts an int width into HiMetric units + * XformWidthInHimetricToPixels Converts an int width from HiMetric units + * XformHeightInPixelsToHimetric Converts an int height into HiMetric units + * XformHeightInHimetricToPixels Converts an int height from HiMetric units + * XformRectInPixelsToHimetric Converts a rect into HiMetric units + * XformRectInHimetricToPixels Converts a rect from HiMetric units + * XformSizeInPixelsToHimetric Converts a SIZEL into HiMetric units + * XformSizeInHimetricToPixels Converts a SIZEL from HiMetric units + * AreRectsEqual Compares to Rect's + * + * ParseCmdLine Determines if -Embedding exists + * OpenOrCreateRootStorage Creates a root docfile for OLE storage + * CommitStorage Commits all changes in a docfile + * CreateChildStorage Creates child storage in another storage + * OpenChildStorage Opens child storage in another storage + * + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + + +#define STRICT 1 +#include "ole2ui.h" +#include +#include + +//Internal function to this module. No need for UNICODE in this function +static LPSTR GetWord(LPSTR lpszSrc, LPSTR lpszDst); + + +/* + * SetDCToAnisotropic + * + * Purpose: + * Setup the correspondence between the rect in device unit (Viewport) and + * the rect in logical unit (Window) so that the proper scaling of + * coordinate systems will be calculated. set up both the Viewport and + * the window as follows: + * + * 1) ------------------ ( 2 + * | | + * | | + * | | + * | | + * | | + * 3) ------------------ ( 4 + * + * Origin = P3 + * X extent = P2x - P3x + * Y extent = P2y - P3y + * + * Parameters: + * hDC HDC to affect + * lprcPhysical LPRECT containing the physical (device) extents of DC + * lprcLogical LPRECT containing the logical extents + * lprcWindowOld LPRECT in which to preserve the window for ResetOrigDC + * lprcViewportOld LPRECT in which to preserver the viewport for ResetOrigDC + * + * Return Value: + * int The original mapping mode of the DC. + */ + +STDAPI_(int) SetDCToAnisotropic( + HDC hDC, + LPRECT lprcPhysical, LPRECT lprcLogical, + LPRECT lprcWindowOld, LPRECT lprcViewportOld) +{ + int nMapModeOld=SetMapMode(hDC, MM_ANISOTROPIC); + + SetWindowOrgEx(hDC, lprcLogical->left, lprcLogical->bottom, (LPPOINT)&lprcWindowOld->left); + SetWindowExtEx(hDC, (lprcLogical->right-lprcLogical->left), (lprcLogical->top-lprcLogical->bottom), (LPSIZE)&lprcWindowOld->right); + SetViewportOrgEx(hDC, lprcPhysical->left, lprcPhysical->bottom, (LPPOINT)&lprcViewportOld->left); + SetViewportExtEx(hDC, (lprcPhysical->right-lprcPhysical->left), (lprcPhysical->top-lprcPhysical->bottom), (LPSIZE)&lprcViewportOld->right); + + return nMapModeOld; +} + + +/* + * SetDCToDrawInHimetricRect + * + * Purpose: + * Setup the correspondence between the rect in pixels (Viewport) and + * the rect in HIMETRIC (Window) so that the proper scaling of + * coordinate systems will be calculated. set up both the Viewport and + * the window as follows: + * + * 1) ------------------ ( 2 + * | | + * | | + * | | + * | | + * | | + * 3) ------------------ ( 4 + * + * Origin = P3 + * X extent = P2x - P3x + * Y extent = P2y - P3y + * + * Parameters: + * hDC HDC to affect + * lprcPix LPRECT containing the pixel extents of DC + * lprcHiMetric LPRECT to receive the himetric extents + * lprcWindowOld LPRECT in which to preserve the window for ResetOrigDC + * lprcViewportOld LPRECT in which to preserver the viewport for ResetOrigDC + * + * Return Value: + * int The original mapping mode of the DC. + */ +STDAPI_(int) SetDCToDrawInHimetricRect( + HDC hDC, + LPRECT lprcPix, LPRECT lprcHiMetric, + LPRECT lprcWindowOld, LPRECT lprcViewportOld) + { + int nMapModeOld=SetMapMode(hDC, MM_ANISOTROPIC); + BOOL fSystemDC =FALSE; + + if (NULL==hDC) + { + hDC=GetDC(NULL); + fSystemDC=TRUE; + } + + XformRectInPixelsToHimetric(hDC, lprcPix, lprcHiMetric); + + SetWindowOrgEx(hDC, lprcHiMetric->left, lprcHiMetric->bottom, (LPPOINT)&lprcWindowOld->left); + SetWindowExtEx(hDC, (lprcHiMetric->right-lprcHiMetric->left), (lprcHiMetric->top-lprcHiMetric->bottom), (LPSIZE)&lprcWindowOld->right); + SetViewportOrgEx(hDC, lprcPix->left, lprcPix->bottom, (LPPOINT)&lprcViewportOld->left); + SetViewportExtEx(hDC, (lprcPix->right-lprcPix->left), (lprcPix->top-lprcPix->bottom), (LPSIZE)&lprcViewportOld->right); + + if (fSystemDC) + ReleaseDC(NULL, hDC); + + return nMapModeOld; + } + + + +/* + * ResetOrigDC + * + * Purpose: + * Restores a DC set to draw in himetric from SetDCToDrawInHimetricRect. + * + * Parameters: + * hDC HDC to restore + * nMapModeOld int original mapping mode of hDC + * lprcWindowOld LPRECT filled in SetDCToDrawInHimetricRect + * lprcViewportOld LPRECT filled in SetDCToDrawInHimetricRect + * + * Return Value: + * int Same as nMapModeOld. + */ + +STDAPI_(int) ResetOrigDC( + HDC hDC, int nMapModeOld, + LPRECT lprcWindowOld, LPRECT lprcViewportOld) + { + POINT pOld; + + SetMapMode(hDC, nMapModeOld); + + SetWindowOrgEx(hDC, lprcWindowOld->left, lprcWindowOld->top, (LPPOINT)&pOld); + SetWindowExtEx(hDC, lprcWindowOld->right, lprcWindowOld->bottom, (LPSIZE)&pOld); + SetViewportOrgEx(hDC, lprcViewportOld->left, lprcViewportOld->top, (LPPOINT)&pOld); + SetViewportExtEx(hDC, lprcViewportOld->right, lprcViewportOld->bottom, (LPSIZE)&pOld); + + return nMapModeOld; + } + + + +/* + * XformWidthInPixelsToHimetric + * XformWidthInHimetricToPixels + * XformHeightInPixelsToHimetric + * XformHeightInHimetricToPixels + * + * Functions to convert an int between a device coordinate system and + * logical HiMetric units. + * + * Parameters: + * hDC HDC providing reference to the pixel mapping. If + * NULL, a screen DC is used. + * + * Size Functions: + * lpSizeSrc LPSIZEL providing the structure to convert. This + * contains pixels in XformSizeInPixelsToHimetric and + * logical HiMetric units in the complement function. + * lpSizeDst LPSIZEL providing the structure to receive converted + * units. This contains pixels in + * XformSizeInPixelsToHimetric and logical HiMetric + * units in the complement function. + * + * Width Functions: + * iWidth int containing the value to convert. + * + * Return Value: + * Size Functions: None + * Width Functions: Converted value of the input parameters. + * + * NOTE: + * When displaying on the screen, Window apps display everything enlarged + * from its actual size so that it is easier to read. For example, if an + * app wants to display a 1in. horizontal line, that when printed is + * actually a 1in. line on the printed page, then it will display the line + * on the screen physically larger than 1in. This is described as a line + * that is "logically" 1in. along the display width. Windows maintains as + * part of the device-specific information about a given display device: + * LOGPIXELSX -- no. of pixels per logical in along the display width + * LOGPIXELSY -- no. of pixels per logical in along the display height + * + * The following formula converts a distance in pixels into its equivalent + * logical HIMETRIC units: + * + * DistInHiMetric = (HIMETRIC_PER_INCH * DistInPix) + * ------------------------------- + * PIXELS_PER_LOGICAL_IN + * + */ +STDAPI_(int) XformWidthInPixelsToHimetric(HDC hDC, int iWidthInPix) + { + int iXppli; //Pixels per logical inch along width + int iWidthInHiMetric; + BOOL fSystemDC=FALSE; + + if (NULL==hDC) + { + hDC=GetDC(NULL); + fSystemDC=TRUE; + } + + iXppli = GetDeviceCaps (hDC, LOGPIXELSX); + + //We got pixel units, convert them to logical HIMETRIC along the display + iWidthInHiMetric = MAP_PIX_TO_LOGHIM(iWidthInPix, iXppli); + + if (fSystemDC) + ReleaseDC(NULL, hDC); + + return iWidthInHiMetric; + } + + +STDAPI_(int) XformWidthInHimetricToPixels(HDC hDC, int iWidthInHiMetric) + { + int iXppli; //Pixels per logical inch along width + int iWidthInPix; + BOOL fSystemDC=FALSE; + + if (NULL==hDC) + { + hDC=GetDC(NULL); + fSystemDC=TRUE; + } + + iXppli = GetDeviceCaps (hDC, LOGPIXELSX); + + //We got logical HIMETRIC along the display, convert them to pixel units + iWidthInPix = MAP_LOGHIM_TO_PIX(iWidthInHiMetric, iXppli); + + if (fSystemDC) + ReleaseDC(NULL, hDC); + + return iWidthInPix; + } + + +STDAPI_(int) XformHeightInPixelsToHimetric(HDC hDC, int iHeightInPix) + { + int iYppli; //Pixels per logical inch along height + int iHeightInHiMetric; + BOOL fSystemDC=FALSE; + + if (NULL==hDC) + { + hDC=GetDC(NULL); + fSystemDC=TRUE; + } + + iYppli = GetDeviceCaps (hDC, LOGPIXELSY); + + //* We got pixel units, convert them to logical HIMETRIC along the display + iHeightInHiMetric = MAP_PIX_TO_LOGHIM(iHeightInPix, iYppli); + + if (fSystemDC) + ReleaseDC(NULL, hDC); + + return iHeightInHiMetric; + } + + +STDAPI_(int) XformHeightInHimetricToPixels(HDC hDC, int iHeightInHiMetric) + { + int iYppli; //Pixels per logical inch along height + int iHeightInPix; + BOOL fSystemDC=FALSE; + + if (NULL==hDC) + { + hDC=GetDC(NULL); + fSystemDC=TRUE; + } + + iYppli = GetDeviceCaps (hDC, LOGPIXELSY); + + //* We got logical HIMETRIC along the display, convert them to pixel units + iHeightInPix = MAP_LOGHIM_TO_PIX(iHeightInHiMetric, iYppli); + + if (fSystemDC) + ReleaseDC(NULL, hDC); + + return iHeightInPix; + } + + + +/* + * XformRectInPixelsToHimetric + * XformRectInHimetricToPixels + * + * Purpose: + * Convert a rectangle between pixels of a given hDC and HIMETRIC units + * as manipulated in OLE. If the hDC is NULL, then a screen DC is used + * and assumes the MM_TEXT mapping mode. + * + * Parameters: + * hDC HDC providing reference to the pixel mapping. If + * NULL, a screen DC is used. + * lprcSrc LPRECT providing the rectangle to convert. This + * contains pixels in XformRectInPixelsToHimetric and + * logical HiMetric units in the complement function. + * lprcDst LPRECT providing the rectangle to receive converted units. + * This contains pixels in XformRectInPixelsToHimetric and + * logical HiMetric units in the complement function. + * + * Return Value: + * None + * + * NOTE: + * When displaying on the screen, Window apps display everything enlarged + * from its actual size so that it is easier to read. For example, if an + * app wants to display a 1in. horizontal line, that when printed is + * actually a 1in. line on the printed page, then it will display the line + * on the screen physically larger than 1in. This is described as a line + * that is "logically" 1in. along the display width. Windows maintains as + * part of the device-specific information about a given display device: + * LOGPIXELSX -- no. of pixels per logical in along the display width + * LOGPIXELSY -- no. of pixels per logical in along the display height + * + * The following formula converts a distance in pixels into its equivalent + * logical HIMETRIC units: + * + * DistInHiMetric = (HIMETRIC_PER_INCH * DistInPix) + * ------------------------------- + * PIXELS_PER_LOGICAL_IN + * + * Rect in Pixels (MM_TEXT): + * + * 0---------- X + * | + * | 1) ------------------ ( 2 P1 = (rc.left, rc.top) + * | | | P2 = (rc.right, rc.top) + * | | | P3 = (rc.left, rc.bottom) + * | | | P4 = (rc.right, rc.bottom) + * | | + * Y | | + * 3) ------------------ ( 4 + * + * NOTE: Origin = (P1x, P1y) + * X extent = P4x - P1x + * Y extent = P4y - P1y + * + * + * Rect in Himetric (MM_HIMETRIC): + * + * + * 1) ------------------ ( 2 P1 = (rc.left, rc.top) + * Y | | P2 = (rc.right, rc.top) + * | | P3 = (rc.left, rc.bottom) + * | | | P4 = (rc.right, rc.bottom) + * | | | + * | | | + * | 3) ------------------ ( 4 + * | + * 0---------- X + * + * NOTE: Origin = (P3x, P3y) + * X extent = P2x - P3x + * Y extent = P2y - P3y + * + * + */ + +STDAPI_(void) XformRectInPixelsToHimetric( + HDC hDC, LPRECT lprcPix, LPRECT lprcHiMetric) + { + int iXppli; //Pixels per logical inch along width + int iYppli; //Pixels per logical inch along height + int iXextInPix=(lprcPix->right-lprcPix->left); + int iYextInPix=(lprcPix->bottom-lprcPix->top); + BOOL fSystemDC=FALSE; + + if (NULL==hDC || GetDeviceCaps(hDC, LOGPIXELSX) == 0) + { + hDC=GetDC(NULL); + fSystemDC=TRUE; + } + + iXppli = GetDeviceCaps (hDC, LOGPIXELSX); + iYppli = GetDeviceCaps (hDC, LOGPIXELSY); + + //We got pixel units, convert them to logical HIMETRIC along the display + lprcHiMetric->right = MAP_PIX_TO_LOGHIM(iXextInPix, iXppli); + lprcHiMetric->top = MAP_PIX_TO_LOGHIM(iYextInPix, iYppli); + + lprcHiMetric->left = 0; + lprcHiMetric->bottom = 0; + + if (fSystemDC) + ReleaseDC(NULL, hDC); + + return; + } + + + +STDAPI_(void) XformRectInHimetricToPixels( + HDC hDC, LPRECT lprcHiMetric, LPRECT lprcPix) + { + int iXppli; //Pixels per logical inch along width + int iYppli; //Pixels per logical inch along height + int iXextInHiMetric=(lprcHiMetric->right-lprcHiMetric->left); + int iYextInHiMetric=(lprcHiMetric->bottom-lprcHiMetric->top); + BOOL fSystemDC=FALSE; + + if (NULL==hDC || GetDeviceCaps(hDC, LOGPIXELSX) == 0) + { + hDC=GetDC(NULL); + fSystemDC=TRUE; + } + + iXppli = GetDeviceCaps (hDC, LOGPIXELSX); + iYppli = GetDeviceCaps (hDC, LOGPIXELSY); + + //We got pixel units, convert them to logical HIMETRIC along the display + lprcPix->right = MAP_LOGHIM_TO_PIX(iXextInHiMetric, iXppli); + lprcPix->top = MAP_LOGHIM_TO_PIX(iYextInHiMetric, iYppli); + + lprcPix->left = 0; + lprcPix->bottom= 0; + + if (fSystemDC) + ReleaseDC(NULL, hDC); + + return; + } + + + + +/* + * XformSizeInPixelsToHimetric + * XformSizeInHimetricToPixels + * + * Functions to convert a SIZEL structure (Size functions) or + * an int (Width functions) between a device coordinate system and + * logical HiMetric units. + * + * Parameters: + * hDC HDC providing reference to the pixel mapping. If + * NULL, a screen DC is used. + * + * Size Functions: + * lpSizeSrc LPSIZEL providing the structure to convert. This + * contains pixels in XformSizeInPixelsToHimetric and + * logical HiMetric units in the complement function. + * lpSizeDst LPSIZEL providing the structure to receive converted + * units. This contains pixels in + * XformSizeInPixelsToHimetric and logical HiMetric + * units in the complement function. + * + * Width Functions: + * iWidth int containing the value to convert. + * + * Return Value: + * Size Functions: None + * Width Functions: Converted value of the input parameters. + * + * NOTE: + * When displaying on the screen, Window apps display everything enlarged + * from its actual size so that it is easier to read. For example, if an + * app wants to display a 1in. horizontal line, that when printed is + * actually a 1in. line on the printed page, then it will display the line + * on the screen physically larger than 1in. This is described as a line + * that is "logically" 1in. along the display width. Windows maintains as + * part of the device-specific information about a given display device: + * LOGPIXELSX -- no. of pixels per logical in along the display width + * LOGPIXELSY -- no. of pixels per logical in along the display height + * + * The following formula converts a distance in pixels into its equivalent + * logical HIMETRIC units: + * + * DistInHiMetric = (HIMETRIC_PER_INCH * DistInPix) + * ------------------------------- + * PIXELS_PER_LOGICAL_IN + * + */ + +STDAPI_(void) XformSizeInPixelsToHimetric( + HDC hDC, LPSIZEL lpSizeInPix, LPSIZEL lpSizeInHiMetric) + { + int iXppli; //Pixels per logical inch along width + int iYppli; //Pixels per logical inch along height + BOOL fSystemDC=FALSE; + + if (NULL==hDC || GetDeviceCaps(hDC, LOGPIXELSX) == 0) + { + hDC=GetDC(NULL); + fSystemDC=TRUE; + } + + iXppli = GetDeviceCaps (hDC, LOGPIXELSX); + iYppli = GetDeviceCaps (hDC, LOGPIXELSY); + + //We got pixel units, convert them to logical HIMETRIC along the display + lpSizeInHiMetric->cx = (long)MAP_PIX_TO_LOGHIM((int)lpSizeInPix->cx, iXppli); + lpSizeInHiMetric->cy = (long)MAP_PIX_TO_LOGHIM((int)lpSizeInPix->cy, iYppli); + + if (fSystemDC) + ReleaseDC(NULL, hDC); + + return; + } + + +STDAPI_(void) XformSizeInHimetricToPixels( + HDC hDC, LPSIZEL lpSizeInHiMetric, LPSIZEL lpSizeInPix) + { + int iXppli; //Pixels per logical inch along width + int iYppli; //Pixels per logical inch along height + BOOL fSystemDC=FALSE; + + if (NULL==hDC || GetDeviceCaps(hDC, LOGPIXELSX) == 0) + { + hDC=GetDC(NULL); + fSystemDC=TRUE; + } + + iXppli = GetDeviceCaps (hDC, LOGPIXELSX); + iYppli = GetDeviceCaps (hDC, LOGPIXELSY); + + //We got logical HIMETRIC along the display, convert them to pixel units + lpSizeInPix->cx = (long)MAP_LOGHIM_TO_PIX((int)lpSizeInHiMetric->cx, iXppli); + lpSizeInPix->cy = (long)MAP_LOGHIM_TO_PIX((int)lpSizeInHiMetric->cy, iYppli); + + if (fSystemDC) + ReleaseDC(NULL, hDC); + + return; + } + + +#if defined( OBSOLETE ) +// This function has been converted to a macro + +/* AreRectsEqual +** ------------- +*/ +STDAPI_(BOOL) AreRectsEqual(LPRECT lprc1, LPRECT lprc2) +{ + if ((lprc1->top == lprc2->top) && + (lprc1->left == lprc2->left) && + (lprc1->right == lprc2->right) && + (lprc1->bottom == lprc2->bottom)) + return TRUE; + + return FALSE; +} +#endif // OBSOLETE + + +/* + * ParseCmdLine + * + * Parses the Windows command line which was passed to WinMain. + * This function determines if the -Embedding switch has been given. + * + */ + +STDAPI_(void) ParseCmdLine( + LPSTR lpszLine, + BOOL FAR* lpfEmbedFlag, + LPSTR szFileName) +{ + int i=0; + CHAR szBuf[256]; + + if(lpfEmbedFlag) + *lpfEmbedFlag = FALSE; + szFileName[0]='\0'; // NULL string + + // skip blanks + while(isspace(*lpszLine)) lpszLine++; + + if(!*lpszLine) // No filename or options, so start a fresh document. + return; + + // Check for "-Embedding" or "/Embedding" and set fEmbedding. + if(lpfEmbedFlag && (*lpszLine == '-' || *lpszLine == '/')) { + lpszLine++; + lpszLine = GetWord(lpszLine, szBuf); + *lpfEmbedFlag = (BOOL) !strcmp(szBuf, EMBEDDINGFLAG); + } + + // skip blanks + while(isspace(*lpszLine)) lpszLine++; + + // set szFileName to argument + while(lpszLine[i]) { + szFileName[i]=lpszLine[i]; + i++; + } + szFileName[i]='\0'; +} + + +/* GetWord + * ------- + * + * LPSTR lpszSrc - Pointer to a source string + * LPSTR lpszDst - Pointer to destination buffer + * + * Will copy one space-terminated or null-terminated word from the source + * string to the destination buffer. + * returns: pointer to next character following the word. + */ +static LPSTR GetWord(LPSTR lpszSrc, LPSTR lpszDst) +{ + while (*lpszSrc && !isspace(*lpszSrc)) + *lpszDst++ = *lpszSrc++; + + *lpszDst = '\0'; + return lpszSrc; +} + + + + + diff --git a/private/oleutest/letest/ole2ui/outlui.d32 b/private/oleutest/letest/ole2ui/outlui.d32 new file mode 100644 index 000000000..502d0b598 --- /dev/null +++ b/private/oleutest/letest/ole2ui/outlui.d32 @@ -0,0 +1,138 @@ +;; +;; ole2ui.def +;; +;; Definition file for ole2ui.dll +;; +;; (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +;; +;; + +CODE MOVEABLE DISCARDABLE +DATA MOVEABLE SINGLE + +HEAPSIZE 16392 + +EXPORTS WEP @1 RESIDENTNAME +;; +;; NOTE: DO NOT PLACE ANY EXPORTS HERE -- USE THE +;; __export KEYWORD INSTEAD. + +SetDCToAnisotropic +SetDCToDrawInHimetricRect +ResetOrigDC +XformRectInPixelsToHimetric +XformRectInHimetricToPixels +XformSizeInPixelsToHimetric +XformSizeInHimetricToPixels +XformWidthInHimetricToPixels +XformWidthInPixelsToHimetric +XformHeightInHimetricToPixels +XformHeightInPixelsToHimetric +AreRectsEqual +ParseCmdLine +OleStdIsOleLink +OleStdQueryInterface +OleStdCreateRootStorage +OleStdOpenRootStorage +OleStdOpenOrCreateRootStorage +OleStdCreateChildStorage +OleStdOpenChildStorage +OleStdCommitStorage +OleStdCreateStorageOnHGlobal +OleStdCreateTempStorage +OleStdDoConvert +OleStdGetTreatAsFmtUserType +OleStdDoTreatAsClass +OleStdSetupAdvises +OleStdSwitchDisplayAspect +OleStdSetIconInCache +OleStdGetData +OleStdMarkPasteEntryList +OleStdGetPriorityClipboardFormat +OleStdIsDuplicateFormat +OleStdRegisterAsRunning +OleStdRevokeAsRunning +OleStdNoteFileChangeTime +OleStdNoteObjectChangeTime +OleStdGetOleObjectData +OleStdGetLinkSourceData +OleStdGetObjectDescriptorData +OleStdGetObjectDescriptorDataFromOleObject +OleStdFillObjectDescriptorFromData +OleStdCopyMetafilePict +OleStdGetMetafilePictFromOleObject +OleStdQueryOleObjectData +OleStdQueryLinkSourceData +OleStdQueryObjectDescriptorData +OleStdQueryFormatMedium +OleStdGetDropEffect +OleStdCreateTempFileMoniker +OleStdGetFirstMoniker +OleStdGetLenFilePrefixOfMoniker +OleStdMalloc +OleStdRealloc +OleStdFree +OleStdGetSize +OleStdFreeString +OleStdCopyString +OleStdGetItemToken +OleStdInitVtbl +OleStdCheckVtbl +OleStdVerifyRelease +OleStdRelease +OleStdCreateDC +OleStdCreateIC +OleStdCreateTargetDevice +OleStdDeleteTargetDevice +OleStdCopyTargetDevice +OleStdCopyFormatEtc +OleDbgPrint +OleDbgPrintAlways +OleDbgSetDbgLevel +OleDbgGetDbgLevel +OleDbgIndent +OleDbgPrintRefCnt +OleDbgPrintRefCntAlways +OleDbgPrintRect +OleDbgPrintRectAlways +OleDbgPrintScodeAlways +OleUIInitialize +OleUIUnInitialize +OleUIAddVerbMenu +OleUIMetafilePictFromIconAndLabel +OleUIMetafilePictIconFree +OleUIMetafilePictIconDraw +OleUIMetafilePictExtractLabel +OleUIMetafilePictExtractIcon +OleUIMetafilePictExtractIconSource +OleUIInsertObject +OleUIPasteSpecial +OleUIEditLinks +OleUIChangeIcon +OleUIConvert +OleUIBusy +OleUIUpdateLinks +OleUIDrawHandles +OleUIDrawShading +OleUIShowObject +RegisterHatchWindowClass +CreateHatchWindow +GetHatchWidth +GetHatchRect +SetHatchRect +SetHatchWindowSize +OleUIPromptUser +OleStdEnumFmtEtc_Create +GetIconOfFile +GetIconOfClass +OleStdGetAuxUserType +OleStdGetUserTypeOfClass +OleStdIconLabelTextOut +OleStdMsgFilter_Create +OleStdMsgFilter_SetInComingCallStatus +OleStdMsgFilter_GetInComingCallStatus +OleStdMsgFilter_EnableBusyDialog +OleStdMsgFilter_EnableNotRespondingDialog +OleStdMsgFilter_SetParentWindow +OleStdGetMiscStatusOfClass +OleStdGetDefaultFileFormatOfClass diff --git a/private/oleutest/letest/ole2ui/pastespl.c b/private/oleutest/letest/ole2ui/pastespl.c new file mode 100644 index 000000000..0cf086cf1 --- /dev/null +++ b/private/oleutest/letest/ole2ui/pastespl.c @@ -0,0 +1,1713 @@ +/* + * PASTESPL.C + * + * Implements the OleUIPasteSpecial function which invokes the complete + * Paste Special dialog. + * + * Copyright (c)1992 Microsoft Corporation, All Rights Reserved + */ + +#define STRICT 1 +#include "ole2ui.h" +#include "pastespl.h" +#include "common.h" +#include "utility.h" +#include "resimage.h" +#include "iconbox.h" +#include "geticon.h" +#include "icon.h" +#include "regdb.h" +#include + +OLEDBGDATA + +/* + * OleUIPasteSpecial + * + * Purpose: + * Invokes the standard OLE Paste Special dialog box which allows the user + * to select the format of the clipboard object to be pasted or paste linked. + * + * Parameters: + * lpPS LPOLEUIPasteSpecial pointing to the in-out structure + * for this dialog. + * + * Return Value: + * UINT One of the following codes or one of the standard error codes (OLEUI_ERR_*) + * defined in OLE2UI.H, indicating success or error: + * OLEUI_OK User selected OK + * OLEUI_CANCEL User cancelled the dialog + * OLEUI_IOERR_SRCDATAOBJECTINVALID lpSrcDataObject field of OLEUIPASTESPECIAL invalid + * OLEUI_IOERR_ARRPASTEENTRIESINVALID arrPasteEntries field of OLEUIPASTESPECIAL invalid + * OLEUI_IOERR_ARRLINKTYPESINVALID arrLinkTypes field of OLEUIPASTESPECIAL invalid + * OLEUI_PSERR_CLIPBOARDCHANGED Clipboard contents changed while dialog was up + */ + +STDAPI_(UINT) OleUIPasteSpecial(LPOLEUIPASTESPECIAL lpPS) +{ + UINT uRet; + HGLOBAL hMemDlg=NULL; + + uRet=UStandardValidation((LPOLEUISTANDARD)lpPS, sizeof(OLEUIPASTESPECIAL) + , &hMemDlg); + + if (uRet != OLEUI_SUCCESS) + return uRet; + + //Validate PasteSpecial specific fields + if (NULL == lpPS->lpSrcDataObj || IsBadReadPtr(lpPS->lpSrcDataObj, sizeof(IDataObject))) + uRet = OLEUI_IOERR_SRCDATAOBJECTINVALID; + if (NULL == lpPS->arrPasteEntries || IsBadReadPtr(lpPS->arrPasteEntries, sizeof(OLEUIPASTEENTRY))) + uRet = OLEUI_IOERR_ARRPASTEENTRIESINVALID; + if (NULL != lpPS->arrLinkTypes && IsBadReadPtr(lpPS->arrLinkTypes, sizeof(UINT))) + uRet = OLEUI_IOERR_ARRLINKTYPESINVALID; + + if (0!=lpPS->cClsidExclude) + { + if (NULL!=lpPS->lpClsidExclude && IsBadReadPtr(lpPS->lpClsidExclude + , lpPS->cClsidExclude*sizeof(CLSID))) + uRet=OLEUI_IOERR_LPCLSIDEXCLUDEINVALID; + } + + if (uRet >= OLEUI_ERR_STANDARDMIN) + { + if (NULL != hMemDlg) + FreeResource(hMemDlg); + return uRet; + } + + //Now that we've validated everything, we can invoke the dialog. + uRet = UStandardInvocation(PasteSpecialDialogProc, (LPOLEUISTANDARD)lpPS + , hMemDlg, MAKEINTRESOURCE(IDD_PASTESPECIAL)); + + /* + * IF YOU ARE CREATING ANYTHING BASED ON THE RESULTS, DO IT HERE. + */ + + return uRet; +} + + +/* + * PasteSpecialDialogProc + * + * Purpose: + * Implements the OLE Paste Special dialog as invoked through the + * OleUIPasteSpecial function. + * + * Parameters: + * Standard + * + * Return Value: + * Standard + */ + +BOOL CALLBACK EXPORT PasteSpecialDialogProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam) +{ + LPOLEUIPASTESPECIAL lpOPS; + LPPASTESPECIAL lpPS; + BOOL fHook=FALSE; + HCURSOR hCursorOld; + + //Declare Win16/Win32 compatible WM_COMMAND parameters. + COMMANDPARAMS(wID, wCode, hWndMsg); + + //This will fail under WM_INITDIALOG, where we allocate it. + lpPS=(LPPASTESPECIAL)LpvStandardEntry(hDlg, iMsg, wParam, lParam, &fHook); + + //If the hook processed the message, we're done. + if (0!=fHook) + return fHook; + + // Process help message from Change Icon + if (iMsg == uMsgHelp) + { + PostMessage(lpPS->lpOPS->hWndOwner, uMsgHelp, wParam, lParam); + return FALSE; + } + + //Process the temination message + if (iMsg==uMsgEndDialog) + { + HWND hwndNextViewer; + + // Free the icon/icon-title metafile corresponding to Paste/PasteList option which is not selected + if (lpPS->fLink) + OleUIMetafilePictIconFree(lpPS->hMetaPictOD); + else OleUIMetafilePictIconFree(lpPS->hMetaPictLSD); + + // Free data associated with each list box entry + FreeListData(GetDlgItem(hDlg, ID_PS_PASTELIST)); + FreeListData(GetDlgItem(hDlg, ID_PS_PASTELINKLIST)); + + //Free any specific allocations before calling StandardCleanup + if (lpPS->hObjDesc) GlobalFree(lpPS->hObjDesc); + if (lpPS->hLinkSrcDesc) GlobalFree(lpPS->hLinkSrcDesc); + if (lpPS->hBuff) GlobalFree(lpPS->hBuff); + + // Change the clipboard notification chain + hwndNextViewer = GetProp(hDlg, NEXTCBVIEWER); + if (hwndNextViewer != HWND_BROADCAST) + { + SetProp(hDlg, NEXTCBVIEWER, HWND_BROADCAST); + ChangeClipboardChain(hDlg, hwndNextViewer); + } + RemoveProp(hDlg, NEXTCBVIEWER); + + StandardCleanup(lpPS, hDlg); + EndDialog(hDlg, wParam); + return TRUE; + } + + switch (iMsg) + { + case WM_INITDIALOG: + hCursorOld = HourGlassOn(); + FPasteSpecialInit(hDlg, wParam, lParam); + HourGlassOff(hCursorOld); + return FALSE; + + case WM_DRAWCLIPBOARD: + { + HWND hwndNextViewer = GetProp(hDlg, NEXTCBVIEWER); + HWND hDlg_ChgIcon; + + if (hwndNextViewer == HWND_BROADCAST) + break; + + if (hwndNextViewer) + { + SendMessage(hwndNextViewer, iMsg, wParam, lParam); + // Refresh next viewer in case it got modified + // by the SendMessage() (likely if multiple + // PasteSpecial dialogs are up simultaneously) + hwndNextViewer = GetProp(hDlg, NEXTCBVIEWER); + } + SetProp(hDlg, NEXTCBVIEWER, HWND_BROADCAST); + ChangeClipboardChain(hDlg, hwndNextViewer); + + /* OLE2NOTE: if the ChangeIcon dialog is currently up, then + ** we need to defer bringing down PasteSpecial dialog + ** until after ChangeIcon dialog returns. if the + ** ChangeIcon dialog is NOT up, then we can bring down + ** the PasteSpecial dialog immediately. + */ + if ((hDlg_ChgIcon=(HWND)GetProp(hDlg,PROP_HWND_CHGICONDLG))!=NULL) + { + // ChangeIcon dialog is UP + lpPS->fClipboardChanged = TRUE; + } else { + // ChangeIcon dialog is NOT up + + // Free icon and icon title metafile + SendDlgItemMessage( + hDlg, ID_PS_ICONDISPLAY, IBXM_IMAGEFREE, 0, 0L); + + SendMessage( + hDlg, uMsgEndDialog, OLEUI_PSERR_CLIPBOARDCHANGED,0L); + } + break; + } + + case WM_CHANGECBCHAIN: + { + HWND hwndNextViewer = GetProp(hDlg, NEXTCBVIEWER); + + if (wParam == (WORD)hwndNextViewer) + SetProp(hDlg, NEXTCBVIEWER, (hwndNextViewer = (HWND)LOWORD(lParam))); + else if (hwndNextViewer && hwndNextViewer != HWND_BROADCAST) + SendMessage(hwndNextViewer, iMsg, wParam, lParam); + break; + } + + case WM_COMMAND: + switch (wID) + { + case ID_PS_PASTE: + FTogglePasteType(hDlg, lpPS, PSF_SELECTPASTE); + break; + + case ID_PS_PASTELINK: + FTogglePasteType(hDlg, lpPS, PSF_SELECTPASTELINK); + break; + + case ID_PS_DISPLAYLIST: + switch (wCode) + { + case LBN_SELCHANGE: + ChangeListSelection(hDlg, lpPS, hWndMsg); + break; + + case LBN_DBLCLK: + // Same as pressing OK + SendCommand(hDlg, IDOK, BN_CLICKED, hWndMsg); + break; + } + break; + + case ID_PS_DISPLAYASICON: + ToggleDisplayAsIcon(hDlg, lpPS); + break; + + case ID_PS_CHANGEICON: + ChangeIcon(hDlg, lpPS); + if (lpPS->fClipboardChanged) { + // Free icon and icon title metafile + SendDlgItemMessage( + hDlg, ID_PS_ICONDISPLAY, IBXM_IMAGEFREE,0,0L); + SendMessage( + hDlg, uMsgEndDialog, + OLEUI_PSERR_CLIPBOARDCHANGED, 0L); + } + break; + + case IDOK: + { + BOOL fDestAspectIcon = + ((lpPS->dwFlags & PSF_CHECKDISPLAYASICON) ? + TRUE : FALSE); + lpOPS = lpPS->lpOPS; + // Return current flags + lpOPS->dwFlags = lpPS->dwFlags; + // Return index of arrPasteEntries[] corresponding to format selected by user + lpOPS->nSelectedIndex = lpPS->nSelectedIndex; + // Return if user selected Paste or PasteLink + lpOPS->fLink = lpPS->fLink; + + /* if user selected same ASPECT as displayed in the + ** source, then sizel passed in the + ** ObjectDescriptor/LinkSrcDescriptor is + ** applicable. otherwise, the sizel does not apply. + */ + if (lpPS->fLink) { + if (lpPS->fSrcAspectIconLSD == fDestAspectIcon) + lpOPS->sizel = lpPS->sizelLSD; + else + lpOPS->sizel.cx = lpOPS->sizel.cy = 0; + } else { + if (lpPS->fSrcAspectIconOD == fDestAspectIcon) + lpOPS->sizel = lpPS->sizelOD; + else + lpOPS->sizel.cx = lpOPS->sizel.cy = 0; + } + // Return metafile with icon and icon title that the user selected + lpOPS->hMetaPict=(HGLOBAL)SendDlgItemMessage(hDlg, ID_PS_ICONDISPLAY, + IBXM_IMAGEGET, 0, 0L); + SendMessage(hDlg, uMsgEndDialog, OLEUI_OK, 0L); + break; + } + case IDCANCEL: + // Free icon and icon title metafile + SendDlgItemMessage( + hDlg, ID_PS_ICONDISPLAY, IBXM_IMAGEFREE, 0, 0L); + SendMessage(hDlg, uMsgEndDialog, OLEUI_CANCEL, 0L); + break; + + case ID_OLEUIHELP: + PostMessage(lpPS->lpOPS->hWndOwner, uMsgHelp, + (WPARAM)hDlg, MAKELPARAM(IDD_PASTESPECIAL, 0)); + break; + } + break; + } + return FALSE; +} + + +/* + * FPasteSpecialInit + * + * Purpose: + * WM_INITIDIALOG handler for the Paste Special dialog box. + * + * Parameters: + * hDlg HWND of the dialog + * wParam WPARAM of the message + * lParam LPARAM of the message + * + * Return Value: + * BOOL Value to return for WM_INITDIALOG. + */ + +BOOL FPasteSpecialInit(HWND hDlg, WPARAM wParam, LPARAM lParam) +{ + LPPASTESPECIAL lpPS; + LPOLEUIPASTESPECIAL lpOPS; + HFONT hFont; + BOOL fPasteAvailable, fPasteLinkAvailable; + STGMEDIUM medium; + LPOBJECTDESCRIPTOR lpOD; + LPLINKSRCDESCRIPTOR lpLSD; + int n; + CLIPFORMAT cfFormat; + + // Copy the structure at lParam into our instance memory. + lpPS = (LPPASTESPECIAL)LpvStandardInit(hDlg, sizeof(PASTESPECIAL), TRUE, &hFont); + + // PvStandardInit sent a termination to us already. + if (NULL == lpPS) + return FALSE; + + lpOPS=(LPOLEUIPASTESPECIAL)lParam; + + // Copy other information from lpOPS that we might modify. + lpPS->lpOPS = lpOPS; + lpPS->dwFlags = lpOPS->dwFlags; + + // Initialize user selections in the Paste and PasteLink listboxes + lpPS->nPasteListCurSel = 0; + lpPS->nPasteLinkListCurSel = 0; + + // If we got a font, send it to the necessary controls. + if (NULL!=hFont) + { + SendDlgItemMessage(hDlg, ID_PS_SOURCETEXT, WM_SETFONT, (WPARAM)hFont, 0L); + SendDlgItemMessage(hDlg, ID_PS_RESULTTEXT, WM_SETFONT, (WPARAM)hFont, 0L); + } + + // Hide the help button if required + if (!(lpPS->lpOPS->dwFlags & PSF_SHOWHELP)) + StandardShowDlgItem(hDlg, ID_OLEUIHELP, SW_HIDE); + + // Hide all DisplayAsIcon related controls if it should be disabled + if ( lpPS->dwFlags & PSF_DISABLEDISPLAYASICON ) { + StandardShowDlgItem(hDlg, ID_PS_DISPLAYASICON, SW_HIDE); + StandardShowDlgItem(hDlg, ID_PS_CHANGEICON, SW_HIDE); + StandardShowDlgItem(hDlg, ID_PS_ICONDISPLAY, SW_HIDE); + } + + // PSF_CHECKDISPLAYASICON is an OUT flag. Clear it if has been set on the way in. + lpPS->dwFlags = lpPS->dwFlags & ~PSF_CHECKDISPLAYASICON; + + // Change the caption if required + if (NULL != lpOPS->lpszCaption) + SetWindowText(hDlg, lpOPS->lpszCaption); + + // Load 'Unknown Source' and 'Unknown Type' strings + n = LoadString(ghInst, IDS_PSUNKNOWNTYPE, lpPS->szUnknownType, PS_UNKNOWNSTRLEN); + if (n) + n = LoadString(ghInst, IDS_PSUNKNOWNSRC, lpPS->szUnknownSource, PS_UNKNOWNSTRLEN); + if (!n) + { + PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_LOADSTRING, 0L); + return FALSE; + } + lpPS->szAppName[0]=TEXT('\0'); + + // GetData CF_OBJECTDESCRIPTOR. If the object on the clipboard in an OLE1 object (offering CF_OWNERLINK) + // or has been copied to clipboard by FileMaager (offering CF_FILENAME), an OBJECTDESCRIPTOR will be + // created will be created from CF_OWNERLINK or CF_FILENAME. See OBJECTDESCRIPTOR for more info. + + if (lpPS->hObjDesc = OleStdFillObjectDescriptorFromData(lpOPS->lpSrcDataObj, &medium, &cfFormat)) + { + lpOD = GlobalLock(lpPS->hObjDesc); + + // Get FullUserTypeName, SourceOfCopy and CLSID + if (lpOD->dwFullUserTypeName) + lpPS->szFullUserTypeNameOD = (LPTSTR)lpOD+lpOD->dwFullUserTypeName; + else lpPS->szFullUserTypeNameOD = lpPS->szUnknownType; + + if (lpOD->dwSrcOfCopy) + { + lpPS->szSourceOfDataOD = (LPTSTR)lpOD+lpOD->dwSrcOfCopy; + // If CF_FILENAME was offered, source of copy is a path name. Fit the path to the + // static control that will display it. + if (cfFormat == cfFileName) + lpPS->szSourceOfDataOD = ChopText(GetDlgItem(hDlg, ID_PS_SOURCETEXT), 0, lpPS->szSourceOfDataOD); + } + else lpPS->szSourceOfDataOD = lpPS->szUnknownSource; + + lpPS->clsidOD = lpOD->clsid; + lpPS->sizelOD = lpOD->sizel; + + // Does source specify DVASPECT_ICON? + if (lpOD->dwDrawAspect & DVASPECT_ICON) + lpPS->fSrcAspectIconOD = TRUE; + else lpPS->fSrcAspectIconOD = FALSE; + + // Does source specify OLEMISC_ONLYICONIC? + if (lpOD->dwStatus & OLEMISC_ONLYICONIC) + lpPS->fSrcOnlyIconicOD = TRUE; + else lpPS->fSrcOnlyIconicOD = FALSE; + + // Get application name of source from auxusertype3 in the registration database + if (0==OleStdGetAuxUserType(&lpPS->clsidOD, 3, lpPS->szAppName, OLEUI_CCHKEYMAX_SIZE, NULL)) + { + // Use "the application which created it" as the name of the application + if (0==LoadString(ghInst, IDS_PSUNKNOWNAPP, lpPS->szAppName, PS_UNKNOWNSTRLEN)) + { + PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_LOADSTRING, 0L); + return FALSE; + } + } + + // Retrieve an icon from the object + if (lpPS->fSrcAspectIconOD) + { + lpPS->hMetaPictOD = OleStdGetData( + lpOPS->lpSrcDataObj, + (CLIPFORMAT) CF_METAFILEPICT, + NULL, + DVASPECT_ICON, + &medium + ); + + } + // If object does not offer icon, obtain it from the CLSID + if (NULL == lpPS->hMetaPictOD) + { +#ifdef OLE201 + lpPS->hMetaPictOD = GetIconOfClass( + ghInst, + &lpPS->clsidOD, + NULL, + TRUE); // Use the short user type name (auxusertype3) +#endif + lpPS->hMetaPictOD = NULL; + + + } + } + + // Does object offer CF_LINKSRCDESCRIPTOR? + if (lpPS->hLinkSrcDesc = OleStdGetData( + lpOPS->lpSrcDataObj, + (CLIPFORMAT) cfLinkSrcDescriptor, + NULL, + DVASPECT_CONTENT, + &medium)) + { + // Get FullUserTypeName, SourceOfCopy and CLSID + lpLSD = GlobalLock(lpPS->hLinkSrcDesc); + if (lpLSD->dwFullUserTypeName) + lpPS->szFullUserTypeNameLSD = (LPTSTR)lpLSD+lpLSD->dwFullUserTypeName; + else lpPS->szFullUserTypeNameLSD = lpPS->szUnknownType; + + if (lpLSD->dwSrcOfCopy) + lpPS->szSourceOfDataLSD = (LPTSTR)lpLSD+lpLSD->dwSrcOfCopy; + else lpPS->szSourceOfDataLSD = lpPS->szUnknownSource; + + // if no ObjectDescriptor, then use LinkSourceDescriptor source string + if (!lpPS->hObjDesc) + lpPS->szSourceOfDataOD = lpPS->szSourceOfDataLSD; + + lpPS->clsidLSD = lpLSD->clsid; + lpPS->sizelLSD = lpLSD->sizel; + + // Does source specify DVASPECT_ICON? + if (lpLSD->dwDrawAspect & DVASPECT_ICON) + lpPS->fSrcAspectIconLSD = TRUE; + else lpPS->fSrcAspectIconLSD = FALSE; + + // Does source specify OLEMISC_ONLYICONIC? + if (lpLSD->dwStatus & OLEMISC_ONLYICONIC) + lpPS->fSrcOnlyIconicLSD = TRUE; + else lpPS->fSrcOnlyIconicLSD = FALSE; + + // Retrieve an icon from the object + if (lpPS->fSrcAspectIconLSD) + { + lpPS->hMetaPictLSD = OleStdGetData( + lpOPS->lpSrcDataObj, + CF_METAFILEPICT, + NULL, + DVASPECT_ICON, + &medium + ); + + } + // If object does not offer icon, obtain it from the CLSID + if (NULL == lpPS->hMetaPictLSD) + { + TCHAR szLabel[OLEUI_CCHLABELMAX]; + HWND hIconWnd; + RECT IconRect; + int nWidth; + LPTSTR lpszLabel; + + hIconWnd = GetDlgItem(hDlg, ID_PS_ICONDISPLAY); + + GetClientRect(hIconWnd, &IconRect); + + nWidth = ((IconRect.right-IconRect.left) * 3) / 2; // width is 1.5 times width of iconbox + + LSTRCPYN(szLabel, lpPS->szSourceOfDataLSD, OLEUI_CCHLABELMAX); + szLabel[OLEUI_CCHLABELMAX-1] = TEXT('\0'); + + lpszLabel = ChopText(hIconWnd, nWidth, (LPTSTR)szLabel); + +#ifdef OLE201 + lpPS->hMetaPictLSD = GetIconOfClass( + ghInst, + &lpPS->clsidLSD, + lpszLabel, /* use chopped source string as label */ + FALSE /* not applicable */ + ); +#endif + lpPS->hMetaPictLSD = NULL; + + } + } + else if (lpPS->hObjDesc) // Does not offer CF_LINKSRCDESCRIPTOR but offers CF_OBJECTDESCRIPTOR + { + // Copy the values of OBJECTDESCRIPTOR + lpPS->szFullUserTypeNameLSD = lpPS->szFullUserTypeNameOD; + lpPS->szSourceOfDataLSD = lpPS->szSourceOfDataOD; + lpPS->clsidLSD = lpPS->clsidOD; + lpPS->sizelLSD = lpPS->sizelOD; + lpPS->fSrcAspectIconLSD = lpPS->fSrcAspectIconOD; + lpPS->fSrcOnlyIconicLSD = lpPS->fSrcOnlyIconicOD; + + // Don't copy the hMetaPict; instead get a separate copy + if (lpPS->fSrcAspectIconLSD) + { + lpPS->hMetaPictLSD = OleStdGetData( + lpOPS->lpSrcDataObj, + CF_METAFILEPICT, + NULL, + DVASPECT_ICON, + &medium + ); + } + if (NULL == lpPS->hMetaPictLSD) + { + TCHAR szLabel[OLEUI_CCHLABELMAX]; + HWND hIconWnd; + RECT IconRect; + int nWidth; + LPTSTR lpszLabel; + + hIconWnd = GetDlgItem(hDlg, ID_PS_ICONDISPLAY); + + GetClientRect(hIconWnd, &IconRect); + + nWidth = ((IconRect.right-IconRect.left) * 3) / 2; // width is 1.5 times width of iconbox + + LSTRCPYN(szLabel, lpPS->szSourceOfDataLSD, OLEUI_CCHLABELMAX); + szLabel[OLEUI_CCHLABELMAX-1] = TEXT('\0'); + + lpszLabel = ChopText(hIconWnd, nWidth, (LPTSTR)szLabel); + +#ifdef OLE201 + lpPS->hMetaPictLSD = GetIconOfClass( + ghInst, + &lpPS->clsidLSD, + lpszLabel, /* Use chopped source string as label */ + FALSE /* Not applicable */ + ); +#endif + lpPS->hMetaPictLSD = NULL; + + } + } + + // Not an OLE object + if (lpPS->hObjDesc == NULL && lpPS->hLinkSrcDesc == NULL) + { + lpPS->szFullUserTypeNameLSD = lpPS->szFullUserTypeNameOD = lpPS->szUnknownType; + lpPS->szSourceOfDataLSD = lpPS->szSourceOfDataOD = lpPS->szUnknownSource; + lpPS->hMetaPictLSD = lpPS->hMetaPictOD = NULL; + } + + // Allocate scratch memory to construct item names in the paste and pastelink listboxes + lpPS->hBuff = AllocateScratchMem(lpPS); + if (lpPS->hBuff == NULL) + { + PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_GLOBALMEMALLOC, 0L); + return FALSE; + } + + // Select the Paste Link Button if specified. Otherwise select + // Paste Button by default + if (lpPS->dwFlags & PSF_SELECTPASTELINK) + lpPS->dwFlags = (lpPS->dwFlags & ~PSF_SELECTPASTE) | PSF_SELECTPASTELINK; + else + lpPS->dwFlags =(lpPS->dwFlags & ~PSF_SELECTPASTELINK) | PSF_SELECTPASTE; + + // Mark which PasteEntry formats are available from source data object + OleStdMarkPasteEntryList( + lpOPS->lpSrcDataObj,lpOPS->arrPasteEntries,lpOPS->cPasteEntries); + + // Check if items are available to be pasted + fPasteAvailable = FFillPasteList(hDlg, lpPS); + if (!fPasteAvailable) + { + lpPS->dwFlags &= ~PSF_SELECTPASTE; + EnableWindow(GetDlgItem(hDlg, ID_PS_PASTE), FALSE); + } + + // Check if items are available to be paste-linked + fPasteLinkAvailable = FFillPasteLinkList(hDlg, lpPS); + if (!fPasteLinkAvailable) + { + lpPS->dwFlags &= ~PSF_SELECTPASTELINK; + EnableWindow(GetDlgItem(hDlg, ID_PS_PASTELINK), FALSE); + } + + // If one of Paste or PasteLink is disabled, select the other one + // regardless of what the input flags say + if (fPasteAvailable && !fPasteLinkAvailable) + lpPS->dwFlags |= PSF_SELECTPASTE; + if (fPasteLinkAvailable && !fPasteAvailable) + lpPS->dwFlags |= PSF_SELECTPASTELINK; + + if (lpPS->dwFlags & PSF_SELECTPASTE) + { + // FTogglePaste will set the PSF_SELECTPASTE flag, so clear it. + lpPS->dwFlags &= ~PSF_SELECTPASTE; + CheckRadioButton(hDlg, ID_PS_PASTE, ID_PS_PASTELINK, ID_PS_PASTE); + FTogglePasteType(hDlg, lpPS, PSF_SELECTPASTE); + } + else if (lpPS->dwFlags & PSF_SELECTPASTELINK) + { + // FTogglePaste will set the PSF_SELECTPASTELINK flag, so clear it. + lpPS->dwFlags &= ~PSF_SELECTPASTELINK; + CheckRadioButton(hDlg, ID_PS_PASTE, ID_PS_PASTELINK, ID_PS_PASTELINK); + FTogglePasteType(hDlg, lpPS, PSF_SELECTPASTELINK); + } + else // Items are not available to be be Pasted or Paste-Linked + { + // Enable or disable DisplayAsIcon and set the result text and image + EnableDisplayAsIcon(hDlg, lpPS); + SetPasteSpecialHelpResults(hDlg, lpPS); + } + + // Give initial focus to the list box + SetFocus(GetDlgItem(hDlg, ID_PS_DISPLAYLIST)); + + // Set property to handle clipboard change notifications + SetProp(hDlg, NEXTCBVIEWER, HWND_BROADCAST); + SetProp(hDlg, NEXTCBVIEWER, SetClipboardViewer(hDlg)); + + lpPS->fClipboardChanged = FALSE; + + /* + * PERFORM OTHER INITIALIZATION HERE. + */ + + // Call the hook with lCustData in lParam + UStandardHook(lpPS, hDlg, WM_INITDIALOG, wParam, lpOPS->lCustData); + return TRUE; +} + +/* + * FTogglePasteType + * + * Purpose: + * Toggles between Paste and Paste Link. The Paste list and PasteLink + * list are always invisible. The Display List is filled from either + * the Paste list or the PasteLink list depending on which Paste radio + * button is selected. + * + * Parameters: + * hDlg HWND of the dialog + * lpPS Paste Special Dialog Structure + * dwOption Paste or PasteSpecial option + * + * Return Value: + * BOOL Returns TRUE if the option has already been selected. + * Otherwise the option is selected and FALSE is returned + */ + +BOOL FTogglePasteType(HWND hDlg, LPPASTESPECIAL lpPS, DWORD dwOption) +{ + DWORD dwTemp; + HWND hList, hListDisplay; + DWORD dwData; + int i, nItems; + LPTSTR lpsz; + + // Skip all this if the button is already selected + if (lpPS->dwFlags & dwOption) + return TRUE; + + dwTemp = PSF_SELECTPASTE | PSF_SELECTPASTELINK; + lpPS->dwFlags = (lpPS->dwFlags & ~dwTemp) | dwOption; + + // Hide IconDisplay. This prevents flashing if the icon display is changed + StandardShowDlgItem(hDlg, ID_PS_ICONDISPLAY, SW_HIDE); + + hListDisplay = GetDlgItem(hDlg, ID_PS_DISPLAYLIST); + + // If Paste was selected + if (lpPS->dwFlags & PSF_SELECTPASTE) + { + // Set the Source of the object in the clipboard + SetDlgItemText(hDlg, ID_PS_SOURCETEXT, lpPS->szSourceOfDataOD); + + // If an icon is available + if (lpPS->hMetaPictOD) + // Set the icon display + SendDlgItemMessage(hDlg, ID_PS_ICONDISPLAY, IBXM_IMAGESET, + (WPARAM)lpPS->hMetaPictOD, 0L); + + + hList = GetDlgItem(hDlg, ID_PS_PASTELIST); + // We are switching from PasteLink to Paste. Remember current selection + // in PasteLink list so it can be restored. + lpPS->nPasteLinkListCurSel = (int)SendMessage(hListDisplay, LB_GETCURSEL, 0, 0L); + if (lpPS->nPasteLinkListCurSel == LB_ERR) + lpPS->nPasteLinkListCurSel = 0; + // Remember if user selected Paste or PasteLink + lpPS->fLink = FALSE; + } + else // If PasteLink was selected + { + // Set the Source of the object in the clipboard + SetDlgItemText(hDlg, ID_PS_SOURCETEXT, lpPS->szSourceOfDataLSD); + + // If an icon is available + if (lpPS->hMetaPictLSD) + // Set the icon display + SendDlgItemMessage(hDlg, ID_PS_ICONDISPLAY, IBXM_IMAGESET, + (WPARAM)lpPS->hMetaPictLSD, 0L); + + + hList = GetDlgItem(hDlg, ID_PS_PASTELINKLIST); + // We are switching from Paste to PasteLink. Remember current selection + // in Paste list so it can be restored. + lpPS->nPasteListCurSel = (int)SendMessage(hListDisplay, LB_GETCURSEL, 0, 0L); + if (lpPS->nPasteListCurSel == LB_ERR) + lpPS->nPasteListCurSel = 0; + // Remember if user selected Paste or PasteLink + lpPS->fLink = TRUE; + } + + // Turn drawing off while the Display List is being filled + SendMessage(hListDisplay, WM_SETREDRAW, (WPARAM)FALSE, 0L); + + // Move data to Display list box + SendMessage(hListDisplay, LB_RESETCONTENT, 0, 0L); + nItems = (int) SendMessage(hList, LB_GETCOUNT, 0, 0L); + lpsz = (LPTSTR)GlobalLock(lpPS->hBuff); + for (i = 0; i < nItems; i++) + { + SendMessage(hList, LB_GETTEXT, (WPARAM)i, (LPARAM)lpsz); + dwData = SendMessage(hList, LB_GETITEMDATA, (WPARAM)i, 0L); + SendMessage(hListDisplay, LB_INSERTSTRING, (WPARAM)i, (LPARAM)lpsz); + SendMessage(hListDisplay, LB_SETITEMDATA, (WPARAM)i, dwData); + } + GlobalUnlock(lpPS->hBuff); + + // Restore the selection in the Display List from user's last selection + if (lpPS->dwFlags & PSF_SELECTPASTE) + SendMessage(hListDisplay, LB_SETCURSEL, lpPS->nPasteListCurSel, 0L); + else + SendMessage(hListDisplay, LB_SETCURSEL, lpPS->nPasteLinkListCurSel, 0L); + + // Paint Display List + SendMessage(hListDisplay, WM_SETREDRAW, (WPARAM)TRUE, 0L); + InvalidateRect(hListDisplay, NULL, TRUE); + UpdateWindow(hListDisplay); + + // Auto give the focus to the Display List + SetFocus(hListDisplay); + + // Enable/Disable DisplayAsIcon and set the help result text and bitmap corresponding to + // the current selection + ChangeListSelection(hDlg, lpPS, hListDisplay); + + return FALSE; +} + + +/* + * ChangeListSelection + * + * Purpose: + * When the user changes the selection in the list, DisplayAsIcon is enabled or disabled, + * Result text and bitmap are updated and the index of the arrPasteEntries[] corresponding + * to the current format selection is saved. + * + * Parameters: + * hDlg HWND of the dialog + * lpPS Paste Special Dialog Structure + * hList HWND of the List + * + * Return Value: + * No return value + */ + +void ChangeListSelection(HWND hDlg, LPPASTESPECIAL lpPS, HWND hList) +{ + LPPASTELISTITEMDATA lpItemData; + int nCurSel; + + EnableDisplayAsIcon(hDlg, lpPS); + SetPasteSpecialHelpResults(hDlg, lpPS); + + // Remember index of arrPasteEntries[] corresponding to the current selection + nCurSel = (int)SendMessage(hList, LB_GETCURSEL, 0, 0L); + if (nCurSel == LB_ERR) return; + lpItemData = (LPPASTELISTITEMDATA) SendMessage(hList, LB_GETITEMDATA, + (WPARAM)nCurSel, 0L); + if ((LRESULT)lpItemData == LB_ERR) return; + lpPS->nSelectedIndex = lpItemData->nPasteEntriesIndex; +} + +/* + * EnableDisplayAsIcon + * + * Purpose: + * Enable or disable the DisplayAsIcon button depending on whether + * the current selection can be displayed as an icon or not. The following table describes + * the state of DisplayAsIcon. The calling application is termed CONTAINER, the source + * of data on the clipboard is termed SOURCE. + * Y = Yes; N = No; Blank = State does not matter; + * ===================================================================== + * SOURCE SOURCE CONTAINER DisplayAsIcon + * specifies specifies specifies Initial State + * DVASPECT_ICON OLEMISC_ONLYICONIC OLEUIPASTE_ENABLEICON + * + * N Unchecked&Disabled + * Y Y Checked&Disabled + * Y N Y Checked&Enabled + * N N Y Unchecked&Enabled + * ===================================================================== + * + * Parameters: + * hDlg HWND of the dialog + * lpPS Paste Special Dialog Structure + * + * Return Value: + * No return value + */ + +void EnableDisplayAsIcon(HWND hDlg, LPPASTESPECIAL lpPS) +{ + int nIndex; + BOOL fCntrEnableIcon; + BOOL fSrcOnlyIconic = (lpPS->fLink) ? lpPS->fSrcOnlyIconicLSD : lpPS->fSrcOnlyIconicOD; + BOOL fSrcAspectIcon = (lpPS->fLink) ? lpPS->fSrcAspectIconLSD : lpPS->fSrcAspectIconOD; + HWND hList; + LPPASTELISTITEMDATA lpItemData; + HGLOBAL hMetaPict = (lpPS->fLink) ? lpPS->hMetaPictLSD : lpPS->hMetaPictOD; + + hList = GetDlgItem(hDlg, ID_PS_DISPLAYLIST); + + // Get data corresponding to the current selection in the listbox + nIndex = (int)SendMessage(hList, LB_GETCURSEL, 0, 0); + if (nIndex != LB_ERR) + { + lpItemData = (LPPASTELISTITEMDATA) SendMessage(hList, LB_GETITEMDATA, (WPARAM)nIndex, 0L); + if ((LRESULT)lpItemData != LB_ERR) + fCntrEnableIcon = lpItemData->fCntrEnableIcon; + else fCntrEnableIcon = FALSE; + } + else fCntrEnableIcon = FALSE; + + // If there is an icon available + if (hMetaPict != NULL) + { + if (!fCntrEnableIcon) // Does CONTAINER specify OLEUIPASTE_ENABLEICON? + { + // Uncheck & Disable DisplayAsIcon + lpPS->dwFlags &= ~PSF_CHECKDISPLAYASICON; + CheckDlgButton(hDlg, ID_PS_DISPLAYASICON, FALSE); + EnableWindow(GetDlgItem(hDlg, ID_PS_DISPLAYASICON), FALSE); + + // Hide IconDisplay and ChangeIcon button + StandardShowDlgItem(hDlg, ID_PS_ICONDISPLAY, SW_HIDE); + StandardShowDlgItem(hDlg, ID_PS_CHANGEICON, SW_HIDE); + } + else if (fSrcOnlyIconic) // Does SOURCE specify OLEMISC_ONLYICONIC? + { + // Check & Disable DisplayAsIcon + lpPS->dwFlags |= PSF_CHECKDISPLAYASICON; + CheckDlgButton(hDlg, ID_PS_DISPLAYASICON, TRUE); + EnableWindow(GetDlgItem(hDlg, ID_PS_DISPLAYASICON), FALSE); + + // Show IconDisplay and ChangeIcon button + StandardShowDlgItem(hDlg, ID_PS_ICONDISPLAY, SW_SHOWNORMAL); + StandardShowDlgItem(hDlg, ID_PS_CHANGEICON, SW_SHOWNORMAL); + } + else if (fSrcAspectIcon) // Does SOURCE specify DVASPECT_ICON? + { + // Check & Enable DisplayAsIcon + lpPS->dwFlags |= PSF_CHECKDISPLAYASICON; + CheckDlgButton(hDlg, ID_PS_DISPLAYASICON, TRUE); + EnableWindow(GetDlgItem(hDlg, ID_PS_DISPLAYASICON), TRUE); + + // Show IconDisplay and ChangeIcon button + StandardShowDlgItem(hDlg, ID_PS_ICONDISPLAY, SW_SHOWNORMAL); + StandardShowDlgItem(hDlg, ID_PS_CHANGEICON, SW_SHOWNORMAL); + } + else + { + //Uncheck and Enable DisplayAsIcon + lpPS->dwFlags &= ~PSF_CHECKDISPLAYASICON; + CheckDlgButton(hDlg, ID_PS_DISPLAYASICON, FALSE); + EnableWindow(GetDlgItem(hDlg, ID_PS_DISPLAYASICON), TRUE); + + // Hide IconDisplay and ChangeIcon button + StandardShowDlgItem(hDlg, ID_PS_ICONDISPLAY, SW_HIDE); + StandardShowDlgItem(hDlg, ID_PS_CHANGEICON, SW_HIDE); + + } + } + else // No icon available + { + // Unchecked & Disabled + lpPS->dwFlags &= ~PSF_CHECKDISPLAYASICON; + CheckDlgButton(hDlg, ID_PS_DISPLAYASICON, FALSE); + EnableWindow(GetDlgItem(hDlg, ID_PS_DISPLAYASICON), FALSE); + + // Hide IconDisplay and ChangeIcon button + StandardShowDlgItem(hDlg, ID_PS_ICONDISPLAY, SW_HIDE); + StandardShowDlgItem(hDlg, ID_PS_CHANGEICON, SW_HIDE); + } +} + +/* + * ToggleDisplayAsIcon + * + * Purpose: + * Toggles the DisplayAsIcon button. Hides or shows the Icon Display and + * the ChangeIcon button and changes the help result text and bitmap. + * + * Parameters: + * hDlg HWND of the dialog + * lpPS Paste Special Dialog Structure + * + * Return Value: + * None + * + */ + +void ToggleDisplayAsIcon(HWND hDlg, LPPASTESPECIAL lpPS) +{ + BOOL fCheck; + int i; + + fCheck = IsDlgButtonChecked(hDlg, ID_PS_DISPLAYASICON); + + if (fCheck) + lpPS->dwFlags |= PSF_CHECKDISPLAYASICON; + else lpPS->dwFlags &= ~PSF_CHECKDISPLAYASICON; + + // Set the help result text and bitmap + SetPasteSpecialHelpResults(hDlg, lpPS); + + // Show or hide the Icon Display and ChangeIcon button depending + // on the check state + i = (fCheck) ? SW_SHOWNORMAL : SW_HIDE; + StandardShowDlgItem(hDlg, ID_PS_ICONDISPLAY, i); + StandardShowDlgItem(hDlg, ID_PS_CHANGEICON, i); +} + +/* + * ChangeIcon + * + * Purpose: + * Brings up the ChangeIcon dialog which allows the user to change + * the icon and label. + * + * Parameters: + * hDlg HWND of the dialog + * lpPS Paste Special Dialog Structure + * + * Return Value: + * None + * + */ + +void ChangeIcon(HWND hDlg, LPPASTESPECIAL lpPS) +{ + OLEUICHANGEICON ci; + UINT uRet; + CLSID clsid = (lpPS->fLink) ? lpPS->clsidLSD : lpPS->clsidOD; + + //Initialize the structure + _fmemset((LPOLEUICHANGEICON)&ci, 0, sizeof(ci)); + + ci.hMetaPict = (HGLOBAL)SendDlgItemMessage(hDlg, ID_PS_ICONDISPLAY, IBXM_IMAGEGET, 0, 0L); + ci.cbStruct = sizeof(ci); + ci.hWndOwner = hDlg; + ci.clsid = clsid; + ci.dwFlags = CIF_SELECTCURRENT; + + // Only show help in the ChangeIcon dialog if we're showing it in this dialog. + if (lpPS->dwFlags & PSF_SHOWHELP) + ci.dwFlags |= CIF_SHOWHELP; + + // Let the hook in to customize Change Icon if desired. + uRet = UStandardHook(lpPS, hDlg, uMsgChangeIcon, 0, (LONG)(LPSTR)&ci); + + if (0 == uRet) + uRet=(UINT)(OLEUI_OK==OleUIChangeIcon(&ci)); + + // Update the display if necessary. + if (0!=uRet) + { + /* + * OleUIChangeIcon will have already freed our + * current hMetaPict that we passed in when OK is + * pressed in that dialog. So we use 0L as lParam + * here so the IconBox doesn't try to free the + * metafilepict again. + */ + SendDlgItemMessage(hDlg, ID_PS_ICONDISPLAY, IBXM_IMAGESET, (WPARAM)ci.hMetaPict, 0L); + // Remember the new icon chosen by the user. Note that Paste and PasteLink have separate + // icons - changing one does not change the other. + if (lpPS->fLink) + lpPS->hMetaPictLSD = ci.hMetaPict; + else lpPS->hMetaPictOD = ci.hMetaPict; + } +} + +/* + *SetPasteSpecialHelpResults + * + * Purpose: + * Sets the help result text and bitmap according to the current + * list selection. The following state table indicates which ResultText + * and ResultImage are selected. If %s in the lpstrFormatName is present, + * it is assumed that an object is being pasted/paste-linked, otherwise it + * is assumed that data is being pasted/paste-linked. + * Y = Yes; N = No; Blank = State does not matter; + * The numbers in the the ResultText and ResultImage columns refer to the table + * entries that follow. + * ===================================================================== + * Paste/ lpstrFormatName in DisplayAsIcon Result Result + * PasteLink arrPasteEntry[]contains %s checked Text Image + * (Is Object == Y, Is Data == N) + * Paste N 1 1 + * Paste Y N 2 2 + * Paste Y Y 3 3 + * PasteLink N 4 4 + * PasteLink Y N 5 4 + * PasteLink Y Y 6 5 + * ===================================================================== + * Result Text: + * + * 1. "Inserts the contents of the Clipboard into your document as " + * 2. "Inserts the contents of the Clipboard into your document so that you may + * activate it using " + * 3. "Inserts the contents of the Clipboard into your document so that you may + * activate it using . It will be displayed as an icon." + * 4. "Inserts the contents of the Clipboard into your document as . + * Paste Link creates a link to the source file so that changes to the source file + * will be reflected in your document." + * 5. "Inserts a picture of the Clipboard contents into your document. Paste Link + * creates a link to the source file so that changes to the source file will be + * reflected in your document." + * 6. "Inserts an icon into your document which represents the Clipboard contents. + * Paste Link creates a link to the source file so that changes to the source file + * will be reflected in your document." + * ===================================================================== + * Result Image: + * + * 1. Clipboard Image + * 2. Paste image, non-iconic. + * 3. Paste image, iconic. + * 4. Paste Link image, non-iconic + * 5. Paste Link image, iconic + * ==================================================================== + * + * Parameters: + * hDlg HWND of the dialog + * lpPS Paste Special Dialog Structure + * + * Return Value: + * No return value + */ +void SetPasteSpecialHelpResults(HWND hDlg, LPPASTESPECIAL lpPS) +{ + LPTSTR psz1, psz2, psz3, psz4; + UINT i, iString, iImage, cch; + int nPasteEntriesIndex; + BOOL fDisplayAsIcon; + BOOL fIsObject; + HWND hList; + LPPASTELISTITEMDATA lpItemData; + LPOLEUIPASTESPECIAL lpOPS = lpPS->lpOPS; + LPTSTR szFullUserTypeName = (lpPS->fLink) ? + lpPS->szFullUserTypeNameLSD : lpPS->szFullUserTypeNameOD; + LPTSTR szInsert; + + hList = GetDlgItem(hDlg, ID_PS_DISPLAYLIST); + + i=(UINT)SendMessage(hList, LB_GETCURSEL, 0, 0L); + if (i != LB_ERR) + { + lpItemData = (LPPASTELISTITEMDATA)SendMessage(hList, LB_GETITEMDATA, i, 0L); + if ((LRESULT)lpItemData == LB_ERR) return; + nPasteEntriesIndex = lpItemData->nPasteEntriesIndex; + // Check if there is a '%s' in the lpstrFormatName, then an object is being + // pasted/pastelinked. Otherwise Data is being pasted-pastelinked. + fIsObject = FHasPercentS(lpOPS->arrPasteEntries[nPasteEntriesIndex].lpstrFormatName, + lpPS); + } + else return; + + // Is DisplayAsIcon checked? + fDisplayAsIcon=(0L!=(lpPS->dwFlags & PSF_CHECKDISPLAYASICON)); + + szInsert = szFullUserTypeName; + + if (lpPS->dwFlags & PSF_SELECTPASTE) // If user selected Paste + { + if (fIsObject) + { + iString = fDisplayAsIcon ? IDS_PSPASTEOBJECTASICON : IDS_PSPASTEOBJECT; + iImage = fDisplayAsIcon ? RESULTIMAGE_EMBEDICON : RESULTIMAGE_EMBED; + szInsert = lpPS->szAppName; + } + else + { + iString = IDS_PSPASTEDATA; + iImage = RESULTIMAGE_PASTE; + } + } + else if (lpPS->dwFlags & PSF_SELECTPASTELINK) // User selected PasteLink + { + if (fIsObject) + { + iString = fDisplayAsIcon ? IDS_PSPASTELINKOBJECTASICON : IDS_PSPASTELINKOBJECT; + iImage = fDisplayAsIcon ? RESULTIMAGE_LINKICON : RESULTIMAGE_LINK; + } + else + { + iString = IDS_PSPASTELINKDATA; + iImage = RESULTIMAGE_LINK; + } + + } + else // Should never occur. + { + iString = IDS_PSNONOLE; + iImage = RESULTIMAGE_PASTE; + } + + // hBuff contains enough space for the 4 buffers required to build up the help + // result text. + cch = (UINT)GlobalSize(lpPS->hBuff)/4; + + psz1=(LPTSTR)GlobalLock(lpPS->hBuff); + psz2=psz1+cch; + psz3=psz2+cch; + psz4=psz3+cch; + + // Default is an empty string. + *psz1=0; + + if (0!=LoadString(ghInst, iString, psz1, cch)) + { + // Insert the FullUserTypeName of the source object into the partial result text + // specified by the container. + wsprintf(psz3, lpOPS->arrPasteEntries[nPasteEntriesIndex].lpstrResultText, + (LPTSTR)szInsert); + // Insert the above partial result text into the standard result text. + wsprintf(psz4, psz1, (LPTSTR)psz3); + psz1=psz4; + } + + // If LoadString failed, we simply clear out the results (*psz1=0 above) + SetDlgItemText(hDlg, ID_PS_RESULTTEXT, psz1); + + // Change the result bitmap + SendDlgItemMessage(hDlg, ID_PS_RESULTIMAGE, RIM_IMAGESET, iImage, 0L); + + GlobalUnlock(lpPS->hBuff); +} + +/* + * FAddPasteListItem + * + * Purpose: + * Adds an item to the list box + * + * Parameters: + * hList HWND List into which item is to be added + * fInsertFirst BOOL Insert in the beginning of the list? + * nPasteEntriesIndex int Index of Paste Entry array this list item corresponsds to + * lpPS Paste Special Dialog Structure + * pIMalloc LPMALLOC Memory Allocator + * lpszBuf LPSTR Scratch buffer to build up string for list entry + * lpszFullUserTypeName LPSTR full user type name for object entry + * + * Return Value: + * BOOL TRUE if sucessful. + * FALSE if unsucessful. + */ +BOOL FAddPasteListItem( + HWND hList, BOOL fInsertFirst, int nPasteEntriesIndex, + LPPASTESPECIAL lpPS, + LPMALLOC pIMalloc, LPTSTR lpszBuf, LPTSTR lpszFullUserTypeName) +{ + LPOLEUIPASTESPECIAL lpOPS = lpPS->lpOPS; + LPPASTELISTITEMDATA lpItemData; + int nIndex; + + // Allocate memory for each list box item + lpItemData = (LPPASTELISTITEMDATA)pIMalloc->lpVtbl->Alloc( + pIMalloc, (DWORD)sizeof(PASTELISTITEMDATA)); + if (NULL == lpItemData) + return FALSE; + + // Fill data associated with each list box item + lpItemData->nPasteEntriesIndex = nPasteEntriesIndex; + lpItemData->fCntrEnableIcon = ((lpOPS->arrPasteEntries[nPasteEntriesIndex].dwFlags & + OLEUIPASTE_ENABLEICON) ? TRUE : FALSE); + + // Build list box entry string, insert the string and add the data the corresponds to it + wsprintf( + (LPTSTR)lpszBuf, + lpOPS->arrPasteEntries[nPasteEntriesIndex].lpstrFormatName, + (LPTSTR)lpszFullUserTypeName + ); + + // only add to listbox if not a duplicate + if (LB_ERR!=SendMessage(hList,LB_FINDSTRING, 0, (LPARAM)(LPTSTR)lpszBuf)) { + // item is already in list; SKIP this one + pIMalloc->lpVtbl->Free(pIMalloc, (LPVOID)lpItemData); + return TRUE; // this is NOT an error + } + + nIndex = (int)SendMessage( + hList, + (fInsertFirst ? LB_INSERTSTRING : LB_ADDSTRING), + 0, + (LPARAM)(LPTSTR)lpszBuf + ); + SendMessage( + hList, + LB_SETITEMDATA, + nIndex, + (LPARAM)(LPPASTELISTITEMDATA)lpItemData + ); + return TRUE; +} + + +/* + * FFillPasteList + * + * Purpose: + * Fills the invisible paste list with the formats offered by the clipboard object and + * asked for by the container. + * + * Parameters: + * hDlg HWND of the dialog + * lpPS Paste Special Dialog Structure + * + * Return Value: + * BOOL TRUE if sucessful and if formats could be found. + * FALSE if unsucessful or if no formats could be found. + */ +BOOL FFillPasteList(HWND hDlg, LPPASTESPECIAL lpPS) +{ + LPOLEUIPASTESPECIAL lpOPS = lpPS->lpOPS; + LPMALLOC pIMalloc = NULL; + LPTSTR lpszBuf = (LPTSTR)GlobalLock(lpPS->hBuff); + HWND hList; + int i, j; + int nItems = 0; + int nDefFormat = -1; + BOOL fTryObjFmt = FALSE; + BOOL fInsertFirst; + BOOL fExclude; + HRESULT hrErr; + + hrErr = CoGetMalloc(MEMCTX_TASK, &pIMalloc); + if (hrErr != NOERROR) + goto error; + + hList = GetDlgItem(hDlg, ID_PS_PASTELIST); + + // Loop over the target's priority list of formats + for (i = 0; i < lpOPS->cPasteEntries; i++) + { + if (lpOPS->arrPasteEntries[i].dwFlags != OLEUIPASTE_PASTEONLY && + !(lpOPS->arrPasteEntries[i].dwFlags & OLEUIPASTE_PASTE)) + continue; + + fInsertFirst = FALSE; + + if (lpOPS->arrPasteEntries[i].fmtetc.cfFormat==cfFileName + || lpOPS->arrPasteEntries[i].fmtetc.cfFormat==cfEmbeddedObject + || lpOPS->arrPasteEntries[i].fmtetc.cfFormat==cfEmbedSource) { + if (! fTryObjFmt) { + fTryObjFmt = TRUE; // only use 1st object format + fInsertFirst = TRUE; // OLE obj format should always be 1st + + //Check if this CLSID is in the exclusion list. + fExclude=FALSE; + + for (j=0; j < (int)lpOPS->cClsidExclude; j++) + { + if (IsEqualCLSID(&lpPS->clsidOD, + (LPCLSID)(lpOPS->lpClsidExclude+j))) + { + fExclude=TRUE; + break; + } + } + + if (fExclude) + continue; // don't add the object entry to list + + } else { + continue; // already added an object format to list + } + } + + // add to list if entry is marked TRUE + if (lpOPS->arrPasteEntries[i].dwScratchSpace) { + if (nDefFormat < 0) + nDefFormat = (fInsertFirst ? 0 : nItems); + else if (fInsertFirst) + nDefFormat++; // adjust for obj fmt inserted 1st in list + + if (!FAddPasteListItem(hList, fInsertFirst, i, lpPS, pIMalloc, + lpszBuf, lpPS->szFullUserTypeNameOD)) + goto error; + nItems++; + } + } + + // initialize selection to first format matched in list + if (nDefFormat >= 0) + lpPS->nPasteListCurSel = nDefFormat; + + // Clean up + if (pIMalloc) + pIMalloc->lpVtbl->Release(pIMalloc); + if (lpszBuf) + GlobalUnlock(lpPS->hBuff); + + // If no items have been added to the list box (none of the formats + // offered by the source matched those acceptable to the container), + // return FALSE + if (nItems > 0) + return TRUE; + else + return FALSE; + +error: + if (pIMalloc) + pIMalloc->lpVtbl->Release(pIMalloc); + if (lpszBuf) + GlobalUnlock(lpPS->hBuff); + FreeListData(hList); + + return FALSE; +} + + +/* + * FFillPasteLinkList + * + * Purpose: + * Fills the invisible paste link list with the formats offered by the clipboard object and + * asked for by the container. + * + * Parameters: + * hDlg HWND of the dialog + * lpPS Paste Special Dialog Structure + * + * Return Value: + * BOOL TRUE if sucessful and if formats could be found. + * FALSE if unsucessful or if no formats could be found. + */ +BOOL FFillPasteLinkList(HWND hDlg, LPPASTESPECIAL lpPS) +{ + LPOLEUIPASTESPECIAL lpOPS = lpPS->lpOPS; + LPDATAOBJECT lpSrcDataObj = lpOPS->lpSrcDataObj; + LPENUMFORMATETC lpEnumFmtEtc = NULL; + LPMALLOC pIMalloc = NULL; + LPTSTR lpszBuf = (LPTSTR)GlobalLock(lpPS->hBuff); + OLEUIPASTEFLAG pasteFlag; + UINT arrLinkTypesSupported[PS_MAXLINKTYPES]; // Array of flags that + // indicate which link types + // are supported by source. + FORMATETC fmtetc; + int i, j; + int nItems = 0; + BOOL fLinkTypeSupported = FALSE; + HWND hList; + int nDefFormat = -1; + BOOL fTryObjFmt = FALSE; + BOOL fInsertFirst; + HRESULT hrErr; + + hrErr = CoGetMalloc(MEMCTX_TASK, &pIMalloc); + if (hrErr != NOERROR) + goto error; + + // Remember which link type formats are offered by lpSrcDataObj. + _fmemset(&fmtetc, 0, sizeof(FORMATETC)); + for (i = 0; i < lpOPS->cLinkTypes; i++) + { + if (lpOPS->arrLinkTypes[i] = cfLinkSource) { + OLEDBG_BEGIN2(TEXT("OleQueryLinkFromData called\r\n")) + hrErr = OleQueryLinkFromData(lpSrcDataObj); + OLEDBG_END2 + if(NOERROR == hrErr) + { + arrLinkTypesSupported[i] = 1; + fLinkTypeSupported = TRUE; + } + else arrLinkTypesSupported[i] = 0; + } + else { + fmtetc.cfFormat = lpOPS->arrLinkTypes[i]; + fmtetc.dwAspect = DVASPECT_CONTENT; + fmtetc.tymed = 0xFFFFFFFF; // All tymed values + fmtetc.lindex = -1; + OLEDBG_BEGIN2(TEXT("IDataObject::QueryGetData called\r\n")) + hrErr = lpSrcDataObj->lpVtbl->QueryGetData(lpSrcDataObj,&fmtetc); + OLEDBG_END2 + if(NOERROR == hrErr) + { + arrLinkTypesSupported[i] = 1; + fLinkTypeSupported = TRUE; + } + else arrLinkTypesSupported[i] = 0; + } + } + // No link types are offered by lpSrcDataObj + if (! fLinkTypeSupported) { + nItems = 0; + goto cleanup; + } + + hList = GetDlgItem(hDlg, ID_PS_PASTELINKLIST); + + // Enumerate the formats acceptable to container + for (i = 0; i < lpOPS->cPasteEntries; i++) + { + fLinkTypeSupported = FALSE; + + // If container will accept any link type offered by source object + if (lpOPS->arrPasteEntries[i].dwFlags & OLEUIPASTE_LINKANYTYPE) + fLinkTypeSupported = TRUE; + else + { + // Check if any of the link types offered by the source + // object are acceptable to the container + // This code depends on the LINKTYPE enum values being powers of 2 + for (pasteFlag = OLEUIPASTE_LINKTYPE1, j = 0; + j < lpOPS->cLinkTypes; + pasteFlag*=2, j++) + { + if ((lpOPS->arrPasteEntries[i].dwFlags & pasteFlag) && + arrLinkTypesSupported[j]) + { + fLinkTypeSupported = TRUE; + break; + } + } + } + + fInsertFirst = FALSE; + + if (lpOPS->arrPasteEntries[i].fmtetc.cfFormat==cfFileName + || lpOPS->arrPasteEntries[i].fmtetc.cfFormat==cfLinkSource) { + if (! fTryObjFmt) { + fTryObjFmt = TRUE; // only use 1st object format + fInsertFirst = TRUE; // OLE obj format should always be 1st + } else { + continue; // already added an object format to list + } + } + + // add to list if entry is marked TRUE + if (fLinkTypeSupported && lpOPS->arrPasteEntries[i].dwScratchSpace) { + if (nDefFormat < 0) + nDefFormat = (fInsertFirst ? 0 : nItems); + else if (fInsertFirst) + nDefFormat++; // adjust for obj fmt inserted 1st in list + + if (!FAddPasteListItem(hList, fInsertFirst, i, lpPS, pIMalloc, + lpszBuf, lpPS->szFullUserTypeNameLSD)) + goto error; + nItems++; + } + } // end FOR + + nItems = (int)SendMessage(hList, LB_GETCOUNT, 0, 0L); + + // initialize selection to first format matched in list + if (nDefFormat >= 0) + lpPS->nPasteLinkListCurSel = nDefFormat; + +cleanup: + // Clean up + if (pIMalloc) + pIMalloc->lpVtbl->Release(pIMalloc); + if (lpszBuf) + GlobalUnlock(lpPS->hBuff); + + // If no items have been added to the list box (none of the formats + // offered by the source matched those acceptable to the destination), + // return FALSE + if (nItems > 0) + return TRUE; + else + return FALSE; + +error: + if (pIMalloc) + pIMalloc->lpVtbl->Release(pIMalloc); + if (lpszBuf) + GlobalUnlock(lpPS->hBuff); + FreeListData(hList); + + return FALSE; +} + + +/* + * FreeListData + * + * Purpose: + * Free the local memory associated with each list box item + * + * Parameters: + * hList HWND of the list + * + * Return Value: + * None + */ +void FreeListData(HWND hList) +{ + int nItems, i; + LPPASTELISTITEMDATA lpItemData; + LPMALLOC pIMalloc; + HRESULT hrErr; + + hrErr = CoGetMalloc(MEMCTX_TASK, &pIMalloc); + if (hrErr != NOERROR) + return; + + nItems = (int) SendMessage(hList, LB_GETCOUNT, 0, 0L); + for (i = 0; i < nItems; i++) + { + lpItemData = (LPPASTELISTITEMDATA)SendMessage(hList, LB_GETITEMDATA, (WPARAM)i, 0L); + if ((LRESULT)lpItemData != LB_ERR) + pIMalloc->lpVtbl->Free(pIMalloc, (LPVOID)lpItemData); + } + pIMalloc->lpVtbl->Release(pIMalloc); +} + +/* + * FHasPercentS + * + * Purpose: + * Determines if string contains %s. + * + * Parameters: + * lpsz LPCSTR string in which occurence of '%s' is looked for + * + * Return Value: + * BOOL TRUE if %s is found, else FALSE. + */ + +BOOL FHasPercentS(LPCTSTR lpsz, LPPASTESPECIAL lpPS) +{ + int n = 0; + LPTSTR lpszTmp; + + if (!lpsz) return FALSE; + // Copy input string to buffer. This allows caller to pass a + // code-based string. Code segments may be swapped out in low memory situations + // and so code-based strings need to be copied before string elements can be accessed. + lpszTmp = (LPTSTR)GlobalLock(lpPS->hBuff); + lstrcpy(lpszTmp, lpsz); + + while (*lpszTmp) + { + if (*lpszTmp == TEXT('%')) + { +#ifdef WIN32 + // AnsiNext is obsolete in Win32 + lpszTmp = CharNext(lpszTmp); +#else + lpszTmp = AnsiNext(lpszTmp); +#endif + if (*lpszTmp == TEXT('s')) // If %s, return + { + GlobalUnlock(lpPS->hBuff); + return TRUE; + } + else if (*lpszTmp == TEXT('%')) // if %%, skip to next character +#ifdef WIN32 + // AnsiNext is obsolete in Win32 + lpszTmp = CharNext(lpszTmp); +#else + lpszTmp = AnsiNext(lpszTmp); +#endif + } + else +#ifdef WIN32 + lpszTmp = CharNext(lpszTmp); +#else + lpszTmp = AnsiNext(lpszTmp); +#endif + } + + GlobalUnlock(lpPS->hBuff); + return FALSE; +} + +/* + * AllocateScratchMem + * + * Purpose: + * Allocates scratch memory for use by the PasteSpecial dialog. The memory is + * is used as the buffer for building up strings using wsprintf. Strings are built up + * using the buffer while inserting items into the Paste & PasteLink lists and while + * setting the help result text. It must be big enough to handle the string that results after + * replacing the %s in the lpstrFormatName and lpstrResultText in arrPasteEntries[] + * by the FullUserTypeName. It must also be big enough to build the dialog's result text + * after %s substitutions by the FullUserTypeName or the ApplicationName. + * + * Parameters: + * lpPS Paste Special Dialog Structure + * + * Return Value: + * HGLOBAL Handle to allocated global memory + */ + +HGLOBAL AllocateScratchMem(LPPASTESPECIAL lpPS) +{ + LPOLEUIPASTESPECIAL lpOPS = lpPS->lpOPS; + int nLen, i; + int nSubstitutedText = 0; + int nAlloc = 0; + + // Get the maximum length of the FullUserTypeNames specified by OBJECTDESCRIPTOR + // and the LINKSRCDESCRIPTOR and the Application Name. Any of these may be substituted + // for %s in the result-text/list entries. + if (lpPS->szFullUserTypeNameOD) + nSubstitutedText = lstrlen(lpPS->szFullUserTypeNameOD); + if (lpPS->szFullUserTypeNameLSD) + nSubstitutedText = __max(nSubstitutedText, lstrlen(lpPS->szFullUserTypeNameLSD)); + if (lpPS->szAppName) + nSubstitutedText = __max(nSubstitutedText, lstrlen(lpPS->szAppName)); + + // Get the maximum length of lpstrFormatNames & lpstrResultText in arrPasteEntries + nLen = 0; + for (i = 0; i < lpOPS->cPasteEntries; i++) + { + nLen = __max(nLen, lstrlen(lpOPS->arrPasteEntries[i].lpstrFormatName)); + nLen = __max(nLen, lstrlen(lpOPS->arrPasteEntries[i].lpstrResultText)); + } + + // Get the maximum length of lpstrFormatNames and lpstrResultText after %s has + // been substituted (At most one %s can appear in each string). + // Add 1 to hold NULL terminator. + nAlloc = (nLen+nSubstitutedText+1)*sizeof(TCHAR); + + // Allocate scratch memory to be used to build strings + // nAlloc is big enough to hold any of the lpstrResultText or lpstrFormatName in arrPasteEntries[] + // after %s substitution. + // We also need space to build up the help result text. 512 is the maximum length of the + // standard dialog help text before substitutions. 512+nAlloc is the maximum length + // after %s substition. + // SetPasteSpecialHelpResults() requires 4 such buffers to build up the result text + return GlobalAlloc(GHND, (DWORD)4*(512+nAlloc)); +} + diff --git a/private/oleutest/letest/ole2ui/pastespl.dlg b/private/oleutest/letest/ole2ui/pastespl.dlg new file mode 100644 index 000000000..d64f5e45c --- /dev/null +++ b/private/oleutest/letest/ole2ui/pastespl.dlg @@ -0,0 +1,40 @@ +// DLGINCLUDE RCDATA DISCARDABLE +// BEGIN +// "PASTESPL.H\0" +// END + +IDD_PASTESPECIAL DIALOG 3, 15, 293, 140 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Paste Special" +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "Source:", ID_PS_STXSOURCE, 6, 9, 30, 8 + LTEXT "", ID_PS_SOURCETEXT, 37, 9, 180, 8, SS_NOPREFIX | NOT + WS_GROUP + CONTROL "&Paste", ID_PS_PASTE, "Button", BS_AUTORADIOBUTTON | + WS_GROUP | WS_TABSTOP, 6, 38, 55, 10 + CONTROL "Paste &Link", ID_PS_PASTELINK, "Button", + BS_AUTORADIOBUTTON, 6, 63, 55, 10 + LTEXT "&As:", ID_PS_STXAS, 65, 25, 16, 8 + LISTBOX ID_PS_PASTELIST, 65, 36, 153, 57, LBS_USETABSTOPS | + WS_VSCROLL | WS_GROUP | WS_TABSTOP | NOT WS_VISIBLE + LISTBOX ID_PS_PASTELINKLIST, 65, 36, 153, 57, LBS_USETABSTOPS | + WS_VSCROLL | WS_GROUP | WS_TABSTOP | NOT WS_VISIBLE + LISTBOX ID_PS_DISPLAYLIST, 65, 36, 153, 57, LBS_USETABSTOPS | + WS_VSCROLL | WS_GROUP | WS_TABSTOP + DEFPUSHBUTTON "OK", IDOK, 224, 6, 66, 14, WS_GROUP + PUSHBUTTON "Cancel", IDCANCEL, 224, 23, 66, 14 + PUSHBUTTON "&Help", ID_OLEUIHELP, 224, 42, 66, 14 + CONTROL "&Display As Icon", ID_PS_DISPLAYASICON, "Button", + BS_AUTOCHECKBOX | WS_TABSTOP, 224, 59, 66, 14 +// CONTROL "", ID_PS_ICONDISPLAY, SZCLASSICONBOX, 0, 224, 75, 66, 44 + PUSHBUTTON "Change &Icon...", ID_PS_CHANGEICON, 224, 123, 66, 14 +// CONTROL "", ID_PS_RESULTIMAGE, SZCLASSRESULTIMAGE, 0, 8, 101, +// 42, 34 + LTEXT "Result", ID_PS_RESULTTEXT, 54, 100, 159, 35, + SS_NOPREFIX | NOT WS_GROUP + GROUPBOX "Result", ID_PS_RESULTGROUP, 6, 90, 212, 48, WS_GROUP +END + + + diff --git a/private/oleutest/letest/ole2ui/pastespl.h b/private/oleutest/letest/ole2ui/pastespl.h new file mode 100644 index 000000000..526462f36 --- /dev/null +++ b/private/oleutest/letest/ole2ui/pastespl.h @@ -0,0 +1,110 @@ +/* + * PASTESPL.H + * + * Internal definitions, structures, and function prototypes for the + * OLE 2.0 UI Paste Special dialog. + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + +#ifndef _PASTESPL_H_ +#define _PASTESPL_H_ + +#ifndef RC_INVOKED +#pragma message ("INCLUDING PASTESPL.H from " __FILE__) +#endif /* RC_INVOKED */ + + +// Length of buffers to hold the strings 'Unknown Type', Unknown Source' +// and 'the application which created it' +#define PS_UNKNOWNSTRLEN 100 + +//Property label used to store clipboard viewer chain information +#define NEXTCBVIEWER TEXT("NextCBViewer") + +//Internally used structure +typedef struct tagPASTESPECIAL +{ + //Keep this item first as the Standard* functions depend on it here. + LPOLEUIPASTESPECIAL lpOPS; //Original structure passed. + + /* + * What we store extra in this structure besides the original caller's + * pointer are those fields that we need to modify during the life of + * the dialog but that we don't want to change in the original structure + * until the user presses OK. + */ + + DWORD dwFlags; // Local copy of paste special flags + + int nPasteListCurSel; // Save the selection the user made last + int nPasteLinkListCurSel; // in the paste and pastelink lists + int nSelectedIndex; // Index in arrPasteEntries[] corresponding to user selection + BOOL fLink; // Indicates if Paste or PasteLink was selected by user + + HGLOBAL hBuff; // Scratch Buffer for building up strings + TCHAR szUnknownType[PS_UNKNOWNSTRLEN]; // Buffer for 'Unknown Type' string + TCHAR szUnknownSource[PS_UNKNOWNSTRLEN]; // Buffer for 'Unknown Source' string + TCHAR szAppName[OLEUI_CCHKEYMAX]; // Application name of Source. Used in the result text + // when Paste is selected. Obtained using clsidOD. + + // Information obtained from OBJECTDESCRIPTOR. This information is accessed when the Paste + // radio button is selected. + CLSID clsidOD; // ClassID of source + SIZEL sizelOD; // sizel transfered in + // ObjectDescriptor + LPTSTR szFullUserTypeNameOD; // Full User Type Name + LPTSTR szSourceOfDataOD; // Source of Data + BOOL fSrcAspectIconOD; // Does Source specify DVASPECT_ICON? + BOOL fSrcOnlyIconicOD; // Does Source specify OLEMISC_ONLYICONIC? + HGLOBAL hMetaPictOD; // Metafile containing icon and icon title + HGLOBAL hObjDesc; // Handle to OBJECTDESCRIPTOR structure from which the + // above information is obtained + + // Information obtained from LINKSRCDESCRIPTOR. This infomation is accessed when the PasteLink + // radio button is selected. + CLSID clsidLSD; // ClassID of source + SIZEL sizelLSD; // sizel transfered in + // LinkSrcDescriptor + LPTSTR szFullUserTypeNameLSD;// Full User Type Name + LPTSTR szSourceOfDataLSD; // Source of Data + BOOL fSrcAspectIconLSD; // Does Source specify DVASPECT_ICON? + BOOL fSrcOnlyIconicLSD; // Does Source specify OLEMISC_ONLYICONIC? + HGLOBAL hMetaPictLSD; // Metafile containing icon and icon title + HGLOBAL hLinkSrcDesc; // Handle to LINKSRCDESCRIPTOR structure from which the + // above information is obtained + + BOOL fClipboardChanged; // Has clipboard content changed + // if so bring down dlg after + // ChangeIcon dlg returns. +} PASTESPECIAL, *PPASTESPECIAL, FAR *LPPASTESPECIAL; + +// Data corresponding to each list item. A pointer to this structure is attached to each +// Paste\PasteLink list box item using LB_SETITEMDATA +typedef struct tagPASTELISTITEMDATA +{ + int nPasteEntriesIndex; // Index of arrPasteEntries[] corresponding to list item + BOOL fCntrEnableIcon; // Does calling application (called container here) + // specify OLEUIPASTE_ENABLEICON for this item? +} PASTELISTITEMDATA, *PPASTELISTITEMDATA, FAR *LPPASTELISTITEMDATA; + + +//Internal function prototypes +//PASTESPL.C +BOOL CALLBACK EXPORT PasteSpecialDialogProc(HWND, UINT, WPARAM, LPARAM); +BOOL FPasteSpecialInit(HWND hDlg, WPARAM, LPARAM); +BOOL FTogglePasteType(HWND, LPPASTESPECIAL, DWORD); +void ChangeListSelection(HWND, LPPASTESPECIAL, HWND); +void EnableDisplayAsIcon(HWND, LPPASTESPECIAL); +void ToggleDisplayAsIcon(HWND, LPPASTESPECIAL); +void ChangeIcon(HWND, LPPASTESPECIAL); +void SetPasteSpecialHelpResults(HWND, LPPASTESPECIAL); +BOOL FAddPasteListItem(HWND, BOOL, int, LPPASTESPECIAL, LPMALLOC, LPTSTR, LPTSTR); +BOOL FFillPasteList(HWND, LPPASTESPECIAL); +BOOL FFillPasteLinkList(HWND, LPPASTESPECIAL); +BOOL FHasPercentS(LPCTSTR, LPPASTESPECIAL); +HGLOBAL AllocateScratchMem(LPPASTESPECIAL); +void FreeListData(HWND); + +#endif //_PASTESPL_H_ + diff --git a/private/oleutest/letest/ole2ui/precomp.c b/private/oleutest/letest/ole2ui/precomp.c new file mode 100644 index 000000000..1385d8a41 --- /dev/null +++ b/private/oleutest/letest/ole2ui/precomp.c @@ -0,0 +1,23 @@ +/* + * PRECOMP.C + * + * This file is used to precompile the OLE2UI.H header file + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + +#define STRICT 1 +#include "ole2ui.h" + +// This dummy function is needed in order for the static link version +// of this library to work correctly. When we include PRECOMP.OBJ +// in our library (.LIB file), it will only get linked into our +// application IFF at least one function in precomp.c is called from +// either our EXE or LIB. Therefore, we will use a function +// here called OleUIStaticLibDummy(). You need to call it from +// your application. + +void FAR PASCAL OleUIStaticLibDummy(void) +{ + +} diff --git a/private/oleutest/letest/ole2ui/prompt.dlg b/private/oleutest/letest/ole2ui/prompt.dlg new file mode 100644 index 000000000..fc8474315 --- /dev/null +++ b/private/oleutest/letest/ole2ui/prompt.dlg @@ -0,0 +1,80 @@ +Exclamation ICON bang.ico + + +IDD_LINKSOURCEUNAVAILABLE DIALOG 21, 34, 175, 78 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "" +FONT 8, "MS Shell Dlg" +BEGIN + ICON "Exclamation", ID_DUMMY, 8, 8, 0, 0, SS_ICON + LTEXT "This action cannot be completed because the selected link's source is presently unavailable.", ID_PU_TEXT, 48, 8, 117, 32 + DEFPUSHBUTTON "OK", IDOK, 39, 58, 40, 14 + PUSHBUTTON "Links...", ID_PU_LINKS, 95, 58, 40, 14 +END + + +IDD_CANNOTUPDATELINK DIALOG 21, 34, 175, 78 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "" +FONT 8, "MS Shell Dlg" +BEGIN + ICON "Exclamation", ID_DUMMY, 8, 8, 0, 0, SS_ICON + LTEXT "Some links could not be updated because their sources are presently unavailable.", ID_PU_TEXT, 48, 8, 117, 32 + DEFPUSHBUTTON "OK", IDOK, 39, 58, 40, 14 + PUSHBUTTON "Links...", ID_PU_LINKS, 95, 58, 40, 14 +END + + +IDD_SERVERNOTREG DIALOG 39, 30, 198, 78 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +FONT 8, "MS Shell Dlg" +BEGIN + ICON "Exclamation", ID_DUMMY, 8, 8, 0, 0, SS_ICON + LTEXT "The application necessary to activate this %s is unavailable. You may convert it to or activate it as another type of object using Convert...", ID_PU_TEXT, 39, 8, 152, 36 + DEFPUSHBUTTON "Convert...", ID_PU_CONVERT, 23, 58, 40, 14 + PUSHBUTTON "Cancel", IDCANCEL, 79, 58, 40, 14 + PUSHBUTTON "Help", ID_OLEUIHELP, 135, 58, 40, 14 +END + + +IDD_LINKTYPECHANGED DIALOG 39, 30, 198, 78 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +FONT 8, "MS Shell Dlg" +BEGIN + ICON "Exclamation", ID_DUMMY, 8, 8, 0, 0, SS_ICON + LTEXT "The link is no longer a %s. Please choose a different command offered by the new type.", + ID_PU_TEXT, 39, 8, 152, 36 + PUSHBUTTON "OK", IDOK, 79, 58, 40, 14 +END + + +IDD_SERVERNOTFOUND DIALOG 36, 39, 183, 90 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +FONT 8, "MS Shell Dlg" +BEGIN + ICON "Exclamation", ID_DUMMY, 8, 8, 0, 0, SS_ICON + LTEXT "The server application cannot be found.\n\nMake sure the application is properly installed, or exists in your DOS path, and that is has not been deleted, moved, or renamed.", + ID_PU_TEXT, 38, 8, 136, 52 + DEFPUSHBUTTON "OK", IDOK, 71, 70, 40, 14 +END + + +IDD_UPDATELINKS DIALOG 50, 57, 179, 55 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "", ID_PU_METER, "Static", SS_BLACKFRAME, 5, 40, 122, 9 + DEFPUSHBUTTON "Stop", ID_PU_STOP, 134, 37, 40, 14 + LTEXT "Update links...", ID_DUMMY, 5, 7, 56, 8 + LTEXT "", ID_PU_PERCENT, 56, 26, 20, 8 +END + + +IDD_OUTOFMEMORY DIALOG 36, 39, 107, 73 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +FONT 8, "MS Shell Dlg" +BEGIN + ICON "Exclamation", ID_DUMMY, 8, 8, 0, 0, SS_ICON + LTEXT "Out of memory!", ID_PU_TEXT, 41, 13, 57, 12 + DEFPUSHBUTTON "OK", IDOK, 33, 53, 40, 14 +END diff --git a/private/oleutest/letest/ole2ui/regdb.c b/private/oleutest/letest/ole2ui/regdb.c new file mode 100644 index 000000000..b6922b260 --- /dev/null +++ b/private/oleutest/letest/ole2ui/regdb.c @@ -0,0 +1,401 @@ +/* + * REGDB.C + * + * Functions to query the registration database + * + * OleStdGetMiscStatusOfClass + * OleStdGetDefaultFileFormatOfClass + * OleStdGetAuxUserType + * OleStdGetUserTypeOfClass + * + * (c) Copyright Microsoft Corp. 1992-1993 All Rights Reserved + * + */ + +#define STRICT 1 +#include "ole2ui.h" +#include "common.h" +#include + +OLEDBGDATA + +// Replacement for stdlib atol, +// which didn't work and doesn't take far pointers. +// Must be tolerant of leading spaces. +// +// +static LONG Atol(LPTSTR lpsz) +{ + signed int sign = +1; + UINT base = 10; + LONG l = 0; + + if (NULL==lpsz) + { + OleDbgAssert (0); + return 0; + } + while (isspace(*lpsz)) + lpsz++; + + if (*lpsz=='-') + { + lpsz++; + sign = -1; + } + if (lpsz[0]==TEXT('0') && lpsz[1]==TEXT('x')) + { + base = 16; + lpsz+=2; + } + + if (base==10) + { + while (isdigit(*lpsz)) + { + l = l * base + *lpsz - '0'; + lpsz++; + } + } + else + { + OleDbgAssert (base==16); + while (isxdigit(*lpsz)) + { + l = l * base + isdigit(*lpsz) ? *lpsz - '0' : toupper(*lpsz) - 'A' + 10; + lpsz++; + } + } + return l * sign; +} + + + +/* + * OleStdGetUserTypeOfClass(REFCLSID, LPSTR, UINT, HKEY) + * + * Purpose: + * Returns the user type (human readable class name) of the specified class. + * + * Parameters: + * rclsid pointer to the clsid to retrieve user type of. + * lpszUserType pointer to buffer to return user type in. + * cch length of buffer pointed to by lpszUserType + * hKey hKey for reg db - if this is NULL, then we + * open and close the reg db within this function. If it + * is non-NULL, then we assume it's a valid key to the + * \ root and use it without closing it. (useful + * if you're doing lots of reg db stuff). + * + * Return Value: + * UINT Number of characters in returned string. 0 on error. + * + */ +STDAPI_(UINT) OleStdGetUserTypeOfClass(REFCLSID rclsid, LPTSTR lpszUserType, UINT cch, HKEY hKey) +{ + + LONG dw; + LONG lRet; + LPSTR lpszCLSID, lpszProgID; + BOOL fFreeProgID = FALSE; + BOOL bCloseRegDB = FALSE; + TCHAR szKey[128]; + LPMALLOC lpIMalloc; + + if (!lpszUserType) + return 0; + + *lpszUserType = TEXT('\0'); + if (hKey == NULL) + { + + //Open up the root key. + lRet=RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hKey); + + if ((LONG)ERROR_SUCCESS!=lRet) + return (UINT)FALSE; + + bCloseRegDB = TRUE; + } + + // Get a string containing the class name + StringFromCLSIDA(rclsid, &lpszCLSID); + + wsprintf(szKey, TEXT("CLSID\\%s"), lpszCLSID); + + dw=cch; + lRet = RegQueryValue(hKey, szKey, lpszUserType, &dw); + + if ((LONG)ERROR_SUCCESS!=lRet) { + // Load 'Unknown Source' and 'Unknown Type' strings + dw = (LONG)LoadString(ghInst, IDS_PSUNKNOWNTYPE, lpszUserType, cch); + } + + if ( ((LONG)ERROR_SUCCESS!=lRet) && (CoIsOle1Class(rclsid)) ) + { + // We've got an OLE 1.0 class, so let's try to get the user type + // name from the ProgID entry. + + ProgIDFromCLSIDA(rclsid, &lpszProgID); + fFreeProgID = TRUE; + + dw = cch; + lRet = RegQueryValue(hKey, lpszProgID, lpszUserType, &dw); + + if ((LONG)ERROR_SUCCESS != lRet) + dw = 0; + } + + + if (NOERROR == CoGetMalloc(MEMCTX_TASK, &lpIMalloc)) + { + if (fFreeProgID) + lpIMalloc->lpVtbl->Free(lpIMalloc, (LPVOID)lpszProgID); + + lpIMalloc->lpVtbl->Free(lpIMalloc, (LPVOID)lpszCLSID); + lpIMalloc->lpVtbl->Release(lpIMalloc); + } + + if (bCloseRegDB) + RegCloseKey(hKey); + + return (UINT)dw; + +} + + + +/* + * OleStdGetAuxUserType(RCLSID, WORD, LPSTR, int, HKEY) + * + * Purpose: + * Returns the specified AuxUserType from the reg db. + * + * Parameters: + * rclsid pointer to the clsid to retrieve aux user type of. + * hKey hKey for reg db - if this is NULL, then we + * open and close the reg db within this function. If it + * is non-NULL, then we assume it's a valid key to the + * \ root and use it without closing it. (useful + * if you're doing lots of reg db stuff). + * wAuxUserType which aux user type field to look for. In 4/93 release + * 2 is short name and 3 is exe name. + * lpszUserType pointer to buffer to return user type in. + * cch length of buffer pointed to by lpszUserType + * + * Return Value: + * UINT Number of characters in returned string. 0 on error. + * + */ +STDAPI_(UINT) OleStdGetAuxUserType(REFCLSID rclsid, + WORD wAuxUserType, + LPTSTR lpszAuxUserType, + int cch, + HKEY hKey) +{ + HKEY hThisKey; + BOOL fCloseRegDB = FALSE; + LONG dw; + LRESULT lRet; + LPTSTR lpszCLSID; + LPMALLOC lpIMalloc; + TCHAR szKey[OLEUI_CCHKEYMAX]; + TCHAR szTemp[32]; + + lpszAuxUserType[0] = TEXT('\0'); + + if (NULL == hKey) + { + lRet = RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hThisKey); + + if (ERROR_SUCCESS != lRet) + return 0; + } + else + hThisKey = hKey; + + StringFromCLSIDA(rclsid, &lpszCLSID); + + lstrcpy(szKey, TEXT("CLSID\\")); + lstrcat(szKey, lpszCLSID); + wsprintf(szTemp, TEXT("\\AuxUserType\\%d"), wAuxUserType); + lstrcat(szKey, szTemp); + + dw = cch; + + lRet = RegQueryValue(hThisKey, szKey, lpszAuxUserType, &dw); + + if (ERROR_SUCCESS != lRet) { + dw = 0; + lpszAuxUserType[0] = TEXT('\0'); + } + + + if (fCloseRegDB) + RegCloseKey(hThisKey); + + if (NOERROR == CoGetMalloc(MEMCTX_TASK, &lpIMalloc)) + { + lpIMalloc->lpVtbl->Free(lpIMalloc, (LPVOID)lpszCLSID); + lpIMalloc->lpVtbl->Release(lpIMalloc); + } + + return (UINT)dw; +} + + + +/* + * OleStdGetMiscStatusOfClass(REFCLSID, HKEY) + * + * Purpose: + * Returns the value of the misc status for the given clsid. + * + * Parameters: + * rclsid pointer to the clsid to retrieve user type of. + * hKey hKey for reg db - if this is NULL, then we + * open and close the reg db within this function. If it + * is non-NULL, then we assume it's a valid key to the + * \\CLSID root and use it without closing it. (useful + * if you're doing lots of reg db stuff). + * + * Return Value: + * BOOL TRUE on success, FALSE on failure. + * + */ +STDAPI_(BOOL) OleStdGetMiscStatusOfClass(REFCLSID rclsid, HKEY hKey, DWORD FAR * lpdwValue) +{ + DWORD dw; + LONG lRet; + LPTSTR lpszCLSID; + TCHAR szKey[64]; + TCHAR szMiscStatus[OLEUI_CCHKEYMAX]; + BOOL bCloseRegDB = FALSE; + + if (hKey == NULL) + { + + //Open up the root key. + lRet=RegOpenKey(HKEY_CLASSES_ROOT, TEXT("CLSID"), &hKey); + + if ((LONG)ERROR_SUCCESS!=lRet) + return FALSE; + + bCloseRegDB = TRUE; + } + + // Get a string containing the class name + StringFromCLSIDA(rclsid, &lpszCLSID); + + // Construct key + lstrcpy(szKey, lpszCLSID); + + lstrcat(szKey, TEXT("\\MiscStatus")); + + + dw=OLEUI_CCHKEYMAX_SIZE; + lRet = RegQueryValue(hKey, szKey, (LPTSTR)szMiscStatus, &dw); + + if ((LONG)ERROR_SUCCESS!=lRet) + { + OleStdFreeString(lpszCLSID, NULL); + + if (bCloseRegDB) + RegCloseKey(hKey); + + return FALSE; + + } + + *lpdwValue = Atol((LPTSTR)szMiscStatus); + + OleStdFreeString(lpszCLSID, NULL); + + if (bCloseRegDB) + RegCloseKey(hKey); + + return TRUE; + + +} + + +/* + * CLIPFORMAT OleStdGetDefaultFileFormatOfClass(REFCLSID, HKEY) + * + * Purpose: + * Returns the default file format of the specified class. + * this is entered in REGDB as follows: + * CLSID\{...}\DataFormats\DefaultFile = + * + * Parameters: + * rclsid pointer to the clsid to retrieve user type of. + * hKey hKey for reg db- if this is NULL, then we + * open and close the reg db within this function. If it + * is non-NULL, then we assume it's a valid key to the + * \ root and use it without closing it. (useful + * if you're doing lots of reg db stuff). + * + * Return Value: + * cfFmt -- DefaultFile format + * NULL -- failed to get default file format + * + */ +STDAPI_(CLIPFORMAT) OleStdGetDefaultFileFormatOfClass( + REFCLSID rclsid, + HKEY hKey +) +{ + CLIPFORMAT cfFmt = 0; + DWORD dw; + LONG lRet; + LPTSTR lpszCLSID; + BOOL bCloseRegDB = FALSE; + TCHAR szKey[128]; + TCHAR szDefaultFile[OLEUI_CCHKEYMAX]; + BOOL bStatus = TRUE; + + + if (hKey == NULL) + { + + //Open up the root key. + lRet=RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hKey); + + if ((LONG)ERROR_SUCCESS!=lRet) + return 0; + + bCloseRegDB = TRUE; + } + + + // Get a string containing the class name + StringFromCLSIDA(rclsid, &lpszCLSID); + + // Construct key + wsprintf(szKey, TEXT("CLSID\\%s\\DataFormats\\DefaultFile"), lpszCLSID); + + OleStdFreeString(lpszCLSID, NULL); + + dw=OLEUI_CCHKEYMAX_SIZE; + lRet = RegQueryValue(hKey, szKey, (LPTSTR)szDefaultFile, (LONG FAR *)&dw); + + if ((LONG)ERROR_SUCCESS!=lRet) + bStatus = FALSE; + else { + /* if the format is a number, then it should refer to one of the + ** standard Windows formats. + */ + if (isdigit(szDefaultFile[0])) + cfFmt = (CLIPFORMAT)Atol(szDefaultFile); + else + cfFmt = RegisterClipboardFormat(szDefaultFile); + } + + if (bCloseRegDB) + RegCloseKey(hKey); + + return cfFmt; +} + + diff --git a/private/oleutest/letest/ole2ui/regdb.h b/private/oleutest/letest/ole2ui/regdb.h new file mode 100644 index 000000000..d05bc93b2 --- /dev/null +++ b/private/oleutest/letest/ole2ui/regdb.h @@ -0,0 +1,8 @@ +// This file is now OBSOLETE (include olestd.h instead) +/* + * Regdb.h + * + * (c) Copyright Microsoft Corp. 1992 All Rights Reserved + */ + +// Function prototypes moved to olestd.h diff --git a/private/oleutest/letest/ole2ui/resimage.c b/private/oleutest/letest/ole2ui/resimage.c new file mode 100644 index 000000000..8a95f4c71 --- /dev/null +++ b/private/oleutest/letest/ole2ui/resimage.c @@ -0,0 +1,363 @@ +/* + * RESIMAGE.C + * + * Implementation of the Results Image control for OLE 2.0 UI dialogs. + * We need a separate control for dialogs in order to control the repaints + * properly and to provide a clean message interface for the dialog + * implementations. + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + + +#define STRICT 1 +#include "ole2ui.h" +#include "resimage.h" + +OLEDBGDATA + +//Flag indicating if we've registered the class +static BOOL fRegistered=FALSE; + +//Bitmap and image dimensions for result images. +static HBITMAP hBmpResults=NULL; +static UINT cxBmpResult=0; +static UINT cyBmpResult=0; + +/* + * FResultImageInitialize + * + * Purpose: + * Attempts to load result bitmaps for the current display driver + * for use in OLE 2.0 UI dialogs. Also registers the ResultImage + * control class. + * + * Parameters: + * hInst HINSTANCE instance of the DLL. + * + * hPrevInst HINSTANCE of the previous instance. Used to + * determine whether to register window classes or not. + * + * lpszClassName LPSTR containing the class name to register the + * ResultImage control class with. + * + * Return Value: + * BOOL TRUE if all initialization succeeded, FALSE otherwise. + */ + +BOOL FResultImageInitialize(HINSTANCE hInst, HINSTANCE hPrevInst, LPTSTR lpszClassName) + { + int cx, iBmp; + HDC hDC; + BITMAP bm; + + WNDCLASS wc; + + + /* + * Determine the aspect ratio of the display we're currently + * running on and load the appropriate bitmap into the global + * hBmpResults (used from the ResultImage control only). + * + * By retrieving the logical Y extent of the display driver, you + * only have limited possibilities: + * LOGPIXELSY Display + * ---------------------------------------- + * 48 CGA (unsupported) + * 72 EGA + * 96 VGA + * 120 8514/a (i.e. HiRes VGA) + */ + + hDC=GetDC(NULL); + + if (NULL==hDC) + return FALSE; + + cx=GetDeviceCaps(hDC, LOGPIXELSY); + ReleaseDC(NULL, hDC); + + /* + * Instead of single comparisons, check ranges instead, so in case + * we get something funky, we'll act reasonable. + */ + if (72 >=cx) iBmp=IDB_RESULTSEGA; + if (72 < cx && 120 > cx) iBmp=IDB_RESULTSVGA; + if (120 <=cx) iBmp=IDB_RESULTSHIRESVGA; + + hBmpResults=LoadBitmap(hInst, MAKEINTRESOURCE(iBmp)); + + if (NULL==hBmpResults) + { + //On error, fail loading the DLL + OleDbgOut1(TEXT("FResultImageInitialize: Failed LoadBitmap.\r\n")); + return FALSE; + } + + OleDbgOut4(TEXT("FResultImageInitialize: Loaded hBmpResults\r\n")); + + //Now that we have the bitmap, calculate image dimensions + GetObject(hBmpResults, sizeof(BITMAP), &bm); + cxBmpResult=bm.bmWidth; + cyBmpResult=bm.bmHeight/CIMAGESY; + + + // Only register class if we're the first instance + if (hPrevInst) + fRegistered = TRUE; + else + { + // Static flag fRegistered guards against calling this function more + // than once in the same instance + + if (!fRegistered) + { + wc.lpfnWndProc =ResultImageWndProc; + wc.cbClsExtra =0; + wc.cbWndExtra =CBRESULTIMAGEWNDEXTRA; + wc.hInstance =hInst; + wc.hIcon =NULL; + wc.hCursor =LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground =NULL; + wc.lpszMenuName =NULL; + wc.lpszClassName =lpszClassName; + wc.style =CS_GLOBALCLASS | CS_VREDRAW | CS_HREDRAW; + + fRegistered = RegisterClass(&wc); + } + } + + return fRegistered; +} + + + + + +/* + * ResultImageUninitialize + * + * Purpose: + * Cleans up anything done in FResultImageInitialize, such as freeing + * the bitmaps. Call from WEP. + * + * Parameters: + * None + * + * Return Value: + * None + */ + +void ResultImageUninitialize(void) + { + if (NULL!=hBmpResults) + { + DeleteObject(hBmpResults); + } + + return; + } + + + + + + +/* + * ResultImageWndProc + * + * Purpose: + * Window Procedure for the ResultImage custom control. Only handles + * WM_CREATE, WM_PAINT, and private messages to manipulate the bitmap. + * + * Parameters: + * Standard + * + * Return Value: + * Standard + */ + +LONG CALLBACK EXPORT ResultImageWndProc(HWND hWnd, UINT iMsg + , WPARAM wParam, LPARAM lParam) + { + UINT iBmp; + PAINTSTRUCT ps; + HDC hDC; + + //Handle standard Windows messages. + switch (iMsg) + { + case WM_CREATE: + SetWindowWord(hWnd, RIWW_IMAGEINDEX, RESULTIMAGE_NONE); + return 0L; + + case WM_PAINT: + iBmp=GetWindowWord(hWnd, RIWW_IMAGEINDEX); + + hDC=BeginPaint(hWnd, &ps); + + if (RESULTIMAGE_NONE!=iBmp) + { + RECT rc; + UINT x, y; + HDC hDCDlg; + HBRUSH hBr; + LOGBRUSH lb; + HWND hDlg; + + /* + * Our job before using TransparentBlt is to figure out + * where to position the result image. We place it centered + * on this control, so get our rect's center and subtract + * half of the image dimensions. + */ + GetClientRect(hWnd, &rc); + x=(rc.right+rc.left-cxBmpResult)/2; + y=(rc.bottom+rc.top-cyBmpResult)/2; + + //Get the backgroup color the dialog is using. + hDlg=GetParent(hWnd); + hDCDlg=GetDC(hDlg); +#if defined( WIN32 ) + hBr = (HBRUSH)SendMessage(hDlg, + WM_CTLCOLORDLG, + (WPARAM)hDCDlg, + (LPARAM)hDlg); +#else + hBr = (HBRUSH)SendMessage(hDlg, + WM_CTLCOLOR, + (WPARAM)hDCDlg, + MAKELPARAM(hDlg, CTLCOLOR_DLG)); +#endif + ReleaseDC(hDlg, hDCDlg); + + GetObject(hBr, sizeof(LOGBRUSH), &lb); + SetBkColor(hDC, lb.lbColor); + + TransparentBlt(hDC, x, y, hBmpResults, 0, iBmp*cyBmpResult + , cxBmpResult, cyBmpResult, RGBTRANSPARENT); + } + + EndPaint(hWnd, &ps); + break; + + case RIM_IMAGESET: + //wParam contains the new index. + iBmp=GetWindowWord(hWnd, RIWW_IMAGEINDEX); + + //Validate the index before changing it and repainting + if (RESULTIMAGE_NONE==wParam || + ((RESULTIMAGE_MIN <= wParam) && (RESULTIMAGE_MAX >= wParam))) + { + SetWindowWord(hWnd, RIWW_IMAGEINDEX, (WORD)wParam); + InvalidateRect(hWnd, NULL, FALSE); + UpdateWindow(hWnd); + } + + //Return the previous index. + return iBmp; + + case RIM_IMAGEGET: + //Return the current index. + iBmp=GetWindowWord(hWnd, RIWW_IMAGEINDEX); + return (LONG)iBmp; + + default: + return DefWindowProc(hWnd, iMsg, wParam, lParam); + } + + return 0L; + } + + + + + + +/* + * TransparentBlt + * + * Purpose: + * Given a DC, a bitmap, and a color to assume as transparent in that + * bitmap, BitBlts the bitmap to the DC letting the existing background + * show in place of the transparent color. + * + * Parameters: + * hDC HDC on which to draw. + * x, y UINT location at which to draw the bitmap + * hBmp HBITMIP to draw from + * xOrg, yOrg UINT coordinates from which to draw the bitamp + * cx, cy UINT dimensions of the bitmap to Blt. + * cr COLORREF to consider as transparent. + * + * Return Value: + * None + */ + +void TransparentBlt(HDC hDC, UINT x, UINT y, HBITMAP hBmp, UINT xOrg, UINT yOrg + , UINT cx, UINT cy, COLORREF cr) + { + HDC hDCSrc, hDCMid, hMemDC; + HBITMAP hBmpMono, hBmpT; + HBRUSH hBr, hBrT; + COLORREF crBack, crText; + + if (NULL==hBmp) + return; + + //Get three intermediate DC's + hDCSrc=CreateCompatibleDC(hDC); + hDCMid=CreateCompatibleDC(hDC); + hMemDC=CreateCompatibleDC(hDC); + + SelectObject(hDCSrc, hBmp); + + //Create a monochrome bitmap for masking + hBmpMono=CreateCompatibleBitmap(hDCMid, cx, cy); + SelectObject(hDCMid, hBmpMono); + + //Create a middle bitmap + hBmpT=CreateCompatibleBitmap(hDC, cx, cy); + SelectObject(hMemDC, hBmpT); + + + //Create a monochrome mask where we have 0's in the image, 1's elsewhere. + crBack=SetBkColor(hDCSrc, cr); + BitBlt(hDCMid, 0, 0, cx, cy, hDCSrc, xOrg, yOrg, SRCCOPY); + SetBkColor(hDCSrc, crBack); + + //Put the unmodified image in the temporary bitmap + BitBlt(hMemDC, 0, 0, cx, cy, hDCSrc, xOrg, yOrg, SRCCOPY); + + //Create an select a brush of the background color + hBr=CreateSolidBrush(GetBkColor(hDC)); + hBrT=SelectObject(hMemDC, hBr); + + //Force conversion of the monochrome to stay black and white. + crText=SetTextColor(hMemDC, 0L); + crBack=SetBkColor(hMemDC, RGB(255, 255, 255)); + + /* + * Where the monochrome mask is 1, Blt the brush; where the mono mask + * is 0, leave the destination untouches. This results in painting + * around the image with the background brush. We do this first + * in the temporary bitmap, then put the whole thing to the screen. + */ + BitBlt(hMemDC, 0, 0, cx, cy, hDCMid, 0, 0, ROP_DSPDxax); + BitBlt(hDC, x, y, cx, cy, hMemDC, 0, 0, SRCCOPY); + + + SetTextColor(hMemDC, crText); + SetBkColor(hMemDC, crBack); + + SelectObject(hMemDC, hBrT); + DeleteObject(hBr); + + DeleteDC(hMemDC); + DeleteDC(hDCSrc); + DeleteDC(hDCMid); + DeleteObject(hBmpT); + DeleteObject(hBmpMono); + + return; + } diff --git a/private/oleutest/letest/ole2ui/resimage.h b/private/oleutest/letest/ole2ui/resimage.h new file mode 100644 index 000000000..31640be91 --- /dev/null +++ b/private/oleutest/letest/ole2ui/resimage.h @@ -0,0 +1,61 @@ +/* + * RESIMAGE.H + * + * Structures and definitions for the ResultImage control. + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + + +#ifndef _RESIMAGE_H_ +#define _RESIMAGE_H_ + + +/* + * Indices into the bitmaps to extract the right image. Each bitmap + * contains five images arranged vertically, so the offset to the correct + * image is (iImage*cy) + */ + +#define RESULTIMAGE_NONE 0xFFFF +#define RESULTIMAGE_PASTE 0 +#define RESULTIMAGE_EMBED 1 +#define RESULTIMAGE_EMBEDICON 2 +#define RESULTIMAGE_LINK 3 +#define RESULTIMAGE_LINKICON 4 +#define RESULTIMAGE_LINKTOLINK 5 +#define RESULTIMAGE_LINKTOLINKICON 6 + +#define RESULTIMAGE_MIN 0 +#define RESULTIMAGE_MAX 6 + + +//Total number of images in each bitmap. +#define CIMAGESY (RESULTIMAGE_MAX+1) + +//The color to use for transparancy (cyan) +#define RGBTRANSPARENT RGB(0, 255, 255) + + +//Function prototypes +BOOL FResultImageInitialize(HINSTANCE, HINSTANCE, LPTSTR); +void ResultImageUninitialize(void); +LONG CALLBACK EXPORT ResultImageWndProc(HWND, UINT, WPARAM, LPARAM); +void TransparentBlt(HDC, UINT, UINT, HBITMAP, UINT, UINT, UINT, UINT, COLORREF); + + +//Window extra bytes contain the bitmap index we deal with currently. +#define CBRESULTIMAGEWNDEXTRA sizeof(UINT) +#define RIWW_IMAGEINDEX 0 + + +//Control messages +#define RIM_IMAGESET (WM_USER+0) +#define RIM_IMAGEGET (WM_USER+1) + + +//Special ROP code for TransparentBlt. +#define ROP_DSPDxax 0x00E20746 + + +#endif //_RESIMAGE_H_ diff --git a/private/oleutest/letest/ole2ui/stdpal.c b/private/oleutest/letest/ole2ui/stdpal.c new file mode 100644 index 000000000..abe3e82ac --- /dev/null +++ b/private/oleutest/letest/ole2ui/stdpal.c @@ -0,0 +1,94 @@ +/*----------------------------------------------------------------------- +| stdpal.c +| +| Standard App Palette useful for OLE applications. v 1.01 +| +| NOTE: Palette MUST be created with OleStdCreateStandardPalette +| +| Copyright (c) 1992 - 1993 Microsoft Corporation. All rights reserved. +| +-----------------------------------------------------------------------*/ + +#ifndef PC_RESERVED +#ifndef INC_OLE2 + #define INC_OLE2 +#endif + +#undef UNICODE +#include +#include +#endif + +#include "stdpal.h" + +#define cpeAppPal 256 // number of colors in our apps palette +typedef struct + { + WORD wVersion; + WORD cpe; + PALETTEENTRY rgpe[cpeAppPal]; + } LOGPAL; + + +/*----------------------------------------------------------------------- +| OleStdCreateStandardPalette +| +| Creates the standard Apps palette. Create one of these for your +| app, and select/realize it into each DC. +| +| Arguments: +| void: +| +| Returns: +| +| Keywords: +-----------------------------------------------------------------------*/ +STDAPI_(HPALETTE) OleStdCreateStandardPalette(void) + { + HDC hdc; + HPALETTE hpal; + + hpal = (HPALETTE) NULL; + hdc = GetDC(NULL); + if (hdc != NULL && GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) + { + int cpeSysPal; + int cpeReserved; + + cpeSysPal = GetDeviceCaps(hdc, SIZEPALETTE); + cpeReserved = GetDeviceCaps(hdc, NUMRESERVED); + if (cpeSysPal > cpeReserved) + { + int cpeReserved2; + unsigned char FAR* lpb; + PALETTEENTRY FAR* ppe; + PALETTEENTRY FAR* ppeMac; + LOGPAL logpal; + + cpeReserved2 = cpeReserved/2; + + // Get the system palette entries at the beginning and end. + GetSystemPaletteEntries(hdc, 0, cpeReserved2, logpal.rgpe); + GetSystemPaletteEntries(hdc, cpeSysPal - cpeReserved2, cpeReserved2, + &logpal.rgpe[cpeAppPal-cpeReserved2]); + + logpal.cpe = cpeAppPal; + logpal.wVersion = 0x300; + + lpb = (BYTE FAR *) &palSVGA[10]; + ppe = (PALETTEENTRY FAR*)&logpal.rgpe[cpeReserved2]; + ppeMac = (PALETTEENTRY FAR*)&logpal.rgpe[cpeAppPal-cpeReserved2]; + while (ppe < ppeMac) + { + ppe->peFlags = PC_NOCOLLAPSE; + ppe->peRed = *lpb++; + ppe->peGreen = *lpb++; + ppe->peBlue = *lpb++; + ppe++; + } + hpal = CreatePalette((LOGPALETTE FAR *)&logpal); + } + } + ReleaseDC(NULL, hdc); + return hpal; + } diff --git a/private/oleutest/letest/ole2ui/stdpal.h b/private/oleutest/letest/ole2ui/stdpal.h new file mode 100644 index 000000000..59162ed78 --- /dev/null +++ b/private/oleutest/letest/ole2ui/stdpal.h @@ -0,0 +1,292 @@ +/*----------------------------------------------------------------------- +| stdpal.h +| +| Standard App Palette useful for OLE applications. v 1.01 +| +| #include this file in the same file as HpalCreateAppPalette +| +| NOTE: Palette MUST be created with HpalCreateAppPalette +| +| Copyright (c) 1992 - 1993 Microsoft Corporation. All rights reserved. +| +-----------------------------------------------------------------------*/ + +#include // needed for LPPRINTDLG +#include // needed for HKEY + +#ifdef WIN32 +#define _based(A) +#define _segname(A) +#endif + +#ifndef CSCONST +#ifdef FLAT +#define CSCONST(type) type const +#else +#define CSCONST(type) type _based(_segname("_CODE")) const +#endif +#endif + +CSCONST(unsigned char) palSVGA[256][3] = + { + // R G B + {0x00, 0x00, 0x00}, // 0 Sys Black gray 0 + {0x80, 0x00, 0x00}, // 1 Sys Dk Red + {0x00, 0x80, 0x00}, // 2 Sys Dk Green + {0x80, 0x80, 0x00}, // 3 Sys Dk Yellow + {0x00, 0x00, 0x80}, // 4 Sys Dk Blue + {0x80, 0x00, 0x80}, // 5 Sys Dk Violet + {0x00, 0x80, 0x80}, // 6 Sys Dk Cyan + {0xc0, 0xc0, 0xc0}, // 7 Sys Lt Grey gray 192 + {0xc0, 0xdc, 0xc0}, // 8 Sys 8 + {0xa6, 0xca, 0xf0}, // 9 Sys 9 (the first 10 are fixed by Windows) + + {0x80, 0x00, 0x00}, // 10 Sys Dk Red repeat + {0x00, 0x80, 0x00}, // 11 Sys Dk Green repeat + {0x80, 0x80, 0x00}, // 12 Sys Dk Yellow repeat + {0x00, 0x00, 0x80}, // 13 Sys Dk Blue repeat + {0x80, 0x00, 0x80}, // 14 Sys Dk Violet repeat + {0x00, 0x80, 0x80}, // 15 Sys Dk Cyan repeat + {0x80, 0x80, 0x80}, // 16 Sys Dk Grey repeat gray 128 + {0x80, 0x80, 0xff}, // 17 Excel Chart Fill 1 + {0x80, 0x20, 0x60}, // 18 Excel Chart Fill 2 + {0xff, 0xff, 0xc0}, // 19 Excel Chart Fill 3 + {0xa0, 0xe0, 0xe0}, // 20 Excel Chart Fill 4 + {0x60, 0x00, 0x80}, // 21 Excel Chart Fill 4 + {0xff, 0x80, 0x80}, // 22 Excel Chart Fill 6 + {0x00, 0x80, 0xc0}, // 23 Excel Chart Fill 7 + {0xc0, 0xc0, 0xff}, // 24 Excel Chart Fill 8 + {0x00, 0xcf, 0xff}, // 25 Excel clrt entry + {0x69, 0xff, 0xff}, // 26 Excel clrt entry + {0xe0, 0xff, 0xe0}, // 27 Excel clrt entry + {0xdd, 0x9c, 0xb3}, // 28 Excel clrt entry + {0xb3, 0x8f, 0xee}, // 29 Excel clrt entry + {0x2a, 0x6f, 0xf9}, // 30 Excel clrt entry + {0x3f, 0xb8, 0xcd}, // 31 Excel clrt entry + {0x48, 0x84, 0x36}, // 32 Excel clrt entry + {0x95, 0x8c, 0x41}, // 33 Excel clrt entry + {0x8e, 0x5e, 0x42}, // 34 Excel clrt entry + {0xa0, 0x62, 0x7a}, // 35 Excel clrt entry + {0x62, 0x4f, 0xac}, // 36 Excel clrt entry + {0x1d, 0x2f, 0xbe}, // 37 Excel clrt entry + {0x28, 0x66, 0x76}, // 38 Excel clrt entry + {0x00, 0x45, 0x00}, // 39 Excel clrt entry + {0x45, 0x3e, 0x01}, // 40 Excel clrt entry + {0x6a, 0x28, 0x13}, // 41 Excel clrt entry + {0x85, 0x39, 0x6a}, // 42 Excel clrt entry + {0x4a, 0x32, 0x85}, // 43 Excel clrt entry + {0x04, 0x04, 0x04}, // 44 gray 4 + {0x08, 0x08, 0x08}, // 45 gray 8 + {0x0c, 0x0c, 0x0c}, // 46 gray 12 + {0x11, 0x11, 0x11}, // 47 gray 17 + {0x16, 0x16, 0x16}, // 48 gray 22 + {0x1c, 0x1c, 0x1c}, // 49 gray 28 + {0x22, 0x22, 0x22}, // 50 gray 34 + {0x29, 0x29, 0x29}, // 51 gray 41 + {0x30, 0x30, 0x30}, // 52 gray 48 + {0x5f, 0x5f, 0x5f}, // 53 swapped so inversions look good gray 95 + {0x55, 0x55, 0x55}, // 54 swapped so inversions look good gray 85 + {0x4d, 0x4d, 0x4d}, // 55 swapped so inversions look good gray 77 + {0x42, 0x42, 0x42}, // 56 swapped so inversions look good gray 66 + {0x39, 0x39, 0x39}, // 57 swapped so inversions look good gray 57 + {0x00, 0x07, 0x00}, // 58 + {0x0d, 0x00, 0x00}, // 59 + {0xb7, 0x99, 0x81}, // 60 + {0x84, 0x99, 0xb4}, // 61 + {0xbd, 0xbd, 0x90}, // 62 + {0x7f, 0x7f, 0x60}, // 63 + {0x60, 0x60, 0x7f}, // 64 + {0x00, 0x0e, 0x00}, // 65 + {0x1b, 0x00, 0x00}, // 66 + {0x28, 0x00, 0x00}, // 67 + {0x08, 0x09, 0x2b}, // 68 + {0x00, 0x1d, 0x00}, // 69 + {0x39, 0x00, 0x00}, // 70 + {0x00, 0x00, 0x9b}, // 71 + {0x00, 0x25, 0x00}, // 72 + {0x49, 0x00, 0x00}, // 73 + {0x11, 0x11, 0x3b}, // 74 + {0x00, 0x2f, 0x00}, // 75 + {0x5d, 0x00, 0x00}, // 76 + {0x17, 0x17, 0x45}, // 77 + {0x00, 0x3a, 0x00}, // 78 + {0x49, 0x11, 0x11}, // 79 + {0x1c, 0x1c, 0x53}, // 80 + {0x00, 0x16, 0xff}, // 81 + {0x2b, 0x00, 0xff}, // 82 + {0x21, 0x21, 0x6c}, // 83 + {0x59, 0x14, 0x14}, // 84 + {0x00, 0x51, 0x00}, // 85 + {0x47, 0x1a, 0x6a}, // 86 + {0x19, 0x32, 0x67}, // 87 + {0x00, 0x61, 0x00}, // 88 + {0x00, 0x31, 0xff}, // 89 + {0x61, 0x00, 0xff}, // 90 + {0x53, 0x20, 0x7b}, // 91 + {0x16, 0x43, 0x67}, // 92 + {0x2e, 0x2e, 0xe2}, // 93 + {0x26, 0x59, 0x16}, // 94 + {0x51, 0x46, 0x04}, // 95 + {0x68, 0x2e, 0x49}, // 96 + {0x07, 0x52, 0x8f}, // 97 + {0x6a, 0x18, 0xb8}, // 98 + {0x90, 0x23, 0x15}, // 99 + {0x00, 0x53, 0xff}, // 100 + {0xa3, 0x00, 0xff}, // 101 + {0x6a, 0x4a, 0x12}, // 102 + {0x75, 0x33, 0x6c}, // 103 + {0x4a, 0x41, 0x9a}, // 104 + {0x37, 0x65, 0x0b}, // 105 + {0xa4, 0x2c, 0x15}, // 106 + {0x83, 0x1f, 0xb1}, // 107 + {0x4e, 0x2c, 0xff}, // 108 + {0x20, 0x51, 0xb6}, // 109 + {0x08, 0x64, 0x92}, // 110 + {0x6f, 0x56, 0x0b}, // 111 + {0x59, 0x43, 0xad}, // 112 + {0x36, 0x72, 0x12}, // 113 + {0xb0, 0x33, 0x17}, // 114 + {0x00, 0xa1, 0x00}, // 115 + {0x77, 0x5f, 0x1f}, // 116 + {0x89, 0x47, 0x71}, // 117 + {0xb0, 0x43, 0x1c}, // 118 + {0xb7, 0x2d, 0x7d}, // 119 + {0x00, 0x86, 0x95}, // 120 + {0x7a, 0x6e, 0x23}, // 121 + {0x26, 0x9f, 0x00}, // 122 + {0x73, 0xa9, 0x01}, // 123 + {0x00, 0x00, 0x00}, // 124 free 0 gray 0 + {0x00, 0x00, 0x00}, // 125 free 2 gray 0 + {0x00, 0x00, 0x00}, // 126 free 4 gray 0 + {0x00, 0x00, 0x00}, // 127 free 6 gray 0 + {0x00, 0x00, 0x00}, // 128 free 7 gray 0 + {0x00, 0x00, 0x00}, // 129 free 5 gray 0 + {0x00, 0x00, 0x00}, // 130 free 3 gray 0 + {0x00, 0x00, 0x00}, // 131 free 1 gray 0 + {0x00, 0xca, 0x00}, // 132 + {0xac, 0x5b, 0x01}, // 133 + {0x20, 0x1d, 0xc2}, // 134 + {0x94, 0x52, 0x70}, // 135 + {0x24, 0xaa, 0x4c}, // 136 + {0x0a, 0x94, 0x89}, // 137 + {0x36, 0x6e, 0x7b}, // 138 + {0x44, 0x75, 0x90}, // 139 + {0xff, 0x00, 0xa8}, // 140 + {0x00, 0x71, 0xff}, // 141 + {0xdf, 0x00, 0xff}, // 142 + {0x56, 0x91, 0x4a}, // 143 + {0x34, 0x48, 0xf8}, // 144 + {0xcc, 0x32, 0x82}, // 145 + {0xe4, 0x41, 0x70}, // 146 + {0x68, 0xca, 0x01}, // 147 + {0x36, 0xbc, 0x42}, // 148 + {0x00, 0x9a, 0xff}, // 149 + {0x96, 0x22, 0xb7}, // 150 + {0x85, 0x7d, 0x33}, // 151 + {0x25, 0xb7, 0x8c}, // 152 + {0x36, 0x5a, 0xed}, // 153 + {0x5c, 0xff, 0x00}, // 154 + {0xff, 0x48, 0x00}, // 155 + {0x22, 0x9b, 0xa2}, // 156 + {0x42, 0xcf, 0x4d}, // 157 + {0xc2, 0x58, 0x52}, // 158 + {0x20, 0xd3, 0x95}, // 159 + {0xa5, 0x24, 0xe0}, // 160 + {0x73, 0x56, 0xb5}, // 161 + {0xa9, 0xa9, 0x00}, // 162 + {0xd0, 0x6f, 0x3c}, // 163 + {0x67, 0x9f, 0x58}, // 164 + {0x89, 0xcf, 0x0b}, // 165 + {0xff, 0xac, 0x00}, // 166 + {0xa7, 0x2e, 0xfe}, // 167 + {0xe2, 0x59, 0x7f}, // 168 + {0x4c, 0xdc, 0x67}, // 169 + {0xff, 0x18, 0xff}, // 170 + {0x3a, 0x7d, 0xff}, // 171 + {0xb1, 0xd0, 0x18}, // 172 + {0xc7, 0xff, 0x00}, // 173 + {0xff, 0xe2, 0x00}, // 174 + {0xdf, 0x9a, 0x3d}, // 175 + {0x56, 0x81, 0x9f}, // 176 + {0xc6, 0x43, 0xba}, // 177 + {0xaf, 0x71, 0x8b}, // 178 + {0x38, 0xa2, 0xc9}, // 179 + {0xd1, 0x53, 0xce}, // 180 + {0xff, 0x9a, 0x65}, // 181 + {0x46, 0xca, 0xdb}, // 182 + {0xff, 0x4d, 0xff}, // 183 + {0xc8, 0xe9, 0x6a}, // 184 + {0x4c, 0xde, 0xe0}, // 185 + {0xff, 0x98, 0xff}, // 186 + {0xdf, 0xc0, 0x82}, // 187 + {0xe9, 0xec, 0xa5}, // 188 + {0xf5, 0xf6, 0xcd}, // 189 + {0xff, 0xd0, 0xff}, // 190 + {0xb1, 0xac, 0x5a}, // 191 + {0x63, 0x91, 0xae}, // 192 + {0x22, 0x4c, 0x65}, // 193 + {0x8d, 0x4e, 0x3f}, // 194 + {0x50, 0x70, 0x70}, // 195 + {0xd0, 0xff, 0xff}, // 196 + {0xff, 0xe7, 0xff}, // 197 + {0x69, 0x69, 0x69}, // 198 gray 105 + {0x77, 0x77, 0x77}, // 199 gray 119 + {0x86, 0x86, 0x86}, // 200 gray 134 + {0x96, 0x96, 0x96}, // 201 gray 150 + {0x9d, 0x9d, 0x9d}, // 202 gray 157 + {0xa4, 0xa4, 0xa4}, // 203 gray 164 + {0xb2, 0xb2, 0xb2}, // 204 gray 178 + {0xcb, 0xcb, 0xcb}, // 205 gray 203 + {0xd7, 0xd7, 0xd7}, // 206 gray 215 + {0xdd, 0xdd, 0xdd}, // 207 gray 221 + {0xe3, 0xe3, 0xe3}, // 208 gray 227 + {0xea, 0xea, 0xea}, // 209 gray 234 + {0xf1, 0xf1, 0xf1}, // 210 gray 241 + {0xf8, 0xf8, 0xf8}, // 211 gray 248 + {0xb2, 0xc1, 0x66}, // 212 + {0x80, 0xbf, 0x78}, // 213 + {0xc6, 0xf0, 0xf0}, // 214 + {0xb2, 0xa4, 0xff}, // 215 + {0xff, 0xb3, 0xff}, // 216 + {0xd1, 0x8e, 0xa3}, // 217 + {0xc3, 0xdc, 0x37}, // 218 + {0xa0, 0x9e, 0x54}, // 219 + {0x76, 0xae, 0x70}, // 220 + {0x78, 0x9e, 0xc1}, // 221 + {0x83, 0x64, 0xbf}, // 222 + {0xa4, 0x83, 0xd3}, // 223 + {0xd1, 0x3f, 0x32}, // 224 + {0xff, 0x7d, 0x00}, // 225 + {0x44, 0x78, 0x23}, // 226 + {0x24, 0x5f, 0x60}, // 227 + {0x0e, 0x0e, 0x2c}, // 228 + {0xbe, 0x00, 0x00}, // 229 + {0xff, 0x1f, 0x00}, // 230 + {0x31, 0x39, 0x00}, // 231 + {0xd9, 0x85, 0x3e}, // 232 + {0x02, 0x77, 0x85}, // 233 + {0xb0, 0xd8, 0x81}, // 234 + {0x56, 0x21, 0x1d}, // 235 + {0x00, 0x00, 0x30}, // 236 + {0x88, 0xc8, 0xb3}, // 237 + {0xa0, 0x79, 0x00}, // 238 + {0xc0, 0xc0, 0xc0}, // 239 Sys Dk Grey repeat inversion gray 192 + {0xea, 0x70, 0x81}, // 240 + {0x51, 0xf1, 0x69}, // 241 + {0xff, 0xff, 0x80}, // 242 + {0x91, 0x74, 0xcd}, // 243 + {0xff, 0x7c, 0xff}, // 244 + {0xa2, 0xff, 0xff}, // 245 + + {0xff, 0xfb, 0xf0}, // 246 Sys Reserved + {0xa0, 0xa0, 0xa4}, // 247 Sys Reserved + {0x80, 0x80, 0x80}, // 248 Sys Lt Gray gray 128 + {0xff, 0x00, 0x00}, // 249 Sys Red + {0x00, 0xff, 0x00}, // 250 Sys Green + {0xff, 0xff, 0x00}, // 251 Sys Yellow + {0x00, 0x00, 0xff}, // 252 Sys Blue + {0xff, 0x00, 0xff}, // 253 Sys Violet + {0x00, 0xff, 0xff}, // 254 Sys Cyan + {0xff, 0xff, 0xff} // 255 Sys White gray 255 + }; + diff --git a/private/oleutest/letest/ole2ui/strings.rc b/private/oleutest/letest/ole2ui/strings.rc new file mode 100644 index 000000000..f3f8c415a --- /dev/null +++ b/private/oleutest/letest/ole2ui/strings.rc @@ -0,0 +1,124 @@ +/* + * STRINGS.RC + * + * strings for the OLE 2.0 UI Support Library. + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + + +#include "ole2ui.h" + + +//Stringtable common for all dialogs. +STRINGTABLE + BEGIN + IDS_FILTERS, "All Files (*.*)|*.*|" + IDS_ICONFILTERS, "Icon Files|*.exe;*.dll;*.ico|Programs (*.exe)|*.exe|Libraries (*.dll)|Icons (*.ico)|All Files (*.*)|*.*|" + END + +// browse dialog +STRINGTABLE + BEGIN + IDS_BROWSE "Browse" + END + + +//Insert Object stringtable. +STRINGTABLE + BEGIN + IDS_IORESULTNEW, "Inserts a new %s object into your document." + IDS_IORESULTNEWICON, "Inserts a new %s object into your document. It will be displayed as an icon." + IDS_IORESULTFROMFILE1, "Inserts the contents of the file as an object into your document so that you may activate it using the " + IDS_IORESULTFROMFILE2, "application which created it." + IDS_IORESULTFROMFILEICON2, "application which created it. It will be displayed as an icon." + IDS_IORESULTLINKFILE1, "Inserts a picture of the file contents into your document. The picture will be linked to " + IDS_IORESULTLINKFILE2, "the file so that changes to the file will be reflected in your document." + IDS_IORESULTLINKFILEICON1, "Inserts an icon into your document which represents the file. The icon will be linked to " + IDS_IORESULTLINKFILEICON2, "the file so that changes to the file will be reflected in your document." + END + +//Change Icon stringtable +STRINGTABLE + BEGIN + IDS_CINOICONSINFILE, "There are no icons in %s." + IDS_CIINVALIDFILE, "File %s does not exist." + IDS_CIFILEACCESS, "Unable to open file %s. Access denied." + IDS_CIFILESHARE, "Unable to open file %s. Sharing violation." + IDS_CIFILEOPENFAIL, "Unable to open file %s. General failure." + END + +// Convert stringtable. +STRINGTABLE + BEGIN + IDS_CVRESULTCONVERTLINK, "A linked object must be converted at the source." + IDS_CVRESULTCONVERTTO, "Permanently changes the selected %s object to a %s object." + IDS_CVRESULTNOCHANGE, "The selected %s object will not be converted." + IDS_CVRESULTDISPLAYASICON, " It will be displayed as an icon." + IDS_CVRESULTACTIVATEAS, "Every %s object will be activated as a %s object" + IDS_CVRESULTACTIVATEDIFF, ", but it will not be converted." + END + +//Paste Special stringtable +STRINGTABLE + BEGIN + IDS_PSPASTEDATA, "Inserts the contents of the Clipboard into your document as %s." + IDS_PSPASTEOBJECT, "Inserts the contents of the Clipboard into your document so that you may activate it using %s." + IDS_PSPASTEOBJECTASICON, "Inserts the contents of the Clipboard into your document so that you may activate it using %s. It will be displayed as an icon." + IDS_PSPASTELINKDATA, "Inserts the contents of the Clipboard into your document as %s. Paste Link creates a link to the source file so that changes to the source file will be reflected in your document." + IDS_PSPASTELINKOBJECT, "Inserts a picture of the Clipboard contents into your document. Paste Link creates a link to the source file so that changes to the source file will be reflected in your document." + IDS_PSPASTELINKOBJECTASICON, "Inserts an icon into your document which represents the Clipboard contents. Paste Link creates a link to the source file so that changes to the source file will be reflected in your document." + IDS_PSNONOLE, "Inserts the contents of the Clipboard into your document." + IDS_PSUNKNOWNTYPE, "Unknown Type" + IDS_PSUNKNOWNSRC, "Unknown Source" + IDS_PSUNKNOWNAPP, "the application which created it" + END + +// Busy/Blocked dialog stringtable +STRINGTABLE + BEGIN + IDS_BZRESULTTEXTBUSY "This action cannot be completed because the %s application (%s) is busy. Choose ""Switch To"" to activate %s and correct the problem." + IDS_BZRESULTTEXTNOTRESPONDING "This action cannot be completed because the %s application (%s) is not responding. Choose ""Switch To"" to activate %s and correct the problem." + END + +// OLESTD stringtable +STRINGTABLE + BEGIN + IDS_OLESTDNOCREATEFILE, "Could not create file!" + IDS_OLESTDNOOPENFILE, "Could not open file!" + IDS_OLESTDDISKFULL, "Disk full--unable to complete save operation" + END + +// OLE2UI stringtable +STRINGTABLE + BEGIN + IDS_OLE2UIEDITNOOBJCMD, "&Object" + IDS_OLE2UIEDITLINKCMD_1VERB, "0%s Linked %s &Object" + IDS_OLE2UIEDITOBJECTCMD_1VERB, "0%s %s &Object" + IDS_OLE2UIEDITLINKCMD_NVERB, "Linked %s &Object" + IDS_OLE2UIEDITOBJECTCMD_NVERB, "%s &Object" + IDS_OLE2UIUNKNOWN, "Unknown" + IDS_OLE2UILINK, "Link" + IDS_OLE2UIOBJECT, "Object" + IDS_OLE2UIEDIT, "&Edit" + IDS_OLE2UICONVERT, "&Convert..." + IDS_DEFICONLABEL, "Document" + IDS_OLE2UIPASTELINKEDTYPE, "Linked %s" + END + +// LINKS stringtable +STRINGTABLE + BEGIN + IDS_LINK_AUTO "Automatic" + IDS_LINK_MANUAL "Manual" + IDS_LINK_UNKNOWN "Unavail" + IDS_LINKS "Links" + IDS_FAILED "Operation failed!" + IDS_CHANGESOURCE "Change Source" + IDS_INVALIDSOURCE "Invalid Source : Do you want to correct it?" + IDS_CHANGEADDITIONALLINKS "The selected link has been changed.\nThis document contains additional links to\n%s.\n\nChange additional links?" + IDS_ERR_GETLINKSOURCE "Fail to get source of the link!" + IDS_ERR_GETLINKUPDATEOPTIONS "Fail to get update option of the link!" + IDS_ERR_ADDSTRING "Fail to add item to ListBox!" + IDS_CLOSE "Close" + END diff --git a/private/oleutest/letest/ole2ui/suminfo.cpp b/private/oleutest/letest/ole2ui/suminfo.cpp new file mode 100644 index 000000000..528fe2540 --- /dev/null +++ b/private/oleutest/letest/ole2ui/suminfo.cpp @@ -0,0 +1,1371 @@ +/************************************************************************* +** +** OLE 2.0 Property Set Utilities +** +** suminfo.cpp +** +** This file contains functions that are useful for the manipulation +** of OLE 2.0 Property Sets particularly to manage the Summary Info +** property set. +** +** (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved +** +*************************************************************************/ + +// Note: this file is designed to be stand-alone; it includes a +// carefully chosen, minimal set of headers. +// +// For conditional compilation we use the ole2 conventions, +// _MAC = mac +// WIN32 = Win32 (NT really) +// = defaults to Win16 + +// REVIEW: the following needs to modified to handle _MAC +#define STRICT +#ifndef INC_OLE2 + #define INC_OLE2 +#endif + +#include +#include +#include +#include "ole2ui.h" + +OLEDBGDATA + +/* A LPSUMINFO variable is a pointer to an instance of an abstract data +** type. There can be an arbitrary number of SummaryInfo streams open +** simultaneously (subject to available memory); each must have its +** own LPSUMINFO instance. Each LPSUMINFO instance must +** be initialized prior to use by calling Init and freed after its +** last use by calling Free. The param argument to Init is reserved +** for future expansion and should be zero initially. Once a LPSUMINFO +** instance is allocated (by Init), the user can call the Set +** procedures to initialize fields. A copy of the arguments is made +** in every case except SetThumbnail where control of the storage +** occupied by the METAFILEPICT is merely transferred. When the +** Free routine is called, all storage will be deallocated including +** that of the thumbnail. The arguments to SetThumbNail and the +** return values from GetThumbNail correspond to the OLE2.0 spec. +** Note that on input, the thumbnail is read on demand but all the +** other properties are pre-loaded. The thumbnail is manipulated as +** a windows handle to a METAFILEPICT structure, which in turn +** contains a handle to the METAFILE. The transferClip argument on +** GetThumbNail, when set to true, transfers responsibility for +** storage management of the thumbnail to the caller; that is, after +** Free has been called, the handle is still valid. Clear can be +** used to free storage for all the properties but then you must +** call Read to load them again. All the code is based on FAR +** pointers. +** CoInitialize MUST be called PRIOR to calling OleStdInitSummaryInfo. +** Memory is allocated using the currently active IMalloc* +** allocator (as is returned by call CoGetMalloc(MEMCTX_TASK) ). +** +** Common scenarios: +** Read SummaryInfo +** ---------------- +** OleStdInitSummaryInfo() +** OleStdReadSummaryInfo() +** . . . . . +** call different Get routines +** . . . . . +** OleStdFreeSummaryInfo() +** +** Create SummaryInfo +** ------------------ +** OleStdInitSummaryInfo() +** call different Set routines +** OleStdWriteSummaryInfo() +** OleStdFreeSummaryInfo() +** +** Update SummaryInfo +** ------------------ +** OleStdInitSummaryInfo() +** OleStdReadSummaryInfo() +** OleStdGetThumbNailProperty(necessary only if no SetThumb) +** call different Set routines +** OleStdWriteSummaryInfo() +** OleStdFreeSummaryInfo() +*/ + +#ifdef WIN32 +#define CHAR TCHAR +#else +#define CHAR unsigned char +#endif +#define fTrue 1 +#define fFalse 0 +#define BYTE unsigned char +#define WORD unsigned short +#define DWORD unsigned long +#define LPVOID void FAR * +#define uchar unsigned char +#define ulong unsigned long +#define BOOL unsigned char +#define BF unsigned int + +#include "suminfo.h" +#include "wn_dos.h" + +#if defined( _DEBUG ) + #ifndef NOASSERT + // following is from compobj.dll (ole2) + #ifdef UNICODE + #define ASSERT(x) (!(x) ? FnAssert(TEXT(#x), NULL, \ + TEXT(__FILE__), __LINE__) : 0) + #else + #define ASSERT(x) (!(x) ? \ + { \ + WCHAR wsz[255]; \ + wcscpy(wsz, (#x)); \ + FnAssert(wsz, NULL, TEXT(__FILE__), __LINE__) \ + } \ + : 0) + #endif + #else + #define ASSERT(x) + #endif +#else +#define ASSERT(x) +#endif + + +typedef struct _RSUMINFO + { + WORD byteOrder; + WORD formatVersion; + WORD getOSVersion; + WORD osVersion; + CLSID classId; //from compobj.h + DWORD cSections; + PROPSETLIST rgPropSet[1/*cSections*/]; //one section in standard summary info + STANDARDSECINMEM section; + ULONG fileOffset; //offset for thumbnail to support demand read + } RSUMINFO; + +typedef RSUMINFO FAR * LPRSI; + + typedef union _foo{ + ULARGE_INTEGER uli; + struct { + DWORD dw; + DWORD dwh; + }; + struct { + WORD w0; + WORD w1; + WORD w2; + WORD w3; + }; + } Foo; + + + +/* MemAlloc +** --------- +** allocate memory using the currently active IMalloc* allocator +*/ +static LPVOID MemAlloc(ULONG ulSize) +{ + LPVOID pout; + LPMALLOC pmalloc; + + if (CoGetMalloc(MEMCTX_TASK, &pmalloc) != NOERROR) { + OleDbgAssert(pmalloc); + return NULL; + } + + pout = (LPVOID)pmalloc->Alloc(ulSize); + + if (pmalloc != NULL) { + ULONG refs = pmalloc->Release(); + } + + return pout; +} + + +/* MemFree +** ------- +** free memory using the currently active IMalloc* allocator +*/ +static void MemFree(LPVOID pmem) +{ + LPMALLOC pmalloc; + + if (pmem == NULL) + return; + + if (CoGetMalloc(MEMCTX_TASK, &pmalloc) != NOERROR) { + OleDbgAssert(pmalloc); + return; + } + + pmalloc->Free(pmem); + + if (pmalloc != NULL) { + ULONG refs = pmalloc->Release(); + } +} + +// Replace the first argument with the product of itself and the multiplier +static void ulargeMultiply(ULARGE_INTEGER FAR *ul, USHORT m) +{ + Foo out, in; + in.uli = *ul; + out.dw = (ULONG)m * in.w0; in.w0 = out.w0; + out.dw = (ULONG)m * in.w1 + out.w1; in.w1 = out.w0; + out.dw = (ULONG)m * in.w2 + out.w1; in.w2 = out.w0; + out.dw = (ULONG)m * in.w3 + out.w1; in.w3 = out.w0; + *ul = in.uli; +} + +// Replace the first argument with the product of itself and the multiplier +static void ulargeDivide(ULARGE_INTEGER FAR *ul, USHORT m) +{ + Foo out, in; + DWORD i; + in.uli = *ul; + out.dwh = in.dwh/(ULONG)m; + i = in.dwh%(ULONG)m; + in.w2 = in.w1; + in.w3 = (WORD)i; + out.w1 = (WORD)(in.dwh/(ULONG)m); + in.w1 = (WORD)(in.dwh%(ULONG)m); + out.w0 = (WORD)(in.dw/(ULONG)m); + *ul = out.uli; +} + + +static void setStandard(LPRSI lprsi) +{ + int i; + lprsi->cSections = 1; + SetSumInfFMTID(&lprsi->rgPropSet[0].formatID); + _fmemcpy(&lprsi->classId, &lprsi->rgPropSet[0].formatID, sizeof(FMTID)); + lprsi->rgPropSet[0].byteOffset = cbNewSummaryInfo(1); + for (i=0; isection.rgPropId[i].propertyID = PID_TITLE+i; + lprsi->section.cProperties = cPID_STANDARD; //always; do null test to check validity +} + +extern "C" { + +/************************************************************************* +** +** OleStdInitSummaryInfo +** +** Purpose: +** Initialize a Summary Info structure. +** +** Parameters: +** int reserved - reserverd for future use. must be 0. +** +** Return Value: +** LPSUMINFO +** +** Comments: +** CoInitialize MUST be called PRIOR to calling OleStdInitSummaryInfo. +** Memory is allocated using the currently active IMalloc* +** allocator (as is returned by call CoGetMalloc(MEMCTX_TASK) ). +** Each LPSUMINFO instance must be initialized prior to use by +** calling OleStdInitSummaryInfo. Once a LPSUMINFO instance is allocated +** (by OleStdInitSummaryInfo), the user can call the Set procedures to +** initialize fields. +*************************************************************************/ + +STDAPI_(LPSUMINFO) OleStdInitSummaryInfo(int reserved) +{ + LPRSI lprsi; + + if ((lprsi = (LPRSI)MemAlloc(sizeof(RSUMINFO))) != NULL) + { + ClearSumInf(lprsi, sizeof(RSUMINFO)); + } else return NULL; + + setStandard(lprsi); + return (LPSUMINFO)lprsi; +} + + +/************************************************************************* +** +** OleStdFreeSummaryInfo +** +** Purpose: +** Free a Summary Info structure. +** +** Parameters: +** LPSUMINFO FAR *lp - pointer to open Summary Info struct +** +** Return Value: +** void +** +** Comments: +** Memory is freed using the currently active IMalloc* +** allocator (as is returned by call CoGetMalloc(MEMCTX_TASK) ). +** Every LPSUMINFO struct must be freed after its last use. +** When the OleStdFreeSummaryInfo routine is called, all storage will be +** deallocated including that of the thumbnail (unless ownership of +** the thumbnail has been transfered to the caller -- see +** description of transferClip in GetThumbnail API). +** +*************************************************************************/ + +STDAPI_(void) OleStdFreeSummaryInfo(LPSUMINFO FAR *lplp) +{ + if (lplp==NULL||*lplp==NULL) return; + OleStdClearSummaryInfo(*lplp); + MemFree(*lplp); + *lplp = NULL; +} + + +/************************************************************************* +** +** OleStdClearSummaryInfo +** +** Purpose: +** Free storage (memory) for all the properties of the LPSUMINFO. +** +** Parameters: +** LPSUMINFO FAR *lp - pointer to open Summary Info struct +** +** Return Value: +** void +** +** Comments: +** After calling OleStdClearSummaryInfo you must call OleStdReadSummaryInfo to +** load them again. +** +*************************************************************************/ + +STDAPI_(void) OleStdClearSummaryInfo(LPSUMINFO lp) +{ + OleStdSetStringProperty(lp, PID_TITLE, NULL); + OleStdSetStringProperty(lp, PID_SUBJECT, NULL); + OleStdSetStringProperty(lp, PID_AUTHOR, NULL); + OleStdSetStringProperty(lp, PID_KEYWORDS, NULL); + OleStdSetStringProperty(lp, PID_COMMENTS, NULL); + OleStdSetStringProperty(lp, PID_TEMPLATE, NULL); + OleStdSetStringProperty(lp, PID_REVNUMBER, NULL); + OleStdSetStringProperty(lp, PID_APPNAME, NULL); + OleStdSetThumbNailProperty(NULL, lp, VT_CF_EMPTY, 0, NULL, NULL, 0); + ClearSumInf((LPRSI)lp, sizeof(RSUMINFO)); +} + + +/************************************************************************* +** +** OleStdReadSummaryInfo +** +** Purpose: +** Read all Summary Info properties into memory (except thumbnail +** which is demand loaded). +** +** Parameters: +** LPSTREAM lps - open SummaryInfo IStream* +** LPSUMINFO FAR *lp - pointer to open Summary Info struct +** +** Return Value: +** int - 1 for success +** - 0 if error occurs +** Comments: +** +*************************************************************************/ + +STDAPI_(int) OleStdReadSummaryInfo(LPSTREAM lpStream, LPSUMINFO lp) +{ + STANDARDSECINMEM FAR *lpSSIM=(STANDARDSECINMEM FAR*)&((LPRSI)lp)->section; + LPRSI lpSumInfo = (LPRSI)lp; + SCODE sc; + ULONG cbRead,i,sectionOffset; + LARGE_INTEGER a; + ULARGE_INTEGER b; + int j,k,l; + union { + RSUMINFO rsi; + STDZ stdz; + }; + OleStdClearSummaryInfo(lp); + LISet32(a, 0); + sc = GetScode(lpStream->Seek(a, STREAM_SEEK_SET, &b)); + if (FAILED(sc)) goto fail; + sectionOffset = cbNewSummaryInfo(1); + sc = GetScode(lpStream->Read(&rsi, sectionOffset, &cbRead)); + if (FAILED(sc)||cbRead0) { + if (FEqSumInfFMTID(&rsi.rgPropSet[0].formatID)) { + sectionOffset = rsi.rgPropSet[0].byteOffset; + break; + } else { + sc = GetScode(lpStream->Read(&rsi.rgPropSet[0].formatID, sizeof(PROPSETLIST), &cbRead)); + if (FAILED(sc)||cbRead!=sizeof(PROPSETLIST)) goto fail; + } + if (j<=0) goto fail; + } + + LISet32(a, sectionOffset); + sc = GetScode(lpStream->Seek(a, STREAM_SEEK_SET, &b)); + if (FAILED(sc)) goto fail; + sc = GetScode(lpStream->Read(&rsi.section, cbNewSection(1), &cbRead)); + if (FAILED(sc)||cbRead!=cbNewSection(1)) goto fail; + i = rsi.section.cBytes+sectionOffset; + j = (int)rsi.section.cProperties; + if (j>cPID_STANDARD) goto fail; + k = 0; + while (j-->0) { + k++; + switch (l=(int)rsi.section.rgPropId[0].propertyID) { + case PID_PAGECOUNT: + case PID_WORDCOUNT: + case PID_CHARCOUNT: + case PID_SECURITY: + if (l==PID_SECURITY) l=3; else l-=PID_PAGECOUNT; + cbRead = sectionOffset+rsi.section.rgPropId[0].byteOffset; + if (cbRead>=i) goto fail; + LISet32(a, cbRead); + sc = GetScode(lpStream->Seek(a, STREAM_SEEK_SET, &b)); + if (FAILED(sc)) goto fail; + sc = GetScode(lpStream->Read(&lpSSIM->rgInts[l], sizeof(INTS), &cbRead)); + if (FAILED(sc)||cbRead!=sizeof(INTS)) goto fail; + if (lpSSIM->rgInts[l].vtType==VT_EMPTY) break; + if (lpSSIM->rgInts[l].vtType!=VT_I4) goto fail; + break; + case PID_EDITTIME: + case PID_LASTPRINTED: + case PID_CREATE_DTM_RO: + case PID_LASTSAVE_DTM: + l-=PID_EDITTIME; + cbRead = sectionOffset+rsi.section.rgPropId[0].byteOffset; + if (cbRead>=i) goto fail; + LISet32(a, cbRead); + sc = GetScode(lpStream->Seek(a, STREAM_SEEK_SET, &b)); + if (FAILED(sc)) goto fail; + sc = GetScode(lpStream->Read(&lpSSIM->rgTime[l], sizeof(TIME), &cbRead)); + if (FAILED(sc)||cbRead!=sizeof(TIME)) goto fail; + if (lpSSIM->rgTime[l].vtType==VT_EMPTY) break; + if (lpSSIM->rgTime[l].vtType!=VT_FILETIME) goto fail; + break; + case PID_TITLE: + case PID_SUBJECT: + case PID_AUTHOR: + case PID_KEYWORDS: + case PID_COMMENTS: + case PID_TEMPLATE: + case PID_LASTAUTHOR: + case PID_REVNUMBER: + case PID_APPNAME: + cbRead = sectionOffset+rsi.section.rgPropId[0].byteOffset; + if (cbRead>=i) goto fail; + LISet32(a, cbRead); + sc = GetScode(lpStream->Seek(a, STREAM_SEEK_SET, &b)); + if (FAILED(sc)) goto fail; + sc = GetScode(lpStream->Read(&stdz, sizeof(STDZ), &cbRead)); + if (FAILED(sc)||cbReadWORDMAX) goto fail; + stdz.rgchars[(int)stdz.vtByteCount-1] = TEXT('\0'); + OleStdSetStringProperty(lp, (DWORD)l, (LPTSTR)&stdz.rgchars[0]); + break; + case PID_THUMBNAIL: + cbRead = sectionOffset+rsi.section.rgPropId[0].byteOffset; + if (cbRead>=i) goto fail; + LISet32(a, cbRead); + sc = GetScode(lpStream->Seek(a, STREAM_SEEK_SET, &b)); + if (FAILED(sc)) goto fail; + lpSumInfo->fileOffset = cbRead+sizeof(DWORD)*3; + sc = GetScode(lpStream->Read(&lpSSIM->thumb, sizeof(DWORD)*4, &cbRead)); + if (FAILED(sc)||cbRead!=sizeof(DWORD)*4) { + lpSSIM->thumb.vtType = VT_EMPTY; + goto fail; + } + if (lpSSIM->thumb.vtType == VT_EMPTY) { + lpSSIM->thumb.cBytes = 0; + break; + } + if (lpSSIM->thumb.vtType != VT_CF) { + lpSSIM->thumb.vtType = VT_EMPTY; + goto fail; + } + lpSSIM->thumb.cBytes -= sizeof(DWORD); //for selector + if (lpSSIM->thumb.selector==VT_CF_WIN||lpSSIM->thumb.selector==VT_CF_MAC) { + lpSumInfo->fileOffset += sizeof(DWORD); + lpSSIM->thumb.cBytes -= sizeof(DWORD); //for format val + } + break; + default: ; + } + if (j<=0) + { + // We should fail if the document is password-protected. + if(OleStdGetSecurityProperty(lp)==fSecurityPassworded) + goto fail; + return 1; + } + LISet32(a, sectionOffset+sizeof(DWORD)*2+k*sizeof(PROPIDLIST)); + sc = GetScode(lpStream->Seek(a, STREAM_SEEK_SET, &b)); + if (FAILED(sc)) goto fail; + sc = GetScode(lpStream->Read(&rsi.section.rgPropId[0], sizeof(PROPIDLIST), &cbRead)); + if (FAILED(sc)||cbRead!=sizeof(PROPIDLIST)) goto fail; + } + +fail: + OleStdClearSummaryInfo(lpSumInfo); + + return 0; +} + + +/************************************************************************* +** +** OleStdWriteSummaryInfo +** +** Purpose: +** Write all Summary Info properties to a IStream* +** +** Parameters: +** LPSTREAM lps - open SummaryInfo IStream* +** LPSUMINFO FAR *lp - pointer to open Summary Info struct +** +** Return Value: +** int - 1 for success +** - 0 if error occurs +** Comments: +** +*************************************************************************/ + +STDAPI_(int) OleStdWriteSummaryInfo(LPSTREAM lpStream, LPSUMINFO lp) +{ + + + STANDARDSECINMEM FAR *lpSSIM=(STANDARDSECINMEM FAR*)&((LPRSI)lp)->section; + // REVIEW: localization issues for propert sets + // do we need to include a code page and dictionary? + + LPRSI lpSumInfo = (LPRSI)lp; + SCODE sc; + ULONG cbWritten; + ULONG cBytes, oBytes, k,l,m,n; + LARGE_INTEGER a; + ULARGE_INTEGER b; + CHAR FAR *lps; + LPMETAFILEPICT lpmfp; + int i,j,s; + + setStandard(lpSumInfo); + oBytes = cbNewSection(cPID_STANDARD); //offsets are relative to the section + cBytes = cbNewSection(cPID_STANDARD)+(sizeof(TIME)*MAXTIME)+(sizeof(INTS)*MAXINTS); + + lpSSIM->rgPropId[PID_EDITTIME-2].byteOffset = oBytes; + lpSSIM->rgPropId[PID_LASTPRINTED-2].byteOffset = oBytes+sizeof(TIME); + lpSSIM->rgPropId[PID_CREATE_DTM_RO-2].byteOffset = oBytes+sizeof(TIME)*2; + lpSSIM->rgPropId[PID_LASTSAVE_DTM-2].byteOffset = oBytes+sizeof(TIME)*3; + + lpSSIM->rgPropId[PID_PAGECOUNT-2].byteOffset = oBytes+(sizeof(TIME)*MAXTIME); + lpSSIM->rgPropId[PID_WORDCOUNT-2].byteOffset = oBytes+(sizeof(TIME)*MAXTIME+sizeof(INTS)); + lpSSIM->rgPropId[PID_CHARCOUNT-2].byteOffset = oBytes+(sizeof(TIME)*MAXTIME+sizeof(INTS)*2); + lpSSIM->rgPropId[PID_SECURITY-2].byteOffset = oBytes+(sizeof(TIME)*MAXTIME+sizeof(INTS)*3); + oBytes += sizeof(TIME)*MAXTIME + sizeof(INTS)*MAXINTS; + + lpSSIM->rgPropId[PID_THUMBNAIL-2].byteOffset = oBytes; + l = 0; + if (lpSSIM->thumb.vtType==VT_EMPTY) k = sizeof(DWORD); + else { + l = ((lpSSIM->thumb.cBytes+4-1)>>2)<<2; + if (lpSSIM->thumb.selector==VT_CF_BYTES) k = sizeof(DWORD)*3; + else if (lpSSIM->thumb.selector==VT_CF_FMTID) {k = sizeof(DWORD)*3; l += sizeof(FMTID); } + else if (lpSSIM->thumb.selector==VT_CF_NAME) {k = sizeof(DWORD)*3; l += (((*lpSSIM->thumb.lpstzName+1+3)>>2)<<2);} + else k = sizeof(DWORD)*4; + } + cBytes += k+l; + oBytes += k+l; + + for (i=0; irglpsz[i]!=NULL) { + j = lpSSIM->rglpsz[i]->VTCB+1/*null*/; + lpSSIM->rglpsz[i]->vtByteCount = j; + j = (((j+4-1)>>2)<<2)+sizeof(DWORD); + cBytes += j; + } + if (i!=MAXSTDZ-1) lpSSIM->rgPropId[i].byteOffset = oBytes; + else lpSSIM->rgPropId[PID_APPNAME-2].byteOffset = oBytes; + oBytes += j+sizeof(DWORD); + cBytes += sizeof(DWORD); //type + } + lpSSIM->cBytes = cBytes; + + + LISet32(a, 0); + sc = GetScode(lpStream->Seek(a, STREAM_SEEK_SET, &b)); + if (FAILED(sc)) return 0; + sc = GetScode(lpStream->Write(lpSumInfo, cbNewSummaryInfo(1), &cbWritten)); + if (FAILED(sc)||cbWritten!=cbNewSummaryInfo(1)) return 0; + sc = GetScode(lpStream->Write(lpSSIM, cbNewSection(cPID_STANDARD)+sizeof(TIME)*MAXTIME+sizeof(INTS)*MAXINTS, &cbWritten)); + if (FAILED(sc)||cbWritten!=cbNewSection(cPID_STANDARD)+sizeof(TIME)*MAXTIME+sizeof(INTS)*MAXINTS) return 0; + + m = lpSSIM->thumb.cBytes; + if (lpSSIM->thumb.lpstzName!=NULL) s = *lpSSIM->thumb.lpstzName; + else s = 0; + if (m!=0) { + lpSSIM->thumb.cBytes = (k-sizeof(DWORD)*2)+ + (((lpSSIM->thumb.cBytes+4-1)>>2)<<2)+(((s+4-1)>>2)<<2); + n = lpSSIM->thumb.selector; + lps = lpSSIM->thumb.lpByte; + OleDbgAssert(lps!=NULL); //maybe a GetThumbNail here + OleDbgAssert(n!=VT_CF_NAME); + if (n==VT_CF_WIN) { //bytes are in global memory + lpmfp = (LPMETAFILEPICT)GlobalLock((HANDLE)(DWORD)lps); + if (lpmfp==NULL) goto fail; + lps = (CHAR FAR*)GlobalLock(lpmfp->hMF); + } + if (n==VT_CF_NAME) lpSSIM->thumb.selector = *lpSSIM->thumb.lpstzName+1/*null*/; + } + sc = GetScode(lpStream->Write(&lpSSIM->thumb, k, &cbWritten)); + if (FAILED(sc)||cbWritten!=k) goto fail; + if (s!=0) { + k = ((s+1+4-1)>>2)<<2; + sc = GetScode(lpStream->Write(lpSSIM->thumb.lpstzName+1, k, &cbWritten)); + if (FAILED(sc)||cbWritten!=k) goto fail; + } + if (m!=0) { + k = ((m+3)>>2)<<2; + if (n==VT_CF_WIN||VT_CF_NAME) { //bytes are in global memory + sc = GetScode(lpStream->Write(lpmfp, sizeof(METAFILEPICT), &cbWritten)); + k -= sizeof(METAFILEPICT); + } + sc = GetScode(lpStream->Write(lps, k, &cbWritten)); + if (FAILED(sc)||cbWritten!=k) goto fail; + if (n==VT_CF_WIN||VT_CF_NAME) { //bytes are in global memory + GlobalUnlock(lpmfp->hMF); + GlobalUnlock((HANDLE)(DWORD)lpSSIM->thumb.lpByte); + } + } + lpSSIM->thumb.cBytes = m; //restore in mem value + lpSSIM->thumb.selector = n; + + k = VT_EMPTY; + for (i=0; irglpsz[i]!=NULL) { + l = lpSSIM->rglpsz[i]->vtByteCount; + j = ((((int)l+4-1)/4)*4)+sizeof(DWORD)*2; + sc = GetScode(lpStream->Write(lpSSIM->rglpsz[i], j, &cbWritten)); + if (FAILED(sc)||cbWritten!=(ULONG)j) return 0; + lpSSIM->rglpsz[i]->vtByteCount = 0; //restore stz count convention + lpSSIM->rglpsz[i]->VTCB = (int)l; + } else { + sc = GetScode(lpStream->Write(&k, sizeof(DWORD), &cbWritten)); + if (FAILED(sc)||cbWritten!=sizeof(DWORD)) return 0; + } + } + return 1; +fail: + lpSSIM->thumb.cBytes = m; //restore in mem value + lpSSIM->thumb.selector = n; + if (m!=0&&(n==VT_CF_WIN||VT_CF_NAME)) { //bytes are in global memory + GlobalUnlock((HANDLE)(DWORD)lps); + } + + return 0; +} + + +/************************************************************************* +** +** OleStdGetSecurityProperty +** +** Purpose: +** Retrieve the Security Property +** +** Parameters: +** LPSUMINFO FAR *lp - pointer to open Summary Info struct +** +** Return Value: +** DWORD - security level +** AllSecurityFlagsEqNone 0 - no security +** fSecurityPassworded 1 - password required +** fSecurityRORecommended 2 - read-only is recommended +** fSecurityRO 4 - read-only is required +** fSecurityLockedForAnnotations 8 - locked for annotations +** +** Comments: +** by noting the (suggested; that is, application-enforced) security +** level on the document, an application other than the originator +** of the document can adjust its user interface to the properties +** appropriately. An application should not display any of the +** information about a password protected document, and should not +** allow modifications to enforced read-only or locked for +** annotations documents. It should warn the user about read-only +** recommended if the user attempts to modify properties. +** +*************************************************************************/ + +STDAPI_(DWORD) OleStdGetSecurityProperty(LPSUMINFO lp) +{ +STANDARDSECINMEM FAR *lpSSIM=(STANDARDSECINMEM FAR*)&((LPRSI)lp)->section; + if (lpSSIM->rgInts[3].vtType == VT_I4) return lpSSIM->rgInts[3].value; + + return 0; +} + + +/************************************************************************* +** +** OleStdSetSecurityProperty +** +** Purpose: +** Set the Security Property +** +** Parameters: +** LPSUMINFO FAR *lp - pointer to open Summary Info struct +** DWORD security - security level +** AllSecurityFlagsEqNone 0 - no security +** fSecurityPassworded 1 - password required +** fSecurityRORecommended 2 - read-only is recommended +** fSecurityRO 4 - read-only is required +** fSecurityLockedForAnnotations 8 - locked for annotations +** +** Return Value: +** int - 1 for success +** - 0 if error occurs +** (there are no errors) +** +** Comments: +** by noting the (suggested; that is, application-enforced) security +** level on the document, an application other than the originator +** of the document can adjust its user interface to the properties +** appropriately. An application should not display any of the +** information about a password protected document, and should not +** allow modifications to enforced read-only or locked for +** annotations documents. It should warn the user about read-only +** recommended if the user attempts to modify properties. +** +*************************************************************************/ + +STDAPI_(int) OleStdSetSecurityProperty(LPSUMINFO lp, DWORD security) +{ + STANDARDSECINMEM FAR *lpSSIM=(STANDARDSECINMEM FAR*)&((LPRSI)lp)->section; + + // REVIEW: check valid transitions; how do we know APP called us? + + if (security==0) { + lpSSIM->rgInts[3].vtType = VT_EMPTY; + return 1; + } + lpSSIM->rgInts[3].vtType = VT_I4; + lpSSIM->rgInts[3].value = security; + return 1; +} + + +/************************************************************************* +** +** OleStdGetStringProperty +** +** Purpose: +** Retrieve a String Propety. +** (returns zero terminated string -- C string) +** +** Parameters: +** LPSUMINFO FAR *lp - pointer to open Summary Info struct +** DWORD pid - ID of String Property +** +** Return Value: +** LPTSTR - value of String Property +** (zero terminated string--C string) +** +** Comments: +** String should NOT be freed by caller. Memory for string will be +** freed when OleStdFreeSummaryInfo is called. +*************************************************************************/ + +STDAPI_(LPTSTR) OleStdGetStringProperty(LPSUMINFO lp, DWORD pid) +{ + LPTSTR l = OleStdGetStringZProperty(lp,pid); + if (l==NULL) return NULL; else return l+1; +} + + +/************************************************************************* +** +** OleStdSetStringProperty +** +** Purpose: +** Set a String Propety +** (takes zero terminated string -- C string) +** +** Parameters: +** LPSUMINFO FAR *lp - pointer to open Summary Info struct +** DWORD pid - ID of String Property +** LPTSTR lpsz - new value for String Property. +** zero terminated string -- C string. +** May be NULL, in which case the +** propery is cleared. +** +** Return Value: +** int - 1 if successful +** - 0 invalid property id +** +** Comments: +** The input string is copied. +** +*************************************************************************/ + +STDAPI_(int) OleStdSetStringProperty(LPSUMINFO lp, DWORD pid, LPTSTR lpsz) +{ + LPRSI lprsi=(LPRSI)lp; + STANDARDSECINMEM FAR* lpSSIM=(STANDARDSECINMEM FAR*)&((LPRSI)lp)->section; + int i; + if (pid==PID_APPNAME) { + pid = MAXSTDZ-1; + } else if (pidPID_REVNUMBER) return 0; else pid -= 2; + OleDbgAssert(lpSSIM); + if (lpSSIM->rglpsz[pid]) MemFree(lpSSIM->rglpsz[pid]); + if ((lpsz==NULL)||(*lpsz==0)) { + lpSSIM->rglpsz[pid] = NULL; + return (1); + } + i = _fstrlen(lpsz); + lpSSIM->rglpsz[pid] = (STDZ FAR*)MemAlloc((i+1/*null*/)*sizeof(TCHAR)+ + sizeof(DWORD)*2); + if (lpSSIM->rglpsz[pid]==NULL) return 0; + _fstrcpy((LPTSTR)&lpSSIM->rglpsz[pid]->rgchars, lpsz); + lpSSIM->rglpsz[pid]->vtType = VT_LPSTR; + lpSSIM->rglpsz[pid]->vtByteCount = 0; + lpSSIM->rglpsz[pid]->VTCB = i; + return (1); +} + + +/************************************************************************* +** +** OleStdGetStringZProperty +** +** Purpose: +** Retrieve a String Propety. +** (returns zero-terminated with leading byte count string) +** +** Parameters: +** LPSUMINFO FAR *lp - pointer to open Summary Info struct +** DWORD pid - ID of Property +** +** Return Value: +** LPSTZR - value of String Property +** (zero-terminated with leading +** byte count) +** +** Comments: +** String should NOT be freed by caller. Memory for string will be +** freed when OleStdFreeSummaryInfo is called. +*************************************************************************/ + +STDAPI_(LPSTZR) OleStdGetStringZProperty(LPSUMINFO lp, DWORD pid) +{ + STANDARDSECINMEM FAR *lpSSIM=(STANDARDSECINMEM FAR*)&((LPRSI)lp)->section; + if (pid==PID_APPNAME) { + pid = MAXSTDZ-1; + } else if (pidPID_REVNUMBER) return NULL; else pid -= 2; + if (lpSSIM->rglpsz[pid]!=NULL) { + return (LPTSTR)&lpSSIM->rglpsz[pid]->VTCB; + } + return NULL; +} + + +/************************************************************************* +** +** OleStdGetDocProperty +** +** Purpose: +** Retrieve document properties (no. pages, no. words, no. characters) +** +** Parameters: +** LPSUMINFO FAR *lp - pointer to open Summary Info struct +** DWORD FAR *nPage - (OUT) number of pages in document +** DWORD FAR *nWords - (OUT) number of words in document +** DWORD FAR *nChars - (OUT) number of charactrs in doc +** +** Return Value: +** void +** +** Comments: +** +*************************************************************************/ + +STDAPI_(void) OleStdGetDocProperty( + LPSUMINFO lp, + DWORD FAR* nPage, + DWORD FAR* nWords, + DWORD FAR* nChars +) +{ +STANDARDSECINMEM FAR *lpSSIM=(STANDARDSECINMEM FAR*)&((LPRSI)lp)->section; + *nPage=0; *nWords=0; *nChars=0; + if (lpSSIM->rgInts[0].vtType == VT_I4) *nPage = lpSSIM->rgInts[0].value; + if (lpSSIM->rgInts[1].vtType == VT_I4) *nWords = lpSSIM->rgInts[1].value; + if (lpSSIM->rgInts[2].vtType == VT_I4) *nChars = lpSSIM->rgInts[2].value; +} + + +/************************************************************************* +** +** OleStdSetDocProperty +** +** Purpose: +** Set document properties (no. pages, no. words, no. characters) +** +** Parameters: +** LPSUMINFO FAR *lp - pointer to open Summary Info struct +** DWORD nPage - number of pages in document +** DWORD nWords - number of words in document +** DWORD nChars - number of charactrs in doc +** +** Return Value: +** int - 1 for success +** - 0 if error occurs +** (there are no errors) +** +** Comments: +** +*************************************************************************/ + +STDAPI_(int) OleStdSetDocProperty( + LPSUMINFO lp, + DWORD nPage, + DWORD nWords, + DWORD nChars +) +{ +DWORD vttype=VT_I4; +STANDARDSECINMEM FAR *lpSSIM=(STANDARDSECINMEM FAR*)&((LPRSI)lp)->section; + if ((nPage|nWords|nChars)==0) { + vttype = VT_EMPTY; + nPage=0; nWords=0; nChars=0; + } + lpSSIM->rgInts[0].vtType = vttype; + lpSSIM->rgInts[1].vtType = vttype; + lpSSIM->rgInts[2].vtType = vttype; + lpSSIM->rgInts[0].value = nPage; + lpSSIM->rgInts[1].value = nWords; + lpSSIM->rgInts[2].value = nChars; + return 1; +} + + +/************************************************************************* +** +** OleStdGetThumbNailProperty +** +** Purpose: +** Retrieve a Thumbnail Property +** +** Parameters: +** LPSTREAM lps +** LPSUMINFO FAR *lp - pointer to open Summary Info struct +** DWORD FAR* clipFormatNo - clipboard format for thumbnail +** (type of value depends on vtcf +** return value.) +** NOTE: ONLY VT_CF_WIN is +** implemented, so clipFormatNo +** will be CF_METAFILEPICT +** LPTSTR FAR* lpszName - format name if VT_CF_NAME is +** returned +** NOTE: NOT IMPLEMENTED +** THUMBNAIL FAR* clip - handle to thumbnail +** for VT_CF_WIN clip will be +** handle to MetafilePict +** NOTE: only VT_CF_WIN IMPLEMENTED +** DWORD FAR* byteCount - size of thumbnail stream +** for VT_CF_WIN case this should +** be combined size of both the +** Metafile as well as the +** MetafilePict structure. +** BOOL transferClip - transfer ownership of thumbnail +** to caller. (see comment) +** +** Return Value: +** int vtcfNo - OLE thumbnail selector value +** VT_CF_WIN - Windows thumbnail +** (interpret clipFormatNo as +** Windows clipboard format) +** VT_CF_FMTID - (NOT IMPLEMENTED) +** thumbnail format is specified +** by ID. use clipFormatNo. +** (but NOT a Windows format ID) +** +** VT_CF_NAME - (NOT IMPLEMENTED) +** thumbnail format is specified +** by name. use lpszName. +** VT_CF_EMPTY - blank thumbnail +** (clip will be NULL) +** VT_CF_OOM - Memory allocation failure +** +** Comments: +** NOTE: Currently there is only proper support for VT_CF_WIN. +** OleStdSetThumbNailProperty does implement VT_CF_FMTID and VT_CF_NAME, +** however, OleStdGetThumbNailProperty, OleStdReadSummaryInfo and +** OleStdWriteSummaryInfo only support VT_CF_WIN. +** +** Note that on input, the thumbnail is read on demand while all the +** other properties are pre-loaded. The thumbnail is manipulated as +** a windows handle to a METAFILEPICT structure, which in turn +** contains a handle to the METAFILE. The transferClip argument on +** GetThumbNail, when set to true, transfers responsibility for +** storage management of the thumbnail to the caller; that is, after +** OleStdFreeSummaryInfo has been called, the handle is still valid. +*************************************************************************/ + +STDAPI_(int) OleStdGetThumbNailProperty( + LPSTREAM lps, + LPSUMINFO lp, + DWORD FAR* clipFormatNo, + LPTSTR FAR* lpszName, + THUMBNAIL FAR* clip, + DWORD FAR* byteCount, + BOOL transferClip +) +{ + int i; + LPRSI lprsi=(LPRSI)lp; + STANDARDSECINMEM FAR *lpSSIM=(STANDARDSECINMEM FAR*)&((LPRSI)lp)->section; + ULONG cbRead, cbToRead; + LARGE_INTEGER a; + ULARGE_INTEGER b; + CHAR FAR *lpst; + LPMETAFILEPICT lpmfp; + HANDLE hst, hmfp; + SCODE sc; + *byteCount = 0; + if (lpSSIM->thumb.cBytes==0) return VT_CF_EMPTY; + if (lpSSIM->thumb.lpByte==NULL) { + LISet32(a, lprsi->fileOffset); + sc = GetScode(lps->Seek(a, STREAM_SEEK_SET, &b)); + if (FAILED(sc)) return VT_CF_EMPTY; + i = (int) lpSSIM->thumb.selector; + if (i>0||i==VT_CF_FMTID) { + if (i>255) return VT_CF_EMPTY; + else if (i==VT_CF_FMTID) i = sizeof(FMTID); + else lpSSIM->thumb.selector = VT_CF_NAME; + cbToRead = ((i+3)>>2)<<2; + lpSSIM->thumb.lpstzName=(CHAR FAR*)MemAlloc(i+1/*n*/+1); + if (lpSSIM->thumb.lpstzName==NULL) return VT_CF_OOM; + sc = GetScode(lps->Read(lpSSIM->thumb.lpstzName+1, cbToRead, &cbRead)); + if (FAILED(sc)||cbRead!=cbToRead) return VT_CF_EMPTY; + *lpSSIM->thumb.lpstzName = i; + *(lpSSIM->thumb.lpstzName+i) = 0; + lpSSIM->thumb.cBytes -= cbToRead+sizeof(DWORD); + } + i = (int) lpSSIM->thumb.selector; + cbToRead = lpSSIM->thumb.cBytes; + if (cbToRead>65535) return VT_CF_OOM; + OleDbgAssert(i!=VT_CF_NAME); + if (i==VT_CF_WIN) { + cbToRead -= sizeof(METAFILEPICT); + hmfp = GlobalAlloc(GMEM_MOVEABLE, sizeof(METAFILEPICT)); + if (hmfp==NULL) return VT_CF_OOM; + hst = GlobalAlloc(GMEM_MOVEABLE, cbToRead); + if (hst==NULL) { + GlobalFree(hmfp); + return VT_CF_OOM; + } + lpmfp = (LPMETAFILEPICT)GlobalLock(hmfp); + sc = GetScode(lps->Read(lpmfp, sizeof(METAFILEPICT), &cbRead)); + if (FAILED(sc)||cbRead!=sizeof(METAFILEPICT)) { + GlobalUnlock(hmfp); + GlobalFree(hmfp); + GlobalFree(hst); + return VT_CF_EMPTY; + } + lpst = (CHAR FAR*)GlobalLock(hst); + lpmfp->hMF = (HMETAFILE)hst; + lpSSIM->thumb.lpByte = (CHAR FAR*)hmfp; + } else { + lpst =(CHAR FAR*)MemAlloc((int)cbToRead); + if (lpst==NULL) return VT_CF_OOM; + lpSSIM->thumb.lpByte = lpst; + } + sc = GetScode(lps->Read(lpst, cbToRead, &cbRead)); + if (i==VT_CF_WIN) { + GlobalUnlock(hst); + GlobalUnlock(hmfp); + } + if (FAILED(sc)||cbRead!=cbToRead) { + if (i==VT_CF_WIN) { + GlobalFree(hst); + GlobalFree(hmfp); + } else MemFree(lpst); + lpSSIM->thumb.lpByte = NULL; + if ((i==VT_CF_NAME||i==VT_CF_FMTID)&&(lpSSIM->thumb.lpstzName!=NULL)) + MemFree(lpSSIM->thumb.lpstzName); + return VT_CF_EMPTY; + } + } + *clipFormatNo = lpSSIM->thumb.clipFormat; + *byteCount = lpSSIM->thumb.cBytes; + if(lpszName!=NULL) + *lpszName = (TCHAR FAR*)lpSSIM->thumb.lpstzName+1; + *clip = (TCHAR FAR*)lpSSIM->thumb.lpByte; + if (transferClip) lpSSIM->thumb.lpByte=NULL; + return (int)lpSSIM->thumb.selector; +} + + +/************************************************************************* +** +** OleStdSetThumbNailProperty +** +** Purpose: +** Set a Thumbnail Property +** +** Parameters: +** LPSTREAM lps - open SummaryInfo IStream* +** LPSUMINFO FAR *lp - pointer to open Summary Info struct +** int vtcfNo - OLE thumbnail selector value +** VT_CF_WIN - Windows thumbnail +** (interpret clipFormatNo as +** Windows clipboard format) +** VT_CF_FMTID - thumbnail format is specified +** by ID. use clipFormatNo. +** (but NOT a Windows format ID) +** +** VT_CF_NAME - thumbnail format is specified +** by name. use lpszName. +** VT_CF_EMPTY - blank thumbnail +** (clip will be NULL) +** +** DWORD FAR* clipFormatNo - clipboard format for thumbnail +** used if vtcfNo is VT_CF_WIN or +** VT_CF_FMTID. interpretation of +** value depends on vtcfNo specified. +** (normally vtcfNo==VT_CF_WIN and +** clipFormatNo==CF_METAFILEPICT) +** LPSTR FAR* lpszName - format name if vtcfNo is VT_CF_NAME +** THUMBNAIL clip - handle to thumbnail +** for VT_CF_WIN clip will be +** handle to MetafilePict +** DWORD FAR* byteCount - size of thumbnail stream +** for VT_CF_WIN case this should +** be combined size of both the +** Metafile as well as the +** MetafilePict structure. +** +** Return Value: +** int - 1 for success +** - 0 if error occurs +** +** Comments: +** NOTE: Currently there is only proper support for VT_CF_WIN. +** OleStdSetThumbNailProperty does implement VT_CF_FMTID and VT_CF_NAME, +** however, OleStdGetThumbNailProperty, OleStdReadSummaryInfo and +** OleStdWriteSummaryInfo only support VT_CF_WIN. +** +** This function copies lpszName but saves the "clip" handle passed. +** +** NOTE: overwriting or emptying frees space for clip and name. +** The thumbnail is manipulated as a windows handle to a +** METAFILEPICT structure, which in turn contains a handle to the +** METAFILE. +*************************************************************************/ + +STDAPI_(int) OleStdSetThumbNailProperty( + LPSTREAM lps, + LPSUMINFO lp, + int vtcfNo, + DWORD clipFormatNo, + LPTSTR lpszName, + THUMBNAIL clip, + DWORD byteCount +) +{ + int i; + LPRSI lprsi=(LPRSI)lp; + STANDARDSECINMEM FAR *lpSSIM=(STANDARDSECINMEM FAR*)&((LPRSI)lp)->section; + LPMETAFILEPICT lpmfp; + if (lpSSIM==NULL||vtcfNo>0||vtcfNothumb.vtType; + if (i!=VT_EMPTY) { + i = (int) lpSSIM->thumb.selector; + OleDbgAssert(i!=VT_CF_NAME); + if (i==VT_CF_WIN) { + if (lpSSIM->thumb.lpByte!=NULL) { + lpmfp = (LPMETAFILEPICT)GlobalLock((HANDLE)(DWORD)lpSSIM->thumb.lpByte); + GlobalFree(lpmfp->hMF); + GlobalUnlock((HANDLE)(DWORD)lpSSIM->thumb.lpByte); + GlobalFree((HANDLE)(DWORD)lpSSIM->thumb.lpByte); + } + } else { + MemFree(lpSSIM->thumb.lpByte); + } + if ((i==VT_CF_NAME||i==VT_CF_FMTID)&&(lpSSIM->thumb.lpstzName!=NULL)) + MemFree(lpSSIM->thumb.lpstzName); + lpSSIM->thumb.lpstzName = NULL; + lpSSIM->thumb.lpByte = NULL; + } + if (vtcfNo==VT_CF_EMPTY) { + lpSSIM->thumb.vtType = VT_EMPTY; + lpSSIM->thumb.cBytes = 0; + } else { + lpSSIM->thumb.vtType = VT_CF; + lpSSIM->thumb.selector = vtcfNo; + lpSSIM->thumb.cBytes = byteCount; + lpSSIM->thumb.clipFormat = clipFormatNo; + lpSSIM->thumb.lpByte = (CHAR FAR*)clip; //just save the hnadle + if (vtcfNo==VT_CF_NAME||vtcfNo==VT_CF_FMTID) { + i = _fstrlen(lpszName); + if (vtcfNo==VT_CF_FMTID) OleDbgAssert(i*sizeof(TCHAR)==sizeof(FMTID)); + lpSSIM->thumb.lpstzName = + (CHAR FAR*)MemAlloc((i+1/*n*/+1/*null*/)*sizeof(TCHAR)); + if (lpSSIM->thumb.lpstzName==NULL) { + lpSSIM->thumb.vtType = VT_EMPTY; + return 0; + } + _fstrcpy((TCHAR FAR*)lpSSIM->thumb.lpstzName+1, lpszName); + *lpSSIM->thumb.lpstzName = i; + } + } + return 1; +} + + +/************************************************************************* +** +** OleStdGetDateProperty +** +** Purpose: +** Retrieve Data Property +** +** Parameters: +** LPSUMINFO FAR *lp - pointer to open Summary Info struct +** DWORD pid - ID of Property +** int FAR *yr - (OUT) year +** int FAR *mo - (OUT) month +** int FAR *dy - (OUT) day +** DWORD FAR *sc - (OUT) seconds +** +** Return Value: +** void +** +** Comments: +** +*************************************************************************/ + +STDAPI_(void) OleStdGetDateProperty( + LPSUMINFO lp, + DWORD pid, + int FAR* yr, + int FAR* mo, + int FAR* dy, + DWORD FAR* sc +) +{ + STANDARDSECINMEM FAR *lpSSIM=(STANDARDSECINMEM FAR*)&((LPRSI)lp)->section; + SFFS sffs; + pid -= PID_EDITTIME; + *yr = 0; *mo = 0; *dy = 0; *sc = 0; + if (pid<0||pid>=MAXTIME) return; + if (lpSSIM->rgTime[pid].vtType == VT_FILETIME) { + if (pid==0) { + //convert from 100ns to seconds + ulargeDivide((ULARGE_INTEGER FAR*)&lpSSIM->rgTime[0].time, 10000); + ulargeDivide((ULARGE_INTEGER FAR*)&lpSSIM->rgTime[0].time, 1000); + pid = lpSSIM->rgTime[0].time.dwLowDateTime; + *sc = pid%((DWORD)60*60*24); + pid /= (DWORD)60*60*24; + *dy = (int)(pid%(DWORD)30); + pid /= (DWORD)30; + *mo = (int)(pid%(DWORD)12); + *yr = (int)(pid/(DWORD)12); + } else { + if (CoFileTimeToDosDateTime(&lpSSIM->rgTime[pid].time, + &sffs.dateVariable, &sffs.timeVariable)) { + *yr = sffs.yr+1980; + *mo = sffs.mon; + *dy = sffs.dom; + *sc = (DWORD)sffs.hr*3600+sffs.mint*60+sffs.sec*2; + } + } + } + return; +} + + + +/************************************************************************* +** +** OleStdSetDateProperty +** +** Purpose: +** Set Data Property +** +** Parameters: +** LPSUMINFO FAR *lp - pointer to open Summary Info struct +** DWORD pid - ID of Property +** int yr - year +** int mo - month +** int dy - day +** DWORD sc - seconds +** +** Return Value: +** int - 1 for success +** - 0 if error occurs +** +** Comments: +** Use all zeros to clear. +** The following is an example of valid input: +** yr=1993 mo=1(Jan) dy=1(1st) hr=12(noon) mn=30 sc=23 +** for PID_EDITTIME property, the values are a zero-origin duration +** of time. +** +*************************************************************************/ + +STDAPI_(int) OleStdSetDateProperty( + LPSUMINFO lp, + DWORD pid, + int yr, + int mo, + int dy, + int hr, + int mn, + int sc +) +{ + STANDARDSECINMEM FAR *lpSSIM=(STANDARDSECINMEM FAR*)&((LPRSI)lp)->section; + SFFS sffs; + pid -= PID_EDITTIME; + if (pid<0||pid>=MAXTIME) return 0; + if ((yr|mo|dy|hr|mn|sc)==0) { //all must be zero + lpSSIM->rgTime[pid].vtType = VT_EMPTY; + return 1; + } + lpSSIM->rgTime[pid].vtType = VT_FILETIME; + if (pid==0) { + lpSSIM->rgTime[0].time.dwLowDateTime = + (((((DWORD)yr*365+mo*30)+dy)*24+hr)*60+mn)*60+sc; + lpSSIM->rgTime[0].time.dwHighDateTime = 0; + //10^7 nanoseconds/second + ulargeMultiply((ULARGE_INTEGER FAR*)&lpSSIM->rgTime[0].time, 10000); + //convert to units of 100 ns + ulargeMultiply((ULARGE_INTEGER FAR*)&lpSSIM->rgTime[0].time, 1000); + } else { + sffs.yr = max(yr-1980,0); + sffs.mon = mo; + sffs.dom = dy; + sffs.hr = hr; + sffs.mint= mn; + sffs.sec = sc/2; //dos is 2 second intervals + if (!CoDosDateTimeToFileTime(sffs.date, sffs.time, + &lpSSIM->rgTime[pid].time)) { + lpSSIM->rgTime[pid].vtType = VT_EMPTY; + return 0; + } + } + return 1; +} + +} //END C diff --git a/private/oleutest/letest/ole2ui/suminfo.h b/private/oleutest/letest/ole2ui/suminfo.h new file mode 100644 index 000000000..ef803ab65 --- /dev/null +++ b/private/oleutest/letest/ole2ui/suminfo.h @@ -0,0 +1,331 @@ +/************************************************************************* +** +** OLE 2.0 Property Set Utilities +** +** suminfo.h +** +** This file contains file contains data structure defintions, +** function prototypes, constants, etc. for OLE 2.0 Property Set +** utilities used to manage the Summary Info property set. +** +** (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved +** +*************************************************************************/ + +#ifndef SUMINFO_H +#define SUMINFO_H + +#include + +/* A SUMINFO variable is an instance of an abstract data type. Thus, +** there can be an arbitrary number of SummaryInfo streams open +** simultaneously (subject to available memory). Each variable must +** be initialized prior to use by calling Init and freed after its +** last use by calling Free. The param argument to Init is reserved +** for future expansion and should be zero initially. Once a SUMINFO +** variable is allocated (by Init), the user can call the Set +** procedures to initialize fields. A copy of the arguments is made +** in every case except SetThumbnail where control of the storage +** occupied by the METAFILEPICT is merely transferred. When the +** Free routine is called, all storage will be deallocated including +** that of the thumbnail. The arguments to SetThumbNail and the +** return values from GetThumbNail correspond to the OLE2.0 spec. +** Note that on input, the thumbnail is read on demand but all the +** other properties are pre-loaded. The thumbnail is manipulated as +** a windows handle to a METAFILEPICT structure, which in turn +** contains a handle to the METAFILE. The transferClip argument on +** GetThumbNail, when set to true, transfers responsibility for +** storage management of the thumbnail to the caller; that is, after +** Free has been called, the handle is still valid. Clear can be +** used to free storage for all the properties but then you must +** call Read to load them again. All the code is based on FAR +** pointers. +** CoInitialize MUST be called PRIOR to calling OleStdInitSummaryInfo. +** Memory is allocated using the currently active IMalloc* +** allocator (as is returned by call CoGetMalloc(MEMCTX_TASK) ). +** +** Common scenarios: +** Read SummaryInfo +** ---------------- +** OleStdInitSummaryInfo() +** OleStdReadSummaryInfo() +** . . . . . +** call different Get routines +** . . . . . +** OleStdFreeSummaryInfo() +** +** Create SummaryInfo +** ------------------ +** OleStdInitSummaryInfo() +** call different Set routines +** OleStdWriteSummaryInfo() +** OleStdFreeSummaryInfo() +** +** Update SummaryInfo +** ------------------ +** OleStdInitSummaryInfo() +** OleStdReadSummaryInfo() +** OleStdGetThumbNailProperty(necessary only if no SetThumb) +** call different Set routines +** OleStdWriteSummaryInfo() +** OleStdFreeSummaryInfo() +*/ + +#define WORDMAX 256 //current string max for APPS; 255 + null terminator + + +typedef union { + short iVal; /* VT_I2 */ + long lVal; /* VT_I4 */ + float fltVal; /* VT_R4 */ + double dblVal; /* VT_R8 */ + DWORD bool; /* VT_BOOL */ + SCODE scodeVal; /* VT_ERROR */ + DWORD systimeVal; /* VT_SYSTIME */ +#ifdef UNICODE + TCHAR bstrVal[WORDMAX]; /* VT_BSTR */ +#else + unsigned char bstrVal[WORDMAX]; /* VT_BSTR */ +#endif + } VTUNION; + +#if 0 +typedef struct _FMTID + { + DWORD dword; + WORD words[2]; + BYTE bytes[8]; + } FMTID; +#endif + +typedef struct _PROPSETLIST + { + FMTID formatID; + DWORD byteOffset; + } PROPSETLIST; + +typedef struct _PROPIDLIST + { + DWORD propertyID; + DWORD byteOffset; + } PROPIDLIST; + +typedef struct _PROPVALUE + { + DWORD vtType; + VTUNION vtValue; + } PROPVALUE; + +typedef struct _SECTION + { + DWORD cBytes; + DWORD cProperties; + PROPIDLIST rgPropId[1/*cProperties*/]; //variable-length array + PROPVALUE rgPropValue[1]; //CANNOT BE ACCESSED BY NAME; ONLY BY POINTER + } SECTION; + +typedef struct _SUMMARYINFO + { + WORD byteOrder; + WORD formatVersion; + WORD getOSVersion; + WORD osVersion; + CLSID classId; //from compobj.h + DWORD cSections; + PROPSETLIST rgPropSet[1/*cSections*/]; //variable-length array + SECTION rgSections[1/*cSections*/]; //CANNOT BE ACCESSED BY NAME; ONLY BY POINTER + } SUMMARYINFO; + +#define osWinOnDos 0 +#define osMac 1 +#define osWinNT 2 + +#define PID_DICTIONARY 0X00000000 +#define PID_CODEPAGE 0X00000001 +#define PID_TITLE 0X00000002 +#define PID_SUBJECT 0X00000003 +#define PID_AUTHOR 0X00000004 +#define PID_KEYWORDS 0X00000005 +#define PID_COMMENTS 0X00000006 +#define PID_TEMPLATE 0X00000007 +#define PID_LASTAUTHOR 0X00000008 +#define PID_REVNUMBER 0X00000009 +#define PID_EDITTIME 0X0000000A +#define PID_LASTPRINTED 0X0000000B +#define PID_CREATE_DTM_RO 0X0000000C +#define PID_LASTSAVE_DTM 0X0000000D +#define PID_PAGECOUNT 0X0000000E +#define PID_WORDCOUNT 0X0000000F +#define PID_CHARCOUNT 0X00000010 +#define PID_THUMBNAIL 0X00000011 +#define PID_APPNAME 0X00000012 +#define PID_SECURITY 0X00000013 +#define cPID_STANDARD (PID_SECURITY+1-2) + +#define MAXWORD 256 //maximum string size for APPS at present + +typedef struct _STDZ + { + DWORD vtType; + union { + DWORD vtByteCount; +#ifdef UNICODE + TCHAR fill[4]; //use last byte as byte count for stz requests +#else + unsigned char fill[4]; //use last byte as byte count for stz requests +#endif + }; + +#ifdef UNICODE + TCHAR rgchars[MAXWORD]; +#else + unsigned char rgchars[MAXWORD]; +#endif + } STDZ; +#define VTCB fill[3] //used to set/get the count byte when in memory + +typedef struct _THUMB + { + DWORD vtType; + DWORD cBytes; //clip size in memory + DWORD selector; //on disk -1,win clip no. -2,mac clip no. -3,ole FMTID 0,bytes nameLength, format name + DWORD clipFormat; + char FAR *lpstzName; + char FAR *lpByte; + } THUMB; + +#define VT_CF_BYTES 0 +#define VT_CF_WIN ((DWORD)(-1)) +#define VT_CF_MAC ((DWORD)(-2)) +#define VT_CF_FMTID ((DWORD)(-3)) +#define VT_CF_NAME ((DWORD)(-4)) +#define VT_CF_EMPTY ((DWORD)(-5)) +#define VT_CF_OOM ((DWORD)(-6)) // Out of memory +typedef THUMB FAR *LPTHUMB; + +typedef STDZ FAR *LPSTDZ; + +typedef struct _TIME + { + DWORD vtType; + FILETIME time; + } TIME; + +typedef struct _INTS + { + DWORD vtType; + DWORD value; + } INTS; + +#define MAXTIME (PID_LASTSAVE_DTM-PID_EDITTIME+1) +#define MAXINTS (PID_CHARCOUNT-PID_PAGECOUNT+1+1) +#define MAXSTDZ (PID_REVNUMBER-PID_TITLE+1+1) + +typedef struct _STANDARDSECINMEM + { + DWORD cBytes; + DWORD cProperties; + PROPIDLIST rgPropId[cPID_STANDARD/*cProperties*/]; //variable-length array + TIME rgTime[MAXTIME]; + INTS rgInts[MAXINTS]; + LPSTDZ rglpsz[MAXSTDZ]; + THUMB thumb; + } STANDARDSECINMEM; + + +#define OFFSET_NIL 0X00000000 + +#define AllSecurityFlagsEqNone 0 +#define fSecurityPassworded 1 +#define fSecurityRORecommended 2 +#define fSecurityRO 4 +#define fSecurityLockedForAnnotations 8 + +#define PropStreamNamePrefixByte '\005' +#define PropStreamName "\005SummaryInformation" +#define cbNewSummaryInfo(nSection) (sizeof(SUMMARYINFO)-sizeof(SECTION)+sizeof(PROPSETLIST)*((nSection)-1)) +#define cbNewSection(nPropIds) (sizeof(SECTION)-sizeof(PROPVALUE)+sizeof(PROPIDLIST)*((nPropIds)-1)) + +#define FIntelOrder(prop) ((prop)->byteOrder==0xfffe) +#define SetOs(prop, os) {(prop)->osVersion=os; (prop)->getOSVersion=LOWORD(GetVersion());} +#define SetSumInfFMTID(fmtId) {(fmtId)->Data1=0XF29F85E0; *(long FAR *)&(fmtId)->Data2=0X10684FF9;\ + *(long FAR *)&(fmtId)->Data4[0]=0X000891AB; *(long FAR *)&(fmtId)->Data4[4]=0XD9B3272B;} +#define FEqSumInfFMTID(fmtId) ((fmtId)->Data1==0XF29F85E0&&*((long FAR *)&(fmtId)->Data2)==0X10684FF9&&\ + *((long FAR *)&(fmtId)->Data4[0])==0X000891AB&&*((long FAR *)&(fmtId)->Data4[4])==0XD9B3272B) +#define FSzEqPropStreamName(sz) _fstricmp(sz, PropStreamName) +#define ClearSumInf(lpsuminf, cb) {_fmemset(lpsuminf,0,cb); (lpsuminf)->byteOrder=0xfffe;\ + SetOs(lpsuminf, osWinOnDos);} + +typedef void FAR *LPSUMINFO; +typedef LPTSTR LPSTZR; +typedef void FAR *THUMBNAIL; //for VT_CF_WIN this is an unlocked global handle +#define API __far __pascal + + +/************************************************************************* +** Public Summary Info Property Set Management API +*************************************************************************/ + +extern "C" { +STDAPI_(LPSUMINFO) OleStdInitSummaryInfo(int reserved); +STDAPI_(void) OleStdFreeSummaryInfo(LPSUMINFO FAR *lplp); +STDAPI_(void) OleStdClearSummaryInfo(LPSUMINFO lp); +STDAPI_(int) OleStdReadSummaryInfo(LPSTREAM lpStream, LPSUMINFO lp); +STDAPI_(int) OleStdWriteSummaryInfo(LPSTREAM lpStream, LPSUMINFO lp); +STDAPI_(DWORD) OleStdGetSecurityProperty(LPSUMINFO lp); +STDAPI_(int) OleStdSetSecurityProperty(LPSUMINFO lp, DWORD security); +STDAPI_(LPTSTR) OleStdGetStringProperty(LPSUMINFO lp, DWORD pid); +STDAPI_(int) OleStdSetStringProperty(LPSUMINFO lp, DWORD pid, LPTSTR lpsz); +STDAPI_(LPSTZR) OleStdGetStringZProperty(LPSUMINFO lp, DWORD pid); +STDAPI_(void) OleStdGetDocProperty( + LPSUMINFO lp, + DWORD FAR* nPage, + DWORD FAR* nWords, + DWORD FAR* nChars +); +STDAPI_(int) OleStdSetDocProperty( + LPSUMINFO lp, + DWORD nPage, + DWORD nWords, + DWORD nChars +); +STDAPI_(int) OleStdGetThumbNailProperty( + LPSTREAM lps, + LPSUMINFO lp, + DWORD FAR* clipFormatNo, + LPTSTR FAR* lpszName, + THUMBNAIL FAR* clip, + DWORD FAR* byteCount, + BOOL transferClip +); +STDAPI_(int) OleStdSetThumbNailProperty( + LPSTREAM lps, + LPSUMINFO lp, + int vtcfNo, + DWORD clipFormatNo, + LPTSTR lpszName, + THUMBNAIL clip, + DWORD byteCount +); +STDAPI_(void) OleStdGetDateProperty( + LPSUMINFO lp, + DWORD pid, + int FAR* yr, + int FAR* mo, + int FAR* dy, + DWORD FAR* sc +); +STDAPI_(int) OleStdSetDateProperty( + LPSUMINFO lp, + DWORD pid, + int yr, + int mo, + int dy, + int hr, + int mn, + int sc +); + +} //END C + +#endif // SUMINFO_H diff --git a/private/oleutest/letest/ole2ui/targtdev.c b/private/oleutest/letest/ole2ui/targtdev.c new file mode 100644 index 000000000..55b6b0886 --- /dev/null +++ b/private/oleutest/letest/ole2ui/targtdev.c @@ -0,0 +1,328 @@ +/************************************************************************* +** +** OLE 2 Standard Utilities +** +** olestd.c +** +** This file contains utilities that are useful for dealing with +** target devices. +** +** (c) Copyright Microsoft Corp. 1992 All Rights Reserved +** +*************************************************************************/ + +#define STRICT 1 +#include "ole2ui.h" +#ifndef WIN32 +#include +#endif + +/* + * OleStdCreateDC() + * + * Purpose: + * + * Parameters: + * + * Return Value: + * SCODE - S_OK if successful + */ +STDAPI_(HDC) OleStdCreateDC(DVTARGETDEVICE FAR* ptd) +{ + HDC hdc=NULL; + LPDEVNAMES lpDevNames; + LPDEVMODE lpDevMode; + LPTSTR lpszDriverName; + LPTSTR lpszDeviceName; + LPTSTR lpszPortName; + + if (ptd == NULL) { + hdc = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL); + goto errReturn; + } + + lpDevNames = (LPDEVNAMES) ptd; // offset for size field + + if (ptd->tdExtDevmodeOffset == 0) { + lpDevMode = NULL; + }else{ + lpDevMode = (LPDEVMODE) ((LPSTR)ptd + ptd->tdExtDevmodeOffset); + } + + lpszDriverName = (LPTSTR) lpDevNames + ptd->tdDriverNameOffset; + lpszDeviceName = (LPTSTR) lpDevNames + ptd->tdDeviceNameOffset; + lpszPortName = (LPTSTR) lpDevNames + ptd->tdPortNameOffset; + + hdc = CreateDC(lpszDriverName, lpszDeviceName, lpszPortName, lpDevMode); + +errReturn: + return hdc; +} + + +/* + * OleStdCreateIC() + * + * Purpose: Same as OleStdCreateDC, except that information context is + * created, rather than a whole device context. (CreateIC is + * used rather than CreateDC). + * OleStdDeleteDC is still used to delete the information context. + * + * Parameters: + * + * Return Value: + * SCODE - S_OK if successful + */ +STDAPI_(HDC) OleStdCreateIC(DVTARGETDEVICE FAR* ptd) +{ + HDC hdcIC=NULL; + LPDEVNAMES lpDevNames; + LPDEVMODE lpDevMode; + LPTSTR lpszDriverName; + LPTSTR lpszDeviceName; + LPTSTR lpszPortName; + + if (ptd == NULL) { + hdcIC = CreateIC(TEXT("DISPLAY"), NULL, NULL, NULL); + goto errReturn; + } + + lpDevNames = (LPDEVNAMES) ptd; // offset for size field + + lpDevMode = (LPDEVMODE) ((LPTSTR)ptd + ptd->tdExtDevmodeOffset); + + lpszDriverName = (LPTSTR) lpDevNames + ptd->tdDriverNameOffset; + lpszDeviceName = (LPTSTR) lpDevNames + ptd->tdDeviceNameOffset; + lpszPortName = (LPTSTR) lpDevNames + ptd->tdPortNameOffset; + + hdcIC = CreateIC(lpszDriverName, lpszDeviceName, lpszPortName, lpDevMode); + +errReturn: + return hdcIC; +} + + +#ifdef NEVER +// This code is wrong +/* + * OleStdCreateTargetDevice() + * + * Purpose: + * + * Parameters: + * + * Return Value: + * SCODE - S_OK if successful + */ +STDAPI_(DVTARGETDEVICE FAR*) OleStdCreateTargetDevice(LPPRINTDLG lpPrintDlg) +{ + DVTARGETDEVICE FAR* ptd=NULL; + LPDEVNAMES lpDevNames, pDN; + LPDEVMODE lpDevMode, pDM; + UINT nMaxOffset; + LPTSTR pszName; + DWORD dwDevNamesSize, dwDevModeSize, dwPtdSize; + + if ((pDN = (LPDEVNAMES)GlobalLock(lpPrintDlg->hDevNames)) == NULL) { + goto errReturn; + } + + if ((pDM = (LPDEVMODE)GlobalLock(lpPrintDlg->hDevMode)) == NULL) { + goto errReturn; + } + + nMaxOffset = (pDN->wDriverOffset > pDN->wDeviceOffset) ? + pDN->wDriverOffset : pDN->wDeviceOffset ; + + nMaxOffset = (pDN->wOutputOffset > nMaxOffset) ? + pDN->wOutputOffset : nMaxOffset ; + + pszName = (LPTSTR)pDN + nMaxOffset; + + dwDevNamesSize = (DWORD)((nMaxOffset+lstrlen(pszName) + 1/* NULL term */)*sizeof(TCHAR)); + dwDevModeSize = (DWORD) (pDM->dmSize + pDM->dmDriverExtra); + + dwPtdSize = sizeof(DWORD) + dwDevNamesSize + dwDevModeSize; + + if ((ptd = (DVTARGETDEVICE FAR*)OleStdMalloc(dwPtdSize)) != NULL) { + + // copy in the info + ptd->tdSize = (UINT)dwPtdSize; + + lpDevNames = (LPDEVNAMES) &ptd->tdDriverNameOffset; + _fmemcpy(lpDevNames, pDN, (size_t)dwDevNamesSize); + + lpDevMode=(LPDEVMODE)((LPTSTR)&ptd->tdDriverNameOffset+dwDevNamesSize); + _fmemcpy(lpDevMode, pDM, (size_t)dwDevModeSize); + + ptd->tdDriverNameOffset += 4 ; + ptd->tdDeviceNameOffset += 4 ; + ptd->tdPortNameOffset += 4 ; + ptd->tdExtDevmodeOffset = (UINT)dwDevNamesSize + 4 ; + } + +errReturn: + GlobalUnlock(lpPrintDlg->hDevNames); + GlobalUnlock(lpPrintDlg->hDevMode); + + return ptd; +} +#endif // NEVER + + + +/* + * OleStdDeleteTargetDevice() + * + * Purpose: + * + * Parameters: + * + * Return Value: + * SCODE - S_OK if successful + */ +STDAPI_(BOOL) OleStdDeleteTargetDevice(DVTARGETDEVICE FAR* ptd) +{ + BOOL res=TRUE; + + if (ptd != NULL) { + OleStdFree(ptd); + } + + return res; +} + + + +/* + * OleStdCopyTargetDevice() + * + * Purpose: + * duplicate a TARGETDEVICE struct. this function allocates memory for + * the copy. the caller MUST free the allocated copy when done with it + * using the standard allocator returned from CoGetMalloc. + * (OleStdFree can be used to free the copy). + * + * Parameters: + * ptdSrc pointer to source TARGETDEVICE + * + * Return Value: + * pointer to allocated copy of ptdSrc + * if ptdSrc==NULL then retuns NULL is returned. + * if ptdSrc!=NULL and memory allocation fails, then NULL is returned + */ +STDAPI_(DVTARGETDEVICE FAR*) OleStdCopyTargetDevice(DVTARGETDEVICE FAR* ptdSrc) +{ + DVTARGETDEVICE FAR* ptdDest = NULL; + + if (ptdSrc == NULL) { + return NULL; + } + + if ((ptdDest = (DVTARGETDEVICE FAR*)OleStdMalloc(ptdSrc->tdSize)) != NULL) { + _fmemcpy(ptdDest, ptdSrc, (size_t)ptdSrc->tdSize); + } + + return ptdDest; +} + + +/* + * OleStdCopyFormatEtc() + * + * Purpose: + * Copies the contents of a FORMATETC structure. this function takes + * special care to copy correctly copying the pointer to the TARGETDEVICE + * contained within the source FORMATETC structure. + * if the source FORMATETC has a non-NULL TARGETDEVICE, then a copy + * of the TARGETDEVICE will be allocated for the destination of the + * FORMATETC (petcDest). + * + * OLE2NOTE: the caller MUST free the allocated copy of the TARGETDEVICE + * within the destination FORMATETC when done with it + * using the standard allocator returned from CoGetMalloc. + * (OleStdFree can be used to free the copy). + * + * Parameters: + * petcDest pointer to destination FORMATETC + * petcSrc pointer to source FORMATETC + * + * Return Value: + * returns TRUE is copy is successful; retuns FALSE if not successful + */ +STDAPI_(BOOL) OleStdCopyFormatEtc(LPFORMATETC petcDest, LPFORMATETC petcSrc) +{ + if ((petcDest == NULL) || (petcSrc == NULL)) { + return FALSE; + } + + petcDest->cfFormat = petcSrc->cfFormat; + petcDest->ptd = OleStdCopyTargetDevice(petcSrc->ptd); + petcDest->dwAspect = petcSrc->dwAspect; + petcDest->lindex = petcSrc->lindex; + petcDest->tymed = petcSrc->tymed; + + return TRUE; + +} + + +// returns 0 for exact match, 1 for no match, -1 for partial match (which is +// defined to mean the left is a subset of the right: fewer aspects, null target +// device, fewer medium). + +STDAPI_(int) OleStdCompareFormatEtc(FORMATETC FAR* pFetcLeft, FORMATETC FAR* pFetcRight) +{ + BOOL bExact = TRUE; + + if (pFetcLeft->cfFormat != pFetcRight->cfFormat) + return 1; + else if (!OleStdCompareTargetDevice (pFetcLeft->ptd, pFetcRight->ptd)) + return 1; + if (pFetcLeft->dwAspect == pFetcRight->dwAspect) + // same aspects; equal + ; + else if ((pFetcLeft->dwAspect & ~pFetcRight->dwAspect) != 0) + // left not subset of aspects of right; not equal + return 1; + else + // left subset of right + bExact = FALSE; + + if (pFetcLeft->tymed == pFetcRight->tymed) + // same medium flags; equal + ; + else if ((pFetcLeft->tymed & ~pFetcRight->tymed) != 0) + // left not subset of medium flags of right; not equal + return 1; + else + // left subset of right + bExact = FALSE; + + return bExact ? 0 : -1; +} + + + +STDAPI_(BOOL) OleStdCompareTargetDevice + (DVTARGETDEVICE FAR* ptdLeft, DVTARGETDEVICE FAR* ptdRight) +{ + if (ptdLeft == ptdRight) + // same address of td; must be same (handles NULL case) + return TRUE; + else if ((ptdRight == NULL) || (ptdLeft == NULL)) + return FALSE; + else if (ptdLeft->tdSize != ptdRight->tdSize) + // different sizes, not equal + return FALSE; +#ifdef WIN32 + else if (memcmp(ptdLeft, ptdRight, ptdLeft->tdSize) != 0) +#else + else if (_fmemcmp(ptdLeft, ptdRight, (int)ptdLeft->tdSize) != 0) +#endif + // not same target device, not equal + return FALSE; + + return TRUE; +} + diff --git a/private/oleutest/letest/ole2ui/template.c b/private/oleutest/letest/ole2ui/template.c new file mode 100644 index 000000000..9c35b4c2f --- /dev/null +++ b/private/oleutest/letest/ole2ui/template.c @@ -0,0 +1,243 @@ +/* + * TEMPLATE.C + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + * + * + * CUSTOMIZATION INSTRUCTIONS: + * + * 1. Replace with the uppercased filename for this file. + * Lowercase the .h entry + * + * 2. Replace with the mixed case dialog name in one word, + * such as InsertObject + * + * 3. Replace with the mixed case dialog name in multiple + * words, such as Insert Object + * + * 4. Replace with the suffix for pointer variables, such + * as the IO in InsertObject's pIO or the CI in ChangeIcon's pCI. + * Check the alignment of the first variable declaration in the + * Dialog Proc after this. I will probably be misaligned with the + * rest of the variables. + * + * 5. Replace with the uppercase structure name for this + * dialog sans OLEUI, such as INSERTOBJECT. Changes OLEUI + * in most cases, but we also use this for IDD_ as the + * standard template resource ID. + * + * 6. Find fields and fill them out with whatever is appropriate. + * + * 7. Delete this header up to the start of the next comment. + */ + + +/* + * .C + * + * Implements the OleUI function which invokes the complete + * dialog. + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + +#define STRICT 1 +#include "ole2ui.h" +#include "common.h" + +#ifndef WIN32 +#include ".h" +#else + #include "template.h" +#endif + + + + +/* + * OleUI + * + * Purpose: + * Invokes the standard OLE dialog box allowing the user + * to + * + * Parameters: + * lp LPOLEUI pointing to the in-out structure + * for this dialog. + * + * Return Value: + * UINT One of the following codes, indicating success or error: + * OLEUI_SUCCESS Success + * OLEUI_ERR_STRUCTSIZE The dwStructSize value is wrong + */ + +STDAPI_(UINT) OleUI(LPOLEUI lp) + { + UINT uRet; + HGLOBAL hMemDlg=NULL; + + uRet=UStandardValidation((LPOLEUISTANDARD)lp, sizeof(OLEUI) + , &hMemDlg); + + if (OLEUI_SUCCESS!=uRet) + return uRet; + + /* + * PERFORM ANY STRUCTURE-SPECIFIC VALIDATION HERE! + * ON FAILURE: + * { + * if (NULL!=hMemDlg) + * FreeResource(hMemDlg) + * + * return OLEUI_ERR_ + * } + */ + + //Now that we've validated everything, we can invoke the dialog. + uRet=UStandardInvocation(DialogProc, (LPOLEUISTANDARD)lp + , hMemDlg, MAKEINTRESOURCE(IDD_)); + + /* + * IF YOU ARE CREATING ANYTHING BASED ON THE RESULTS, DO IT HERE. + */ + + + return uRet; + } + + + + + +/* + * DialogProc + * + * Purpose: + * Implements the OLE dialog as invoked through the + * OleUI function. + * + * Parameters: + * Standard + * + * Return Value: + * Standard + */ + +BOOL CALLBACK EXPORT DialogProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam) + { + P p; + BOOL fHook=FALSE; + + //Declare Win16/Win32 compatible WM_COMMAND parameters. + COMMANDPARAMS(wID, wCode, hWndMsg); + + //This will fail under WM_INITDIALOG, where we allocate it. + p=()PvStandardEntry(hDlg, iMsg, wParam, lParam, &uHook); + + //If the hook processed the message, we're done. + if (0!=uHook) + return (BOOL)uHook; + + //Process the temination message + if (iMsg==uMsgEndDialog) + { + //Free any specific allocations before calling StandardCleanup + StandardCleanup((PVOID)p, hDlg); + EndDialog(hDlg, wParam); + return TRUE; + } + + switch (iMsg) + { + case WM_INITDIALOG: + FInit(hDlg, wParam, lParam); + return TRUE; + + + case WM_COMMAND: + switch (wID) + { + case IDOK: + /* + * PERFORM WHATEVER FUNCTIONS ARE DEFAULT HERE. + */ + SendMessage(hDlg, uMsgEndDialog, OLEUI_OK, 0L); + break; + + case IDCANCEL: + /* + * PERFORM ANY UNDOs HERE, BUT NOT CLEANUP THAT WILL + * ALWAYS HAPPEN WHICH SHOULD BE IN uMsgEndDialog. + */ + SendMessage(hDlg, uMsgEndDialog, OLEUI_CANCEL, 0L); + break; + + case ID_OLEUIHELP: + PostMessage(p->lpO->hWndOwner, uMsgHelp + , (WPARAM)hDlg, MAKELPARAM(IDD_, 0)); + break; + } + break; + } + return FALSE; + } + + + + +/* + * FInit + * + * Purpose: + * WM_INITIDIALOG handler for the dialog box. + * + * Parameters: + * hDlg HWND of the dialog + * wParam WPARAM of the message + * lParam LPARAM of the message + * + * Return Value: + * BOOL Value to return for WM_INITDIALOG. + */ + +BOOL FInit(HWND hDlg, WPARAM wParam, LPARAM lParam) + { + P p; + LPOLEUI lpO; + HFONT hFont; + + //1. Copy the structure at lParam into our instance memory. + p=(PSTRUCT)PvStandardInit(hDlg, sizeof(), TRUE, &hFont); + + //PvStandardInit send a termination to us already. + if (NULL==p) + return FALSE; + + lpO=(LPOLEUI)lParam); + + p->lpO=lpO; + + //Copy other information from lpO that we might modify. + + + //2. If we got a font, send it to the necessary controls. + if (NULL!=hFont) + { + //Do this for as many controls as you need it for. + SendDlgItemMessage(hDlg, ID_, WM_SETFONT, (WPARAM)hFont, 0L); + } + + + //3. Show or hide the help button + if (!(p->lpO->dwFlags & F_SHOWHELP)) + StandardShowDlgItem(hDlg, ID_OLEUIHELP, SW_HIDE); + + /* + * PERFORM OTHER INITIALIZATION HERE. ON ANY LoadString + * FAILURE POST OLEUI_MSG_ENDDIALOG WITH OLEUI_ERR_LOADSTRING. + */ + + //n. Call the hook with lCustData in lParam + UStandardHook((PVOID)p, hDlg, WM_INITDIALOG, wParam, lpO->lCustData); + return TRUE; + } diff --git a/private/oleutest/letest/ole2ui/template.h b/private/oleutest/letest/ole2ui/template.h new file mode 100644 index 000000000..3f277aec1 --- /dev/null +++ b/private/oleutest/letest/ole2ui/template.h @@ -0,0 +1,119 @@ +/* + * TEMPLATE.H + * + * CUSTOMIZATION INSTRUCTIONS: + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + * + * + * 1. Replace with the uppercased filename for this file. + * Lowercase the .h entry + * + * 2. Replace with the mixed case dialog name in one word, + * such as InsertObject + * + * 3. Replace with the mixed case dialog name in multiple + * words, such as Insert Object + * + * 4. Replace with the suffix for pointer variables, such + * as the IO in InsertObject's pIO or the CI in ChangeIcon's pCI. + * Check the alignment of the first variable declaration in the + * Dialog Proc after this. I will probably be misaligned with the + * rest of the variables. + * + * 5. Replace with the uppercase structure name for this + * dialog sans OLEUI, such as INSERTOBJECT. Changes OLEUI + * in most cases, but we also use this for IDD_ as the + * standard template resource ID. + * + * 6. Find fields and fill them out with whatever is appropriate. + * + * 7. Delete this header up to the start of the next comment. + * + */ + + +/* + * .H + * + * Internal definitions, structures, and function prototypes for the + * OLE 2.0 UI dialog. + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + + +#ifndef +#define + +//UFILL> Move from here to INTERNAL to to OLE2UI.H + + +typedef struct tagOLEUI + { + //These IN fields are standard across all OLEUI dialog functions. + DWORD cbStruct; //Structure Size + DWORD dwFlags; //IN-OUT: Flags + HWND hWndOwner; //Owning window + LPCTSTR lpszCaption; //Dialog caption bar contents + LPFNOLEUIHOOK lpfnHook; //Hook callback + LPARAM lCustData; //Custom data to pass to hook + HINSTANCE hInstance; //Instance for customized template name + LPCTSTR lpszTemplate; //Customized template name + HRSRC hResource; //Customized template handle + + //Specifics for OLEUI. All are IN-OUT unless otherwise spec. + } OLEUI, *POLEUI, FAR *LPOLEUI; + + +//API Prototype +UINT FAR PASCAL OleUI(LPOLEUI); + + +// flags +#define F_SHOWHELP 0x00000001L + + + +// specific error codes +//DEFINE AS OLEUI_ERR_ (OLEUI_ERR_STANDARDMAX+n) + + + +// Dialog identifiers +//FILL IN DIALOG IDs HERE + + + + + + +//INTERNAL INFORMATION STARTS HERE + +//Internally used structure +typedef struct tag + { + //Keep this item first as the Standard* functions depend on it here. + LPOLEUI lpO; //Original structure passed. + + /* + * What we store extra in this structure besides the original caller's + * pointer are those fields that we need to modify during the life of + * the dialog but that we don't want to change in the original structure + * until the user presses OK. + */ + + + } , *P; + + + +//Internal function prototypes +//.C +BOOL FAR PASCAL DialogProc(HWND, UINT, WPARAM, LPARAM); +BOOL FInit(HWND hDlg, WPARAM, LPARAM); + + + + +#endif // diff --git a/private/oleutest/letest/ole2ui/uiclass.h b/private/oleutest/letest/ole2ui/uiclass.h new file mode 100644 index 000000000..801819141 --- /dev/null +++ b/private/oleutest/letest/ole2ui/uiclass.h @@ -0,0 +1,2 @@ +#define SZCLASSICONBOX TEXT("OLE2UIIBClass") +#define SZCLASSRESULTIMAGE TEXT("OLE2UIRIClass") diff --git a/private/oleutest/letest/ole2ui/uimake.cmd b/private/oleutest/letest/ole2ui/uimake.cmd new file mode 100644 index 000000000..b6bd1f6c7 --- /dev/null +++ b/private/oleutest/letest/ole2ui/uimake.cmd @@ -0,0 +1 @@ +nmake -f ole2ui.mak %1 %2 %3 %4 %5 %6 %7 %8 %9 diff --git a/private/oleutest/letest/ole2ui/uimake.ini b/private/oleutest/letest/ole2ui/uimake.ini new file mode 100644 index 000000000..a7d847908 --- /dev/null +++ b/private/oleutest/letest/ole2ui/uimake.ini @@ -0,0 +1,24 @@ +# This is the DEBUG static .LIB UILibrary INI file +MSG=DEBUG Static LIB Version ($(LANG)) +DEBUG=1 +MODEL=M +# Make a static library called OLE2UI.LIB +LIBNAME=OLE2UI +REL_DIR=d:\cairo\cairole\h\export +OLEREL_DIR=d:\cairo\cairole\h\export +OBJ=DEBUGLIB +BUILD=LIB +RESOURCE=RESOURCE + +# 16 bit CFLAGS=-c -Od -GA2s -W3 -Zpei -AM -D_DEBUG -DWIN32 -DUNICODE + +CFLAGS=-c -Od -Gs -W3 -Zpei -D_DEBUG -DWIN32 -DUNICODE +RFLAGS=-D DEBUG +LFLAGS=/MAP:FULL /CO /LINE /NOD /NOE /SE:300 /NOPACKCODE +UILIBS=mlibcew libw ole2 storage shell commdlg toolhelp +CC=cl +AS=masm +RS=rc +LK=link +LANG=USA +LIBOBJS = $(UI_COBJS:D^\=DEBUGLIB^\) $(UI_NOPCOBJS:D^\=DEBUGLIB\NOPC^\) diff --git a/private/oleutest/letest/ole2ui/utility.c b/private/oleutest/letest/ole2ui/utility.c new file mode 100644 index 000000000..98deecc25 --- /dev/null +++ b/private/oleutest/letest/ole2ui/utility.c @@ -0,0 +1,1039 @@ +/* + * UTILITY.C + * + * Utility routines for functions inside OLE2UI.DLL + * + * General: + * ---------------------- + * HourGlassOn Displays the hourglass + * HourGlassOff Hides the hourglass + * + * Misc Tools: + * ---------------------- + * Browse Displays the "File..." or "Browse..." dialog. + * ReplaceCharWithNull Used to form filter strings for Browse. + * ErrorWithFile Creates an error message with embedded filename + * OpenFileError Give error message for OpenFile error return + * ChopText Chop a file path to fit within a specified width + * DoesFileExist Checks if file is valid + * + * Registration Database: + * ---------------------- + * HIconFromClass Extracts the first icon in a class's server path + * FServerFromClass Retrieves the server path for a class name (fast) + * UClassFromDescription Finds the classname given a description (slow) + * UDescriptionFromClass Retrieves the description for a class name (fast) + * FGetVerb Retrieves a specific verb for a class (fast) + * + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + +#define STRICT 1 +#include "ole2ui.h" +#include +#include +#include +#include +#include "common.h" +#include "utility.h" +#include "geticon.h" + +OLEDBGDATA + +/* + * HourGlassOn + * + * Purpose: + * Shows the hourglass cursor returning the last cursor in use. + * + * Parameters: + * None + * + * Return Value: + * HCURSOR Cursor in use prior to showing the hourglass. + */ + +HCURSOR WINAPI HourGlassOn(void) + { + HCURSOR hCur; + + hCur=SetCursor(LoadCursor(NULL, IDC_WAIT)); + ShowCursor(TRUE); + + return hCur; + } + + + +/* + * HourGlassOff + * + * Purpose: + * Turns off the hourglass restoring it to a previous cursor. + * + * Parameters: + * hCur HCURSOR as returned from HourGlassOn + * + * Return Value: + * None + */ + +void WINAPI HourGlassOff(HCURSOR hCur) + { + ShowCursor(FALSE); + SetCursor(hCur); + return; + } + + + + +/* + * Browse + * + * Purpose: + * Displays the standard GetOpenFileName dialog with the title of + * "Browse." The types listed in this dialog are controlled through + * iFilterString. If it's zero, then the types are filled with "*.*" + * Otherwise that string is loaded from resources and used. + * + * Parameters: + * hWndOwner HWND owning the dialog + * lpszFile LPSTR specifying the initial file and the buffer in + * which to return the selected file. If there is no + * initial file the first character of this string should + * be NULL. + * lpszInitialDir LPSTR specifying the initial directory. If none is to + * set (ie, the cwd should be used), then this parameter + * should be NULL. + * cchFile UINT length of pszFile + * iFilterString UINT index into the stringtable for the filter string. + * dwOfnFlags DWORD flags to OR with OFN_HIDEREADONLY + * + * Return Value: + * BOOL TRUE if the user selected a file and pressed OK. + * FALSE otherwise, such as on pressing Cancel. + */ + +BOOL WINAPI Browse(HWND hWndOwner, LPTSTR lpszFile, LPTSTR lpszInitialDir, UINT cchFile, UINT iFilterString, DWORD dwOfnFlags) + { + UINT cch; + TCHAR szFilters[256]; + OPENFILENAME ofn; + BOOL fStatus; + DWORD dwError; + TCHAR szDlgTitle[128]; // that should be big enough + + if (NULL==lpszFile || 0==cchFile) + return FALSE; + + /* + * REVIEW: Exact contents of the filter combobox is TBD. One idea + * is to take all the extensions in the RegDB and place them in here + * with the descriptive class name associate with them. This has the + * extra step of finding all extensions of the same class handler and + * building one extension string for all of them. Can get messy quick. + * UI demo has only *.* which we do for now. + */ + + if (0!=iFilterString) + cch=LoadString(ghInst, iFilterString, (LPTSTR)szFilters, sizeof(szFilters)/sizeof(TCHAR)); + else + { + szFilters[0]=0; + cch=1; + } + + if (0==cch) + return FALSE; + + ReplaceCharWithNull(szFilters, szFilters[cch-1]); + + //Prior string must also be initialized, if there is one. + _fmemset((LPOPENFILENAME)&ofn, 0, sizeof(ofn)); + ofn.lStructSize =sizeof(ofn); + ofn.hwndOwner =hWndOwner; + ofn.lpstrFile =lpszFile; + ofn.nMaxFile =cchFile; + ofn.lpstrFilter =(LPTSTR)szFilters; + ofn.nFilterIndex=1; + if (LoadString(ghInst, IDS_BROWSE, (LPTSTR)szDlgTitle, sizeof(szDlgTitle)/sizeof(TCHAR))) + ofn.lpstrTitle =(LPTSTR)szDlgTitle; + ofn.hInstance = ghInst; + ofn.lpTemplateName = MAKEINTRESOURCE(IDD_FILEOPEN); + if (NULL != lpszInitialDir) + ofn.lpstrInitialDir = lpszInitialDir; + + ofn.Flags= OFN_HIDEREADONLY | OFN_ENABLETEMPLATE | (dwOfnFlags) ; + + //On success, copy the chosen filename to the static display + fStatus = GetOpenFileName((LPOPENFILENAME)&ofn); + dwError = CommDlgExtendedError(); + return fStatus; + + } + + + + + +/* + * ReplaceCharWithNull + * + * Purpose: + * Walks a null-terminated string and replaces a given character + * with a zero. Used to turn a single string for file open/save + * filters into the appropriate filter string as required by the + * common dialog API. + * + * Parameters: + * psz LPTSTR to the string to process. + * ch int character to replace. + * + * Return Value: + * int Number of characters replaced. -1 if psz is NULL. + */ + +int WINAPI ReplaceCharWithNull(LPTSTR psz, int ch) + { + int cChanged=-1; + + if (NULL!=psz) + { + while (0!=*psz) + { + if (ch==*psz) + { + *psz=TEXT('\0'); + cChanged++; + } + psz++; + } + } + return cChanged; + } + + + + + + +/* + * ErrorWithFile + * + * Purpose: + * Displays a message box built from a stringtable string containing + * one %s as a placeholder for a filename and from a string of the + * filename to place there. + * + * Parameters: + * hWnd HWND owning the message box. The caption of this + * window is the caption of the message box. + * hInst HINSTANCE from which to draw the idsErr string. + * idsErr UINT identifier of a stringtable string containing + * the error message with a %s. + * lpszFile LPSTR to the filename to include in the message. + * uFlags UINT flags to pass to MessageBox, like MB_OK. + * + * Return Value: + * int Return value from MessageBox. + */ + +int WINAPI ErrorWithFile(HWND hWnd, HINSTANCE hInst, UINT idsErr + , LPTSTR pszFile, UINT uFlags) + { + int iRet=0; + HANDLE hMem; + const UINT cb=(2*OLEUI_CCHPATHMAX_SIZE); + LPTSTR psz1, psz2, psz3; + + if (NULL==hInst || NULL==pszFile) + return iRet; + + //Allocate three 2*OLEUI_CCHPATHMAX byte work buffers + hMem=GlobalAlloc(GHND, (DWORD)(3*cb)); + + if (NULL==hMem) + return iRet; + + psz1=GlobalLock(hMem); + psz2=psz1+cb; + psz3=psz2+cb; + + if (0!=LoadString(hInst, idsErr, psz1, cb)) + { + wsprintf(psz2, psz1, pszFile); + + //Steal the caption of the dialog + GetWindowText(hWnd, psz3, cb); + iRet=MessageBox(hWnd, psz2, psz3, uFlags); + } + + GlobalUnlock(hMem); + GlobalFree(hMem); + return iRet; + } + + + + + + + + + +/* + * HIconFromClass + * + * Purpose: + * Given an object class name, finds an associated executable in the + * registration database and extracts the first icon from that + * executable. If none is available or the class has no associated + * executable, this function returns NULL. + * + * Parameters: + * pszClass LPSTR giving the object class to look up. + * + * Return Value: + * HICON Handle to the extracted icon if there is a module + * associated to pszClass. NULL on failure to either + * find the executable or extract and icon. + */ + +HICON WINAPI HIconFromClass(LPTSTR pszClass) + { + HICON hIcon; + TCHAR szEXE[OLEUI_CCHPATHMAX]; + UINT Index; + CLSID clsid; + + if (NULL==pszClass) + return NULL; + + CLSIDFromStringA(pszClass, &clsid); + + if (!FIconFileFromClass((REFCLSID)&clsid, szEXE, OLEUI_CCHPATHMAX_SIZE, &Index)) + return NULL; + + hIcon=ExtractIcon(ghInst, szEXE, Index); + + if ((HICON)32 > hIcon) + hIcon=NULL; + + return hIcon; + } + + + + + +/* + * FServerFromClass + * + * Purpose: + * Looks up the classname in the registration database and retrieves + * the name undet protocol\StdFileEditing\server. + * + * Parameters: + * pszClass LPSTR to the classname to look up. + * pszEXE LPSTR at which to store the server name + * cch UINT size of pszEXE + * + * Return Value: + * BOOL TRUE if one or more characters were loaded into pszEXE. + * FALSE otherwise. + */ + +BOOL WINAPI FServerFromClass(LPTSTR pszClass, LPTSTR pszEXE, UINT cch) +{ + + DWORD dw; + LONG lRet; + HKEY hKey; + + if (NULL==pszClass || NULL==pszEXE || 0==cch) + return FALSE; + + /* + * We have to go walking in the registration database under the + * classname, so we first open the classname key and then check + * under "\\LocalServer" to get the .EXE. + */ + + //Open up the class key + lRet=RegOpenKey(HKEY_CLASSES_ROOT, pszClass, &hKey); + + if ((LONG)ERROR_SUCCESS!=lRet) + return FALSE; + + //Get the executable path. + dw=(DWORD)cch; + lRet=RegQueryValue(hKey, TEXT("LocalServer"), pszEXE, &dw); + + RegCloseKey(hKey); + + return ((ERROR_SUCCESS == lRet) && (dw > 0)); +} + + + +/* + * UClassFromDescription + * + * Purpose: + * Looks up the actual OLE class name in the registration database + * for the given descriptive name chosen from a listbox. + * + * Parameters: + * psz LPSTR to the descriptive name. + * pszClass LPSTR in which to store the class name. + * cb UINT maximum length of pszClass. + * + * Return Value: + * UINT Number of characters copied to pszClass. 0 on failure. + */ + +UINT WINAPI UClassFromDescription(LPTSTR psz, LPTSTR pszClass, UINT cb) + { + DWORD dw; + HKEY hKey; + TCHAR szClass[OLEUI_CCHKEYMAX]; + LONG lRet; + UINT i; + + //Open up the root key. + lRet=RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hKey); + + if ((LONG)ERROR_SUCCESS!=lRet) + return 0; + + i=0; + lRet=RegEnumKey(hKey, i++, szClass, OLEUI_CCHKEYMAX_SIZE); + + //Walk the available keys + while ((LONG)ERROR_SUCCESS==lRet) + { + dw=(DWORD)cb; + lRet=RegQueryValue(hKey, szClass, pszClass, &dw); + + //Check if the description matches the one just enumerated + if ((LONG)ERROR_SUCCESS==lRet) + { + if (!lstrcmp(pszClass, psz)) + break; + } + + //Continue with the next key. + lRet=RegEnumKey(hKey, i++, szClass, OLEUI_CCHKEYMAX_SIZE); + } + + //If we found it, copy to the return buffer + if ((LONG)ERROR_SUCCESS==lRet) + lstrcpy(pszClass, szClass); + else + dw=0L; + + RegCloseKey(hKey); + return (UINT)dw; + } + + + + + + + + +/* + * UDescriptionFromClass + * + * Purpose: + * Looks up the actual OLE descriptive name name in the registration + * database for the given class name. + * + * Parameters: + * pszClass LPSTR to the class name. + * psz LPSTR in which to store the descriptive name. + * cb UINT maximum length of psz. + * + * Return Value: + * UINT Number of characters copied to pszClass. 0 on failure. + */ + +UINT WINAPI UDescriptionFromClass(LPTSTR pszClass, LPTSTR psz, UINT cb) + { + DWORD dw; + HKEY hKey; + LONG lRet; + + if (NULL==pszClass || NULL==psz) + return 0; + + //Open up the root key. + lRet=RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hKey); + + if ((LONG)ERROR_SUCCESS!=lRet) + return 0; + + //Get the descriptive name using the class name. + dw=(DWORD)cb; + lRet=RegQueryValue(hKey, pszClass, psz, &dw); + + RegCloseKey(hKey); + + psz+=lstrlen(psz)+1; + *psz=0; + + if ((LONG)ERROR_SUCCESS!=lRet) + return 0; + + return (UINT)dw; + } + + + +// returns width of line of text. this is a support routine for ChopText +static LONG GetTextWSize(HDC hDC, LPTSTR lpsz) +{ + SIZE size; + + if (GetTextExtentPoint(hDC, lpsz, lstrlen(lpsz), (LPSIZE)&size)) + return size.cx; + else { + return 0; + } +} + + +/* + * ChopText + * + * Purpose: + * Parse a string (pathname) and convert it to be within a specified + * length by chopping the least significant part + * + * Parameters: + * hWnd window handle in which the string resides + * nWidth max width of string in pixels + * use width of hWnd if zero + * lpch pointer to beginning of the string + * + * Return Value: + * pointer to the modified string + */ +LPTSTR WINAPI ChopText(HWND hWnd, int nWidth, LPTSTR lpch) +{ +#define PREFIX_SIZE 7 + 1 +#define PREFIX_FORMAT TEXT("%c%c%c...\\") + + TCHAR szPrefix[PREFIX_SIZE]; + BOOL fDone = FALSE; + int i; + RECT rc; + HDC hdc; + HFONT hfont; + HFONT hfontOld = NULL; + + if (!hWnd || !lpch) + return NULL; + + /* Get length of static field. */ + if (!nWidth) { + GetClientRect(hWnd, (LPRECT)&rc); + nWidth = rc.right - rc.left; + } + + /* Set up DC appropriately for the static control */ + hdc = GetDC(hWnd); + hfont = (HFONT)SendMessage(hWnd, WM_GETFONT, 0, 0L); + + if (NULL != hfont) // WM_GETFONT returns NULL if window uses system font + hfontOld = SelectObject(hdc, hfont); + + /* check horizontal extent of string */ + if (GetTextWSize(hdc, lpch) > nWidth) { + + /* string is too long to fit in static control; chop it */ + /* set up new prefix & determine remaining space in control */ + wsprintf((LPTSTR) szPrefix, PREFIX_FORMAT, lpch[0], lpch[1], lpch[2]); + nWidth -= (int)GetTextWSize(hdc, (LPTSTR) szPrefix); + + /* + ** advance a directory at a time until the remainder of the + ** string fits into the static control after the "x:\...\" prefix + */ + while (!fDone) { + +#ifdef DBCS + while (*lpch && (*lpch != TEXT('\\'))) +#ifdef WIN32 + lpch = CharNext(lpch); +#else + lpch = AnsiNext(lpch); +#endif + if (*lpch) +#ifdef WIN32 + lpch = CharNext(lpch); +#else + lpch = AnsiNext(lpch); +#endif +#else + while (*lpch && (*lpch++ != TEXT('\\'))); +#endif + + if (!*lpch || GetTextWSize(hdc, lpch) <= nWidth) { + if (!*lpch) + /* + ** Nothing could fit after the prefix; remove the + ** final "\" from the prefix + */ + szPrefix[lstrlen((LPTSTR) szPrefix) - 1] = 0; + + /* rest or string fits -- stick prefix on front */ + for (i = lstrlen((LPTSTR) szPrefix) - 1; i >= 0; --i) + *--lpch = szPrefix[i]; + fDone = TRUE; + } + } + } + + if (NULL != hfont) + SelectObject(hdc, hfontOld); + ReleaseDC(hWnd, hdc); + + return(lpch); + +#undef PREFIX_SIZE +#undef PREFIX_FORMAT +} + + +/* + * OpenFileError + * + * Purpose: + * display message for error returned from OpenFile + * + * Parameters: + * hDlg HWND of the dialog. + * nErrCode UINT error code returned in OFSTRUCT passed to OpenFile + * lpszFile LPSTR file name passed to OpenFile + * + * Return Value: + * None + */ +void WINAPI OpenFileError(HWND hDlg, UINT nErrCode, LPTSTR lpszFile) +{ + switch (nErrCode) { + case 0x0005: // Access denied + ErrorWithFile(hDlg, ghInst, IDS_CIFILEACCESS, lpszFile, MB_OK); + break; + + case 0x0020: // Sharing violation + ErrorWithFile(hDlg, ghInst, IDS_CIFILESHARE, lpszFile, MB_OK); + break; + + case 0x0002: // File not found + case 0x0003: // Path not found + ErrorWithFile(hDlg, ghInst, IDS_CIINVALIDFILE, lpszFile, MB_OK); + break; + + default: + ErrorWithFile(hDlg, ghInst, IDS_CIFILEOPENFAIL, lpszFile, MB_OK); + break; + } +} + +#define chSpace TEXT(' ') +#define chPeriod TEXT('.') +#define PARSE_EMPTYSTRING -1 +#define PARSE_INVALIDDRIVE -2 +#define PARSE_INVALIDPERIOD -3 +#define PARSE_INVALIDDIRCHAR -4 +#define PARSE_INVALIDCHAR -5 +#define PARSE_WILDCARDINDIR -6 +#define PARSE_INVALIDNETPATH -7 +#define PARSE_INVALIDSPACE -8 +#define PARSE_EXTENTIONTOOLONG -9 +#define PARSE_DIRECTORYNAME -10 +#define PARSE_FILETOOLONG -11 + +/*--------------------------------------------------------------------------- + * ParseFile + * Purpose: Determine if the filename is a legal DOS name + * Input: Long pointer to a SINGLE file name + * Circumstance checked: + * 1) Valid as directory name, but not as file name + * 2) Empty String + * 3) Illegal Drive label + * 4) Period in invalid location (in extention, 1st in file name) + * 5) Missing directory character + * 6) Illegal character + * 7) Wildcard in directory name + * 8) Double slash beyond 1st 2 characters + * 9) Space character in the middle of the name (trailing spaces OK) + * 10) Filename greater than 8 characters + * 11) Extention greater than 3 characters + * Notes: + * Filename length is NOT checked. + * Valid filenames will have leading spaces, trailing spaces and + * terminating period stripped in place. + * + * Returns: If valid, LOWORD is byte offset to filename + * HIWORD is byte offset to extention + * if string ends with period, 0 + * if no extention is given, string length + * If invalid, LOWORD is error code suggesting problem (< 0) + * HIWORD is approximate offset where problem found + * Note that this may be beyond the offending character + *--------------------------------------------------------------------------*/ + +static long ParseFile(LPTSTR lpstrFileName) +{ + short nFile, nExt, nFileOffset, nExtOffset; + BOOL bExt; + BOOL bWildcard; + short nNetwork = 0; + BOOL bUNCPath = FALSE; + LPTSTR lpstr = lpstrFileName; + +/* Strip off initial white space. Note that TAB is not checked */ +/* because it cannot be received out of a standard edit control */ +/* 30 January 1991 clarkc */ + while (*lpstr == chSpace) + lpstr++; + + if (!*lpstr) + { + nFileOffset = PARSE_EMPTYSTRING; + goto FAILURE; + } + + if (lpstr != lpstrFileName) + { + lstrcpy(lpstrFileName, lpstr); + lpstr = lpstrFileName; + } + + if ( + +#ifdef WIN32 + *CharNext(lpstr) +#else + *AnsiNext(lpstr) +#endif + == TEXT(':') + ) + + { + TCHAR cDrive = (*lpstr | (BYTE) 0x20); /* make lowercase */ + +/* This does not test if the drive exists, only if it's legal */ + if ((cDrive < TEXT('a')) || (cDrive > TEXT('z'))) + { + nFileOffset = PARSE_INVALIDDRIVE; + goto FAILURE; + } +#ifdef WIN32 + lpstr = CharNext(CharNext(lpstr)); +#else + lpstr = AnsiNext(AnsiNext(lpstr)); +#endif + } + + if ((*lpstr == TEXT('\\')) || (*lpstr == TEXT('/'))) + { + if (*++lpstr == chPeriod) /* cannot have c:\. */ + { + if ((*++lpstr != TEXT('\\')) && (*lpstr != TEXT('/'))) /* unless it's stupid */ + { + if (!*lpstr) /* it's the root directory */ + goto MustBeDir; + + nFileOffset = PARSE_INVALIDPERIOD; + goto FAILURE; + } + else + ++lpstr; /* it's saying top directory (again), thus allowed */ + } + else if ((*lpstr == TEXT('\\')) && (*(lpstr-1) == TEXT('\\'))) + { +/* It seems that for a full network path, whether a drive is declared or + * not is insignificant, though if a drive is given, it must be valid + * (hence the code above should remain there). + * 13 February 1991 clarkc + */ + ++lpstr; /* ...since it's the first slash, 2 are allowed */ + nNetwork = -1; /* Must receive server and share to be real */ + bUNCPath = TRUE; /* No wildcards allowed if UNC name */ + } + else if (*lpstr == TEXT('/')) + { + nFileOffset = PARSE_INVALIDDIRCHAR; + goto FAILURE; + } + } + else if (*lpstr == chPeriod) + { + if (*++lpstr == chPeriod) /* Is this up one directory? */ + ++lpstr; + if (!*lpstr) + goto MustBeDir; + if ((*lpstr != TEXT('\\')) && (*lpstr != TEXT('/'))) + { + nFileOffset = PARSE_INVALIDPERIOD; + goto FAILURE; + } + else + ++lpstr; /* it's saying directory, thus allowed */ + } + + if (!*lpstr) + { + goto MustBeDir; + } + +/* Should point to first char in 8.3 filename by now */ + nFileOffset = nExtOffset = nFile = nExt = 0; + bWildcard = bExt = FALSE; + while (*lpstr) + { +/* + * The next comparison MUST be unsigned to allow for extended characters! + * 21 Feb 1991 clarkc + */ + if (*lpstr < chSpace) + { + nFileOffset = PARSE_INVALIDCHAR; + goto FAILURE; + } + switch (*lpstr) + { + case TEXT('"'): /* All invalid */ + case TEXT('+'): + case TEXT(','): + case TEXT(':'): + case TEXT(';'): + case TEXT('<'): + case TEXT('='): + case TEXT('>'): + case TEXT('['): + case TEXT(']'): + case TEXT('|'): + { + nFileOffset = PARSE_INVALIDCHAR; + goto FAILURE; + } + + case TEXT('\\'): /* Subdirectory indicators */ + case TEXT('/'): + nNetwork++; + if (bWildcard) + { + nFileOffset = PARSE_WILDCARDINDIR; + goto FAILURE; + } + + else if (nFile == 0) /* can't have 2 in a row */ + { + nFileOffset = PARSE_INVALIDDIRCHAR; + goto FAILURE; + } + else + { /* reset flags */ + ++lpstr; + if (!nNetwork && !*lpstr) + { + nFileOffset = PARSE_INVALIDNETPATH; + goto FAILURE; + } + nFile = nExt = 0; + bExt = FALSE; + } + break; + + case chSpace: + { + LPTSTR lpSpace = lpstr; + + *lpSpace = TEXT('\0'); + while (*++lpSpace) + { + if (*lpSpace != chSpace) + { + *lpstr = chSpace; /* Reset string, abandon ship */ + nFileOffset = PARSE_INVALIDSPACE; + goto FAILURE; + } + } + } + break; + + case chPeriod: + if (nFile == 0) + { + if (*++lpstr == chPeriod) + ++lpstr; + if (!*lpstr) + goto MustBeDir; + + if ((*lpstr != TEXT('\\')) && (*lpstr != TEXT('/'))) + { + nFileOffset = PARSE_INVALIDPERIOD; + goto FAILURE; + } + + ++lpstr; /* Flags are already set */ + } + else if (bExt) + { + nFileOffset = PARSE_INVALIDPERIOD; /* can't have one in ext */ + goto FAILURE; + } + else + { + nExtOffset = 0; + ++lpstr; + bExt = TRUE; + } + break; + + case TEXT('*'): + case TEXT('?'): + if (bUNCPath) + { + nFileOffset = PARSE_INVALIDNETPATH; + goto FAILURE; + } + bWildcard = TRUE; +/* Fall through to normal character processing */ + + default: + if (bExt) + { + if (++nExt == 1) + nExtOffset = lpstr - lpstrFileName; + else if (nExt > 3) + { + nFileOffset = PARSE_EXTENTIONTOOLONG; + goto FAILURE; + } + if ((nNetwork == -1) && (nFile + nExt > 11)) + { + nFileOffset = PARSE_INVALIDNETPATH; + goto FAILURE; + } + } + else if (++nFile == 1) + nFileOffset = lpstr - lpstrFileName; + else if (nFile > 8) + { + /* If it's a server name, it can have 11 characters */ + if (nNetwork != -1) + { + nFileOffset = PARSE_FILETOOLONG; + goto FAILURE; + } + else if (nFile > 11) + { + nFileOffset = PARSE_INVALIDNETPATH; + goto FAILURE; + } + } + +#ifdef WIN32 + lpstr = CharNext(lpstr); +#else + lpstr = AnsiNext(lpstr); +#endif + break; + } + } + +/* Did we start with a double backslash but not have any more slashes? */ + if (nNetwork == -1) + { + nFileOffset = PARSE_INVALIDNETPATH; + goto FAILURE; + } + + if (!nFile) + { +MustBeDir: + nFileOffset = PARSE_DIRECTORYNAME; + goto FAILURE; + } + + if ((*(lpstr - 1) == chPeriod) && /* if true, no extention wanted */ + ( +#ifdef WIN32 + *CharNext(lpstr-2) +#else + *AnsiNext(lpstr-2) +#endif + == chPeriod + )) + *(lpstr - 1) = TEXT('\0'); /* Remove terminating period */ + else if (!nExt) +FAILURE: + nExtOffset = lpstr - lpstrFileName; + + return(MAKELONG(nFileOffset, nExtOffset)); +} + + +/* + * DoesFileExist + * + * Purpose: + * Determines if a file path exists + * + * Parameters: + * lpszFile LPTSTR - file name + * lpOpenBuf OFSTRUCT FAR* - points to the OFSTRUCT structure that + * will receive information about the file when the + * file is first opened. this field is filled by the + * Windows OpenFile API. + * + * Return Value: + * HFILE HFILE_ERROR - file does NOT exist + * file handle (as returned from OpenFile) - file exists + */ +HFILE WINAPI DoesFileExist(LPTSTR lpszFile, OFSTRUCT FAR* lpOpenBuf) +{ + long nRet; + int i; + static TCHAR *arrIllegalNames[] = { + TEXT("LPT1"), + TEXT("LPT2"), + TEXT("LPT3"), + TEXT("COM1"), + TEXT("COM2"), + TEXT("COM3"), + TEXT("COM4"), + TEXT("CON"), + TEXT("AUX"), + TEXT("PRN") + }; + + // Check if file name is syntactically correct. + // (OpenFile sometimes crashes if path is not syntactically correct) + nRet = ParseFile(lpszFile); + if (LOWORD(nRet) < 0) + goto error; + + // Check is the name is an illegal name (eg. the name of a device) + for (i=0; i < (sizeof(arrIllegalNames)/sizeof(arrIllegalNames[0])); i++) { + if (lstrcmpi(lpszFile, arrIllegalNames[i])==0) + goto error; // illegal name FOUND + } + + return OpenFile(lpszFile, lpOpenBuf, OF_EXIST); + +error: + _fmemset(lpOpenBuf, 0, sizeof(OFSTRUCT)); + lpOpenBuf->nErrCode = 0x0002; // File not found + return HFILE_ERROR; +} + diff --git a/private/oleutest/letest/ole2ui/utility.h b/private/oleutest/letest/ole2ui/utility.h new file mode 100644 index 000000000..10b295cd5 --- /dev/null +++ b/private/oleutest/letest/ole2ui/utility.h @@ -0,0 +1,37 @@ +/* + * UTILITY.H + * + * Miscellaneous prototypes and definitions for OLE UI dialogs. + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + + +#ifndef _UTILITY_H_ +#define _UTILITY_H_ + +//Function prototypes +//UTILITY.C +HCURSOR WINAPI HourGlassOn(void); +void WINAPI HourGlassOff(HCURSOR); + +BOOL WINAPI Browse(HWND, LPTSTR, LPTSTR, UINT, UINT, DWORD); +int WINAPI ReplaceCharWithNull(LPTSTR, int); +int WINAPI ErrorWithFile(HWND, HINSTANCE, UINT, LPTSTR, UINT); +HFILE WINAPI DoesFileExist(LPTSTR lpszFile, OFSTRUCT FAR* lpOpenBuf); + + +HICON FAR PASCAL HIconAndSourceFromClass(REFCLSID, LPTSTR, UINT FAR *); +BOOL FAR PASCAL FIconFileFromClass(REFCLSID, LPTSTR, UINT, UINT FAR *); +LPTSTR FAR PASCAL PointerToNthField(LPTSTR, int, TCHAR); +BOOL FAR PASCAL GetAssociatedExecutable(LPTSTR, LPTSTR); +HICON WINAPI HIconFromClass(LPTSTR); +BOOL WINAPI FServerFromClass(LPTSTR, LPTSTR, UINT); +UINT WINAPI UClassFromDescription(LPTSTR, LPTSTR, UINT); +UINT WINAPI UDescriptionFromClass(LPTSTR, LPTSTR, UINT); +BOOL WINAPI FVerbGet(LPTSTR, UINT, LPTSTR); +LPTSTR WINAPI ChopText(HWND hwndStatic, int nWidth, LPTSTR lpch); +void WINAPI OpenFileError(HWND hDlg, UINT nErrCode, LPTSTR lpszFile); + + +#endif //_UTILITY_H_ diff --git a/private/oleutest/letest/ole2ui/verlocal.h b/private/oleutest/letest/ole2ui/verlocal.h new file mode 100644 index 000000000..92b7000c8 --- /dev/null +++ b/private/oleutest/letest/ole2ui/verlocal.h @@ -0,0 +1,54 @@ +/* + * VERLOCAL.H + * + * Version resource file for the OLE 2.0 UI Support DLL. + * + * Copyright (c)1993 Microsoft Corporation, All Rights Reserved. + * + * This file contains the text that needs to be translated in the version + * resource. All of the following variables must be localized: + * + * wLanguage + * szTranslation + * szzCompanyName + * szzProductName + * szzLegalCopyright + */ + +/* wLanguage comes from the table of "langID" values on page 218 of + the Windows 3.1 SDK Programmer's Reference, Volume 4: Resources. + This page is in Chapter 13, "Resource-Definition Statements", in the + description of the "VERSIONINFO" statment. + + For example, + 0x0407 German + 0x0409 U.S. English + 0x0809 U.K. English + 0x040C French + 0x040A Castilian Spanish +*/ +#define wLanguage 0x0409 /* U.S. English */ + +/* The first 4 characters of szTranslation must be the same as wLanguage, + without the "0x". The last 4 characters of szTranslation MUST be + 04E4. Note that any alphabetic characters in szTranslation must + be capitalized. */ +#define szTranslation "040904E4" /* U.S. English */ + + +/* The following szz strings must all end with the two characters "\0" */ +/* Note that the "\251" in szzLegalCopyright stands for the "circle c" + copyright symbol, and it should be left as \251 rather than + substituting the actual ANSI copyright character in the string. */ +#define szzCompanyName "Microsoft Corporation\0" +#define szzFileDescription "Microsoft Windows(TM) OLE 2.0 User Interface Support\0" +#define szzLegalCopyright "Copyright \251 1992-1993 Microsoft Corp. All rights reserved.\0" + +#ifdef PUBLISHER +#define szzProductName "Microsoft Publisher for Windows 2.0\0" +#else +#define szzProductName szzFileDescription +#endif + + +/* DO NOT CHANGE ANY LINES BELOW THIS POINT */ diff --git a/private/oleutest/letest/ole2ui/vgares.bmp b/private/oleutest/letest/ole2ui/vgares.bmp new file mode 100644 index 000000000..496902f9f Binary files /dev/null and b/private/oleutest/letest/ole2ui/vgares.bmp differ diff --git a/private/oleutest/letest/ole2ui/wn_dos.h b/private/oleutest/letest/ole2ui/wn_dos.h new file mode 100644 index 000000000..dbc75a643 --- /dev/null +++ b/private/oleutest/letest/ole2ui/wn_dos.h @@ -0,0 +1,174 @@ +/************************************************************************* +** +** OLE 2.0 Property Set Utilities +** +** wn_dos.h +** +** This file contains file contains data structure defintions, +** function prototypes, constants, etc. for Windows 3.x form of +** DOS calls. This is used by the SUMINFO OLE 2.0 Property Set +** utilities used to manage the Summary Info property set. +** +** (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved +** +*************************************************************************/ + +#ifndef WN_DOS_H +#define WN_DOS_H + +#include + +#define WIN 1 + +#define cbMaxFile 146 //from inc\path.h +#define SEEK_FROM_BEGINNING 0 +#define SEEK_FROM_END 2 +#define chDOSPath ('\\') // FUTURE: not used all places it could be +#define chDOSWildAll '*' /* DOS File name wild card. */ +#define chDOSWildSingle '?' + + + +// Close, seek, delete, rename, flush, get attributes, read, write +/* RPC TEMP +int FCloseOsfnWin(WORD); +#define FCloseOsfn(osfn) FCloseOsfnWin(osfn) +long DwSeekDwWin(WORD,LONG,WORD); +#define DwSeekDw(osfn, dwSeek, bSeekFrom) DwSeekDwWin(osfn, dwSeek, bSeekFrom) +EC EcDeleteSzFfnameWin(char *); +#define EcDeleteSzFfname(szFile) EcDeleteSzFfnameWin(szFile) +EC EcRenameSzFfnameWin(char *,char *); +#define EcRenameSzFfname(szFileCur,szFileNew) EcRenameSzFfnameWin(szFileCur,szFileNew) +int FFlushOsfnWin(int); +#define FFlushOsfn(osfn) FFlushOsfnWin(osfn) +WORD DaGetFileModeSzWin(char *); +#define DaGetFileModeSz(szFile) DaGetFileModeSzWin(szFile) +int CbReadOsfnWin(int, void far *, UINT); +int CbWriteOsfnWin(int, void far *, UINT); +#define CbWriteOsfn(osfn,lpch,cbWrite) CbWriteOsfnWin(osfn,lpch,cbWrite) +*/ +#define WinOpenFile(sz,ofs,n) OpenFile(sz,ofs,n) +#define SeekHfile(f,off,kind) _llseek(f,off,kind) +#define CbReadOsfn(osfn,lpch,cbRead) CbReadOsfnWin(osfn,lpch,cbRead) +#define CbReadHfile(f,buf,n) _lread(f,buf,n) +#define CbReadOsfnWin(f,buf,n) CbReadHfile(f,buf,n) +#define EcFindFirst4dm(a,b,c) _dos_findfirst((const char *)(b),c,(struct find_t*)a) +#define EcFindNext4dm(a) _dos_findnext((struct find_t*)a) +#define FHfileToSffsDate(handle,date,time) _dos_getftime(handle, (unsigned *)(date), (unsigned *)(time)) +#define SeekHfile(f, off, kind) _llseek(f,off,kind) + +/* buffer structure to be used with EcFindFirst() and EcFindNext() */ +typedef struct _SFFS + { /* Search Find File Structure */ + uchar buff[21]; // dos search info + uchar wAttr; + union + { + unsigned short timeVariable; /*RPC47*/ + BF time:16; + struct + { + BF sec : 5; + BF mint: 6; + BF hr : 5; + }; + }; + union + { + unsigned short dateVariable; + BF date:16; + struct + { + BF dom : 5; + BF mon : 4; + BF yr : 7; + }; + }; + ulong cbFile; + uchar szFileName[13]; + } SFFS; + +// find first file/find next file +#define PszFromPsffs(psffs) ((psffs)->szFileName) +#define CopySzFilePsffs(psffs,sz) OemToAnsi((char HUGE *)&((psffs)->szFileName[0]),(char HUGE *)(sz)) +#define CbSzFilePsffs(psffs) CbSz((psffs)->szFileName) +#define CbFileSizePsffs(psffs) (psffs)->cbFile +#define AttribPsffs(psffs) (psffs)->wAttr +#define EcFindFirstCore(psffs, sz, wAttr) EcFindFirst(psffs, sz, wAttr) /*RPC22*/ +#define FDotPsffs(psffs) ((psffs)->szFileName[0]=='.') /*RPC23*/ +#define AppendSzWild(sz) {int i=_fstrlen((char FAR *)(sz)); sz[i]='*'; sz[i+1]='.'; sz[i+2]='*'; sz[i+3]='\0';} +// disk free space + +unsigned long LcbDiskFreeSpaceWin(int); +#define LcbDiskFreeSpace(chDrive) LcbDiskFreeSpaceWin(chDrive) + +// date and time /*RPC39*/ +/* +typedef struct _TIM { // Time structure returned by OsTime + CHAR minutes, hour, hsec, sec; + } TIM; + +typedef struct _DAT { // Date structure returned by OsDate + int year; + CHAR month, day, dayOfWeek; + } DAT; +*/ +#define TIM dostime_t /*RPC39*/ +#define DAT dosdate_t +#define OsTimeWin(TIM) _dos_gettime(TIM) +#define OsDateWin(DAT) _dos_getdate(DAT) + + +/* DOS File Attributes */ +#define DA_NORMAL 0x00 +#define DA_READONLY 0x01 +#define DA_HIDDEN 0x02 +#define DA_SYSTEM 0x04 +#define DA_VOLUME 0x08 +#define DA_SUBDIR 0x10 +#define DA_ARCHIVE 0x20 +#define DA_NIL 0xFFFF /* Error DA */ +#define dosxSharing 32 /* Extended error code for sharing viol. */ +#define nErrNoAcc 5 /* OpenFile error code for Access Denied */ +#define nErrFnf 2 /* OpenFile error code for File Not Found */ + +/* Components of the Open mode for OpenSzFfname (DOS FUNC 3DH) */ +#define MASK_fINH 0x80 +#define MASK_bSHARE 0x70 +#define MASK_bACCESS 0x07 + +#define bSHARE_DENYRDWR 0x10 +#define bSHARE_DENYWR 0x20 +#define bSHARE_DENYNONE 0x40 + +/* Seek-from type codes passed to DOS function 42H */ + +#define SF_BEGINNING 0 /* Seek from beginning of file */ +#define SF_CURRENT 1 /* Seek from current file pointer */ +#define SF_END 2 /* Seek from end of file */ + + +typedef struct _DOSDTTM /* DOS DaTe TiMe */ + { + union + { + long lDOSDttm; + struct + { + BF day: 5; + BF month: 4; + BF year: 7; + BF sec: 5; + BF mint: 6; + BF hours: 5; + } S1; + } U1; + } DOSDTTM; + +int FOsfnIsFile(int); + +void DateStamp(int, LONG *, int); +int DosxError(void); +int ShellExec(int, int); + +#endif //WN_DOS_H diff --git a/private/oleutest/letest/outline/classfac.c b/private/oleutest/letest/outline/classfac.c new file mode 100644 index 000000000..cf3070227 --- /dev/null +++ b/private/oleutest/letest/outline/classfac.c @@ -0,0 +1,219 @@ +/************************************************************************* +** +** OLE 2 Sample Code +** +** classfac.c +** +** This file contains the implementation for IClassFactory for both the +** server and the client version of the OUTLINE app. +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + +#include "outline.h" + +OLEDBGDATA + +extern LPOUTLINEAPP g_lpApp; + + +/* OLE2NOTE: this object illustrates the manner in which to statically +** (compile-time) initialize an interface VTBL. +*/ +static IClassFactoryVtbl g_AppClassFactoryVtbl = { + AppClassFactory_QueryInterface, + AppClassFactory_AddRef, + AppClassFactory_Release, + AppClassFactory_CreateInstance, + AppClassFactory_LockServer +}; + + +/* AppClassFactory_Create +** ---------------------- +** create an instance of APPCLASSFACTORY. +** NOTE: type of pointer returned is an IClassFactory* interface ptr. +** the returned pointer can be directly passed to +** CoRegisterClassObject and released later by calling the +** Release method of the interface. +*/ +LPCLASSFACTORY WINAPI AppClassFactory_Create(void) +{ + LPAPPCLASSFACTORY lpAppClassFactory; + LPMALLOC lpMalloc; + + if (CoGetMalloc(MEMCTX_TASK, (LPMALLOC FAR*)&lpMalloc) != NOERROR) + return NULL; + + lpAppClassFactory = (LPAPPCLASSFACTORY)lpMalloc->lpVtbl->Alloc( + lpMalloc, (sizeof(APPCLASSFACTORY))); + lpMalloc->lpVtbl->Release(lpMalloc); + if (! lpAppClassFactory) return NULL; + + lpAppClassFactory->m_lpVtbl = &g_AppClassFactoryVtbl; + lpAppClassFactory->m_cRef = 1; +#if defined( _DEBUG ) + lpAppClassFactory->m_cSvrLock = 0; +#endif + return (LPCLASSFACTORY)lpAppClassFactory; +} + + +/************************************************************************* +** OleApp::IClassFactory interface implementation +*************************************************************************/ + +STDMETHODIMP AppClassFactory_QueryInterface( + LPCLASSFACTORY lpThis, REFIID riid, LPVOID FAR* ppvObj) +{ + LPAPPCLASSFACTORY lpAppClassFactory = (LPAPPCLASSFACTORY)lpThis; + SCODE scode; + + // Two interfaces supported: IUnknown, IClassFactory + + if (IsEqualIID(riid, &IID_IClassFactory) || + IsEqualIID(riid, &IID_IUnknown)) { + lpAppClassFactory->m_cRef++; // A pointer to this object is returned + *ppvObj = lpThis; + scode = S_OK; + } + else { // unsupported interface + *ppvObj = NULL; + scode = E_NOINTERFACE; + } + + return ResultFromScode(scode); +} + + +STDMETHODIMP_(ULONG) AppClassFactory_AddRef(LPCLASSFACTORY lpThis) +{ + LPAPPCLASSFACTORY lpAppClassFactory = (LPAPPCLASSFACTORY)lpThis; + return ++lpAppClassFactory->m_cRef; +} + +STDMETHODIMP_(ULONG) AppClassFactory_Release(LPCLASSFACTORY lpThis) +{ + LPAPPCLASSFACTORY lpAppClassFactory = (LPAPPCLASSFACTORY)lpThis; + LPMALLOC lpMalloc; + + if (--lpAppClassFactory->m_cRef != 0) // Still used by others + return lpAppClassFactory->m_cRef; + + // Free storage + if (CoGetMalloc(MEMCTX_TASK, (LPMALLOC FAR*)&lpMalloc) != NOERROR) + return 0; + + lpMalloc->lpVtbl->Free(lpMalloc, lpAppClassFactory); + lpMalloc->lpVtbl->Release(lpMalloc); + return 0; +} + + +STDMETHODIMP AppClassFactory_CreateInstance ( + LPCLASSFACTORY lpThis, + LPUNKNOWN lpUnkOuter, + REFIID riid, + LPVOID FAR* lplpvObj +) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + LPOLEDOC lpOleDoc; + HRESULT hrErr; + + OLEDBG_BEGIN2("AppClassFactory_CreateInstance\r\n") + + /* OLE2NOTE: we must make sure to set all out parameters to NULL. */ + *lplpvObj = NULL; + + /********************************************************************* + ** OLE2NOTE: this is an SDI app; it can only create and support one + ** instance. After the instance is created, the OLE libraries + ** should not call CreateInstance again. it is a good practise + ** to specifically guard against this. + *********************************************************************/ + + if (lpOutlineApp->m_lpDoc != NULL) + return ResultFromScode(E_UNEXPECTED); + + /* OLE2NOTE: create a new document instance. by the time we return + ** from this method the document's refcnt must be 1. + */ + lpOutlineApp->m_lpDoc = OutlineApp_CreateDoc(lpOutlineApp, FALSE); + lpOleDoc = (LPOLEDOC)lpOutlineApp->m_lpDoc; + if (! lpOleDoc) { + OLEDBG_END2 + return ResultFromScode(E_OUTOFMEMORY); + } + + /* OLE2NOTE: retrieve pointer to requested interface. the ref cnt + ** of the object after OutlineApp_CreateDoc is 0. this call to + ** QueryInterface will increment the refcnt to 1. the object + ** returned from IClassFactory::CreateInstance should have a + ** refcnt of 1 and be controlled by the caller. If the caller + ** releases the document, the document should be destroyed. + */ + hrErr = OleDoc_QueryInterface(lpOleDoc, riid, lplpvObj); + + OLEDBG_END2 + return hrErr; +} + + +STDMETHODIMP AppClassFactory_LockServer ( + LPCLASSFACTORY lpThis, + BOOL fLock +) +{ + LPAPPCLASSFACTORY lpAppClassFactory = (LPAPPCLASSFACTORY)lpThis; + LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; + HRESULT hrErr; + OLEDBG_BEGIN2("AppClassFactory_LockServer\r\n") + +#if defined( _DEBUG ) + if (fLock) { + ++lpAppClassFactory->m_cSvrLock; + OleDbgOutRefCnt3( + "AppClassFactory_LockServer: cLock++\r\n", + lpAppClassFactory, lpAppClassFactory->m_cSvrLock); + } else { + + /* OLE2NOTE: when there are no open documents and the app is not + ** under the control of the user and there are no outstanding + ** locks on the app, then revoke our ClassFactory to enable the + ** app to shut down. + */ + --lpAppClassFactory->m_cSvrLock; + OleDbgAssertSz (lpAppClassFactory->m_cSvrLock >= 0, + "AppClassFactory_LockServer(FALSE) called with cLock == 0" + ); + + if (lpAppClassFactory->m_cSvrLock == 0) { + OleDbgOutRefCnt2( + "AppClassFactory_LockServer: UNLOCKED\r\n", + lpAppClassFactory, lpAppClassFactory->m_cSvrLock); + } else { + OleDbgOutRefCnt3( + "AppClassFactory_LockServer: cLock--\r\n", + lpAppClassFactory, lpAppClassFactory->m_cSvrLock); + } + } +#endif // _DEBUG + /* OLE2NOTE: in order to hold the application alive we call + ** CoLockObjectExternal to add a strong reference to our app + ** object. this will keep the app alive when all other external + ** references release us. if the user issues File.Exit the + ** application will shut down in any case ignoring any + ** outstanding LockServer locks because CoDisconnectObject is + ** called in OleApp_CloseAllDocsAndExitCommand. this will + ** forceably break any existing strong reference counts + ** including counts that we add ourselves by calling + ** CoLockObjectExternal and guarantee that the App object gets + ** its final release (ie. cRefs goes to 0). + */ + hrErr = OleApp_Lock(lpOleApp, fLock, TRUE /* fLastUnlockReleases */); + + OLEDBG_END2 + return hrErr; +} diff --git a/private/oleutest/letest/outline/classfac.h b/private/oleutest/letest/outline/classfac.h new file mode 100644 index 000000000..cf3070227 --- /dev/null +++ b/private/oleutest/letest/outline/classfac.h @@ -0,0 +1,219 @@ +/************************************************************************* +** +** OLE 2 Sample Code +** +** classfac.c +** +** This file contains the implementation for IClassFactory for both the +** server and the client version of the OUTLINE app. +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + +#include "outline.h" + +OLEDBGDATA + +extern LPOUTLINEAPP g_lpApp; + + +/* OLE2NOTE: this object illustrates the manner in which to statically +** (compile-time) initialize an interface VTBL. +*/ +static IClassFactoryVtbl g_AppClassFactoryVtbl = { + AppClassFactory_QueryInterface, + AppClassFactory_AddRef, + AppClassFactory_Release, + AppClassFactory_CreateInstance, + AppClassFactory_LockServer +}; + + +/* AppClassFactory_Create +** ---------------------- +** create an instance of APPCLASSFACTORY. +** NOTE: type of pointer returned is an IClassFactory* interface ptr. +** the returned pointer can be directly passed to +** CoRegisterClassObject and released later by calling the +** Release method of the interface. +*/ +LPCLASSFACTORY WINAPI AppClassFactory_Create(void) +{ + LPAPPCLASSFACTORY lpAppClassFactory; + LPMALLOC lpMalloc; + + if (CoGetMalloc(MEMCTX_TASK, (LPMALLOC FAR*)&lpMalloc) != NOERROR) + return NULL; + + lpAppClassFactory = (LPAPPCLASSFACTORY)lpMalloc->lpVtbl->Alloc( + lpMalloc, (sizeof(APPCLASSFACTORY))); + lpMalloc->lpVtbl->Release(lpMalloc); + if (! lpAppClassFactory) return NULL; + + lpAppClassFactory->m_lpVtbl = &g_AppClassFactoryVtbl; + lpAppClassFactory->m_cRef = 1; +#if defined( _DEBUG ) + lpAppClassFactory->m_cSvrLock = 0; +#endif + return (LPCLASSFACTORY)lpAppClassFactory; +} + + +/************************************************************************* +** OleApp::IClassFactory interface implementation +*************************************************************************/ + +STDMETHODIMP AppClassFactory_QueryInterface( + LPCLASSFACTORY lpThis, REFIID riid, LPVOID FAR* ppvObj) +{ + LPAPPCLASSFACTORY lpAppClassFactory = (LPAPPCLASSFACTORY)lpThis; + SCODE scode; + + // Two interfaces supported: IUnknown, IClassFactory + + if (IsEqualIID(riid, &IID_IClassFactory) || + IsEqualIID(riid, &IID_IUnknown)) { + lpAppClassFactory->m_cRef++; // A pointer to this object is returned + *ppvObj = lpThis; + scode = S_OK; + } + else { // unsupported interface + *ppvObj = NULL; + scode = E_NOINTERFACE; + } + + return ResultFromScode(scode); +} + + +STDMETHODIMP_(ULONG) AppClassFactory_AddRef(LPCLASSFACTORY lpThis) +{ + LPAPPCLASSFACTORY lpAppClassFactory = (LPAPPCLASSFACTORY)lpThis; + return ++lpAppClassFactory->m_cRef; +} + +STDMETHODIMP_(ULONG) AppClassFactory_Release(LPCLASSFACTORY lpThis) +{ + LPAPPCLASSFACTORY lpAppClassFactory = (LPAPPCLASSFACTORY)lpThis; + LPMALLOC lpMalloc; + + if (--lpAppClassFactory->m_cRef != 0) // Still used by others + return lpAppClassFactory->m_cRef; + + // Free storage + if (CoGetMalloc(MEMCTX_TASK, (LPMALLOC FAR*)&lpMalloc) != NOERROR) + return 0; + + lpMalloc->lpVtbl->Free(lpMalloc, lpAppClassFactory); + lpMalloc->lpVtbl->Release(lpMalloc); + return 0; +} + + +STDMETHODIMP AppClassFactory_CreateInstance ( + LPCLASSFACTORY lpThis, + LPUNKNOWN lpUnkOuter, + REFIID riid, + LPVOID FAR* lplpvObj +) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + LPOLEDOC lpOleDoc; + HRESULT hrErr; + + OLEDBG_BEGIN2("AppClassFactory_CreateInstance\r\n") + + /* OLE2NOTE: we must make sure to set all out parameters to NULL. */ + *lplpvObj = NULL; + + /********************************************************************* + ** OLE2NOTE: this is an SDI app; it can only create and support one + ** instance. After the instance is created, the OLE libraries + ** should not call CreateInstance again. it is a good practise + ** to specifically guard against this. + *********************************************************************/ + + if (lpOutlineApp->m_lpDoc != NULL) + return ResultFromScode(E_UNEXPECTED); + + /* OLE2NOTE: create a new document instance. by the time we return + ** from this method the document's refcnt must be 1. + */ + lpOutlineApp->m_lpDoc = OutlineApp_CreateDoc(lpOutlineApp, FALSE); + lpOleDoc = (LPOLEDOC)lpOutlineApp->m_lpDoc; + if (! lpOleDoc) { + OLEDBG_END2 + return ResultFromScode(E_OUTOFMEMORY); + } + + /* OLE2NOTE: retrieve pointer to requested interface. the ref cnt + ** of the object after OutlineApp_CreateDoc is 0. this call to + ** QueryInterface will increment the refcnt to 1. the object + ** returned from IClassFactory::CreateInstance should have a + ** refcnt of 1 and be controlled by the caller. If the caller + ** releases the document, the document should be destroyed. + */ + hrErr = OleDoc_QueryInterface(lpOleDoc, riid, lplpvObj); + + OLEDBG_END2 + return hrErr; +} + + +STDMETHODIMP AppClassFactory_LockServer ( + LPCLASSFACTORY lpThis, + BOOL fLock +) +{ + LPAPPCLASSFACTORY lpAppClassFactory = (LPAPPCLASSFACTORY)lpThis; + LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; + HRESULT hrErr; + OLEDBG_BEGIN2("AppClassFactory_LockServer\r\n") + +#if defined( _DEBUG ) + if (fLock) { + ++lpAppClassFactory->m_cSvrLock; + OleDbgOutRefCnt3( + "AppClassFactory_LockServer: cLock++\r\n", + lpAppClassFactory, lpAppClassFactory->m_cSvrLock); + } else { + + /* OLE2NOTE: when there are no open documents and the app is not + ** under the control of the user and there are no outstanding + ** locks on the app, then revoke our ClassFactory to enable the + ** app to shut down. + */ + --lpAppClassFactory->m_cSvrLock; + OleDbgAssertSz (lpAppClassFactory->m_cSvrLock >= 0, + "AppClassFactory_LockServer(FALSE) called with cLock == 0" + ); + + if (lpAppClassFactory->m_cSvrLock == 0) { + OleDbgOutRefCnt2( + "AppClassFactory_LockServer: UNLOCKED\r\n", + lpAppClassFactory, lpAppClassFactory->m_cSvrLock); + } else { + OleDbgOutRefCnt3( + "AppClassFactory_LockServer: cLock--\r\n", + lpAppClassFactory, lpAppClassFactory->m_cSvrLock); + } + } +#endif // _DEBUG + /* OLE2NOTE: in order to hold the application alive we call + ** CoLockObjectExternal to add a strong reference to our app + ** object. this will keep the app alive when all other external + ** references release us. if the user issues File.Exit the + ** application will shut down in any case ignoring any + ** outstanding LockServer locks because CoDisconnectObject is + ** called in OleApp_CloseAllDocsAndExitCommand. this will + ** forceably break any existing strong reference counts + ** including counts that we add ourselves by calling + ** CoLockObjectExternal and guarantee that the App object gets + ** its final release (ie. cRefs goes to 0). + */ + hrErr = OleApp_Lock(lpOleApp, fLock, TRUE /* fLastUnlockReleases */); + + OLEDBG_END2 + return hrErr; +} diff --git a/private/oleutest/letest/outline/clipbrd.c b/private/oleutest/letest/outline/clipbrd.c new file mode 100644 index 000000000..a6e7effa3 --- /dev/null +++ b/private/oleutest/letest/outline/clipbrd.c @@ -0,0 +1,3401 @@ +/************************************************************************* +** +** OLE 2 Sample Code +** +** clipbrd.c +** +** This file contains the major interfaces, methods and related support +** functions for implementing clipboard data transfer. The code +** contained in this file is used by BOTH the Container and Server +** (Object) versions of the Outline sample code. +** (see file dragdrop.c for Drag/Drop support implementation) +** +** OleDoc Object +** exposed interfaces: +** IDataObject +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + +#include "outline.h" + +OLEDBGDATA + +extern LPOUTLINEAPP g_lpApp; + +// REVIEW: should use string resource for messages +char ErrMsgPasting[] = "Could not paste data from clipboard!"; +char ErrMsgBadFmt[] = "Invalid format selected!"; +char ErrMsgPasteFailed[] = "Could not paste data from clipboard!"; +char ErrMsgClipboardChanged[] = "Contents of clipboard have changed!\r\nNo paste performed."; + + + +/************************************************************************* +** OleDoc::IDataObject interface implementation +*************************************************************************/ + +// IDataObject::QueryInterface +STDMETHODIMP OleDoc_DataObj_QueryInterface ( + LPDATAOBJECT lpThis, + REFIID riid, + LPVOID FAR* lplpvObj +) +{ + LPOLEDOC lpOleDoc = ((struct CDocDataObjectImpl FAR*)lpThis)->lpOleDoc; + + return OleDoc_QueryInterface((LPOLEDOC)lpOleDoc, riid, lplpvObj); +} + + +// IDataObject::AddRef +STDMETHODIMP_(ULONG) OleDoc_DataObj_AddRef(LPDATAOBJECT lpThis) +{ + LPOLEDOC lpOleDoc = ((struct CDocDataObjectImpl FAR*)lpThis)->lpOleDoc; + + OleDbgAddRefMethod(lpThis, "IDataObject"); + + return OleDoc_AddRef((LPOLEDOC)lpOleDoc); +} + + +// IDataObject::Release +STDMETHODIMP_(ULONG) OleDoc_DataObj_Release (LPDATAOBJECT lpThis) +{ + LPOLEDOC lpOleDoc = ((struct CDocDataObjectImpl FAR*)lpThis)->lpOleDoc; + + OleDbgReleaseMethod(lpThis, "IDataObject"); + + return OleDoc_Release((LPOLEDOC)lpOleDoc); +} + + +// IDataObject::GetData +STDMETHODIMP OleDoc_DataObj_GetData ( + LPDATAOBJECT lpThis, + LPFORMATETC lpFormatetc, + LPSTGMEDIUM lpMedium +) +{ + LPOLEDOC lpOleDoc = ((struct CDocDataObjectImpl FAR*)lpThis)->lpOleDoc; + HRESULT hrErr; + + OLEDBG_BEGIN2("OleDoc_DataObj_GetData\r\n") + +#if defined( OLE_SERVER ) + // Call OLE Server specific version of this function + hrErr = ServerDoc_GetData((LPSERVERDOC)lpOleDoc, lpFormatetc, lpMedium); +#endif +#if defined( OLE_CNTR ) + // Call OLE Container specific version of this function + hrErr = ContainerDoc_GetData( + (LPCONTAINERDOC)lpOleDoc, + lpFormatetc, + lpMedium + ); +#endif + + OLEDBG_END2 + return hrErr; +} + + +// IDataObject::GetDataHere +STDMETHODIMP OleDoc_DataObj_GetDataHere ( + LPDATAOBJECT lpThis, + LPFORMATETC lpFormatetc, + LPSTGMEDIUM lpMedium +) +{ + LPOLEDOC lpOleDoc = ((struct CDocDataObjectImpl FAR*)lpThis)->lpOleDoc; + HRESULT hrErr; + + OLEDBG_BEGIN2("OleDoc_DataObj_GetDataHere\r\n") + +#if defined( OLE_SERVER ) + // Call OLE Server specific version of this function + hrErr = ServerDoc_GetDataHere( + (LPSERVERDOC)lpOleDoc, + lpFormatetc, + lpMedium + ); +#endif +#if defined( OLE_CNTR ) + // Call OLE Container specific version of this function + hrErr = ContainerDoc_GetDataHere( + (LPCONTAINERDOC)lpOleDoc, + lpFormatetc, + lpMedium + ); +#endif + + OLEDBG_END2 + return hrErr; +} + + +// IDataObject::QueryGetData +STDMETHODIMP OleDoc_DataObj_QueryGetData ( + LPDATAOBJECT lpThis, + LPFORMATETC lpFormatetc +) +{ + LPOLEDOC lpOleDoc = ((struct CDocDataObjectImpl FAR*)lpThis)->lpOleDoc; + HRESULT hrErr; + OLEDBG_BEGIN2("OleDoc_DataObj_QueryGetData\r\n"); + +#if defined( OLE_SERVER ) + // Call OLE Server specific version of this function + hrErr = ServerDoc_QueryGetData((LPSERVERDOC)lpOleDoc, lpFormatetc); +#endif +#if defined( OLE_CNTR ) + // Call OLE Container specific version of this function + hrErr = ContainerDoc_QueryGetData((LPCONTAINERDOC)lpOleDoc, lpFormatetc); +#endif + + OLEDBG_END2 + return hrErr; +} + + +// IDataObject::GetCanonicalFormatEtc +STDMETHODIMP OleDoc_DataObj_GetCanonicalFormatEtc( + LPDATAOBJECT lpThis, + LPFORMATETC lpformatetc, + LPFORMATETC lpformatetcOut +) +{ + HRESULT hrErr; + OleDbgOut2("OleDoc_DataObj_GetCanonicalFormatEtc\r\n"); + + if (!lpformatetcOut) + return ResultFromScode(E_INVALIDARG); + + /* OLE2NOTE: we must make sure to set all out parameters to NULL. */ + lpformatetcOut->ptd = NULL; + + if (!lpformatetc) + return ResultFromScode(E_INVALIDARG); + + // OLE2NOTE: we must validate that the format requested is supported + if ((hrErr=lpThis->lpVtbl->QueryGetData(lpThis,lpformatetc)) != NOERROR) + return hrErr; + + /* OLE2NOTE: an app that is insensitive to target device (as the + ** Outline Sample is) should fill in the lpformatOut parameter + ** but NULL out the "ptd" field; it should return NOERROR if the + ** input formatetc->ptd what non-NULL. this tells the caller + ** that it is NOT necessary to maintain a separate screen + ** rendering and printer rendering. if should return + ** DATA_S_SAMEFORMATETC if the input and output formatetc's are + ** identical. + */ + + *lpformatetcOut = *lpformatetc; + if (lpformatetc->ptd == NULL) + return ResultFromScode(DATA_S_SAMEFORMATETC); + else { + lpformatetcOut->ptd = NULL; + return NOERROR; + } +} + + +// IDataObject::SetData +STDMETHODIMP OleDoc_DataObj_SetData ( + LPDATAOBJECT lpThis, + LPFORMATETC lpFormatetc, + LPSTGMEDIUM lpMedium, + BOOL fRelease +) +{ + LPOLEDOC lpOleDoc = ((struct CDocDataObjectImpl FAR*)lpThis)->lpOleDoc; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc; + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + SCODE sc = S_OK; + OLEDBG_BEGIN2("OleDoc_DataObj_SetData\r\n") + + /* OLE2NOTE: a document that is used to transfer data (either via + ** the clipboard or drag/drop) does NOT accept SetData on ANY + ** format! + */ + if (lpOutlineDoc->m_fDataTransferDoc) { + sc = E_FAIL; + goto error; + } + +#if defined( OLE_SERVER ) + if (lpFormatetc->cfFormat == lpOutlineApp->m_cfOutline) { + OLEDBG_BEGIN2("ServerDoc_SetData: CF_OUTLINE\r\n") + OutlineDoc_SetRedraw ( lpOutlineDoc, FALSE ); + OutlineDoc_ClearAllLines(lpOutlineDoc); + OutlineDoc_PasteOutlineData(lpOutlineDoc,lpMedium->hGlobal,-1); + OutlineDoc_SetRedraw ( lpOutlineDoc, TRUE ); + OLEDBG_END3 + } else if (lpFormatetc->cfFormat == CF_TEXT) { + OLEDBG_BEGIN2("ServerDoc_SetData: CF_TEXT\r\n") + OutlineDoc_SetRedraw ( lpOutlineDoc, FALSE ); + OutlineDoc_ClearAllLines(lpOutlineDoc); + OutlineDoc_PasteTextData(lpOutlineDoc,lpMedium->hGlobal,-1); + OutlineDoc_SetRedraw ( lpOutlineDoc, TRUE ); + OLEDBG_END3 + } else { + sc = DV_E_FORMATETC; + } +#endif // OLE_SERVER +#if defined( OLE_CNTR ) + /* the Container-Only version of Outline does NOT offer + ** IDataObject interface from its User documents. this is + ** required by objects which can be embedded or linked. the + ** Container-only app only allows linking to its contained + ** objects, NOT the data of the container itself. + */ + OleDbgAssertSz(0, "User documents do NOT support IDataObject\r\n"); + sc = E_NOTIMPL; +#endif // OLE_CNTR + +error: + + /* OLE2NOTE: if fRelease==TRUE, then we must take + ** responsibility to release the lpMedium. we should only do + ** this if we are going to return NOERROR. if we do NOT + ** accept the data, then we should NOT release the lpMedium. + ** if fRelease==FALSE, then the caller retains ownership of + ** the data. + */ + if (sc == S_OK && fRelease) + ReleaseStgMedium(lpMedium); + + OLEDBG_END2 + return ResultFromScode(sc); + +} + + +// IDataObject::EnumFormatEtc +STDMETHODIMP OleDoc_DataObj_EnumFormatEtc( + LPDATAOBJECT lpThis, + DWORD dwDirection, + LPENUMFORMATETC FAR* lplpenumFormatEtc +) +{ + LPOLEDOC lpOleDoc=((struct CDocDataObjectImpl FAR*)lpThis)->lpOleDoc; + HRESULT hrErr; + + OLEDBG_BEGIN2("OleDoc_DataObj_EnumFormatEtc\r\n") + + /* OLE2NOTE: we must make sure to set all out parameters to NULL. */ + *lplpenumFormatEtc = NULL; + +#if defined( OLE_SERVER ) + /* OLE2NOTE: a user document only needs to enumerate the static list + ** of formats that are registered for our app in the + ** registration database. OLE provides a default enumerator + ** which enumerates from the registration database. this default + ** enumerator is requested by returning OLE_S_USEREG. it is NOT + ** required that a user document (ie. non-DataTransferDoc) + ** enumerate the OLE formats: CF_LINKSOURCE, CF_EMBEDSOURCE, or + ** CF_EMBEDDEDOBJECT. + ** + ** An object implemented as a server EXE (as this sample + ** is) may simply return OLE_S_USEREG to instruct the OLE + ** DefHandler to call the OleReg* helper API which uses info in + ** the registration database. Alternatively, the OleRegEnumFormatEtc + ** API may be called directly. Objects implemented as a server + ** DLL may NOT return OLE_S_USEREG; they must call the OleReg* + ** API or provide their own implementation. For EXE based + ** objects it is more efficient to return OLE_S_USEREG, because + ** in then the enumerator is instantiated in the callers + ** process space and no LRPC remoting is required. + */ + if (! ((LPOUTLINEDOC)lpOleDoc)->m_fDataTransferDoc) + return ResultFromScode(OLE_S_USEREG); + + // Call OLE Server specific version of this function + hrErr = ServerDoc_EnumFormatEtc( + (LPSERVERDOC)lpOleDoc, + dwDirection, + lplpenumFormatEtc + ); +#endif +#if defined( OLE_CNTR ) + // Call OLE Container specific version of this function + hrErr = ContainerDoc_EnumFormatEtc( + (LPCONTAINERDOC)lpOleDoc, + dwDirection, + lplpenumFormatEtc + ); +#endif + + OLEDBG_END2 + return hrErr; +} + + +// IDataObject::DAdvise +STDMETHODIMP OleDoc_DataObj_DAdvise( + LPDATAOBJECT lpThis, + FORMATETC FAR* lpFormatetc, + DWORD advf, + LPADVISESINK lpAdvSink, + DWORD FAR* lpdwConnection +) +{ + LPOLEDOC lpOleDoc=((struct CDocDataObjectImpl FAR*)lpThis)->lpOleDoc; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc; + SCODE sc; + + OLEDBG_BEGIN2("OleDoc_DataObj_DAdvise\r\n") + + /* OLE2NOTE: we must make sure to set all out parameters to NULL. */ + *lpdwConnection = 0; + + /* OLE2NOTE: a document that is used to transfer data (either via + ** the clipboard or drag/drop) does NOT support Advise notifications. + */ + if (lpOutlineDoc->m_fDataTransferDoc) { + sc = OLE_E_ADVISENOTSUPPORTED; + goto error; + } + +#if defined( OLE_SERVER ) + { + HRESULT hrErr; + LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOleDoc; + + /* OLE2NOTE: we should validate if the caller is setting up an + ** Advise for a data type that we support. we must + ** explicitly allow an advise for the "wildcard" advise. + */ + if ( !( lpFormatetc->cfFormat == 0 && + lpFormatetc->ptd == NULL && + lpFormatetc->dwAspect == -1L && + lpFormatetc->lindex == -1L && + lpFormatetc->tymed == -1L) && + (hrErr = OleDoc_DataObj_QueryGetData(lpThis, lpFormatetc)) + != NOERROR) { + sc = GetScode(hrErr); + goto error; + } + + if (lpServerDoc->m_OleDoc.m_fObjIsClosing) + { + // We don't accept any more Advise's once we're closing + sc = OLE_E_ADVISENOTSUPPORTED; + goto error; + } + + if (lpServerDoc->m_lpDataAdviseHldr == NULL && + CreateDataAdviseHolder(&lpServerDoc->m_lpDataAdviseHldr) + != NOERROR) { + sc = E_OUTOFMEMORY; + goto error; + } + + OLEDBG_BEGIN2("IDataAdviseHolder::Advise called\r\n"); + hrErr = lpServerDoc->m_lpDataAdviseHldr->lpVtbl->Advise( + lpServerDoc->m_lpDataAdviseHldr, + (LPDATAOBJECT)&lpOleDoc->m_DataObject, + lpFormatetc, + advf, + lpAdvSink, + lpdwConnection + ); + OLEDBG_END2 + + OLEDBG_END2 + return hrErr; + } +#endif // OLE_SVR +#if defined( OLE_CNTR ) + { + /* the Container-Only version of Outline does NOT offer + ** IDataObject interface from its User documents. this is + ** required by objects which can be embedded or linked. the + ** Container-only app only allows linking to its contained + ** objects, NOT the data of the container itself. + */ + OleDbgAssertSz(0, "User documents do NOT support IDataObject\r\n"); + sc = E_NOTIMPL; + goto error; + } +#endif // OLE_CNTR + +error: + OLEDBG_END2 + return ResultFromScode(sc); +} + + + +// IDataObject::DUnadvise +STDMETHODIMP OleDoc_DataObj_DUnadvise(LPDATAOBJECT lpThis, DWORD dwConnection) +{ + LPOLEDOC lpOleDoc=((struct CDocDataObjectImpl FAR*)lpThis)->lpOleDoc; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc; + SCODE sc; + + OLEDBG_BEGIN2("OleDoc_DataObj_DUnadvise\r\n") + + /* OLE2NOTE: a document that is used to transfer data (either via + ** the clipboard or drag/drop) does NOT support Advise notifications. + */ + if (lpOutlineDoc->m_fDataTransferDoc) { + sc = OLE_E_ADVISENOTSUPPORTED; + goto error; + } + +#if defined( OLE_SERVER ) + { + LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOleDoc; + HRESULT hrErr; + + if (lpServerDoc->m_lpDataAdviseHldr == NULL) { + sc = E_FAIL; + goto error; + } + + OLEDBG_BEGIN2("IDataAdviseHolder::Unadvise called\r\n"); + hrErr = lpServerDoc->m_lpDataAdviseHldr->lpVtbl->Unadvise( + lpServerDoc->m_lpDataAdviseHldr, + dwConnection + ); + OLEDBG_END2 + + OLEDBG_END2 + return hrErr; + } +#endif +#if defined( OLE_CNTR ) + { + /* the Container-Only version of Outline does NOT offer + ** IDataObject interface from its User documents. this is + ** required by objects which can be embedded or linked. the + ** Container-only app only allows linking to its contained + ** objects, NOT the data of the container itself. + */ + OleDbgAssertSz(0, "User documents do NOT support IDataObject\r\n"); + sc = E_NOTIMPL; + goto error; + } +#endif + +error: + OLEDBG_END2 + return ResultFromScode(sc); +} + + +// IDataObject::EnumDAdvise +STDMETHODIMP OleDoc_DataObj_EnumDAdvise( + LPDATAOBJECT lpThis, + LPENUMSTATDATA FAR* lplpenumAdvise +) +{ + LPOLEDOC lpOleDoc=((struct CDocDataObjectImpl FAR*)lpThis)->lpOleDoc; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc; + SCODE sc; + + OLEDBG_BEGIN2("OleDoc_DataObj_EnumDAdvise\r\n") + + /* OLE2NOTE: we must make sure to set all out parameters to NULL. */ + *lplpenumAdvise = NULL; + + /* OLE2NOTE: a document that is used to transfer data (either via + ** the clipboard or drag/drop) does NOT support Advise notifications. + */ + if (lpOutlineDoc->m_fDataTransferDoc) { + sc = OLE_E_ADVISENOTSUPPORTED; + goto error; + } + +#if defined( OLE_SERVER ) + { + LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOleDoc; + HRESULT hrErr; + + if (lpServerDoc->m_lpDataAdviseHldr == NULL) { + sc = E_FAIL; + goto error; + } + + OLEDBG_BEGIN2("IDataAdviseHolder::EnumAdvise called\r\n"); + hrErr = lpServerDoc->m_lpDataAdviseHldr->lpVtbl->EnumAdvise( + lpServerDoc->m_lpDataAdviseHldr, + lplpenumAdvise + ); + OLEDBG_END2 + + OLEDBG_END2 + return hrErr; + } +#endif +#if defined( OLE_CNTR ) + { + /* the Container-Only version of Outline does NOT offer + ** IDataObject interface from its User documents. this is + ** required by objects which can be embedded or linked. the + ** Container-only app only allows linking to its contained + ** objects, NOT the data of the container itself. + */ + OleDbgAssertSz(0, "User documents do NOT support IDataObject\r\n"); + sc = E_NOTIMPL; + goto error; + } +#endif + +error: + OLEDBG_END2 + return ResultFromScode(sc); +} + + + +/************************************************************************* +** OleDoc Supprt Functions common to both Container and Server versions +*************************************************************************/ + + +/* OleDoc_CopyCommand + * ------------------ + * Copy selection to clipboard. + * Post to the clipboard the formats that the app can render. + * the actual data is not rendered at this time. using the + * delayed rendering technique, Windows will send the clipboard + * owner window either a WM_RENDERALLFORMATS or a WM_RENDERFORMAT + * message when the actual data is requested. + * + * OLE2NOTE: the normal delayed rendering technique where Windows + * sends the clipboard owner window either a WM_RENDERALLFORMATS or + * a WM_RENDERFORMAT message when the actual data is requested is + * NOT exposed to the app calling OleSetClipboard. OLE internally + * creates its own window as the clipboard owner and thus our app + * will NOT get these WM_RENDER messages. + */ +void OleDoc_CopyCommand(LPOLEDOC lpSrcOleDoc) +{ + LPOUTLINEDOC lpSrcOutlineDoc = (LPOUTLINEDOC)lpSrcOleDoc; + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + LPOUTLINEDOC lpClipboardDoc; + + /* squirrel away a copy of the current selection to the ClipboardDoc */ + lpClipboardDoc = OutlineDoc_CreateDataTransferDoc(lpSrcOutlineDoc); + + if (! lpClipboardDoc) + return; // Error: could not create DataTransferDoc + + lpOutlineApp->m_lpClipboardDoc = (LPOUTLINEDOC)lpClipboardDoc; + + /* OLE2NOTE: initially the Doc object is created with a 0 ref + ** count. in order to have a stable Doc object during the + ** process of initializing the Doc instance and transfering it + ** to the clipboard, we intially AddRef the Doc ref cnt and later + ** Release it. This initial AddRef is artificial; it is simply + ** done to guarantee that a harmless QueryInterface followed by + ** a Release does not inadvertantly force our object to destroy + ** itself prematurely. + */ + OleDoc_AddRef((LPOLEDOC)lpClipboardDoc); + + /* OLE2NOTE: the OLE 2.0 style to put data onto the clipboard is to + ** give the clipboard a pointer to an IDataObject interface that + ** is able to statisfy IDataObject::GetData calls to render + ** data. in our case we give the pointer to the ClipboardDoc + ** which holds a cloned copy of the current user's selection. + */ + OLEDBG_BEGIN2("OleSetClipboard called\r\n") + OleSetClipboard((LPDATAOBJECT)&((LPOLEDOC)lpClipboardDoc)->m_DataObject); + OLEDBG_END2 + + OleDoc_Release((LPOLEDOC)lpClipboardDoc); // rel artificial AddRef above +} + + +/* OleDoc_PasteCommand +** ------------------- +** Paste default format data from the clipboard. +** In this function we choose the highest fidelity format that the +** source clipboard IDataObject* offers that we understand. +** +** OLE2NOTE: clipboard handling in an OLE 2.0 application is +** different than normal Windows clipboard handling. Data from the +** clipboard is retieved by getting the IDataObject* pointer +** returned by calling OleGetClipboard. +*/ +void OleDoc_PasteCommand(LPOLEDOC lpOleDoc) +{ + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc; + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + LPDATAOBJECT lpClipboardDataObj = NULL; + BOOL fLink = FALSE; + BOOL fLocalDataObj = FALSE; + BOOL fStatus; + HRESULT hrErr; + + hrErr = OleGetClipboard((LPDATAOBJECT FAR*)&lpClipboardDataObj); + if (hrErr != NOERROR) + return; // Clipboard seems to be empty or can't be accessed + + OutlineDoc_SetRedraw ( lpOutlineDoc, FALSE ); + + /* check if the data on the clipboard is local to our application + ** instance. + */ + if (lpOutlineApp->m_lpClipboardDoc) { + LPOLEDOC lpOleDoc = (LPOLEDOC)lpOutlineApp->m_lpClipboardDoc; + if (lpClipboardDataObj == (LPDATAOBJECT)&lpOleDoc->m_DataObject) + fLocalDataObj = TRUE; + } + + fStatus = OleDoc_PasteFromData( + lpOleDoc, + lpClipboardDataObj, + fLocalDataObj, + fLink + ); + + OutlineDoc_SetRedraw ( lpOutlineDoc, TRUE ); + + if (! fStatus) + OutlineApp_ErrorMessage(g_lpApp,"Could not paste data from clipboard!"); + + if (lpClipboardDataObj) + OleStdRelease((LPUNKNOWN)lpClipboardDataObj); +} + + +/* OleDoc_PasteSpecialCommand +** -------------------------- +** Allow the user to paste data in a particular format from the +** clipboard. The paste special command displays a dialog to the +** user that allows him to choose the format to be pasted from the +** list of formats available. +** +** OLE2NOTE: the PasteSpecial dialog is one of the standard OLE 2.0 +** UI dialogs for which the dialog is implemented and in the OLE2UI +** library. +** +** OLE2NOTE: clipboard handling in an OLE 2.0 application is +** different than normal Windows clipboard handling. Data from the +** clipboard is retieved by getting the IDataObject* pointer +** returned by calling OleGetClipboard. +*/ +void OleDoc_PasteSpecialCommand(LPOLEDOC lpOleDoc) +{ + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc; + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; + LPDATAOBJECT lpClipboardDataObj = NULL; + CLIPFORMAT cfFormat; + int nFmtEtc; + UINT uInt; + BOOL fLink = FALSE; + BOOL fLocalDataObj = FALSE; + BOOL fStatus; + HRESULT hrErr; + OLEUIPASTESPECIAL ouiPasteSpl; + BOOL fDisplayAsIcon; + + hrErr = OleGetClipboard((LPDATAOBJECT FAR*)&lpClipboardDataObj); + if (hrErr != NOERROR) + return; // Clipboard seems to be empty or can't be accessed + + /* check if the data on the clipboard is local to our application + ** instance. + */ + if (lpOutlineApp->m_lpClipboardDoc) { + LPOLEDOC lpOleDoc = (LPOLEDOC)lpOutlineApp->m_lpClipboardDoc; + if (lpClipboardDataObj == (LPDATAOBJECT)&lpOleDoc->m_DataObject) + fLocalDataObj = TRUE; + } + + /* Display the PasteSpecial dialog and allow the user to select the + ** format to paste. + */ + _fmemset((LPOLEUIPASTESPECIAL)&ouiPasteSpl, 0, sizeof(ouiPasteSpl)); + ouiPasteSpl.cbStruct = sizeof(ouiPasteSpl); //Structure Size + ouiPasteSpl.dwFlags = PSF_SELECTPASTE | PSF_SHOWHELP; //IN-OUT: Flags + ouiPasteSpl.hWndOwner = lpOutlineApp->m_lpDoc->m_hWndDoc; //Owning window + ouiPasteSpl.lpszCaption = "Paste Special"; //Dialog caption bar contents + ouiPasteSpl.lpfnHook = NULL; //Hook callback + ouiPasteSpl.lCustData = 0; //Custom data to pass to hook + ouiPasteSpl.hInstance = NULL; //Instance for customized template name + ouiPasteSpl.lpszTemplate = NULL; //Customized template name + ouiPasteSpl.hResource = NULL; //Customized template handle + + ouiPasteSpl.arrPasteEntries = lpOleApp->m_arrPasteEntries; + ouiPasteSpl.cPasteEntries = lpOleApp->m_nPasteEntries; + ouiPasteSpl.lpSrcDataObj = lpClipboardDataObj; + ouiPasteSpl.arrLinkTypes = lpOleApp->m_arrLinkTypes; + ouiPasteSpl.cLinkTypes = lpOleApp->m_nLinkTypes; + ouiPasteSpl.cClsidExclude = 0; + + OLEDBG_BEGIN3("OleUIPasteSpecial called\r\n") + uInt = OleUIPasteSpecial(&ouiPasteSpl); + OLEDBG_END3 + + fDisplayAsIcon = + (ouiPasteSpl.dwFlags & PSF_CHECKDISPLAYASICON ? TRUE : FALSE); + + if (uInt == OLEUI_OK) { + nFmtEtc = ouiPasteSpl.nSelectedIndex; + fLink = ouiPasteSpl.fLink; + + if (nFmtEtc < 0 || nFmtEtc >= lpOleApp->m_nPasteEntries) { + OutlineApp_ErrorMessage(lpOutlineApp, ErrMsgBadFmt); + goto error; + } + + OutlineDoc_SetRedraw ( lpOutlineDoc, FALSE ); + + cfFormat = lpOleApp->m_arrPasteEntries[nFmtEtc].fmtetc.cfFormat; + + fStatus = OleDoc_PasteFormatFromData( + lpOleDoc, + cfFormat, + lpClipboardDataObj, + fLocalDataObj, + fLink, + fDisplayAsIcon, + ouiPasteSpl.hMetaPict, + (LPSIZEL)&ouiPasteSpl.sizel + ); + + OutlineDoc_SetRedraw ( lpOutlineDoc, TRUE ); + + if (! fStatus) { + OutlineApp_ErrorMessage(lpOutlineApp, ErrMsgPasteFailed); + goto error; + } + + } else if (uInt == OLEUI_PSERR_CLIPBOARDCHANGED) { + /* OLE2NOTE: this error code is returned when the contents of + ** the clipboard change while the PasteSpecial dialog is up. + ** in this situation the PasteSpecial dialog automatically + ** brings itself down and NO paste operation should be performed. + */ + OutlineApp_ErrorMessage(lpOutlineApp, ErrMsgClipboardChanged); + } + +error: + + if (lpClipboardDataObj) + OleStdRelease((LPUNKNOWN)lpClipboardDataObj); + + if (uInt == OLEUI_OK && ouiPasteSpl.hMetaPict) + // clean up metafile + OleUIMetafilePictIconFree(ouiPasteSpl.hMetaPict); +} + + + +/* OleDoc_CreateDataTransferDoc + * ---------------------------- + * + * Create a document to be use to transfer data (either via a + * drag/drop operation of the clipboard). Copy the selection of the + * source doc to the data transfer document. A data transfer document is + * the same as a document that is created by the user except that it is + * NOT made visible to the user. it is specially used to hold a copy of + * data that the user should not be able to change. + * + * OLE2NOTE: in the OLE version the data transfer document is used + * specifically to provide an IDataObject* that renders the data copied. + */ +LPOUTLINEDOC OleDoc_CreateDataTransferDoc(LPOLEDOC lpSrcOleDoc) +{ + LPOUTLINEDOC lpSrcOutlineDoc = (LPOUTLINEDOC)lpSrcOleDoc; + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + LPOUTLINEDOC lpDestOutlineDoc; + LPLINELIST lpSrcLL = &lpSrcOutlineDoc->m_LineList; + LINERANGE lrSel; + int nCopied; + + lpDestOutlineDoc = OutlineApp_CreateDoc(lpOutlineApp, TRUE); + if (! lpDestOutlineDoc) return NULL; + + // set the ClipboardDoc to an (Untitled) doc. + if (! OutlineDoc_InitNewFile(lpDestOutlineDoc)) + goto error; + + LineList_GetSel(lpSrcLL, (LPLINERANGE)&lrSel); + nCopied = LineList_CopySelToDoc( + lpSrcLL, + (LPLINERANGE)&lrSel, + lpDestOutlineDoc + ); + + if (nCopied != (lrSel.m_nEndLine - lrSel.m_nStartLine + 1)) { + OleDbgAssertSz(FALSE,"OleDoc_CreateDataTransferDoc: entire selection NOT copied\r\n"); + goto error; // ERROR: all lines could NOT be copied + } + +#if defined( OLE_SERVER ) + { + LPOLEDOC lpSrcOleDoc = (LPOLEDOC)lpSrcOutlineDoc; + LPOLEDOC lpDestOleDoc = (LPOLEDOC)lpDestOutlineDoc; + LPSERVERDOC lpDestServerDoc = (LPSERVERDOC)lpDestOutlineDoc; + LPMONIKER lpmkDoc = NULL; + LPMONIKER lpmkItem = NULL; + + /* If source document is able to provide a moniker, then the + ** destination document (lpDestOutlineDoc) should offer + ** CF_LINKSOURCE via its IDataObject interface that it gives + ** to the clipboard or the drag/drop operation. + ** + ** OLE2NOTE: we want to ask the source document if it can + ** produce a moniker, but we do NOT want to FORCE moniker + ** assignment at this point. we only want to FORCE moniker + ** assignment later if a Paste Link occurs (ie. GetData for + ** CF_LINKSOURCE). if the source document is able to give + ** a moniker, then we store a pointer to the source document + ** so we can ask it at a later time to get the moniker. we + ** also save the range of the current selection so we can + ** generate a proper item name later when Paste Link occurs. + ** Also we need to give a string which identifies the source + ** of the copy in the CF_OBJECTDESCRIPTOR format. this + ** string is used to display in the PasteSpecial dialog. we + ** get and store a TEMPFORUSER moniker which identifies the + ** source of copy. + */ + lpDestOleDoc->m_lpSrcDocOfCopy = lpSrcOleDoc; + lpmkDoc = OleDoc_GetFullMoniker(lpSrcOleDoc, GETMONIKER_TEMPFORUSER); + if (lpmkDoc != NULL) { + lpDestOleDoc->m_fLinkSourceAvail = TRUE; + lpDestServerDoc->m_lrSrcSelOfCopy = lrSel; + OleStdRelease((LPUNKNOWN)lpmkDoc); + } + } +#endif +#if defined( OLE_CNTR ) + { + LPOLEDOC lpSrcOleDoc = (LPOLEDOC)lpSrcOutlineDoc; + LPOLEDOC lpDestOleDoc = (LPOLEDOC)lpDestOutlineDoc; + LPCONTAINERDOC lpDestContainerDoc = (LPCONTAINERDOC)lpDestOutlineDoc; + + /* If one line was copied from the source document, and it was a + ** single OLE object, then the destination document should + ** offer additional data formats to allow the transfer of + ** the OLE object via IDataObject::GetData. Specifically, the + ** following additional data formats are offered if a single + ** OLE object is copied: + ** CF_EMBEDDEDOBJECT + ** CF_OBJECTDESCRIPTOR (should be given even w/o object) + ** CF_METAFILEPICT (note: dwAspect depends on object) + ** CF_LINKSOURCE -- if linking is possible + ** CF_LINKSOURCEDESCRIPTOR -- if linking is possible + ** + ** optionally the container may give + ** + */ + + if (nCopied == 1) { + LPOLEOBJECT lpSrcOleObj; + LPCONTAINERLINE lpSrcContainerLine; + DWORD dwStatus; + + lpSrcContainerLine = (LPCONTAINERLINE)LineList_GetLine( + lpSrcLL, + lrSel.m_nStartLine + ); + + if (! lpSrcContainerLine) + goto error; + + lpDestOleDoc->m_lpSrcDocOfCopy = lpSrcOleDoc; + + if ((((LPLINE)lpSrcContainerLine)->m_lineType==CONTAINERLINETYPE) + && ((lpSrcOleObj=lpSrcContainerLine->m_lpOleObj)!=NULL)) { + + lpDestContainerDoc->m_fEmbeddedObjectAvail = TRUE; + lpSrcOleObj->lpVtbl->GetUserClassID( + lpSrcOleObj, + &lpDestContainerDoc->m_clsidOleObjCopied + ); + lpDestContainerDoc->m_dwAspectOleObjCopied = + lpSrcContainerLine->m_dwDrawAspect; + + /* OLE2NOTE: if the object is allowed to be linked + ** to from the inside (ie. we are allowed to + ** give out a moniker which binds to the running + ** OLE object), then we want to offer + ** CF_LINKSOURCE format. if the object is an OLE + ** 2.0 embedded object then it is allowed to be + ** linked to from the inside. if the object is + ** either an OleLink or an OLE 1.0 embedding + ** then it can not be linked to from the inside. + ** if we were a container/server app then we + ** could offer linking to the outside of the + ** object (ie. a pseudo object within our + ** document). we are a container only app that + ** does not support linking to ranges of its data. + */ + + lpSrcOleObj->lpVtbl->GetMiscStatus( + lpSrcOleObj, + DVASPECT_CONTENT, /* aspect is not important */ + (LPDWORD)&dwStatus + ); + if (! (dwStatus & OLEMISC_CANTLINKINSIDE)) { + /* Our container supports linking to an embedded + ** object. We want the lpDestContainerDoc to + ** offer CF_LINKSOURCE via the IDataObject + ** interface that it gives to the clipboard or + ** the drag/drop operation. The link source will + ** be identified by a composite moniker + ** comprised of the FileMoniker of the source + ** document and an ItemMoniker which identifies + ** the OLE object inside the container. we do + ** NOT want to force moniker assignment to the + ** OLE object now (at copy time); we only want + ** to FORCE moniker assignment later if a Paste + ** Link occurs (ie. GetData for CF_LINKSOURCE). + ** thus we store a pointer to the source document + ** and the source ContainerLine so we can + ** generate a proper ItemMoniker later when + ** Paste Link occurs. + */ + lpDestOleDoc->m_fLinkSourceAvail = TRUE; + lpDestContainerDoc->m_lpSrcContainerLine = + lpSrcContainerLine; + } + } + } + } + +#endif // OLE_CNTR + + return lpDestOutlineDoc; + +error: + if (lpDestOutlineDoc) + OutlineDoc_Destroy(lpDestOutlineDoc); + + return NULL; +} + + +/* OleDoc_PasteFromData +** -------------------- +** +** Paste data from an IDataObject*. The IDataObject* may come from +** the clipboard (GetClipboard) or from a drag/drop operation. +** In this function we choose the best format that we prefer. +** +** Returns TRUE if data was successfully pasted. +** FALSE if data could not be pasted. +*/ + +BOOL OleDoc_PasteFromData( + LPOLEDOC lpOleDoc, + LPDATAOBJECT lpSrcDataObj, + BOOL fLocalDataObj, + BOOL fLink +) +{ + LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; + CLIPFORMAT cfFormat; + BOOL fDisplayAsIcon = FALSE; + SIZEL sizelInSrc = {0, 0}; + HGLOBAL hMem = NULL; + HGLOBAL hMetaPict = NULL; + STGMEDIUM medium; + + if (fLink) { +#if defined( OLE_SERVER ) + return FALSE; // server version of app does NOT support links +#endif +#if defined( OLE_CNTR ) + // container version of app only supports OLE object type links + cfFormat = lpOleApp->m_cfLinkSource; +#endif + + } else { + + int nFmtEtc; + + nFmtEtc = OleStdGetPriorityClipboardFormat( + lpSrcDataObj, + lpOleApp->m_arrPasteEntries, + lpOleApp->m_nPasteEntries + ); + + if (nFmtEtc < 0) + return FALSE; // there is no format we like + + cfFormat = lpOleApp->m_arrPasteEntries[nFmtEtc].fmtetc.cfFormat; + } + + /* OLE2NOTE: we need to check what dwDrawAspect is being + ** transfered. if the data is an object that is displayed as an + ** icon in the source, then we want to keep it as an icon. the + ** aspect the object is displayed in at the source is transfered + ** via the CF_OBJECTDESCRIPTOR format for a Paste operation. + */ + if (hMem = OleStdGetData( + lpSrcDataObj, + lpOleApp->m_cfObjectDescriptor, + NULL, + DVASPECT_CONTENT, + (LPSTGMEDIUM)&medium)) { + LPOBJECTDESCRIPTOR lpOD = GlobalLock(hMem); + fDisplayAsIcon = (lpOD->dwDrawAspect == DVASPECT_ICON ? TRUE : FALSE); + sizelInSrc = lpOD->sizel; // size of object/picture in source (opt.) + GlobalUnlock(hMem); + ReleaseStgMedium((LPSTGMEDIUM)&medium); // equiv to GlobalFree + + if (fDisplayAsIcon) { + hMetaPict = OleStdGetData( + lpSrcDataObj, + CF_METAFILEPICT, + NULL, + DVASPECT_ICON, + (LPSTGMEDIUM)&medium + ); + if (hMetaPict == NULL) + fDisplayAsIcon = FALSE; // give up; failed to get icon MFP + } + } + + return OleDoc_PasteFormatFromData( + lpOleDoc, + cfFormat, + lpSrcDataObj, + fLocalDataObj, + fLink, + fDisplayAsIcon, + hMetaPict, + (LPSIZEL)&sizelInSrc + ); + + if (hMetaPict) + ReleaseStgMedium((LPSTGMEDIUM)&medium); // properly free METAFILEPICT +} + + +/* OleDoc_PasteFormatFromData +** -------------------------- +** +** Paste a particular data format from a IDataObject*. The +** IDataObject* may come from the clipboard (GetClipboard) or from a +** drag/drop operation. +** +** Returns TRUE if data was successfully pasted. +** FALSE if data could not be pasted. +*/ + +BOOL OleDoc_PasteFormatFromData( + LPOLEDOC lpOleDoc, + CLIPFORMAT cfFormat, + LPDATAOBJECT lpSrcDataObj, + BOOL fLocalDataObj, + BOOL fLink, + BOOL fDisplayAsIcon, + HGLOBAL hMetaPict, + LPSIZEL lpSizelInSrc +) +{ +#if defined( OLE_SERVER ) + /* call server specific version of the function. */ + return ServerDoc_PasteFormatFromData( + (LPSERVERDOC)lpOleDoc, + cfFormat, + lpSrcDataObj, + fLocalDataObj, + fLink + ); +#endif +#if defined( OLE_CNTR ) + + /* call container specific version of the function. */ + return ContainerDoc_PasteFormatFromData( + (LPCONTAINERDOC)lpOleDoc, + cfFormat, + lpSrcDataObj, + fLocalDataObj, + fLink, + fDisplayAsIcon, + hMetaPict, + lpSizelInSrc + ); +#endif +} + + +/* OleDoc_QueryPasteFromData +** ------------------------- +** +** Check if the IDataObject* offers data in a format that we can +** paste. The IDataObject* may come from the clipboard +** (GetClipboard) or from a drag/drop operation. +** +** Returns TRUE if paste can be performed +** FALSE if paste is not possible. +*/ + +BOOL OleDoc_QueryPasteFromData( + LPOLEDOC lpOleDoc, + LPDATAOBJECT lpSrcDataObj, + BOOL fLink +) +{ +#if defined( OLE_SERVER ) + return ServerDoc_QueryPasteFromData( + (LPSERVERDOC) lpOleDoc, + lpSrcDataObj, + fLink + ); +#endif +#if defined( OLE_CNTR ) + + return ContainerDoc_QueryPasteFromData( + (LPCONTAINERDOC) lpOleDoc, + lpSrcDataObj, + fLink + ); +#endif +} + + +/* OleDoc_GetExtent + * ---------------- + * + * Get the extent (width, height) of the entire document in Himetric. + */ +void OleDoc_GetExtent(LPOLEDOC lpOleDoc, LPSIZEL lpsizel) +{ + LPLINELIST lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList; + + LineList_CalcSelExtentInHimetric(lpLL, NULL, lpsizel); +} + + +/* OleDoc_GetObjectDescriptorData + * ------------------------------ + * + * Return a handle to an object's data in CF_OBJECTDESCRIPTOR form + * + */ +HGLOBAL OleDoc_GetObjectDescriptorData(LPOLEDOC lpOleDoc, LPLINERANGE lplrSel) +{ + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc; + + /* Only our data transfer doc renders CF_OBJECTDESCRIPTOR */ + OleDbgAssert(lpOutlineDoc->m_fDataTransferDoc); + +#if defined( OLE_SERVER ) + { + LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOleDoc; + SIZEL sizel; + POINTL pointl; + LPSTR lpszSrcOfCopy = NULL; + IBindCtx FAR *pbc = NULL; + HGLOBAL hObjDesc; + DWORD dwStatus = 0; + LPOUTLINEDOC lpSrcDocOfCopy=(LPOUTLINEDOC)lpOleDoc->m_lpSrcDocOfCopy; + LPMONIKER lpSrcMonikerOfCopy = ServerDoc_GetSelFullMoniker( + (LPSERVERDOC)lpOleDoc->m_lpSrcDocOfCopy, + &lpServerDoc->m_lrSrcSelOfCopy, + GETMONIKER_TEMPFORUSER + ); + + SvrDoc_OleObj_GetMiscStatus( + (LPOLEOBJECT)&lpServerDoc->m_OleObject, + DVASPECT_CONTENT, + &dwStatus + ); + + OleDoc_GetExtent(lpOleDoc, &sizel); + pointl.x = pointl.y = 0; + + if (lpSrcMonikerOfCopy) { + CreateBindCtx(0, (LPBC FAR*)&pbc); + CallIMonikerGetDisplayNameA( + lpSrcMonikerOfCopy, pbc, NULL, &lpszSrcOfCopy); + pbc->lpVtbl->Release(pbc); + lpSrcMonikerOfCopy->lpVtbl->Release(lpSrcMonikerOfCopy); + } else { + /* this document has no moniker; use our FullUserTypeName + ** as the description of the source of copy. + */ + lpszSrcOfCopy = FULLUSERTYPENAME; + } + + hObjDesc = OleStdGetObjectDescriptorData( + CLSID_APP, + DVASPECT_CONTENT, + sizel, + pointl, + dwStatus, + FULLUSERTYPENAME, + lpszSrcOfCopy + ); + + if (lpSrcMonikerOfCopy && lpszSrcOfCopy) + OleStdFreeString(lpszSrcOfCopy, NULL); + return hObjDesc; + + } +#endif +#if defined( OLE_CNTR ) + { + LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOleDoc; + LPLINELIST lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList; + LPCONTAINERLINE lpContainerLine; + HGLOBAL hObjDesc; + BOOL fSelIsOleObject = FALSE; + LPOLEOBJECT lpOleObj; + SIZEL sizel; + POINTL pointl; + + if ( lpLL->m_nNumLines == 1 ) { + fSelIsOleObject = ContainerDoc_IsSelAnOleObject( + lpContainerDoc, + &IID_IOleObject, + (LPUNKNOWN FAR*)&lpOleObj, + NULL, /* we don't need the line index */ + (LPCONTAINERLINE FAR*)&lpContainerLine + ); + } + + pointl.x = pointl.y = 0; + + if (fSelIsOleObject) { + /* OLE2NOTE: a single OLE object is being transfered via + ** this DataTransferDoc. we need to generate the + ** CF_ObjectDescrioptor which describes the OLE object. + */ + + LPOUTLINEDOC lpSrcOutlineDoc = + (LPOUTLINEDOC)lpOleDoc->m_lpSrcDocOfCopy; + LPSTR lpszSrcOfCopy = lpSrcOutlineDoc->m_szFileName; + BOOL fFreeSrcOfCopy = FALSE; + SIZEL sizelOleObject; + LPLINE lpLine = (LPLINE)lpContainerLine; + + /* if the object copied can be linked to then get a + ** TEMPFORUSER form of the moniker which identifies the + ** source of copy. we do not want to force the + ** assignment of the moniker until CF_LINKSOURCE is + ** rendered. + ** if the object copied can not be a link source then use + ** the source filename to identify the source of copy. + ** there is no need to generate a moniker for the object + ** copied. + */ + if (lpOleDoc->m_fLinkSourceAvail && + lpContainerDoc->m_lpSrcContainerLine) { + LPBINDCTX pbc = NULL; + LPMONIKER lpSrcMonikerOfCopy = ContainerLine_GetFullMoniker( + lpContainerDoc->m_lpSrcContainerLine, + GETMONIKER_TEMPFORUSER + ); + if (lpSrcMonikerOfCopy) { + CreateBindCtx(0, (LPBC FAR*)&pbc); + if (pbc != NULL) { + CallIMonikerGetDisplayNameA( + lpSrcMonikerOfCopy, pbc, NULL, &lpszSrcOfCopy); + + pbc->lpVtbl->Release(pbc); + fFreeSrcOfCopy = TRUE; + } + lpSrcMonikerOfCopy->lpVtbl->Release(lpSrcMonikerOfCopy); + } + } + + /* OLE2NOTE: Get size that object is being drawn. If the + ** object has been scaled because the user resized the + ** object, then we want to pass the scaled size of the + ** object in the ObjectDescriptor rather than the size + ** that the object would return via + ** IOleObject::GetExtent and IViewObject2::GetExtent. in + ** this way if the object is transfered to another container + ** (via clipboard or drag/drop), then the object will + ** remain the scaled size. + */ + sizelOleObject.cx = lpLine->m_nWidthInHimetric; + sizelOleObject.cy = lpLine->m_nHeightInHimetric; + + hObjDesc = OleStdGetObjectDescriptorDataFromOleObject( + lpOleObj, + lpszSrcOfCopy, + lpContainerLine->m_dwDrawAspect, + pointl, + (LPSIZEL)&sizelOleObject + ); + + if (fFreeSrcOfCopy && lpszSrcOfCopy) + OleStdFreeString(lpszSrcOfCopy, NULL); + OleStdRelease((LPUNKNOWN)lpOleObj); + return hObjDesc; + } else { + /* OLE2NOTE: the data being transfered via this + ** DataTransferDoc is NOT a single OLE object. thus in + ** this case the CF_ObjectDescriptor data should + ** describe our container app itself. + */ + OleDoc_GetExtent(lpOleDoc, &sizel); + return OleStdGetObjectDescriptorData( + CLSID_NULL, /* not used if no object formats */ + DVASPECT_CONTENT, + sizel, + pointl, + 0, + NULL, /* UserTypeName not used if no obj fmt's */ + FULLUSERTYPENAME /* string to identify source of copy */ + ); + + } + } +#endif // OLE_CNTR +} + + +#if defined( OLE_SERVER ) + +/************************************************************************* +** ServerDoc Supprt Functions Used by Server versions +*************************************************************************/ + + +/* ServerDoc_PasteFormatFromData +** ----------------------------- +** +** Paste a particular data format from a IDataObject*. The +** IDataObject* may come from the clipboard (GetClipboard) or from a +** drag/drop operation. +** +** NOTE: fLink is specified then FALSE if returned because the +** Server only version of the app can not support links. +** +** Returns TRUE if data was successfully pasted. +** FALSE if data could not be pasted. +*/ +BOOL ServerDoc_PasteFormatFromData( + LPSERVERDOC lpServerDoc, + CLIPFORMAT cfFormat, + LPDATAOBJECT lpSrcDataObj, + BOOL fLocalDataObj, + BOOL fLink +) +{ + LPLINELIST lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpServerDoc)->m_LineList; + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; + int nIndex; + int nCount = 0; + HGLOBAL hData; + STGMEDIUM medium; + LINERANGE lrSel; + + if (LineList_GetCount(lpLL) == 0) + nIndex = -1; // pasting to empty list + else + nIndex=LineList_GetFocusLineIndex(lpLL); + + if (fLink) { + /* We should paste a Link to the data, but we do not support links */ + return FALSE; + + } else { + + if (cfFormat == lpOutlineApp->m_cfOutline) { + + hData = OleStdGetData( + lpSrcDataObj, + lpOutlineApp->m_cfOutline, + NULL, + DVASPECT_CONTENT, + (LPSTGMEDIUM)&medium + ); + if (hData == NULL) + return FALSE; + + nCount = OutlineDoc_PasteOutlineData( + (LPOUTLINEDOC)lpServerDoc, + hData, + nIndex + ); + // OLE2NOTE: we must free data handle by releasing the medium + ReleaseStgMedium((LPSTGMEDIUM)&medium); + + } else if(cfFormat == CF_TEXT) { + + hData = OleStdGetData( + lpSrcDataObj, + CF_TEXT, + NULL, + DVASPECT_CONTENT, + (LPSTGMEDIUM)&medium + ); + if (hData == NULL) + return FALSE; + + nCount = OutlineDoc_PasteTextData( + (LPOUTLINEDOC)lpServerDoc, + hData, + nIndex + ); + // OLE2NOTE: we must free data handle by releasing the medium + ReleaseStgMedium((LPSTGMEDIUM)&medium); + } + } + + lrSel.m_nEndLine = nIndex + 1; + lrSel.m_nStartLine = nIndex + nCount; + LineList_SetSel(lpLL, &lrSel); + return TRUE; +} + + +/* ServerDoc_QueryPasteFromData +** ---------------------------- +** +** Check if the IDataObject* offers data in a format that we can +** paste. The IDataObject* may come from the clipboard +** (GetClipboard) or from a drag/drop operation. +** In this function we look if one of the following formats is +** offered: +** CF_OUTLINE +** CF_TEXT +** +** NOTE: fLink is specified then FALSE if returned because the +** Server only version of the app can not support links. +** +** Returns TRUE if paste can be performed +** FALSE if paste is not possible. +*/ +BOOL ServerDoc_QueryPasteFromData( + LPSERVERDOC lpServerDoc, + LPDATAOBJECT lpSrcDataObj, + BOOL fLink +) +{ + LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; + + if (fLink) { + /* we do not support links */ + return FALSE; + + } else { + + int nFmtEtc; + + nFmtEtc = OleStdGetPriorityClipboardFormat( + lpSrcDataObj, + lpOleApp->m_arrPasteEntries, + lpOleApp->m_nPasteEntries + ); + + if (nFmtEtc < 0) + return FALSE; // there is no format we like + } + + return TRUE; +} + + +/* ServerDoc_GetData + * ----------------- + * + * Render data from the document on a CALLEE allocated STGMEDIUM. + * This routine is called via IDataObject::GetData. + */ + +HRESULT ServerDoc_GetData ( + LPSERVERDOC lpServerDoc, + LPFORMATETC lpformatetc, + LPSTGMEDIUM lpMedium +) +{ + LPOLEDOC lpOleDoc = (LPOLEDOC)lpServerDoc; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; + LPSERVERAPP lpServerApp = (LPSERVERAPP)g_lpApp; + LPOLEAPP lpOleApp = (LPOLEAPP)lpServerApp; + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpServerApp; + HRESULT hrErr; + SCODE sc; + + // OLE2NOTE: we must set out pointer parameters to NULL + lpMedium->pUnkForRelease = NULL; + + /* OLE2NOTE: we must make sure to set all out parameters to NULL. */ + lpMedium->tymed = TYMED_NULL; + lpMedium->pUnkForRelease = NULL; // we transfer ownership to caller + lpMedium->hGlobal = NULL; + + if(lpformatetc->cfFormat == lpOutlineApp->m_cfOutline) { + // Verify caller asked for correct medium + if (!(lpformatetc->tymed & TYMED_HGLOBAL)) { + sc = DV_E_FORMATETC; + goto error; + } + lpMedium->hGlobal = OutlineDoc_GetOutlineData (lpOutlineDoc,NULL); + if (! lpMedium->hGlobal) { + sc = E_OUTOFMEMORY; + goto error; + } + + lpMedium->tymed = TYMED_HGLOBAL; + OleDbgOut3("ServerDoc_GetData: rendered CF_OUTLINE\r\n"); + return NOERROR; + + } else if (lpformatetc->cfFormat == CF_METAFILEPICT && + (lpformatetc->dwAspect & DVASPECT_CONTENT) ) { + // Verify caller asked for correct medium + if (!(lpformatetc->tymed & TYMED_MFPICT)) { + sc = DV_E_FORMATETC; + goto error; + } + + lpMedium->hGlobal = ServerDoc_GetMetafilePictData(lpServerDoc,NULL); + if (! lpMedium->hGlobal) { + sc = E_OUTOFMEMORY; + goto error; + } + + lpMedium->tymed = TYMED_MFPICT; + OleDbgOut3("ServerDoc_GetData: rendered CF_METAFILEPICT\r\n"); + return NOERROR; + + } else if (lpformatetc->cfFormat == CF_METAFILEPICT && + (lpformatetc->dwAspect & DVASPECT_ICON) ) { + CLSID clsid; + // Verify caller asked for correct medium + if (!(lpformatetc->tymed & TYMED_MFPICT)) { + sc = DV_E_FORMATETC; + goto error; + } + + /* OLE2NOTE: we should return the default icon for our class. + ** we must be carefull to use the correct CLSID here. + ** if we are currently preforming a "TreatAs (aka. ActivateAs)" + ** operation then we need to use the class of the object + ** written in the storage of the object. otherwise we would + ** use our own class id. + */ + if (ServerDoc_GetClassID(lpServerDoc, (LPCLSID)&clsid) != NOERROR) { + sc = DV_E_FORMATETC; + goto error; + } + + lpMedium->hGlobal=GetIconOfClass(g_lpApp->m_hInst,(REFCLSID)&clsid, NULL, FALSE); + if (! lpMedium->hGlobal) { + sc = E_OUTOFMEMORY; + goto error; + } + + lpMedium->tymed = TYMED_MFPICT; + OleDbgOut3("ServerDoc_GetData: rendered CF_METAFILEPICT (icon)\r\n"); + return NOERROR; + + } else if (lpformatetc->cfFormat == CF_TEXT) { + // Verify caller asked for correct medium + if (!(lpformatetc->tymed & TYMED_HGLOBAL)) { + sc = DV_E_FORMATETC; + goto error; + } + + lpMedium->hGlobal = OutlineDoc_GetTextData ( + (LPOUTLINEDOC)lpServerDoc, + NULL + ); + if (! lpMedium->hGlobal) { + sc = E_OUTOFMEMORY; + goto error; + } + + lpMedium->tymed = TYMED_HGLOBAL; + OleDbgOut3("ServerDoc_GetData: rendered CF_TEXT\r\n"); + return NOERROR; + } + + /* the above are the only formats supports by a user document (ie. + ** a non-data transfer doc). if the document is used for + ** purposes of data transfer, then additional formats are offered. + */ + if (! lpOutlineDoc->m_fDataTransferDoc) { + sc = DV_E_FORMATETC; + goto error; + } + + /* OLE2NOTE: ObjectDescriptor and LinkSrcDescriptor will + ** contain the same data for the pure container and pure server + ** type applications. only a container/server application may + ** have different content for ObjectDescriptor and + ** LinkSrcDescriptor. if a container/server copies a link for + ** example, then the ObjectDescriptor would give the class + ** of the link source but the LinkSrcDescriptor would give the + ** class of the container/server itself. in this situation if a + ** paste operation occurs, an equivalent link is pasted, but if + ** a pastelink operation occurs, then a link to a pseudo object + ** in the container/server is created. + */ + if (lpformatetc->cfFormat == lpOleApp->m_cfObjectDescriptor || + (lpformatetc->cfFormat == lpOleApp->m_cfLinkSrcDescriptor && + lpOleDoc->m_fLinkSourceAvail)) { + // Verify caller asked for correct medium + if (!(lpformatetc->tymed & TYMED_HGLOBAL)) { + sc = DV_E_FORMATETC; + goto error; + } + + lpMedium->hGlobal = OleDoc_GetObjectDescriptorData ( + (LPOLEDOC)lpServerDoc, + NULL + ); + if (! lpMedium->hGlobal) { + sc = E_OUTOFMEMORY; + goto error; + } + + lpMedium->tymed = TYMED_HGLOBAL; + OleDbgOut3("ServerDoc_GetData: rendered CF_OBJECTDESCRIPTOR\r\n"); + return NOERROR; + + } else if (lpformatetc->cfFormat == lpOleApp->m_cfEmbedSource) { + hrErr = OleStdGetOleObjectData( + (LPPERSISTSTORAGE)&lpServerDoc->m_PersistStorage, + lpformatetc, + lpMedium, + FALSE /* fUseMemory -- (use file-base stg) */ + + ); + if (hrErr != NOERROR) { + sc = GetScode(hrErr); + goto error; + } + OleDbgOut3("ServerDoc_GetData: rendered CF_EMBEDSOURCE\r\n"); + return NOERROR; + + } else if (lpformatetc->cfFormat == lpOleApp->m_cfLinkSource) { + if (lpOleDoc->m_fLinkSourceAvail) { + LPMONIKER lpmk; + + lpmk = ServerDoc_GetSelFullMoniker( + (LPSERVERDOC)lpOleDoc->m_lpSrcDocOfCopy, + &lpServerDoc->m_lrSrcSelOfCopy, + GETMONIKER_FORCEASSIGN + ); + if (lpmk) { + hrErr = OleStdGetLinkSourceData( + lpmk, + (LPCLSID)&CLSID_APP, + lpformatetc, + lpMedium + ); + OleStdRelease((LPUNKNOWN)lpmk); + if (hrErr != NOERROR) { + sc = GetScode(hrErr); + goto error; + } + OleDbgOut3("ServerDoc_GetData: rendered CF_LINKSOURCE\r\n"); + return NOERROR; + + } else { + sc = E_FAIL; + goto error; + } + } else { + sc = DV_E_FORMATETC; + goto error; + } + + } else { + sc = DV_E_FORMATETC; + goto error; + } + + return NOERROR; + +error: + return ResultFromScode(sc); +} + + +/* ServerDoc_GetDataHere + * --------------------- + * + * Render data from the document on a CALLER allocated STGMEDIUM. + * This routine is called via IDataObject::GetDataHere. + */ +HRESULT ServerDoc_GetDataHere ( + LPSERVERDOC lpServerDoc, + LPFORMATETC lpformatetc, + LPSTGMEDIUM lpMedium +) +{ + LPOLEDOC lpOleDoc = (LPOLEDOC)lpServerDoc; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; + LPSERVERAPP lpServerApp = (LPSERVERAPP)g_lpApp; + LPOLEAPP lpOleApp = (LPOLEAPP)lpServerApp; + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpServerApp; + HRESULT hrErr; + SCODE sc; + + // OLE2NOTE: lpMedium is an IN parameter. we should NOT set + // lpMedium->pUnkForRelease to NULL + + /* our user document does not support any formats for GetDataHere. + ** if the document is used for + ** purposes of data transfer, then additional formats are offered. + */ + if (! lpOutlineDoc->m_fDataTransferDoc) { + sc = DV_E_FORMATETC; + goto error; + } + + if (lpformatetc->cfFormat == lpOleApp->m_cfEmbedSource) { + hrErr = OleStdGetOleObjectData( + (LPPERSISTSTORAGE)&lpServerDoc->m_PersistStorage, + lpformatetc, + lpMedium, + FALSE /* fUseMemory -- (use file-base stg) */ + ); + if (hrErr != NOERROR) { + sc = GetScode(hrErr); + goto error; + } + OleDbgOut3("ServerDoc_GetDataHere: rendered CF_EMBEDSOURCE\r\n"); + return NOERROR; + + } else if (lpformatetc->cfFormat == lpOleApp->m_cfLinkSource) { + if (lpOleDoc->m_fLinkSourceAvail) { + LPMONIKER lpmk; + + lpmk = ServerDoc_GetSelFullMoniker( + (LPSERVERDOC)lpOleDoc->m_lpSrcDocOfCopy, + &lpServerDoc->m_lrSrcSelOfCopy, + GETMONIKER_FORCEASSIGN + ); + if (lpmk) { + hrErr = OleStdGetLinkSourceData( + lpmk, + (LPCLSID)&CLSID_APP, + lpformatetc, + lpMedium + ); + OleStdRelease((LPUNKNOWN)lpmk); + if (hrErr != NOERROR) { + sc = GetScode(hrErr); + goto error; + } + + OleDbgOut3("ServerDoc_GetDataHere: rendered CF_LINKSOURCE\r\n"); + return NOERROR; + + } else { + sc = E_FAIL; + goto error; + } + } else { + sc = DV_E_FORMATETC; + goto error; + } + } else { + + /* Caller is requesting data to be returned in Caller allocated + ** medium, but we do NOT support this. we only support + ** global memory blocks that WE allocate for the caller. + */ + sc = DV_E_FORMATETC; + goto error; + } + + return NOERROR; + +error: + return ResultFromScode(sc); +} + + +/* ServerDoc_QueryGetData + * ---------------------- + * + * Answer if a particular data format is supported via GetData/GetDataHere. + * This routine is called via IDataObject::QueryGetData. + */ + +HRESULT ServerDoc_QueryGetData (LPSERVERDOC lpServerDoc,LPFORMATETC lpformatetc) +{ + LPOLEDOC lpOleDoc = (LPOLEDOC)lpServerDoc; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; + LPSERVERAPP lpServerApp = (LPSERVERAPP)g_lpApp; + LPOLEAPP lpOleApp = (LPOLEAPP)lpServerApp; + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpServerApp; + + /* Caller is querying if we support certain format but does not + ** want any data actually returned. + */ + if (lpformatetc->cfFormat == lpOutlineApp->m_cfOutline || + lpformatetc->cfFormat == CF_TEXT) { + // we only support HGLOBAL + return OleStdQueryFormatMedium(lpformatetc, TYMED_HGLOBAL); + } else if (lpformatetc->cfFormat == CF_METAFILEPICT && + (lpformatetc->dwAspect & + (DVASPECT_CONTENT | DVASPECT_ICON)) ) { + return OleStdQueryFormatMedium(lpformatetc, TYMED_MFPICT); + } + + /* the above are the only formats supports by a user document (ie. + ** a non-data transfer doc). if the document is used for + ** purposes of data transfer, then additional formats are offered. + */ + if (! lpOutlineDoc->m_fDataTransferDoc) + return ResultFromScode(DV_E_FORMATETC); + + if (lpformatetc->cfFormat == lpOleApp->m_cfEmbedSource) { + return OleStdQueryOleObjectData(lpformatetc); + + } else if (lpformatetc->cfFormat == lpOleApp->m_cfLinkSource && + lpOleDoc->m_fLinkSourceAvail) { + return OleStdQueryLinkSourceData(lpformatetc); + + } else if (lpformatetc->cfFormat == lpOleApp->m_cfObjectDescriptor) { + return OleStdQueryObjectDescriptorData(lpformatetc); + + } else if (lpformatetc->cfFormat == lpOleApp->m_cfLinkSrcDescriptor && + lpOleDoc->m_fLinkSourceAvail) { + return OleStdQueryObjectDescriptorData(lpformatetc); + } + + return ResultFromScode(DV_E_FORMATETC); +} + + +/* ServerDoc_EnumFormatEtc + * ----------------------- + * + * Return an enumerator which enumerates the data accepted/offered by + * the document. + * This routine is called via IDataObject::EnumFormatEtc. + */ +HRESULT ServerDoc_EnumFormatEtc( + LPSERVERDOC lpServerDoc, + DWORD dwDirection, + LPENUMFORMATETC FAR* lplpenumFormatEtc +) +{ + LPOLEDOC lpOleDoc = (LPOLEDOC)lpServerDoc; + LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; + int nActualFmts; + SCODE sc = S_OK; + + /* OLE2NOTE: the enumeration of formats for a data transfer + ** document is not a static list. the list of formats offered + ** may or may not include CF_LINKSOURCE depending on whether a + ** moniker is available for our document. thus we can NOT use + ** the default OLE enumerator which enumerates the formats that + ** are registered for our app in the registration database. + */ + if (dwDirection == DATADIR_GET) { + nActualFmts = lpOleApp->m_nDocGetFmts; + + /* If the document does not have a Moniker, then exclude + ** CF_LINKSOURCE and CF_LINKSRCDESCRIPTOR from the list of + ** formats available. these formats are deliberately listed + ** last in the array of possible "Get" formats. + */ + if (! lpOleDoc->m_fLinkSourceAvail) + nActualFmts -= 2; + + *lplpenumFormatEtc = OleStdEnumFmtEtc_Create( + nActualFmts, lpOleApp->m_arrDocGetFmts); + if (*lplpenumFormatEtc == NULL) + sc = E_OUTOFMEMORY; + + } else if (dwDirection == DATADIR_SET) { + /* OLE2NOTE: a document that is used to transfer data + ** (either via the clipboard or drag/drop does NOT + ** accept SetData on ANY format! + */ + sc = E_NOTIMPL; + goto error; + } else { + sc = E_INVALIDARG; + goto error; + } + +error: + return ResultFromScode(sc); +} + + +/* ServerDoc_GetMetafilePictData + * ----------------------------- + * + * Return a handle to an object's picture data in metafile format. + * + * + * RETURNS: A handle to the object's data in metafile format. + * + */ +HGLOBAL ServerDoc_GetMetafilePictData( + LPSERVERDOC lpServerDoc, + LPLINERANGE lplrSel +) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + LPOUTLINEDOC lpOutlineDoc=(LPOUTLINEDOC)lpServerDoc; + LPLINELIST lpLL=(LPLINELIST)&lpOutlineDoc->m_LineList; + LPLINE lpLine; + LPMETAFILEPICT lppict = NULL; + HGLOBAL hMFPict = NULL; + HMETAFILE hMF = NULL; + RECT rect; + RECT rectWBounds; + HDC hDC; + int i; + int nWidth; + int nStart = (lplrSel ? lplrSel->m_nStartLine : 0); + int nEnd =(lplrSel ? lplrSel->m_nEndLine : LineList_GetCount(lpLL)-1); + int nLines = nEnd - nStart + 1; + UINT fuAlign; + POINT point; + SIZE size; + + hDC = CreateMetaFile(NULL); + + rect.left = 0; + rect.right = 0; + rect.bottom = 0; + + if (nLines > 0) { + // calculate the total height/width of LineList in HIMETRIC + for(i = nStart; i <= nEnd; i++) { + lpLine = LineList_GetLine(lpLL,i); + if (! lpLine) + continue; + + nWidth = Line_GetTotalWidthInHimetric(lpLine); + rect.right = max(rect.right, nWidth); + rect.bottom -= Line_GetHeightInHimetric(lpLine); + } + + + SetMapMode(hDC, MM_ANISOTROPIC); + + SetWindowOrgEx(hDC, 0, 0, &point); + SetWindowExtEx(hDC, rect.right, rect.bottom, &size); + rectWBounds = rect; + + // Set the default font size, and font face name + SelectObject(hDC, OutlineApp_GetActiveFont(lpOutlineApp)); + + FillRect(hDC, (LPRECT) &rect, GetStockObject(WHITE_BRUSH)); + + rect.bottom = 0; + + fuAlign = SetTextAlign(hDC, TA_LEFT | TA_TOP | TA_NOUPDATECP); + + /* While more lines print out the text */ + for(i = nStart; i <= nEnd; i++) { + lpLine = LineList_GetLine(lpLL,i); + if (! lpLine) + continue; + + rect.top = rect.bottom; + rect.bottom -= Line_GetHeightInHimetric(lpLine); + + /* Draw the line */ + Line_Draw(lpLine, hDC, &rect, &rectWBounds, FALSE /*fHighlight*/); + } + + SetTextAlign(hDC, fuAlign); + } + + // Get handle to the metafile. + if (!(hMF = CloseMetaFile (hDC))) + return NULL; + + if (!(hMFPict = GlobalAlloc (GMEM_SHARE | GMEM_ZEROINIT, + sizeof (METAFILEPICT)))) { + DeleteMetaFile (hMF); + return NULL; + } + + if (!(lppict = (LPMETAFILEPICT)GlobalLock(hMFPict))) { + DeleteMetaFile (hMF); + GlobalFree (hMFPict); + return NULL; + } + + lppict->mm = MM_ANISOTROPIC; + lppict->hMF = hMF; + lppict->xExt = rect.right; + lppict->yExt = - rect.bottom; // add minus sign to make it +ve + GlobalUnlock (hMFPict); + + return hMFPict; +} + +#endif // OLE_SERVER + + + +#if defined( OLE_CNTR ) + +/************************************************************************* +** ContainerDoc Supprt Functions Used by Container versions +*************************************************************************/ + + +/* Paste OLE Link from clipboard */ +void ContainerDoc_PasteLinkCommand(LPCONTAINERDOC lpContainerDoc) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; + LPDATAOBJECT lpClipboardDataObj = NULL; + BOOL fLink = TRUE; + BOOL fLocalDataObj = FALSE; + BOOL fDisplayAsIcon = FALSE; + SIZEL sizelInSrc; + HCURSOR hPrevCursor; + HGLOBAL hMem = NULL; + HGLOBAL hMetaPict = NULL; + STGMEDIUM medium; + BOOL fStatus; + HRESULT hrErr; + + hrErr = OleGetClipboard((LPDATAOBJECT FAR*)&lpClipboardDataObj); + if (hrErr != NOERROR) + return; // Clipboard seems to be empty or can't be accessed + + // this may take a while, put up hourglass cursor + hPrevCursor = SetCursor(LoadCursor(NULL, IDC_WAIT)); + + /* check if the data on the clipboard is local to our application + ** instance. + */ + if (lpOutlineApp->m_lpClipboardDoc) { + LPOLEDOC lpOleDoc = (LPOLEDOC)lpOutlineApp->m_lpClipboardDoc; + if (lpClipboardDataObj == (LPDATAOBJECT)&lpOleDoc->m_DataObject) + fLocalDataObj = TRUE; + } + + /* OLE2NOTE: we need to check what dwDrawAspect is being + ** transfered. if the data is an object that is displayed as an + ** icon in the source, then we want to keep it as an icon. the + ** aspect the object is displayed in at the source is transfered + ** via the CF_LINKSOURCEDESCRIPTOR format for a PasteLink + ** operation. + */ + if (hMem = OleStdGetData( + lpClipboardDataObj, + lpOleApp->m_cfLinkSrcDescriptor, + NULL, + DVASPECT_CONTENT, + (LPSTGMEDIUM)&medium)) { + LPOBJECTDESCRIPTOR lpOD = GlobalLock(hMem); + fDisplayAsIcon = (lpOD->dwDrawAspect == DVASPECT_ICON ? TRUE : FALSE); + sizelInSrc = lpOD->sizel; // size of object/picture in source (opt.) + GlobalUnlock(hMem); + ReleaseStgMedium((LPSTGMEDIUM)&medium); // equiv to GlobalFree + + if (fDisplayAsIcon) { + hMetaPict = OleStdGetData( + lpClipboardDataObj, + CF_METAFILEPICT, + NULL, + DVASPECT_ICON, + (LPSTGMEDIUM)&medium + ); + if (hMetaPict == NULL) + fDisplayAsIcon = FALSE; // give up; failed to get icon MFP + } + } + + fStatus = ContainerDoc_PasteFormatFromData( + lpContainerDoc, + lpOleApp->m_cfLinkSource, + lpClipboardDataObj, + fLocalDataObj, + fLink, + fDisplayAsIcon, + hMetaPict, + (LPSIZEL)&sizelInSrc + ); + + if (!fStatus) + OutlineApp_ErrorMessage(g_lpApp, ErrMsgPasting); + + if (hMetaPict) + ReleaseStgMedium((LPSTGMEDIUM)&medium); // properly free METAFILEPICT + + if (lpClipboardDataObj) + OleStdRelease((LPUNKNOWN)lpClipboardDataObj); + + SetCursor(hPrevCursor); // restore original cursor +} + + +/* ContainerDoc_PasteFormatFromData +** -------------------------------- +** +** Paste a particular data format from a IDataObject*. The +** IDataObject* may come from the clipboard (GetClipboard) or from a +** drag/drop operation. +** +** Returns TRUE if data was successfully pasted. +** FALSE if data could not be pasted. +*/ +BOOL ContainerDoc_PasteFormatFromData( + LPCONTAINERDOC lpContainerDoc, + CLIPFORMAT cfFormat, + LPDATAOBJECT lpSrcDataObj, + BOOL fLocalDataObj, + BOOL fLink, + BOOL fDisplayAsIcon, + HGLOBAL hMetaPict, + LPSIZEL lpSizelInSrc +) +{ + LPLINELIST lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpContainerDoc)->m_LineList; + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; + LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp; + int nIndex; + int nCount = 0; + HGLOBAL hData; + STGMEDIUM medium; + FORMATETC formatetc; + HRESULT hrErr; + LINERANGE lrSel; + + if (LineList_GetCount(lpLL) == 0) + nIndex = -1; // pasting to empty list + else + nIndex=LineList_GetFocusLineIndex(lpLL); + + if (fLink) { + + /* We should paste a Link to the data */ + + if (cfFormat != lpOleApp->m_cfLinkSource) + return FALSE; // we only support OLE object type links + + nCount = ContainerDoc_PasteOleObject( + lpContainerDoc, + lpSrcDataObj, + OLECREATEFROMDATA_LINK, + cfFormat, + nIndex, + fDisplayAsIcon, + hMetaPict, + lpSizelInSrc + ); + return (nCount > 0 ? TRUE : FALSE); + + } else { + + if (cfFormat == lpContainerApp->m_cfCntrOutl) { + if (fLocalDataObj) { + + /* CASE I: IDataObject* is local to our app + ** + ** if the source of the data is local to our + ** application instance, then we can get direct + ** access to the original OleDoc object that + ** corresponds to the IDataObject* given. + ** CF_CNTROUTL data is passed through a LPSTORAGE. + ** if we call OleGetData asking for CF_CNTROUTL, we + ** will be returned a copy of the existing open pStg + ** of the original source document. we can NOT open + ** streams and sub-storages again via this pStg + ** since it is already open within our same + ** application instance. we must copy the data from + ** the original OleDoc source document. + */ + LPLINELIST lpSrcLL; + LPOLEDOC lpLocalSrcDoc = + ((struct CDocDataObjectImpl FAR*)lpSrcDataObj)->lpOleDoc; + + /* copy all lines from SrcDoc to DestDoc. */ + lpSrcLL = &((LPOUTLINEDOC)lpLocalSrcDoc)->m_LineList; + nCount = LineList_CopySelToDoc( + lpSrcLL, + NULL, + (LPOUTLINEDOC)lpContainerDoc + ); + + } else { + + /* CASE II: IDataObject* is NOT local to our app + ** + ** if the source of the data comes from another + ** application instance. we can call GetDataHere to + ** retrieve the CF_CNTROUTL data. CF_CNTROUTL data + ** is passed through a LPSTORAGE. we MUST use + ** IDataObject::GetDataHere. calling + ** IDataObject::GetData does NOT work because OLE + ** currently does NOT support remoting of a callee + ** allocated root storage back to the caller. this + ** hopefully will be supported in a future version. + ** in order to call GetDataHere we must allocate an + ** IStorage instance for the callee to write into. + ** we will allocate an IStorage docfile that will + ** delete-on-release. we could use either a + ** memory-based storage or a file-based storage. + */ + LPSTORAGE lpTmpStg = OleStdCreateTempStorage( + FALSE /*fUseMemory*/, + STGM_READWRITE | STGM_TRANSACTED |STGM_SHARE_EXCLUSIVE + ); + if (! lpTmpStg) + return FALSE; + + formatetc.cfFormat = cfFormat; + formatetc.ptd = NULL; + formatetc.dwAspect = DVASPECT_CONTENT; + formatetc.tymed = TYMED_ISTORAGE; + formatetc.lindex = -1; + + medium.tymed = TYMED_ISTORAGE; + medium.pstg = lpTmpStg; + medium.pUnkForRelease = NULL; + + OLEDBG_BEGIN2("IDataObject::GetDataHere called\r\n") + hrErr = lpSrcDataObj->lpVtbl->GetDataHere( + lpSrcDataObj, + (LPFORMATETC)&formatetc, + (LPSTGMEDIUM)&medium + ); + OLEDBG_END2 + + if (hrErr == NOERROR) { + nCount = ContainerDoc_PasteCntrOutlData( + lpContainerDoc, + lpTmpStg, + nIndex + ); + } + OleStdVerifyRelease( + (LPUNKNOWN)lpTmpStg, "Temp stg NOT released!\r\n"); + return ((hrErr == NOERROR) ? TRUE : FALSE); + } + + } else if (cfFormat == lpOutlineApp->m_cfOutline) { + + hData = OleStdGetData( + lpSrcDataObj, + lpOutlineApp->m_cfOutline, + NULL, + DVASPECT_CONTENT, + (LPSTGMEDIUM)&medium + ); + nCount = OutlineDoc_PasteOutlineData( + (LPOUTLINEDOC)lpContainerDoc, + hData, + nIndex + ); + // OLE2NOTE: we must free data handle by releasing the medium + ReleaseStgMedium((LPSTGMEDIUM)&medium); + + } else if (cfFormat == lpOleApp->m_cfEmbedSource || + cfFormat == lpOleApp->m_cfEmbeddedObject || + cfFormat == lpOleApp->m_cfFileName) { + /* OLE2NOTE: OleCreateFromData API creates an OLE object if + ** CF_EMBEDDEDOBJECT, CF_EMBEDSOURCE, or CF_FILENAME are + ** available from the source data object. the + ** CF_FILENAME case arises when a file is copied to the + ** clipboard from the FileManager. if the file has an + ** associated class (see GetClassFile API), then an + ** object of that class is created. otherwise an OLE 1.0 + ** Packaged object is created. + */ + nCount = ContainerDoc_PasteOleObject( + lpContainerDoc, + lpSrcDataObj, + OLECREATEFROMDATA_OBJECT, + 0, /* N/A -- cfFormat */ + nIndex, + fDisplayAsIcon, + hMetaPict, + lpSizelInSrc + ); + return (nCount > 0 ? TRUE : FALSE); + + } else if (cfFormat == CF_METAFILEPICT + || cfFormat == CF_DIB + || cfFormat == CF_BITMAP) { + + /* OLE2NOTE: OleCreateStaticFromData API creates an static + ** OLE object if CF_METAFILEPICT, CF_DIB, or CF_BITMAP is + ** CF_EMBEDDEDOBJECT, CF_EMBEDSOURCE, or CF_FILENAME are + ** available from the source data object. + */ + nCount = ContainerDoc_PasteOleObject( + lpContainerDoc, + lpSrcDataObj, + OLECREATEFROMDATA_STATIC, + cfFormat, + nIndex, + fDisplayAsIcon, + hMetaPict, + lpSizelInSrc + ); + return (nCount > 0 ? TRUE : FALSE); + + } else if(cfFormat == CF_TEXT) { + + hData = OleStdGetData( + lpSrcDataObj, + CF_TEXT, + NULL, + DVASPECT_CONTENT, + (LPSTGMEDIUM)&medium + ); + nCount = OutlineDoc_PasteTextData( + (LPOUTLINEDOC)lpContainerDoc, + hData, + nIndex + ); + // OLE2NOTE: we must free data handle by releasing the medium + ReleaseStgMedium((LPSTGMEDIUM)&medium); + + } else { + return FALSE; // no acceptable format available to paste + } + } + + lrSel.m_nStartLine = nIndex + nCount; + lrSel.m_nEndLine = nIndex + 1; + LineList_SetSel(lpLL, &lrSel); + return TRUE; +} + + +/* ContainerDoc_PasteCntrOutlData + * ------------------------------- + * + * Load the lines stored in a lpSrcStg (stored in CF_CNTROUTL format) + * into the document. + * + * Return the number of items added + */ +int ContainerDoc_PasteCntrOutlData( + LPCONTAINERDOC lpDestContainerDoc, + LPSTORAGE lpSrcStg, + int nStartIndex +) +{ + int nCount; + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + LPOUTLINEDOC lpDestOutlineDoc = (LPOUTLINEDOC)lpDestContainerDoc; + LPOUTLINEDOC lpSrcOutlineDoc; + LPLINELIST lpSrcLL; + + // create a temp document that will be used to load the lpSrcStg data. + lpSrcOutlineDoc = (LPOUTLINEDOC)OutlineApp_CreateDoc(lpOutlineApp, FALSE); + if ( ! lpSrcOutlineDoc ) + return 0; + + if (! OutlineDoc_LoadFromStg(lpSrcOutlineDoc, lpSrcStg)) + goto error; + + /* copy all lines from the SrcDoc to the DestDoc. */ + lpSrcLL = &lpSrcOutlineDoc->m_LineList; + nCount = LineList_CopySelToDoc(lpSrcLL, NULL, lpDestOutlineDoc); + + if (lpSrcOutlineDoc) // destroy temporary document. + OutlineDoc_Close(lpSrcOutlineDoc, OLECLOSE_NOSAVE); + + return nCount; + +error: + if (lpSrcOutlineDoc) // destroy temporary document. + OutlineDoc_Close(lpSrcOutlineDoc, OLECLOSE_NOSAVE); + + return 0; +} + + +/* ContainerDoc_QueryPasteFromData +** ------------------------------- +** +** Check if the IDataObject* offers data in a format that we can +** paste. The IDataObject* may come from the clipboard +** (GetClipboard) or from a drag/drop operation. +** In this function we look if one of the following formats is +** offered: +** CF_OUTLINE +** +** CF_TEXT +** +** NOTE: fLink is specified and CF_LINKSOURCE is available then TRUE +** is returned, else FALSE. +** +** Returns TRUE if paste can be performed +** FALSE if paste is not possible. +*/ +BOOL ContainerDoc_QueryPasteFromData( + LPCONTAINERDOC lpContainerDoc, + LPDATAOBJECT lpSrcDataObj, + BOOL fLink +) +{ + LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; + + if (fLink) { + /* check if we can paste a Link to the data */ + if (OleQueryLinkFromData(lpSrcDataObj) != NOERROR) + return FALSE; // linking is NOT possible + } else { + + int nFmtEtc; + + nFmtEtc = OleStdGetPriorityClipboardFormat( + lpSrcDataObj, + lpOleApp->m_arrPasteEntries, + lpOleApp->m_nPasteEntries + ); + + if (nFmtEtc < 0) + return FALSE; // there is no format we like + } + + return TRUE; +} + + +/* ContainerDoc_PasteOleObject +** --------------------------- +** +** Embed or link an OLE object. the source of the data is a pointer +** to an IDataObject. normally this lpSrcDataObj comes from the +** clipboard after call OleGetClipboard. +** +** dwCreateType controls what type of object will created: +** OLECREATEFROMDATA_LINK -- OleCreateLinkFromData will be called +** OLECREATEFROMDATA_OBJECT -- OleCreateFromData will be called +** OLECREATEFROMDATA_STATIC -- OleCreateStaticFromData will be called +** cfFormat controls the type of static +** a CONTAINERLINE object is created to manage the OLE object. this +** CONTAINERLINE is added to the ContainerDoc after line nIndex. +** +*/ +int ContainerDoc_PasteOleObject( + LPCONTAINERDOC lpContainerDoc, + LPDATAOBJECT lpSrcDataObj, + DWORD dwCreateType, + CLIPFORMAT cfFormat, + int nIndex, + BOOL fDisplayAsIcon, + HGLOBAL hMetaPict, + LPSIZEL lpSizelInSrc +) +{ + LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList; + LPLINE lpLine = NULL; + HDC hDC; + int nTab = 0; + char szStgName[CWCSTORAGENAME]; + LPCONTAINERLINE lpContainerLine = NULL; + + ContainerDoc_GetNextStgName(lpContainerDoc, szStgName, sizeof(szStgName)); + + /* default the new line to have the same indent as previous line */ + lpLine = LineList_GetLine(lpLL, nIndex); + if (lpLine) + nTab = Line_GetTabLevel(lpLine); + + hDC = LineList_GetDC(lpLL); + + lpContainerLine = ContainerLine_CreateFromData( + hDC, + nTab, + lpContainerDoc, + lpSrcDataObj, + dwCreateType, + cfFormat, + fDisplayAsIcon, + hMetaPict, + szStgName + ); + LineList_ReleaseDC(lpLL, hDC); + + if (! lpContainerLine) + goto error; + + /* add a ContainerLine object to the document's LineList. The + ** ContainerLine manages the rectangle on the screen occupied by + ** the OLE object. later when the app is updated to support + ** extended layout, there could be more than one Line associated + ** with the OLE object. + */ + + LineList_AddLine(lpLL, (LPLINE)lpContainerLine, nIndex); + + /* OLE2NOTE: if the source of the OLE object just pasted, passed a + ** non-zero sizel in the ObjectDescriptor, then we will try to + ** keep the object the same size as it is in the source. this + ** may be a scaled size if the object had been resized in the + ** source container. if the source did not give a valid sizel, + ** then we will retrieve the size of the object by calling + ** IViewObject2::GetExtent. + */ + if (lpSizelInSrc && (lpSizelInSrc->cx != 0 || lpSizelInSrc->cy != 0)) { + ContainerLine_UpdateExtent(lpContainerLine, lpSizelInSrc); + } else + ContainerLine_UpdateExtent(lpContainerLine, NULL); + + OutlineDoc_SetModified((LPOUTLINEDOC)lpContainerDoc, TRUE, TRUE, TRUE); + + return 1; // one line added to LineList + +error: + // NOTE: if ContainerLine_CreateFromClip failed + OutlineApp_ErrorMessage(g_lpApp, "Paste Object failed!"); + return 0; // no lines added to line list +} + + +/* ContainerDoc_GetData + * -------------------- + * + * Render data from the document on a CALLEE allocated STGMEDIUM. + * This routine is called via IDataObject::GetData. + */ +HRESULT ContainerDoc_GetData ( + LPCONTAINERDOC lpContainerDoc, + LPFORMATETC lpformatetc, + LPSTGMEDIUM lpMedium +) +{ + LPOLEDOC lpOleDoc = (LPOLEDOC)lpContainerDoc; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerDoc; + LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp; + LPOLEAPP lpOleApp = (LPOLEAPP)lpContainerApp; + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpContainerApp; + HRESULT hrErr; + SCODE sc; + + // OLE2NOTE: we must set out pointer parameters to NULL + lpMedium->pUnkForRelease = NULL; + + /* OLE2NOTE: we must set all out pointer parameters to NULL. */ + lpMedium->tymed = TYMED_NULL; + lpMedium->pUnkForRelease = NULL; // we transfer ownership to caller + lpMedium->hGlobal = NULL; + + if (lpformatetc->cfFormat == lpContainerApp->m_cfCntrOutl) { + + /* OLE2NOTE: currently OLE does NOT support remoting a root + ** level IStorage (either memory or file based) as an OUT + ** parameter. thus, we can NOT support GetData for this + ** TYMED_ISTORAGE based format. the caller MUST call GetDataHere. + */ + sc = DV_E_FORMATETC; + goto error; + + } else if (!lpContainerDoc->m_fEmbeddedObjectAvail && + lpformatetc->cfFormat == lpOutlineApp->m_cfOutline) { + // Verify caller asked for correct medium + if (!(lpformatetc->tymed & TYMED_HGLOBAL)) { + sc = DV_E_FORMATETC; + goto error; + } + + lpMedium->hGlobal = OutlineDoc_GetOutlineData(lpOutlineDoc, NULL); + if (! lpMedium->hGlobal) { + sc = E_OUTOFMEMORY; + goto error; + } + + lpMedium->tymed = TYMED_HGLOBAL; + OleDbgOut3("ContainerDoc_GetData: rendered CF_OUTLINE\r\n"); + return NOERROR; + + } else if (!lpContainerDoc->m_fEmbeddedObjectAvail && + lpformatetc->cfFormat == CF_TEXT) { + // Verify caller asked for correct medium + if (!(lpformatetc->tymed & TYMED_HGLOBAL)) { + sc = DV_E_FORMATETC; + goto error; + } + + lpMedium->hGlobal = OutlineDoc_GetTextData ( + (LPOUTLINEDOC)lpContainerDoc, + NULL + ); + if (! lpMedium->hGlobal) { + sc = E_OUTOFMEMORY; + goto error; + } + + lpMedium->tymed = TYMED_HGLOBAL; + OleDbgOut3("ContainerDoc_GetData: rendered CF_TEXT\r\n"); + return NOERROR; + + } else if ( lpformatetc->cfFormat == lpOleApp->m_cfObjectDescriptor || + (lpformatetc->cfFormat == lpOleApp->m_cfLinkSrcDescriptor && + lpOleDoc->m_fLinkSourceAvail) ) { + // Verify caller asked for correct medium + if (!(lpformatetc->tymed & TYMED_HGLOBAL)) { + sc = DV_E_FORMATETC; + goto error; + } + + lpMedium->hGlobal = OleDoc_GetObjectDescriptorData ( + (LPOLEDOC)lpContainerDoc, + NULL + ); + if (! lpMedium->hGlobal) { + sc = E_OUTOFMEMORY; + goto error; + } + + lpMedium->tymed = TYMED_HGLOBAL; +#if defined( _DEBUG ) + if (lpformatetc->cfFormat == lpOleApp->m_cfObjectDescriptor) + OleDbgOut3( + "ContainerDoc_GetData: rendered CF_OBJECTDESCRIPTOR\r\n"); + else + OleDbgOut3( + "ContainerDoc_GetData: rendered CF_LINKSRCDESCRIPTOR\r\n"); +#endif + return NOERROR; + + } else if (lpContainerDoc->m_fEmbeddedObjectAvail) { + + /* OLE2NOTE: if this document contains a single OLE object + ** (ie. cfEmbeddedObject data format is available), then + ** the formats offered via our IDataObject must include + ** the formats available from the OLE object itself. + ** thus, we delegate this call to the IDataObject* of the + ** OLE object. + */ + + if (lpformatetc->cfFormat == lpOleApp->m_cfEmbeddedObject) { + LPPERSISTSTORAGE lpPersistStg = + (LPPERSISTSTORAGE)ContainerDoc_GetSingleOleObject( + lpContainerDoc, + &IID_IPersistStorage, + NULL + ); + + if (! lpPersistStg) + return ResultFromScode(DV_E_FORMATETC); + + /* render CF_EMBEDDEDOBJECT by asking the object to save + ** into a temporary, DELETEONRELEASE pStg allocated by us. + */ + + hrErr = OleStdGetOleObjectData( + lpPersistStg, + lpformatetc, + lpMedium, + FALSE /* fUseMemory -- (use file-base stg) */ + ); + OleStdRelease((LPUNKNOWN)lpPersistStg); + if (hrErr != NOERROR) { + sc = GetScode(hrErr); + goto error; + } + OleDbgOut3("ContainerDoc_GetData: rendered CF_EMBEDDEDOBJECT\r\n"); + return hrErr; + + } else if (lpformatetc->cfFormat == CF_METAFILEPICT) { + + /* OLE2NOTE: as a container which draws objects, when a single + ** OLE object is copied, we can give the Metafile picture of + ** the object. + */ + LPCONTAINERLINE lpContainerLine; + LPOLEOBJECT lpOleObj; + SIZEL sizelOleObject; + + // Verify caller asked for correct medium + if (!(lpformatetc->tymed & TYMED_MFPICT)) { + sc = DV_E_FORMATETC; + goto error; + } + + lpOleObj = (LPOLEOBJECT)ContainerDoc_GetSingleOleObject( + lpContainerDoc, + &IID_IOleObject, + (LPCONTAINERLINE FAR*)&lpContainerLine + ); + + if (! lpOleObj) { + sc = E_OUTOFMEMORY; // could not load object + goto error; + } + if (lpformatetc->dwAspect & lpContainerLine->m_dwDrawAspect) { + LPLINE lpLine = (LPLINE)lpContainerLine; + + /* render CF_METAFILEPICT by drawing the object into + ** a metafile DC + */ + + /* OLE2NOTE: Get size that object is being drawn. If the + ** object has been scaled because the user resized the + ** object, then we want to render a metafile with the + ** scaled size. + */ + sizelOleObject.cx = lpLine->m_nWidthInHimetric; + sizelOleObject.cy = lpLine->m_nHeightInHimetric; + + lpMedium->hGlobal = OleStdGetMetafilePictFromOleObject( + lpOleObj, + lpContainerLine->m_dwDrawAspect, + (LPSIZEL)&sizelOleObject, + lpformatetc->ptd + ); + OleStdRelease((LPUNKNOWN)lpOleObj); + if (! lpMedium->hGlobal) { + sc = E_OUTOFMEMORY; + goto error; + } + + lpMedium->tymed = TYMED_MFPICT; + OleDbgOut3("ContainerDoc_GetData: rendered CF_METAFILEPICT\r\n"); + return NOERROR; + } else { + // improper aspect requested + OleStdRelease((LPUNKNOWN)lpOleObj); + return ResultFromScode(DV_E_FORMATETC); + } + + } else if (lpformatetc->cfFormat == lpOleApp->m_cfLinkSource) { + if (lpOleDoc->m_fLinkSourceAvail) { + LPMONIKER lpmk; + + lpmk = ContainerLine_GetFullMoniker( + lpContainerDoc->m_lpSrcContainerLine, + GETMONIKER_FORCEASSIGN + ); + if (lpmk) { + hrErr = OleStdGetLinkSourceData( + lpmk, + &lpContainerDoc->m_clsidOleObjCopied, + lpformatetc, + lpMedium + ); + OleStdRelease((LPUNKNOWN)lpmk); + if (hrErr != NOERROR) { + sc = GetScode(hrErr); + goto error; + } + OleDbgOut3("ContainerDoc_GetData: rendered CF_LINKSOURCE\r\n"); + return hrErr; + } else { + sc = DV_E_FORMATETC; + goto error; + } + } else { + sc = DV_E_FORMATETC; + goto error; + } + + } +#if defined( OPTIONAL_ADVANCED_DATA_TRANSFER ) + /* OLE2NOTE: optionally, a container that wants to have a + ** potentially richer data transfer, can enumerate the data + ** formats from the OLE object's cache and offer them too. if + ** the object has a special handler, then it might be able to + ** render additional data formats. in this case, the + ** container must delegate the GetData call to the object if + ** it does not directly support the format. + ** + ** CNTROUTL does NOT enumerate the cache; it implements the + ** simpler strategy of offering a static list of formats. + ** thus the delegation is NOT required. + */ + else { + + /* OLE2NOTE: we delegate this call to the IDataObject* of the + ** OLE object. + */ + LPDATAOBJECT lpDataObj; + + lpDataObj = (LPDATAOBJECT)ContainerDoc_GetSingleOleObject( + lpContainerDoc, + &IID_IDataObject, + NULL + ); + + if (! lpDataObj) { + sc = DV_E_FORMATETC; + goto error; + } + + OLEDBG_BEGIN2("ContainerDoc_GetData: delegate to OLE obj\r\n") + hrErr=lpDataObj->lpVtbl->GetData(lpDataObj,lpformatetc,lpMedium); + OLEDBG_END2 + + OleStdRelease((LPUNKNOWN)lpDataObj); + return hrErr; + } +#endif // ! OPTIONAL_ADVANCED_DATA_TRANSFER + + } + + // if we get here then we do NOT support the requested format + sc = DV_E_FORMATETC; + +error: + return ResultFromScode(sc); +} + + +/* ContainerDoc_GetDataHere + * ------------------------ + * + * Render data from the document on a CALLER allocated STGMEDIUM. + * This routine is called via IDataObject::GetDataHere. + */ +HRESULT ContainerDoc_GetDataHere ( + LPCONTAINERDOC lpContainerDoc, + LPFORMATETC lpformatetc, + LPSTGMEDIUM lpMedium +) +{ + LPOLEDOC lpOleDoc = (LPOLEDOC)lpContainerDoc; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerDoc; + LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp; + LPOLEAPP lpOleApp = (LPOLEAPP)lpContainerApp; + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpContainerApp; + HRESULT hrErr; + + // OLE2NOTE: lpMedium is an IN parameter. we should NOT set + // lpMedium->pUnkForRelease to NULL + + // we only support IStorage medium + if (lpformatetc->cfFormat == lpContainerApp->m_cfCntrOutl) { + if (!(lpformatetc->tymed & TYMED_ISTORAGE)) + return ResultFromScode(DV_E_FORMATETC); + + if (lpMedium->tymed == TYMED_ISTORAGE) { + /* Caller has allocated the storage. we must copy all of our + ** data into his storage. + */ + + /* OLE2NOTE: we must be sure to write our class ID into our + ** storage. this information is used by OLE to determine the + ** class of the data stored in our storage. + */ + if((hrErr=WriteClassStg(lpMedium->pstg,&CLSID_APP)) != NOERROR) + return hrErr; + + OutlineDoc_SaveSelToStg( + (LPOUTLINEDOC)lpContainerDoc, + NULL, /* entire doc */ + lpContainerApp->m_cfCntrOutl, + lpMedium->pstg, + FALSE, /* fSameAsLoad */ + FALSE /* fRemember */ + ); + OleStdCommitStorage(lpMedium->pstg); + + OleDbgOut3("ContainerDoc_GetDataHere: rendered CF_CNTROUTL\r\n"); + return NOERROR; + } else { + // we only support IStorage medium + return ResultFromScode(DV_E_FORMATETC); + } + + } else if (lpContainerDoc->m_fEmbeddedObjectAvail) { + + /* OLE2NOTE: if this document contains a single OLE object + ** (ie. cfEmbeddedObject data format is available), then + ** the formats offered via our IDataObject must include + ** CF_EMBEDDEDOBJECT and the formats available from the OLE + ** object itself. + */ + + if (lpformatetc->cfFormat == lpOleApp->m_cfEmbeddedObject) { + LPPERSISTSTORAGE lpPersistStg = + (LPPERSISTSTORAGE)ContainerDoc_GetSingleOleObject( + lpContainerDoc, + &IID_IPersistStorage, + NULL + ); + + if (! lpPersistStg) { + return ResultFromScode(E_OUTOFMEMORY); + } + /* render CF_EMBEDDEDOBJECT by asking the object to save + ** into the IStorage allocated by the caller. + */ + + hrErr = OleStdGetOleObjectData( + lpPersistStg, + lpformatetc, + lpMedium, + FALSE /* fUseMemory -- N/A */ + ); + OleStdRelease((LPUNKNOWN)lpPersistStg); + if (hrErr != NOERROR) { + return hrErr; + } + OleDbgOut3("ContainerDoc_GetDataHere: rendered CF_EMBEDDEDOBJECT\r\n"); + return hrErr; + + } else if (lpformatetc->cfFormat == lpOleApp->m_cfLinkSource) { + if (lpOleDoc->m_fLinkSourceAvail) { + LPMONIKER lpmk; + + lpmk = ContainerLine_GetFullMoniker( + lpContainerDoc->m_lpSrcContainerLine, + GETMONIKER_FORCEASSIGN + ); + if (lpmk) { + hrErr = OleStdGetLinkSourceData( + lpmk, + &lpContainerDoc->m_clsidOleObjCopied, + lpformatetc, + lpMedium + ); + OleStdRelease((LPUNKNOWN)lpmk); + OleDbgOut3("ContainerDoc_GetDataHere: rendered CF_LINKSOURCE\r\n"); + return hrErr; + } else { + return ResultFromScode(E_FAIL); + } + } else { + return ResultFromScode(DV_E_FORMATETC); + } + + } else { +#if !defined( OPTIONAL_ADVANCED_DATA_TRANSFER ) + return ResultFromScode(DV_E_FORMATETC); +#endif +#if defined( OPTIONAL_ADVANCED_DATA_TRANSFER ) + /* OLE2NOTE: optionally, a container that wants to have a + ** potentially richer data transfer, can enumerate the data + ** formats from the OLE object's cache and offer them too. if + ** the object has a special handler, then it might be able to + ** render additional data formats. in this case, the + ** container must delegate the GetData call to the object if + ** it does not directly support the format. + ** + ** CNTROUTL does NOT enumerate the cache; it implements the + ** simpler strategy of offering a static list of formats. + ** thus the delegation is NOT required. + */ + /* OLE2NOTE: we delegate this call to the IDataObject* of the + ** OLE object. + */ + LPDATAOBJECT lpDataObj; + + lpDataObj = (LPDATAOBJECT)ContainerDoc_GetSingleOleObject( + lpContainerDoc, + &IID_IDataObject, + NULL + ); + + if (! lpDataObj) + return ResultFromScode(DV_E_FORMATETC); + + OLEDBG_BEGIN2("ContainerDoc_GetDataHere: delegate to OLE obj\r\n") + hrErr = lpDataObj->lpVtbl->GetDataHere( + lpDataObj, + lpformatetc, + lpMedium + ); + OLEDBG_END2 + + OleStdRelease((LPUNKNOWN)lpDataObj); + return hrErr; +#endif // OPTIONAL_ADVANCED_DATA_TRANSFER + } + } else { + return ResultFromScode(DV_E_FORMATETC); + } +} + + +/* ContainerDoc_QueryGetData + * ------------------------- + * + * Answer if a particular data format is supported via GetData/GetDataHere. + * This routine is called via IDataObject::QueryGetData. + */ +HRESULT ContainerDoc_QueryGetData ( + LPCONTAINERDOC lpContainerDoc, + LPFORMATETC lpformatetc +) +{ + LPOLEDOC lpOleDoc = (LPOLEDOC)lpContainerDoc; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerDoc; + LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp; + LPOLEAPP lpOleApp = (LPOLEAPP)lpContainerApp; + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpContainerApp; + LPDATAOBJECT lpDataObj = NULL; + LPCONTAINERLINE lpContainerLine = NULL; + SCODE sc; + HRESULT hrErr; + + if (lpContainerDoc->m_fEmbeddedObjectAvail) { + lpDataObj = (LPDATAOBJECT)ContainerDoc_GetSingleOleObject( + lpContainerDoc, + &IID_IDataObject, + (LPCONTAINERLINE FAR*)&lpContainerLine + ); + } + + /* Caller is querying if we support certain format but does not + ** want any data actually returned. + */ + if (lpformatetc->cfFormat == lpContainerApp->m_cfCntrOutl) { + // we only support ISTORAGE medium + sc = GetScode( OleStdQueryFormatMedium(lpformatetc, TYMED_ISTORAGE) ); + + } else if (lpformatetc->cfFormat == lpOleApp->m_cfEmbeddedObject && + lpContainerDoc->m_fEmbeddedObjectAvail ) { + sc = GetScode( OleStdQueryOleObjectData(lpformatetc) ); + + } else if (lpformatetc->cfFormat == lpOleApp->m_cfLinkSource && + lpOleDoc->m_fLinkSourceAvail) { + sc = GetScode( OleStdQueryLinkSourceData(lpformatetc) ); + + // CF_TEXT and CF_OUTLINE are NOT supported when single object is copied + } else if (!lpContainerDoc->m_fEmbeddedObjectAvail && + (lpformatetc->cfFormat == (lpOutlineApp)->m_cfOutline || + lpformatetc->cfFormat == CF_TEXT) ) { + // we only support HGLOBAL medium + sc = GetScode( OleStdQueryFormatMedium(lpformatetc, TYMED_HGLOBAL) ); + + } else if ( lpformatetc->cfFormat == lpOleApp->m_cfObjectDescriptor || + (lpformatetc->cfFormat == lpOleApp->m_cfLinkSrcDescriptor && + lpOleDoc->m_fLinkSourceAvail) ) { + sc = GetScode( OleStdQueryObjectDescriptorData(lpformatetc) ); + + } else if (lpformatetc->cfFormat == CF_METAFILEPICT && + lpContainerDoc->m_fEmbeddedObjectAvail && lpContainerLine && + (lpformatetc->dwAspect & lpContainerLine->m_dwDrawAspect)) { + + /* OLE2NOTE: as a container which draws objects, when a single + ** OLE object is copied, we can give the Metafile picture of + ** the object. + */ + // we only support MFPICT medium + sc = GetScode( OleStdQueryFormatMedium(lpformatetc, TYMED_MFPICT) ); + + } else if (lpDataObj) { + + /* OLE2NOTE: if this document contains a single OLE object + ** (ie. cfEmbeddedObject data format is available), then + ** the formats offered via our IDataObject must include + ** the formats available from the OLE object itself. + ** thus we delegate this call to the IDataObject* of the + ** OLE object. + */ + OLEDBG_BEGIN2("ContainerDoc_QueryGetData: delegate to OLE obj\r\n") + hrErr = lpDataObj->lpVtbl->QueryGetData(lpDataObj, lpformatetc); + OLEDBG_END2 + + sc = GetScode(hrErr); + + } else { + sc = DV_E_FORMATETC; + } + + if (lpDataObj) + OleStdRelease((LPUNKNOWN)lpDataObj); + return ResultFromScode(sc); +} + + + +/* ContainerDoc_SetData + * -------------------- + * + * Set (modify) data of the document. + * This routine is called via IDataObject::SetData. + */ +HRESULT ContainerDoc_SetData ( + LPCONTAINERDOC lpContainerDoc, + LPFORMATETC lpformatetc, + LPSTGMEDIUM lpmedium, + BOOL fRelease +) +{ + /* in the container version of Outline, only DataTransferDoc's support + ** IDataObject interface; the user documents do not support + ** IDataObject. DataTransferDoc's do not accept SetData calls. + */ + return ResultFromScode(DV_E_FORMATETC); +} + + +/* ContainerDoc_EnumFormatEtc + * -------------------------- + * + * Return an enumerator which enumerates the data accepted/offered by + * the document. + * This routine is called via IDataObject::SetData. + */ +HRESULT ContainerDoc_EnumFormatEtc( + LPCONTAINERDOC lpContainerDoc, + DWORD dwDirection, + LPENUMFORMATETC FAR* lplpenumFormatEtc +) +{ + LPOLEDOC lpOleDoc = (LPOLEDOC)lpContainerDoc; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerDoc; + LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; + LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)lpOleApp; + int nActualFmts; + int i; + SCODE sc = S_OK; + + /* the Container-Only version of Outline does NOT offer + ** IDataObject interface from its User documents. + */ + if (! lpOutlineDoc->m_fDataTransferDoc) + return ResultFromScode(E_FAIL); + + if (dwDirection == DATADIR_GET) { + if (lpContainerDoc->m_fEmbeddedObjectAvail) { + + /* OLE2NOTE: if this document contains a single OLE object + ** (ie. cfEmbeddedObject data format is available), then + ** the formats offered via our enumerator must include + ** the formats available from the OLE object itself. we + ** have previously set up a special array of FORMATETC's + ** in OutlineDoc_CreateDataTransferDoc routine which includes + ** the combination of data we offer directly and data + ** offered by the OLE object. + */ + + /* If the document does not have a Moniker, then exclude + ** CF_LINKSOURCE CF_LINKSRCDESCRIPTOR from the list of + ** formats available. these formats are deliberately + ** listed last in the array of possible "Get" formats. + */ + nActualFmts = lpContainerApp->m_nSingleObjGetFmts; + if (! lpOleDoc->m_fLinkSourceAvail) + nActualFmts -= 2; + + // set correct dwDrawAspect for METAFILEPICT of object copied + for (i = 0; i < nActualFmts; i++) { + if (lpContainerApp->m_arrSingleObjGetFmts[i].cfFormat == + CF_METAFILEPICT) { + lpContainerApp->m_arrSingleObjGetFmts[i].dwAspect = + lpContainerDoc->m_dwAspectOleObjCopied; + break; // DONE + } + } + *lplpenumFormatEtc = OleStdEnumFmtEtc_Create( + nActualFmts, lpContainerApp->m_arrSingleObjGetFmts); + if (*lplpenumFormatEtc == NULL) + sc = E_OUTOFMEMORY; + + } else { + + /* This document does NOT offer cfEmbeddedObject, + ** therefore we can simply enumerate the + ** static list of formats that we handle directly. + */ + *lplpenumFormatEtc = OleStdEnumFmtEtc_Create( + lpOleApp->m_nDocGetFmts, lpOleApp->m_arrDocGetFmts); + if (*lplpenumFormatEtc == NULL) + sc = E_OUTOFMEMORY; + } + } else if (dwDirection == DATADIR_SET) { + /* OLE2NOTE: a document that is used to transfer data + ** (either via the clipboard or drag/drop does NOT + ** accept SetData on ANY format! + */ + sc = E_NOTIMPL; + + } else { + sc = E_NOTIMPL; + } + + return ResultFromScode(sc); +} + + +#if defined( OPTIONAL_ADVANCED_DATA_TRANSFER ) +/* OLE2NOTE: optionally, a container that wants to have a +** potentially richer data transfer, can enumerate the data +** formats from the OLE object's cache and offer them too. if +** the object has a special handler, then it might be able to +** render additional data formats. +** +** CNTROUTL does NOT enumerate the cache; it implements the simpler +** strategy of offering a static list of formats. the following +** function is included in order to illustrates how enumerating the +** cache could be done. CNTROUTL does NOT call this function. +** +*/ + +/* ContainerDoc_SetupDocGetFmts +** ---------------------------- +** Setup the combined list of formats that this data transfer +** ContainerDoc which contains a single OLE object should offer. +** +** OLE2NOTE: The list of formats that should be offered when a +** single OLE object is being transfered include the following: +** * any formats the container app wants to give +** * CF_EMBEDDEDOBJECT +** * CF_METAFILEPICT +** * any formats that the OLE object's cache can offer directly +** +** We will offer the following formats in the order given: +** 1. CF_CNTROUTL +** 2. CF_EMBEDDEDOBJECT +** 3. CF_OBJECTDESCRIPTOR +** 4. CF_METAFILEPICT +** 5. +** 6. CF_LINKSOURCE +** 7. CF_LINKSRCDESCRIPTOR +*/ +BOOL ContainerDoc_SetupDocGetFmts( + LPCONTAINERDOC lpContainerDoc, + LPCONTAINERLINE lpContainerLine +) +{ + LPOLEDOC lpOleDoc = (LPOLEDOC)lpContainerDoc; + LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; + LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp; + LPOLECACHE lpOleCache; + HRESULT hrErr; + STATDATA StatData; + LPENUMSTATDATA lpEnumStatData = NULL; + LPFORMATETC lparrDocGetFmts = NULL; + UINT nOleObjFmts = 0; + UINT nTotalFmts; + UINT i; + UINT iFmt; + + lpOleCache = (LPOLECACHE)OleStdQueryInterface( + (LPUNKNOWN)lpContainerLine->m_lpOleObj, + &IID_IOleCache + ); + if (lpOleCache) { + OLEDBG_BEGIN2("IOleCache::EnumCache called\r\n") + hrErr = lpOleCache->lpVtbl->EnumCache( + lpOleCache, + (LPENUMSTATDATA FAR*)&lpEnumStatData + ); + OLEDBG_END2 + } + + if (lpEnumStatData) { + /* Cache enumerator is available. count the number of + ** formats that the OLE object's cache offers. + */ + while(lpEnumStatData->lpVtbl->Next( + lpEnumStatData, + 1, + (LPSTATDATA)&StatData, + NULL) == NOERROR) { + nOleObjFmts++; + // OLE2NOTE: we MUST free the TargetDevice + OleStdFree(StatData.formatetc.ptd); + } + lpEnumStatData->lpVtbl->Reset(lpEnumStatData); // reset for next loop + } + + /* OLE2NOTE: the maximum total number of formats that our IDataObject + ** could offer equals the sum of the following: + ** n offered by the OLE object's cache + ** + n normally offered by our app + ** + 1 CF_EMBEDDEDOBJECT + ** + 1 CF_METAFILEPICT + ** + 1 CF_LINKSOURCE + ** + 1 CF_LINKSRCDESCRIPTOR + ** the actual number of formats that we can offer could be less + ** than this total if there is any clash between the formats + ** that we offer directly and those offered by the cache. if + ** there is a clash, the container's rendering overrides that of + ** the object. eg.: as a container transfering an OLE object we + ** should directly offer CF_METAFILEPICT to guarantee that this + ** format is always available. thus, if the cache offers + ** CF_METAFILEPICT then it is skipped. + */ + nTotalFmts = nOleObjFmts + lpOleApp->m_nDocGetFmts + 4; + lparrDocGetFmts = (LPFORMATETC)New (nTotalFmts * sizeof(FORMATETC)); + + OleDbgAssertSz(lparrDocGetFmts != NULL,"Error allocating arrDocGetFmts"); + if (lparrDocGetFmts == NULL) + return FALSE; + + for (i = 0, iFmt = 0; i < lpOleApp->m_nDocGetFmts; i++) { + _fmemcpy((LPFORMATETC)&lparrDocGetFmts[iFmt++], + (LPFORMATETC)&lpOleApp->m_arrDocGetFmts[i], + sizeof(FORMATETC) + ); + if (lpOleApp->m_arrDocGetFmts[i].cfFormat == + lpContainerApp->m_cfCntrOutl) { + /* insert CF_EMBEDDEDOBJECT, CF_METAFILEPICT, and formats + ** available from the OLE object's cache following + ** CF_CNTROUTL. + */ + lparrDocGetFmts[iFmt].cfFormat = lpOleApp->m_cfEmbeddedObject; + lparrDocGetFmts[iFmt].ptd = NULL; + lparrDocGetFmts[iFmt].dwAspect = DVASPECT_CONTENT; + lparrDocGetFmts[iFmt].tymed = TYMED_ISTORAGE; + lparrDocGetFmts[iFmt].lindex = -1; + iFmt++; + lparrDocGetFmts[iFmt].cfFormat = CF_METAFILEPICT; + lparrDocGetFmts[iFmt].ptd = NULL; + lparrDocGetFmts[iFmt].dwAspect = lpContainerLine->m_dwDrawAspect; + lparrDocGetFmts[iFmt].tymed = TYMED_MFPICT; + lparrDocGetFmts[iFmt].lindex = -1; + iFmt++; + + if (lpEnumStatData) { + /* Cache enumerator is available. enumerate all of + ** the formats that the OLE object's cache offers. + */ + while(lpEnumStatData->lpVtbl->Next( + lpEnumStatData, + 1, + (LPSTATDATA)&StatData, + NULL) == NOERROR) { + /* check if the format clashes with one of our fmts */ + if (StatData.formatetc.cfFormat != CF_METAFILEPICT + && ! OleStdIsDuplicateFormat( + (LPFORMATETC)&StatData.formatetc, + lpOleApp->m_arrDocGetFmts, + lpOleApp->m_nDocGetFmts)) { + OleStdCopyFormatEtc( + &(lparrDocGetFmts[iFmt]),&StatData.formatetc); + iFmt++; + } + // OLE2NOTE: we MUST free the TargetDevice + OleStdFree(StatData.formatetc.ptd); + } + } + } + } + + if (lpOleCache) + OleStdRelease((LPUNKNOWN)lpOleCache); + + /* append CF_LINKSOURCE format */ + lparrDocGetFmts[iFmt].cfFormat = lpOleApp->m_cfLinkSource; + lparrDocGetFmts[iFmt].ptd = NULL; + lparrDocGetFmts[iFmt].dwAspect = DVASPECT_CONTENT; + lparrDocGetFmts[iFmt].tymed = TYMED_ISTREAM; + lparrDocGetFmts[iFmt].lindex = -1; + iFmt++; + + /* append CF_LINKSRCDESCRIPTOR format */ + lparrDocGetFmts[iFmt].cfFormat = lpOleApp->m_cfLinkSrcDescriptor; + lparrDocGetFmts[iFmt].ptd = NULL; + lparrDocGetFmts[iFmt].dwAspect = DVASPECT_CONTENT; + lparrDocGetFmts[iFmt].tymed = TYMED_HGLOBAL; + lparrDocGetFmts[iFmt].lindex = -1; + iFmt++; + + lpContainerDoc->m_lparrDocGetFmts = lparrDocGetFmts; + lpContainerDoc->m_nDocGetFmts = iFmt; + + if (lpEnumStatData) + OleStdVerifyRelease( + (LPUNKNOWN)lpEnumStatData, + "Cache enumerator not released properly" + ); + + return TRUE; +} +#endif // OPTIONAL_ADVANCED_DATA_TRANSFER + +#endif // OLE_CNTR diff --git a/private/oleutest/letest/outline/cntrbase.c b/private/oleutest/letest/outline/cntrbase.c new file mode 100644 index 000000000..6fc947998 --- /dev/null +++ b/private/oleutest/letest/outline/cntrbase.c @@ -0,0 +1,2002 @@ +/************************************************************************* +** +** OLE 2 Container Sample Code +** +** cntrbase.c +** +** This file contains all interfaces, methods and related support +** functions for the basic OLE Container application. The +** basic OLE Container application supports being a container for +** embedded and linked objects. +** The basic Container application includes the following +** implementation objects: +** +** ContainerDoc Object +** no required interfaces for basic functionality +** (see linking.c for linking related support) +** (see clipbrd.c for clipboard related support) +** (see dragdrop.c for drag/drop related support) +** +** ContainerLine Object +** (see cntrline.c for all ContainerLine functions and interfaces) +** exposed interfaces: +** IOleClientSite +** IAdviseSink +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + +#include "outline.h" +#include + + +OLEDBGDATA + + +extern LPOUTLINEAPP g_lpApp; +extern IOleUILinkContainerVtbl g_CntrDoc_OleUILinkContainerVtbl; + +#if defined( INPLACE_CNTR ) +extern BOOL g_fInsideOutContainer; +#endif // INPLACE_CNTR + +// REVIEW: should use string resource for messages +char ErrMsgShowObj[] = "Could not show object server!"; +char ErrMsgInsertObj[] = "Insert Object failed!"; +char ErrMsgConvertObj[] = "Convert Object failed!"; +char ErrMsgCantConvert[] = "Unable to convert the selection!"; +char ErrMsgActivateAsObj[] = "Activate As Object failed!"; + +extern char ErrMsgSaving[]; +extern char ErrMsgOpening[]; + + +/* ContainerDoc_Init + * ----------------- + * + * Initialize the fields of a new ContainerDoc object. The doc is initially + * not associated with a file or an (Untitled) document. This function sets + * the docInitType to DOCTYPE_UNKNOWN. After calling this function the + * caller should call: + * 1.) Doc_InitNewFile to set the ContainerDoc to (Untitled) + * 2.) Doc_LoadFromFile to associate the ContainerDoc with a file. + * This function creates a new window for the document. + * + * NOTE: the window is initially created with a NIL size. it must be + * sized and positioned by the caller. also the document is initially + * created invisible. the caller must call Doc_ShowWindow + * after sizing it to make the document window visible. + */ +BOOL ContainerDoc_Init(LPCONTAINERDOC lpContainerDoc, BOOL fDataTransferDoc) +{ + LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerDoc; + + lpOutlineDoc->m_cfSaveFormat = lpContainerApp->m_cfCntrOutl; + lpContainerDoc->m_nNextObjNo = 0L; + lpContainerDoc->m_lpNewStg = NULL; + lpContainerDoc->m_fEmbeddedObjectAvail = FALSE; + lpContainerDoc->m_clsidOleObjCopied = CLSID_NULL; + lpContainerDoc->m_dwAspectOleObjCopied = DVASPECT_CONTENT; + lpContainerDoc->m_lpSrcContainerLine = NULL; + lpContainerDoc->m_fShowObject = TRUE; + +#if defined( INPLACE_CNTR ) + lpContainerDoc->m_lpLastIpActiveLine = NULL; + lpContainerDoc->m_lpLastUIActiveLine = NULL; + lpContainerDoc->m_hWndUIActiveObj = NULL; + lpContainerDoc->m_fAddMyUI = TRUE; // UI needs to be added + lpContainerDoc->m_cIPActiveObjects = 0; + lpContainerApp->m_fMenuHelpMode = FALSE; // F1 pressed in menu + +#if defined( INPLACE_CNTRSVR ) + lpContainerDoc->m_lpTopIPFrame = + (LPOLEINPLACEUIWINDOW)&lpContainerDoc->m_OleInPlaceFrame; + lpContainerDoc->m_lpTopIPDoc = + (LPOLEINPLACEUIWINDOW)&lpContainerDoc->m_OleInPlaceDoc; + lpContainerDoc->m_hSharedMenu = NULL; + lpContainerDoc->m_hOleMenu = NULL; + +#endif // INPLACE_CNTRSVR +#endif // INPLACE_CNTR + + INIT_INTERFACEIMPL( + &lpContainerDoc->m_OleUILinkContainer, + &g_CntrDoc_OleUILinkContainerVtbl, + lpContainerDoc + ); + + return TRUE; +} + + +/* ContainerDoc_GetNextLink + * ------------------------ + * + * Update all links in the document. A dialog box will be popped up showing + * the progress of the update and allow the user to quit by pushing the + * stop button + */ +LPCONTAINERLINE ContainerDoc_GetNextLink( + LPCONTAINERDOC lpContainerDoc, + LPCONTAINERLINE lpContainerLine +) +{ + LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList; + DWORD dwNextLink = 0; + LPLINE lpLine; + static int nIndex = 0; + + if (lpContainerLine==NULL) + nIndex = 0; + + for ( ; nIndex < lpLL->m_nNumLines; nIndex++) { + lpLine = LineList_GetLine(lpLL, nIndex); + + if (lpLine + && (Line_GetLineType(lpLine) == CONTAINERLINETYPE) + && ContainerLine_IsOleLink((LPCONTAINERLINE)lpLine)) { + + nIndex++; + ContainerLine_LoadOleObject((LPCONTAINERLINE)lpLine); + return (LPCONTAINERLINE)lpLine; + } + } + + return NULL; +} + + + +/* ContainerDoc_UpdateLinks + * ------------------------ + * + * Update all links in the document. A dialog box will be popped up showing + * the progress of the update and allow the user to quit by pushing the + * stop button + */ +void ContainerDoc_UpdateLinks(LPCONTAINERDOC lpContainerDoc) +{ + int cLinks; + BOOL fAllLinksUpToDate = TRUE; + HWND hwndDoc = ((LPOUTLINEDOC)lpContainerDoc)->m_hWndDoc; + HCURSOR hCursor; + LPCONTAINERLINE lpContainerLine = NULL; + HRESULT hrErr; + DWORD dwUpdateOpt; + LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; + BOOL fPrevEnable1; + BOOL fPrevEnable2; + + hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT)); + + /* OLE2NOTE: we do not want to ever give the Busy/NotResponding + ** dialogs when we are updating automatic links as part of + ** opening a document. even if the link source of data is busy, + ** we do not want put up the busy dialog. thus we will disable + ** the dialog and later re-enable them + */ + OleApp_DisableBusyDialogs(lpOleApp, &fPrevEnable1, &fPrevEnable2); + + /* get total number of automatic links */ + cLinks = 0; + while (lpContainerLine = ContainerDoc_GetNextLink( + lpContainerDoc, + lpContainerLine)) { + hrErr = CntrDoc_LinkCont_GetLinkUpdateOptions( + (LPOLEUILINKCONTAINER)&lpContainerDoc->m_OleUILinkContainer, + (DWORD)lpContainerLine, + (LPDWORD)&dwUpdateOpt + ); + if (hrErr == NOERROR) { + if (dwUpdateOpt==OLEUPDATE_ALWAYS) { + cLinks++; + if (fAllLinksUpToDate) { + OLEDBG_BEGIN2("IOleObject::IsUpToDate called\r\n") + hrErr = lpContainerLine->m_lpOleObj->lpVtbl->IsUpToDate( + lpContainerLine->m_lpOleObj); + OLEDBG_END2 + if (hrErr != NOERROR) + fAllLinksUpToDate = FALSE; + } + } + } +#if defined( _DEBUG ) + else + OleDbgOutHResult("IOleUILinkContainer::GetLinkUpdateOptions returned",hrErr); +#endif + + } + + if (fAllLinksUpToDate) + goto done; // don't bother user if all links are up-to-date + + SetCursor(hCursor); + + if ((cLinks > 0) && !OleUIUpdateLinks( + (LPOLEUILINKCONTAINER)&lpContainerDoc->m_OleUILinkContainer, + hwndDoc, + (LPSTR)APPNAME, + cLinks)) { + if (ID_PU_LINKS == OleUIPromptUser( + (WORD)IDD_CANNOTUPDATELINK, + hwndDoc, + (LPSTR)APPNAME)) { + ContainerDoc_EditLinksCommand(lpContainerDoc); + } + } + +done: + // re-enable the Busy/NotResponding dialogs + OleApp_EnableBusyDialogs(lpOleApp, fPrevEnable1, fPrevEnable2); +} + + + +/* ContainerDoc_SetShowObjectFlag + * ------------------------------ + * + * Set/Clear the ShowObject flag of ContainerDoc + */ +void ContainerDoc_SetShowObjectFlag(LPCONTAINERDOC lpContainerDoc, BOOL fShow) +{ + if (!lpContainerDoc) + return; + + lpContainerDoc->m_fShowObject = fShow; +} + + +/* ContainerDoc_GetShowObjectFlag + * ------------------------------ + * + * Get the ShowObject flag of ContainerDoc + */ +BOOL ContainerDoc_GetShowObjectFlag(LPCONTAINERDOC lpContainerDoc) +{ + if (!lpContainerDoc) + return FALSE; + + return lpContainerDoc->m_fShowObject; +} + + +/* ContainerDoc_InsertOleObjectCommand + * ----------------------------------- + * + * Insert a new OLE object in the ContainerDoc. + */ +void ContainerDoc_InsertOleObjectCommand(LPCONTAINERDOC lpContainerDoc) +{ + LPLINELIST lpLL =&((LPOUTLINEDOC)lpContainerDoc)->m_LineList; + LPLINE lpLine = NULL; + HDC hDC; + int nTab = 0; + int nIndex = LineList_GetFocusLineIndex(lpLL); + LPCONTAINERLINE lpContainerLine=NULL; + char szStgName[CWCSTORAGENAME]; + UINT uRet; + OLEUIINSERTOBJECT io; + char szFile[OLEUI_CCHPATHMAX]; + DWORD dwOleCreateType; + BOOL fDisplayAsIcon; + HCURSOR hPrevCursor; + + _fmemset((LPOLEUIINSERTOBJECT)&io, 0, sizeof(io)); + io.cbStruct=sizeof(io); + io.dwFlags=IOF_SELECTCREATENEW | IOF_SHOWHELP; + io.hWndOwner=((LPOUTLINEDOC)lpContainerDoc)->m_hWndDoc; + io.lpszFile=(LPSTR)szFile; + io.cchFile=sizeof(szFile); + _fmemset((LPSTR)szFile, 0, OLEUI_CCHPATHMAX); + +#if defined( OLE_VERSION ) + OleApp_PreModalDialog((LPOLEAPP)g_lpApp, (LPOLEDOC)lpContainerDoc); +#endif + + OLEDBG_BEGIN3("OleUIInsertObject called\r\n") + uRet=OleUIInsertObject((LPOLEUIINSERTOBJECT)&io); + OLEDBG_END3 + +#if defined( OLE_VERSION ) + OleApp_PostModalDialog((LPOLEAPP)g_lpApp, (LPOLEDOC)lpContainerDoc); +#endif + + if (OLEUI_OK != uRet) + return; // user canceled dialog + + // this may take a while, put up hourglass cursor + hPrevCursor = SetCursor(LoadCursor(NULL, IDC_WAIT)); + + fDisplayAsIcon = (io.dwFlags & IOF_CHECKDISPLAYASICON ? TRUE : FALSE); + + // make up a storage name for the OLE object + ContainerDoc_GetNextStgName(lpContainerDoc, szStgName, sizeof(szStgName)); + + /* default the new line to have the same indent as previous line */ + lpLine = LineList_GetLine(lpLL, nIndex); + if (lpLine) + nTab = Line_GetTabLevel(lpLine); + + hDC = LineList_GetDC(lpLL); + + if ((io.dwFlags & IOF_SELECTCREATENEW)) + dwOleCreateType = IOF_SELECTCREATENEW; + else if ((io.dwFlags & IOF_CHECKLINK)) + dwOleCreateType = IOF_CHECKLINK; + else + dwOleCreateType = IOF_SELECTCREATEFROMFILE; + + lpContainerLine = ContainerLine_Create( + dwOleCreateType, + hDC, + nTab, + lpContainerDoc, + &io.clsid, + (LPSTR)szFile, + fDisplayAsIcon, + io.hMetaPict, + szStgName + ); + + if (!lpContainerLine) + goto error; // creation of OLE object FAILED + + if (io.hMetaPict) { + OleUIMetafilePictIconFree(io.hMetaPict); // clean up metafile + } + + /* add a ContainerLine object to the document's LineList. The + ** ContainerLine manages the rectangle on the screen occupied by + ** the OLE object. + */ + + LineList_AddLine(lpLL, (LPLINE)lpContainerLine, nIndex); + + /* before calling DoVerb(OLEIVERB_SHOW), check to see if the object + ** has any initial extents. + */ + ContainerLine_UpdateExtent(lpContainerLine, NULL); + + /* If a new embedded object was created, tell the object server to + ** make itself visible (show itself). + ** OLE2NOTE: the standard OLE 2 User Model is to only call + ** IOleObject::DoVerb(OLEIVERB_SHOW...) if a new object is + ** created. specifically, it should NOT be calld if the object + ** is created from file or link to file. + */ + if (dwOleCreateType == IOF_SELECTCREATENEW) { + if (! ContainerLine_DoVerb( + lpContainerLine, OLEIVERB_SHOW, NULL, TRUE, TRUE)) { + OutlineApp_ErrorMessage(g_lpApp, ErrMsgShowObj); + } + + /* OLE2NOTE: we will immediately force a save of the object + ** to guarantee that a valid initial object is saved + ** with our document. if the object is a OLE 1.0 object, + ** then it may exit without update. by forcing this + ** initial save we consistently always have a valid + ** object even if it is a OLE 1.0 object that exited + ** without saving. if we did NOT do this save here, then + ** we would have to worry about deleting the object if + ** it was a OLE 1.0 object that closed without saving. + ** the OLE 2.0 User Model dictates that the object + ** should always be valid after CreateNew performed. the + ** user must explicitly delete it. + */ + ContainerLine_SaveOleObjectToStg( + lpContainerLine, + lpContainerLine->m_lpStg, + lpContainerLine->m_lpStg, + TRUE /* fRemember */ + ); + } +#if defined( INPLACE_CNTR ) + else if (dwOleCreateType == IOF_SELECTCREATEFROMFILE) { + /* OLE2NOTE: an inside-out container should check if the object + ** created from file is an inside-out and prefers to be + ** activated when visible type of object. if so, the object + ** should be immediately activated in-place, BUT NOT UIActived. + */ + if (g_fInsideOutContainer && + lpContainerLine->m_dwDrawAspect == DVASPECT_CONTENT && + lpContainerLine->m_fInsideOutObj ) { + HWND hWndDoc = OutlineDoc_GetWindow((LPOUTLINEDOC)lpContainerDoc); + + ContainerLine_DoVerb( + lpContainerLine,OLEIVERB_INPLACEACTIVATE,NULL,FALSE,FALSE); + + /* OLE2NOTE: following this DoVerb(INPLACEACTIVATE) the + ** object may have taken focus. but because the + ** object is NOT UIActive it should NOT have focus. + ** we will make sure our document has focus. + */ + SetFocus(hWndDoc); + } + } +#endif // INPLACE_CNTR + + OutlineDoc_SetModified((LPOUTLINEDOC)lpContainerDoc, TRUE, TRUE, TRUE); + + LineList_ReleaseDC(lpLL, hDC); + + SetCursor(hPrevCursor); // restore original cursor + + return; + +error: + // NOTE: if ContainerLine_Create failed + LineList_ReleaseDC(lpLL, hDC); + + if (OLEUI_OK == uRet && io.hMetaPict) + OleUIMetafilePictIconFree(io.hMetaPict); // clean up metafile + + SetCursor(hPrevCursor); // restore original cursor + OutlineApp_ErrorMessage(g_lpApp, ErrMsgInsertObj); +} + + + +void ContainerDoc_EditLinksCommand(LPCONTAINERDOC lpContainerDoc) +{ + UINT uRet; + OLEUIEDITLINKS el; + LPCONTAINERLINE lpContainerLine = NULL; + LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList; + + _fmemset((LPOLEUIEDITLINKS)&el,0,sizeof(el)); + el.cbStruct=sizeof(el); + el.dwFlags=ELF_SHOWHELP; + el.hWndOwner=((LPOUTLINEDOC)lpContainerDoc)->m_hWndDoc; + el.lpOleUILinkContainer = + (LPOLEUILINKCONTAINER)&lpContainerDoc->m_OleUILinkContainer; + +#if defined( OLE_VERSION ) + OleApp_PreModalDialog((LPOLEAPP)g_lpApp, (LPOLEDOC)lpContainerDoc); +#endif + + OLEDBG_BEGIN3("OleUIEditLinks called\r\n") + uRet=OleUIEditLinks((LPOLEUIEDITLINKS)&el); + OLEDBG_END3 + +#if defined( OLE_VERSION ) + OleApp_PostModalDialog((LPOLEAPP)g_lpApp, (LPOLEDOC)lpContainerDoc); +#endif + + OleDbgAssert((uRet==1) || (uRet==OLEUI_CANCEL)); + +} + + +/* Convert command - brings up the "Convert" dialog + */ +void ContainerDoc_ConvertCommand( + LPCONTAINERDOC lpContainerDoc, + BOOL fServerNotRegistered +) +{ + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerDoc; + OLEUICONVERT ct; + UINT uRet; + LPDATAOBJECT lpDataObj; + LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList; + LPCONTAINERLINE lpContainerLine = NULL; + BOOL fSelIsOleObject; + int nIndex; + STGMEDIUM medium; + LPSTR lpErrMsg = NULL; + HRESULT hrErr; + HCURSOR hPrevCursor; + BOOL fMustRun = FALSE; + BOOL fMustClose = FALSE; + BOOL fObjConverted = FALSE; + BOOL fDisplayChanged = FALSE; + BOOL fHaveCLSID = FALSE; + BOOL fHaveFmtUserType = FALSE; + char szUserType[128]; + BOOL fMustActivate; + + /* OLE2NOTE: if we came to the Convert dialog because the user + ** activated a non-registered object, then we should activate + ** the object after the user has converted it or setup an + ** ActivateAs server. + */ + fMustActivate = fServerNotRegistered; + + _fmemset((LPOLEUICONVERT)&ct,0,sizeof(ct)); + + fSelIsOleObject = ContainerDoc_IsSelAnOleObject( + (LPCONTAINERDOC)lpContainerDoc, + &IID_IDataObject, + (LPUNKNOWN FAR*)&lpDataObj, + &nIndex, + (LPCONTAINERLINE FAR*)&lpContainerLine + ); + + lpErrMsg = ErrMsgCantConvert; + + if (! fSelIsOleObject) + goto error; // can NOT do Convert. + + if (! lpContainerLine) { + OleStdRelease((LPUNKNOWN)lpDataObj); + goto error; // can NOT do Convert. + } + + ct.cbStruct = sizeof(OLEUICONVERT); + ct.dwFlags = CF_SHOWHELPBUTTON; + ct.hWndOwner = lpContainerDoc->m_OleDoc.m_OutlineDoc.m_hWndDoc; + ct.lpszCaption = (LPSTR)NULL; + ct.lpfnHook = NULL; + ct.lCustData = 0; + ct.hInstance = NULL; + ct.lpszTemplate = NULL; + ct.hResource = 0; + ct.fIsLinkedObject = ContainerLine_IsOleLink(lpContainerLine); + ct.dvAspect = lpContainerLine->m_dwDrawAspect; + ct.cClsidExclude = 0; + ct.lpClsidExclude = NULL; + + if (! ct.fIsLinkedObject || !lpContainerLine->m_lpOleLink) { + /* OLE2NOTE: the object is an embedded object. we should first + ** attempt to read the actual object CLSID, file data + ** format, and full user type name that is written inside of + ** the object's storage as this should be the most + ** definitive information. if this fails we will ask the + ** object what its class is and attempt to get the rest of + ** the information out of the REGDB. + */ + hrErr=ReadClassStg(lpContainerLine->m_lpStg,(CLSID FAR*)&(ct.clsid)); + if (hrErr == NOERROR) + fHaveCLSID = TRUE; + else { + OleDbgOutHResult("ReadClassStg returned", hrErr); + } + + hrErr = ReadFmtUserTypeStgA( + lpContainerLine->m_lpStg, + (CLIPFORMAT FAR*)&ct.wFormat, + &ct.lpszUserType); + + if (hrErr == NOERROR) + fHaveFmtUserType = TRUE; + else { + OleDbgOutHResult("ReadFmtUserTypeStg returned", hrErr); + } + } else { + /* OLE2NOTE: the object is a linked object. we should give the + ** DisplayName of the link source as the default icon label. + */ + OLEDBG_BEGIN2("IOleLink::GetSourceDisplayName called\r\n") + + hrErr = CallIOleLinkGetSourceDisplayNameA( + lpContainerLine->m_lpOleLink, &ct.lpszDefLabel); + + OLEDBG_END2 + } + + if (! fHaveCLSID) { + hrErr = lpContainerLine->m_lpOleObj->lpVtbl->GetUserClassID( + lpContainerLine->m_lpOleObj, + (CLSID FAR*)&ct.clsid + ); + if (hrErr != NOERROR) + ct.clsid = CLSID_NULL; + } + if (! fHaveFmtUserType) { + ct.wFormat = 0; + if (OleStdGetUserTypeOfClass( + (CLSID FAR*)&ct.clsid,szUserType,sizeof(szUserType),NULL)) { + ct.lpszUserType = OleStdCopyString(szUserType, NULL); + } else { + ct.lpszUserType = NULL; + } + } + + if (lpContainerLine->m_dwDrawAspect == DVASPECT_ICON) { + ct.hMetaPict = OleStdGetData( + lpDataObj, + CF_METAFILEPICT, + NULL, + DVASPECT_ICON, + (LPSTGMEDIUM)&medium + ); + } else { + ct.hMetaPict = NULL; + } + OleStdRelease((LPUNKNOWN)lpDataObj); + +#if defined( OLE_VERSION ) + OleApp_PreModalDialog((LPOLEAPP)g_lpApp, (LPOLEDOC)lpContainerDoc); +#endif + + OLEDBG_BEGIN3("OleUIConvert called\r\n") + uRet = OleUIConvert(&ct); + OLEDBG_END3 + +#if defined( OLE_VERSION ) + OleApp_PostModalDialog((LPOLEAPP)g_lpApp, (LPOLEDOC)lpContainerDoc); +#endif + + // this may take a while, put up hourglass cursor + hPrevCursor = SetCursor(LoadCursor(NULL, IDC_WAIT)); + + if (uRet == OLEUI_OK) { + + /***************************************************************** + ** OLE2NOTE: the convert dialog actually allows the user to + ** change two orthogonal properties of the object: the + ** object's type/server and the object's display aspect. + ** first we will execute the ConvertTo/ActivateAs action and + ** then we will deal with any display aspect change. we want + ** to be careful to only call IOleObject::Update once + ** because this is an expensive operation; it results in + ** launching the object's server. + *****************************************************************/ + + if (ct.dwFlags & CF_SELECTCONVERTTO && + ! IsEqualCLSID(&ct.clsid, &ct.clsidNew)) { + + /* user selected CONVERT. + ** + ** OLE2NOTE: to achieve the "Convert To" at this point we + ** need to take the following steps: + ** 1. unload the object. + ** 2. write the NEW CLSID and NEW user type name + ** string into the storage of the object, + ** BUT write the OLD format tag. + ** 3. force an update to force the actual conversion of + ** the data bits. + */ + lpErrMsg = ErrMsgConvertObj; // setup correct msg in case of error + + ContainerLine_UnloadOleObject(lpContainerLine, OLECLOSE_SAVEIFDIRTY); + + OLEDBG_BEGIN2("OleStdDoConvert called \r\n") + hrErr = OleStdDoConvert( + lpContainerLine->m_lpStg, (REFCLSID)&ct.clsidNew); + OLEDBG_END2 + if (hrErr != NOERROR) + goto error; + + // Reload the object + ContainerLine_LoadOleObject(lpContainerLine); + + /* we need to force the object to run to complete the + ** conversion. set flag to force OleRun to be called at + ** end of function. + */ + fMustRun = TRUE; + fObjConverted = TRUE; + + } else if (ct.dwFlags & CF_SELECTACTIVATEAS) { + /* user selected ACTIVATE AS. + ** + ** OLE2NOTE: to achieve the "Activate As" at this point we + ** need to take the following steps: + ** 1. unload ALL objects of the OLD class that app knows about + ** 2. add the TreatAs tag in the registration database + ** by calling CoTreatAsClass(). + ** 3. lazily it can reload the objects; when the objects + ** are reloaded the TreatAs will take effect. + */ + lpErrMsg = ErrMsgActivateAsObj; // setup msg in case of error + + ContainerDoc_UnloadAllOleObjectsOfClass( + lpContainerDoc, + (REFCLSID)&ct.clsid, + OLECLOSE_SAVEIFDIRTY + ); + + OLEDBG_BEGIN2("OleStdDoTreatAsClass called \r\n") + hrErr = OleStdDoTreatAsClass(ct.lpszUserType, (REFCLSID)&ct.clsid, + (REFCLSID)&ct.clsidNew); + OLEDBG_END2 + + // Reload the object + ContainerLine_LoadOleObject(lpContainerLine); + + fMustActivate = TRUE; // we should activate this object + } + + /***************************************************************** + ** OLE2NOTE: now we will try to change the display if + ** necessary. + *****************************************************************/ + + if (lpContainerLine->m_lpOleObj && + ct.dvAspect != lpContainerLine->m_dwDrawAspect) { + /* user has selected to change display aspect between icon + ** aspect and content aspect. + ** + ** OLE2NOTE: if we got here because the server was not + ** registered, then we will NOT delete the object's + ** original display aspect. because we do not have the + ** original server, we can NEVER get it back. this is a + ** safety precaution. + */ + + hrErr = OleStdSwitchDisplayAspect( + lpContainerLine->m_lpOleObj, + &lpContainerLine->m_dwDrawAspect, + ct.dvAspect, + ct.hMetaPict, + !fServerNotRegistered, /* fDeleteOldAspect */ + TRUE, /* fSetupViewAdvise */ + (LPADVISESINK)&lpContainerLine->m_AdviseSink, + (BOOL FAR*)&fMustRun + ); + + if (hrErr == NOERROR) + fDisplayChanged = TRUE; + +#if defined( INPLACE_CNTR ) + ContainerDoc_UpdateInPlaceObjectRects( + lpContainerLine->m_lpDoc, nIndex); +#endif + + } else if (ct.dvAspect == DVASPECT_ICON && ct.fObjectsIconChanged) { + hrErr = OleStdSetIconInCache( + lpContainerLine->m_lpOleObj, + ct.hMetaPict + ); + + if (hrErr == NOERROR) + fDisplayChanged = TRUE; + } + + /* we deliberately run the object so that the update won't shut + ** the server down. + */ + if (fMustActivate || fMustRun) { + + /* if we force the object to run, then shut it down after + ** the update. do NOT force the object to close if we + ** want to activate the object or if the object was + ** already running. + */ + if (!fMustActivate && !OleIsRunning(lpContainerLine->m_lpOleObj)) + fMustClose = TRUE; // shutdown after update + + hrErr = ContainerLine_RunOleObject(lpContainerLine); + + if (fObjConverted && + FAILED(hrErr) && GetScode(hrErr)!=OLE_E_STATIC) { + + // ERROR: convert of the object failed. + // revert the storage to restore the original link. + // (OLE2NOTE: static object always return OLE_E_STATIC + // when told to run; this is NOT an error here. + // the OLE2 libraries have built in handlers for + // the static objects that do the conversion. + ContainerLine_UnloadOleObject( + lpContainerLine, OLECLOSE_NOSAVE); + lpContainerLine->m_lpStg->lpVtbl->Revert( + lpContainerLine->m_lpStg); + goto error; + + } else if (fObjConverted) { + FORMATETC FmtEtc; + DWORD dwNewConnection; + LPOLECACHE lpOleCache = (LPOLECACHE)OleStdQueryInterface + ((LPUNKNOWN)lpContainerLine->m_lpOleObj,&IID_IOleCache); + + /* OLE2NOTE: we need to force the converted object to + ** setup a new OLERENDER_DRAW cache. it is possible + ** that the new object needs to cache different data + ** in order to support drawing than the old object. + */ + if (lpOleCache && + lpContainerLine->m_dwDrawAspect == DVASPECT_CONTENT) { + FmtEtc.cfFormat = 0; // whatever is needed for Draw + FmtEtc.ptd = NULL; + FmtEtc.dwAspect = DVASPECT_CONTENT; + FmtEtc.lindex = -1; + FmtEtc.tymed = TYMED_NULL; + + OLEDBG_BEGIN2("IOleCache::Cache called\r\n") + hrErr = lpOleCache->lpVtbl->Cache( + lpOleCache, + (LPFORMATETC)&FmtEtc, + ADVF_PRIMEFIRST, + (LPDWORD)&dwNewConnection + ); + OLEDBG_END2 +#if defined( _DEBUG ) + if (! SUCCEEDED(hrErr)) + OleDbgOutHResult("IOleCache::Cache returned", hrErr); +#endif + OleStdRelease((LPUNKNOWN)lpOleCache); + } + + // Close and force object to save; this will commit the stg + ContainerLine_CloseOleObject( + lpContainerLine, OLECLOSE_SAVEIFDIRTY); + fMustClose = FALSE; // we already closed the object + } + if (fMustClose) + ContainerLine_CloseOleObject(lpContainerLine,OLECLOSE_NOSAVE); + } + + if (fDisplayChanged) { + /* the Object's display was changed, force a repaint of + ** the line. note the extents of the object may have + ** changed. + */ + ContainerLine_UpdateExtent(lpContainerLine, NULL); + LineList_ForceLineRedraw(lpLL, nIndex, TRUE); + } + + if (fDisplayChanged || fObjConverted) { + /* mark ContainerDoc as now dirty. if display changed, then + ** the extents of the object may have changed. + */ + OutlineDoc_SetModified(lpOutlineDoc, TRUE, TRUE, fDisplayChanged); + } + + if (fMustActivate) { + ContainerLine_DoVerb( + lpContainerLine, OLEIVERB_PRIMARY, NULL, FALSE,FALSE); + } + } + + + if (ct.lpszUserType) + OleStdFreeString(ct.lpszUserType, NULL); + + if (ct.lpszDefLabel) + OleStdFreeString(ct.lpszDefLabel, NULL); + + if (ct.hMetaPict) + OleUIMetafilePictIconFree(ct.hMetaPict); // clean up metafile + + SetCursor(hPrevCursor); // restore original cursor + + return; + +error: + if (ct.lpszUserType) + OleStdFreeString(ct.lpszUserType, NULL); + + if (ct.hMetaPict) + OleUIMetafilePictIconFree(ct.hMetaPict); // clean up metafile + + SetCursor(hPrevCursor); // restore original cursor + if (lpErrMsg) + OutlineApp_ErrorMessage(g_lpApp, lpErrMsg); + +} + + +/* ContainerDoc_CloseAllOleObjects +** ------------------------------- +** Close all OLE objects. This forces all OLE objects to transition +** from the running state to the loaded state. +** +** Returns TRUE if all objects closed successfully +** FALSE if any object could not be closed. +*/ +BOOL ContainerDoc_CloseAllOleObjects( + LPCONTAINERDOC lpContainerDoc, + DWORD dwSaveOption +) +{ + LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList; + int i; + LPLINE lpLine; + BOOL fStatus = TRUE; + + for (i = 0; i < lpLL->m_nNumLines; i++) { + lpLine=LineList_GetLine(lpLL, i); + + if (lpLine && (Line_GetLineType(lpLine)==CONTAINERLINETYPE)) + if (! ContainerLine_CloseOleObject( + (LPCONTAINERLINE)lpLine,dwSaveOption)) + fStatus = FALSE; + } + + return fStatus; +} + + +/* ContainerDoc_UnloadAllOleObjectsOfClass +** --------------------------------------- +** Unload all OLE objects of a particular class. this is necessary +** when a class level "ActivateAs" (aka. TreatAs) is setup. the user +** can do this with the Convert dialog. for the TreatAs to take +** effect, all objects of the class have to loaded and reloaded. +*/ +void ContainerDoc_UnloadAllOleObjectsOfClass( + LPCONTAINERDOC lpContainerDoc, + REFCLSID rClsid, + DWORD dwSaveOption +) +{ + LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList; + int i; + LPLINE lpLine; + CLSID clsid; + HRESULT hrErr; + + for (i = 0; i < lpLL->m_nNumLines; i++) { + lpLine=LineList_GetLine(lpLL, i); + + if (lpLine && (Line_GetLineType(lpLine)==CONTAINERLINETYPE)) { + LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)lpLine; + + if (! lpContainerLine->m_lpOleObj) + continue; // this object is NOT loaded + + hrErr = lpContainerLine->m_lpOleObj->lpVtbl->GetUserClassID( + lpContainerLine->m_lpOleObj, + (CLSID FAR*)&clsid + ); + if (hrErr == NOERROR && + ( IsEqualCLSID((CLSID FAR*)&clsid,rClsid) + || IsEqualCLSID(rClsid,&CLSID_NULL) ) ) { + ContainerLine_UnloadOleObject(lpContainerLine, dwSaveOption); + } + } + } +} + + +/* ContainerDoc_UpdateExtentOfAllOleObjects +** ---------------------------------------- +** Update the extents of any OLE object that is marked that its size +** may have changed. when an IAdviseSink::OnViewChange notification +** is received, the corresponding ContainerLine is marked +** (m_fDoGetExtent==TRUE) and a message (WM_U_UPDATEOBJECTEXTENT) is +** posted to the document indicating that there are dirty objects. +** when this message is received, this function is called. +*/ +void ContainerDoc_UpdateExtentOfAllOleObjects(LPCONTAINERDOC lpContainerDoc) +{ + LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList; + int i; + LPLINE lpLine; + BOOL fStatus = TRUE; +#if defined( INPLACE_CNTR ) + int nFirstUpdate = -1; +#endif + + for (i = 0; i < lpLL->m_nNumLines; i++) { + lpLine=LineList_GetLine(lpLL, i); + + if (lpLine && (Line_GetLineType(lpLine)==CONTAINERLINETYPE)) { + LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)lpLine; + + if (lpContainerLine->m_fDoGetExtent) { + ContainerLine_UpdateExtent(lpContainerLine, NULL); +#if defined( INPLACE_CNTR ) + if (nFirstUpdate == -1) + nFirstUpdate = i; +#endif + } + } + } + +#if defined( INPLACE_CNTR ) + /* OLE2NOTE: after changing the extents of any line, we need to + ** update the PosRect of the In-Place active + ** objects (if any) that follow the first modified line. + */ + if (nFirstUpdate != -1) + ContainerDoc_UpdateInPlaceObjectRects(lpContainerDoc, nFirstUpdate+1); +#endif +} + + +BOOL ContainerDoc_SaveToFile( + LPCONTAINERDOC lpContainerDoc, + LPCSTR lpszFileName, + UINT uFormat, + BOOL fRemember +) +{ + LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerDoc; + LPOLEDOC lpOleDoc = (LPOLEDOC)lpContainerDoc; + LPSTORAGE lpDestStg; + BOOL fStatus; + BOOL fMustRelDestStg = FALSE; + HRESULT hrErr; +#if defined( OPTIONAL ) + FILETIME filetimeBeforeSave; +#endif + + if (fRemember) { + if (lpszFileName) { + fStatus = OutlineDoc_SetFileName( + lpOutlineDoc, (LPSTR)lpszFileName, NULL); + if (! fStatus) goto error; + } + + /* The ContainerDoc keeps its storage open at all times. it is not + ** necessary to reopen the file. + ** if SaveAs is pending, then lpNewStg is the new destination for + ** the save operation, else the existing storage is the dest. + */ + lpDestStg = (lpContainerDoc->m_lpNewStg ? + lpContainerDoc->m_lpNewStg : lpOleDoc->m_lpStg); + +#if defined( OPTIONAL ) + /* OLE2NOTE: an automatic link to an embedded object within the + ** same container document (that uses ItemMonikers) will + ** always be considered "out-of-date' by OLE. if a container + ** application REALLY wants to fix this it can do one of the + ** following: + ** 1. implement a new moniker better than ItemMonikers + ** that look into the objects storage to find the real last + ** change time (rather then defaulting to that of the outer + ** container file). + ** or 2. using item monikers it is possible to fix the case + ** where the container document is saved while the embedded + ** object is running but it will NOT fix the case when the + ** document is saved when the embedded object was only + ** loaded. the fix is to: + ** a. remember the time (T) before the save operation starts + ** b. call IRunningObjectTable::NoteChangeTime(lpDoc, T) + ** c. do the saving and commit the file + ** d. call StgSetTimes to reset the file time to T + ** e. remember time T in document structure and when the + ** root storage is finally released reset the file time + ** again to T (closing the file on DOS sets the time). + */ + CoFileTimeNow( &filetimeBeforeSave ); + if (lpOleDoc->m_dwRegROT != 0) { + LPRUNNINGOBJECTTABLE lprot; + + if (GetRunningObjectTable(0,&lprot) == NOERROR) + { + OleDbgOut2("IRunningObjectTable::NoteChangeTime called\r\n"); + lprot->lpVtbl->NoteChangeTime( + lprot, lpOleDoc->m_dwRegROT, &filetimeBeforeSave ); + lprot->lpVtbl->Release(lprot); + } + } +#endif + } else { + if (! lpszFileName) + goto error; + + /* OLE2NOTE: since we are preforming a SaveCopyAs operation, we + ** do not need to have the DocFile open in STGM_TRANSACTED mode. + ** there is less overhead to use STGM_DIRECT mode. + */ + hrErr = StgCreateDocfileA( + lpszFileName, + STGM_READWRITE|STGM_DIRECT|STGM_SHARE_EXCLUSIVE|STGM_CREATE, + 0, + &lpDestStg + ); + + OleDbgAssertSz(hrErr == NOERROR, "Could not create Docfile"); + if (hrErr != NOERROR) { + OleDbgOutHResult("StgCreateDocfile returned", hrErr); + goto error; + } + fMustRelDestStg = TRUE; + } + + /* OLE2NOTE: we must be sure to write our class ID into our + ** storage. this information is used by OLE to determine the + ** class of the data stored in our storage. Even for top + ** "file-level" objects this information should be written to + ** the file. + */ + hrErr = WriteClassStg(lpDestStg, &CLSID_APP); + if(hrErr != NOERROR) goto error; + + fStatus = OutlineDoc_SaveSelToStg( + lpOutlineDoc, + NULL, // save all lines + uFormat, + lpDestStg, + FALSE, // fSameAsLoad + TRUE // remember this stg + ); + + if (fStatus) + fStatus = OleStdCommitStorage(lpDestStg); + + if (fRemember) { + /* if SaveAs was pending, then release the old storage and remember + ** the new storage as the active current storage. all data from + ** the old storage has been copied into the new storage. + */ + if (lpContainerDoc->m_lpNewStg) { + OleStdRelease((LPUNKNOWN)lpOleDoc->m_lpStg); // free old stg + lpOleDoc->m_lpStg = lpContainerDoc->m_lpNewStg; // save new stg + lpContainerDoc->m_lpNewStg = NULL; + } + if (! fStatus) goto error; + + OutlineDoc_SetModified(lpOutlineDoc, FALSE, FALSE, FALSE); + +#if defined( OPTIONAL ) + /* reset time of file on disk to be time just prior to saving. + ** NOTE: it would also be necessary to remember + ** filetimeBeforeSave in the document structure and when the + ** root storage is finally released reset the file time + ** again to this value (closing the file on DOS sets the time). + */ + StgSetTimesA(lpOutlineDoc->m_szFileName, + NULL, NULL, &filetimeBeforeSave); +#endif + } + + if (fMustRelDestStg) + OleStdRelease((LPUNKNOWN)lpDestStg); + return TRUE; + +error: + if (fMustRelDestStg) + OleStdRelease((LPUNKNOWN)lpDestStg); + OutlineApp_ErrorMessage(g_lpApp, ErrMsgSaving); + return FALSE; +} + + +/* ContainerDoc_ContainerLineDoVerbCommand +** --------------------------------------- +** Execute a verb of the OLE object in the current focus line. +*/ +void ContainerDoc_ContainerLineDoVerbCommand( + LPCONTAINERDOC lpContainerDoc, + LONG iVerb +) +{ + LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList; + int nIndex = LineList_GetFocusLineIndex(lpLL); + LPLINE lpLine = LineList_GetLine(lpLL, nIndex); + HCURSOR hPrevCursor; + + if (! lpLine || (Line_GetLineType(lpLine) != CONTAINERLINETYPE) ) return; + + // this may take a while, put up hourglass cursor + hPrevCursor = SetCursor(LoadCursor(NULL, IDC_WAIT)); + + ContainerLine_DoVerb((LPCONTAINERLINE) lpLine, iVerb, NULL, TRUE, TRUE); + + SetCursor(hPrevCursor); // restore original cursor +} + + +/* ContainerDoc_GetNextStgName +** --------------------------- +** Generate the next unused name for a sub-storage to be used by an +** OLE object. The ContainerDoc keeps a counter. The storages for +** OLE objects are simply numbered (eg. Obj 0, Obj 1). A "long" +** integer worth of storage names should be more than enough than we +** will ever need. +** +** NOTE: when an OLE object is transfered via drag/drop or the +** clipboard, we attempt to keep the currently assigned name for the +** object (if not currently in use). thus it is possible that an +** object with a the next default name (eg. "Obj 5") already exists +** in the current document if an object with this name was privously +** transfered (pasted or dropped). we therefore loop until we find +** the next lowest unused name. +*/ +void ContainerDoc_GetNextStgName( + LPCONTAINERDOC lpContainerDoc, + LPSTR lpszStgName, + int nLen +) +{ + wsprintf(lpszStgName, "%s %ld", + (LPSTR)DEFOBJNAMEPREFIX, + ++(lpContainerDoc->m_nNextObjNo) + ); + + while (ContainerDoc_IsStgNameUsed(lpContainerDoc, lpszStgName) == TRUE) { + wsprintf(lpszStgName, "%s %ld", + (LPSTR)DEFOBJNAMEPREFIX, + ++(lpContainerDoc->m_nNextObjNo) + ); + } +} + + +/* ContainerDoc_IsStgNameUsed +** -------------------------- +** Check if a given StgName is already in use. +*/ +BOOL ContainerDoc_IsStgNameUsed( + LPCONTAINERDOC lpContainerDoc, + LPSTR lpszStgName +) +{ + LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList; + int i; + LPLINE lpLine; + + for (i = 0; i < lpLL->m_nNumLines; i++) { + lpLine=LineList_GetLine(lpLL, i); + + if (lpLine && (Line_GetLineType(lpLine)==CONTAINERLINETYPE)) { + if (lstrcmp(lpszStgName, + ((LPCONTAINERLINE)lpLine)->m_szStgName) == 0) { + return TRUE; // Match FOUND! + } + } + } + return FALSE; // if we get here, then NO match was found. +} + + +LPSTORAGE ContainerDoc_GetStg(LPCONTAINERDOC lpContainerDoc) +{ + return ((LPOLEDOC)lpContainerDoc)->m_lpStg; +} + + +/* ContainerDoc_GetSingleOleObject +** ------------------------------- +** If the entire document contains a single OLE object, then +** return the desired interface of the object. +** +** Returns NULL if there is are multiple lines in the document or +** the single line is not a ContainerLine. +*/ +LPUNKNOWN ContainerDoc_GetSingleOleObject( + LPCONTAINERDOC lpContainerDoc, + REFIID riid, + LPCONTAINERLINE FAR* lplpContainerLine +) +{ + LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList; + LPLINE lpLine; + LPUNKNOWN lpObj = NULL; + + if (lplpContainerLine) + *lplpContainerLine = NULL; + + if (lpLL->m_nNumLines != 1) + return NULL; // doc does NOT contain a single line + + lpLine=LineList_GetLine(lpLL, 0); + + if (lpLine && (Line_GetLineType(lpLine)==CONTAINERLINETYPE)) + lpObj = ContainerLine_GetOleObject((LPCONTAINERLINE)lpLine, riid); + + if (lplpContainerLine) + *lplpContainerLine = (LPCONTAINERLINE)lpLine; + + return lpObj; +} + + +/* ContainerDoc_IsSelAnOleObject +** ----------------------------- +** Check if the selection is a single selection of an OLE object. +** if so, then optionally return the desired interface of the object +** and/or index of the ContainerLine containing the OLE object. +** +** Returns FALSE if there is a multiple selection or the single +** selection is not a ContainerLine. +*/ +BOOL ContainerDoc_IsSelAnOleObject( + LPCONTAINERDOC lpContainerDoc, + REFIID riid, + LPUNKNOWN FAR* lplpvObj, + int FAR* lpnIndex, + LPCONTAINERLINE FAR* lplpContainerLine +) +{ + LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList; + LINERANGE lrSel; + int nNumSel; + LPLINE lpLine; + + if (lplpvObj) *lplpvObj = NULL; + if (lpnIndex) *lpnIndex = -1; + if (lplpContainerLine) *lplpContainerLine = NULL; + + nNumSel = LineList_GetSel(lpLL, (LPLINERANGE)&lrSel); + if (nNumSel != 1) + return FALSE; // selection is not a single line + + lpLine = LineList_GetLine(lpLL, lrSel.m_nStartLine); + + if (lpLine && (Line_GetLineType(lpLine)==CONTAINERLINETYPE)) { + if (lpnIndex) + *lpnIndex = lrSel.m_nStartLine; + if (lplpContainerLine) + *lplpContainerLine = (LPCONTAINERLINE)lpLine; + if (riid) { + *lplpvObj = ContainerLine_GetOleObject( + (LPCONTAINERLINE)lpLine, + riid + ); + } + + return (*lplpvObj ? TRUE : FALSE); + } + + return FALSE; +} + + +/************************************************************************* +** ContainerDoc::IOleUILinkContainer interface implementation +*************************************************************************/ + +STDMETHODIMP CntrDoc_LinkCont_QueryInterface( + LPOLEUILINKCONTAINER lpThis, + REFIID riid, + LPVOID FAR* lplpvObj +) +{ + LPOLEDOC lpOleDoc = (LPOLEDOC) + ((struct CDocOleUILinkContainerImpl FAR*)lpThis)->lpContainerDoc; + + return OleDoc_QueryInterface(lpOleDoc, riid, lplpvObj); +} + + +STDMETHODIMP_(ULONG) CntrDoc_LinkCont_AddRef(LPOLEUILINKCONTAINER lpThis) +{ + LPOLEDOC lpOleDoc = (LPOLEDOC) + ((struct CDocOleUILinkContainerImpl FAR*)lpThis)->lpContainerDoc; + + OleDbgAddRefMethod(lpThis, "IOleUILinkContainer"); + + return OleDoc_AddRef(lpOleDoc); +} + + +STDMETHODIMP_(ULONG) CntrDoc_LinkCont_Release(LPOLEUILINKCONTAINER lpThis) +{ + LPOLEDOC lpOleDoc = (LPOLEDOC) + ((struct CDocOleUILinkContainerImpl FAR*)lpThis)->lpContainerDoc; + + OleDbgReleaseMethod(lpThis, "IOleUILinkContainer"); + + return OleDoc_Release(lpOleDoc); +} + + +STDMETHODIMP_(DWORD) CntrDoc_LinkCont_GetNextLink( + LPOLEUILINKCONTAINER lpThis, + DWORD dwLink +) +{ + LPCONTAINERDOC lpContainerDoc = + ((struct CDocOleUILinkContainerImpl FAR*)lpThis)->lpContainerDoc; + LPCONTAINERLINE lpContainerLine = NULL; + + OLEDBG_BEGIN2("CntrDoc_LinkCont_GetNextLink\r\n") + + lpContainerLine = ContainerDoc_GetNextLink( + lpContainerDoc, + (LPCONTAINERLINE)dwLink + ); + + OLEDBG_END2 + return (DWORD)lpContainerLine; +} + + +STDMETHODIMP CntrDoc_LinkCont_SetLinkUpdateOptions( + LPOLEUILINKCONTAINER lpThis, + DWORD dwLink, + DWORD dwUpdateOpt +) +{ + LPCONTAINERDOC lpContainerDoc = + ((struct CDocOleUILinkContainerImpl FAR*)lpThis)->lpContainerDoc; + LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)dwLink; + LPOLELINK lpOleLink = lpContainerLine->m_lpOleLink; + SCODE sc = S_OK; + HRESULT hrErr; + + OLEDBG_BEGIN2("CntrDoc_LinkCont_SetLinkUpdateOptions\r\n") + + OleDbgAssert(lpContainerLine); + + if (! lpOleLink) { + sc = E_FAIL; + goto error; + } + + OLEDBG_BEGIN2("IOleLink::SetUpdateOptions called\r\n") + hrErr = lpOleLink->lpVtbl->SetUpdateOptions( + lpOleLink, + dwUpdateOpt + ); + OLEDBG_END2 + + // save new link type update option + lpContainerLine->m_dwLinkType = dwUpdateOpt; + + if (hrErr != NOERROR) { + OleDbgOutHResult("IOleLink::SetUpdateOptions returned", hrErr); + sc = GetScode(hrErr); + goto error; + } + + OLEDBG_END2 + return ResultFromScode(sc); + +error: + OLEDBG_END2 + return ResultFromScode(sc); +} + + +STDMETHODIMP CntrDoc_LinkCont_GetLinkUpdateOptions( + LPOLEUILINKCONTAINER lpThis, + DWORD dwLink, + DWORD FAR* lpdwUpdateOpt +) +{ + LPCONTAINERDOC lpContainerDoc = + ((struct CDocOleUILinkContainerImpl FAR*)lpThis)->lpContainerDoc; + LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)dwLink; + LPOLELINK lpOleLink = lpContainerLine->m_lpOleLink; + SCODE sc = S_OK; + HRESULT hrErr; + + OLEDBG_BEGIN2("CntrDoc_LinkCont_GetLinkUpdateOptions\r\n") + + OleDbgAssert(lpContainerLine); + + if (! lpOleLink) { + sc = E_FAIL; + goto error; + } + + OLEDBG_BEGIN2("IOleLink::GetUpdateOptions called\r\n") + hrErr = lpOleLink->lpVtbl->GetUpdateOptions( + lpOleLink, + lpdwUpdateOpt + ); + OLEDBG_END2 + + // reset saved link type to ensure it is correct + lpContainerLine->m_dwLinkType = *lpdwUpdateOpt; + + if (hrErr != NOERROR) { + OleDbgOutHResult("IOleLink::GetUpdateOptions returned", hrErr); + sc = GetScode(hrErr); + goto error; + } + + OLEDBG_END2 + return ResultFromScode(sc); + +error: + OLEDBG_END2 + return ResultFromScode(sc); +} + + +STDMETHODIMP CntrDoc_LinkCont_SetLinkSource( + LPOLEUILINKCONTAINER lpThis, + DWORD dwLink, + LPSTR lpszDisplayName, + ULONG lenFileName, + ULONG FAR* lpchEaten, + BOOL fValidateSource +) +{ + LPCONTAINERDOC lpContainerDoc = + ((struct CDocOleUILinkContainerImpl FAR*)lpThis)->lpContainerDoc; + LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)dwLink; + SCODE sc = S_OK; + HRESULT hrErr; + LPOLELINK lpOleLink = lpContainerLine->m_lpOleLink; + LPBC lpbc = NULL; + LPMONIKER lpmk = NULL; + LPOLEOBJECT lpLinkSrcOleObj = NULL; + CLSID clsid = CLSID_NULL; + CLSID clsidOld = CLSID_NULL; + + + OLEDBG_BEGIN2("CntrDoc_LinkCont_SetLinkSource\r\n") + + OleDbgAssert(lpContainerLine); + + lpContainerLine->m_fLinkUnavailable = TRUE; + + if (fValidateSource) { + + /* OLE2NOTE: validate the link source by parsing the string + ** into a Moniker. if this is successful, then the string is + ** valid. + */ + hrErr = CreateBindCtx(0, (LPBC FAR*)&lpbc); + if (hrErr != NOERROR) { + sc = GetScode(hrErr); // ERROR: OOM + goto cleanup; + } + + // Get class of orignial link source if it is available + if (lpContainerLine->m_lpOleObj) { + + OLEDBG_BEGIN2("IOleObject::GetUserClassID called\r\n") + hrErr = lpContainerLine->m_lpOleObj->lpVtbl->GetUserClassID( + lpContainerLine->m_lpOleObj, (CLSID FAR*)&clsidOld); + OLEDBG_END2 + if (hrErr != NOERROR) clsidOld = CLSID_NULL; + } + + hrErr = OleStdMkParseDisplayName( + &clsidOld,lpbc,lpszDisplayName,lpchEaten,(LPMONIKER FAR*)&lpmk); + + if (hrErr != NOERROR) { + sc = GetScode(hrErr); // ERROR in parsing moniker! + goto cleanup; + } + /* OLE2NOTE: the link source was validated; it successfully + ** parsed into a Moniker. we can set the source of the link + ** directly with this Moniker. if we want the link to be + ** able to know the correct class for the new link source, + ** we must bind to the moniker and get the CLSID. if we do + ** not do this then methods like IOleObject::GetUserType + ** will return nothing (NULL strings). + */ + + hrErr = lpmk->lpVtbl->BindToObject( + lpmk,lpbc,NULL,&IID_IOleObject,(LPVOID FAR*)&lpLinkSrcOleObj); + if (hrErr == NOERROR) { + OLEDBG_BEGIN2("IOleObject::GetUserClassID called\r\n") + hrErr = lpLinkSrcOleObj->lpVtbl->GetUserClassID( + lpLinkSrcOleObj, (CLSID FAR*)&clsid); + OLEDBG_END2 + lpContainerLine->m_fLinkUnavailable = FALSE; + + /* get the short user type name of the link because it may + ** have changed. we cache this name and must update our + ** cache. this name is used all the time when we have to + ** build the object verb menu. we cache this information + ** to make it quicker to build the verb menu. + */ + if (lpContainerLine->m_lpszShortType) { + OleStdFree(lpContainerLine->m_lpszShortType); + lpContainerLine->m_lpszShortType = NULL; + } + OLEDBG_BEGIN2("IOleObject::GetUserType called\r\n") + + CallIOleObjectGetUserTypeA( + lpContainerLine->m_lpOleObj, + USERCLASSTYPE_SHORT, + (LPSTR FAR*)&lpContainerLine->m_lpszShortType + ); + + OLEDBG_END2 + } + else + lpContainerLine->m_fLinkUnavailable = TRUE; + } + else { + LPMONIKER lpmkFile = NULL; + LPMONIKER lpmkItem = NULL; + char szDelim[2]; + LPSTR lpszName; + + szDelim[0] = lpszDisplayName[(int)lenFileName]; + szDelim[1] = '\0'; + lpszDisplayName[(int)lenFileName] = '\0'; + + OLEDBG_BEGIN2("CreateFileMoniker called\r\n") + + CreateFileMonikerA(lpszDisplayName, (LPMONIKER FAR*)&lpmkFile); + + OLEDBG_END2 + + lpszDisplayName[(int)lenFileName] = szDelim[0]; + + if (!lpmkFile) + goto cleanup; + + if (lstrlen(lpszDisplayName) > (int)lenFileName) { // have item name + lpszName = lpszDisplayName + lenFileName + 1; + + OLEDBG_BEGIN2("CreateItemMoniker called\r\n") + + CreateItemMonikerA( + szDelim, lpszName, (LPMONIKER FAR*)&lpmkItem); + + OLEDBG_END2 + + if (!lpmkItem) { + OleStdRelease((LPUNKNOWN)lpmkFile); + goto cleanup; + } + + OLEDBG_BEGIN2("CreateGenericComposite called\r\n") + CreateGenericComposite(lpmkFile, lpmkItem, (LPMONIKER FAR*)&lpmk); + OLEDBG_END2 + + if (lpmkFile) + OleStdRelease((LPUNKNOWN)lpmkFile); + if (lpmkItem) + OleStdRelease((LPUNKNOWN)lpmkItem); + + if (!lpmk) + goto cleanup; + } + else + lpmk = lpmkFile; + } + + if (! lpOleLink) { + OleDbgAssert(lpOleLink != NULL); + sc = E_FAIL; + goto cleanup; + } + + if (lpmk) { + + OLEDBG_BEGIN2("IOleLink::SetSourceMoniker called\r\n") + hrErr = lpOleLink->lpVtbl->SetSourceMoniker( + lpOleLink, lpmk, (REFCLSID)&clsid); + OLEDBG_END2 + + if (FAILED(GetScode(hrErr))) { + OleDbgOutHResult("IOleLink::SetSourceMoniker returned",hrErr); + sc = GetScode(hrErr); + goto cleanup; + } + + /* OLE2NOTE: above we forced the link source moniker to bind. + ** because we deliberately hold on to the bind context + ** (lpbc) the link source object will not shut down. during + ** the call to IOleLink::SetSourceMoniker, the link will + ** connect to the running link source (the link internally + ** calls BindIfRunning). it is important to initially allow + ** the link to bind to the running object so that it can get + ** an update of the presentation for its cache. we do not + ** want the connection from our link to the link source be + ** the only reason the link source stays running. thus we + ** deliberately for the link to release (unbind) the source + ** object, we then release the bind context, and then we + ** allow the link to rebind to the link source if it is + ** running anyway. + */ + if (lpbc && lpmk->lpVtbl->IsRunning(lpmk,lpbc,NULL,NULL) == NOERROR) { + + OLEDBG_BEGIN2("IOleLink::Update called\r\n") + hrErr = lpOleLink->lpVtbl->Update(lpOleLink, NULL); + OLEDBG_END2 + +#if defined( _DEBUG ) + if (FAILED(GetScode(hrErr))) + OleDbgOutHResult("IOleLink::Update returned",hrErr); +#endif + + OLEDBG_BEGIN2("IOleLink::UnbindSource called\r\n") + hrErr = lpOleLink->lpVtbl->UnbindSource(lpOleLink); + OLEDBG_END2 + +#if defined( _DEBUG ) + if (FAILED(GetScode(hrErr))) + OleDbgOutHResult("IOleLink::UnbindSource returned",hrErr); +#endif + + if (lpLinkSrcOleObj) { + OleStdRelease((LPUNKNOWN)lpLinkSrcOleObj); + lpLinkSrcOleObj = NULL; + } + + if (lpbc) { + OleStdRelease((LPUNKNOWN)lpbc); + lpbc = NULL; + } + + OLEDBG_BEGIN2("IOleLink::BindIfRunning called\r\n") + hrErr = lpOleLink->lpVtbl->BindIfRunning(lpOleLink); + OLEDBG_END2 + +#if defined( _DEBUG ) + if (FAILED(GetScode(hrErr))) + OleDbgOutHResult("IOleLink::BindIfRunning returned",hrErr); +#endif + } + } else { + /* OLE2NOTE: the link source was NOT validated; it was NOT + ** successfully parsed into a Moniker. we can only set the + ** display name string as the source of the link. this link + ** is not able to bind. + */ + OLEDBG_BEGIN2("IOleLink::SetSourceDisplayName called\r\n") + + hrErr = CallIOleLinkSetSourceDisplayNameA( + lpOleLink, lpszDisplayName); + + OLEDBG_END2 + + if (hrErr != NOERROR) { + OleDbgOutHResult("IOleLink::SetSourceDisplayName returned",hrErr); + sc = GetScode(hrErr); + goto cleanup; + } + } + +cleanup: + if (lpLinkSrcOleObj) + OleStdRelease((LPUNKNOWN)lpLinkSrcOleObj); + if (lpmk) + OleStdRelease((LPUNKNOWN)lpmk); + if (lpbc) + OleStdRelease((LPUNKNOWN)lpbc); + + OLEDBG_END2 + return ResultFromScode(sc); +} + + +STDMETHODIMP CntrDoc_LinkCont_GetLinkSource( + LPOLEUILINKCONTAINER lpThis, + DWORD dwLink, + LPSTR FAR* lplpszDisplayName, + ULONG FAR* lplenFileName, + LPSTR FAR* lplpszFullLinkType, + LPSTR FAR* lplpszShortLinkType, + BOOL FAR* lpfSourceAvailable, + BOOL FAR* lpfIsSelected +) +{ + LPCONTAINERDOC lpContainerDoc = + ((struct CDocOleUILinkContainerImpl FAR*)lpThis)->lpContainerDoc; + LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)dwLink; + LPOLELINK lpOleLink = lpContainerLine->m_lpOleLink; + LPOLEOBJECT lpOleObj = NULL; + LPMONIKER lpmk = NULL; + LPMONIKER lpmkFirst = NULL; + LPBC lpbc = NULL; + SCODE sc = S_OK; + HRESULT hrErr; + + OLEDBG_BEGIN2("CntrDoc_LinkCont_GetLinkSource\r\n") + + /* OLE2NOTE: we must make sure to set all out parameters to NULL. */ + *lplpszDisplayName = NULL; + *lplpszFullLinkType = NULL; + *lplpszShortLinkType= NULL; + *lplenFileName = 0; + *lpfSourceAvailable = !lpContainerLine->m_fLinkUnavailable; + + OleDbgAssert(lpContainerLine); + + if (! lpOleLink) { + OLEDBG_END2 + return ResultFromScode(E_FAIL); + } + + OLEDBG_BEGIN2("IOleLink::GetSourceMoniker called\r\n") + hrErr = lpOleLink->lpVtbl->GetSourceMoniker( + lpOleLink, + (LPMONIKER FAR*)&lpmk + ); + OLEDBG_END2 + + if (hrErr == NOERROR) { + /* OLE2NOTE: the link has the Moniker form of the link source; + ** this is therefore a validated link source. if the first + ** part of the Moniker is a FileMoniker, then we need to + ** return the length of the filename string. we need to + ** return the ProgID associated with the link source as the + ** "lpszShortLinkType". we need to return the + ** FullUserTypeName associated with the link source as the + ** "lpszFullLinkType". + */ + + lpOleObj = (LPOLEOBJECT)OleStdQueryInterface( + (LPUNKNOWN)lpOleLink, &IID_IOleObject); + if (lpOleObj) { + CallIOleObjectGetUserTypeA( + lpOleObj, + USERCLASSTYPE_FULL, + lplpszFullLinkType + ); + + CallIOleObjectGetUserTypeA( + lpOleObj, + USERCLASSTYPE_SHORT, + lplpszShortLinkType + ); + + OleStdRelease((LPUNKNOWN)lpOleObj); + } + *lplenFileName = OleStdGetLenFilePrefixOfMoniker(lpmk); + lpmk->lpVtbl->Release(lpmk); + } + + OLEDBG_BEGIN2("IOleLink::GetSourceDisplayName called\r\n") + + hrErr = CallIOleLinkGetSourceDisplayNameA( + lpOleLink, + lplpszDisplayName + ); + + OLEDBG_END2 + + if (hrErr != NOERROR) { + OleDbgOutHResult("IOleLink::GetSourceDisplayName returned", hrErr); + OLEDBG_END2 + return hrErr; + } + + OLEDBG_END2 + + if (lpfIsSelected) + *lpfIsSelected = Line_IsSelected((LPLINE)lpContainerLine); + + return NOERROR; +} + + +STDMETHODIMP CntrDoc_LinkCont_OpenLinkSource( + LPOLEUILINKCONTAINER lpThis, + DWORD dwLink +) +{ + LPCONTAINERDOC lpContainerDoc = + ((struct CDocOleUILinkContainerImpl FAR*)lpThis)->lpContainerDoc; + LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)dwLink; + SCODE sc = S_OK; + + OLEDBG_BEGIN2("CntrDoc_LinkCont_OpenLinkSource\r\n") + + OleDbgAssert(lpContainerLine); + + if (! ContainerLine_DoVerb( + lpContainerLine, OLEIVERB_SHOW, NULL, TRUE, FALSE)) { + sc = E_FAIL; + } + + lpContainerLine->m_fLinkUnavailable = (sc != S_OK); + + OLEDBG_END2 + return ResultFromScode(sc); +} + + +STDMETHODIMP CntrDoc_LinkCont_UpdateLink( + LPOLEUILINKCONTAINER lpThis, + DWORD dwLink, + BOOL fErrorMessage, + BOOL fErrorAction // ignore if fErrorMessage + // is FALSE +) +{ + LPCONTAINERDOC lpContainerDoc = + ((struct CDocOleUILinkContainerImpl FAR*)lpThis)->lpContainerDoc; + LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)dwLink; + SCODE sc = S_OK; + /* Default to update of the link */ + HRESULT hrErr = S_FALSE; + + OLEDBG_BEGIN2("CntrDoc_LinkCont_UpdateLink\r\n") + + OleDbgAssert(lpContainerLine); + + if (! lpContainerLine->m_lpOleObj) + ContainerLine_LoadOleObject(lpContainerLine); + + if (!fErrorMessage) { + OLEDBG_BEGIN2("IOleObject::IsUpToDate called\r\n") + hrErr = lpContainerLine->m_lpOleObj->lpVtbl->IsUpToDate( + lpContainerLine->m_lpOleObj + ); + OLEDBG_END2 + } + + if (hrErr != NOERROR) { + OLEDBG_BEGIN2("IOleObject::Update called\r\n") + hrErr = lpContainerLine->m_lpOleObj->lpVtbl->Update( + lpContainerLine->m_lpOleObj + ); + OLEDBG_END2 + } + + /* OLE2NOTE: If IOleObject::Update on the Link object returned + ** OLE_E_CLASSDIFF because the link source is no longer + ** the expected class, then the link should be re-created with + ** the new link source. thus the link will be updated with the + ** new link source. + */ + if (GetScode(hrErr) == OLE_E_CLASSDIFF) + hrErr = ContainerLine_ReCreateLinkBecauseClassDiff(lpContainerLine); + + lpContainerLine->m_fLinkUnavailable = (hrErr != NOERROR); + + if (hrErr != NOERROR) { + OleDbgOutHResult("IOleObject::Update returned", hrErr); + sc = GetScode(hrErr); + if (fErrorMessage) { + ContainerLine_ProcessOleRunError( + lpContainerLine,hrErr,fErrorAction,FALSE/*fMenuInvoked*/); + } + } + /* OLE2NOTE: if the update of the object requires us to update our + ** display, then we will automatically be sent a OnViewChange + ** advise. thus we do not need to take any action here to force + ** a repaint. + */ + + OLEDBG_END2 + return ResultFromScode(sc); +} + + +/* CntrDoc_LinkCont_CancelLink +** --------------------------- +** Convert the link to a static picture. +** +** OLE2NOTE: OleCreateStaticFromData can be used to create a static +** picture object. +*/ +STDMETHODIMP CntrDoc_LinkCont_CancelLink( + LPOLEUILINKCONTAINER lpThis, + DWORD dwLink +) +{ + LPCONTAINERDOC lpContainerDoc = + ((struct CDocOleUILinkContainerImpl FAR*)lpThis)->lpContainerDoc; + LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)dwLink; + LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList; + LPLINE lpLine = NULL; + HDC hDC; + int nTab = 0; + char szStgName[CWCSTORAGENAME]; + LPCONTAINERLINE lpNewContainerLine = NULL; + LPDATAOBJECT lpSrcDataObj; + LPOLELINK lpOleLink = lpContainerLine->m_lpOleLink; + int nIndex = LineList_GetLineIndex(lpLL, (LPLINE)lpContainerLine); + + OLEDBG_BEGIN2("CntrDoc_LinkCont_CancelLink\r\n") + + /* we will first break the connection of the link to its source. */ + if (lpOleLink) { + lpContainerLine->m_dwLinkType = 0; + OLEDBG_BEGIN2("IOleLink::SetSourceMoniker called\r\n") + lpOleLink->lpVtbl->SetSourceMoniker( + lpOleLink, NULL, (REFCLSID)&CLSID_NULL); + OLEDBG_END2 + } + + lpSrcDataObj = (LPDATAOBJECT)ContainerLine_GetOleObject( + lpContainerLine,&IID_IDataObject); + if (! lpSrcDataObj) + goto error; + + ContainerDoc_GetNextStgName(lpContainerDoc, szStgName, sizeof(szStgName)); + nTab = Line_GetTabLevel((LPLINE)lpContainerLine); + hDC = LineList_GetDC(lpLL); + + lpNewContainerLine = ContainerLine_CreateFromData( + hDC, + nTab, + lpContainerDoc, + lpSrcDataObj, + OLECREATEFROMDATA_STATIC, + 0, /* no special cfFormat required */ + (lpContainerLine->m_dwDrawAspect == DVASPECT_ICON), + NULL, /* hMetaPict */ + szStgName + ); + LineList_ReleaseDC(lpLL, hDC); + + OleStdRelease((LPUNKNOWN)lpSrcDataObj); + + if (! lpNewContainerLine) + goto error; + + OutlineDoc_SetModified((LPOUTLINEDOC)lpContainerDoc, TRUE, TRUE, FALSE); + + LineList_ReplaceLine(lpLL, (LPLINE)lpNewContainerLine, nIndex); + + OLEDBG_END2 + return ResultFromScode(NOERROR); + +error: + OutlineApp_ErrorMessage(g_lpApp, "Could not break the link."); + OLEDBG_END2 + return ResultFromScode(E_FAIL); +} diff --git a/private/oleutest/letest/outline/cntrinpl.c b/private/oleutest/letest/outline/cntrinpl.c new file mode 100644 index 000000000..3d8dcd8a8 --- /dev/null +++ b/private/oleutest/letest/outline/cntrinpl.c @@ -0,0 +1,1940 @@ +/************************************************************************* +** +** OLE 2 Container Sample Code +** +** cntrinpl.c +** +** This file contains all interfaces, methods and related support +** functions for an In-Place Container application (aka. Visual +** Editing). The in-place Container application includes the following +** implementation objects: +** +** ContainerApp Object +** exposed interfaces: +** IOleInPlaceFrame +** +** ContainerDoc Object +** support functions only +** (ICntrOtl is an SDI app; it doesn't support a Doc level IOleUIWindow) +** +** ContainerLin Object +** exposed interfaces: +** IOleInPlaceSite +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + +#include "outline.h" +#if defined( USE_STATUSBAR ) +#include "status.h" +#endif + +OLEDBGDATA + +extern LPOUTLINEAPP g_lpApp; +extern BOOL g_fInsideOutContainer; +extern RECT g_rectNull; + +/************************************************************************* +** ContainerApp::IOleInPlaceFrame interface implementation +*************************************************************************/ + +// IOleInPlaceFrame::QueryInterface +STDMETHODIMP CntrApp_IPFrame_QueryInterface( + LPOLEINPLACEFRAME lpThis, + REFIID riid, + LPVOID FAR* lplpvObj +) +{ + SCODE sc = E_NOINTERFACE; + LPCONTAINERAPP lpContainerApp = + ((struct COleInPlaceFrameImpl FAR*)lpThis)->lpContainerApp; + + /* The object should not be able to access the other interfaces + ** of our App object by doing QI on this interface. + */ + *lplpvObj = NULL; + if (IsEqualIID(riid, &IID_IUnknown) || + IsEqualIID(riid, &IID_IOleWindow) || + IsEqualIID(riid, &IID_IOleInPlaceUIWindow) || + IsEqualIID(riid, &IID_IOleInPlaceFrame)) { + OleDbgOut4("CntrApp_IPFrame_QueryInterface: IOleInPlaceFrame* RETURNED\r\n"); + *lplpvObj = (LPVOID) &lpContainerApp->m_OleInPlaceFrame; + OleApp_AddRef((LPOLEAPP)lpContainerApp); + sc = S_OK; + } + + OleDbgQueryInterfaceMethod(*lplpvObj); + + return ResultFromScode(sc); +} + + +// IOleInPlaceFrame::AddRef +STDMETHODIMP_(ULONG) CntrApp_IPFrame_AddRef(LPOLEINPLACEFRAME lpThis) +{ + OleDbgAddRefMethod(lpThis, "IOleInPlaceFrame"); + + return OleApp_AddRef((LPOLEAPP)g_lpApp); +} + + +// IOleInPlaceFrame::Release +STDMETHODIMP_(ULONG) CntrApp_IPFrame_Release(LPOLEINPLACEFRAME lpThis) +{ + OleDbgReleaseMethod(lpThis, "IOleInPlaceFrame"); + + return OleApp_Release((LPOLEAPP)g_lpApp); +} + + +// IOleInPlaceFrame::GetWindow +STDMETHODIMP CntrApp_IPFrame_GetWindow( + LPOLEINPLACEFRAME lpThis, + HWND FAR* lphwnd +) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + + OLEDBG_BEGIN2("CntrApp_IPFrame_GetWindow\r\n") + *lphwnd = lpOutlineApp->m_hWndApp; + OLEDBG_END2 + return NOERROR; +} + + +// IOleInPlaceFrame::ContextSensitiveHelp +STDMETHODIMP CntrApp_IPFrame_ContextSensitiveHelp( + LPOLEINPLACEFRAME lpThis, + BOOL fEnterMode +) +{ + LPCONTAINERAPP lpContainerApp = + ((struct COleInPlaceFrameImpl FAR*)lpThis)->lpContainerApp; + + OleDbgOut("CntrApp_IPFrame_ContextSensitiveHelp\r\n"); + /* OLE2NOTE: see context sensitive help technote (CSHELP.DOC) + ** This method is called when F1 is pressed when a menu item is + ** selected. We set the frame's m_fMenuMode flag here. later, + ** in WM_COMMAND processing in the AppWndProc, if this flag is + ** set then the command is NOT executed and help is given + ** instead. + */ + lpContainerApp->m_fMenuHelpMode = fEnterMode; + + return NOERROR; +} + + +// IOleInPlaceFrame::GetBorder +STDMETHODIMP CntrApp_IPFrame_GetBorder( + LPOLEINPLACEFRAME lpThis, + LPRECT lprectBorder +) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + + OLEDBG_BEGIN2("CntrApp_IPFrame_GetBorder\r\n") + + OutlineApp_GetFrameRect(lpOutlineApp, lprectBorder); + + OLEDBG_END2 + return NOERROR; +} + + +// IOleInPlaceFrame::RequestBorderSpace +STDMETHODIMP CntrApp_IPFrame_RequestBorderSpace( + LPOLEINPLACEFRAME lpThis, + LPCBORDERWIDTHS lpWidths +) +{ +#if defined( _DEBUG ) + OleDbgOut2("CntrApp_IPFrame_RequestBorderSpace\r\n"); + + { + /* FOR DEBUGING PURPOSES ONLY -- we will fail to allow to an + ** object to get any frame border space for frame tools if + ** our own frame tools are poped up in the tool pallet. this + ** is NOT recommended UI behavior but it allows us to test + ** in the condition when the frame does not give border + ** space for the object. an object in this situation must + ** then either popup its tools in a floating pallet, do + ** without the tools, or fail to in-place activate. + */ + LPCONTAINERAPP lpContainerApp = + ((struct COleInPlaceFrameImpl FAR*)lpThis)->lpContainerApp; + LPFRAMETOOLS lpft = OutlineApp_GetFrameTools( + (LPOUTLINEAPP)lpContainerApp); + + if (lpft->m_ButtonBar.m_nState == BARSTATE_POPUP && + lpft->m_FormulaBar.m_nState == BARSTATE_POPUP) { + OleDbgOut3( + "CntrApp_IPFrame_RequestBorderSpace: allow NO SPACE\r\n"); + return ResultFromScode(E_FAIL); + } + } +#endif // _DEBUG + + /* OLE2NOTE: we allow the object to have as much border space as it + ** wants. + */ + return NOERROR; +} + + +// IOleInPlaceFrame::SetBorderSpace +STDMETHODIMP CntrApp_IPFrame_SetBorderSpace( + LPOLEINPLACEFRAME lpThis, + LPCBORDERWIDTHS lpWidths +) +{ + LPCONTAINERAPP lpContainerApp = + ((struct COleInPlaceFrameImpl FAR*)lpThis)->lpContainerApp; + OLEDBG_BEGIN2("CntrApp_IPFrame_SetBorderSpace\r\n") + + /* OLE2NOTE: this fMustResizeClientArea flag is used as part of our + ** defensive programming for frame window resizing. when the + ** frame window is resized,IOleInPlaceActiveObject::ResizeBorder + ** is called the object should normally call back to renegotiate + ** for frame-level tools space. if SetBorderSpace is called then + ** our client area windows are properly resized. if the in-place + ** active object does NOT call SetBorderSpace, then the + ** container must take care to resize its client area windows + ** itself (see ContainerDoc_FrameWindowResized) + */ + if (lpContainerApp->m_fMustResizeClientArea) + lpContainerApp->m_fMustResizeClientArea = FALSE; + + if (lpWidths == NULL) { + + /* OLE2NOTE: IOleInPlaceSite::SetBorderSpace(NULL) is called + ** when the in-place active object does NOT want any tool + ** space. in this situation the in-place container should + ** put up its tools. + */ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpContainerApp; + LPCONTAINERDOC lpContainerDoc; + + lpContainerDoc =(LPCONTAINERDOC)OutlineApp_GetActiveDoc(lpOutlineApp); + ContainerDoc_AddFrameLevelTools(lpContainerDoc); + } else { + + // OLE2NOTE: you could do validation of borderwidths here +#if defined( _DEBUG ) + /* FOR DEBUGING PURPOSES ONLY -- we will fail to allow to an + ** object to get any frame border space for frame tools if + ** our own frame tools are poped up in the tool pallet. this + ** is NOT recommended UI behavior but it allows us to test + ** in the condition when the frame does not give border + ** space for the object. an object in this situation must + ** then either popup its tools in a floating pallet, do + ** without the tools, or fail to in-place activate. + */ + LPFRAMETOOLS lpft = OutlineApp_GetFrameTools( + (LPOUTLINEAPP)lpContainerApp); + + if ((lpft->m_ButtonBar.m_nState == BARSTATE_POPUP && + lpft->m_FormulaBar.m_nState == BARSTATE_POPUP) && + (lpWidths->top || lpWidths->bottom || + lpWidths->left || lpWidths->right) ) { + OleDbgOut3("CntrApp_IPFrame_SetBorderSpace: allow NO SPACE\r\n"); + OLEDBG_END2 + + OutlineApp_SetBorderSpace( + (LPOUTLINEAPP) lpContainerApp, + (LPBORDERWIDTHS)&g_rectNull + ); + OLEDBG_END2 + return ResultFromScode(E_FAIL); + } +#endif // _DEBUG + + OutlineApp_SetBorderSpace( + (LPOUTLINEAPP) lpContainerApp, + (LPBORDERWIDTHS)lpWidths + ); + } + OLEDBG_END2 + return NOERROR; +} + + +// IOleInPlaceFrame::SetActiveObject +STDMETHODIMP CntrApp_IPFrame_SetActiveObjectA( + LPOLEINPLACEFRAME lpThis, + LPOLEINPLACEACTIVEOBJECT lpActiveObject, + LPCSTR lpszObjName +) +{ + LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp; + OLEDBG_BEGIN2("CntrApp_IPFrame_SetActiveObject\r\n") + + lpContainerApp->m_hWndUIActiveObj = NULL; + + if (lpContainerApp->m_lpIPActiveObj) + lpContainerApp->m_lpIPActiveObj->lpVtbl->Release(lpContainerApp->m_lpIPActiveObj); + + if ((lpContainerApp->m_lpIPActiveObj = lpActiveObject) != NULL) { + lpContainerApp->m_lpIPActiveObj->lpVtbl->AddRef( + lpContainerApp->m_lpIPActiveObj); + + OLEDBG_BEGIN2("IOleInPlaceActiveObject::GetWindow called\r\n") + lpActiveObject->lpVtbl->GetWindow( + lpActiveObject, + (HWND FAR*)&lpContainerApp->m_hWndUIActiveObj + ); + OLEDBG_END2 + + /* OLE2NOTE: see comment for ContainerDoc_ForwardPaletteChangedMsg */ + /* No need to do this if you don't allow object to own the palette */ + OleApp_QueryNewPalette((LPOLEAPP)lpContainerApp); + } + + /* OLE2NOTE: the new UI Guidelines recommend that in-place + ** containers do NOT change their window titles when an object + ** becomes in-place (UI) active. + */ + + OLEDBG_END2 + return NOERROR; +} + + +STDMETHODIMP CntrApp_IPFrame_SetActiveObject( + LPOLEINPLACEFRAME lpThis, + LPOLEINPLACEACTIVEOBJECT lpActiveObject, + LPCOLESTR lpszObjName +) +{ + CREATESTR(pstr, lpszObjName) + + HRESULT hr = CntrApp_IPFrame_SetActiveObjectA(lpThis, lpActiveObject, pstr); + + FREESTR(pstr) + + return hr; +} + + +// IOleInPlaceFrame::InsertMenus +STDMETHODIMP CntrApp_IPFrame_InsertMenus( + LPOLEINPLACEFRAME lpThis, + HMENU hMenu, + LPOLEMENUGROUPWIDTHS lpMenuWidths +) +{ + LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp; + BOOL fNoError = TRUE; + + OLEDBG_BEGIN2("CntrApp_IPFrame_InsertMenus\r\n") + + fNoError &= AppendMenu(hMenu, MF_POPUP, (UINT)lpContainerApp->m_hMenuFile, + "&File"); + fNoError &= AppendMenu(hMenu, MF_POPUP, (UINT)lpContainerApp->m_hMenuView, + "O&utline"); + fNoError &= AppendMenu(hMenu, MF_POPUP,(UINT)lpContainerApp->m_hMenuDebug, + "DbgI&Cntr"); + lpMenuWidths->width[0] = 1; + lpMenuWidths->width[2] = 1; + lpMenuWidths->width[4] = 1; + + OLEDBG_END2 + + return (fNoError ? NOERROR : ResultFromScode(E_FAIL)); +} + + +// IOleInPlaceFrame::SetMenu +STDMETHODIMP CntrApp_IPFrame_SetMenu( + LPOLEINPLACEFRAME lpThis, + HMENU hMenuShared, + HOLEMENU hOleMenu, + HWND hwndActiveObject +) +{ + LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp; + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + HMENU hMenu; + HRESULT hrErr; + + OLEDBG_BEGIN2("CntrApp_IPFrame_InsertMenus\r\n") + + + /* OLE2NOTE: either put up the shared menu (combined menu from + ** in-place server and in-place container) or our container's + ** normal menu as directed. + */ + if (hOleMenu && hMenuShared) + hMenu = hMenuShared; + else + hMenu = lpOutlineApp->m_hMenuApp; + + /* OLE2NOTE: SDI apps put menu on frame by calling SetMenu. + ** MDI apps would send WM_MDISETMENU message instead. + */ + SetMenu (lpOutlineApp->m_hWndApp, hMenu); + OLEDBG_BEGIN2("OleSetMenuDescriptor called\r\n") + hrErr = OleSetMenuDescriptor (hOleMenu, lpOutlineApp->m_hWndApp, + hwndActiveObject, NULL, NULL); + OLEDBG_END2 + + OLEDBG_END2 + return hrErr; +} + + +// IOleInPlaceFrame::RemoveMenus +STDMETHODIMP CntrApp_IPFrame_RemoveMenus( + LPOLEINPLACEFRAME lpThis, + HMENU hMenu +) +{ + LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp; + BOOL fNoError = TRUE; + + OLEDBG_BEGIN2("CntrApp_IPFrame_RemoveMenus\r\n") + + /* Remove container group menus */ + while (GetMenuItemCount(hMenu)) + fNoError &= RemoveMenu(hMenu, 0, MF_BYPOSITION); + + OleDbgAssert(fNoError == TRUE); + + OLEDBG_END2 + + return (fNoError ? NOERROR : ResultFromScode(E_FAIL)); +} + + +// IOleInPlaceFrame::SetStatusText +STDMETHODIMP CntrApp_IPFrame_SetStatusTextA( + LPOLEINPLACEFRAME lpThis, + LPCSTR lpszStatusText +) +{ +#if defined( USE_STATUSBAR ) + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + static char szMessageHold[128]; + OleDbgOut2("CntrApp_IPFrame_SetStatusText\r\n"); + + /* OLE2NOTE: it is important to save a private copy of status text. + ** lpszStatusText is only valid for the duration of this call. + */ + LSTRCPYN(szMessageHold, lpszStatusText, sizeof(szMessageHold)); + OutlineApp_SetStatusText(lpOutlineApp, (LPSTR)szMessageHold); + + return ResultFromScode(S_OK); +#else + return ResultFromScode(E_NOTIMPL); +#endif // USE_STATUSBAR +} + + +STDMETHODIMP CntrApp_IPFrame_SetStatusText( + LPOLEINPLACEFRAME lpThis, + LPCOLESTR lpszStatusText +) +{ + CREATESTR(pstr, lpszStatusText) + + HRESULT hr = CntrApp_IPFrame_SetStatusTextA(lpThis, pstr); + + FREESTR(pstr) + + return hr; +} + + + +// IOleInPlaceFrame::EnableModeless +STDMETHODIMP CntrApp_IPFrame_EnableModeless( + LPOLEINPLACEFRAME lpThis, + BOOL fEnable +) +{ + LPOLEAPP lpOleApp = (LPOLEAPP) + ((struct COleInPlaceFrameImpl FAR*)lpThis)->lpContainerApp; +#if defined( _DEBUG ) + if (fEnable) + OleDbgOut2("CntrApp_IPFrame_EnableModeless(TRUE)\r\n"); + else + OleDbgOut2("CntrApp_IPFrame_EnableModeless(FALSE)\r\n"); +#endif // _DEBUG + + /* OLE2NOTE: this method is called when an object puts up a modal + ** dialog. it tells the top-level in-place container to disable + ** it modeless dialogs for the duration that the object is + ** displaying a modal dialog. + ** + ** ICNTROTL does not use any modeless dialogs, thus we can + ** ignore this method. + */ + return NOERROR; +} + + +// IOleInPlaceFrame::TranslateAccelerator +STDMETHODIMP CntrApp_IPFrame_TranslateAccelerator( + LPOLEINPLACEFRAME lpThis, + LPMSG lpmsg, + WORD wID +) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp; + SCODE sc; + + if (TranslateAccelerator (lpOutlineApp->m_hWndApp, + lpContainerApp->m_hAccelIPCntr, lpmsg)) + sc = S_OK; + +#if defined (MDI_VERSION) + else if (TranslateMDISysAccel(lpOutlineApp->m_hWndMDIClient, lpmsg)) + sc = S_OK; +#endif // MDI_VERSION + + else + sc = S_FALSE; + + return ResultFromScode(sc); +} + + + +/************************************************************************* +** ContainerDoc Support Functions +*************************************************************************/ + + +/* ContainerDoc_UpdateInPlaceObjectRects +** ------------------------------------- +** Update the PosRect and ClipRect of the currently in-place active +** object. if there is no object active in-place, then do nothing. +** +** OLE2NOTE: this function should be called when an action occurs +** that changes either the position of the object in the document +** (eg. changing document margins changes PosRect) or the clipRect +** changes (eg. resizing the document window changes the ClipRect). +*/ +void ContainerDoc_UpdateInPlaceObjectRects(LPCONTAINERDOC lpContainerDoc, int nIndex) +{ + LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList; + int i; + LPLINE lpLine; + RECT rcClipRect; + + if (g_fInsideOutContainer) { + + if (lpContainerDoc->m_cIPActiveObjects) { + + /* OLE2NOTE: (INSIDE-OUT CONTAINER) we must update the + ** PosRect/ClipRect for all in-place active objects + ** starting from line "nIndex". + */ + ContainerDoc_GetClipRect(lpContainerDoc, (LPRECT)&rcClipRect); + +#if defined( _DEBUG ) + OleDbgOutRect3( + "ContainerDoc_UpdateInPlaceObjectRects (ClipRect)", + (LPRECT)&rcClipRect + ); +#endif + for (i = nIndex; i < lpLL->m_nNumLines; i++) { + lpLine=LineList_GetLine(lpLL, i); + + if (lpLine && (Line_GetLineType(lpLine)==CONTAINERLINETYPE)) { + LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)lpLine; + ContainerLine_UpdateInPlaceObjectRects( + lpContainerLine, &rcClipRect); + } + } + } + } + else { + /* OLE2NOTE: (OUTSIDE-IN CONTAINER) if there is a currently + ** UIActive object, we must inform it that the + ** PosRect/ClipRect has now changed. + */ + LPCONTAINERLINE lpLastUIActiveLine = + lpContainerDoc->m_lpLastUIActiveLine; + if (lpLastUIActiveLine && lpLastUIActiveLine->m_fUIActive) { + ContainerDoc_GetClipRect(lpContainerDoc, (LPRECT)&rcClipRect); + + OleDbgOutRect3("OutlineDoc_Resize (ClipRect)",(LPRECT)&rcClipRect); + ContainerLine_UpdateInPlaceObjectRects( + lpLastUIActiveLine, &rcClipRect); + } + } +} + +/* ContainerDoc_IsUIDeactivateNeeded +** --------------------------------- +** Check if it is necessary to UIDeactivate an in-place active +** object upon a mouse LBUTTONDOWN event. The position of the button +** down click is given by "pt". +** If there is not currently an in-place active line, then +** UIDeactivate is NOT needed. +** If there is a current in-place active line, then check if the +** point position is outside of the object extents on the screen. If +** so, then the object should be UIDeactivated, otherwise not. +*/ +BOOL ContainerDoc_IsUIDeactivateNeeded( + LPCONTAINERDOC lpContainerDoc, + POINT pt +) +{ + LPCONTAINERLINE lpUIActiveLine=lpContainerDoc->m_lpLastUIActiveLine; + RECT rect; + + if (! lpUIActiveLine || ! lpUIActiveLine->m_fUIActive) + return FALSE; + + ContainerLine_GetPosRect( + lpUIActiveLine, + (LPRECT) &rect + ); + + if (! PtInRect((LPRECT) &rect, pt)) + return TRUE; + + return FALSE; +} + + +/* ContainerDoc_ShutDownLastInPlaceServerIfNotNeeded +** ------------------------------------------------- +** OLE2NOTE: this function ONLY applies for OUTSIDE-IN containers +** +** If there is a previous in-place active server still running and +** this server will not be needed to support the next OLE object +** about to be activated, then shut it down. +** in this way we manage a policy of having at most one in-place +** server running at a time. we do not imediately shut down the +** in-place server when the object is UIDeactivated because we want +** it to be fast if the server decides to re-activate the object +** in-place. +** +** shutting down the server is achieved by forcing the object to +** transition from running to loaded by calling IOleObject::Close. +*/ +void ContainerDoc_ShutDownLastInPlaceServerIfNotNeeded( + LPCONTAINERDOC lpContainerDoc, + LPCONTAINERLINE lpNextActiveLine +) +{ + LPCONTAINERLINE lpLastIpActiveLine = lpContainerDoc->m_lpLastIpActiveLine; + BOOL fEnableServerShutDown = TRUE; + LPMONIKER lpmkLinkSrc; + LPMONIKER lpmkLastActiveObj; + LPMONIKER lpmkCommonPrefix; + LPOLELINK lpOleLink; + HRESULT hrErr; + + /* OLE2NOTE: an inside-out style container can NOT use this scheme + ** to shut down in-place servers. it would have to have a more + ** sophistocated mechanism by which it keeps track of which + ** objects are on screen and which were the last recently used. + */ + if (g_fInsideOutContainer) + return; + + if (lpLastIpActiveLine != lpNextActiveLine) { + if (lpLastIpActiveLine) { + + /* OLE2NOTE: if the object which is about to be activated is + ** actually a link to the OLE object in last activated line, + ** then we do NOT want to shut down the last activated + ** server because it is about to be used. when activating a + ** linked object, the source of the link gets activated. + */ + lpOleLink = (LPOLELINK)ContainerLine_GetOleObject( + lpNextActiveLine, + &IID_IOleLink + ); + if (lpOleLink) { + OLEDBG_BEGIN2("IOleObject::GetSourceMoniker called\r\n") + lpOleLink->lpVtbl->GetSourceMoniker( + lpOleLink, + (LPMONIKER FAR*)&lpmkLinkSrc + ); + OLEDBG_END2 + + if (lpmkLinkSrc) { + lpmkLastActiveObj = ContainerLine_GetFullMoniker( + lpLastIpActiveLine, + GETMONIKER_ONLYIFTHERE + ); + if (lpmkLastActiveObj) { + hrErr = lpmkLinkSrc->lpVtbl->CommonPrefixWith( + lpmkLinkSrc, + lpmkLastActiveObj, + &lpmkCommonPrefix + + ); + if (GetScode(hrErr) == MK_S_HIM || + hrErr == NOERROR || + GetScode(hrErr) == MK_S_US) { + /* the link source IS to the object + ** contained in the last activated + ** line of the document; disable the + ** attempt to shut down the last + ** running in-place server. + */ + fEnableServerShutDown = FALSE; + } + if (lpmkCommonPrefix) + OleStdRelease((LPUNKNOWN)lpmkCommonPrefix); + OleStdRelease((LPUNKNOWN)lpmkLastActiveObj); + } + OleStdRelease((LPUNKNOWN)lpmkLinkSrc); + } + OleStdRelease((LPUNKNOWN)lpOleLink); + } + + /* if it is OK to shut down the previous in-place server + ** and one is still running, then shut it down. shutting + ** down the server is accomplished by forcing the OLE + ** object to close. this forces the object to transition + ** from running to loaded. if the object is actually + ** only loaded then this is a NOP. + */ + if (fEnableServerShutDown && + lpLastIpActiveLine->m_fIpServerRunning) { + + OleDbgOut1("@@@ previous in-place server SHUT DOWN\r\n"); + ContainerLine_CloseOleObject( + lpLastIpActiveLine, OLECLOSE_SAVEIFDIRTY); + + // we can now forget this last in-place active line. + lpContainerDoc->m_lpLastIpActiveLine = NULL; + } + } + } +} + + +/* ContainerDoc_GetUIActiveWindow +** ------------------------------ +** If there is an UIActive object, then return its HWND. +*/ +HWND ContainerDoc_GetUIActiveWindow(LPCONTAINERDOC lpContainerDoc) +{ + return lpContainerDoc->m_hWndUIActiveObj; +} + + +/* ContainerDoc_GetClipRect +** ------------------------ +** Get the ClipRect in client coordinates. +** +** OLE2NOTE: the ClipRect is defined as the maximum window rectangle +** that the in-place active object must be clipped to. this +** rectangle MUST be described in Client Coordinates of the window +** that is used as the Parent of the in-place active object's +** window. in our case, the LineList ListBox window is both the +** parent of the in-place active object AND defines precisely the +** clipping rectangle. +*/ +void ContainerDoc_GetClipRect( + LPCONTAINERDOC lpContainerDoc, + LPRECT lprcClipRect +) +{ + /* OLE2NOTE: the ClipRect can be used to ensure that the in-place + ** server does not overwrite areas of the window that the + ** container paints into but which should never be overwritten + ** (eg. if an app were to paint row and col headings directly in + ** the same window that is the parent of the in-place window. + ** whenever the window size changes or gets scrolled, in-place + ** active object must be informed of the new clip rect. + ** + ** normally an app would pass the rect returned from GetClientRect. + ** but because CntrOutl uses separate windows for row/column + ** headings, status line, formula/tool bars, etc. it is NOT + ** necessary to pass a constrained clip rect. Windows standard + ** window clipping will automatically take care of all clipping + ** that is necessary. thus we can take a short cut of passing an + ** "infinite" clip rect, and then we do NOT need to call + ** IOleInPlaceObject::SetObjectRects when our document is scrolled. + */ + + lprcClipRect->top = -32767; + lprcClipRect->left = -32767; + lprcClipRect->right = 32767; + lprcClipRect->bottom = 32767; +} + + +/* ContainerDoc_GetTopInPlaceFrame +** ------------------------------- +** returns NON-AddRef'ed pointer to Top In-Place Frame interface +*/ +LPOLEINPLACEFRAME ContainerDoc_GetTopInPlaceFrame( + LPCONTAINERDOC lpContainerDoc +) +{ +#if defined( INPLACE_CNTRSVR ) + return lpContainerDoc->m_lpTopIPFrame; +#else + return (LPOLEINPLACEFRAME)&((LPCONTAINERAPP)g_lpApp)->m_OleInPlaceFrame; +#endif +} + +void ContainerDoc_GetSharedMenuHandles( + LPCONTAINERDOC lpContainerDoc, + HMENU FAR* lphSharedMenu, + HOLEMENU FAR* lphOleMenu +) +{ +#if defined( INPLACE_CNTRSVR ) + if (lpContainerDoc->m_DocType == DOCTYPE_EMEBEDDEDOBJECT) { + *lphSharedMenu = lpContainerDoc->m_hSharedMenu; + *lphOleMenu = lpContainerDoc->m_hOleMenu; + return; + } +#endif + + *lphSharedMenu = NULL; + *lphOleMenu = NULL; +} + + +#if defined( USE_FRAMETOOLS ) +void ContainerDoc_RemoveFrameLevelTools(LPCONTAINERDOC lpContainerDoc) +{ + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerDoc; + OleDbgAssert(lpOutlineDoc->m_lpFrameTools != NULL); + + FrameTools_Enable(lpOutlineDoc->m_lpFrameTools, FALSE); +} +#endif + + +void ContainerDoc_AddFrameLevelUI(LPCONTAINERDOC lpContainerDoc) +{ + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerDoc; + LPOLEINPLACEFRAME lpTopIPFrame = ContainerDoc_GetTopInPlaceFrame( + lpContainerDoc); + HMENU hSharedMenu; // combined obj/cntr menu + HOLEMENU hOleMenu; // returned by OleCreateMenuDesc. + + ContainerDoc_GetSharedMenuHandles( + lpContainerDoc, + &hSharedMenu, + &hOleMenu + ); + + lpTopIPFrame->lpVtbl->SetMenu( + lpTopIPFrame, + hSharedMenu, + hOleMenu, + lpOutlineDoc->m_hWndDoc + ); + + /* OLE2NOTE: even if our app does NOT use FrameTools, we must still + ** call IOleInPlaceFrame::SetBorderSpace. + */ + ContainerDoc_AddFrameLevelTools(lpContainerDoc); +} + + +void ContainerDoc_AddFrameLevelTools(LPCONTAINERDOC lpContainerDoc) +{ + LPOLEINPLACEFRAME lpTopIPFrame = ContainerDoc_GetTopInPlaceFrame( + lpContainerDoc); + LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerDoc; + + OleDbgAssert(lpTopIPFrame != NULL); + +#if defined( USE_FRAMETOOLS ) + + FrameTools_Enable(lpOutlineDoc->m_lpFrameTools, TRUE); + OutlineDoc_UpdateFrameToolButtons(lpOutlineDoc); + + FrameTools_NegotiateForSpaceAndShow( + lpOutlineDoc->m_lpFrameTools, + NULL, + lpTopIPFrame + ); + +#else // ! USE_FRAMETOOLS + +#if defined( INPLACE_CNTRSVR ) + if (lpContainerDoc->m_DocType == DOCTYPE_EMBEDDEDOBJECT) { + /* this says i do not need space, so the top Frame should + ** leave its tools behind + */ + OLEDBG_BEGIN2("IOleInPlaceFrame::SetBorderSpace(NULL) called\r\n") + lpTopIPFrame->lpVtbl->SetBorderSpace(lpTopIPFrame, NULL); + OLEDBG_END2 + return; + } +#else // INPLACE_CNTR && ! USE_FRAMETOOLS + + OLEDBG_BEGIN2("IOleInPlaceFrame::SetBorderSpace(0,0,0,0) called\r\n") + lpTopIPFrame->lpVtbl->SetBorderSpace( + lpTopIPFrame, + (LPCBORDERWIDTHS)&g_rectNull + ); + OLEDBG_END2 + +#endif // INPLACE_CNTR && ! USE_FRAMETOOLS +#endif // ! USE_FRAMETOOLS + +} + + +void ContainerDoc_FrameWindowResized(LPCONTAINERDOC lpContainerDoc) +{ + LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp; + + if (lpContainerApp->m_lpIPActiveObj) { + RECT rcFrameRect; + + /* OLE2NOTE: this fMustResizeClientArea flag is used as part of + ** our defensive programming for frame window resizing. when + ** the frame window is + ** resized, IOleInPlaceActiveObject::ResizeBorder is called + ** the object should normally call back to renegotiate + ** for frame-level tools space. if SetBorderSpace is called + ** then our client area windows are properly resized. + ** CntrApp_IPFrame_SetBorderSpace clears this flag. if the + ** in-place active object does NOT call SetBorderSpace, then + ** the container must take care to resize its client area + ** windows itself. + */ + lpContainerApp->m_fMustResizeClientArea = TRUE; + + OutlineApp_GetFrameRect(g_lpApp, (LPRECT)&rcFrameRect); + + OLEDBG_BEGIN2("IOleInPlaceActiveObject::ResizeBorder called\r\n") + lpContainerApp->m_lpIPActiveObj->lpVtbl->ResizeBorder( + lpContainerApp->m_lpIPActiveObj, + (LPCRECT)&rcFrameRect, + (LPOLEINPLACEUIWINDOW)&lpContainerApp->m_OleInPlaceFrame, + TRUE /* fFrameWindow */ + ); + OLEDBG_END2 + + /* the object did NOT call IOleInPlaceUIWindow::SetBorderSpace + ** therefore we must resize our client area windows ourself. + */ + if (lpContainerApp->m_fMustResizeClientArea) { + lpContainerApp->m_fMustResizeClientArea = FALSE; + OutlineApp_ResizeClientArea(g_lpApp); + } + } + +#if defined( USE_FRAMETOOLS ) + else { + ContainerDoc_AddFrameLevelTools(lpContainerDoc); + } +#endif +} + + +#if defined( INPLACE_CNTRSVR ) || defined( INPLACE_MDICNTR ) + +/* ContainerDoc_GetTopInPlaceDoc +** returns NON-AddRef'ed pointer to Top In-Place Doc interface +*/ +LPOLEINPLACEUIWINDOW ContainerDoc_GetTopInPlaceDoc( + LPCONTAINERDOC lpContainerDoc +) +{ +#if defined( INPLACE_CNTRSVR ) + return lpContainerDoc->m_lpTopIPDoc; +#else + return (LPOLEINPLACEUIWINDOW)&lpContainerDoc->m_OleInPlaceDoc; +#endif +} + + +void ContainerDoc_RemoveDocLevelTools(LPCONTAINERDOC lpContainerDoc); +{ + LPOLEINPLACEUIWINDOW lpTopIPDoc = ContainerDoc_GetTopInPlaceDoc( + lpContainerDoc); + + if (lpTopIPDoc && lpContainerDoc->m_fMyToolsOnDoc) { + lpContainerDoc->m_fMyToolsOnDoc = FALSE; + + // if we had doc tools we would HIDE them here; + // but NOT call SetBorderSpace(NULL) + + } +} + +void ContainerDoc_AddDocLevelTools(LPCONTAINERDOC lpContainerDoc) +{ + LPOLEINPLACEUIWINDOW lpTopIPDoc = ContainerDoc_GetTopInPlaceDoc( + lpContainerDoc); + + if (! lpTopIPDoc) + return; + +#if defined( USE_DOCTOOLS ) + if (lpTopIPDoc && ! lpContainerDoc->m_fMyToolsOnDoc) { + + /* if we had doc tools we would negotiate for toolbar space at + ** doc level and SHOW them. + */ + + /* we do NOT have doc level tools, so we just call + ** SetBorderSpace() to indicate to the top doc that + ** our object does not need tool space. + */ + + lpContainerDoc->m_fMyToolsOnDoc = TRUE; + return; + } +#else // ! USE_DOCTOOLS + +#if defined( INPLACE_CNTRSVR ) + if (lpContainerDoc->m_DocType == DOCTYPE_EMBEDDEDOBJECT) { + /* this says i do not need space, so the top doc should + ** leave its tools behind + */ + lpTopIPDoc->lpVtbl->SetBorderSpace(lpTopIPDoc, NULL); + return; + } +#else + lpTopIPDoc->lpVtbl->SetBorderSpace( + lpTopIPDoc, + (LPCBORDERWIDTHS)&g_rectNull + ); + +#endif +#endif // ! USE_DOCTOOLS +} + +#endif // INPLACE_CNTRSVR || INPLACE_MDICNTR + + +/* ContainerDoc_ContextSensitiveHelp +** --------------------------------- +** forward the ContextSensitiveHelp mode on to any in-place objects +** that currently have their window visible. this informs the +** objects whether to give help or take action on subsequent mouse +** clicks and menu commands. this function is called from our +** IOleInPlaceSite::ContextSensitiveHelp implementation. +** +** OLE2NOTE: see context sensitive help technote (CSHELP.DOC). +** This function is called when SHIFT-F1 context sensitive help is +** entered. the cursor should then change to a question mark +** cursor and the app should enter a modal state where the next +** mouse click does not perform its normal action but rather +** gives help corresponding to the location clicked. if the app +** does not implement a help system, it should at least eat the +** click and do nothing. +*/ +void ContainerDoc_ContextSensitiveHelp( + LPCONTAINERDOC lpContainerDoc, + BOOL fEnterMode, + BOOL fInitiatedByObj +) +{ + LPOLEDOC lpOleDoc = (LPOLEDOC)lpContainerDoc; + LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList; + int i; + LPLINE lpLine; + + lpOleDoc->m_fCSHelpMode = fEnterMode; + + if (g_fInsideOutContainer) { + + if (lpContainerDoc->m_cIPActiveObjects) { + for (i = 0; i < lpLL->m_nNumLines; i++) { + lpLine=LineList_GetLine(lpLL, i); + + if (lpLine && (Line_GetLineType(lpLine)==CONTAINERLINETYPE)) { + LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)lpLine; + ContainerLine_ContextSensitiveHelp( + lpContainerLine, fEnterMode); + } + } + } + } + else if (! fInitiatedByObj) { + /* OLE2NOTE: (OUTSIDE-IN CONTAINER) if there is a currently + ** UIActive object (ie. its window is visible), we must + ** forward the ContextSensitiveHelp mode on to the + ** object--assuming it was not the object that initiated the + ** context sensitve help mode. + */ + LPCONTAINERLINE lpLastUIActiveLine = + lpContainerDoc->m_lpLastUIActiveLine; + if (lpLastUIActiveLine && lpLastUIActiveLine->m_fUIActive) { + ContainerLine_ContextSensitiveHelp(lpLastUIActiveLine,fEnterMode); + } + } +} + +/* ContainerDoc_ForwardPaletteChangedMsg +** ------------------------------------- +** forward the WM_PALETTECHANGED message (via SendMessage) to any +** in-place objects that currently have their window visible. this +** gives these objects the chance to select their palette as a +** BACKGROUND palette. +** +** SEE THE TECHNOTE FOR DETAILED INFORMATION ON PALETTE COORDINATION +** +** OLE2NOTE: For containers and objects to manage palettes properly +** (when objects are getting inplace edited) they should follow a +** set of rules. +** +** Rule 1: The Container can decide if it wants to own the palette or +** it wants to allow its UIActive object to own the palette. +** a) If the container wants to let its UIActive object own the +** palette then it should forward WM_QUERYNEWPALETTE to the object +** when it is received to the top frame window. also it should send +** WM_QUERYNEWPALETTE to the object in its +** IOleInPlaceFrame::SetActiveObject implementation. if the object +** is given ownership of the palette, then it owns the palette until +** it is UIDeactivated. +** b) If the container wants to own the palette it should NOT send +** WM_QUERYNEWPALETTE to the UIActive object. +** +** Rule 2: Whether the container wants to own the palette or not, it +** should forward the WM_PALETTECHANGED to the immediate child +** inplace active objects in its documents. if it is an inside-out +** style container then it must forward it to ALL objects that +** currently have their windows visible. When the object recives the +** WM_PALETTECHANGED message it must select its color palette as the +** background palette. When the objects are in loaded state they will be +** drawn by (OLE) by selecting their palettes as background palettes +** anyway. +** +** Note: IOleObject::SetColorScheme is not related to the palette +** issue. +*/ +void ContainerDoc_ForwardPaletteChangedMsg( + LPCONTAINERDOC lpContainerDoc, + HWND hwndPalChg +) +{ + LPLINELIST lpLL; + int i; + LPLINE lpLine; + + if (!lpContainerDoc) + return; + + lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList; + if (g_fInsideOutContainer) { + + if (lpContainerDoc->m_cIPActiveObjects) { + for (i = 0; i < lpLL->m_nNumLines; i++) { + lpLine=LineList_GetLine(lpLL, i); + + if (lpLine && (Line_GetLineType(lpLine)==CONTAINERLINETYPE)) { + LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)lpLine; + ContainerLine_ForwardPaletteChangedMsg( + lpContainerLine, hwndPalChg); + } + } + } + } + else { + /* OLE2NOTE: (OUTSIDE-IN CONTAINER) if there is a currently + ** UIActive object (ie. its window is visible), we must + ** forward it the WM_PALETTECHANGED message. + */ + LPCONTAINERLINE lpLastUIActiveLine = + lpContainerDoc->m_lpLastUIActiveLine; + if (lpLastUIActiveLine && lpLastUIActiveLine->m_fUIActive) { + ContainerLine_ForwardPaletteChangedMsg( + lpLastUIActiveLine, hwndPalChg); + } + } +} + + +/************************************************************************* +** ContainerLine Support Functions and Interfaces +*************************************************************************/ + + +/* ContainerLine_UIDeactivate +** -------------------------- +** tell the OLE object associated with the ContainerLine to +** UIDeactivate. this informs the in-place server to tear down +** the UI and window that it put up for the object. it will remove +** its active editor menus and any frame and object adornments +** (eg. toolbars, rulers, etc.). +*/ +void ContainerLine_UIDeactivate(LPCONTAINERLINE lpContainerLine) +{ + HRESULT hrErr; + + if (!lpContainerLine || !lpContainerLine->m_fUIActive) + return; + + OLEDBG_BEGIN2("IOleInPlaceObject::UIDeactivate called\r\n") + hrErr = lpContainerLine->m_lpOleIPObj->lpVtbl->UIDeactivate( + lpContainerLine->m_lpOleIPObj); + OLEDBG_END2 + + if (hrErr != NOERROR) { + OleDbgOutHResult("IOleInPlaceObject::UIDeactivate returned", hrErr); + return; + } +} + + + +/* ContainerLine_UpdateInPlaceObjectRects +** ------------------------------------- +** Update the PosRect and ClipRect of the given line +** currently in-place active +** object. if there is no object active in-place, then do nothing. +** +** OLE2NOTE: this function should be called when an action occurs +** that changes either the position of the object in the document +** (eg. changing document margins changes PosRect) or the clipRect +** changes (eg. resizing the document window changes the ClipRect). +*/ +void ContainerLine_UpdateInPlaceObjectRects( + LPCONTAINERLINE lpContainerLine, + LPRECT lprcClipRect +) +{ + LPCONTAINERDOC lpContainerDoc = lpContainerLine->m_lpDoc; + RECT rcClipRect; + RECT rcPosRect; + + + if (! lpContainerLine->m_fIpVisible) + return; + + if (! lprcClipRect) { + ContainerDoc_GetClipRect(lpContainerDoc, (LPRECT)&rcClipRect); + lprcClipRect = (LPRECT)&rcClipRect; + } + +#if defined( _DEBUG ) + OleDbgOutRect3( + "ContainerLine_UpdateInPlaceObjectRects (ClipRect)", + (LPRECT)&rcClipRect + ); +#endif + ContainerLine_GetPosRect(lpContainerLine,(LPRECT)&rcPosRect); + +#if defined( _DEBUG ) + OleDbgOutRect3( + "ContainerLine_UpdateInPlaceObjectRects (PosRect)",(LPRECT)&rcPosRect); +#endif + + OLEDBG_BEGIN2("IOleInPlaceObject::SetObjectRects called\r\n") + lpContainerLine->m_lpOleIPObj->lpVtbl->SetObjectRects( + lpContainerLine->m_lpOleIPObj, + (LPRECT)&rcPosRect, + lprcClipRect + ); + OLEDBG_END2 +} + + +/* ContainerLine_ContextSensitveHelp +** --------------------------------- +** forward the ContextSensitiveHelp mode on to the in-place object +** if it currently has its window visible. this informs the +** object whether to give help or take action on subsequent mouse +** clicks and menu commands. +** +** this function is called from ContainerDoc_ContextSensitiveHelp +** function as a result of a call to +** IOleInPlaceSite::ContextSensitiveHelp if the in-place container +** is operating as an in-side out container. +*/ +void ContainerLine_ContextSensitiveHelp( + LPCONTAINERLINE lpContainerLine, + BOOL fEnterMode +) +{ + if (! lpContainerLine->m_fIpVisible) + return; + + OLEDBG_BEGIN2("IOleInPlaceObject::ContextSensitiveHelp called\r\n") + lpContainerLine->m_lpOleIPObj->lpVtbl->ContextSensitiveHelp( + lpContainerLine->m_lpOleIPObj, fEnterMode); + OLEDBG_END2 +} + + +/* ContainerLine_ForwardPaletteChangedMsg +** -------------------------------------- +** forward it the WM_PALETTECHANGED message (via SendMessage) to the +** in-place object if it currently has its window visible. this +** gives the object the chance to select its palette as a BACKGROUND +** palette if it doesn't own the palette--or as the +** foreground palette if it currently DOES own the palette. +** +** SEE THE TECHNOTE FOR DETAILED INFORMATION ON PALETTE COORDINATION +*/ +void ContainerLine_ForwardPaletteChangedMsg( + LPCONTAINERLINE lpContainerLine, + HWND hwndPalChg +) +{ + if (! lpContainerLine->m_fIpVisible) + return; + + OleDbgAssert(lpContainerLine->m_hWndIpObject); + SendMessage( + lpContainerLine->m_hWndIpObject, + WM_PALETTECHANGED, + (WPARAM)hwndPalChg, + 0L + ); +} + + + +/************************************************************************* +** ContainerLine::IOleInPlaceSite interface implementation +*************************************************************************/ + +STDMETHODIMP CntrLine_IPSite_QueryInterface( + LPOLEINPLACESITE lpThis, + REFIID riid, + LPVOID FAR* lplpvObj +) +{ + LPCONTAINERLINE lpContainerLine = + ((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine; + + return ContainerLine_QueryInterface(lpContainerLine, riid, lplpvObj); +} + + +STDMETHODIMP_(ULONG) CntrLine_IPSite_AddRef(LPOLEINPLACESITE lpThis) +{ + LPCONTAINERLINE lpContainerLine = + ((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine; + + OleDbgAddRefMethod(lpThis, "IOleInPlaceSite"); + + return ContainerLine_AddRef(lpContainerLine); +} + + +STDMETHODIMP_(ULONG) CntrLine_IPSite_Release(LPOLEINPLACESITE lpThis) +{ + LPCONTAINERLINE lpContainerLine = + ((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine; + + OleDbgReleaseMethod(lpThis, "IOleInPlaceSite"); + + return ContainerLine_Release(lpContainerLine); +} + + +STDMETHODIMP CntrLine_IPSite_GetWindow( + LPOLEINPLACESITE lpThis, + HWND FAR* lphwnd +) +{ + LPCONTAINERLINE lpContainerLine = + ((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine; + OleDbgOut2("CntrLine_IPSite_GetWindow\r\n"); + + *lphwnd = LineList_GetWindow( + &((LPOUTLINEDOC)lpContainerLine->m_lpDoc)->m_LineList); + return NOERROR; +} + +// IOleInPlaceSite::ContextSensitiveHelp +STDMETHODIMP CntrLine_IPSite_ContextSensitiveHelp( + LPOLEINPLACESITE lpThis, + BOOL fEnterMode +) +{ + LPCONTAINERLINE lpContainerLine = + ((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine; + LPOLEDOC lpOleDoc = (LPOLEDOC)lpContainerLine->m_lpDoc; + OleDbgOut2("CntrLine_IPSite_ContextSensitiveHelp\r\n"); + + /* OLE2NOTE: see context sensitive help technote (CSHELP.DOC). + ** This method is called when SHIFT-F1 context sensitive help is + ** entered. the cursor should then change to a question mark + ** cursor and the app should enter a modal state where the next + ** mouse click does not perform its normal action but rather + ** gives help corresponding to the location clicked. if the app + ** does not implement a help system, it should at least eat the + ** click and do nothing. + ** + ** NOTE: the implementation here is specific to an SDI simple + ** container. an MDI container or container/server application + ** would have additional work to do (see the technote). + ** + ** NOTE: (INSIDE-OUT CONTAINER) if there are currently + ** any in-place objects active with their windows visible + ** (ie. fIpVisible), we must forward the + ** ContextSensitiveHelp mode on to these objects. + */ + ContainerDoc_ContextSensitiveHelp( + lpContainerLine->m_lpDoc,fEnterMode,TRUE /*InitiatedByObj*/); + + return NOERROR; +} + + +STDMETHODIMP CntrLine_IPSite_CanInPlaceActivate(LPOLEINPLACESITE lpThis) +{ + LPCONTAINERLINE lpContainerLine = + ((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine; + OleDbgOut2("CntrLine_IPSite_CanInPlaceActivate\r\n"); + + /* OLE2NOTE: the container can NOT allow in-place activation if it + ** is currently displaying the object as an ICON + ** (DVASPECT_ICON). it can ONLY do in-place activation if it is + ** displaying the DVASPECT_CONTENT of the OLE object. + */ + if (lpContainerLine->m_dwDrawAspect == DVASPECT_CONTENT) + return NOERROR; + else + return ResultFromScode(S_FALSE); +} + +STDMETHODIMP CntrLine_IPSite_OnInPlaceActivate(LPOLEINPLACESITE lpThis) +{ + LPCONTAINERLINE lpContainerLine = + ((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine; + LPCONTAINERDOC lpContainerDoc = lpContainerLine->m_lpDoc; + SCODE sc = S_OK; + + OLEDBG_BEGIN2("CntrLine_IPSite_OnInPlaceActivate\r\n"); + + /* OLE2NOTE: (OUTSIDE-IN CONTAINER) as a policy for managing + ** running in-place servers, we will keep only 1 inplace server + ** active at any given time. so when we start to inp-place activate + ** another line, then we want to shut down the previously + ** activated server. in this way we keep at most one inplace + ** server active at a time. this is NOT a required policy. apps + ** may choose to have a more sophisticated strategy. inside-out + ** containers will HAVE to have a more sophisticated strategy, + ** because they need (at a minimum) to keep all visible object + ** servers running. + ** + ** if the in-place activation is the result of activating a + ** linked object in another container, then we may arrive at + ** this method while another object is currently active. + ** normally, if the object is in-place activated by + ** double-clicking or Edit. from our own container, then + ** the previous in-place object would have been de-activated in + ** ContainerLine_DoVerb method. + */ + if (!g_fInsideOutContainer) { + if (lpContainerDoc->m_lpLastIpActiveLine) { + ContainerDoc_ShutDownLastInPlaceServerIfNotNeeded( + lpContainerDoc, lpContainerLine); + } + lpContainerDoc->m_lpLastIpActiveLine = lpContainerLine; + } + + /* OLE2NOTE: to avoid LRPC problems it is important to cache the + ** IOleInPlaceObject* pointer and NOT to call QueryInterface + ** each time it is needed. + */ + lpContainerLine->m_lpOleIPObj = (LPOLEINPLACEOBJECT) + ContainerLine_GetOleObject(lpContainerLine,&IID_IOleInPlaceObject); + + if (! lpContainerLine->m_lpOleIPObj) { +#if defined( _DEBUG ) + OleDbgAssertSz( + lpContainerLine->m_lpOleIPObj!=NULL, + "OLE object must support IOleInPlaceObject" + ); +#endif + return ResultFromScode(E_FAIL); // ERROR: refuse to in-place activate + } + + lpContainerLine->m_fIpActive = TRUE; + lpContainerLine->m_fIpVisible = TRUE; + + OLEDBG_BEGIN2("IOleInPlaceObject::GetWindow called\r\n") + lpContainerLine->m_lpOleIPObj->lpVtbl->GetWindow( + lpContainerLine->m_lpOleIPObj, + (HWND FAR*)&lpContainerLine->m_hWndIpObject + ); + OLEDBG_END2 + + if (! lpContainerLine->m_fIpServerRunning) { + /* OLE2NOTE: it is VERY important that an in-place container + ** that also support linking to embeddings properly manage + ** the running of its in-place objects. in an outside-in + ** style in-place container, when the user clicks + ** outside of the in-place active object, the object gets + ** UIDeactivated and the object hides its window. in order + ** to make the object fast to reactivate, the container + ** deliberately does not call IOleObject::Close. the object + ** stays running in the invisible unlocked state. the idea + ** here is if the user simply clicks outside of the object + ** and then wants to double click again to re-activate the + ** object, we do not want this to be slow. if we want to + ** keep the object running, however, we MUST Lock it + ** running. otherwise the object will be in an unstable + ** state where if a linking client does a "silent-update" + ** (eg. UpdateNow from the Links dialog), then the in-place + ** server will shut down even before the object has a chance + ** to be saved back in its container. this saving normally + ** occurs when the in-place container closes the object. also + ** keeping the object in the unstable, hidden, running, + ** not-locked state can cause problems in some scenarios. + ** ICntrOtl keeps only one object running. if the user + ** intiates a DoVerb on another object, then that last + ** running in-place active object is closed. a more + ** sophistocated in-place container may keep more object running. + ** this lock gets unlocked in ContainerLine_CloseOleObject. + */ + lpContainerLine->m_fIpServerRunning = TRUE; + + OLEDBG_BEGIN2("OleLockRunning(TRUE, 0) called\r\n") + OleLockRunning((LPUNKNOWN)lpContainerLine->m_lpOleIPObj, TRUE, 0); + OLEDBG_END2 + } + + lpContainerLine->m_lpDoc->m_cIPActiveObjects++; + + OLEDBG_END2 + return NOERROR; +} + + +STDMETHODIMP CntrLine_IPSite_OnUIActivate (LPOLEINPLACESITE lpThis) +{ + LPCONTAINERLINE lpContainerLine = + ((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine; + LPCONTAINERDOC lpContainerDoc = lpContainerLine->m_lpDoc; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerLine->m_lpDoc; + LPCONTAINERLINE lpLastUIActiveLine = lpContainerDoc->m_lpLastUIActiveLine; + + OLEDBG_BEGIN2("CntrLine_IPSite_OnUIActivate\r\n"); + + lpContainerLine->m_fUIActive = TRUE; + lpContainerDoc->m_fAddMyUI = FALSE; + lpContainerDoc->m_lpLastUIActiveLine = lpContainerLine; + + if (g_fInsideOutContainer) { + /* OLE2NOTE: (INSIDE-OUT CONTAINER) an inside-out style + ** container must UIDeactivate the previous UIActive object + ** when a new object is going UIActive. since the inside-out + ** objects have their own windows visible, it is possible + ** that a click directly in an another server window will + ** cause it to UIActivate. OnUIActivate is the containers + ** notification that such has occured. it must then + ** UIDeactivate the other because at most one object can be + ** UIActive at a time. + */ + if (lpLastUIActiveLine && (lpLastUIActiveLine!=lpContainerLine)) { + ContainerLine_UIDeactivate(lpLastUIActiveLine); + + // Make sure new UIActive window is on top of all others + SetWindowPos( + lpContainerLine->m_hWndIpObject, + HWND_TOPMOST, + 0,0,0,0, + SWP_NOMOVE | SWP_NOSIZE + ); + + OLEDBG_END2 + return NOERROR; + } + } + + lpContainerDoc->m_hWndUIActiveObj = lpContainerLine->m_hWndIpObject; + +#if defined( USE_FRAMETOOLS ) + ContainerDoc_RemoveFrameLevelTools(lpContainerDoc); +#endif + +#if defined( USE_DOCTOOLS ) + ContainerDoc_RemoveDocLevelTools(lpContainerDoc); +#endif + + OLEDBG_END2 + return NOERROR; +} + + +STDMETHODIMP CntrLine_IPSite_GetWindowContext( + LPOLEINPLACESITE lpThis, + LPOLEINPLACEFRAME FAR* lplpFrame, + LPOLEINPLACEUIWINDOW FAR* lplpDoc, + LPRECT lprcPosRect, + LPRECT lprcClipRect, + LPOLEINPLACEFRAMEINFO lpFrameInfo +) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp; + LPCONTAINERLINE lpContainerLine = + ((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine; + + OLEDBG_BEGIN2("CntrLine_IPSite_GetWindowContext\r\n") + + /* OLE2NOTE: The server should fill in the "cb" field so that the + ** container can tell what size structure the server is + ** expecting. this enables this structure to be easily extended + ** in future releases of OLE. the container should check this + ** field so that it doesn't try to use fields that do not exist + ** since the server may be using an old structure definition. + ** Since this is the first release of OLE2.0, the structure is + ** guaranteed to be at least large enough for the current + ** definition of OLEINPLACEFRAMEINFO struct. thus we do NOT need + ** to consider this an error if the server did not fill in this + ** field correctly. this server may have trouble in the future, + ** however, when the structure is extended. + */ + *lplpFrame = (LPOLEINPLACEFRAME)&lpContainerApp->m_OleInPlaceFrame; + (*lplpFrame)->lpVtbl->AddRef(*lplpFrame); // must return AddRef'ed ptr + + // OLE2NOTE: an MDI app would have to provide *lplpDoc + *lplpDoc = NULL; + + ContainerLine_GetPosRect(lpContainerLine, lprcPosRect); + ContainerDoc_GetClipRect(lpContainerLine->m_lpDoc, lprcClipRect); + + OleDbgOutRect3("CntrLine_IPSite_GetWindowContext (PosRect)", lprcPosRect); + OleDbgOutRect3("CntrLine_IPSite_GetWindowContext (ClipRect)",lprcClipRect); + lpFrameInfo->hwndFrame = lpOutlineApp->m_hWndApp; + +#if defined( MDI_VERSION ) + lpFrameInfo->fMDIApp = TRUE; +#else + lpFrameInfo->fMDIApp = FALSE; +#endif + + lpFrameInfo->haccel = lpContainerApp->m_hAccelIPCntr; + lpFrameInfo->cAccelEntries = + GetAccelItemCount(lpContainerApp->m_hAccelIPCntr); + + OLEDBG_END2 + return NOERROR; +} + + +STDMETHODIMP CntrLine_IPSite_Scroll( + LPOLEINPLACESITE lpThis, + SIZE scrollExtent +) +{ + OleDbgOut2("CntrLine_IPSite_Scroll\r\n"); + return ResultFromScode(E_FAIL); +} + + +STDMETHODIMP CntrLine_IPSite_OnUIDeactivate( + LPOLEINPLACESITE lpThis, + BOOL fUndoable +) +{ + LPCONTAINERLINE lpContainerLine = + ((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerLine->m_lpDoc; + LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP) g_lpApp; + LPLINELIST lpLL; + int nIndex; + MSG msg; + HRESULT hrErr; + OLEDBG_BEGIN2("CntrLine_IPSite_OnUIDeactivate\r\n") + + lpContainerLine->m_fUIActive = FALSE; + lpContainerLine->m_fIpChangesUndoable = fUndoable; + lpContainerLine->m_lpDoc->m_hWndUIActiveObj = NULL; + + if (lpContainerLine == lpContainerLine->m_lpDoc->m_lpLastUIActiveLine) { + + lpContainerLine->m_lpDoc->m_lpLastUIActiveLine = NULL; + + /* OLE2NOTE: here we look ahead if there is a DBLCLK sitting in our + ** message queue. if so, it could result in in-place activating + ** another object. we want to avoid placing our tools and + ** repainting if immediately another object is going to do the + ** same. SO, if there is a DBLCLK in the queue for this document + ** we will only set the fAddMyUI flag to indicate that this work + ** is still to be done. if another object actually in-place + ** activates then this flag will be cleared in + ** IOleInPlaceSite::OnUIActivate. if it does NOT get cleared, + ** then at the end of processing the DBLCLK message in our + ** OutlineDocWndProc we will put our tools back. + */ + if (! PeekMessage(&msg, lpOutlineDoc->m_hWndDoc, + WM_LBUTTONDBLCLK, WM_LBUTTONDBLCLK, + PM_NOREMOVE | PM_NOYIELD)) { + + /* OLE2NOTE: You need to generate QueryNewPalette only if + ** you own the top level frame (ie. you are a top-level + ** inplace container). + */ + + OleApp_QueryNewPalette((LPOLEAPP)g_lpApp); + +#if defined( USE_DOCTOOLS ) + ContainerDoc_AddDocLevelTools(lpContainerLine->m_lpDoc); +#endif + +#if defined( USE_FRAMETOOLS ) + ContainerDoc_AddFrameLevelUI(lpContainerLine->m_lpDoc); +#endif + } else { + lpContainerLine->m_lpDoc->m_fAddMyUI = TRUE; + } + + /* OLE2NOTE: we should re-take focus. the in-place server window + ** previously had the focus; this window has just been removed. + */ + SetFocus(OutlineDoc_GetWindow((LPOUTLINEDOC)lpContainerLine->m_lpDoc)); + + // force the line to redraw to remove in-place active hatch + lpLL = OutlineDoc_GetLineList(lpOutlineDoc); + nIndex = LineList_GetLineIndex(lpLL, (LPLINE)lpContainerLine); + LineList_ForceLineRedraw(lpLL, nIndex, TRUE); + } + +#if defined( UNDOSUPPORTED ) + + /* OLE2NOTE: an outside-in style container that supports UNDO would + ** call IOleObject::DoVerb(OLEIVERB_HIDE) to make the in-place + ** object go invisible. when it wants the in-place active object + ** to discard its undo state, it would call + ** IOleInPlaceObject::InPlaceDeactivate when it wants the object + ** to discard its undo state. there is no need for an outside-in + ** style container to call + ** IOleObject::DoVerb(OLEIVERB_DISCARDUNDOSTATE). if either the + ** container or the object do not support UNDO, then the + ** container might as well immediately call InPlaceDeactivate + ** instead of calling DoVerb(HIDE). + ** + ** an inside-out style container that supports UNDO would simply + ** UIDeactivate the object. it would call + ** IOleObject::DoVerb(OLEIVERB_DISCARDUNDOSTATE) when it wants + ** the object discard its undo state. it would call + ** IOleInPlaceObject::InPlaceDeactivate if it wants the object + ** to take down its window. + */ + if (! g_fInsideOutContainer || !lpContainerLine->m_fInsideOutObj) { + + if (lpContainerLine->m_fIpChangesUndoable) { + ContainerLine_DoVerb( + lpContainerLine,OLEIVERB_HIDE,NULL,FALSE,FALSE); + } else { + lpContainerLine->m_lpOleIPObj->lpVtbl->InPlaceDeactivate( + lpContainerLine->m_lpOleIPObj); + } + lpContainerLine->m_fIpVisible = FALSE; + lpContainerLine->m_hWndIpObject = NULL; + } +#else + + /* OLE2NOTE: an outside-in style container that does NOT support + ** UNDO would immediately tell the UIDeactivated server (UI + ** removed) to IOleInPlaceObject::InPlaceDeactivate. + ** + ** an inside-out style container that does NOT support UNDO + ** would call IOleObject::DoVerb(OLEIVERB_DISCARDUNDOSTATE) to + ** tell the object to discard its undo state. it would call + ** IOleInPlaceObject::InPlaceDeactivate if it wants the object + ** to take down its window. + */ + + if (g_fInsideOutContainer) { + + if (lpContainerLine->m_fInsideOutObj) { + + if (lpContainerLine->m_fIpChangesUndoable) { + OLEDBG_BEGIN3("ContainerLine_DoVerb(OLEIVERB_DISCARDUNDOSTATE) called!\r\n") + ContainerLine_DoVerb(lpContainerLine, + OLEIVERB_DISCARDUNDOSTATE,NULL,FALSE,FALSE); + OLEDBG_END3 + } + + } else { // !fInsideOutObj + + /* OLE2NOTE: (INSIDEOUT CONTAINER) if the object is not + ** registered OLEMISC_ACTIVATEWHENVISIBLE, then we will + ** make the object behave in an outside-in manner. since + ** we do NOT deal with UNDO we can simply + ** InPlaceDeactivate the object. it should NOT be + ** allowed to leave its window visible when + ** UIDeactivated. + */ + OLEDBG_BEGIN2("IOleInPlaceObject::InPlaceDeactivate called\r\n") + hrErr = lpContainerLine->m_lpOleIPObj->lpVtbl->InPlaceDeactivate( + lpContainerLine->m_lpOleIPObj); + OLEDBG_END2 + if (hrErr != NOERROR) { + OleDbgOutHResult("IOleInPlaceObject::InPlaceDeactivate returned", hrErr); + } + } + + } else { + + /* OLE2NOTE: (OUTSIDE-IN CONTAINER) since we do NOT deal with + ** UNDO we can simply InPlaceDeactivate the object. it + ** should NOT be allowed to leave its window visible when + ** UIDeactivated. + ** + ** NOTE: In-place servers must handle InPlaceDeactivate + ** being called before its call to + ** IOleInPlaceSite::OnUIDeactivate returns. in case there + ** are misbehaving servers out there, one way to work around + ** this problem is to call + ** IOleObject::DoVerb(OLEIVERB_HIDE...) here. + */ + OLEDBG_BEGIN2("IOleInPlaceObject::InPlaceDeactivate called\r\n") + hrErr = lpContainerLine->m_lpOleIPObj->lpVtbl->InPlaceDeactivate( + lpContainerLine->m_lpOleIPObj); + OLEDBG_END2 + if (hrErr != NOERROR) { + OleDbgOutHResult("IOleInPlaceObject::InPlaceDeactivate returned", hrErr); + } + } + +#endif // ! UNDOSUPPORTED + + OLEDBG_END2 + return NOERROR; +} + + +STDMETHODIMP CntrLine_IPSite_OnInPlaceDeactivate(LPOLEINPLACESITE lpThis) +{ + LPCONTAINERLINE lpContainerLine = + ((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine; + + OLEDBG_BEGIN2("CntrLine_IPSite_OnInPlaceDeactivate\r\n"); + + lpContainerLine->m_fIpActive = FALSE; + lpContainerLine->m_fIpVisible = FALSE; + lpContainerLine->m_fIpChangesUndoable = FALSE; + lpContainerLine->m_hWndIpObject = NULL; + + OleStdRelease((LPUNKNOWN) lpContainerLine->m_lpOleIPObj); + lpContainerLine->m_lpOleIPObj = NULL; + lpContainerLine->m_lpDoc->m_cIPActiveObjects--; + + OLEDBG_END2 + return NOERROR; +} + + +STDMETHODIMP CntrLine_IPSite_DiscardUndoState(LPOLEINPLACESITE lpThis) +{ + OleDbgOut2("CntrLine_IPSite_DiscardUndoState\r\n"); + return NOERROR; +} + + +STDMETHODIMP CntrLine_IPSite_DeactivateAndUndo(LPOLEINPLACESITE lpThis) +{ + OleDbgOut2("CntrLine_IPSite_DeactivateAndUndo\r\n"); + return NOERROR; +} + + +STDMETHODIMP CntrLine_IPSite_OnPosRectChange( + LPOLEINPLACESITE lpThis, + LPCRECT lprcPosRect +) +{ + LPCONTAINERLINE lpContainerLine = + ((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerLine->m_lpDoc; + LPSCALEFACTOR lpscale = OutlineDoc_GetScaleFactor(lpOutlineDoc); + LPLINE lpLine = (LPLINE)lpContainerLine; + LPLINELIST lpLL; + int nIndex; + RECT rcClipRect; + RECT rcNewPosRect; + SIZEL sizelPix; + SIZEL sizelHim; + int nIPObjHeight = lprcPosRect->bottom - lprcPosRect->top; + int nIPObjWidth = lprcPosRect->right - lprcPosRect->left; + OLEDBG_BEGIN2("CntrLine_IPSite_OnPosRectChange\r\n") + OleDbgOutRect3("CntrLine_IPSite_OnPosRectChange (PosRect --IN)", (LPRECT)lprcPosRect); + + /* OLE2NOTE: if the in-place container does NOT impose any + ** size contraints on its in-place active objects, then it may + ** simply grant the size requested by the object by immediately + ** calling IOleInPlaceObject::SetObjectRects with the + ** lprcPosRect passed by the in-place object. + ** + ** Container Outline, however, imposes a size constraint on its + ** embedded objects (see comment in ContainerLine_UpdateExtent), + ** thus it is necessary to calculate the size that the in-place + ** active object is allowed to be. + ** + ** Here we need to know the new extents of the in-place object. + ** We can NOT directly ask the object via IOleObject::GetExtent + ** because this method will retreive the extents of the last + ** cached metafile. the cache has not yet been updated by this + ** point. We can not reliably call IOleObject::GetExtent + ** because, despite the fact that will be delegated to the + ** object properly, some objects may not have reformated their + ** object and computed the new extents at the time of calling + ** OnPosRectChange. + ** + ** the best we can do to get the new extents of the object is + ** to determine the scale factor that the object was operating at + ** prior to the OnPosRect call and scale the new lprcPosRect + ** using this scale factor back to HIMETRIC units. + */ + if (lpContainerLine->m_sizeInHimetric.cx > 0 && + lpContainerLine->m_sizeInHimetric.cy > 0) { + sizelHim.cx = lpLine->m_nWidthInHimetric; + sizelHim.cy = lpLine->m_nHeightInHimetric; + XformSizeInHimetricToPixels(NULL, &sizelHim, &sizelPix); + sizelHim.cx = lpContainerLine->m_sizeInHimetric.cx * + nIPObjWidth / sizelPix.cx; + sizelHim.cy = lpContainerLine->m_sizeInHimetric.cy * + nIPObjHeight / sizelPix.cy; + + // Convert size back to 100% zoom + sizelHim.cx = sizelHim.cx * lpscale->dwSxD / lpscale->dwSxN; + sizelHim.cy = sizelHim.cy * lpscale->dwSyD / lpscale->dwSyN; + } else { + sizelHim.cx = (long)DEFOBJWIDTH; + sizelHim.cy = (long)DEFOBJHEIGHT; + XformSizeInHimetricToPixels(NULL, &sizelHim, &sizelPix); + sizelHim.cx = sizelHim.cx * nIPObjWidth / sizelPix.cx; + sizelHim.cy = sizelHim.cy * nIPObjHeight / sizelPix.cy; + } + + ContainerLine_UpdateExtent(lpContainerLine, &sizelHim); + ContainerLine_GetPosRect(lpContainerLine, (LPRECT)&rcNewPosRect); + ContainerDoc_GetClipRect(lpContainerLine->m_lpDoc, (LPRECT)&rcClipRect); + +#if defined( _DEBUG ) + OleDbgOutRect3("CntrLine_IPSite_OnPosRectChange (PosRect --OUT)", + (LPRECT)&rcNewPosRect); + OleDbgOutRect3("CntrLine_IPSite_OnPosRectChange (ClipRect--OUT)", + (LPRECT)&rcClipRect); +#endif + OLEDBG_BEGIN2("IOleInPlaceObject::SetObjectRects called\r\n") + lpContainerLine->m_lpOleIPObj->lpVtbl->SetObjectRects( + lpContainerLine->m_lpOleIPObj, + (LPRECT)&rcNewPosRect, + (LPRECT)&rcClipRect + ); + OLEDBG_END2 + + /* OLE2NOTE: (INSIDEOUT CONTAINER) Because this object just changed + ** size, this may cause other in-place active objects in the + ** document to move. in ICNTROTL's case any object below this + ** object would be affected. in this case it would be necessary + ** to call SetObjectRects to each affected in-place active object. + */ + if (g_fInsideOutContainer) { + lpLL = OutlineDoc_GetLineList(lpOutlineDoc); + nIndex = LineList_GetLineIndex(lpLL, (LPLINE)lpContainerLine); + + ContainerDoc_UpdateInPlaceObjectRects( + lpContainerLine->m_lpDoc, nIndex); + } + OLEDBG_END2 + return NOERROR; +} diff --git a/private/oleutest/letest/outline/cntrline.c b/private/oleutest/letest/outline/cntrline.c new file mode 100644 index 000000000..881925210 --- /dev/null +++ b/private/oleutest/letest/outline/cntrline.c @@ -0,0 +1,3540 @@ +/************************************************************************* +** +** OLE 2 Container Sample Code +** +** cntrline.c +** +** This file contains ContainerLine methods. +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + +#include "outline.h" + +OLEDBGDATA + + + +extern LPOUTLINEAPP g_lpApp; +extern IUnknownVtbl g_CntrLine_UnknownVtbl; +extern IOleClientSiteVtbl g_CntrLine_OleClientSiteVtbl; +extern IAdviseSinkVtbl g_CntrLine_AdviseSinkVtbl; + +#if defined( INPLACE_CNTR ) +extern IOleInPlaceSiteVtbl g_CntrLine_OleInPlaceSiteVtbl; +extern BOOL g_fInsideOutContainer; +#endif // INPLACE_CNTR + +// REVIEW: should use string resource for messages +char ErrMsgDoVerb[] = "OLE object action failed!"; + + +/* prototype for static functions */ +static void InvertDiffRect(LPRECT lprcPix, LPRECT lprcObj, HDC hDC); + + +/************************************************************************* +** ContainerLine +** This object represents the location within the container where +** the embedded/linked object lives. It exposes interfaces to the +** object that allow the object to get information about its +** embedding site and to announce notifications of important events +** (changed, closed, saved) +** +** The ContainerLine exposes the following interfaces: +** IUnknown +** IOleClientSite +** IAdviseSink +*************************************************************************/ + + + +/************************************************************************* +** ContainerLine::IUnknown interface implementation +*************************************************************************/ + + +// IUnknown::QueryInterface +STDMETHODIMP CntrLine_Unk_QueryInterface( + LPUNKNOWN lpThis, + REFIID riid, + LPVOID FAR* lplpvObj +) +{ + LPCONTAINERLINE lpContainerLine = + ((struct COleClientSiteImpl FAR*)lpThis)->lpContainerLine; + + return ContainerLine_QueryInterface(lpContainerLine, riid, lplpvObj); +} + + +// IUnknown::AddRef +STDMETHODIMP_(ULONG) CntrLine_Unk_AddRef(LPUNKNOWN lpThis) +{ + LPCONTAINERLINE lpContainerLine = + ((struct COleClientSiteImpl FAR*)lpThis)->lpContainerLine; + + OleDbgAddRefMethod(lpThis, "IUnknown"); + + return ContainerLine_AddRef(lpContainerLine); +} + + +// IUnknown::Release +STDMETHODIMP_(ULONG) CntrLine_Unk_Release(LPUNKNOWN lpThis) +{ + LPCONTAINERLINE lpContainerLine = + ((struct COleClientSiteImpl FAR*)lpThis)->lpContainerLine; + + OleDbgReleaseMethod(lpThis, "IUnknown"); + + return ContainerLine_Release(lpContainerLine); +} + + +/************************************************************************* +** ContainerLine::IOleClientSite interface implementation +*************************************************************************/ + +// IOleClientSite::QueryInterface +STDMETHODIMP CntrLine_CliSite_QueryInterface( + LPOLECLIENTSITE lpThis, + REFIID riid, + LPVOID FAR* lplpvObj +) +{ + LPCONTAINERLINE lpContainerLine = + ((struct COleClientSiteImpl FAR*)lpThis)->lpContainerLine; + + return ContainerLine_QueryInterface(lpContainerLine, riid, lplpvObj); +} + + +// IOleClientSite::AddRef +STDMETHODIMP_(ULONG) CntrLine_CliSite_AddRef(LPOLECLIENTSITE lpThis) +{ + LPCONTAINERLINE lpContainerLine = + ((struct COleClientSiteImpl FAR*)lpThis)->lpContainerLine; + + OleDbgAddRefMethod(lpThis, "IOleClientSite"); + + return ContainerLine_AddRef(lpContainerLine); +} + + +// IOleClientSite::Release +STDMETHODIMP_(ULONG) CntrLine_CliSite_Release(LPOLECLIENTSITE lpThis) +{ + LPCONTAINERLINE lpContainerLine = + ((struct COleClientSiteImpl FAR*)lpThis)->lpContainerLine; + + OleDbgReleaseMethod(lpThis, "IOleClientSite"); + + return ContainerLine_Release(lpContainerLine); +} + + +// IOleClientSite::SaveObject +STDMETHODIMP CntrLine_CliSite_SaveObject(LPOLECLIENTSITE lpThis) +{ + LPCONTAINERLINE lpContainerLine = + ((struct COleClientSiteImpl FAR*)lpThis)->lpContainerLine; + LPPERSISTSTORAGE lpPersistStg = lpContainerLine->m_lpPersistStg; + SCODE sc = S_OK; + HRESULT hrErr; + + OLEDBG_BEGIN2("CntrLine_CliSite_SaveObject\r\n") + + if (! lpPersistStg) { + /* OLE2NOTE: The object is NOT loaded. a container must be + ** prepared for the fact that an object that it thinks it + ** has unloaded may still call IOleClientSite::SaveObject. + ** in this case the container should fail the save call and + ** NOT try to reload the object. this scenario arises if you + ** have a in-process server (DLL object) which has a + ** connected linking client. even after the embedding + ** container unloads the DLL object, the link connection + ** keeps the object alive. it may then as part of its + ** shutdown try to call IOCS::SaveObject, but then it is too + ** late. + */ + OLEDBG_END2 + return ResultFromScode(E_FAIL); + } + + // mark ContainerDoc as now dirty + OutlineDoc_SetModified( + (LPOUTLINEDOC)lpContainerLine->m_lpDoc, TRUE, TRUE, FALSE); + + /* Tell OLE object to save itself + ** OLE2NOTE: it is NOT sufficient to ONLY call + ** IPersistStorage::Save method. it is also necessary to call + ** WriteClassStg. the helper API OleSave does this automatically. + */ + OLEDBG_BEGIN2("OleSave called\r\n") + hrErr=OleSave(lpPersistStg,lpContainerLine->m_lpStg, TRUE/*fSameAsLoad*/); + OLEDBG_END2 + + if (hrErr != NOERROR) { + OleDbgOutHResult("WARNING: OleSave returned", hrErr); + sc = GetScode(hrErr); + } + + // OLE2NOTE: even if OleSave fails, SaveCompleted must be called. + OLEDBG_BEGIN2("IPersistStorage::SaveCompleted called\r\n") + hrErr = lpPersistStg->lpVtbl->SaveCompleted(lpPersistStg, NULL); + OLEDBG_END2 + + if (hrErr != NOERROR) { + OleDbgOutHResult("WARNING: SaveCompleted returned",hrErr); + if (sc == S_OK) + sc = GetScode(hrErr); + } + + OLEDBG_END2 + return ResultFromScode(sc); +} + + +// IOleClientSite::GetMoniker +STDMETHODIMP CntrLine_CliSite_GetMoniker( + LPOLECLIENTSITE lpThis, + DWORD dwAssign, + DWORD dwWhichMoniker, + LPMONIKER FAR* lplpmk +) +{ + LPCONTAINERLINE lpContainerLine; + + lpContainerLine=((struct COleClientSiteImpl FAR*)lpThis)->lpContainerLine; + + OLEDBG_BEGIN2("CntrLine_CliSite_GetMoniker\r\n") + + // OLE2NOTE: we must make sure to set output pointer parameters to NULL + *lplpmk = NULL; + + switch (dwWhichMoniker) { + + case OLEWHICHMK_CONTAINER: + /* OLE2NOTE: create a FileMoniker which identifies the + ** entire container document. + */ + *lplpmk = OleDoc_GetFullMoniker( + (LPOLEDOC)lpContainerLine->m_lpDoc, + dwAssign + ); + break; + + case OLEWHICHMK_OBJREL: + + /* OLE2NOTE: create an ItemMoniker which identifies the + ** OLE object relative to the container document. + */ + *lplpmk = ContainerLine_GetRelMoniker(lpContainerLine, dwAssign); + break; + + case OLEWHICHMK_OBJFULL: + { + /* OLE2NOTE: create an absolute moniker which identifies the + ** OLE object in the container document. this moniker is + ** created as a composite of the absolute moniker for the + ** entire document appended with an item moniker which + ** identifies the OLE object relative to the document. + */ + + *lplpmk = ContainerLine_GetFullMoniker(lpContainerLine, dwAssign); + break; + } + } + + OLEDBG_END2 + + if (*lplpmk != NULL) + return NOERROR; + else + return ResultFromScode(E_FAIL); +} + + +// IOleClientSite::GetContainer +STDMETHODIMP CntrLine_CliSite_GetContainer( + LPOLECLIENTSITE lpThis, + LPOLECONTAINER FAR* lplpContainer +) +{ + LPCONTAINERLINE lpContainerLine; + HRESULT hrErr; + + OLEDBG_BEGIN2("CntrLine_CliSite_GetContainer\r\n") + + lpContainerLine=((struct COleClientSiteImpl FAR*)lpThis)->lpContainerLine; + + hrErr = OleDoc_QueryInterface( + (LPOLEDOC)lpContainerLine->m_lpDoc, + &IID_IOleContainer, + (LPVOID FAR*)lplpContainer + ); + + OLEDBG_END2 + return hrErr; +} + + +// IOleClientSite::ShowObject +STDMETHODIMP CntrLine_CliSite_ShowObject(LPOLECLIENTSITE lpThis) +{ + LPCONTAINERLINE lpContainerLine = + ((struct COleClientSiteImpl FAR*)lpThis)->lpContainerLine; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerLine->m_lpDoc; + LPLINELIST lpLL = OutlineDoc_GetLineList(lpOutlineDoc); + int nIndex = LineList_GetLineIndex(lpLL, (LPLINE)lpContainerLine); + HWND hWndFrame = OutlineApp_GetFrameWindow(g_lpApp); + + OLEDBG_BEGIN2("CntrLine_CliSite_ShowObject\r\n") + + /* make sure our doc window is visible and not minimized. + ** the OutlineDoc_ShowWindow function will cause the app window + ** to show itself SW_SHOWNORMAL. + */ + if (! IsWindowVisible(hWndFrame) || IsIconic(hWndFrame)) + OutlineDoc_ShowWindow(lpOutlineDoc); + + BringWindowToTop(hWndFrame); + + /* make sure that the OLE object is currently in view. if necessary + ** scroll the document in order to bring it into view. + */ + LineList_ScrollLineIntoView(lpLL, nIndex); + +#if defined( INPLACE_CNTR ) + /* after the in-place object is scrolled into view, we need to ask + ** it to update its rect for the new clip rect coordinates + */ + ContainerDoc_UpdateInPlaceObjectRects((LPCONTAINERDOC)lpOutlineDoc, 0); +#endif + + OLEDBG_END2 + return NOERROR; +} + + +// IOleClientSite::OnShowWindow +STDMETHODIMP CntrLine_CliSite_OnShowWindow(LPOLECLIENTSITE lpThis, BOOL fShow) +{ + LPCONTAINERLINE lpContainerLine = + ((struct COleClientSiteImpl FAR*)lpThis)->lpContainerLine; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerLine->m_lpDoc; + LPLINELIST lpLL = OutlineDoc_GetLineList(lpOutlineDoc); + int nIndex = LineList_GetLineIndex(lpLL, (LPLINE)lpContainerLine); + + if (fShow) { + OLEDBG_BEGIN2("CntrLine_CliSite_OnShowWindow(TRUE)\r\n") + + /* OLE2NOTE: we need to hatch out the OLE object now; it has + ** just been opened in a window elsewhere (open editing as + ** opposed to in-place activation). + ** force the line to re-draw with the hatch. + */ + lpContainerLine->m_fObjWinOpen = TRUE; + LineList_ForceLineRedraw(lpLL, nIndex, FALSE /*fErase*/); + + } else { + OLEDBG_BEGIN2("CntrLine_CliSite_OnShowWindow(FALSE)\r\n") + + /* OLE2NOTE: the object associated with this container site has + ** just closed its server window. we should now remove the + ** hatching that indicates that the object is open + ** elsewhere. also our window should now come to the top. + ** force the line to re-draw without the hatch. + */ + lpContainerLine->m_fObjWinOpen = FALSE; + LineList_ForceLineRedraw(lpLL, nIndex, TRUE /*fErase*/); + + BringWindowToTop(lpOutlineDoc->m_hWndDoc); + SetFocus(lpOutlineDoc->m_hWndDoc); + } + + OLEDBG_END2 + return NOERROR; +} + + +// IOleClientSite::RequestNewObjectLayout +STDMETHODIMP CntrLine_CliSite_RequestNewObjectLayout(LPOLECLIENTSITE lpThis) +{ + OleDbgOut2("CntrLine_CliSite_RequestNewObjectLayout\r\n"); + + /* OLE2NOTE: this method is NOT yet used. it is for future layout + ** negotiation support. + */ + return ResultFromScode(E_NOTIMPL); +} + + +/************************************************************************* +** ContainerLine::IAdviseSink interface implementation +*************************************************************************/ + +// IAdviseSink::QueryInterface +STDMETHODIMP CntrLine_AdvSink_QueryInterface( + LPADVISESINK lpThis, + REFIID riid, + LPVOID FAR* lplpvObj +) +{ + LPCONTAINERLINE lpContainerLine = + ((struct COleClientSiteImpl FAR*)lpThis)->lpContainerLine; + + return ContainerLine_QueryInterface(lpContainerLine, riid, lplpvObj); +} + + +// IAdviseSink::AddRef +STDMETHODIMP_(ULONG) CntrLine_AdvSink_AddRef(LPADVISESINK lpThis) +{ + LPCONTAINERLINE lpContainerLine = + ((struct COleClientSiteImpl FAR*)lpThis)->lpContainerLine; + + OleDbgAddRefMethod(lpThis, "IAdviseSink"); + + return ContainerLine_AddRef(lpContainerLine); +} + + +// IAdviseSink::Release +STDMETHODIMP_(ULONG) CntrLine_AdvSink_Release (LPADVISESINK lpThis) +{ + LPCONTAINERLINE lpContainerLine = + ((struct COleClientSiteImpl FAR*)lpThis)->lpContainerLine; + + OleDbgReleaseMethod(lpThis, "IAdviseSink"); + + return ContainerLine_Release(lpContainerLine); +} + + +// IAdviseSink::OnDataChange +STDMETHODIMP_(void) CntrLine_AdvSink_OnDataChange( + LPADVISESINK lpThis, + FORMATETC FAR* lpFormatetc, + STGMEDIUM FAR* lpStgmed +) +{ + OleDbgOut2("CntrLine_AdvSink_OnDataChange\r\n"); + // We are not interested in data changes (only view changes) + // (ie. nothing to do) +} + + +STDMETHODIMP_(void) CntrLine_AdvSink_OnViewChange( + LPADVISESINK lpThis, + DWORD aspects, + LONG lindex +) +{ + LPCONTAINERLINE lpContainerLine; + LPOUTLINEDOC lpOutlineDoc; + HWND hWndDoc; + LPLINELIST lpLL; + MSG msg; + int nIndex; + + OLEDBG_BEGIN2("CntrLine_AdvSink_OnViewChange\r\n") + + lpContainerLine = ((struct CAdviseSinkImpl FAR*)lpThis)->lpContainerLine; + lpOutlineDoc = (LPOUTLINEDOC)lpContainerLine->m_lpDoc; + + /* OLE2NOTE: at this point we simply invalidate the rectangle of + ** the object to force a repaint in the future, we mark + ** that the extents of the object may have changed + ** (m_fDoGetExtent=TRUE), and we post a message + ** (WM_U_UPDATEOBJECTEXTENT) to our document that one or more + ** OLE objects may need to have their extents updated. later + ** when this message is processed, the document loops through + ** all lines to see if any are marked as needing an extent update. + ** if infact the extents did change. this can be done by calling + ** IViewObject2::GetExtent to retreive the object's current + ** extents and comparing with the last known extents for the + ** object. if the extents changed, then relayout space for the + ** object before drawing. we postpone the check to get + ** the extents now because OnViewChange is an asyncronis method, + ** and we have to careful not to call any syncronis methods back + ** to the object. while it WOULD be OK to call the + ** IViewObject2::GetExtent method within the asyncronis + ** OnViewChange method (because this method is handled by the + ** object handler and never remoted), it is good practise to not + ** call any object methods from within an asyncronis + ** notification method. + ** if there is already WM_U_UPDATEOBJECTEXTENT message waiting + ** in our message queue, there is no need to post another one. + ** in this way, if the server is updating quicker than we can + ** keep up, we do not make unneccsary GetExtent calls. also if + ** drawing is disabled, we postpone updating the extents of any + ** objects until drawing is re-enabled. + */ + lpContainerLine->m_fDoGetExtent = TRUE; + hWndDoc = OutlineDoc_GetWindow((LPOUTLINEDOC)lpContainerLine->m_lpDoc); + + if (lpOutlineDoc->m_nDisableDraw == 0 && + ! PeekMessage(&msg, hWndDoc, + WM_U_UPDATEOBJECTEXTENT, WM_U_UPDATEOBJECTEXTENT, + PM_NOREMOVE | PM_NOYIELD)) { + PostMessage(hWndDoc, WM_U_UPDATEOBJECTEXTENT, 0, 0L); + } + + // force the modified line to redraw. + lpLL = OutlineDoc_GetLineList(lpOutlineDoc); + nIndex = LineList_GetLineIndex(lpLL, (LPLINE)lpContainerLine); + LineList_ForceLineRedraw(lpLL, nIndex, TRUE /*fErase*/); + + OLEDBG_END2 +} + + +// IAdviseSink::OnRename +STDMETHODIMP_(void) CntrLine_AdvSink_OnRename( + LPADVISESINK lpThis, + LPMONIKER lpmk +) +{ + OleDbgOut2("CntrLine_AdvSink_OnRename\r\n"); + /* OLE2NOTE: the Embedding Container has nothing to do here. this + ** notification is important for linking situations. it tells + ** the OleLink objects to update their moniker because the + ** source object has been renamed (track the link source). + */ +} + + +// IAdviseSink::OnSave +STDMETHODIMP_(void) CntrLine_AdvSink_OnSave(LPADVISESINK lpThis) +{ + OleDbgOut2("CntrLine_AdvSink_OnSave\r\n"); + /* OLE2NOTE: the Embedding Container has nothing to do here. this + ** notification is only useful to clients which have set up a + ** data cache with the ADVFCACHE_ONSAVE flag. + */ +} + + +// IAdviseSink::OnClose +STDMETHODIMP_(void) CntrLine_AdvSink_OnClose(LPADVISESINK lpThis) +{ + OleDbgOut2("CntrLine_AdvSink_OnClose\r\n"); + /* OLE2NOTE: the Embedding Container has nothing to do here. this + ** notification is important for the OLE's default object handler + ** and the OleLink object. it tells them the remote object is + ** shutting down. + */ +} + + +/************************************************************************* +** ContainerLine Support Functions +*************************************************************************/ + + +/* ContainerLine_Init +** ------------------ +** Initialize fields in a newly constructed ContainerLine line object. +** NOTE: ref cnt of ContainerLine initialized to 0 +*/ +void ContainerLine_Init(LPCONTAINERLINE lpContainerLine, int nTab, HDC hDC) +{ + Line_Init((LPLINE)lpContainerLine, nTab, hDC); // init base class fields + + ((LPLINE)lpContainerLine)->m_lineType = CONTAINERLINETYPE; + ((LPLINE)lpContainerLine)->m_nWidthInHimetric = DEFOBJWIDTH; + ((LPLINE)lpContainerLine)->m_nHeightInHimetric = DEFOBJHEIGHT; + lpContainerLine->m_cRef = 0; + lpContainerLine->m_szStgName[0] = '\0'; + lpContainerLine->m_fObjWinOpen = FALSE; + lpContainerLine->m_fMonikerAssigned = FALSE; + lpContainerLine->m_dwDrawAspect = DVASPECT_CONTENT; + + lpContainerLine->m_fGuardObj = FALSE; + lpContainerLine->m_fDoGetExtent = FALSE; + lpContainerLine->m_fDoSetExtent = FALSE; + lpContainerLine->m_sizeInHimetric.cx = -1; + lpContainerLine->m_sizeInHimetric.cy = -1; + + lpContainerLine->m_lpStg = NULL; + lpContainerLine->m_lpDoc = NULL; + lpContainerLine->m_lpOleObj = NULL; + lpContainerLine->m_lpViewObj2 = NULL; + lpContainerLine->m_lpPersistStg = NULL; + lpContainerLine->m_lpOleLink = NULL; + lpContainerLine->m_dwLinkType = 0; + lpContainerLine->m_fLinkUnavailable = FALSE; + lpContainerLine->m_lpszShortType = NULL; + +#if defined( INPLACE_CNTR ) + lpContainerLine->m_fIpActive = FALSE; + lpContainerLine->m_fUIActive = FALSE; + lpContainerLine->m_fIpVisible = FALSE; + lpContainerLine->m_lpOleIPObj = NULL; + lpContainerLine->m_fInsideOutObj = FALSE; + lpContainerLine->m_fIpChangesUndoable = FALSE; + lpContainerLine->m_fIpServerRunning = FALSE; + lpContainerLine->m_hWndIpObject = NULL; + lpContainerLine->m_nHorizScrollShift = 0; +#endif // INPLACE_CNTR + + INIT_INTERFACEIMPL( + &lpContainerLine->m_Unknown, + &g_CntrLine_UnknownVtbl, + lpContainerLine + ); + + INIT_INTERFACEIMPL( + &lpContainerLine->m_OleClientSite, + &g_CntrLine_OleClientSiteVtbl, + lpContainerLine + ); + + INIT_INTERFACEIMPL( + &lpContainerLine->m_AdviseSink, + &g_CntrLine_AdviseSinkVtbl, + lpContainerLine + ); + +#if defined( INPLACE_CNTR ) + INIT_INTERFACEIMPL( + &lpContainerLine->m_OleInPlaceSite, + &g_CntrLine_OleInPlaceSiteVtbl, + lpContainerLine + ); +#endif // INPLACE_CNTR +} + + +/* Setup the OLE object associated with the ContainerLine */ +BOOL ContainerLine_SetupOleObject( + LPCONTAINERLINE lpContainerLine, + BOOL fDisplayAsIcon, + HGLOBAL hMetaPict +) +{ + DWORD dwDrawAspect = (fDisplayAsIcon ? DVASPECT_ICON : DVASPECT_CONTENT); + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerLine->m_lpDoc; + + /* Cache a pointer to the IViewObject2* interface. *Required* + ** we need this everytime we draw the object. + ** + ** OLE2NOTE: We require the object to support IViewObject2 + ** interface. this is an extension to the IViewObject interface + ** that was added with the OLE 2.01 release. This interface must + ** be supported by all object handlers and DLL-based objects. + */ + lpContainerLine->m_lpViewObj2 = (LPVIEWOBJECT2)OleStdQueryInterface( + (LPUNKNOWN)lpContainerLine->m_lpOleObj, &IID_IViewObject2); + if (! lpContainerLine->m_lpViewObj2) { +#if defined( _DEBUG ) + OleDbgAssertSz( + lpContainerLine->m_lpViewObj2,"IViewObject2 NOT supported\r\n"); +#endif + return FALSE; + } + + // Cache a pointer to the IPersistStorage* interface. *Required* + // we need this everytime we save the object. + lpContainerLine->m_lpPersistStg = (LPPERSISTSTORAGE)OleStdQueryInterface( + (LPUNKNOWN)lpContainerLine->m_lpOleObj, &IID_IPersistStorage); + if (! lpContainerLine->m_lpPersistStg) { + OleDbgAssert(lpContainerLine->m_lpPersistStg); + return FALSE; + } + + // Cache a pointer to the IOleLink* interface if supported. *Optional* + // if supported the object is a link. we need this to manage the link + lpContainerLine->m_lpOleLink = (LPOLELINK)OleStdQueryInterface( + (LPUNKNOWN)lpContainerLine->m_lpOleObj, &IID_IOleLink); + if (lpContainerLine->m_lpOleLink) { + OLEDBG_BEGIN2("IOleLink::GetUpdateOptions called\r\n") + lpContainerLine->m_lpOleLink->lpVtbl->GetUpdateOptions( + lpContainerLine->m_lpOleLink, &lpContainerLine->m_dwLinkType); + OLEDBG_END2 + } else + lpContainerLine->m_dwLinkType = 0; // NOT a link + + /* get the short user type name of the object. this + ** is used all the time when we have to build the object + ** verb menu. we will cache this information to make it + ** quicker to build the verb menu. + */ + OleDbgAssert(lpContainerLine->m_lpszShortType == NULL); + OLEDBG_BEGIN2("IOleObject::GetUserType called\r\n") + + CallIOleObjectGetUserTypeA( + lpContainerLine->m_lpOleObj, + USERCLASSTYPE_SHORT, + &lpContainerLine->m_lpszShortType + ); + + OLEDBG_END2 + + /* Perform that standard setup for the OLE object. this includes: + ** setup View advise + ** Call IOleObject::SetHostNames + ** Call OleSetContainedObject + */ + OleStdSetupAdvises( + lpContainerLine->m_lpOleObj, + dwDrawAspect, + (LPSTR)APPNAME, + lpOutlineDoc->m_lpszDocTitle, + (LPADVISESINK)&lpContainerLine->m_AdviseSink, + TRUE /*fCreate*/ + ); + +#if defined( INPLACE_CNTR ) + /* OLE2NOTE: (INSIDE-OUT CONTAINER) An inside-out container should + ** check if the object is an inside-out and prefers to be + ** activated when visible type of object. if not the object + ** should not be allowed to keep its window up after it gets + ** UIDeactivated. + */ + if (g_fInsideOutContainer) { + DWORD mstat; + OLEDBG_BEGIN2("IOleObject::GetMiscStatus called\r\n") + lpContainerLine->m_lpOleObj->lpVtbl->GetMiscStatus( + lpContainerLine->m_lpOleObj, + DVASPECT_CONTENT, + (DWORD FAR*)&mstat + ); + OLEDBG_END2 + + lpContainerLine->m_fInsideOutObj = (BOOL) + (mstat & (OLEMISC_INSIDEOUT|OLEMISC_ACTIVATEWHENVISIBLE)); + } +#endif // INPLACE_CNTR + + if (fDisplayAsIcon) { + /* user has requested to display icon aspect instead of content + ** aspect. + ** NOTE: we do not have to delete the previous aspect cache + ** because one did not get set up. + */ + OleStdSwitchDisplayAspect( + lpContainerLine->m_lpOleObj, + &lpContainerLine->m_dwDrawAspect, + dwDrawAspect, + hMetaPict, + FALSE, /* fDeleteOldAspect */ + TRUE, /* fSetupViewAdvise */ + (LPADVISESINK)&lpContainerLine->m_AdviseSink, + NULL /*fMustUpdate*/ // this can be ignored; update + // for switch to icon not req'd + ); + } + return TRUE; +} + + +/* Create an ContainerLine object and return the pointer */ +LPCONTAINERLINE ContainerLine_Create( + DWORD dwOleCreateType, + HDC hDC, + UINT nTab, + LPCONTAINERDOC lpContainerDoc, + LPCLSID lpclsid, + LPSTR lpszFileName, + BOOL fDisplayAsIcon, + HGLOBAL hMetaPict, + LPSTR lpszStgName +) +{ + LPCONTAINERLINE lpContainerLine = NULL; + LPOLEOBJECT lpObj = NULL; + LPSTORAGE lpDocStg = ContainerDoc_GetStg(lpContainerDoc); + DWORD dwDrawAspect = + (fDisplayAsIcon ? DVASPECT_ICON : DVASPECT_CONTENT); + DWORD dwOleRenderOpt = + (fDisplayAsIcon ? OLERENDER_NONE : OLERENDER_DRAW); + HRESULT hrErr; + + OLEDBG_BEGIN3("ContainerLine_Create\r\n") + + if (lpDocStg == NULL) { + OleDbgAssertSz(lpDocStg != NULL, "Doc storage is NULL"); + goto error; + } + + lpContainerLine=(LPCONTAINERLINE) New((DWORD)sizeof(CONTAINERLINE)); + if (lpContainerLine == NULL) { + OleDbgAssertSz(lpContainerLine!=NULL,"Error allocating ContainerLine"); + goto error; + } + + ContainerLine_Init(lpContainerLine, nTab, hDC); + + /* OLE2NOTE: in order to avoid re-entrancy we will set a flag to + ** guard our object. if this guard is set, then the object is + ** not ready to have any OLE interface methods called. it is + ** necessary to guard the object this way while it is being + ** created or loaded. + */ + lpContainerLine->m_fGuardObj = TRUE; + + /* OLE2NOTE: In order to have a stable ContainerLine object we must + ** AddRef the object's refcnt. this will be later released when + ** the ContainerLine is deleted. + */ + ContainerLine_AddRef(lpContainerLine); + + lstrcpy(lpContainerLine->m_szStgName, lpszStgName); + lpContainerLine->m_lpDoc = lpContainerDoc; + + /* Create a new storage for the object inside the doc's storage */ + lpContainerLine->m_lpStg = OleStdCreateChildStorage(lpDocStg,lpszStgName); + if (lpContainerLine->m_lpStg == NULL) { + OleDbgAssert(lpContainerLine->m_lpStg != NULL); + goto error; + } + + lpContainerLine->m_dwLinkType = 0; + + switch (dwOleCreateType) { + + case IOF_SELECTCREATENEW: + + OLEDBG_BEGIN2("OleCreate called\r\n") + hrErr = OleCreate ( + lpclsid, + &IID_IOleObject, + dwOleRenderOpt, + NULL, + (LPOLECLIENTSITE)&lpContainerLine->m_OleClientSite, + lpContainerLine->m_lpStg, + (LPVOID FAR*)&lpContainerLine->m_lpOleObj + ); + OLEDBG_END2 + +#if defined( _DEBUG ) + if (hrErr != NOERROR) + OleDbgOutHResult("OleCreate returned", hrErr); +#endif + + break; + + case IOF_SELECTCREATEFROMFILE: + + OLEDBG_BEGIN2("OleCreateFromFile called\r\n") + + hrErr = OleCreateFromFileA( + &CLSID_NULL, + lpszFileName, + &IID_IOleObject, + dwOleRenderOpt, + NULL, + (LPOLECLIENTSITE)&lpContainerLine->m_OleClientSite, + lpContainerLine->m_lpStg, + (LPVOID FAR*)&lpContainerLine->m_lpOleObj + ); + + OLEDBG_END2 + +#if defined( _DEBUG ) + if (hrErr != NOERROR) + OleDbgOutHResult("OleCreateFromFile returned", hrErr); +#endif + break; + + case IOF_CHECKLINK: + + OLEDBG_BEGIN2("OleCreateLinkToFile called\r\n") + + hrErr = OleCreateLinkToFileA( + lpszFileName, + &IID_IOleObject, + dwOleRenderOpt, + NULL, + (LPOLECLIENTSITE)&lpContainerLine->m_OleClientSite, + lpContainerLine->m_lpStg, + (LPVOID FAR*)&lpContainerLine->m_lpOleObj + ); + + OLEDBG_END2 + +#if defined( _DEBUG ) + if (hrErr != NOERROR) + OleDbgOutHResult("OleCreateLinkToFile returned", hrErr); +#endif + break; + } + if (hrErr != NOERROR) + goto error; + + if (! ContainerLine_SetupOleObject( + lpContainerLine, fDisplayAsIcon, hMetaPict)) { + goto error; + } + + /* OLE2NOTE: clear our re-entrancy guard. the object is now ready + ** to have interface methods called. + */ + lpContainerLine->m_fGuardObj = FALSE; + + OLEDBG_END3 + return lpContainerLine; + +error: + OutlineApp_ErrorMessage(g_lpApp, "Could not create object!"); + + // Destroy partially created OLE object + if (lpContainerLine) + ContainerLine_Delete(lpContainerLine); + OLEDBG_END3 + return NULL; +} + + +LPCONTAINERLINE ContainerLine_CreateFromData( + HDC hDC, + UINT nTab, + LPCONTAINERDOC lpContainerDoc, + LPDATAOBJECT lpSrcDataObj, + DWORD dwCreateType, + CLIPFORMAT cfFormat, + BOOL fDisplayAsIcon, + HGLOBAL hMetaPict, + LPSTR lpszStgName +) +{ + HGLOBAL hData = NULL; + LPCONTAINERLINE lpContainerLine = NULL; + LPOLEOBJECT lpObj = NULL; + LPSTORAGE lpDocStg = ContainerDoc_GetStg(lpContainerDoc); + DWORD dwDrawAspect = + (fDisplayAsIcon ? DVASPECT_ICON : DVASPECT_CONTENT); + DWORD dwOleRenderOpt; + FORMATETC renderFmtEtc; + LPFORMATETC lpRenderFmtEtc = NULL; + HRESULT hrErr; + LPUNKNOWN lpUnk = NULL; + + OLEDBG_BEGIN3("ContainerLine_CreateFromData\r\n") + + if (dwCreateType == OLECREATEFROMDATA_STATIC && cfFormat != 0) { + // a particular type of static object should be created + + dwOleRenderOpt = OLERENDER_FORMAT; + lpRenderFmtEtc = (LPFORMATETC)&renderFmtEtc; + + if (cfFormat == CF_METAFILEPICT) + SETDEFAULTFORMATETC(renderFmtEtc, cfFormat, TYMED_MFPICT); + else if (cfFormat == CF_BITMAP) + SETDEFAULTFORMATETC(renderFmtEtc, cfFormat, TYMED_GDI); + else + SETDEFAULTFORMATETC(renderFmtEtc, cfFormat, TYMED_HGLOBAL); + + } else if (dwCreateType == OLECREATEFROMDATA_STATIC && fDisplayAsIcon) { + // a link that currently displayed as an icon needs to be + // converted to a STATIC picture object. this case is driven + // from "BreakLink" in the "Links" dialog. because the current + // data in the source object's cache is DVASPECT_ICON we need + // to tell the OleCreateStaticFromData API to look for + // DVASPECT_ICON data. the static object that results however, + // is considered to be displayed in the DVASPECT_CONTENT view. + + dwOleRenderOpt = OLERENDER_DRAW; + lpRenderFmtEtc = (LPFORMATETC)&renderFmtEtc; + SETFORMATETC(renderFmtEtc,0,DVASPECT_ICON,NULL,TYMED_NULL,-1); + dwDrawAspect = DVASPECT_CONTENT; // static obj displays only CONTENT + + } else if (fDisplayAsIcon && hMetaPict) { + // a special icon should be used. first we create the object + // OLERENDER_NONE and then we stuff the special icon into the cache. + + dwOleRenderOpt = OLERENDER_NONE; + + } else if (fDisplayAsIcon && hMetaPict == NULL) { + // the object's default icon should be used + + dwOleRenderOpt = OLERENDER_DRAW; + lpRenderFmtEtc = (LPFORMATETC)&renderFmtEtc; + SETFORMATETC(renderFmtEtc,0,DVASPECT_ICON,NULL,TYMED_NULL,-1); + + } else { + // create standard DVASPECT_CONTENT/OLERENDER_DRAW object + dwOleRenderOpt = OLERENDER_DRAW; + } + + if (lpDocStg == NULL) { + OleDbgAssertSz(lpDocStg != NULL, "Doc storage is NULL"); + goto error; + } + + lpContainerLine=(LPCONTAINERLINE) New((DWORD)sizeof(CONTAINERLINE)); + if (lpContainerLine == NULL) { + OleDbgAssertSz(lpContainerLine!=NULL,"Error allocating ContainerLine"); + goto error; + } + + ContainerLine_Init(lpContainerLine, nTab, hDC); + + /* OLE2NOTE: in order to avoid re-entrancy we will set a flag to + ** guard our object. if this guard is set, then the object is + ** not ready to have any OLE interface methods called. it is + ** necessary to guard the object this way while it is being + ** created or loaded. + */ + lpContainerLine->m_fGuardObj = TRUE; + + /* OLE2NOTE: In order to have a stable ContainerLine object we must + ** AddRef the object's refcnt. this will be later released when + ** the ContainerLine is deleted. + */ + ContainerLine_AddRef(lpContainerLine); + + lstrcpy(lpContainerLine->m_szStgName, lpszStgName); + lpContainerLine->m_lpDoc = lpContainerDoc; + + /* Create a new storage for the object inside the doc's storage */ + lpContainerLine->m_lpStg = OleStdCreateChildStorage(lpDocStg,lpszStgName); + if (lpContainerLine->m_lpStg == NULL) { + OleDbgAssert(lpContainerLine->m_lpStg != NULL); + goto error; + } + + switch (dwCreateType) { + + case OLECREATEFROMDATA_LINK: + + OLEDBG_BEGIN2("OleCreateLinkFromData called\r\n") + hrErr = OleCreateLinkFromData ( + lpSrcDataObj, + &IID_IOleObject, + dwOleRenderOpt, + lpRenderFmtEtc, + (LPOLECLIENTSITE)&lpContainerLine->m_OleClientSite, + lpContainerLine->m_lpStg, + (LPVOID FAR*)&lpContainerLine->m_lpOleObj + ); + OLEDBG_END2 + +#if defined( _DEBUG ) + if (hrErr != NOERROR) + OleDbgOutHResult("OleCreateLinkFromData returned", hrErr); +#endif + break; + + case OLECREATEFROMDATA_OBJECT: + + OLEDBG_BEGIN2("OleCreateFromData called\r\n") + hrErr = OleCreateFromData ( + lpSrcDataObj, + &IID_IOleObject, + dwOleRenderOpt, + lpRenderFmtEtc, + (LPOLECLIENTSITE)&lpContainerLine->m_OleClientSite, + lpContainerLine->m_lpStg, + (LPVOID FAR*)&lpContainerLine->m_lpOleObj + ); + OLEDBG_END2 + +#if defined( _DEBUG ) + if (hrErr != NOERROR) + OleDbgOutHResult("OleCreateFromData returned", hrErr); +#endif + break; + + case OLECREATEFROMDATA_STATIC: + + OLEDBG_BEGIN2("OleCreateStaticFromData called\r\n") + hrErr = OleCreateStaticFromData ( + lpSrcDataObj, + &IID_IOleObject, + dwOleRenderOpt, + lpRenderFmtEtc, + (LPOLECLIENTSITE)&lpContainerLine->m_OleClientSite, + lpContainerLine->m_lpStg, + (LPVOID FAR*)&lpContainerLine->m_lpOleObj + ); + OLEDBG_END2 + +#if defined( _DEBUG ) + if (hrErr != NOERROR) + OleDbgOutHResult("OleCreateStaticFromData returned", hrErr); +#endif + break; + } + + if (hrErr != NOERROR) + goto error; + + if (! ContainerLine_SetupOleObject( + lpContainerLine, fDisplayAsIcon, hMetaPict)) { + goto error; + } + + /* OLE2NOTE: clear our re-entrancy guard. the object is now ready + ** to have interface methods called. + */ + lpContainerLine->m_fGuardObj = FALSE; + + OLEDBG_END3 + return lpContainerLine; + +error: + OutlineApp_ErrorMessage(g_lpApp, "Could not create object!"); + // Destroy partially created OLE object + if (lpContainerLine) + ContainerLine_Delete(lpContainerLine); + OLEDBG_END3 + return NULL; +} + + +/* ContainerLine_AddRef +** -------------------- +** +** increment the ref count of the line object. +** +** Returns the new ref count on the object +*/ +ULONG ContainerLine_AddRef(LPCONTAINERLINE lpContainerLine) +{ + ++lpContainerLine->m_cRef; + +#if defined( _DEBUG ) + OleDbgOutRefCnt4( + "ContainerLine_AddRef: cRef++\r\n", + lpContainerLine, + lpContainerLine->m_cRef + ); +#endif + return lpContainerLine->m_cRef; +} + + +/* ContainerLine_Release +** --------------------- +** +** decrement the ref count of the line object. +** if the ref count goes to 0, then the line is destroyed. +** +** Returns the remaining ref count on the object +*/ +ULONG ContainerLine_Release(LPCONTAINERLINE lpContainerLine) +{ + ULONG cRef; + + /********************************************************************* + ** OLE2NOTE: when the obj refcnt == 0, then destroy the object. ** + ** otherwise the object is still in use. ** + *********************************************************************/ + + cRef = --lpContainerLine->m_cRef; + +#if defined( _DEBUG ) + OleDbgAssertSz( + lpContainerLine->m_cRef >= 0,"Release called with cRef == 0"); + + OleDbgOutRefCnt4( + "ContainerLine_Release: cRef--\r\n", + lpContainerLine, + cRef + ); +#endif + if (cRef == 0) + ContainerLine_Destroy(lpContainerLine); + + return cRef; +} + + +/* ContainerLine_QueryInterface +** ---------------------------- +** +** Retrieve a pointer to an interface on the ContainerLine object. +** +** Returns NOERROR if interface is successfully retrieved. +** E_NOINTERFACE if the interface is not supported +*/ +HRESULT ContainerLine_QueryInterface( + LPCONTAINERLINE lpContainerLine, + REFIID riid, + LPVOID FAR* lplpvObj +) +{ + SCODE sc = E_NOINTERFACE; + + /* OLE2NOTE: we must make sure to set all out ptr parameters to NULL. */ + *lplpvObj = NULL; + + if (IsEqualIID(riid, &IID_IUnknown)) { + OleDbgOut4("ContainerLine_QueryInterface: IUnknown* RETURNED\r\n"); + + *lplpvObj = (LPVOID) &lpContainerLine->m_Unknown; + ContainerLine_AddRef(lpContainerLine); + sc = S_OK; + } + else if (IsEqualIID(riid, &IID_IOleClientSite)) { + OleDbgOut4("ContainerLine_QueryInterface: IOleClientSite* RETURNED\r\n"); + + *lplpvObj = (LPVOID) &lpContainerLine->m_OleClientSite; + ContainerLine_AddRef(lpContainerLine); + sc = S_OK; + } + else if (IsEqualIID(riid, &IID_IAdviseSink)) { + OleDbgOut4("ContainerLine_QueryInterface: IAdviseSink* RETURNED\r\n"); + + *lplpvObj = (LPVOID) &lpContainerLine->m_AdviseSink; + ContainerLine_AddRef(lpContainerLine); + sc = S_OK; + } +#if defined( INPLACE_CNTR ) + else if (IsEqualIID(riid, &IID_IOleWindow) + || IsEqualIID(riid, &IID_IOleInPlaceSite)) { + OleDbgOut4("ContainerLine_QueryInterface: IOleInPlaceSite* RETURNED\r\n"); + + *lplpvObj = (LPVOID) &lpContainerLine->m_OleInPlaceSite; + ContainerLine_AddRef(lpContainerLine); + sc = S_OK; + } +#endif // INPLACE_CNTR + + OleDbgQueryInterfaceMethod(*lplpvObj); + + return ResultFromScode(sc); +} + + +BOOL ContainerLine_LoadOleObject(LPCONTAINERLINE lpContainerLine) +{ + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerLine->m_lpDoc; + LPSTORAGE lpDocStg = ContainerDoc_GetStg(lpContainerLine->m_lpDoc); + LPOLECLIENTSITE lpOleClientSite; + LPMONIKER lpmkObj; + LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; + BOOL fPrevEnable1; + BOOL fPrevEnable2; + HRESULT hrErr; + + if (lpContainerLine->m_fGuardObj) + return FALSE; // object in process of creation + + if (lpContainerLine->m_lpOleObj) + return TRUE; // object already loaded + + OLEDBG_BEGIN3("ContainerLine_LoadOleObject\r\n") + + /* OLE2NOTE: in order to avoid re-entrancy we will set a flag to + ** guard our object. if this guard is set, then the object is + ** not ready to have any OLE interface methods called. it is + ** necessary to guard the object this way while it is being + ** created or loaded. + */ + lpContainerLine->m_fGuardObj = TRUE; + + /* if object storage is not already open, then open it */ + if (! lpContainerLine->m_lpStg) { + lpContainerLine->m_lpStg = OleStdOpenChildStorage( + lpDocStg, + lpContainerLine->m_szStgName, + STGM_READWRITE + ); + if (lpContainerLine->m_lpStg == NULL) { + OleDbgAssert(lpContainerLine->m_lpStg != NULL); + goto error; + } + } + + /* OLE2NOTE: if the OLE object being loaded is in a data transfer + ** document, then we should NOT pass a IOleClientSite* pointer + ** to the OleLoad call. This particularly critical if the OLE + ** object is an OleLink object. If a non-NULL client site is + ** passed to the OleLoad function, then the link will bind to + ** the source if its is running. in the situation that we are + ** loading the object as part of a data transfer document we do + ** not want this connection to be established. even worse, if + ** the link source is currently blocked or busy, then this could + ** hang the system. it is simplest to never pass a + ** IOleClientSite* when loading an object in a data transfer + ** document. + */ + lpOleClientSite = (lpOutlineDoc->m_fDataTransferDoc ? + NULL : (LPOLECLIENTSITE)&lpContainerLine->m_OleClientSite); + + /* OLE2NOTE: we do not want to ever give the Busy/NotResponding + ** dialogs when we are loading an object. if the object is a + ** link, it will attempt to BindIfRunning to the link source. if + ** the link source is currently busy, this could cause the Busy + ** dialog to come up. even if the link source is busy, + ** we do not want put up the busy dialog. thus we will disable + ** the dialog and later re-enable them + */ + OleApp_DisableBusyDialogs(lpOleApp, &fPrevEnable1, &fPrevEnable2); + + OLEDBG_BEGIN2("OleLoad called\r\n") + hrErr = OleLoad ( + lpContainerLine->m_lpStg, + &IID_IOleObject, + lpOleClientSite, + (LPVOID FAR*)&lpContainerLine->m_lpOleObj + ); + OLEDBG_END2 + + // re-enable the Busy/NotResponding dialogs + OleApp_EnableBusyDialogs(lpOleApp, fPrevEnable1, fPrevEnable2); + + if (hrErr != NOERROR) { + OleDbgAssertSz(hrErr == NOERROR, "Could not load object!"); + OleDbgOutHResult("OleLoad returned", hrErr); + goto error; + } + + /* Cache a pointer to the IViewObject2* interface. *Required* + ** we need this everytime we draw the object. + ** + ** OLE2NOTE: We require the object to support IViewObject2 + ** interface. this is an extension to the IViewObject interface + ** that was added with the OLE 2.01 release. This interface must + ** be supported by all object handlers and DLL-based objects. + */ + lpContainerLine->m_lpViewObj2 = (LPVIEWOBJECT2)OleStdQueryInterface( + (LPUNKNOWN)lpContainerLine->m_lpOleObj, &IID_IViewObject2); + if (! lpContainerLine->m_lpViewObj2) { +#if defined( _DEBUG ) + OleDbgAssertSz( + lpContainerLine->m_lpViewObj2,"IViewObject2 NOT supported\r\n"); +#endif + goto error; + } + + // Cache a pointer to the IPersistStorage* interface. *Required* + // we need this everytime we save the object. + lpContainerLine->m_lpPersistStg = (LPPERSISTSTORAGE)OleStdQueryInterface( + (LPUNKNOWN)lpContainerLine->m_lpOleObj, &IID_IPersistStorage); + if (! lpContainerLine->m_lpPersistStg) { + OleDbgAssert(lpContainerLine->m_lpPersistStg); + goto error; + } + + // Cache a pointer to the IOleLink* interface if supported. *Optional* + // if supported the object is a link. we need this to manage the link + if (lpContainerLine->m_dwLinkType != 0) { + lpContainerLine->m_lpOleLink = (LPOLELINK)OleStdQueryInterface( + (LPUNKNOWN)lpContainerLine->m_lpOleObj, &IID_IOleLink); + if (! lpContainerLine->m_lpOleLink) { + OleDbgAssert(lpContainerLine->m_lpOleLink); + goto error; + } + } + + /* OLE2NOTE: clear our re-entrancy guard. the object is now ready + ** to have interface methods called. + */ + lpContainerLine->m_fGuardObj = FALSE; + + /* OLE2NOTE: similarly, if the OLE object being loaded is in a data + ** transfer document, then we do NOT need to setup any advises, + ** call SetHostNames, SetMoniker, etc. + */ + if (lpOleClientSite) { + /* Setup the Advises (OLE notifications) that we are interested + ** in receiving. + */ + OleStdSetupAdvises( + lpContainerLine->m_lpOleObj, + lpContainerLine->m_dwDrawAspect, + (LPSTR)APPNAME, + lpOutlineDoc->m_lpszDocTitle, + (LPADVISESINK)&lpContainerLine->m_AdviseSink, + FALSE /*fCreate*/ + ); + + /* OLE2NOTE: if the OLE object has a moniker assigned, we need to + ** inform the object by calling IOleObject::SetMoniker. this + ** will force the OLE object to register in the + ** RunningObjectTable when it enters the running state. + */ + if (lpContainerLine->m_fMonikerAssigned) { + lpmkObj = ContainerLine_GetRelMoniker( + lpContainerLine, + GETMONIKER_ONLYIFTHERE + ); + + if (lpmkObj) { + OLEDBG_BEGIN2("IOleObject::SetMoniker called\r\n") + lpContainerLine->m_lpOleObj->lpVtbl->SetMoniker( + lpContainerLine->m_lpOleObj, + OLEWHICHMK_OBJREL, + lpmkObj + ); + OLEDBG_END2 + OleStdRelease((LPUNKNOWN)lpmkObj); + } + } + + /* get the Short form of the user type name of the object. this + ** is used all the time when we have to build the object + ** verb menu. we will cache this information to make it + ** quicker to build the verb menu. + */ + OLEDBG_BEGIN2("IOleObject::GetUserType called\r\n") + CallIOleObjectGetUserTypeA( + lpContainerLine->m_lpOleObj, + USERCLASSTYPE_SHORT, + &lpContainerLine->m_lpszShortType + ); + + OLEDBG_END2 + +#if defined( INPLACE_CNTR ) + /* OLE2NOTE: an inside-out container should check if the object + ** is an inside-out and prefers to be activated when visible + ** type of object. if so, the object should be immediately + ** activated in-place, BUT NOT UIActived. + */ + if (g_fInsideOutContainer && + lpContainerLine->m_dwDrawAspect == DVASPECT_CONTENT) { + DWORD mstat; + OLEDBG_BEGIN2("IOleObject::GetMiscStatus called\r\n") + lpContainerLine->m_lpOleObj->lpVtbl->GetMiscStatus( + lpContainerLine->m_lpOleObj, + DVASPECT_CONTENT, + (DWORD FAR*)&mstat + ); + OLEDBG_END2 + + lpContainerLine->m_fInsideOutObj = (BOOL) + (mstat & (OLEMISC_INSIDEOUT|OLEMISC_ACTIVATEWHENVISIBLE)); + + if ( lpContainerLine->m_fInsideOutObj ) { + HWND hWndDoc = OutlineDoc_GetWindow(lpOutlineDoc); + + ContainerLine_DoVerb( + lpContainerLine, + OLEIVERB_INPLACEACTIVATE, + NULL, + FALSE, + FALSE + ); + + /* OLE2NOTE: following this DoVerb(INPLACEACTIVATE) the + ** object may have taken focus. but because the + ** object is NOT UIActive it should NOT have focus. + ** we will make sure our document has focus. + */ + SetFocus(hWndDoc); + } + } +#endif // INPLACE_CNTR + OLEDBG_END2 + + } + + OLEDBG_END2 + return TRUE; + +error: + OLEDBG_END2 + return FALSE; +} + + +/* ContainerLine_CloseOleObject +** ---------------------------- +** Close the OLE object associated with the ContainerLine. +** +** Closing the object forces the object to transition from the +** running state to the loaded state. if the object was not running, +** then there is no effect. it is necessary to close the OLE object +** before releasing the pointers to the OLE object. +** +** Returns TRUE if successfully closed, +** FALSE if closing was aborted. +*/ +BOOL ContainerLine_CloseOleObject( + LPCONTAINERLINE lpContainerLine, + DWORD dwSaveOption +) +{ + HRESULT hrErr; + SCODE sc; + + if (lpContainerLine->m_fGuardObj) + return FALSE; // object in process of creation + + if (! lpContainerLine->m_lpOleObj) + return TRUE; // object is NOT loaded + + OLEDBG_BEGIN2("IOleObject::Close called\r\n") + hrErr = lpContainerLine->m_lpOleObj->lpVtbl->Close( + lpContainerLine->m_lpOleObj, + (dwSaveOption == OLECLOSE_NOSAVE ? + OLECLOSE_NOSAVE : OLECLOSE_SAVEIFDIRTY) + ); + OLEDBG_END2 + +#if defined( INPLACE_CNTR ) + if (lpContainerLine->m_fIpServerRunning) { + /* OLE2NOTE: unlock the lock held on the in-place object. + ** it is VERY important that an in-place container + ** that also support linking to embeddings properly manage + ** the running of its in-place objects. in an outside-in + ** style in-place container, when the user clicks + ** outside of the in-place active object, the object gets + ** UIDeactivated and the object hides its window. in order + ** to make the object fast to reactivate, the container + ** deliberately does not call IOleObject::Close. the object + ** stays running in the invisible unlocked state. the idea + ** here is if the user simply clicks outside of the object + ** and then wants to double click again to re-activate the + ** object, we do not want this to be slow. if we want to + ** keep the object running, however, we MUST Lock it + ** running. otherwise the object will be in an unstable + ** state where if a linking client does a "silent-update" + ** (eg. UpdateNow from the Links dialog), then the in-place + ** server will shut down even before the object has a chance + ** to be saved back in its container. this saving normally + ** occurs when the in-place container closes the object. also + ** keeping the object in the unstable, hidden, running, + ** not-locked state can cause problems in some scenarios. + ** ICntrOtl keeps only one object running. if the user + ** intiates a DoVerb on another object, then that last + ** running in-place active object is closed. a more + ** sophistocated in-place container may keep more object running. + ** (see CntrLine_IPSite_OnInPlaceActivate) + */ + lpContainerLine->m_fIpServerRunning = FALSE; + + OLEDBG_BEGIN2("OleLockRunning(FALSE,TRUE) called\r\n") + OleLockRunning((LPUNKNOWN)lpContainerLine->m_lpOleObj, FALSE, TRUE); + OLEDBG_END2 + } +#endif + + if (hrErr != NOERROR) { + OleDbgOutHResult("IOleObject::Close returned", hrErr); + sc = GetScode(hrErr); + if (sc == RPC_E_CALL_REJECTED || sc==OLE_E_PROMPTSAVECANCELLED) + return FALSE; // object aborted shutdown + } + return TRUE; +} + + +/* ContainerLine_UnloadOleObject +** ----------------------------- +** Close the OLE object associated with the ContainerLine and +** release all pointer held to the object. +** +** Closing the object forces the object to transition from the +** running state to the loaded state. if the object was not running, +** then there is no effect. it is necessary to close the OLE object +** before releasing the pointers to the OLE object. releasing all +** pointers to the object allows the object to transition from +** loaded to unloaded (or passive). +*/ +void ContainerLine_UnloadOleObject( + LPCONTAINERLINE lpContainerLine, + DWORD dwSaveOption +) +{ + if (lpContainerLine->m_lpOleObj) { + + OLEDBG_BEGIN2("IOleObject::Close called\r\n") + lpContainerLine->m_lpOleObj->lpVtbl->Close( + lpContainerLine->m_lpOleObj, dwSaveOption); + OLEDBG_END2 + + /* OLE2NOTE: we will take our IOleClientSite* pointer away from + ** the object before we release all pointers to the object. + ** in the scenario where the object is implemented as an + ** in-proc server (DLL object), then, if there are link + ** connections to the DLL object, it is possible that the + ** object will not be destroyed when we release our pointers + ** to the object. the existance of the remote link + ** connections will hold the object alive. later when these + ** strong connections are released, then the object may + ** attempt to call IOleClientSite::Save if we had not taken + ** away the client site pointer. + */ + OLEDBG_BEGIN2("IOleObject::SetClientSite(NULL) called\r\n") + lpContainerLine->m_lpOleObj->lpVtbl->SetClientSite( + lpContainerLine->m_lpOleObj, NULL); + OLEDBG_END2 + + OleStdRelease((LPUNKNOWN)lpContainerLine->m_lpOleObj); + lpContainerLine->m_lpOleObj = NULL; + + if (lpContainerLine->m_lpViewObj2) { + OleStdRelease((LPUNKNOWN)lpContainerLine->m_lpViewObj2); + lpContainerLine->m_lpViewObj2 = NULL; + } + if (lpContainerLine->m_lpPersistStg) { + OleStdRelease((LPUNKNOWN)lpContainerLine->m_lpPersistStg); + lpContainerLine->m_lpPersistStg = NULL; + } + + if (lpContainerLine->m_lpOleLink) { + OleStdRelease((LPUNKNOWN)lpContainerLine->m_lpOleLink); + lpContainerLine->m_lpOleLink = NULL; + } + } + + if (lpContainerLine->m_lpszShortType) { + OleStdFreeString(lpContainerLine->m_lpszShortType, NULL); + lpContainerLine->m_lpszShortType = NULL; + } +} + + +/* ContainerLine_Delete +** -------------------- +** Delete the ContainerLine. +** +** NOTE: we can NOT directly destroy the memory for the +** ContainerLine; the ContainerLine maintains a reference count. a +** non-zero reference count indicates that the object is still +** in-use. The OleObject keeps a reference-counted pointer to the +** ClientLine object. we must take the actions necessary so that the +** ContainerLine object receives Releases for outstanding +** references. when the reference count of the ContainerLine reaches +** zero, then the memory for the object will actually be destroyed +** (ContainerLine_Destroy called). +** +*/ +void ContainerLine_Delete(LPCONTAINERLINE lpContainerLine) +{ + OLEDBG_BEGIN2("ContainerLine_Delete\r\n") + +#if defined( INPLACE_CNTR ) + if (lpContainerLine == lpContainerLine->m_lpDoc->m_lpLastIpActiveLine) + lpContainerLine->m_lpDoc->m_lpLastIpActiveLine = NULL; + if (lpContainerLine == lpContainerLine->m_lpDoc->m_lpLastUIActiveLine) + lpContainerLine->m_lpDoc->m_lpLastUIActiveLine = NULL; +#endif + + /* OLE2NOTE: in order to have a stable line object during the + ** process of deleting, we intially AddRef the line ref cnt and + ** later Release it. This initial AddRef is artificial; it is + ** simply done to guarantee that our object does not destroy + ** itself until the END of this routine. + */ + ContainerLine_AddRef(lpContainerLine); + + // Unload the loaded OLE object + if (lpContainerLine->m_lpOleObj) + ContainerLine_UnloadOleObject(lpContainerLine, OLECLOSE_NOSAVE); + + /* OLE2NOTE: we can NOT directly free the memory for the ContainerLine + ** data structure until everyone holding on to a pointer to our + ** ClientSite interface and IAdviseSink interface has released + ** their pointers. There is one refcnt on the ContainerLine object + ** which is held by the container itself. we will release this + ** refcnt here. + */ + ContainerLine_Release(lpContainerLine); + + /* OLE2NOTE: this call forces all external connections to our + ** ContainerLine to close down and therefore guarantees that + ** we receive all releases associated with those external + ** connections. Strictly this call should NOT be necessary, but + ** it is defensive coding to make this call. + */ + OLEDBG_BEGIN2("CoDisconnectObject(lpContainerLine) called\r\n") + CoDisconnectObject((LPUNKNOWN)&lpContainerLine->m_Unknown, 0); + OLEDBG_END2 + +#if defined( _DEBUG ) + /* at this point the object all references from the OLE object to + ** our ContainerLine object should have been released. there + ** should only be 1 remaining reference that will be released below. + */ + if (lpContainerLine->m_cRef != 1) { + OleDbgOutRefCnt( + "WARNING: ContainerLine_Delete: cRef != 1\r\n", + lpContainerLine, + lpContainerLine->m_cRef + ); + } +#endif + + ContainerLine_Release(lpContainerLine); // release artificial AddRef above + OLEDBG_END2 +} + + +/* ContainerLine_Destroy +** --------------------- +** Destroy (Free) the memory used by a ContainerLine structure. +** This function is called when the ref count of the ContainerLine goes +** to zero. the ref cnt goes to zero after ContainerLine_Delete forces +** the OleObject to unload and release its pointers to the +** ContainerLine IOleClientSite and IAdviseSink interfaces. +*/ + +void ContainerLine_Destroy(LPCONTAINERLINE lpContainerLine) +{ + LPUNKNOWN lpTmpObj; + + OLEDBG_BEGIN2("ContainerLine_Destroy\r\n") + + // Release the storage opened for the OLE object + if (lpContainerLine->m_lpStg) { + lpTmpObj = (LPUNKNOWN)lpContainerLine->m_lpStg; + lpContainerLine->m_lpStg = NULL; + + OleStdRelease(lpTmpObj); + } + + if (lpContainerLine->m_lpszShortType) { + OleStdFreeString(lpContainerLine->m_lpszShortType, NULL); + lpContainerLine->m_lpszShortType = NULL; + } + + Delete(lpContainerLine); // Free the memory for the structure itself + OLEDBG_END2 +} + + +/* ContainerLine_CopyToDoc + * ----------------------- + * + * Copy a ContainerLine to another Document (usually ClipboardDoc) + */ +BOOL ContainerLine_CopyToDoc( + LPCONTAINERLINE lpSrcLine, + LPOUTLINEDOC lpDestDoc, + int nIndex +) +{ + LPCONTAINERLINE lpDestLine = NULL; + LPLINELIST lpDestLL = &lpDestDoc->m_LineList; + HDC hDC; + HRESULT hrErr; + BOOL fStatus; + LPSTORAGE lpDestDocStg = ((LPOLEDOC)lpDestDoc)->m_lpStg; + LPSTORAGE lpDestObjStg = NULL; + + lpDestLine = (LPCONTAINERLINE) New((DWORD)sizeof(CONTAINERLINE)); + if (lpDestLine == NULL) { + OleDbgAssertSz(lpDestLine!=NULL, "Error allocating ContainerLine"); + return FALSE; + } + + hDC = LineList_GetDC(lpDestLL); + ContainerLine_Init(lpDestLine, ((LPLINE)lpSrcLine)->m_nTabLevel, hDC); + LineList_ReleaseDC(lpDestLL, hDC); + + /* OLE2NOTE: In order to have a stable ContainerLine object we must + ** AddRef the object's refcnt. this will be later released when + ** the ContainerLine is deleted. + */ + ContainerLine_AddRef(lpDestLine); + + lpDestLine->m_lpDoc = (LPCONTAINERDOC)lpDestDoc; + + // Copy data of the original source ContainerLine. + ((LPLINE)lpDestLine)->m_nWidthInHimetric = + ((LPLINE)lpSrcLine)->m_nWidthInHimetric; + ((LPLINE)lpDestLine)->m_nHeightInHimetric = + ((LPLINE)lpSrcLine)->m_nHeightInHimetric; + lpDestLine->m_fMonikerAssigned = lpSrcLine->m_fMonikerAssigned; + lpDestLine->m_dwDrawAspect = lpSrcLine->m_dwDrawAspect; + lpDestLine->m_sizeInHimetric = lpSrcLine->m_sizeInHimetric; + lpDestLine->m_dwLinkType = lpSrcLine->m_dwLinkType; + + + /* We must create a new sub-storage for the embedded object within + ** the destination document's storage. We will first attempt to + ** use the same storage name as the source line. if this name is + ** in use, then we will allocate a new name. in this way we try + ** to keep the name associated with the OLE object unchanged + ** through a Cut/Paste operation. + */ + lpDestObjStg = OleStdCreateChildStorage( + lpDestDocStg, + lpSrcLine->m_szStgName + ); + if (lpDestObjStg) { + lstrcpy(lpDestLine->m_szStgName, lpSrcLine->m_szStgName); + } else { + /* the original name was in use, make up a new name. */ + ContainerDoc_GetNextStgName( + (LPCONTAINERDOC)lpDestDoc, + lpDestLine->m_szStgName, + sizeof(lpDestLine->m_szStgName) + ); + lpDestObjStg = OleStdCreateChildStorage( + lpDestDocStg, + lpDestLine->m_szStgName + ); + } + if (lpDestObjStg == NULL) { + OleDbgAssertSz(lpDestObjStg != NULL, "Error creating child stg"); + goto error; + } + + // Copy over storage of the embedded object itself + + if (! lpSrcLine->m_lpOleObj) { + + /***************************************************************** + ** CASE 1: object is NOT loaded. + ** because the object is not loaded, we can simply copy the + ** object's current storage to the new storage. + *****************************************************************/ + + /* if current object storage is not already open, then open it */ + if (! lpSrcLine->m_lpStg) { + LPSTORAGE lpSrcDocStg = ((LPOLEDOC)lpSrcLine->m_lpDoc)->m_lpStg; + + if (! lpSrcDocStg) goto error; + + // open object storage. + lpSrcLine->m_lpStg = OleStdOpenChildStorage( + lpSrcDocStg, + lpSrcLine->m_szStgName, + STGM_READWRITE + ); + if (lpSrcLine->m_lpStg == NULL) { +#if defined( _DEBUG ) + OleDbgAssertSz( + lpSrcLine->m_lpStg != NULL, + "Error opening child stg" + ); +#endif + goto error; + } + } + + hrErr = lpSrcLine->m_lpStg->lpVtbl->CopyTo( + lpSrcLine->m_lpStg, + 0, + NULL, + NULL, + lpDestObjStg + ); + if (hrErr != NOERROR) { + OleDbgOutHResult("WARNING: lpSrcObjStg->CopyTo returned", hrErr); + goto error; + } + + fStatus = OleStdCommitStorage(lpDestObjStg); + + } else { + + /***************************************************************** + ** CASE 2: object IS loaded. + ** we must tell the object to save into the new storage. + *****************************************************************/ + + SCODE sc = S_OK; + LPPERSISTSTORAGE lpPersistStg = lpSrcLine->m_lpPersistStg; + OleDbgAssert(lpPersistStg); + + OLEDBG_BEGIN2("OleSave called\r\n") + hrErr = OleSave(lpPersistStg, lpDestObjStg, FALSE /*fSameAsLoad*/); + OLEDBG_END2 + + if (hrErr != NOERROR) { + OleDbgOutHResult("WARNING: OleSave returned", hrErr); + sc = GetScode(hrErr); + } + + // OLE2NOTE: even if OleSave fails, SaveCompleted must be called. + OLEDBG_BEGIN2("IPersistStorage::SaveCompleted called\r\n") + hrErr=lpPersistStg->lpVtbl->SaveCompleted(lpPersistStg,NULL); + OLEDBG_END2 + + if (hrErr != NOERROR) { + OleDbgOutHResult("WARNING: SaveCompleted returned",hrErr); + if (sc == S_OK) + sc = GetScode(hrErr); + } + + if (sc != S_OK) + goto error; + + } + + OutlineDoc_AddLine(lpDestDoc, (LPLINE)lpDestLine, nIndex); + OleStdVerifyRelease( + (LPUNKNOWN)lpDestObjStg, + "Copied object stg not released" + ); + + return TRUE; + +error: + + // Delete any partially created storage. + if (lpDestObjStg) { + + OleStdVerifyRelease( + (LPUNKNOWN)lpDestObjStg, + "Copied object stg not released" + ); + + CallIStorageDestroyElementA( + lpDestDocStg, + lpDestLine->m_szStgName + ); + + lpDestLine->m_szStgName[0] = '\0'; + } + + // destroy partially created ContainerLine + if (lpDestLine) + ContainerLine_Delete(lpDestLine); + return FALSE; +} + + +/* ContainerLine_UpdateExtent +** -------------------------- +** Update the size of the ContainerLine because the extents of the +** object may have changed. +** +** NOTE: because we are using a Windows OwnerDraw ListBox, we must +** constrain the maximum possible height of a line. the ListBox has +** a limitation (unfortunately) that no line can become larger than +** 255 pixels. thus we force the object to scale maintaining its +** aspect ratio if this maximum line height limit is reached. the +** actual maximum size for an object at 100% Zoom is +** 255 +** +** RETURNS TRUE -- if the extents of the object changed +** FALSE -- if the extents did NOT change +*/ +BOOL ContainerLine_UpdateExtent( + LPCONTAINERLINE lpContainerLine, + LPSIZEL lpsizelHim +) +{ + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerLine->m_lpDoc; + LPLINELIST lpLL = OutlineDoc_GetLineList(lpOutlineDoc); + LPLINE lpLine = (LPLINE)lpContainerLine; + int nIndex = LineList_GetLineIndex(lpLL, lpLine); + UINT nOrgWidthInHimetric = lpLine->m_nWidthInHimetric; + UINT nOrgHeightInHimetric = lpLine->m_nHeightInHimetric; + BOOL fWidthChanged = FALSE; + BOOL fHeightChanged = FALSE; + SIZEL sizelHim; + HRESULT hrErr; + + if (!lpContainerLine || !lpContainerLine->m_lpOleObj) + return FALSE; + + if (lpContainerLine->m_fGuardObj) + return FALSE; // object in process of creation + + OLEDBG_BEGIN3("ContainerLine_UpdateExtent\r\n"); + + lpContainerLine->m_fDoGetExtent = FALSE; + + if (! lpsizelHim) { + /* OLE2NOTE: We want to call IViewObject2::GetExtent instead of + ** IOleObject::GetExtent. IViewObject2::GetExtent method was + ** added in OLE 2.01 release. It always retrieves the + ** extents of the object corresponding to that which will be + ** drawn by calling IViewObject::Draw. Normally, this is + ** determined by the data stored in the data cache. This + ** call will never result in a remoted (LRPC) call. + */ + OLEDBG_BEGIN2("IViewObject2::GetExtent called\r\n") + hrErr = lpContainerLine->m_lpViewObj2->lpVtbl->GetExtent( + lpContainerLine->m_lpViewObj2, + lpContainerLine->m_dwDrawAspect, + -1, /*lindex*/ + NULL, /*ptd*/ + (LPSIZEL)&sizelHim + ); + OLEDBG_END2 + if (hrErr != NOERROR) + sizelHim.cx = sizelHim.cy = 0; + + lpsizelHim = (LPSIZEL)&sizelHim; + } + + if (lpsizelHim->cx == lpContainerLine->m_sizeInHimetric.cx && + lpsizelHim->cy == lpContainerLine->m_sizeInHimetric.cy) { + goto noupdate; + } + + if (lpsizelHim->cx > 0 || lpsizelHim->cy > 0) { + lpContainerLine->m_sizeInHimetric = *lpsizelHim; + } else { + /* object does not have any extents; let's use our container + ** chosen arbitrary size for OLE objects. + */ + lpContainerLine->m_sizeInHimetric.cx = (long)DEFOBJWIDTH; + lpContainerLine->m_sizeInHimetric.cy = (long)DEFOBJHEIGHT; + } + + ContainerLine_SetLineHeightFromObjectExtent( + lpContainerLine, + (LPSIZEL)&lpContainerLine->m_sizeInHimetric); + + // if height of object changed, then reset the height of line in LineList + if (nOrgHeightInHimetric != lpLine->m_nHeightInHimetric) { + LineList_SetLineHeight(lpLL, nIndex, lpLine->m_nHeightInHimetric); + fHeightChanged = TRUE; + } + + fWidthChanged = LineList_RecalcMaxLineWidthInHimetric( + lpLL, + nOrgWidthInHimetric + ); + fWidthChanged |= (nOrgWidthInHimetric != lpLine->m_nWidthInHimetric); + + if (fHeightChanged || fWidthChanged) { + OutlineDoc_ForceRedraw(lpOutlineDoc, TRUE); + + // mark ContainerDoc as now dirty + OutlineDoc_SetModified(lpOutlineDoc, TRUE, TRUE, TRUE); + } + + OLEDBG_END3 + return TRUE; + +noupdate: + OLEDBG_END3 + return FALSE; // No UPDATE necessary +} + + +/* ContainerLine_DoVerb +** -------------------- +** Activate the OLE object and perform a specific verb. +*/ +BOOL ContainerLine_DoVerb( + LPCONTAINERLINE lpContainerLine, + LONG iVerb, + LPMSG lpMsg, + BOOL fMessage, + BOOL fAction +) +{ + HRESULT hrErr; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerLine->m_lpDoc; + RECT rcPosRect; + OLEDBG_BEGIN3("ContainerLine_DoVerb\r\n") + + if (lpContainerLine->m_fGuardObj) { + // object in process of creation--Fail the DoVerb call + hrErr = ResultFromScode(E_FAIL); + goto error; + } + + /* if object is not already loaded, then load it now. objects are + ** loaded lazily in this manner. + */ + if (! lpContainerLine->m_lpOleObj) + ContainerLine_LoadOleObject(lpContainerLine); + + if (! lpContainerLine->m_lpOleObj) { +#if defined( _DEBUG ) + OleDbgAssertSz( + lpContainerLine->m_lpOleObj != NULL, + "OLE object not loaded" + ); +#endif + goto error; + } + +ExecuteDoVerb: + + ContainerLine_GetPosRect(lpContainerLine, (LPRECT)&rcPosRect); + + // run the object + hrErr = ContainerLine_RunOleObject(lpContainerLine); + if (hrErr != NOERROR) + goto error; + + /* Tell object server to perform a "verb". */ + OLEDBG_BEGIN2("IOleObject::DoVerb called\r\n") + hrErr = lpContainerLine->m_lpOleObj->lpVtbl->DoVerb ( + lpContainerLine->m_lpOleObj, + iVerb, + lpMsg, + (LPOLECLIENTSITE)&lpContainerLine->m_OleClientSite, + -1, + OutlineDoc_GetWindow(lpOutlineDoc), + (LPCRECT)&rcPosRect + ); + OLEDBG_END2 + + /* OLE2NOTE: IOleObject::DoVerb may return a success code + ** OLE_S_INVALIDVERB. this SCODE should NOT be considered an + ** error; thus it is important to use the "FAILED" macro to + ** check for an error SCODE. + */ + if (FAILED(GetScode(hrErr))) { + OleDbgOutHResult("WARNING: lpOleObj->DoVerb returned", hrErr); + goto error; + } + +#if defined( INPLACE_CNTR ) + /* OLE2NOTE: we want to keep only 1 inplace server active at any + ** given time. so when we start to do a DoVerb on another line, + ** then we want to shut down the previously activated server. in + ** this way we keep at most one inplace server active at a time. + ** because it is possible that the object we want to do DoVerb + ** on is handled by the same EXE as that of the previously + ** activated server, then we do not want the EXE to be shut down + ** only to be launched again. in order to avoid this we will do + ** the DoVerb BEFORE trying to shutdown the previous object. + */ + if (!g_fInsideOutContainer) { + ContainerDoc_ShutDownLastInPlaceServerIfNotNeeded( + lpContainerLine->m_lpDoc, lpContainerLine); + } +#endif // INPLACE_CNTR + + OLEDBG_END3 + return TRUE; + +error: + + if (lpContainerLine->m_dwLinkType != 0) + lpContainerLine->m_fLinkUnavailable = TRUE; + +#if defined( INPLACE_CNTR ) + /* OLE2NOTE: we want to keep only 1 inplace server active at any + ** given time. so when we start to do a DoVerb on another line, + ** then we want to shut down the previously activated server. in + ** this way we keep at most one inplace server active at a time. + ** even though the DoVerb failed, we will still shutdown the + ** previous server. it is possible that we ran out of memory and + ** that the DoVerb will succeed next time after shutting down + ** the pervious server. + */ + if (!g_fInsideOutContainer) { + ContainerDoc_ShutDownLastInPlaceServerIfNotNeeded( + lpContainerLine->m_lpDoc, lpContainerLine); + } +#endif // INPLACE_CNTR + + /* OLE2NOTE: if an error occurs we must give the appropriate error + ** message box. there are many potential errors that can occur. + ** the OLE2.0 user model has specific guidelines as to the + ** dialogs that should be displayed given the various potential + ** errors (eg. server not registered, unavailable link source. + ** the OLE2UI library includes support for most of the + ** recommended message dialogs. (see OleUIPrompUser function) + */ + if (fMessage) { + BOOL fReDoVerb = ContainerLine_ProcessOleRunError( + lpContainerLine, + hrErr, + fAction, + (lpMsg==NULL && iVerb>=0) /* fMenuInvoked */ + ); + if (fReDoVerb) { + goto ExecuteDoVerb; + } + } + + OLEDBG_END3 + return FALSE; +} + + + +/* ContainerLine_ProcessOleRunError + * -------------------------------- + * + * Handle the various errors possible when attempting OleRun of an object. + * Popup up appropriate message according to the error and/or take action + * specified button pressed by the user. + * + * OLE2NOTE: The OLE 2.0 User Interface Guidelines specify the messages + * that should be given for the following situations: + * 1. Link Source Unavailable...goto Links dialog + * 2. Server Not Registered...goto Convert dialog + * 3. Link Type Changed + * 4. Server Not Found + * + * Returns: TRUE -- repeat IOleObject::DoVerb call. + * FALSE -- do NOT repeat IOleObject::DoVerb call. + * + * Comments: + * (see LinkTypeChanged case) + */ +BOOL ContainerLine_ProcessOleRunError( + LPCONTAINERLINE lpContainerLine, + HRESULT hrErr, + BOOL fAction, + BOOL fMenuInvoked +) +{ + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerLine->m_lpDoc; + HWND hwndParent = OutlineDoc_GetWindow(lpOutlineDoc); + SCODE sc = GetScode(hrErr); + BOOL fReDoVerb = FALSE; + + OleDbgOutHResult("ProcessError", hrErr); + if ((sc >= MK_E_FIRST) && (sc <= MK_E_LAST)) + goto LinkSourceUnavailable; + if (sc == OLE_E_CANT_BINDTOSOURCE) + goto LinkSourceUnavailable; + if (sc == STG_E_PATHNOTFOUND) + goto LinkSourceUnavailable; + if (sc == REGDB_E_CLASSNOTREG) + goto ServerNotReg; + if (sc == OLE_E_STATIC) + goto ServerNotReg; // user dblclk'ed a static object w/ no svr reg'd + if (sc == OLE_E_CLASSDIFF) + goto LinkTypeChanged; + if (sc == CO_E_APPDIDNTREG) + goto ServerNotFound; + if (sc == CO_E_APPNOTFOUND) + goto ServerNotFound; + if (sc == E_OUTOFMEMORY) + goto OutOfMemory; + + if (ContainerLine_IsOleLink(lpContainerLine)) + goto LinkSourceUnavailable; + else + goto ServerNotFound; + + +/************************************************************************* +** Error handling routines ** +*************************************************************************/ +LinkSourceUnavailable: + if (ID_PU_LINKS == OleUIPromptUser( + (WORD)IDD_LINKSOURCEUNAVAILABLE, + hwndParent, + (LPSTR)APPNAME)) { + if (fAction) { + ContainerDoc_EditLinksCommand(lpContainerLine->m_lpDoc); + } + } + return fReDoVerb; + +ServerNotReg: + { + LPSTR lpszUserType = NULL; + CLIPFORMAT cfFormat; // not used + + hrErr = ReadFmtUserTypeStgA( + lpContainerLine->m_lpStg, &cfFormat, &lpszUserType); + + if (ID_PU_CONVERT == OleUIPromptUser( + (WORD)IDD_SERVERNOTREG, + hwndParent, + (LPSTR)APPNAME, + (hrErr == NOERROR) ? lpszUserType : (LPSTR)"Unknown Object")) { + if (fAction) { + ContainerDoc_ConvertCommand( + lpContainerLine->m_lpDoc, + TRUE // fMustActivate + ); + } + } + + if (lpszUserType) + OleStdFreeString(lpszUserType, NULL); + + return fReDoVerb; + } + + +LinkTypeChanged: + { + /* OLE2NOTE: If IOleObject::DoVerb is executed on a Link object and it + ** returns OLE_E_CLASSDIFF because the link source is no longer + ** the expected class, then if the verb is a semantically + ** defined verb (eg. OLEIVERB_PRIMARY, OLEIVERB_SHOW, + ** OLEIVERB_OPEN, etc.), then the link should be re-created with + ** the new link source and the same verb executed on the new + ** link. there is no need to give a message to the user. if the + ** user had selected a verb from the object's verb menu + ** (fMenuInvoked==TRUE), then we can not be certain of the + ** semantics of the verb and whether the new link can still + ** support the verb. in this case the user is given a prompt + ** telling him to "choose a different command offered by the new + ** type". + */ + + LPSTR lpszUserType = NULL; + + if (fMenuInvoked) { + hrErr = CallIOleObjectGetUserTypeA( + lpContainerLine->m_lpOleObj,USERCLASSTYPE_FULL, &lpszUserType); + + OleUIPromptUser( + (WORD)IDD_LINKTYPECHANGED, + hwndParent, + (LPSTR)APPNAME, + (hrErr == NOERROR) ? lpszUserType : (LPSTR)"Unknown Object" + ); + } else { + fReDoVerb = TRUE; + } + ContainerLine_ReCreateLinkBecauseClassDiff(lpContainerLine); + + if (lpszUserType) + OleStdFreeString(lpszUserType, NULL); + + return fReDoVerb; + } + +ServerNotFound: + + OleUIPromptUser( + (WORD)IDD_SERVERNOTFOUND, + hwndParent, + (LPSTR)APPNAME); + return fReDoVerb; + +OutOfMemory: + + OleUIPromptUser( + (WORD)IDD_OUTOFMEMORY, + hwndParent, + (LPSTR)APPNAME); + return fReDoVerb; +} + + +/* ContainerLine_ReCreateLinkBecauseClassDiff +** ------------------------------------------ +** Re-create the link. The existing link was created when +** the moniker binds to a link source bound of a different class +** than the same moniker currently binds to. the link may be a +** special link object specifically used with the old link +** source class. thus the link object needs to be re-created to +** give the new link source the opportunity to create its own +** special link object. (see description "Custom Link Source") +*/ +HRESULT ContainerLine_ReCreateLinkBecauseClassDiff( + LPCONTAINERLINE lpContainerLine +) +{ + LPOLELINK lpOleLink = lpContainerLine->m_lpOleLink; + HGLOBAL hMetaPict = NULL; + LPMONIKER lpmkLinkSrc = NULL; + SCODE sc = E_FAIL; + HRESULT hrErr; + + if (lpOleLink && + lpOleLink->lpVtbl->GetSourceMoniker( + lpOleLink, (LPMONIKER FAR*)&lpmkLinkSrc) == NOERROR) { + + BOOL fDisplayAsIcon = + (lpContainerLine->m_dwDrawAspect==DVASPECT_ICON); + STGMEDIUM medium; + LPDATAOBJECT lpDataObj = NULL; + DWORD dwOleRenderOpt; + FORMATETC renderFmtEtc; + LPFORMATETC lpRenderFmtEtc = NULL; + + // get the current icon if object is displayed as icon + if (fDisplayAsIcon && + (lpDataObj = (LPDATAOBJECT)OleStdQueryInterface( (LPUNKNOWN) + lpContainerLine->m_lpOleObj,&IID_IDataObject)) != NULL ) { + hMetaPict = OleStdGetData( + lpDataObj, CF_METAFILEPICT, NULL, DVASPECT_ICON, &medium); + OleStdRelease((LPUNKNOWN)lpDataObj); + } + + if (fDisplayAsIcon && hMetaPict) { + // a special icon should be used. first we create the object + // OLERENDER_NONE. then we stuff the special icon into the cache. + + dwOleRenderOpt = OLERENDER_NONE; + + } else if (fDisplayAsIcon && hMetaPict == NULL) { + // the object's default icon should be used + + dwOleRenderOpt = OLERENDER_DRAW; + lpRenderFmtEtc = (LPFORMATETC)&renderFmtEtc; + SETFORMATETC(renderFmtEtc,0,DVASPECT_ICON,NULL,TYMED_NULL,-1); + + } else { + // create standard DVASPECT_CONTENT/OLERENDER_DRAW object + dwOleRenderOpt = OLERENDER_DRAW; + } + + // unload original link object + ContainerLine_UnloadOleObject(lpContainerLine, OLECLOSE_SAVEIFDIRTY); + + // delete entire contents of the current object's storage + OleStdDestroyAllElements(lpContainerLine->m_lpStg); + + OLEDBG_BEGIN2("OleCreateLink called\r\n") + hrErr = OleCreateLink ( + lpmkLinkSrc, + &IID_IOleObject, + dwOleRenderOpt, + lpRenderFmtEtc, + (LPOLECLIENTSITE)&lpContainerLine->m_OleClientSite, + lpContainerLine->m_lpStg, + (LPVOID FAR*)&lpContainerLine->m_lpOleObj + ); + OLEDBG_END2 + + if (hrErr == NOERROR) { + if (! ContainerLine_SetupOleObject( + lpContainerLine, fDisplayAsIcon, hMetaPict) ) { + + // ERROR: setup of the new link failed. + // revert the storage to restore the original link. + ContainerLine_UnloadOleObject( + lpContainerLine, OLECLOSE_NOSAVE); + lpContainerLine->m_lpStg->lpVtbl->Revert( + lpContainerLine->m_lpStg); + sc = E_FAIL; + } else { + sc = S_OK; // IT WORKED! + + } + } + else { + sc = GetScode(hrErr); + OleDbgOutHResult("OleCreateLink returned", hrErr); + // ERROR: Re-creating the link failed. + // revert the storage to restore the original link. + lpContainerLine->m_lpStg->lpVtbl->Revert( + lpContainerLine->m_lpStg); + } + } + + if (hMetaPict) + OleUIMetafilePictIconFree(hMetaPict); // clean up metafile + return ResultFromScode(sc); +} + +/* ContainerLine_GetOleObject +** -------------------------- +** return pointer to desired interface of embedded/linked object. +** +** NOTE: this function causes an AddRef to the object. when the caller is +** finished with the object, it must call Release. +** this function does not AddRef the ContainerLine object. +*/ +LPUNKNOWN ContainerLine_GetOleObject( + LPCONTAINERLINE lpContainerLine, + REFIID riid +) +{ + /* if object is not already loaded, then load it now. objects are + ** loaded lazily in this manner. + */ + if (! lpContainerLine->m_lpOleObj) + ContainerLine_LoadOleObject(lpContainerLine); + + if (lpContainerLine->m_lpOleObj) + return OleStdQueryInterface( + (LPUNKNOWN)lpContainerLine->m_lpOleObj, + riid + ); + else + return NULL; +} + + + +/* ContainerLine_RunOleObject +** -------------------------- +** Load and run the object. Upon running and if size of object has changed, +** use SetExtent to change to new size. +** +*/ +HRESULT ContainerLine_RunOleObject(LPCONTAINERLINE lpContainerLine) +{ + LPLINE lpLine = (LPLINE)lpContainerLine; + SIZEL sizelNew; + HRESULT hrErr; + HCURSOR hPrevCursor; + + if (! lpContainerLine) + return NOERROR; + + if (lpContainerLine->m_fGuardObj) { + // object in process of creation--Fail to Run the object + return ResultFromScode(E_FAIL); + } + + if (lpContainerLine->m_lpOleObj && + OleIsRunning(lpContainerLine->m_lpOleObj)) + return NOERROR; // object already running + + // this may take a while, put up hourglass cursor + hPrevCursor = SetCursor(LoadCursor(NULL, IDC_WAIT)); + OLEDBG_BEGIN3("ContainerLine_RunOleObject\r\n") + + if (! lpContainerLine->m_lpOleObj) { + if (! ContainerLine_LoadOleObject(lpContainerLine)) + return ResultFromScode(E_OUTOFMEMORY); // Error: couldn't load obj + } + + OLEDBG_BEGIN2("OleRun called\r\n") + hrErr = OleRun((LPUNKNOWN)lpContainerLine->m_lpOleObj); + OLEDBG_END2 + + if (hrErr != NOERROR) { + SetCursor(hPrevCursor); // restore original cursor + + OleDbgOutHResult("OleRun returned", hrErr); + OLEDBG_END3 + return hrErr; + } + + if (lpContainerLine->m_fDoSetExtent) { + /* OLE2NOTE: the OLE object was resized when it was not running + ** and the object did not have the OLEMISC_RECOMPOSEONRESIZE + ** bit set. if it had, the object would have been run + ** immediately when it was resized. this flag indicates that + ** the object does something other than simple scaling when + ** it is resized. because the object is being run now, we + ** will call IOleObject::SetExtent. + */ + lpContainerLine->m_fDoSetExtent = FALSE; + + // the size stored in our Line includes the border around the object. + // we must subtract the border to get the size of the object itself. + sizelNew.cx = lpLine->m_nWidthInHimetric; + sizelNew.cy = lpLine->m_nHeightInHimetric; + + if ((sizelNew.cx != lpContainerLine->m_sizeInHimetric.cx) || + (sizelNew.cy != lpContainerLine->m_sizeInHimetric.cy)) { + + OLEDBG_BEGIN2("IOleObject::SetExtent called\r\n") + lpContainerLine->m_lpOleObj->lpVtbl->SetExtent( + lpContainerLine->m_lpOleObj, + lpContainerLine->m_dwDrawAspect, + (LPSIZEL)&sizelNew + ); + OLEDBG_END2 + } + } + + SetCursor(hPrevCursor); // restore original cursor + + OLEDBG_END3 + return NOERROR; + +} + + +/* ContainerLine_IsOleLink +** ----------------------- +** +** return TRUE if the ContainerLine has an OleLink. +** FALSE if the ContainerLine has an embedding +*/ +BOOL ContainerLine_IsOleLink(LPCONTAINERLINE lpContainerLine) +{ + if (!lpContainerLine) + return FALSE; + + return (lpContainerLine->m_dwLinkType != 0); +} + + +/* ContainerLine_Draw +** ------------------ +** +** Draw a ContainerLine object on a DC. +** +** Parameters: +** hDC - DC to which the line will be drawn +** lpRect - the object rect in logical coordinates +** lpRectWBounds - bounding rect of the metafile underneath hDC +** (NULL if hDC is not a metafile DC) +** fHighlight - TRUE if line has selection highlight +*/ +void ContainerLine_Draw( + LPCONTAINERLINE lpContainerLine, + HDC hDC, + LPRECT lpRect, + LPRECT lpRectWBounds, + BOOL fHighlight +) +{ + LPLINE lpLine = (LPLINE) lpContainerLine; + HRESULT hrErr = NOERROR; + RECTL rclHim; + RECTL rclHimWBounds; + RECT rcHim; + + if (lpContainerLine->m_fGuardObj) { + // object in process of creation--do NOT try to draw + return; + } + + /* if object is not already loaded, then load it now. objects are + ** loaded lazily in this manner. + */ + if (! lpContainerLine->m_lpViewObj2) { + if (! ContainerLine_LoadOleObject(lpContainerLine)) + return; // Error: could not load object + } + + if (lpRectWBounds) { + rclHimWBounds.left = (long) lpRectWBounds->left; + rclHimWBounds.bottom = (long) lpRectWBounds->bottom; + rclHimWBounds.top = (long) lpRectWBounds->top; + rclHimWBounds.right = (long) lpRectWBounds->right; + } + + /* construct bounds rectangle for the object. + ** offset origin for object to correct tab indentation + */ + rclHim.left = (long) lpRect->left; + rclHim.bottom = (long) lpRect->bottom; + rclHim.top = (long) lpRect->top; + rclHim.right = (long) lpRect->right; + + rclHim.left += (long) ((LPLINE)lpContainerLine)->m_nTabWidthInHimetric; + rclHim.right += (long) ((LPLINE)lpContainerLine)->m_nTabWidthInHimetric; + +#if defined( INPLACE_CNTR ) + /* OLE2NOTE: if the OLE object currently has a visible in-place + ** window, then we do NOT want to draw on top of its window. + ** this could interfere with the object's display. + */ + if ( !lpContainerLine->m_fIpVisible ) +#endif + { + hrErr = lpContainerLine->m_lpViewObj2->lpVtbl->Draw( + lpContainerLine->m_lpViewObj2, + lpContainerLine->m_dwDrawAspect, + -1, + NULL, + NULL, + NULL, + hDC, + (LPRECTL)&rclHim, + (lpRectWBounds ? (LPRECTL)&rclHimWBounds : NULL), + NULL, + 0 + ); + if (hrErr != NOERROR) + OleDbgOutHResult("IViewObject::Draw returned", hrErr); + + if (lpContainerLine->m_fObjWinOpen) + { + rcHim.left = (int) rclHim.left; + rcHim.top = (int) rclHim.top; + rcHim.right = (int) rclHim.right; + rcHim.bottom = (int) rclHim.bottom; + + /* OLE2NOTE: if the object servers window is Open (ie. not active + ** in-place) then we must shade the object in our document to + ** indicate to the user that the object is open elsewhere. + */ + OleUIDrawShading((LPRECT)&rcHim, hDC, OLEUI_SHADE_FULLRECT, 0); + } + } + + /* if the object associated with the ContainerLine is an automatic + ** link then try to connect it with its LinkSource if the + ** LinkSource is already running. we do not want to force the + ** LinkSource to run. + ** + ** OLE2NOTE: a sophistocated container will want to continually + ** attempt to connect its automatic links. OLE does NOT + ** automatically connect links when link sources become + ** available. some containers will want to attempt to connect + ** its links as part of idle time processing. another strategy + ** is to attempt to connect an automatic link every time it is + ** drawn on the screen. (this is the strategy used by this + ** CntrOutl sample application.) + */ + if (lpContainerLine->m_dwLinkType == OLEUPDATE_ALWAYS) + ContainerLine_BindLinkIfLinkSrcIsRunning(lpContainerLine); + + return; +} + + +void ContainerLine_DrawSelHilight( + LPCONTAINERLINE lpContainerLine, + HDC hDC, // MM_TEXT mode + LPRECT lprcPix, // listbox rect + UINT itemAction, + UINT itemState +) +{ + LPLINE lpLine = (LPLINE)lpContainerLine; + RECT rcObj; + DWORD dwFlags = OLEUI_HANDLES_INSIDE | OLEUI_HANDLES_USEINVERSE; + int nHandleSize; + LPCONTAINERDOC lpContainerDoc; + + if (!lpContainerLine || !hDC || !lprcPix) + return; + + lpContainerDoc = lpContainerLine->m_lpDoc; + + // Get size of OLE object + ContainerLine_GetOleObjectRectInPixels(lpContainerLine, (LPRECT)&rcObj); + + nHandleSize = GetProfileInt("windows", "oleinplaceborderwidth", + DEFAULT_HATCHBORDER_WIDTH) + 1; + + OleUIDrawHandles((LPRECT)&rcObj, hDC, dwFlags, nHandleSize, TRUE); +} + +/* InvertDiffRect +** -------------- +** +** Paint the surrounding of the Obj rect black but within lprcPix +** (similar to the lprcPix minus lprcObj) +*/ +static void InvertDiffRect(LPRECT lprcPix, LPRECT lprcObj, HDC hDC) +{ + RECT rcBlack; + + // draw black in all space outside of object's rectangle + rcBlack.top = lprcPix->top; + rcBlack.bottom = lprcPix->bottom; + + rcBlack.left = lprcPix->left + 1; + rcBlack.right = lprcObj->left - 1; + InvertRect(hDC, (LPRECT)&rcBlack); + + rcBlack.left = lprcObj->right + 1; + rcBlack.right = lprcPix->right - 1; + InvertRect(hDC, (LPRECT)&rcBlack); + + rcBlack.top = lprcPix->top; + rcBlack.bottom = lprcPix->top + 1; + rcBlack.left = lprcObj->left - 1; + rcBlack.right = lprcObj->right + 1; + InvertRect(hDC, (LPRECT)&rcBlack); + + rcBlack.top = lprcPix->bottom; + rcBlack.bottom = lprcPix->bottom - 1; + rcBlack.left = lprcObj->left - 1; + rcBlack.right = lprcObj->right + 1; + InvertRect(hDC, (LPRECT)&rcBlack); +} + + +/* Edit the ContainerLine line object. +** returns TRUE if line was changed +** FALSE if the line was NOT changed +*/ +BOOL ContainerLine_Edit(LPCONTAINERLINE lpContainerLine, HWND hWndDoc,HDC hDC) +{ + ContainerLine_DoVerb(lpContainerLine, OLEIVERB_PRIMARY, NULL, TRUE, TRUE); + + /* assume object was NOT changed, if it was obj will send Changed + ** or Saved notification. + */ + return FALSE; +} + + + +/* ContainerLine_SetHeightInHimetric +** --------------------------------- +** +** Set the height of a ContainerLine object. The widht will be changed +** to keep the aspect ratio +*/ +void ContainerLine_SetHeightInHimetric(LPCONTAINERLINE lpContainerLine, int nHeight) +{ + LPLINE lpLine = (LPLINE)lpContainerLine; + SIZEL sizelOleObject; + HRESULT hrErr; + + if (!lpContainerLine) + return; + + if (lpContainerLine->m_fGuardObj) { + // object in process of creation--Fail to set the Height + return; + } + + if (nHeight != -1) { + BOOL fMustClose = FALSE; + BOOL fMustRun = FALSE; + + /* if object is not already loaded, then load it now. objects are + ** loaded lazily in this manner. + */ + if (! lpContainerLine->m_lpOleObj) + ContainerLine_LoadOleObject(lpContainerLine); + + // the height argument specifies the desired height for the Line. + sizelOleObject.cy = nHeight; + + // we will calculate the corresponding width for the object by + // maintaining the current aspect ratio of the object. + sizelOleObject.cx = (int)(sizelOleObject.cy * + lpContainerLine->m_sizeInHimetric.cx / + lpContainerLine->m_sizeInHimetric.cy); + + /* OLE2NOTE: if the OLE object is already running then we can + ** immediately call SetExtent. But, if the object is NOT + ** currently running then we will check if the object + ** indicates that it is normally recomposes itself on + ** resizing. ie. that the object does not simply scale its + ** display when it it resized. if so then we will force the + ** object to run so that we can call IOleObject::SetExtent. + ** SetExtent does not have any effect if the object is only + ** loaded. if the object does NOT indicate that it + ** recomposes on resize (OLEMISC_RECOMPOSEONRESIZE) then we + ** will wait till the next time that the object is run to + ** call SetExtent. we will store a flag in the ContainerLine + ** to indicate that a SetExtent is necessary. It is + ** necessary to persist this flag. + */ + if (! OleIsRunning(lpContainerLine->m_lpOleObj)) { + DWORD dwStatus; + + OLEDBG_BEGIN2("IOleObject::GetMiscStatus called\r\n") + hrErr = lpContainerLine->m_lpOleObj->lpVtbl->GetMiscStatus( + lpContainerLine->m_lpOleObj, + lpContainerLine->m_dwDrawAspect, + (LPDWORD)&dwStatus + ); + OLEDBG_END2 + if (hrErr == NOERROR && (dwStatus & OLEMISC_RECOMPOSEONRESIZE)) { + // force the object to run + ContainerLine_RunOleObject(lpContainerLine); + fMustClose = TRUE; + } else { + /* the OLE object is NOT running and does NOT + ** recompose on resize. simply scale the object now + ** and do the SetExtent the next time the object is + ** run. we set the Line to the new size even though + ** the object's extents have not been changed. + ** this has the result of scaling the object's + ** display to the new size. + */ + lpContainerLine->m_fDoSetExtent = TRUE; + ContainerLine_SetLineHeightFromObjectExtent( + lpContainerLine, (LPSIZEL)&sizelOleObject); + return; + } + } + + OLEDBG_BEGIN2("IOleObject::SetExtent called\r\n") + hrErr = lpContainerLine->m_lpOleObj->lpVtbl->SetExtent( + lpContainerLine->m_lpOleObj, + lpContainerLine->m_dwDrawAspect, + (LPSIZEL)&sizelOleObject); + OLEDBG_END2 + + if (hrErr != NOERROR) { + /* OLE Object refuses to take on the new extents. Set the + ** Line to the new size even though the object refused + ** the new extents. this has the result of scaling the + ** object's display to the new size. + ** + ** if the object HAD accepted the new extents, then it + ** will send out an OnViewChange/OnDataChange + ** notification. this results in our container receiving + ** an OnViewChange notification; the line height will be + ** reset when this notification is received. + */ + ContainerLine_SetLineHeightFromObjectExtent( + lpContainerLine, (LPSIZEL)&sizelOleObject); + } + + if (fMustClose) + ContainerLine_CloseOleObject( + lpContainerLine, OLECLOSE_SAVEIFDIRTY); + } + else { + /* Set the line to default height given the natural (unscaled) + ** extents of the OLE object. + */ + ContainerLine_SetLineHeightFromObjectExtent( + lpContainerLine,(LPSIZEL)&lpContainerLine->m_sizeInHimetric); + } + +} + + +/* ContainerLine_SetLineHeightFromObjectExtent + * + * Purpose: + * Calculate the corresponding line height from the OleObject size + * Scale the line height to fit the limit if necessary + * + * Parameters: + * lpsizelOleObject pointer to size of OLE Object + * + * Returns: + * nil + */ +void ContainerLine_SetLineHeightFromObjectExtent( + LPCONTAINERLINE lpContainerLine, + LPSIZEL lpsizelOleObject +) +{ + LPLINE lpLine = (LPLINE)lpContainerLine; + + UINT uMaxObjectHeight = XformHeightInPixelsToHimetric(NULL, + LISTBOX_HEIGHT_LIMIT); + + if (!lpContainerLine || !lpsizelOleObject) + return; + + if (lpContainerLine->m_fGuardObj) { + // object in process of creation--Fail to set the Height + return; + } + + lpLine->m_nWidthInHimetric = (int)lpsizelOleObject->cx; + lpLine->m_nHeightInHimetric = (int)lpsizelOleObject->cy; + + // Rescale the object if height is greater than the limit + if (lpLine->m_nHeightInHimetric > (UINT)uMaxObjectHeight) { + + lpLine->m_nWidthInHimetric = (UINT) + ((long)lpLine->m_nWidthInHimetric * + (long)uMaxObjectHeight / + (long)lpLine->m_nHeightInHimetric); + + lpLine->m_nHeightInHimetric = uMaxObjectHeight; + } + +} + + +/* ContainerLine_SaveToStg +** ----------------------- +** Save a given ContainerLine and associated OLE object to an IStorage*. +*/ +BOOL ContainerLine_SaveToStm( + LPCONTAINERLINE lpContainerLine, + LPSTREAM lpLLStm +) +{ + CONTAINERLINERECORD_ONDISK objLineRecord; + ULONG nWritten; + HRESULT hrErr; + + // Compilers should handle aligment correctly + lstrcpy(objLineRecord.m_szStgName, lpContainerLine->m_szStgName); + objLineRecord.m_fMonikerAssigned = (USHORT) lpContainerLine->m_fMonikerAssigned; + objLineRecord.m_dwDrawAspect = lpContainerLine->m_dwDrawAspect; + objLineRecord.m_sizeInHimetric = lpContainerLine->m_sizeInHimetric; + objLineRecord.m_dwLinkType = lpContainerLine->m_dwLinkType; + objLineRecord.m_fDoSetExtent = (USHORT) lpContainerLine->m_fDoSetExtent; + + /* write line record */ + hrErr = lpLLStm->lpVtbl->Write( + lpLLStm, + (LPVOID)&objLineRecord, + sizeof(objLineRecord), + &nWritten + ); + + if (hrErr != NOERROR) { + OleDbgAssertSz(hrErr == NOERROR,"Could not write to LineList stream"); + return FALSE; + } + + return TRUE; +} + + +/* ContainerLine_SaveOleObjectToStg +** -------------------------------- +** Save the OLE object associated with the ContainerLine to an IStorage*. +*/ +BOOL ContainerLine_SaveOleObjectToStg( + LPCONTAINERLINE lpContainerLine, + LPSTORAGE lpSrcStg, + LPSTORAGE lpDestStg, + BOOL fRemember +) +{ + HRESULT hrErr; + SCODE sc = S_OK; + BOOL fStatus; + BOOL fSameAsLoad = (lpSrcStg==lpDestStg ? TRUE : FALSE); + LPSTORAGE lpObjDestStg; + + if (lpContainerLine->m_fGuardObj) { + // object in process of creation--Fail to save + return FALSE; + } + + if (! lpContainerLine->m_lpOleObj) { + + /***************************************************************** + ** CASE 1: object is NOT loaded. + *****************************************************************/ + + if (fSameAsLoad) { + /************************************************************* + ** CASE 1A: we are saving to the current storage. because + ** the object is not loaded, it is up-to-date + ** (ie. nothing to do). + *************************************************************/ + + ; + + } else { + /************************************************************* + ** CASE 1B: we are saving to a new storage. because + ** the object is not loaded, we can simply copy the + ** object's current storage to the new storage. + *************************************************************/ + + /* if current object storage is not already open, then open it */ + if (! lpContainerLine->m_lpStg) { + lpContainerLine->m_lpStg = OleStdOpenChildStorage( + lpSrcStg, + lpContainerLine->m_szStgName, + STGM_READWRITE + ); + if (lpContainerLine->m_lpStg == NULL) { +#if defined( _DEBUG ) + OleDbgAssertSz( + lpContainerLine->m_lpStg != NULL, + "Error opening child stg" + ); +#endif + return FALSE; + } + } + + /* Create a child storage inside the destination storage. */ + lpObjDestStg = OleStdCreateChildStorage( + lpDestStg, + lpContainerLine->m_szStgName + ); + + if (lpObjDestStg == NULL) { +#if defined( _DEBUG ) + OleDbgAssertSz( + lpObjDestStg != NULL, + "Could not create obj storage!" + ); +#endif + return FALSE; + } + + hrErr = lpContainerLine->m_lpStg->lpVtbl->CopyTo( + lpContainerLine->m_lpStg, + 0, + NULL, + NULL, + lpObjDestStg + ); + // REVIEW: should we handle error here? + fStatus = OleStdCommitStorage(lpObjDestStg); + + /* if we are supposed to remember this storage as the new + ** storage for the object, then release the old one and + ** save the new one. else, throw away the new one. + */ + if (fRemember) { + OleStdVerifyRelease( + (LPUNKNOWN)lpContainerLine->m_lpStg, + "Original object stg not released" + ); + lpContainerLine->m_lpStg = lpObjDestStg; + } else { + OleStdVerifyRelease( + (LPUNKNOWN)lpObjDestStg, + "Copied object stg not released" + ); + } + } + + } else { + + /***************************************************************** + ** CASE 2: object IS loaded. + *****************************************************************/ + + if (fSameAsLoad) { + /************************************************************* + ** CASE 2A: we are saving to the current storage. if the object + ** is not dirty, then the current storage is up-to-date + ** (ie. nothing to do). + *************************************************************/ + + LPPERSISTSTORAGE lpPersistStg = lpContainerLine->m_lpPersistStg; + OleDbgAssert(lpPersistStg); + + hrErr = lpPersistStg->lpVtbl->IsDirty(lpPersistStg); + + /* OLE2NOTE: we will only accept an explicit "no i + ** am NOT dirty statement" (ie. S_FALSE) as an + ** indication that the object is clean. eg. if + ** the object returns E_NOTIMPL we must + ** interpret it as the object IS dirty. + */ + if (GetScode(hrErr) != S_FALSE) { + + /* OLE object IS dirty */ + + OLEDBG_BEGIN2("OleSave called\r\n") + hrErr = OleSave( + lpPersistStg, lpContainerLine->m_lpStg, fSameAsLoad); + OLEDBG_END2 + + if (hrErr != NOERROR) { + OleDbgOutHResult("WARNING: OleSave returned", hrErr); + sc = GetScode(hrErr); + } + + // OLE2NOTE: if OleSave fails, SaveCompleted must be called. + OLEDBG_BEGIN2("IPersistStorage::SaveCompleted called\r\n") + hrErr=lpPersistStg->lpVtbl->SaveCompleted(lpPersistStg,NULL); + OLEDBG_END2 + + if (hrErr != NOERROR) { + OleDbgOutHResult("WARNING: SaveCompleted returned",hrErr); + if (sc == S_OK) + sc = GetScode(hrErr); + } + + if (sc != S_OK) + return FALSE; + } + + } else { + /************************************************************* + ** CASE 2B: we are saving to a new storage. we must + ** tell the object to save into the new storage. + *************************************************************/ + + LPPERSISTSTORAGE lpPersistStg = lpContainerLine->m_lpPersistStg; + + if (! lpPersistStg) return FALSE; + + /* Create a child storage inside the destination storage. */ + lpObjDestStg = OleStdCreateChildStorage( + lpDestStg, + lpContainerLine->m_szStgName + ); + + if (lpObjDestStg == NULL) { +#if defined( _DEBUG ) + OleDbgAssertSz( + lpObjDestStg != NULL, + "Could not create object storage!" + ); +#endif + return FALSE; + } + + OLEDBG_BEGIN2("OleSave called\r\n") + hrErr = OleSave(lpPersistStg, lpObjDestStg, fSameAsLoad); + OLEDBG_END2 + + // OLE2NOTE: even if OleSave fails, must still call SaveCompleted + if (hrErr != NOERROR) { + OleDbgOutHResult("WARNING: OleSave returned", hrErr); + sc = GetScode(hrErr); + } + + /* OLE2NOTE: a root level container should immediately + ** call IPersistStorage::SaveCompleted after calling + ** OleSave. a nested level container should not call + ** SaveCompleted now, but must wait until SaveCompleted + ** is call on it by its container. since our container + ** is not a container/server, then we always call + ** SaveComplete here. + ** + ** if this is a SaveAs operation, then we need to pass + ** the lpStg back in SaveCompleted to inform the object + ** of its new storage that it may hold on to. if this is + ** a Save or a SaveCopyAs operation, then we simply pass + ** NULL in SaveCompleted; the object can continue to hold + ** its current storage. if an error occurs during the + ** OleSave call we must still call SaveCompleted but we + ** must pass NULL. + */ + OLEDBG_BEGIN2("IPersistStorage::SaveCompleted called\r\n") + hrErr = lpPersistStg->lpVtbl->SaveCompleted( + lpPersistStg, + ((FAILED(sc) || !fRemember) ? NULL : lpObjDestStg) + ); + OLEDBG_END2 + + if (hrErr != NOERROR) { + OleDbgOutHResult("WARNING: SaveCompleted returned",hrErr); + if (sc == S_OK) + sc = GetScode(hrErr); + } + + if (sc != S_OK) { + OleStdVerifyRelease( + (LPUNKNOWN)lpObjDestStg, + "Copied object stg not released" + ); + return FALSE; + } + + /* if we are supposed to remember this storage as the new + ** storage for the object, then release the old one and + ** save the new one. else, throw away the new one. + */ + if (fRemember) { + OleStdVerifyRelease( + (LPUNKNOWN)lpContainerLine->m_lpStg, + "Original object stg not released" + ); + lpContainerLine->m_lpStg = lpObjDestStg; + } else { + OleStdVerifyRelease( + (LPUNKNOWN)lpObjDestStg, + "Copied object stg not released" + ); + } + } + } + + /* OLE2NOTE: after saving an OLE object it is possible that it sent + ** an OnViewChange notification because it had been modified. in + ** this situation it is possible that the extents of the object + ** have changed. if so we want to relayout the space for the + ** object immediately so that the extent information saved with + ** the ContainerLine match the data saved with the OLE object + ** itself. + */ + if (lpContainerLine->m_fDoGetExtent) { + BOOL fSizeChanged = ContainerLine_UpdateExtent(lpContainerLine, NULL); +#if defined( INPLACE_CNTR ) + /* if the extents of this ContainerLine have changed, then we + ** need to reset the fDoGetExtent flag to TRUE so that later + ** when ContainerDoc_UpdateExtentOfAllOleObjects is called + ** (when the WM_U_UPDATEOBJECTEXTENT message is processed), + ** it is recognized that the extents of this line have + ** changed. if any line changes size, then any in-place + ** active object below this line must be told to update the + ** position of their windows (via SetObjectRects -- see + ** ContainerDoc_UpdateInPlaceObjectRects function). + */ + lpContainerLine->m_fDoGetExtent = fSizeChanged; +#endif + } + + return TRUE; +} + + +/* ContainerLine_LoadFromStg +** ------------------------- +** Create a ContainerLine object and initialize it with data that +** was previously writen to an IStorage*. this function does not +** immediately OleLoad the associated OLE object, only the data of +** the ContainerLine object itself is loaded from the IStorage*. +*/ +LPLINE ContainerLine_LoadFromStg( + LPSTORAGE lpSrcStg, + LPSTREAM lpLLStm, + LPOUTLINEDOC lpDestDoc +) +{ + HDC hDC; + LPLINELIST lpDestLL = &lpDestDoc->m_LineList; + ULONG nRead; + HRESULT hrErr; + LPCONTAINERLINE lpContainerLine; + CONTAINERLINERECORD_ONDISK objLineRecord; + + lpContainerLine=(LPCONTAINERLINE) New((DWORD)sizeof(CONTAINERLINE)); + if (lpContainerLine == NULL) { + OleDbgAssertSz(lpContainerLine!=NULL,"Error allocating ContainerLine"); + return NULL; + } + + hDC = LineList_GetDC(lpDestLL); + ContainerLine_Init(lpContainerLine, 0, hDC); + LineList_ReleaseDC(lpDestLL, hDC); + + /* OLE2NOTE: In order to have a stable ContainerLine object we must + ** AddRef the object's refcnt. this will be later released when + ** the ContainerLine is deleted. + */ + ContainerLine_AddRef(lpContainerLine); + + lpContainerLine->m_lpDoc = (LPCONTAINERDOC) lpDestDoc; + + /* read line record */ + hrErr = lpLLStm->lpVtbl->Read( + lpLLStm, + (LPVOID)&objLineRecord, + sizeof(objLineRecord), + &nRead + ); + + if (hrErr != NOERROR) { + OleDbgAssertSz(hrErr==NOERROR, "Could not read from LineList stream"); + goto error; + } + + // Compilers should handle aligment correctly + lstrcpy(lpContainerLine->m_szStgName, objLineRecord.m_szStgName); + lpContainerLine->m_fMonikerAssigned = (BOOL) objLineRecord.m_fMonikerAssigned; + lpContainerLine->m_dwDrawAspect = objLineRecord.m_dwDrawAspect; + lpContainerLine->m_sizeInHimetric = objLineRecord.m_sizeInHimetric; + lpContainerLine->m_dwLinkType = objLineRecord.m_dwLinkType; + lpContainerLine->m_fDoSetExtent = (BOOL) objLineRecord.m_fDoSetExtent; + + return (LPLINE)lpContainerLine; + +error: + // destroy partially created ContainerLine + if (lpContainerLine) + ContainerLine_Delete(lpContainerLine); + return NULL; +} + + +/* ContainerLine_GetTextLen + * ------------------------ + * + * Return length of the string representation of the ContainerLine + * (not considering the tab level). we will use the following as the + * string representation of a ContainerLine: + * "<" + user type name of OLE object + ">" + * eg: + * + */ +int ContainerLine_GetTextLen(LPCONTAINERLINE lpContainerLine) +{ + LPSTR lpszUserType = NULL; + HRESULT hrErr; + int nLen; + BOOL fIsLink = ContainerLine_IsOleLink(lpContainerLine); + + /* if object is not already loaded, then load it now. objects are + ** loaded lazily in this manner. + */ + if (! lpContainerLine->m_lpOleObj) + ContainerLine_LoadOleObject(lpContainerLine); + + OLEDBG_BEGIN2("IOleObject::GetUserType called\r\n") + + hrErr = CallIOleObjectGetUserTypeA( + lpContainerLine->m_lpOleObj, + USERCLASSTYPE_FULL, + &lpszUserType + ); + + OLEDBG_END2 + + if (hrErr != NOERROR) { + // user type is NOT available + nLen = sizeof(UNKNOWN_OLEOBJ_TYPE) + 2; // allow space for '<' + '>' + nLen += lstrlen((LPSTR)(fIsLink ? szOLELINK : szOLEOBJECT)) + 1; + } else { + nLen = lstrlen(lpszUserType) + 2; // allow space for '<' + '>' + nLen += lstrlen((LPSTR)(fIsLink ? szOLELINK : szOLEOBJECT)) + 1; + + /* OLE2NOTE: we must free the string that was allocated by the + ** IOleObject::GetUserType method. + */ + OleStdFreeString(lpszUserType, NULL); + } + + return nLen; +} + + +/* ContainerLine_GetTextData + * ------------------------- + * + * Return the string representation of the ContainerLine + * (not considering the tab level). we will use the following as the + * string representation of a ContainerLine: + * "<" + user type name of OLE object + ">" + * eg: + * + */ +void ContainerLine_GetTextData(LPCONTAINERLINE lpContainerLine, LPSTR lpszBuf) +{ + LPSTR lpszUserType = NULL; + BOOL fIsLink = ContainerLine_IsOleLink(lpContainerLine); + HRESULT hrErr; + + /* if object is not already loaded, then load it now. objects are + ** loaded lazily in this manner. + */ + if (! lpContainerLine->m_lpOleObj) + ContainerLine_LoadOleObject(lpContainerLine); + + hrErr = CallIOleObjectGetUserTypeA( + lpContainerLine->m_lpOleObj, + USERCLASSTYPE_FULL, + &lpszUserType + ); + + if (hrErr != NOERROR) { + // user type is NOT available + wsprintf( + lpszBuf, + "<%s %s>", + UNKNOWN_OLEOBJ_TYPE, + (LPSTR)(fIsLink ? szOLELINK : szOLEOBJECT) + ); + } else { + wsprintf( + lpszBuf, + "<%s %s>", + lpszUserType, + (LPSTR)(fIsLink ? szOLELINK : szOLEOBJECT) + ); + + /* OLE2NOTE: we must free the string that was allocated by the + ** IOleObject::GetUserType method. + */ + OleStdFreeString(lpszUserType, NULL); + } +} + + +/* ContainerLine_GetOutlineData + * ---------------------------- + * + * Return the CF_OUTLINE format data for the ContainerLine. + */ +BOOL ContainerLine_GetOutlineData( + LPCONTAINERLINE lpContainerLine, + LPTEXTLINE lpBuf +) +{ + LPLINE lpLine = (LPLINE)lpContainerLine; + LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerLine->m_lpDoc)->m_LineList; + HDC hDC; + char szTmpBuf[MAXSTRLEN+1]; + LPTEXTLINE lpTmpTextLine; + + // Create a TextLine with the Text representation of the ContainerLine. + ContainerLine_GetTextData(lpContainerLine, (LPSTR)szTmpBuf); + + hDC = LineList_GetDC(lpLL); + lpTmpTextLine = TextLine_Create(hDC, lpLine->m_nTabLevel, szTmpBuf); + LineList_ReleaseDC(lpLL, hDC); + + TextLine_Copy(lpTmpTextLine, lpBuf); + + // Delete the temporary TextLine + TextLine_Delete(lpTmpTextLine); + return TRUE; +} + + +/* ContainerLine_GetPosRect +** ----------------------- +** Get the PosRect in client coordinates for the OLE object's window. +** +** OLE2NOTE: the PosRect must take into account the scroll postion of +** the document window. +*/ +void ContainerLine_GetPosRect( + LPCONTAINERLINE lpContainerLine, + LPRECT lprcPosRect +) +{ + ContainerLine_GetOleObjectRectInPixels(lpContainerLine,lprcPosRect); + + // shift rect for left margin + lprcPosRect->left += lpContainerLine->m_nHorizScrollShift; + lprcPosRect->right += lpContainerLine->m_nHorizScrollShift; +} + + +/* ContainerLine_GetOleObjectRectInPixels +** -------------------------------------- +** Get the extent of the OLE Object contained in the given Line in +** client coordinates after scaling. +*/ +void ContainerLine_GetOleObjectRectInPixels(LPCONTAINERLINE lpContainerLine, LPRECT lprc) +{ + LPOUTLINEDOC lpOutlineDoc; + LPSCALEFACTOR lpscale; + LPLINELIST lpLL; + LPLINE lpLine; + int nIndex; + HDC hdcLL; + + if (!lpContainerLine || !lprc) + return; + + lpOutlineDoc = (LPOUTLINEDOC)lpContainerLine->m_lpDoc; + lpscale = OutlineDoc_GetScaleFactor(lpOutlineDoc); + lpLL = OutlineDoc_GetLineList(lpOutlineDoc); + lpLine = (LPLINE)lpContainerLine; + nIndex = LineList_GetLineIndex(lpLL, lpLine); + + LineList_GetLineRect(lpLL, nIndex, lprc); + + hdcLL = GetDC(lpLL->m_hWndListBox); + + /* lprc is set to be size of Line Object (including the boundary) */ + lprc->left += (int)( + (long)XformWidthInHimetricToPixels(hdcLL, + lpLine->m_nTabWidthInHimetric + + LOWORD(OutlineDoc_GetMargin(lpOutlineDoc))) * + lpscale->dwSxN / lpscale->dwSxD); + lprc->right = (int)( + lprc->left + (long) + XformWidthInHimetricToPixels(hdcLL, lpLine->m_nWidthInHimetric) * + lpscale->dwSxN / lpscale->dwSxD); + + ReleaseDC(lpLL->m_hWndListBox, hdcLL); +} + + +/* ContainerLine_GetOleObjectSizeInHimetric +** ---------------------------------------- +** Get the size of the OLE Object contained in the given Line +*/ +void ContainerLine_GetOleObjectSizeInHimetric(LPCONTAINERLINE lpContainerLine, LPSIZEL lpsizel) +{ + if (!lpContainerLine || !lpsizel) + return; + + *lpsizel = lpContainerLine->m_sizeInHimetric; +} + + +/* ContainerLine_BindLinkIfLinkSrcIsRunning +** ---------------------------------------- +** Try to connect the OLE link object associated with the +** ContainerLine with its LinkSource if the LinkSource is already +** running and the link is an automatic link. we do not want to +** force the LinkSource to run. +** +** OLE2NOTE: a sophistocated container will want to continually +** attempt to connect its automatic links. OLE does NOT +** automatically connect links when link source become available. some +** containers will want to attempt to connect its links as part of +** idle time processing. another strategy is to attempt to connect +** an automatic link every time it is drawn on the screen. (this is +** the strategy used by this CntrOutl sample application.) +*/ +void ContainerLine_BindLinkIfLinkSrcIsRunning(LPCONTAINERLINE lpContainerLine) +{ + LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; + HRESULT hrErr; + BOOL fPrevEnable1; + BOOL fPrevEnable2; + + // if the link source is known to be un-bindable, then don't even try + if (lpContainerLine->m_fLinkUnavailable) + return; + + /* OLE2NOTE: we do not want to ever give the Busy/NotResponding + ** dialogs when we are attempting to BindIfRunning to the link + ** source. if the link source is currently busy, this could + ** cause the Busy dialog to come up. even if the link source is + ** busy, we do not want put up the busy dialog. thus we will + ** disable the dialog and later re-enable them + */ + OleApp_DisableBusyDialogs(lpOleApp, &fPrevEnable1, &fPrevEnable2); + + OLEDBG_BEGIN2("IOleLink::BindIfRunning called\r\n") + hrErr = lpContainerLine->m_lpOleLink->lpVtbl->BindIfRunning( + lpContainerLine->m_lpOleLink); + OLEDBG_END2 + + // re-enable the Busy/NotResponding dialogs + OleApp_EnableBusyDialogs(lpOleApp, fPrevEnable1, fPrevEnable2); +} diff --git a/private/oleutest/letest/outline/cntrline.h b/private/oleutest/letest/outline/cntrline.h new file mode 100644 index 000000000..16b153aa8 --- /dev/null +++ b/private/oleutest/letest/outline/cntrline.h @@ -0,0 +1,3584 @@ +/************************************************************************* +** +** OLE 2 Container Sample Code +** +** cntrline.c +** +** This file contains ContainerLine methods. +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + +#include "outline.h" + +OLEDBGDATA + + + +extern LPOUTLINEAPP g_lpApp; +extern IUnknownVtbl g_CntrLine_UnknownVtbl; +extern IOleClientSiteVtbl g_CntrLine_OleClientSiteVtbl; +extern IAdviseSinkVtbl g_CntrLine_AdviseSinkVtbl; + +#if defined( INPLACE_CNTR ) +extern IOleInPlaceSiteVtbl g_CntrLine_OleInPlaceSiteVtbl; +extern BOOL g_fInsideOutContainer; +#endif // INPLACE_CNTR + +// REVIEW: should use string resource for messages +char ErrMsgDoVerb[] = "OLE object action failed!"; + + +/* prototype for static functions */ +static void InvertDiffRect(LPRECT lprcPix, LPRECT lprcObj, HDC hDC); + + +/************************************************************************* +** ContainerLine +** This object represents the location within the container where +** the embedded/linked object lives. It exposes interfaces to the +** object that allow the object to get information about its +** embedding site and to announce notifications of important events +** (changed, closed, saved) +** +** The ContainerLine exposes the following interfaces: +** IUnknown +** IOleClientSite +** IAdviseSink +*************************************************************************/ + + + +/************************************************************************* +** ContainerLine::IUnknown interface implementation +*************************************************************************/ + + +// IUnknown::QueryInterface +STDMETHODIMP CntrLine_Unk_QueryInterface( + LPUNKNOWN lpThis, + REFIID riid, + LPVOID FAR* lplpvObj +) +{ + LPCONTAINERLINE lpContainerLine = + ((struct COleClientSiteImpl FAR*)lpThis)->lpContainerLine; + + return ContainerLine_QueryInterface(lpContainerLine, riid, lplpvObj); +} + + +// IUnknown::AddRef +STDMETHODIMP_(ULONG) CntrLine_Unk_AddRef(LPUNKNOWN lpThis) +{ + LPCONTAINERLINE lpContainerLine = + ((struct COleClientSiteImpl FAR*)lpThis)->lpContainerLine; + + OleDbgAddRefMethod(lpThis, "IUnknown"); + + return ContainerLine_AddRef(lpContainerLine); +} + + +// IUnknown::Release +STDMETHODIMP_(ULONG) CntrLine_Unk_Release(LPUNKNOWN lpThis) +{ + LPCONTAINERLINE lpContainerLine = + ((struct COleClientSiteImpl FAR*)lpThis)->lpContainerLine; + + OleDbgReleaseMethod(lpThis, "IUnknown"); + + return ContainerLine_Release(lpContainerLine); +} + + +/************************************************************************* +** ContainerLine::IOleClientSite interface implementation +*************************************************************************/ + +// IOleClientSite::QueryInterface +STDMETHODIMP CntrLine_CliSite_QueryInterface( + LPOLECLIENTSITE lpThis, + REFIID riid, + LPVOID FAR* lplpvObj +) +{ + LPCONTAINERLINE lpContainerLine = + ((struct COleClientSiteImpl FAR*)lpThis)->lpContainerLine; + + return ContainerLine_QueryInterface(lpContainerLine, riid, lplpvObj); +} + + +// IOleClientSite::AddRef +STDMETHODIMP_(ULONG) CntrLine_CliSite_AddRef(LPOLECLIENTSITE lpThis) +{ + LPCONTAINERLINE lpContainerLine = + ((struct COleClientSiteImpl FAR*)lpThis)->lpContainerLine; + + OleDbgAddRefMethod(lpThis, "IOleClientSite"); + + return ContainerLine_AddRef(lpContainerLine); +} + + +// IOleClientSite::Release +STDMETHODIMP_(ULONG) CntrLine_CliSite_Release(LPOLECLIENTSITE lpThis) +{ + LPCONTAINERLINE lpContainerLine = + ((struct COleClientSiteImpl FAR*)lpThis)->lpContainerLine; + + OleDbgReleaseMethod(lpThis, "IOleClientSite"); + + return ContainerLine_Release(lpContainerLine); +} + + +// IOleClientSite::SaveObject +STDMETHODIMP CntrLine_CliSite_SaveObject(LPOLECLIENTSITE lpThis) +{ + LPCONTAINERLINE lpContainerLine = + ((struct COleClientSiteImpl FAR*)lpThis)->lpContainerLine; + LPPERSISTSTORAGE lpPersistStg = lpContainerLine->m_lpPersistStg; + SCODE sc = S_OK; + HRESULT hrErr; + + OLEDBG_BEGIN2("CntrLine_CliSite_SaveObject\r\n") + + if (! lpPersistStg) { + /* OLE2NOTE: The object is NOT loaded. a container must be + ** prepared for the fact that an object that it thinks it + ** has unloaded may still call IOleClientSite::SaveObject. + ** in this case the container should fail the save call and + ** NOT try to reload the object. this scenario arises if you + ** have a in-process server (DLL object) which has a + ** connected linking client. even after the embedding + ** container unloads the DLL object, the link connection + ** keeps the object alive. it may then as part of its + ** shutdown try to call IOCS::SaveObject, but then it is too + ** late. + */ + OLEDBG_END2 + return ResultFromScode(E_FAIL); + } + + // mark ContainerDoc as now dirty + OutlineDoc_SetModified( + (LPOUTLINEDOC)lpContainerLine->m_lpDoc, TRUE, TRUE, FALSE); + + /* Tell OLE object to save itself + ** OLE2NOTE: it is NOT sufficient to ONLY call + ** IPersistStorage::Save method. it is also necessary to call + ** WriteClassStg. the helper API OleSave does this automatically. + */ + OLEDBG_BEGIN2("OleSave called\r\n") + hrErr=OleSave(lpPersistStg,lpContainerLine->m_lpStg, TRUE/*fSameAsLoad*/); + OLEDBG_END2 + + if (hrErr != NOERROR) { + OleDbgOutHResult("WARNING: OleSave returned", hrErr); + sc = GetScode(hrErr); + } + + // OLE2NOTE: even if OleSave fails, SaveCompleted must be called. + OLEDBG_BEGIN2("IPersistStorage::SaveCompleted called\r\n") + hrErr = lpPersistStg->lpVtbl->SaveCompleted(lpPersistStg, NULL); + OLEDBG_END2 + + if (hrErr != NOERROR) { + OleDbgOutHResult("WARNING: SaveCompleted returned",hrErr); + if (sc == S_OK) + sc = GetScode(hrErr); + } + + OLEDBG_END2 + return ResultFromScode(sc); +} + + +// IOleClientSite::GetMoniker +STDMETHODIMP CntrLine_CliSite_GetMoniker( + LPOLECLIENTSITE lpThis, + DWORD dwAssign, + DWORD dwWhichMoniker, + LPMONIKER FAR* lplpmk +) +{ + LPCONTAINERLINE lpContainerLine; + + lpContainerLine=((struct COleClientSiteImpl FAR*)lpThis)->lpContainerLine; + + OLEDBG_BEGIN2("CntrLine_CliSite_GetMoniker\r\n") + + // OLE2NOTE: we must make sure to set output pointer parameters to NULL + *lplpmk = NULL; + + switch (dwWhichMoniker) { + + case OLEWHICHMK_CONTAINER: + /* OLE2NOTE: create a FileMoniker which identifies the + ** entire container document. + */ + *lplpmk = OleDoc_GetFullMoniker( + (LPOLEDOC)lpContainerLine->m_lpDoc, + dwAssign + ); + break; + + case OLEWHICHMK_OBJREL: + + /* OLE2NOTE: create an ItemMoniker which identifies the + ** OLE object relative to the container document. + */ + *lplpmk = ContainerLine_GetRelMoniker(lpContainerLine, dwAssign); + break; + + case OLEWHICHMK_OBJFULL: + { + /* OLE2NOTE: create an absolute moniker which identifies the + ** OLE object in the container document. this moniker is + ** created as a composite of the absolute moniker for the + ** entire document appended with an item moniker which + ** identifies the OLE object relative to the document. + */ + + *lplpmk = ContainerLine_GetFullMoniker(lpContainerLine, dwAssign); + break; + } + } + + OLEDBG_END2 + + if (*lplpmk != NULL) + return NOERROR; + else + return ResultFromScode(E_FAIL); +} + + +// IOleClientSite::GetContainer +STDMETHODIMP CntrLine_CliSite_GetContainer( + LPOLECLIENTSITE lpThis, + LPOLECONTAINER FAR* lplpContainer +) +{ + LPCONTAINERLINE lpContainerLine; + HRESULT hrErr; + + OLEDBG_BEGIN2("CntrLine_CliSite_GetContainer\r\n") + + lpContainerLine=((struct COleClientSiteImpl FAR*)lpThis)->lpContainerLine; + + hrErr = OleDoc_QueryInterface( + (LPOLEDOC)lpContainerLine->m_lpDoc, + &IID_IOleContainer, + (LPVOID FAR*)lplpContainer + ); + + OLEDBG_END2 + return hrErr; +} + + +// IOleClientSite::ShowObject +STDMETHODIMP CntrLine_CliSite_ShowObject(LPOLECLIENTSITE lpThis) +{ + LPCONTAINERLINE lpContainerLine = + ((struct COleClientSiteImpl FAR*)lpThis)->lpContainerLine; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerLine->m_lpDoc; + LPLINELIST lpLL = OutlineDoc_GetLineList(lpOutlineDoc); + int nIndex = LineList_GetLineIndex(lpLL, (LPLINE)lpContainerLine); + HWND hWndFrame = OutlineApp_GetFrameWindow(g_lpApp); + + OLEDBG_BEGIN2("CntrLine_CliSite_ShowObject\r\n") + + /* make sure our doc window is visible and not minimized. + ** the OutlineDoc_ShowWindow function will cause the app window + ** to show itself SW_SHOWNORMAL. + */ + if (! IsWindowVisible(hWndFrame) || IsIconic(hWndFrame)) + OutlineDoc_ShowWindow(lpOutlineDoc); + + BringWindowToTop(hWndFrame); + + /* make sure that the OLE object is currently in view. if necessary + ** scroll the document in order to bring it into view. + */ + LineList_ScrollLineIntoView(lpLL, nIndex); + +#if defined( INPLACE_CNTR ) + /* after the in-place object is scrolled into view, we need to ask + ** it to update its rect for the new clip rect coordinates + */ + ContainerDoc_UpdateInPlaceObjectRects((LPCONTAINERDOC)lpOutlineDoc, 0); +#endif + + OLEDBG_END2 + return NOERROR; +} + + +// IOleClientSite::OnShowWindow +STDMETHODIMP CntrLine_CliSite_OnShowWindow(LPOLECLIENTSITE lpThis, BOOL fShow) +{ + LPCONTAINERLINE lpContainerLine = + ((struct COleClientSiteImpl FAR*)lpThis)->lpContainerLine; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerLine->m_lpDoc; + LPLINELIST lpLL = OutlineDoc_GetLineList(lpOutlineDoc); + int nIndex = LineList_GetLineIndex(lpLL, (LPLINE)lpContainerLine); + + if (fShow) { + OLEDBG_BEGIN2("CntrLine_CliSite_OnShowWindow(TRUE)\r\n") + + /* OLE2NOTE: we need to hatch out the OLE object now; it has + ** just been opened in a window elsewhere (open editing as + ** opposed to in-place activation). + ** force the line to re-draw with the hatch. + */ + lpContainerLine->m_fObjWinOpen = TRUE; + LineList_ForceLineRedraw(lpLL, nIndex, FALSE /*fErase*/); + + } else { + OLEDBG_BEGIN2("CntrLine_CliSite_OnShowWindow(FALSE)\r\n") + + /* OLE2NOTE: the object associated with this container site has + ** just closed its server window. we should now remove the + ** hatching that indicates that the object is open + ** elsewhere. also our window should now come to the top. + ** force the line to re-draw without the hatch. + */ + lpContainerLine->m_fObjWinOpen = FALSE; + LineList_ForceLineRedraw(lpLL, nIndex, TRUE /*fErase*/); + + BringWindowToTop(lpOutlineDoc->m_hWndDoc); + SetFocus(lpOutlineDoc->m_hWndDoc); + } + + OLEDBG_END2 + return NOERROR; +} + + +// IOleClientSite::RequestNewObjectLayout +STDMETHODIMP CntrLine_CliSite_RequestNewObjectLayout(LPOLECLIENTSITE lpThis) +{ + OleDbgOut2("CntrLine_CliSite_RequestNewObjectLayout\r\n"); + + /* OLE2NOTE: this method is NOT yet used. it is for future layout + ** negotiation support. + */ + return ResultFromScode(E_NOTIMPL); +} + + +/************************************************************************* +** ContainerLine::IAdviseSink interface implementation +*************************************************************************/ + +// IAdviseSink::QueryInterface +STDMETHODIMP CntrLine_AdvSink_QueryInterface( + LPADVISESINK lpThis, + REFIID riid, + LPVOID FAR* lplpvObj +) +{ + LPCONTAINERLINE lpContainerLine = + ((struct COleClientSiteImpl FAR*)lpThis)->lpContainerLine; + + return ContainerLine_QueryInterface(lpContainerLine, riid, lplpvObj); +} + + +// IAdviseSink::AddRef +STDMETHODIMP_(ULONG) CntrLine_AdvSink_AddRef(LPADVISESINK lpThis) +{ + LPCONTAINERLINE lpContainerLine = + ((struct COleClientSiteImpl FAR*)lpThis)->lpContainerLine; + + OleDbgAddRefMethod(lpThis, "IAdviseSink"); + + return ContainerLine_AddRef(lpContainerLine); +} + + +// IAdviseSink::Release +STDMETHODIMP_(ULONG) CntrLine_AdvSink_Release (LPADVISESINK lpThis) +{ + LPCONTAINERLINE lpContainerLine = + ((struct COleClientSiteImpl FAR*)lpThis)->lpContainerLine; + + OleDbgReleaseMethod(lpThis, "IAdviseSink"); + + return ContainerLine_Release(lpContainerLine); +} + + +// IAdviseSink::OnDataChange +STDMETHODIMP_(void) CntrLine_AdvSink_OnDataChange( + LPADVISESINK lpThis, + FORMATETC FAR* lpFormatetc, + STGMEDIUM FAR* lpStgmed +) +{ + OleDbgOut2("CntrLine_AdvSink_OnDataChange\r\n"); + // We are not interested in data changes (only view changes) + // (ie. nothing to do) +} + + +STDMETHODIMP_(void) CntrLine_AdvSink_OnViewChange( + LPADVISESINK lpThis, + DWORD aspects, + LONG lindex +) +{ + LPCONTAINERLINE lpContainerLine; + LPOUTLINEDOC lpOutlineDoc; + HWND hWndDoc; + LPLINELIST lpLL; + MSG msg; + int nIndex; + + OLEDBG_BEGIN2("CntrLine_AdvSink_OnViewChange\r\n") + + lpContainerLine = ((struct CAdviseSinkImpl FAR*)lpThis)->lpContainerLine; + lpOutlineDoc = (LPOUTLINEDOC)lpContainerLine->m_lpDoc; + + /* OLE2NOTE: at this point we simply invalidate the rectangle of + ** the object to force a repaint in the future, we mark + ** that the extents of the object may have changed + ** (m_fDoGetExtent=TRUE), and we post a message + ** (WM_U_UPDATEOBJECTEXTENT) to our document that one or more + ** OLE objects may need to have their extents updated. later + ** when this message is processed, the document loops through + ** all lines to see if any are marked as needing an extent update. + ** if infact the extents did change. this can be done by calling + ** IViewObject2::GetExtent to retreive the object's current + ** extents and comparing with the last known extents for the + ** object. if the extents changed, then relayout space for the + ** object before drawing. we postpone the check to get + ** the extents now because OnViewChange is an asyncronis method, + ** and we have to careful not to call any syncronis methods back + ** to the object. while it WOULD be OK to call the + ** IViewObject2::GetExtent method within the asyncronis + ** OnViewChange method (because this method is handled by the + ** object handler and never remoted), it is good practise to not + ** call any object methods from within an asyncronis + ** notification method. + ** if there is already WM_U_UPDATEOBJECTEXTENT message waiting + ** in our message queue, there is no need to post another one. + ** in this way, if the server is updating quicker than we can + ** keep up, we do not make unneccsary GetExtent calls. also if + ** drawing is disabled, we postpone updating the extents of any + ** objects until drawing is re-enabled. + */ + lpContainerLine->m_fDoGetExtent = TRUE; + hWndDoc = OutlineDoc_GetWindow((LPOUTLINEDOC)lpContainerLine->m_lpDoc); + + if (lpOutlineDoc->m_nDisableDraw == 0 && + ! PeekMessage(&msg, hWndDoc, + WM_U_UPDATEOBJECTEXTENT, WM_U_UPDATEOBJECTEXTENT, + PM_NOREMOVE | PM_NOYIELD)) { + PostMessage(hWndDoc, WM_U_UPDATEOBJECTEXTENT, 0, 0L); + } + + // force the modified line to redraw. + lpLL = OutlineDoc_GetLineList(lpOutlineDoc); + nIndex = LineList_GetLineIndex(lpLL, (LPLINE)lpContainerLine); + LineList_ForceLineRedraw(lpLL, nIndex, TRUE /*fErase*/); + + OLEDBG_END2 +} + + +// IAdviseSink::OnRename +STDMETHODIMP_(void) CntrLine_AdvSink_OnRename( + LPADVISESINK lpThis, + LPMONIKER lpmk +) +{ + OleDbgOut2("CntrLine_AdvSink_OnRename\r\n"); + /* OLE2NOTE: the Embedding Container has nothing to do here. this + ** notification is important for linking situations. it tells + ** the OleLink objects to update their moniker because the + ** source object has been renamed (track the link source). + */ +} + + +// IAdviseSink::OnSave +STDMETHODIMP_(void) CntrLine_AdvSink_OnSave(LPADVISESINK lpThis) +{ + OleDbgOut2("CntrLine_AdvSink_OnSave\r\n"); + /* OLE2NOTE: the Embedding Container has nothing to do here. this + ** notification is only useful to clients which have set up a + ** data cache with the ADVFCACHE_ONSAVE flag. + */ +} + + +// IAdviseSink::OnClose +STDMETHODIMP_(void) CntrLine_AdvSink_OnClose(LPADVISESINK lpThis) +{ + OleDbgOut2("CntrLine_AdvSink_OnClose\r\n"); + /* OLE2NOTE: the Embedding Container has nothing to do here. this + ** notification is important for the OLE's default object handler + ** and the OleLink object. it tells them the remote object is + ** shutting down. + */ +} + + +/************************************************************************* +** ContainerLine Support Functions +*************************************************************************/ + + +/* ContainerLine_Init +** ------------------ +** Initialize fields in a newly constructed ContainerLine line object. +** NOTE: ref cnt of ContainerLine initialized to 0 +*/ +void ContainerLine_Init(LPCONTAINERLINE lpContainerLine, int nTab, HDC hDC) +{ + Line_Init((LPLINE)lpContainerLine, nTab, hDC); // init base class fields + + ((LPLINE)lpContainerLine)->m_lineType = CONTAINERLINETYPE; + ((LPLINE)lpContainerLine)->m_nWidthInHimetric = DEFOBJWIDTH; + ((LPLINE)lpContainerLine)->m_nHeightInHimetric = DEFOBJHEIGHT; + lpContainerLine->m_cRef = 0; + lpContainerLine->m_szStgName[0] = '\0'; + lpContainerLine->m_fObjWinOpen = FALSE; + lpContainerLine->m_fMonikerAssigned = FALSE; + lpContainerLine->m_dwDrawAspect = DVASPECT_CONTENT; + + lpContainerLine->m_fGuardObj = FALSE; + lpContainerLine->m_fDoGetExtent = FALSE; + lpContainerLine->m_fDoSetExtent = FALSE; + lpContainerLine->m_sizeInHimetric.cx = -1; + lpContainerLine->m_sizeInHimetric.cy = -1; + + lpContainerLine->m_lpStg = NULL; + lpContainerLine->m_lpDoc = NULL; + lpContainerLine->m_lpOleObj = NULL; + lpContainerLine->m_lpViewObj2 = NULL; + lpContainerLine->m_lpPersistStg = NULL; + lpContainerLine->m_lpOleLink = NULL; + lpContainerLine->m_dwLinkType = 0; + lpContainerLine->m_fLinkUnavailable = FALSE; + lpContainerLine->m_lpszShortType = NULL; + +#if defined( INPLACE_CNTR ) + lpContainerLine->m_fIpActive = FALSE; + lpContainerLine->m_fUIActive = FALSE; + lpContainerLine->m_fIpVisible = FALSE; + lpContainerLine->m_lpOleIPObj = NULL; + lpContainerLine->m_fInsideOutObj = FALSE; + lpContainerLine->m_fIpChangesUndoable = FALSE; + lpContainerLine->m_fIpServerRunning = FALSE; + lpContainerLine->m_hWndIpObject = NULL; + lpContainerLine->m_nHorizScrollShift = 0; +#endif // INPLACE_CNTR + + INIT_INTERFACEIMPL( + &lpContainerLine->m_Unknown, + &g_CntrLine_UnknownVtbl, + lpContainerLine + ); + + INIT_INTERFACEIMPL( + &lpContainerLine->m_OleClientSite, + &g_CntrLine_OleClientSiteVtbl, + lpContainerLine + ); + + INIT_INTERFACEIMPL( + &lpContainerLine->m_AdviseSink, + &g_CntrLine_AdviseSinkVtbl, + lpContainerLine + ); + +#if defined( INPLACE_CNTR ) + INIT_INTERFACEIMPL( + &lpContainerLine->m_OleInPlaceSite, + &g_CntrLine_OleInPlaceSiteVtbl, + lpContainerLine + ); +#endif // INPLACE_CNTR +} + + +/* Setup the OLE object associated with the ContainerLine */ +BOOL ContainerLine_SetupOleObject( + LPCONTAINERLINE lpContainerLine, + BOOL fDisplayAsIcon, + HGLOBAL hMetaPict +) +{ + DWORD dwDrawAspect = (fDisplayAsIcon ? DVASPECT_ICON : DVASPECT_CONTENT); + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerLine->m_lpDoc; + + /* Cache a pointer to the IViewObject2* interface. *Required* + ** we need this everytime we draw the object. + ** + ** OLE2NOTE: We require the object to support IViewObject2 + ** interface. this is an extension to the IViewObject interface + ** that was added with the OLE 2.01 release. This interface must + ** be supported by all object handlers and DLL-based objects. + */ + lpContainerLine->m_lpViewObj2 = (LPVIEWOBJECT2)OleStdQueryInterface( + (LPUNKNOWN)lpContainerLine->m_lpOleObj, &IID_IViewObject2); + if (! lpContainerLine->m_lpViewObj2) { +#if defined( _DEBUG ) + OleDbgAssertSz( + lpContainerLine->m_lpViewObj2,"IViewObject2 NOT supported\r\n"); +#endif + return FALSE; + } + + // Cache a pointer to the IPersistStorage* interface. *Required* + // we need this everytime we save the object. + lpContainerLine->m_lpPersistStg = (LPPERSISTSTORAGE)OleStdQueryInterface( + (LPUNKNOWN)lpContainerLine->m_lpOleObj, &IID_IPersistStorage); + if (! lpContainerLine->m_lpPersistStg) { + OleDbgAssert(lpContainerLine->m_lpPersistStg); + return FALSE; + } + + // Cache a pointer to the IOleLink* interface if supported. *Optional* + // if supported the object is a link. we need this to manage the link + lpContainerLine->m_lpOleLink = (LPOLELINK)OleStdQueryInterface( + (LPUNKNOWN)lpContainerLine->m_lpOleObj, &IID_IOleLink); + if (lpContainerLine->m_lpOleLink) { + OLEDBG_BEGIN2("IOleLink::GetUpdateOptions called\r\n") + lpContainerLine->m_lpOleLink->lpVtbl->GetUpdateOptions( + lpContainerLine->m_lpOleLink, &lpContainerLine->m_dwLinkType); + OLEDBG_END2 + } else + lpContainerLine->m_dwLinkType = 0; // NOT a link + + /* get the short user type name of the object. this + ** is used all the time when we have to build the object + ** verb menu. we will cache this information to make it + ** quicker to build the verb menu. + */ + OleDbgAssert(lpContainerLine->m_lpszShortType == NULL); + OLEDBG_BEGIN2("IOleObject::GetUserType called\r\n") + { + LPOLESTR polestr; + + lpContainerLine->m_lpOleObj->lpVtbl->GetUserType( + lpContainerLine->m_lpOleObj, + USERCLASSTYPE_SHORT, + &polestr + ); + CopyAndFreeOLESTR(polestr, &lpContainerLine->m_lpszShortType); + } + OLEDBG_END2 + + /* Perform that standard setup for the OLE object. this includes: + ** setup View advise + ** Call IOleObject::SetHostNames + ** Call OleSetContainedObject + */ + OleStdSetupAdvises( + lpContainerLine->m_lpOleObj, + dwDrawAspect, + (LPSTR)APPNAME, + lpOutlineDoc->m_lpszDocTitle, + (LPADVISESINK)&lpContainerLine->m_AdviseSink, + TRUE /*fCreate*/ + ); + +#if defined( INPLACE_CNTR ) + /* OLE2NOTE: (INSIDE-OUT CONTAINER) An inside-out container should + ** check if the object is an inside-out and prefers to be + ** activated when visible type of object. if not the object + ** should not be allowed to keep its window up after it gets + ** UIDeactivated. + */ + if (g_fInsideOutContainer) { + DWORD mstat; + OLEDBG_BEGIN2("IOleObject::GetMiscStatus called\r\n") + lpContainerLine->m_lpOleObj->lpVtbl->GetMiscStatus( + lpContainerLine->m_lpOleObj, + DVASPECT_CONTENT, + (DWORD FAR*)&mstat + ); + OLEDBG_END2 + + lpContainerLine->m_fInsideOutObj = (BOOL) + (mstat & (OLEMISC_INSIDEOUT|OLEMISC_ACTIVATEWHENVISIBLE)); + } +#endif // INPLACE_CNTR + + if (fDisplayAsIcon) { + /* user has requested to display icon aspect instead of content + ** aspect. + ** NOTE: we do not have to delete the previous aspect cache + ** because one did not get set up. + */ + OleStdSwitchDisplayAspect( + lpContainerLine->m_lpOleObj, + &lpContainerLine->m_dwDrawAspect, + dwDrawAspect, + hMetaPict, + FALSE, /* fDeleteOldAspect */ + TRUE, /* fSetupViewAdvise */ + (LPADVISESINK)&lpContainerLine->m_AdviseSink, + NULL /*fMustUpdate*/ // this can be ignored; update + // for switch to icon not req'd + ); + } + return TRUE; +} + + +/* Create an ContainerLine object and return the pointer */ +LPCONTAINERLINE ContainerLine_Create( + DWORD dwOleCreateType, + HDC hDC, + UINT nTab, + LPCONTAINERDOC lpContainerDoc, + LPCLSID lpclsid, + LPSTR lpszFileName, + BOOL fDisplayAsIcon, + HGLOBAL hMetaPict, + LPSTR lpszStgName +) +{ + LPCONTAINERLINE lpContainerLine = NULL; + LPOLEOBJECT lpObj = NULL; + LPSTORAGE lpDocStg = ContainerDoc_GetStg(lpContainerDoc); + DWORD dwDrawAspect = + (fDisplayAsIcon ? DVASPECT_ICON : DVASPECT_CONTENT); + DWORD dwOleRenderOpt = + (fDisplayAsIcon ? OLERENDER_NONE : OLERENDER_DRAW); + HRESULT hrErr; + + OLEDBG_BEGIN3("ContainerLine_Create\r\n") + + if (lpDocStg == NULL) { + OleDbgAssertSz(lpDocStg != NULL, "Doc storage is NULL"); + goto error; + } + + lpContainerLine=(LPCONTAINERLINE) New((DWORD)sizeof(CONTAINERLINE)); + if (lpContainerLine == NULL) { + OleDbgAssertSz(lpContainerLine!=NULL,"Error allocating ContainerLine"); + goto error; + } + + ContainerLine_Init(lpContainerLine, nTab, hDC); + + /* OLE2NOTE: in order to avoid re-entrancy we will set a flag to + ** guard our object. if this guard is set, then the object is + ** not ready to have any OLE interface methods called. it is + ** necessary to guard the object this way while it is being + ** created or loaded. + */ + lpContainerLine->m_fGuardObj = TRUE; + + /* OLE2NOTE: In order to have a stable ContainerLine object we must + ** AddRef the object's refcnt. this will be later released when + ** the ContainerLine is deleted. + */ + ContainerLine_AddRef(lpContainerLine); + + lstrcpy(lpContainerLine->m_szStgName, lpszStgName); + lpContainerLine->m_lpDoc = lpContainerDoc; + + /* Create a new storage for the object inside the doc's storage */ + lpContainerLine->m_lpStg = OleStdCreateChildStorage(lpDocStg,lpszStgName); + if (lpContainerLine->m_lpStg == NULL) { + OleDbgAssert(lpContainerLine->m_lpStg != NULL); + goto error; + } + + lpContainerLine->m_dwLinkType = 0; + + switch (dwOleCreateType) { + + case IOF_SELECTCREATENEW: + + OLEDBG_BEGIN2("OleCreate called\r\n") + hrErr = OleCreate ( + lpclsid, + &IID_IOleObject, + dwOleRenderOpt, + NULL, + (LPOLECLIENTSITE)&lpContainerLine->m_OleClientSite, + lpContainerLine->m_lpStg, + (LPVOID FAR*)&lpContainerLine->m_lpOleObj + ); + OLEDBG_END2 + +#if defined( _DEBUG ) + if (hrErr != NOERROR) + OleDbgOutHResult("OleCreate returned", hrErr); +#endif + + break; + + case IOF_SELECTCREATEFROMFILE: + + OLEDBG_BEGIN2("OleCreateFromFile called\r\n") + { + CREATEOLESTR(polestr, lpszFileName) + + hrErr = OleCreateFromFile ( + &CLSID_NULL, + polestr, + &IID_IOleObject, + dwOleRenderOpt, + NULL, + (LPOLECLIENTSITE)&lpContainerLine->m_OleClientSite, + lpContainerLine->m_lpStg, + (LPVOID FAR*)&lpContainerLine->m_lpOleObj + ); + + FREEOLESTR(polestr) + } + OLEDBG_END2 + +#if defined( _DEBUG ) + if (hrErr != NOERROR) + OleDbgOutHResult("OleCreateFromFile returned", hrErr); +#endif + break; + + case IOF_CHECKLINK: + + OLEDBG_BEGIN2("OleCreateLinkToFile called\r\n") + { + CREATEOLESTR(polestr, lpszFileName) + + hrErr = OleCreateLinkToFile ( + polestr, + &IID_IOleObject, + dwOleRenderOpt, + NULL, + (LPOLECLIENTSITE)&lpContainerLine->m_OleClientSite, + lpContainerLine->m_lpStg, + (LPVOID FAR*)&lpContainerLine->m_lpOleObj + ); + + FREEOLESTR(polestr) + } + OLEDBG_END2 + +#if defined( _DEBUG ) + if (hrErr != NOERROR) + OleDbgOutHResult("OleCreateLinkToFile returned", hrErr); +#endif + break; + } + if (hrErr != NOERROR) + goto error; + + if (! ContainerLine_SetupOleObject( + lpContainerLine, fDisplayAsIcon, hMetaPict)) { + goto error; + } + + /* OLE2NOTE: clear our re-entrancy guard. the object is now ready + ** to have interface methods called. + */ + lpContainerLine->m_fGuardObj = FALSE; + + OLEDBG_END3 + return lpContainerLine; + +error: + OutlineApp_ErrorMessage(g_lpApp, "Could not create object!"); + + // Destroy partially created OLE object + if (lpContainerLine) + ContainerLine_Delete(lpContainerLine); + OLEDBG_END3 + return NULL; +} + + +LPCONTAINERLINE ContainerLine_CreateFromData( + HDC hDC, + UINT nTab, + LPCONTAINERDOC lpContainerDoc, + LPDATAOBJECT lpSrcDataObj, + DWORD dwCreateType, + CLIPFORMAT cfFormat, + BOOL fDisplayAsIcon, + HGLOBAL hMetaPict, + LPSTR lpszStgName +) +{ + HGLOBAL hData = NULL; + LPCONTAINERLINE lpContainerLine = NULL; + LPOLEOBJECT lpObj = NULL; + LPSTORAGE lpDocStg = ContainerDoc_GetStg(lpContainerDoc); + DWORD dwDrawAspect = + (fDisplayAsIcon ? DVASPECT_ICON : DVASPECT_CONTENT); + DWORD dwOleRenderOpt; + FORMATETC renderFmtEtc; + LPFORMATETC lpRenderFmtEtc = NULL; + HRESULT hrErr; + LPUNKNOWN lpUnk = NULL; + + OLEDBG_BEGIN3("ContainerLine_CreateFromData\r\n") + + if (dwCreateType == OLECREATEFROMDATA_STATIC && cfFormat != 0) { + // a particular type of static object should be created + + dwOleRenderOpt = OLERENDER_FORMAT; + lpRenderFmtEtc = (LPFORMATETC)&renderFmtEtc; + + if (cfFormat == CF_METAFILEPICT) + SETDEFAULTFORMATETC(renderFmtEtc, cfFormat, TYMED_MFPICT); + else if (cfFormat == CF_BITMAP) + SETDEFAULTFORMATETC(renderFmtEtc, cfFormat, TYMED_GDI); + else + SETDEFAULTFORMATETC(renderFmtEtc, cfFormat, TYMED_HGLOBAL); + + } else if (dwCreateType == OLECREATEFROMDATA_STATIC && fDisplayAsIcon) { + // a link that currently displayed as an icon needs to be + // converted to a STATIC picture object. this case is driven + // from "BreakLink" in the "Links" dialog. because the current + // data in the source object's cache is DVASPECT_ICON we need + // to tell the OleCreateStaticFromData API to look for + // DVASPECT_ICON data. the static object that results however, + // is considered to be displayed in the DVASPECT_CONTENT view. + + dwOleRenderOpt = OLERENDER_DRAW; + lpRenderFmtEtc = (LPFORMATETC)&renderFmtEtc; + SETFORMATETC(renderFmtEtc,0,DVASPECT_ICON,NULL,TYMED_NULL,-1); + dwDrawAspect = DVASPECT_CONTENT; // static obj displays only CONTENT + + } else if (fDisplayAsIcon && hMetaPict) { + // a special icon should be used. first we create the object + // OLERENDER_NONE and then we stuff the special icon into the cache. + + dwOleRenderOpt = OLERENDER_NONE; + + } else if (fDisplayAsIcon && hMetaPict == NULL) { + // the object's default icon should be used + + dwOleRenderOpt = OLERENDER_DRAW; + lpRenderFmtEtc = (LPFORMATETC)&renderFmtEtc; + SETFORMATETC(renderFmtEtc,0,DVASPECT_ICON,NULL,TYMED_NULL,-1); + + } else { + // create standard DVASPECT_CONTENT/OLERENDER_DRAW object + dwOleRenderOpt = OLERENDER_DRAW; + } + + if (lpDocStg == NULL) { + OleDbgAssertSz(lpDocStg != NULL, "Doc storage is NULL"); + goto error; + } + + lpContainerLine=(LPCONTAINERLINE) New((DWORD)sizeof(CONTAINERLINE)); + if (lpContainerLine == NULL) { + OleDbgAssertSz(lpContainerLine!=NULL,"Error allocating ContainerLine"); + goto error; + } + + ContainerLine_Init(lpContainerLine, nTab, hDC); + + /* OLE2NOTE: in order to avoid re-entrancy we will set a flag to + ** guard our object. if this guard is set, then the object is + ** not ready to have any OLE interface methods called. it is + ** necessary to guard the object this way while it is being + ** created or loaded. + */ + lpContainerLine->m_fGuardObj = TRUE; + + /* OLE2NOTE: In order to have a stable ContainerLine object we must + ** AddRef the object's refcnt. this will be later released when + ** the ContainerLine is deleted. + */ + ContainerLine_AddRef(lpContainerLine); + + lstrcpy(lpContainerLine->m_szStgName, lpszStgName); + lpContainerLine->m_lpDoc = lpContainerDoc; + + /* Create a new storage for the object inside the doc's storage */ + lpContainerLine->m_lpStg = OleStdCreateChildStorage(lpDocStg,lpszStgName); + if (lpContainerLine->m_lpStg == NULL) { + OleDbgAssert(lpContainerLine->m_lpStg != NULL); + goto error; + } + + switch (dwCreateType) { + + case OLECREATEFROMDATA_LINK: + + OLEDBG_BEGIN2("OleCreateLinkFromData called\r\n") + hrErr = OleCreateLinkFromData ( + lpSrcDataObj, + &IID_IOleObject, + dwOleRenderOpt, + lpRenderFmtEtc, + (LPOLECLIENTSITE)&lpContainerLine->m_OleClientSite, + lpContainerLine->m_lpStg, + (LPVOID FAR*)&lpContainerLine->m_lpOleObj + ); + OLEDBG_END2 + +#if defined( _DEBUG ) + if (hrErr != NOERROR) + OleDbgOutHResult("OleCreateLinkFromData returned", hrErr); +#endif + break; + + case OLECREATEFROMDATA_OBJECT: + + OLEDBG_BEGIN2("OleCreateFromData called\r\n") + hrErr = OleCreateFromData ( + lpSrcDataObj, + &IID_IOleObject, + dwOleRenderOpt, + lpRenderFmtEtc, + (LPOLECLIENTSITE)&lpContainerLine->m_OleClientSite, + lpContainerLine->m_lpStg, + (LPVOID FAR*)&lpContainerLine->m_lpOleObj + ); + OLEDBG_END2 + +#if defined( _DEBUG ) + if (hrErr != NOERROR) + OleDbgOutHResult("OleCreateFromData returned", hrErr); +#endif + break; + + case OLECREATEFROMDATA_STATIC: + + OLEDBG_BEGIN2("OleCreateStaticFromData called\r\n") + hrErr = OleCreateStaticFromData ( + lpSrcDataObj, + &IID_IOleObject, + dwOleRenderOpt, + lpRenderFmtEtc, + (LPOLECLIENTSITE)&lpContainerLine->m_OleClientSite, + lpContainerLine->m_lpStg, + (LPVOID FAR*)&lpContainerLine->m_lpOleObj + ); + OLEDBG_END2 + +#if defined( _DEBUG ) + if (hrErr != NOERROR) + OleDbgOutHResult("OleCreateStaticFromData returned", hrErr); +#endif + break; + } + + if (hrErr != NOERROR) + goto error; + + if (! ContainerLine_SetupOleObject( + lpContainerLine, fDisplayAsIcon, hMetaPict)) { + goto error; + } + + /* OLE2NOTE: clear our re-entrancy guard. the object is now ready + ** to have interface methods called. + */ + lpContainerLine->m_fGuardObj = FALSE; + + OLEDBG_END3 + return lpContainerLine; + +error: + OutlineApp_ErrorMessage(g_lpApp, "Could not create object!"); + // Destroy partially created OLE object + if (lpContainerLine) + ContainerLine_Delete(lpContainerLine); + OLEDBG_END3 + return NULL; +} + + +/* ContainerLine_AddRef +** -------------------- +** +** increment the ref count of the line object. +** +** Returns the new ref count on the object +*/ +ULONG ContainerLine_AddRef(LPCONTAINERLINE lpContainerLine) +{ + ++lpContainerLine->m_cRef; + +#if defined( _DEBUG ) + OleDbgOutRefCnt4( + "ContainerLine_AddRef: cRef++\r\n", + lpContainerLine, + lpContainerLine->m_cRef + ); +#endif + return lpContainerLine->m_cRef; +} + + +/* ContainerLine_Release +** --------------------- +** +** decrement the ref count of the line object. +** if the ref count goes to 0, then the line is destroyed. +** +** Returns the remaining ref count on the object +*/ +ULONG ContainerLine_Release(LPCONTAINERLINE lpContainerLine) +{ + ULONG cRef; + + /********************************************************************* + ** OLE2NOTE: when the obj refcnt == 0, then destroy the object. ** + ** otherwise the object is still in use. ** + *********************************************************************/ + + cRef = --lpContainerLine->m_cRef; + +#if defined( _DEBUG ) + OleDbgAssertSz( + lpContainerLine->m_cRef >= 0,"Release called with cRef == 0"); + + OleDbgOutRefCnt4( + "ContainerLine_Release: cRef--\r\n", + lpContainerLine, + cRef + ); +#endif + if (cRef == 0) + ContainerLine_Destroy(lpContainerLine); + + return cRef; +} + + +/* ContainerLine_QueryInterface +** ---------------------------- +** +** Retrieve a pointer to an interface on the ContainerLine object. +** +** Returns NOERROR if interface is successfully retrieved. +** E_NOINTERFACE if the interface is not supported +*/ +HRESULT ContainerLine_QueryInterface( + LPCONTAINERLINE lpContainerLine, + REFIID riid, + LPVOID FAR* lplpvObj +) +{ + SCODE sc = E_NOINTERFACE; + + /* OLE2NOTE: we must make sure to set all out ptr parameters to NULL. */ + *lplpvObj = NULL; + + if (IsEqualIID(riid, &IID_IUnknown)) { + OleDbgOut4("ContainerLine_QueryInterface: IUnknown* RETURNED\r\n"); + + *lplpvObj = (LPVOID) &lpContainerLine->m_Unknown; + ContainerLine_AddRef(lpContainerLine); + sc = S_OK; + } + else if (IsEqualIID(riid, &IID_IOleClientSite)) { + OleDbgOut4("ContainerLine_QueryInterface: IOleClientSite* RETURNED\r\n"); + + *lplpvObj = (LPVOID) &lpContainerLine->m_OleClientSite; + ContainerLine_AddRef(lpContainerLine); + sc = S_OK; + } + else if (IsEqualIID(riid, &IID_IAdviseSink)) { + OleDbgOut4("ContainerLine_QueryInterface: IAdviseSink* RETURNED\r\n"); + + *lplpvObj = (LPVOID) &lpContainerLine->m_AdviseSink; + ContainerLine_AddRef(lpContainerLine); + sc = S_OK; + } +#if defined( INPLACE_CNTR ) + else if (IsEqualIID(riid, &IID_IOleWindow) + || IsEqualIID(riid, &IID_IOleInPlaceSite)) { + OleDbgOut4("ContainerLine_QueryInterface: IOleInPlaceSite* RETURNED\r\n"); + + *lplpvObj = (LPVOID) &lpContainerLine->m_OleInPlaceSite; + ContainerLine_AddRef(lpContainerLine); + sc = S_OK; + } +#endif // INPLACE_CNTR + + OleDbgQueryInterfaceMethod(*lplpvObj); + + return ResultFromScode(sc); +} + + +BOOL ContainerLine_LoadOleObject(LPCONTAINERLINE lpContainerLine) +{ + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerLine->m_lpDoc; + LPSTORAGE lpDocStg = ContainerDoc_GetStg(lpContainerLine->m_lpDoc); + LPOLECLIENTSITE lpOleClientSite; + LPMONIKER lpmkObj; + LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; + BOOL fPrevEnable1; + BOOL fPrevEnable2; + HRESULT hrErr; + + if (lpContainerLine->m_fGuardObj) + return FALSE; // object in process of creation + + if (lpContainerLine->m_lpOleObj) + return TRUE; // object already loaded + + OLEDBG_BEGIN3("ContainerLine_LoadOleObject\r\n") + + /* OLE2NOTE: in order to avoid re-entrancy we will set a flag to + ** guard our object. if this guard is set, then the object is + ** not ready to have any OLE interface methods called. it is + ** necessary to guard the object this way while it is being + ** created or loaded. + */ + lpContainerLine->m_fGuardObj = TRUE; + + /* if object storage is not already open, then open it */ + if (! lpContainerLine->m_lpStg) { + lpContainerLine->m_lpStg = OleStdOpenChildStorage( + lpDocStg, + lpContainerLine->m_szStgName, + STGM_READWRITE + ); + if (lpContainerLine->m_lpStg == NULL) { + OleDbgAssert(lpContainerLine->m_lpStg != NULL); + goto error; + } + } + + /* OLE2NOTE: if the OLE object being loaded is in a data transfer + ** document, then we should NOT pass a IOleClientSite* pointer + ** to the OleLoad call. This particularly critical if the OLE + ** object is an OleLink object. If a non-NULL client site is + ** passed to the OleLoad function, then the link will bind to + ** the source if its is running. in the situation that we are + ** loading the object as part of a data transfer document we do + ** not want this connection to be established. even worse, if + ** the link source is currently blocked or busy, then this could + ** hang the system. it is simplest to never pass a + ** IOleClientSite* when loading an object in a data transfer + ** document. + */ + lpOleClientSite = (lpOutlineDoc->m_fDataTransferDoc ? + NULL : (LPOLECLIENTSITE)&lpContainerLine->m_OleClientSite); + + /* OLE2NOTE: we do not want to ever give the Busy/NotResponding + ** dialogs when we are loading an object. if the object is a + ** link, it will attempt to BindIfRunning to the link source. if + ** the link source is currently busy, this could cause the Busy + ** dialog to come up. even if the link source is busy, + ** we do not want put up the busy dialog. thus we will disable + ** the dialog and later re-enable them + */ + OleApp_DisableBusyDialogs(lpOleApp, &fPrevEnable1, &fPrevEnable2); + + OLEDBG_BEGIN2("OleLoad called\r\n") + hrErr = OleLoad ( + lpContainerLine->m_lpStg, + &IID_IOleObject, + lpOleClientSite, + (LPVOID FAR*)&lpContainerLine->m_lpOleObj + ); + OLEDBG_END2 + + // re-enable the Busy/NotResponding dialogs + OleApp_EnableBusyDialogs(lpOleApp, fPrevEnable1, fPrevEnable2); + + if (hrErr != NOERROR) { + OleDbgAssertSz(hrErr == NOERROR, "Could not load object!"); + OleDbgOutHResult("OleLoad returned", hrErr); + goto error; + } + + /* Cache a pointer to the IViewObject2* interface. *Required* + ** we need this everytime we draw the object. + ** + ** OLE2NOTE: We require the object to support IViewObject2 + ** interface. this is an extension to the IViewObject interface + ** that was added with the OLE 2.01 release. This interface must + ** be supported by all object handlers and DLL-based objects. + */ + lpContainerLine->m_lpViewObj2 = (LPVIEWOBJECT2)OleStdQueryInterface( + (LPUNKNOWN)lpContainerLine->m_lpOleObj, &IID_IViewObject2); + if (! lpContainerLine->m_lpViewObj2) { +#if defined( _DEBUG ) + OleDbgAssertSz( + lpContainerLine->m_lpViewObj2,"IViewObject2 NOT supported\r\n"); +#endif + goto error; + } + + // Cache a pointer to the IPersistStorage* interface. *Required* + // we need this everytime we save the object. + lpContainerLine->m_lpPersistStg = (LPPERSISTSTORAGE)OleStdQueryInterface( + (LPUNKNOWN)lpContainerLine->m_lpOleObj, &IID_IPersistStorage); + if (! lpContainerLine->m_lpPersistStg) { + OleDbgAssert(lpContainerLine->m_lpPersistStg); + goto error; + } + + // Cache a pointer to the IOleLink* interface if supported. *Optional* + // if supported the object is a link. we need this to manage the link + if (lpContainerLine->m_dwLinkType != 0) { + lpContainerLine->m_lpOleLink = (LPOLELINK)OleStdQueryInterface( + (LPUNKNOWN)lpContainerLine->m_lpOleObj, &IID_IOleLink); + if (! lpContainerLine->m_lpOleLink) { + OleDbgAssert(lpContainerLine->m_lpOleLink); + goto error; + } + } + + /* OLE2NOTE: clear our re-entrancy guard. the object is now ready + ** to have interface methods called. + */ + lpContainerLine->m_fGuardObj = FALSE; + + /* OLE2NOTE: similarly, if the OLE object being loaded is in a data + ** transfer document, then we do NOT need to setup any advises, + ** call SetHostNames, SetMoniker, etc. + */ + if (lpOleClientSite) { + /* Setup the Advises (OLE notifications) that we are interested + ** in receiving. + */ + OleStdSetupAdvises( + lpContainerLine->m_lpOleObj, + lpContainerLine->m_dwDrawAspect, + (LPSTR)APPNAME, + lpOutlineDoc->m_lpszDocTitle, + (LPADVISESINK)&lpContainerLine->m_AdviseSink, + FALSE /*fCreate*/ + ); + + /* OLE2NOTE: if the OLE object has a moniker assigned, we need to + ** inform the object by calling IOleObject::SetMoniker. this + ** will force the OLE object to register in the + ** RunningObjectTable when it enters the running state. + */ + if (lpContainerLine->m_fMonikerAssigned) { + lpmkObj = ContainerLine_GetRelMoniker( + lpContainerLine, + GETMONIKER_ONLYIFTHERE + ); + + if (lpmkObj) { + OLEDBG_BEGIN2("IOleObject::SetMoniker called\r\n") + lpContainerLine->m_lpOleObj->lpVtbl->SetMoniker( + lpContainerLine->m_lpOleObj, + OLEWHICHMK_OBJREL, + lpmkObj + ); + OLEDBG_END2 + OleStdRelease((LPUNKNOWN)lpmkObj); + } + } + + /* get the Short form of the user type name of the object. this + ** is used all the time when we have to build the object + ** verb menu. we will cache this information to make it + ** quicker to build the verb menu. + */ + // block is only for polestr declaration + { + LPOLESTR polestr; + + OLEDBG_BEGIN2("IOleObject::GetUserType called\r\n") + lpContainerLine->m_lpOleObj->lpVtbl->GetUserType( + lpContainerLine->m_lpOleObj, + USERCLASSTYPE_SHORT, + &polestr + ); + + CopyAndFreeOLESTR(polestr, &lpContainerLine->m_lpszShortType); + } + OLEDBG_END2 + +#if defined( INPLACE_CNTR ) + /* OLE2NOTE: an inside-out container should check if the object + ** is an inside-out and prefers to be activated when visible + ** type of object. if so, the object should be immediately + ** activated in-place, BUT NOT UIActived. + */ + if (g_fInsideOutContainer && + lpContainerLine->m_dwDrawAspect == DVASPECT_CONTENT) { + DWORD mstat; + OLEDBG_BEGIN2("IOleObject::GetMiscStatus called\r\n") + lpContainerLine->m_lpOleObj->lpVtbl->GetMiscStatus( + lpContainerLine->m_lpOleObj, + DVASPECT_CONTENT, + (DWORD FAR*)&mstat + ); + OLEDBG_END2 + + lpContainerLine->m_fInsideOutObj = (BOOL) + (mstat & (OLEMISC_INSIDEOUT|OLEMISC_ACTIVATEWHENVISIBLE)); + + if ( lpContainerLine->m_fInsideOutObj ) { + HWND hWndDoc = OutlineDoc_GetWindow(lpOutlineDoc); + + ContainerLine_DoVerb( + lpContainerLine, + OLEIVERB_INPLACEACTIVATE, + NULL, + FALSE, + FALSE + ); + + /* OLE2NOTE: following this DoVerb(INPLACEACTIVATE) the + ** object may have taken focus. but because the + ** object is NOT UIActive it should NOT have focus. + ** we will make sure our document has focus. + */ + SetFocus(hWndDoc); + } + } +#endif // INPLACE_CNTR + OLEDBG_END2 + + } + + OLEDBG_END2 + return TRUE; + +error: + OLEDBG_END2 + return FALSE; +} + + +/* ContainerLine_CloseOleObject +** ---------------------------- +** Close the OLE object associated with the ContainerLine. +** +** Closing the object forces the object to transition from the +** running state to the loaded state. if the object was not running, +** then there is no effect. it is necessary to close the OLE object +** before releasing the pointers to the OLE object. +** +** Returns TRUE if successfully closed, +** FALSE if closing was aborted. +*/ +BOOL ContainerLine_CloseOleObject( + LPCONTAINERLINE lpContainerLine, + DWORD dwSaveOption +) +{ + HRESULT hrErr; + SCODE sc; + + if (lpContainerLine->m_fGuardObj) + return FALSE; // object in process of creation + + if (! lpContainerLine->m_lpOleObj) + return TRUE; // object is NOT loaded + + OLEDBG_BEGIN2("IOleObject::Close called\r\n") + hrErr = lpContainerLine->m_lpOleObj->lpVtbl->Close( + lpContainerLine->m_lpOleObj, + (dwSaveOption == OLECLOSE_NOSAVE ? + OLECLOSE_NOSAVE : OLECLOSE_SAVEIFDIRTY) + ); + OLEDBG_END2 + +#if defined( INPLACE_CNTR ) + if (lpContainerLine->m_fIpServerRunning) { + /* OLE2NOTE: unlock the lock held on the in-place object. + ** it is VERY important that an in-place container + ** that also support linking to embeddings properly manage + ** the running of its in-place objects. in an outside-in + ** style in-place container, when the user clicks + ** outside of the in-place active object, the object gets + ** UIDeactivated and the object hides its window. in order + ** to make the object fast to reactivate, the container + ** deliberately does not call IOleObject::Close. the object + ** stays running in the invisible unlocked state. the idea + ** here is if the user simply clicks outside of the object + ** and then wants to double click again to re-activate the + ** object, we do not want this to be slow. if we want to + ** keep the object running, however, we MUST Lock it + ** running. otherwise the object will be in an unstable + ** state where if a linking client does a "silent-update" + ** (eg. UpdateNow from the Links dialog), then the in-place + ** server will shut down even before the object has a chance + ** to be saved back in its container. this saving normally + ** occurs when the in-place container closes the object. also + ** keeping the object in the unstable, hidden, running, + ** not-locked state can cause problems in some scenarios. + ** ICntrOtl keeps only one object running. if the user + ** intiates a DoVerb on another object, then that last + ** running in-place active object is closed. a more + ** sophistocated in-place container may keep more object running. + ** (see CntrLine_IPSite_OnInPlaceActivate) + */ + lpContainerLine->m_fIpServerRunning = FALSE; + + OLEDBG_BEGIN2("OleLockRunning(FALSE,TRUE) called\r\n") + OleLockRunning((LPUNKNOWN)lpContainerLine->m_lpOleObj, FALSE, TRUE); + OLEDBG_END2 + } +#endif + + if (hrErr != NOERROR) { + OleDbgOutHResult("IOleObject::Close returned", hrErr); + sc = GetScode(hrErr); + if (sc == RPC_E_CALL_REJECTED || sc==OLE_E_PROMPTSAVECANCELLED) + return FALSE; // object aborted shutdown + } + return TRUE; +} + + +/* ContainerLine_UnloadOleObject +** ----------------------------- +** Close the OLE object associated with the ContainerLine and +** release all pointer held to the object. +** +** Closing the object forces the object to transition from the +** running state to the loaded state. if the object was not running, +** then there is no effect. it is necessary to close the OLE object +** before releasing the pointers to the OLE object. releasing all +** pointers to the object allows the object to transition from +** loaded to unloaded (or passive). +*/ +void ContainerLine_UnloadOleObject( + LPCONTAINERLINE lpContainerLine, + DWORD dwSaveOption +) +{ + if (lpContainerLine->m_lpOleObj) { + + OLEDBG_BEGIN2("IOleObject::Close called\r\n") + lpContainerLine->m_lpOleObj->lpVtbl->Close( + lpContainerLine->m_lpOleObj, dwSaveOption); + OLEDBG_END2 + + /* OLE2NOTE: we will take our IOleClientSite* pointer away from + ** the object before we release all pointers to the object. + ** in the scenario where the object is implemented as an + ** in-proc server (DLL object), then, if there are link + ** connections to the DLL object, it is possible that the + ** object will not be destroyed when we release our pointers + ** to the object. the existance of the remote link + ** connections will hold the object alive. later when these + ** strong connections are released, then the object may + ** attempt to call IOleClientSite::Save if we had not taken + ** away the client site pointer. + */ + OLEDBG_BEGIN2("IOleObject::SetClientSite(NULL) called\r\n") + lpContainerLine->m_lpOleObj->lpVtbl->SetClientSite( + lpContainerLine->m_lpOleObj, NULL); + OLEDBG_END2 + + OleStdRelease((LPUNKNOWN)lpContainerLine->m_lpOleObj); + lpContainerLine->m_lpOleObj = NULL; + + if (lpContainerLine->m_lpViewObj2) { + OleStdRelease((LPUNKNOWN)lpContainerLine->m_lpViewObj2); + lpContainerLine->m_lpViewObj2 = NULL; + } + if (lpContainerLine->m_lpPersistStg) { + OleStdRelease((LPUNKNOWN)lpContainerLine->m_lpPersistStg); + lpContainerLine->m_lpPersistStg = NULL; + } + + if (lpContainerLine->m_lpOleLink) { + OleStdRelease((LPUNKNOWN)lpContainerLine->m_lpOleLink); + lpContainerLine->m_lpOleLink = NULL; + } + } + + if (lpContainerLine->m_lpszShortType) { + OleStdFreeString(lpContainerLine->m_lpszShortType, NULL); + lpContainerLine->m_lpszShortType = NULL; + } +} + + +/* ContainerLine_Delete +** -------------------- +** Delete the ContainerLine. +** +** NOTE: we can NOT directly destroy the memory for the +** ContainerLine; the ContainerLine maintains a reference count. a +** non-zero reference count indicates that the object is still +** in-use. The OleObject keeps a reference-counted pointer to the +** ClientLine object. we must take the actions necessary so that the +** ContainerLine object receives Releases for outstanding +** references. when the reference count of the ContainerLine reaches +** zero, then the memory for the object will actually be destroyed +** (ContainerLine_Destroy called). +** +*/ +void ContainerLine_Delete(LPCONTAINERLINE lpContainerLine) +{ + OLEDBG_BEGIN2("ContainerLine_Delete\r\n") + +#if defined( INPLACE_CNTR ) + if (lpContainerLine == lpContainerLine->m_lpDoc->m_lpLastIpActiveLine) + lpContainerLine->m_lpDoc->m_lpLastIpActiveLine = NULL; + if (lpContainerLine == lpContainerLine->m_lpDoc->m_lpLastUIActiveLine) + lpContainerLine->m_lpDoc->m_lpLastUIActiveLine = NULL; +#endif + + /* OLE2NOTE: in order to have a stable line object during the + ** process of deleting, we intially AddRef the line ref cnt and + ** later Release it. This initial AddRef is artificial; it is + ** simply done to guarantee that our object does not destroy + ** itself until the END of this routine. + */ + ContainerLine_AddRef(lpContainerLine); + + // Unload the loaded OLE object + if (lpContainerLine->m_lpOleObj) + ContainerLine_UnloadOleObject(lpContainerLine, OLECLOSE_NOSAVE); + + /* OLE2NOTE: we can NOT directly free the memory for the ContainerLine + ** data structure until everyone holding on to a pointer to our + ** ClientSite interface and IAdviseSink interface has released + ** their pointers. There is one refcnt on the ContainerLine object + ** which is held by the container itself. we will release this + ** refcnt here. + */ + ContainerLine_Release(lpContainerLine); + + /* OLE2NOTE: this call forces all external connections to our + ** ContainerLine to close down and therefore guarantees that + ** we receive all releases associated with those external + ** connections. Strictly this call should NOT be necessary, but + ** it is defensive coding to make this call. + */ + OLEDBG_BEGIN2("CoDisconnectObject(lpContainerLine) called\r\n") + CoDisconnectObject((LPUNKNOWN)&lpContainerLine->m_Unknown, 0); + OLEDBG_END2 + +#if defined( _DEBUG ) + /* at this point the object all references from the OLE object to + ** our ContainerLine object should have been released. there + ** should only be 1 remaining reference that will be released below. + */ + if (lpContainerLine->m_cRef != 1) { + OleDbgOutRefCnt( + "WARNING: ContainerLine_Delete: cRef != 1\r\n", + lpContainerLine, + lpContainerLine->m_cRef + ); + } +#endif + + ContainerLine_Release(lpContainerLine); // release artificial AddRef above + OLEDBG_END2 +} + + +/* ContainerLine_Destroy +** --------------------- +** Destroy (Free) the memory used by a ContainerLine structure. +** This function is called when the ref count of the ContainerLine goes +** to zero. the ref cnt goes to zero after ContainerLine_Delete forces +** the OleObject to unload and release its pointers to the +** ContainerLine IOleClientSite and IAdviseSink interfaces. +*/ + +void ContainerLine_Destroy(LPCONTAINERLINE lpContainerLine) +{ + LPUNKNOWN lpTmpObj; + + OLEDBG_BEGIN2("ContainerLine_Destroy\r\n") + + // Release the storage opened for the OLE object + if (lpContainerLine->m_lpStg) { + lpTmpObj = (LPUNKNOWN)lpContainerLine->m_lpStg; + lpContainerLine->m_lpStg = NULL; + + OleStdRelease(lpTmpObj); + } + + if (lpContainerLine->m_lpszShortType) { + OleStdFreeString(lpContainerLine->m_lpszShortType, NULL); + lpContainerLine->m_lpszShortType = NULL; + } + + Delete(lpContainerLine); // Free the memory for the structure itself + OLEDBG_END2 +} + + +/* ContainerLine_CopyToDoc + * ----------------------- + * + * Copy a ContainerLine to another Document (usually ClipboardDoc) + */ +BOOL ContainerLine_CopyToDoc( + LPCONTAINERLINE lpSrcLine, + LPOUTLINEDOC lpDestDoc, + int nIndex +) +{ + LPCONTAINERLINE lpDestLine = NULL; + LPLINELIST lpDestLL = &lpDestDoc->m_LineList; + HDC hDC; + HRESULT hrErr; + BOOL fStatus; + LPSTORAGE lpDestDocStg = ((LPOLEDOC)lpDestDoc)->m_lpStg; + LPSTORAGE lpDestObjStg = NULL; + + lpDestLine = (LPCONTAINERLINE) New((DWORD)sizeof(CONTAINERLINE)); + if (lpDestLine == NULL) { + OleDbgAssertSz(lpDestLine!=NULL, "Error allocating ContainerLine"); + return FALSE; + } + + hDC = LineList_GetDC(lpDestLL); + ContainerLine_Init(lpDestLine, ((LPLINE)lpSrcLine)->m_nTabLevel, hDC); + LineList_ReleaseDC(lpDestLL, hDC); + + /* OLE2NOTE: In order to have a stable ContainerLine object we must + ** AddRef the object's refcnt. this will be later released when + ** the ContainerLine is deleted. + */ + ContainerLine_AddRef(lpDestLine); + + lpDestLine->m_lpDoc = (LPCONTAINERDOC)lpDestDoc; + + // Copy data of the original source ContainerLine. + ((LPLINE)lpDestLine)->m_nWidthInHimetric = + ((LPLINE)lpSrcLine)->m_nWidthInHimetric; + ((LPLINE)lpDestLine)->m_nHeightInHimetric = + ((LPLINE)lpSrcLine)->m_nHeightInHimetric; + lpDestLine->m_fMonikerAssigned = lpSrcLine->m_fMonikerAssigned; + lpDestLine->m_dwDrawAspect = lpSrcLine->m_dwDrawAspect; + lpDestLine->m_sizeInHimetric = lpSrcLine->m_sizeInHimetric; + lpDestLine->m_dwLinkType = lpSrcLine->m_dwLinkType; + + + /* We must create a new sub-storage for the embedded object within + ** the destination document's storage. We will first attempt to + ** use the same storage name as the source line. if this name is + ** in use, then we will allocate a new name. in this way we try + ** to keep the name associated with the OLE object unchanged + ** through a Cut/Paste operation. + */ + lpDestObjStg = OleStdCreateChildStorage( + lpDestDocStg, + lpSrcLine->m_szStgName + ); + if (lpDestObjStg) { + lstrcpy(lpDestLine->m_szStgName, lpSrcLine->m_szStgName); + } else { + /* the original name was in use, make up a new name. */ + ContainerDoc_GetNextStgName( + (LPCONTAINERDOC)lpDestDoc, + lpDestLine->m_szStgName, + sizeof(lpDestLine->m_szStgName) + ); + lpDestObjStg = OleStdCreateChildStorage( + lpDestDocStg, + lpDestLine->m_szStgName + ); + } + if (lpDestObjStg == NULL) { + OleDbgAssertSz(lpDestObjStg != NULL, "Error creating child stg"); + goto error; + } + + // Copy over storage of the embedded object itself + + if (! lpSrcLine->m_lpOleObj) { + + /***************************************************************** + ** CASE 1: object is NOT loaded. + ** because the object is not loaded, we can simply copy the + ** object's current storage to the new storage. + *****************************************************************/ + + /* if current object storage is not already open, then open it */ + if (! lpSrcLine->m_lpStg) { + LPSTORAGE lpSrcDocStg = ((LPOLEDOC)lpSrcLine->m_lpDoc)->m_lpStg; + + if (! lpSrcDocStg) goto error; + + // open object storage. + lpSrcLine->m_lpStg = OleStdOpenChildStorage( + lpSrcDocStg, + lpSrcLine->m_szStgName, + STGM_READWRITE + ); + if (lpSrcLine->m_lpStg == NULL) { +#if defined( _DEBUG ) + OleDbgAssertSz( + lpSrcLine->m_lpStg != NULL, + "Error opening child stg" + ); +#endif + goto error; + } + } + + hrErr = lpSrcLine->m_lpStg->lpVtbl->CopyTo( + lpSrcLine->m_lpStg, + 0, + NULL, + NULL, + lpDestObjStg + ); + if (hrErr != NOERROR) { + OleDbgOutHResult("WARNING: lpSrcObjStg->CopyTo returned", hrErr); + goto error; + } + + fStatus = OleStdCommitStorage(lpDestObjStg); + + } else { + + /***************************************************************** + ** CASE 2: object IS loaded. + ** we must tell the object to save into the new storage. + *****************************************************************/ + + SCODE sc = S_OK; + LPPERSISTSTORAGE lpPersistStg = lpSrcLine->m_lpPersistStg; + OleDbgAssert(lpPersistStg); + + OLEDBG_BEGIN2("OleSave called\r\n") + hrErr = OleSave(lpPersistStg, lpDestObjStg, FALSE /*fSameAsLoad*/); + OLEDBG_END2 + + if (hrErr != NOERROR) { + OleDbgOutHResult("WARNING: OleSave returned", hrErr); + sc = GetScode(hrErr); + } + + // OLE2NOTE: even if OleSave fails, SaveCompleted must be called. + OLEDBG_BEGIN2("IPersistStorage::SaveCompleted called\r\n") + hrErr=lpPersistStg->lpVtbl->SaveCompleted(lpPersistStg,NULL); + OLEDBG_END2 + + if (hrErr != NOERROR) { + OleDbgOutHResult("WARNING: SaveCompleted returned",hrErr); + if (sc == S_OK) + sc = GetScode(hrErr); + } + + if (sc != S_OK) + goto error; + + } + + OutlineDoc_AddLine(lpDestDoc, (LPLINE)lpDestLine, nIndex); + OleStdVerifyRelease( + (LPUNKNOWN)lpDestObjStg, + "Copied object stg not released" + ); + + return TRUE; + +error: + + // Delete any partially created storage. + if (lpDestObjStg) { + + OleStdVerifyRelease( + (LPUNKNOWN)lpDestObjStg, + "Copied object stg not released" + ); + + { + CREATEOLESTR(polestr, lpDestLine->m_szStgName) + + lpDestDocStg->lpVtbl->DestroyElement( + lpDestDocStg, + lpDestLine->m_szStgName + ); + + FREEOLESTR(polestr); + } + + lpDestLine->m_szStgName[0] = '\0'; + } + + // destroy partially created ContainerLine + if (lpDestLine) + ContainerLine_Delete(lpDestLine); + return FALSE; +} + + +/* ContainerLine_UpdateExtent +** -------------------------- +** Update the size of the ContainerLine because the extents of the +** object may have changed. +** +** NOTE: because we are using a Windows OwnerDraw ListBox, we must +** constrain the maximum possible height of a line. the ListBox has +** a limitation (unfortunately) that no line can become larger than +** 255 pixels. thus we force the object to scale maintaining its +** aspect ratio if this maximum line height limit is reached. the +** actual maximum size for an object at 100% Zoom is +** 255 +** +** RETURNS TRUE -- if the extents of the object changed +** FALSE -- if the extents did NOT change +*/ +BOOL ContainerLine_UpdateExtent( + LPCONTAINERLINE lpContainerLine, + LPSIZEL lpsizelHim +) +{ + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerLine->m_lpDoc; + LPLINELIST lpLL = OutlineDoc_GetLineList(lpOutlineDoc); + LPLINE lpLine = (LPLINE)lpContainerLine; + int nIndex = LineList_GetLineIndex(lpLL, lpLine); + UINT nOrgWidthInHimetric = lpLine->m_nWidthInHimetric; + UINT nOrgHeightInHimetric = lpLine->m_nHeightInHimetric; + BOOL fWidthChanged = FALSE; + BOOL fHeightChanged = FALSE; + SIZEL sizelHim; + HRESULT hrErr; + + if (!lpContainerLine || !lpContainerLine->m_lpOleObj) + return FALSE; + + if (lpContainerLine->m_fGuardObj) + return FALSE; // object in process of creation + + OLEDBG_BEGIN3("ContainerLine_UpdateExtent\r\n"); + + lpContainerLine->m_fDoGetExtent = FALSE; + + if (! lpsizelHim) { + /* OLE2NOTE: We want to call IViewObject2::GetExtent instead of + ** IOleObject::GetExtent. IViewObject2::GetExtent method was + ** added in OLE 2.01 release. It always retrieves the + ** extents of the object corresponding to that which will be + ** drawn by calling IViewObject::Draw. Normally, this is + ** determined by the data stored in the data cache. This + ** call will never result in a remoted (LRPC) call. + */ + OLEDBG_BEGIN2("IViewObject2::GetExtent called\r\n") + hrErr = lpContainerLine->m_lpViewObj2->lpVtbl->GetExtent( + lpContainerLine->m_lpViewObj2, + lpContainerLine->m_dwDrawAspect, + -1, /*lindex*/ + NULL, /*ptd*/ + (LPSIZEL)&sizelHim + ); + OLEDBG_END2 + if (hrErr != NOERROR) + sizelHim.cx = sizelHim.cy = 0; + + lpsizelHim = (LPSIZEL)&sizelHim; + } + + if (lpsizelHim->cx == lpContainerLine->m_sizeInHimetric.cx && + lpsizelHim->cy == lpContainerLine->m_sizeInHimetric.cy) { + goto noupdate; + } + + if (lpsizelHim->cx > 0 || lpsizelHim->cy > 0) { + lpContainerLine->m_sizeInHimetric = *lpsizelHim; + } else { + /* object does not have any extents; let's use our container + ** chosen arbitrary size for OLE objects. + */ + lpContainerLine->m_sizeInHimetric.cx = (long)DEFOBJWIDTH; + lpContainerLine->m_sizeInHimetric.cy = (long)DEFOBJHEIGHT; + } + + ContainerLine_SetLineHeightFromObjectExtent( + lpContainerLine, + (LPSIZEL)&lpContainerLine->m_sizeInHimetric); + + // if height of object changed, then reset the height of line in LineList + if (nOrgHeightInHimetric != lpLine->m_nHeightInHimetric) { + LineList_SetLineHeight(lpLL, nIndex, lpLine->m_nHeightInHimetric); + fHeightChanged = TRUE; + } + + fWidthChanged = LineList_RecalcMaxLineWidthInHimetric( + lpLL, + nOrgWidthInHimetric + ); + fWidthChanged |= (nOrgWidthInHimetric != lpLine->m_nWidthInHimetric); + + if (fHeightChanged || fWidthChanged) { + OutlineDoc_ForceRedraw(lpOutlineDoc, TRUE); + + // mark ContainerDoc as now dirty + OutlineDoc_SetModified(lpOutlineDoc, TRUE, TRUE, TRUE); + } + + OLEDBG_END3 + return TRUE; + +noupdate: + OLEDBG_END3 + return FALSE; // No UPDATE necessary +} + + +/* ContainerLine_DoVerb +** -------------------- +** Activate the OLE object and perform a specific verb. +*/ +BOOL ContainerLine_DoVerb( + LPCONTAINERLINE lpContainerLine, + LONG iVerb, + LPMSG lpMsg, + BOOL fMessage, + BOOL fAction +) +{ + HRESULT hrErr; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerLine->m_lpDoc; + RECT rcPosRect; + OLEDBG_BEGIN3("ContainerLine_DoVerb\r\n") + + if (lpContainerLine->m_fGuardObj) { + // object in process of creation--Fail the DoVerb call + hrErr = ResultFromScode(E_FAIL); + goto error; + } + + /* if object is not already loaded, then load it now. objects are + ** loaded lazily in this manner. + */ + if (! lpContainerLine->m_lpOleObj) + ContainerLine_LoadOleObject(lpContainerLine); + + if (! lpContainerLine->m_lpOleObj) { +#if defined( _DEBUG ) + OleDbgAssertSz( + lpContainerLine->m_lpOleObj != NULL, + "OLE object not loaded" + ); +#endif + goto error; + } + +ExecuteDoVerb: + + ContainerLine_GetPosRect(lpContainerLine, (LPRECT)&rcPosRect); + + // run the object + hrErr = ContainerLine_RunOleObject(lpContainerLine); + if (hrErr != NOERROR) + goto error; + + /* Tell object server to perform a "verb". */ + OLEDBG_BEGIN2("IOleObject::DoVerb called\r\n") + hrErr = lpContainerLine->m_lpOleObj->lpVtbl->DoVerb ( + lpContainerLine->m_lpOleObj, + iVerb, + lpMsg, + (LPOLECLIENTSITE)&lpContainerLine->m_OleClientSite, + -1, + OutlineDoc_GetWindow(lpOutlineDoc), + (LPCRECT)&rcPosRect + ); + OLEDBG_END2 + + /* OLE2NOTE: IOleObject::DoVerb may return a success code + ** OLE_S_INVALIDVERB. this SCODE should NOT be considered an + ** error; thus it is important to use the "FAILED" macro to + ** check for an error SCODE. + */ + if (FAILED(GetScode(hrErr))) { + OleDbgOutHResult("WARNING: lpOleObj->DoVerb returned", hrErr); + goto error; + } + +#if defined( INPLACE_CNTR ) + /* OLE2NOTE: we want to keep only 1 inplace server active at any + ** given time. so when we start to do a DoVerb on another line, + ** then we want to shut down the previously activated server. in + ** this way we keep at most one inplace server active at a time. + ** because it is possible that the object we want to do DoVerb + ** on is handled by the same EXE as that of the previously + ** activated server, then we do not want the EXE to be shut down + ** only to be launched again. in order to avoid this we will do + ** the DoVerb BEFORE trying to shutdown the previous object. + */ + if (!g_fInsideOutContainer) { + ContainerDoc_ShutDownLastInPlaceServerIfNotNeeded( + lpContainerLine->m_lpDoc, lpContainerLine); + } +#endif // INPLACE_CNTR + + OLEDBG_END3 + return TRUE; + +error: + + if (lpContainerLine->m_dwLinkType != 0) + lpContainerLine->m_fLinkUnavailable = TRUE; + +#if defined( INPLACE_CNTR ) + /* OLE2NOTE: we want to keep only 1 inplace server active at any + ** given time. so when we start to do a DoVerb on another line, + ** then we want to shut down the previously activated server. in + ** this way we keep at most one inplace server active at a time. + ** even though the DoVerb failed, we will still shutdown the + ** previous server. it is possible that we ran out of memory and + ** that the DoVerb will succeed next time after shutting down + ** the pervious server. + */ + if (!g_fInsideOutContainer) { + ContainerDoc_ShutDownLastInPlaceServerIfNotNeeded( + lpContainerLine->m_lpDoc, lpContainerLine); + } +#endif // INPLACE_CNTR + + /* OLE2NOTE: if an error occurs we must give the appropriate error + ** message box. there are many potential errors that can occur. + ** the OLE2.0 user model has specific guidelines as to the + ** dialogs that should be displayed given the various potential + ** errors (eg. server not registered, unavailable link source. + ** the OLE2UI library includes support for most of the + ** recommended message dialogs. (see OleUIPrompUser function) + */ + if (fMessage) { + BOOL fReDoVerb = ContainerLine_ProcessOleRunError( + lpContainerLine, + hrErr, + fAction, + (lpMsg==NULL && iVerb>=0) /* fMenuInvoked */ + ); + if (fReDoVerb) { + goto ExecuteDoVerb; + } + } + + OLEDBG_END3 + return FALSE; +} + + + +/* ContainerLine_ProcessOleRunError + * -------------------------------- + * + * Handle the various errors possible when attempting OleRun of an object. + * Popup up appropriate message according to the error and/or take action + * specified button pressed by the user. + * + * OLE2NOTE: The OLE 2.0 User Interface Guidelines specify the messages + * that should be given for the following situations: + * 1. Link Source Unavailable...goto Links dialog + * 2. Server Not Registered...goto Convert dialog + * 3. Link Type Changed + * 4. Server Not Found + * + * Returns: TRUE -- repeat IOleObject::DoVerb call. + * FALSE -- do NOT repeat IOleObject::DoVerb call. + * + * Comments: + * (see LinkTypeChanged case) + */ +BOOL ContainerLine_ProcessOleRunError( + LPCONTAINERLINE lpContainerLine, + HRESULT hrErr, + BOOL fAction, + BOOL fMenuInvoked +) +{ + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerLine->m_lpDoc; + HWND hwndParent = OutlineDoc_GetWindow(lpOutlineDoc); + SCODE sc = GetScode(hrErr); + BOOL fReDoVerb = FALSE; + + OleDbgOutHResult("ProcessError", hrErr); + if ((sc >= MK_E_FIRST) && (sc <= MK_E_LAST)) + goto LinkSourceUnavailable; + if (sc == OLE_E_CANT_BINDTOSOURCE) + goto LinkSourceUnavailable; + if (sc == STG_E_PATHNOTFOUND) + goto LinkSourceUnavailable; + if (sc == REGDB_E_CLASSNOTREG) + goto ServerNotReg; + if (sc == OLE_E_STATIC) + goto ServerNotReg; // user dblclk'ed a static object w/ no svr reg'd + if (sc == OLE_E_CLASSDIFF) + goto LinkTypeChanged; + if (sc == CO_E_APPDIDNTREG) + goto ServerNotFound; + if (sc == CO_E_APPNOTFOUND) + goto ServerNotFound; + if (sc == E_OUTOFMEMORY) + goto OutOfMemory; + + if (ContainerLine_IsOleLink(lpContainerLine)) + goto LinkSourceUnavailable; + else + goto ServerNotFound; + + +/************************************************************************* +** Error handling routines ** +*************************************************************************/ +LinkSourceUnavailable: + if (ID_PU_LINKS == OleUIPromptUser( + (WORD)IDD_LINKSOURCEUNAVAILABLE, + hwndParent, + (LPSTR)APPNAME)) { + if (fAction) { + ContainerDoc_EditLinksCommand(lpContainerLine->m_lpDoc); + } + } + return fReDoVerb; + +ServerNotReg: + { + LPSTR lpszUserType = NULL; + CLIPFORMAT cfFormat; // not used + LPOLESTR polestr; + + hrErr = ReadFmtUserTypeStg( + lpContainerLine->m_lpStg, &cfFormat, &polestr); + + CopyAndFreeOLESTR(polestr, &lpszUserType); + + if (ID_PU_CONVERT == OleUIPromptUser( + (WORD)IDD_SERVERNOTREG, + hwndParent, + (LPSTR)APPNAME, + (hrErr == NOERROR) ? lpszUserType : (LPSTR)"Unknown Object")) { + if (fAction) { + ContainerDoc_ConvertCommand( + lpContainerLine->m_lpDoc, + TRUE // fMustActivate + ); + } + } + + if (lpszUserType) + OleStdFreeString(lpszUserType, NULL); + + return fReDoVerb; + } + + +LinkTypeChanged: + { + /* OLE2NOTE: If IOleObject::DoVerb is executed on a Link object and it + ** returns OLE_E_CLASSDIFF because the link source is no longer + ** the expected class, then if the verb is a semantically + ** defined verb (eg. OLEIVERB_PRIMARY, OLEIVERB_SHOW, + ** OLEIVERB_OPEN, etc.), then the link should be re-created with + ** the new link source and the same verb executed on the new + ** link. there is no need to give a message to the user. if the + ** user had selected a verb from the object's verb menu + ** (fMenuInvoked==TRUE), then we can not be certain of the + ** semantics of the verb and whether the new link can still + ** support the verb. in this case the user is given a prompt + ** telling him to "choose a different command offered by the new + ** type". + */ + + LPSTR lpszUserType = NULL; + + if (fMenuInvoked) { + LPOLESTR polestr; + + hrErr = lpContainerLine->m_lpOleObj->lpVtbl->GetUserType( + lpContainerLine->m_lpOleObj,USERCLASSTYPE_FULL, polestr); + + CopyAndFreeOLESTR(polestr, &lpszUserType); + + OleUIPromptUser( + (WORD)IDD_LINKTYPECHANGED, + hwndParent, + (LPSTR)APPNAME, + (hrErr == NOERROR) ? lpszUserType : (LPSTR)"Unknown Object" + ); + } else { + fReDoVerb = TRUE; + } + ContainerLine_ReCreateLinkBecauseClassDiff(lpContainerLine); + + if (lpszUserType) + OleStdFreeString(lpszUserType, NULL); + + return fReDoVerb; + } + +ServerNotFound: + + OleUIPromptUser( + (WORD)IDD_SERVERNOTFOUND, + hwndParent, + (LPSTR)APPNAME); + return fReDoVerb; + +OutOfMemory: + + OleUIPromptUser( + (WORD)IDD_OUTOFMEMORY, + hwndParent, + (LPSTR)APPNAME); + return fReDoVerb; +} + + +/* ContainerLine_ReCreateLinkBecauseClassDiff +** ------------------------------------------ +** Re-create the link. The existing link was created when +** the moniker binds to a link source bound of a different class +** than the same moniker currently binds to. the link may be a +** special link object specifically used with the old link +** source class. thus the link object needs to be re-created to +** give the new link source the opportunity to create its own +** special link object. (see description "Custom Link Source") +*/ +HRESULT ContainerLine_ReCreateLinkBecauseClassDiff( + LPCONTAINERLINE lpContainerLine +) +{ + LPOLELINK lpOleLink = lpContainerLine->m_lpOleLink; + HGLOBAL hMetaPict = NULL; + LPMONIKER lpmkLinkSrc = NULL; + SCODE sc = E_FAIL; + HRESULT hrErr; + + if (lpOleLink && + lpOleLink->lpVtbl->GetSourceMoniker( + lpOleLink, (LPMONIKER FAR*)&lpmkLinkSrc) == NOERROR) { + + BOOL fDisplayAsIcon = + (lpContainerLine->m_dwDrawAspect==DVASPECT_ICON); + STGMEDIUM medium; + LPDATAOBJECT lpDataObj = NULL; + DWORD dwOleRenderOpt; + FORMATETC renderFmtEtc; + LPFORMATETC lpRenderFmtEtc = NULL; + + // get the current icon if object is displayed as icon + if (fDisplayAsIcon && + (lpDataObj = (LPDATAOBJECT)OleStdQueryInterface( (LPUNKNOWN) + lpContainerLine->m_lpOleObj,&IID_IDataObject)) != NULL ) { + hMetaPict = OleStdGetData( + lpDataObj, CF_METAFILEPICT, NULL, DVASPECT_ICON, &medium); + OleStdRelease((LPUNKNOWN)lpDataObj); + } + + if (fDisplayAsIcon && hMetaPict) { + // a special icon should be used. first we create the object + // OLERENDER_NONE. then we stuff the special icon into the cache. + + dwOleRenderOpt = OLERENDER_NONE; + + } else if (fDisplayAsIcon && hMetaPict == NULL) { + // the object's default icon should be used + + dwOleRenderOpt = OLERENDER_DRAW; + lpRenderFmtEtc = (LPFORMATETC)&renderFmtEtc; + SETFORMATETC(renderFmtEtc,0,DVASPECT_ICON,NULL,TYMED_NULL,-1); + + } else { + // create standard DVASPECT_CONTENT/OLERENDER_DRAW object + dwOleRenderOpt = OLERENDER_DRAW; + } + + // unload original link object + ContainerLine_UnloadOleObject(lpContainerLine, OLECLOSE_SAVEIFDIRTY); + + // delete entire contents of the current object's storage + OleStdDestroyAllElements(lpContainerLine->m_lpStg); + + OLEDBG_BEGIN2("OleCreateLink called\r\n") + hrErr = OleCreateLink ( + lpmkLinkSrc, + &IID_IOleObject, + dwOleRenderOpt, + lpRenderFmtEtc, + (LPOLECLIENTSITE)&lpContainerLine->m_OleClientSite, + lpContainerLine->m_lpStg, + (LPVOID FAR*)&lpContainerLine->m_lpOleObj + ); + OLEDBG_END2 + + if (hrErr == NOERROR) { + if (! ContainerLine_SetupOleObject( + lpContainerLine, fDisplayAsIcon, hMetaPict) ) { + + // ERROR: setup of the new link failed. + // revert the storage to restore the original link. + ContainerLine_UnloadOleObject( + lpContainerLine, OLECLOSE_NOSAVE); + lpContainerLine->m_lpStg->lpVtbl->Revert( + lpContainerLine->m_lpStg); + sc = E_FAIL; + } else { + sc = S_OK; // IT WORKED! + + } + } + else { + sc = GetScode(hrErr); + OleDbgOutHResult("OleCreateLink returned", hrErr); + // ERROR: Re-creating the link failed. + // revert the storage to restore the original link. + lpContainerLine->m_lpStg->lpVtbl->Revert( + lpContainerLine->m_lpStg); + } + } + + if (hMetaPict) + OleUIMetafilePictIconFree(hMetaPict); // clean up metafile + return ResultFromScode(sc); +} + +/* ContainerLine_GetOleObject +** -------------------------- +** return pointer to desired interface of embedded/linked object. +** +** NOTE: this function causes an AddRef to the object. when the caller is +** finished with the object, it must call Release. +** this function does not AddRef the ContainerLine object. +*/ +LPUNKNOWN ContainerLine_GetOleObject( + LPCONTAINERLINE lpContainerLine, + REFIID riid +) +{ + /* if object is not already loaded, then load it now. objects are + ** loaded lazily in this manner. + */ + if (! lpContainerLine->m_lpOleObj) + ContainerLine_LoadOleObject(lpContainerLine); + + if (lpContainerLine->m_lpOleObj) + return OleStdQueryInterface( + (LPUNKNOWN)lpContainerLine->m_lpOleObj, + riid + ); + else + return NULL; +} + + + +/* ContainerLine_RunOleObject +** -------------------------- +** Load and run the object. Upon running and if size of object has changed, +** use SetExtent to change to new size. +** +*/ +HRESULT ContainerLine_RunOleObject(LPCONTAINERLINE lpContainerLine) +{ + LPLINE lpLine = (LPLINE)lpContainerLine; + SIZEL sizelNew; + HRESULT hrErr; + HCURSOR hPrevCursor; + + if (! lpContainerLine) + return NOERROR; + + if (lpContainerLine->m_fGuardObj) { + // object in process of creation--Fail to Run the object + return ResultFromScode(E_FAIL); + } + + if (lpContainerLine->m_lpOleObj && + OleIsRunning(lpContainerLine->m_lpOleObj)) + return NOERROR; // object already running + + // this may take a while, put up hourglass cursor + hPrevCursor = SetCursor(LoadCursor(NULL, IDC_WAIT)); + OLEDBG_BEGIN3("ContainerLine_RunOleObject\r\n") + + if (! lpContainerLine->m_lpOleObj) { + if (! ContainerLine_LoadOleObject(lpContainerLine)) + return ResultFromScode(E_OUTOFMEMORY); // Error: couldn't load obj + } + + OLEDBG_BEGIN2("OleRun called\r\n") + hrErr = OleRun((LPUNKNOWN)lpContainerLine->m_lpOleObj); + OLEDBG_END2 + + if (hrErr != NOERROR) { + SetCursor(hPrevCursor); // restore original cursor + + OleDbgOutHResult("OleRun returned", hrErr); + OLEDBG_END3 + return hrErr; + } + + if (lpContainerLine->m_fDoSetExtent) { + /* OLE2NOTE: the OLE object was resized when it was not running + ** and the object did not have the OLEMISC_RECOMPOSEONRESIZE + ** bit set. if it had, the object would have been run + ** immediately when it was resized. this flag indicates that + ** the object does something other than simple scaling when + ** it is resized. because the object is being run now, we + ** will call IOleObject::SetExtent. + */ + lpContainerLine->m_fDoSetExtent = FALSE; + + // the size stored in our Line includes the border around the object. + // we must subtract the border to get the size of the object itself. + sizelNew.cx = lpLine->m_nWidthInHimetric; + sizelNew.cy = lpLine->m_nHeightInHimetric; + + if ((sizelNew.cx != lpContainerLine->m_sizeInHimetric.cx) || + (sizelNew.cy != lpContainerLine->m_sizeInHimetric.cy)) { + + OLEDBG_BEGIN2("IOleObject::SetExtent called\r\n") + lpContainerLine->m_lpOleObj->lpVtbl->SetExtent( + lpContainerLine->m_lpOleObj, + lpContainerLine->m_dwDrawAspect, + (LPSIZEL)&sizelNew + ); + OLEDBG_END2 + } + } + + SetCursor(hPrevCursor); // restore original cursor + + OLEDBG_END3 + return NOERROR; + +} + + +/* ContainerLine_IsOleLink +** ----------------------- +** +** return TRUE if the ContainerLine has an OleLink. +** FALSE if the ContainerLine has an embedding +*/ +BOOL ContainerLine_IsOleLink(LPCONTAINERLINE lpContainerLine) +{ + if (!lpContainerLine) + return FALSE; + + return (lpContainerLine->m_dwLinkType != 0); +} + + +/* ContainerLine_Draw +** ------------------ +** +** Draw a ContainerLine object on a DC. +** +** Parameters: +** hDC - DC to which the line will be drawn +** lpRect - the object rect in logical coordinates +** lpRectWBounds - bounding rect of the metafile underneath hDC +** (NULL if hDC is not a metafile DC) +** fHighlight - TRUE if line has selection highlight +*/ +void ContainerLine_Draw( + LPCONTAINERLINE lpContainerLine, + HDC hDC, + LPRECT lpRect, + LPRECT lpRectWBounds, + BOOL fHighlight +) +{ + LPLINE lpLine = (LPLINE) lpContainerLine; + HRESULT hrErr = NOERROR; + RECTL rclHim; + RECTL rclHimWBounds; + RECT rcHim; + + if (lpContainerLine->m_fGuardObj) { + // object in process of creation--do NOT try to draw + return; + } + + /* if object is not already loaded, then load it now. objects are + ** loaded lazily in this manner. + */ + if (! lpContainerLine->m_lpViewObj2) { + if (! ContainerLine_LoadOleObject(lpContainerLine)) + return; // Error: could not load object + } + + if (lpRectWBounds) { + rclHimWBounds.left = (long) lpRectWBounds->left; + rclHimWBounds.bottom = (long) lpRectWBounds->bottom; + rclHimWBounds.top = (long) lpRectWBounds->top; + rclHimWBounds.right = (long) lpRectWBounds->right; + } + + /* construct bounds rectangle for the object. + ** offset origin for object to correct tab indentation + */ + rclHim.left = (long) lpRect->left; + rclHim.bottom = (long) lpRect->bottom; + rclHim.top = (long) lpRect->top; + rclHim.right = (long) lpRect->right; + + rclHim.left += (long) ((LPLINE)lpContainerLine)->m_nTabWidthInHimetric; + rclHim.right += (long) ((LPLINE)lpContainerLine)->m_nTabWidthInHimetric; + +#if defined( INPLACE_CNTR ) + /* OLE2NOTE: if the OLE object currently has a visible in-place + ** window, then we do NOT want to draw on top of its window. + ** this could interfere with the object's display. + */ + if ( !lpContainerLine->m_fIpVisible ) +#endif + { + hrErr = lpContainerLine->m_lpViewObj2->lpVtbl->Draw( + lpContainerLine->m_lpViewObj2, + lpContainerLine->m_dwDrawAspect, + -1, + NULL, + NULL, + NULL, + hDC, + (LPRECTL)&rclHim, + (lpRectWBounds ? (LPRECTL)&rclHimWBounds : NULL), + NULL, + 0 + ); + if (hrErr != NOERROR) + OleDbgOutHResult("IViewObject::Draw returned", hrErr); + + if (lpContainerLine->m_fObjWinOpen) + { + rcHim.left = (int) rclHim.left; + rcHim.top = (int) rclHim.top; + rcHim.right = (int) rclHim.right; + rcHim.bottom = (int) rclHim.bottom; + + /* OLE2NOTE: if the object servers window is Open (ie. not active + ** in-place) then we must shade the object in our document to + ** indicate to the user that the object is open elsewhere. + */ + OleUIDrawShading((LPRECT)&rcHim, hDC, OLEUI_SHADE_FULLRECT, 0); + } + } + + /* if the object associated with the ContainerLine is an automatic + ** link then try to connect it with its LinkSource if the + ** LinkSource is already running. we do not want to force the + ** LinkSource to run. + ** + ** OLE2NOTE: a sophistocated container will want to continually + ** attempt to connect its automatic links. OLE does NOT + ** automatically connect links when link sources become + ** available. some containers will want to attempt to connect + ** its links as part of idle time processing. another strategy + ** is to attempt to connect an automatic link every time it is + ** drawn on the screen. (this is the strategy used by this + ** CntrOutl sample application.) + */ + if (lpContainerLine->m_dwLinkType == OLEUPDATE_ALWAYS) + ContainerLine_BindLinkIfLinkSrcIsRunning(lpContainerLine); + + return; +} + + +void ContainerLine_DrawSelHilight( + LPCONTAINERLINE lpContainerLine, + HDC hDC, // MM_TEXT mode + LPRECT lprcPix, // listbox rect + UINT itemAction, + UINT itemState +) +{ + LPLINE lpLine = (LPLINE)lpContainerLine; + RECT rcObj; + DWORD dwFlags = OLEUI_HANDLES_INSIDE | OLEUI_HANDLES_USEINVERSE; + int nHandleSize; + LPCONTAINERDOC lpContainerDoc; + + if (!lpContainerLine || !hDC || !lprcPix) + return; + + lpContainerDoc = lpContainerLine->m_lpDoc; + + // Get size of OLE object + ContainerLine_GetOleObjectRectInPixels(lpContainerLine, (LPRECT)&rcObj); + + nHandleSize = GetProfileInt("windows", "oleinplaceborderwidth", + DEFAULT_HATCHBORDER_WIDTH) + 1; + + OleUIDrawHandles((LPRECT)&rcObj, hDC, dwFlags, nHandleSize, TRUE); +} + +/* InvertDiffRect +** -------------- +** +** Paint the surrounding of the Obj rect black but within lprcPix +** (similar to the lprcPix minus lprcObj) +*/ +static void InvertDiffRect(LPRECT lprcPix, LPRECT lprcObj, HDC hDC) +{ + RECT rcBlack; + + // draw black in all space outside of object's rectangle + rcBlack.top = lprcPix->top; + rcBlack.bottom = lprcPix->bottom; + + rcBlack.left = lprcPix->left + 1; + rcBlack.right = lprcObj->left - 1; + InvertRect(hDC, (LPRECT)&rcBlack); + + rcBlack.left = lprcObj->right + 1; + rcBlack.right = lprcPix->right - 1; + InvertRect(hDC, (LPRECT)&rcBlack); + + rcBlack.top = lprcPix->top; + rcBlack.bottom = lprcPix->top + 1; + rcBlack.left = lprcObj->left - 1; + rcBlack.right = lprcObj->right + 1; + InvertRect(hDC, (LPRECT)&rcBlack); + + rcBlack.top = lprcPix->bottom; + rcBlack.bottom = lprcPix->bottom - 1; + rcBlack.left = lprcObj->left - 1; + rcBlack.right = lprcObj->right + 1; + InvertRect(hDC, (LPRECT)&rcBlack); +} + + +/* Edit the ContainerLine line object. +** returns TRUE if line was changed +** FALSE if the line was NOT changed +*/ +BOOL ContainerLine_Edit(LPCONTAINERLINE lpContainerLine, HWND hWndDoc,HDC hDC) +{ + ContainerLine_DoVerb(lpContainerLine, OLEIVERB_PRIMARY, NULL, TRUE, TRUE); + + /* assume object was NOT changed, if it was obj will send Changed + ** or Saved notification. + */ + return FALSE; +} + + + +/* ContainerLine_SetHeightInHimetric +** --------------------------------- +** +** Set the height of a ContainerLine object. The widht will be changed +** to keep the aspect ratio +*/ +void ContainerLine_SetHeightInHimetric(LPCONTAINERLINE lpContainerLine, int nHeight) +{ + LPLINE lpLine = (LPLINE)lpContainerLine; + SIZEL sizelOleObject; + HRESULT hrErr; + + if (!lpContainerLine) + return; + + if (lpContainerLine->m_fGuardObj) { + // object in process of creation--Fail to set the Height + return; + } + + if (nHeight != -1) { + BOOL fMustClose = FALSE; + BOOL fMustRun = FALSE; + + /* if object is not already loaded, then load it now. objects are + ** loaded lazily in this manner. + */ + if (! lpContainerLine->m_lpOleObj) + ContainerLine_LoadOleObject(lpContainerLine); + + // the height argument specifies the desired height for the Line. + sizelOleObject.cy = nHeight; + + // we will calculate the corresponding width for the object by + // maintaining the current aspect ratio of the object. + sizelOleObject.cx = (int)(sizelOleObject.cy * + lpContainerLine->m_sizeInHimetric.cx / + lpContainerLine->m_sizeInHimetric.cy); + + /* OLE2NOTE: if the OLE object is already running then we can + ** immediately call SetExtent. But, if the object is NOT + ** currently running then we will check if the object + ** indicates that it is normally recomposes itself on + ** resizing. ie. that the object does not simply scale its + ** display when it it resized. if so then we will force the + ** object to run so that we can call IOleObject::SetExtent. + ** SetExtent does not have any effect if the object is only + ** loaded. if the object does NOT indicate that it + ** recomposes on resize (OLEMISC_RECOMPOSEONRESIZE) then we + ** will wait till the next time that the object is run to + ** call SetExtent. we will store a flag in the ContainerLine + ** to indicate that a SetExtent is necessary. It is + ** necessary to persist this flag. + */ + if (! OleIsRunning(lpContainerLine->m_lpOleObj)) { + DWORD dwStatus; + + OLEDBG_BEGIN2("IOleObject::GetMiscStatus called\r\n") + hrErr = lpContainerLine->m_lpOleObj->lpVtbl->GetMiscStatus( + lpContainerLine->m_lpOleObj, + lpContainerLine->m_dwDrawAspect, + (LPDWORD)&dwStatus + ); + OLEDBG_END2 + if (hrErr == NOERROR && (dwStatus & OLEMISC_RECOMPOSEONRESIZE)) { + // force the object to run + ContainerLine_RunOleObject(lpContainerLine); + fMustClose = TRUE; + } else { + /* the OLE object is NOT running and does NOT + ** recompose on resize. simply scale the object now + ** and do the SetExtent the next time the object is + ** run. we set the Line to the new size even though + ** the object's extents have not been changed. + ** this has the result of scaling the object's + ** display to the new size. + */ + lpContainerLine->m_fDoSetExtent = TRUE; + ContainerLine_SetLineHeightFromObjectExtent( + lpContainerLine, (LPSIZEL)&sizelOleObject); + return; + } + } + + OLEDBG_BEGIN2("IOleObject::SetExtent called\r\n") + hrErr = lpContainerLine->m_lpOleObj->lpVtbl->SetExtent( + lpContainerLine->m_lpOleObj, + lpContainerLine->m_dwDrawAspect, + (LPSIZEL)&sizelOleObject); + OLEDBG_END2 + + if (hrErr != NOERROR) { + /* OLE Object refuses to take on the new extents. Set the + ** Line to the new size even though the object refused + ** the new extents. this has the result of scaling the + ** object's display to the new size. + ** + ** if the object HAD accepted the new extents, then it + ** will send out an OnViewChange/OnDataChange + ** notification. this results in our container receiving + ** an OnViewChange notification; the line height will be + ** reset when this notification is received. + */ + ContainerLine_SetLineHeightFromObjectExtent( + lpContainerLine, (LPSIZEL)&sizelOleObject); + } + + if (fMustClose) + ContainerLine_CloseOleObject( + lpContainerLine, OLECLOSE_SAVEIFDIRTY); + } + else { + /* Set the line to default height given the natural (unscaled) + ** extents of the OLE object. + */ + ContainerLine_SetLineHeightFromObjectExtent( + lpContainerLine,(LPSIZEL)&lpContainerLine->m_sizeInHimetric); + } + +} + + +/* ContainerLine_SetLineHeightFromObjectExtent + * + * Purpose: + * Calculate the corresponding line height from the OleObject size + * Scale the line height to fit the limit if necessary + * + * Parameters: + * lpsizelOleObject pointer to size of OLE Object + * + * Returns: + * nil + */ +void ContainerLine_SetLineHeightFromObjectExtent( + LPCONTAINERLINE lpContainerLine, + LPSIZEL lpsizelOleObject +) +{ + LPLINE lpLine = (LPLINE)lpContainerLine; + + UINT uMaxObjectHeight = XformHeightInPixelsToHimetric(NULL, + LISTBOX_HEIGHT_LIMIT); + + if (!lpContainerLine || !lpsizelOleObject) + return; + + if (lpContainerLine->m_fGuardObj) { + // object in process of creation--Fail to set the Height + return; + } + + lpLine->m_nWidthInHimetric = (int)lpsizelOleObject->cx; + lpLine->m_nHeightInHimetric = (int)lpsizelOleObject->cy; + + // Rescale the object if height is greater than the limit + if (lpLine->m_nHeightInHimetric > (UINT)uMaxObjectHeight) { + + lpLine->m_nWidthInHimetric = (UINT) + ((long)lpLine->m_nWidthInHimetric * + (long)uMaxObjectHeight / + (long)lpLine->m_nHeightInHimetric); + + lpLine->m_nHeightInHimetric = uMaxObjectHeight; + } + +} + + +/* ContainerLine_SaveToStg +** ----------------------- +** Save a given ContainerLine and associated OLE object to an IStorage*. +*/ +BOOL ContainerLine_SaveToStm( + LPCONTAINERLINE lpContainerLine, + LPSTREAM lpLLStm +) +{ + CONTAINERLINERECORD objLineRecord; + ULONG nWritten; + HRESULT hrErr; + + lstrcpy(objLineRecord.m_szStgName, lpContainerLine->m_szStgName); + objLineRecord.m_fMonikerAssigned = lpContainerLine->m_fMonikerAssigned; + objLineRecord.m_dwDrawAspect = lpContainerLine->m_dwDrawAspect; + objLineRecord.m_sizeInHimetric = lpContainerLine->m_sizeInHimetric; + objLineRecord.m_dwLinkType = lpContainerLine->m_dwLinkType; + objLineRecord.m_fDoSetExtent = lpContainerLine->m_fDoSetExtent; + + /* write line record */ + hrErr = lpLLStm->lpVtbl->Write( + lpLLStm, + (LPVOID)&objLineRecord, + sizeof(CONTAINERLINERECORD), + &nWritten + ); + + if (hrErr != NOERROR) { + OleDbgAssertSz(hrErr == NOERROR,"Could not write to LineList stream"); + return FALSE; + } + + return TRUE; +} + + +/* ContainerLine_SaveOleObjectToStg +** -------------------------------- +** Save the OLE object associated with the ContainerLine to an IStorage*. +*/ +BOOL ContainerLine_SaveOleObjectToStg( + LPCONTAINERLINE lpContainerLine, + LPSTORAGE lpSrcStg, + LPSTORAGE lpDestStg, + BOOL fRemember +) +{ + HRESULT hrErr; + SCODE sc = S_OK; + BOOL fStatus; + BOOL fSameAsLoad = (lpSrcStg==lpDestStg ? TRUE : FALSE); + LPSTORAGE lpObjDestStg; + + if (lpContainerLine->m_fGuardObj) { + // object in process of creation--Fail to save + return FALSE; + } + + if (! lpContainerLine->m_lpOleObj) { + + /***************************************************************** + ** CASE 1: object is NOT loaded. + *****************************************************************/ + + if (fSameAsLoad) { + /************************************************************* + ** CASE 1A: we are saving to the current storage. because + ** the object is not loaded, it is up-to-date + ** (ie. nothing to do). + *************************************************************/ + + ; + + } else { + /************************************************************* + ** CASE 1B: we are saving to a new storage. because + ** the object is not loaded, we can simply copy the + ** object's current storage to the new storage. + *************************************************************/ + + /* if current object storage is not already open, then open it */ + if (! lpContainerLine->m_lpStg) { + lpContainerLine->m_lpStg = OleStdOpenChildStorage( + lpSrcStg, + lpContainerLine->m_szStgName, + STGM_READWRITE + ); + if (lpContainerLine->m_lpStg == NULL) { +#if defined( _DEBUG ) + OleDbgAssertSz( + lpContainerLine->m_lpStg != NULL, + "Error opening child stg" + ); +#endif + return FALSE; + } + } + + /* Create a child storage inside the destination storage. */ + lpObjDestStg = OleStdCreateChildStorage( + lpDestStg, + lpContainerLine->m_szStgName + ); + + if (lpObjDestStg == NULL) { +#if defined( _DEBUG ) + OleDbgAssertSz( + lpObjDestStg != NULL, + "Could not create obj storage!" + ); +#endif + return FALSE; + } + + hrErr = lpContainerLine->m_lpStg->lpVtbl->CopyTo( + lpContainerLine->m_lpStg, + 0, + NULL, + NULL, + lpObjDestStg + ); + // REVIEW: should we handle error here? + fStatus = OleStdCommitStorage(lpObjDestStg); + + /* if we are supposed to remember this storage as the new + ** storage for the object, then release the old one and + ** save the new one. else, throw away the new one. + */ + if (fRemember) { + OleStdVerifyRelease( + (LPUNKNOWN)lpContainerLine->m_lpStg, + "Original object stg not released" + ); + lpContainerLine->m_lpStg = lpObjDestStg; + } else { + OleStdVerifyRelease( + (LPUNKNOWN)lpObjDestStg, + "Copied object stg not released" + ); + } + } + + } else { + + /***************************************************************** + ** CASE 2: object IS loaded. + *****************************************************************/ + + if (fSameAsLoad) { + /************************************************************* + ** CASE 2A: we are saving to the current storage. if the object + ** is not dirty, then the current storage is up-to-date + ** (ie. nothing to do). + *************************************************************/ + + LPPERSISTSTORAGE lpPersistStg = lpContainerLine->m_lpPersistStg; + OleDbgAssert(lpPersistStg); + + hrErr = lpPersistStg->lpVtbl->IsDirty(lpPersistStg); + + /* OLE2NOTE: we will only accept an explicit "no i + ** am NOT dirty statement" (ie. S_FALSE) as an + ** indication that the object is clean. eg. if + ** the object returns E_NOTIMPL we must + ** interpret it as the object IS dirty. + */ + if (GetScode(hrErr) != S_FALSE) { + + /* OLE object IS dirty */ + + OLEDBG_BEGIN2("OleSave called\r\n") + hrErr = OleSave( + lpPersistStg, lpContainerLine->m_lpStg, fSameAsLoad); + OLEDBG_END2 + + if (hrErr != NOERROR) { + OleDbgOutHResult("WARNING: OleSave returned", hrErr); + sc = GetScode(hrErr); + } + + // OLE2NOTE: if OleSave fails, SaveCompleted must be called. + OLEDBG_BEGIN2("IPersistStorage::SaveCompleted called\r\n") + hrErr=lpPersistStg->lpVtbl->SaveCompleted(lpPersistStg,NULL); + OLEDBG_END2 + + if (hrErr != NOERROR) { + OleDbgOutHResult("WARNING: SaveCompleted returned",hrErr); + if (sc == S_OK) + sc = GetScode(hrErr); + } + + if (sc != S_OK) + return FALSE; + } + + } else { + /************************************************************* + ** CASE 2B: we are saving to a new storage. we must + ** tell the object to save into the new storage. + *************************************************************/ + + LPPERSISTSTORAGE lpPersistStg = lpContainerLine->m_lpPersistStg; + + if (! lpPersistStg) return FALSE; + + /* Create a child storage inside the destination storage. */ + lpObjDestStg = OleStdCreateChildStorage( + lpDestStg, + lpContainerLine->m_szStgName + ); + + if (lpObjDestStg == NULL) { +#if defined( _DEBUG ) + OleDbgAssertSz( + lpObjDestStg != NULL, + "Could not create object storage!" + ); +#endif + return FALSE; + } + + OLEDBG_BEGIN2("OleSave called\r\n") + hrErr = OleSave(lpPersistStg, lpObjDestStg, fSameAsLoad); + OLEDBG_END2 + + // OLE2NOTE: even if OleSave fails, must still call SaveCompleted + if (hrErr != NOERROR) { + OleDbgOutHResult("WARNING: OleSave returned", hrErr); + sc = GetScode(hrErr); + } + + /* OLE2NOTE: a root level container should immediately + ** call IPersistStorage::SaveCompleted after calling + ** OleSave. a nested level container should not call + ** SaveCompleted now, but must wait until SaveCompleted + ** is call on it by its container. since our container + ** is not a container/server, then we always call + ** SaveComplete here. + ** + ** if this is a SaveAs operation, then we need to pass + ** the lpStg back in SaveCompleted to inform the object + ** of its new storage that it may hold on to. if this is + ** a Save or a SaveCopyAs operation, then we simply pass + ** NULL in SaveCompleted; the object can continue to hold + ** its current storage. if an error occurs during the + ** OleSave call we must still call SaveCompleted but we + ** must pass NULL. + */ + OLEDBG_BEGIN2("IPersistStorage::SaveCompleted called\r\n") + hrErr = lpPersistStg->lpVtbl->SaveCompleted( + lpPersistStg, + ((FAILED(sc) || !fRemember) ? NULL : lpObjDestStg) + ); + OLEDBG_END2 + + if (hrErr != NOERROR) { + OleDbgOutHResult("WARNING: SaveCompleted returned",hrErr); + if (sc == S_OK) + sc = GetScode(hrErr); + } + + if (sc != S_OK) { + OleStdVerifyRelease( + (LPUNKNOWN)lpObjDestStg, + "Copied object stg not released" + ); + return FALSE; + } + + /* if we are supposed to remember this storage as the new + ** storage for the object, then release the old one and + ** save the new one. else, throw away the new one. + */ + if (fRemember) { + OleStdVerifyRelease( + (LPUNKNOWN)lpContainerLine->m_lpStg, + "Original object stg not released" + ); + lpContainerLine->m_lpStg = lpObjDestStg; + } else { + OleStdVerifyRelease( + (LPUNKNOWN)lpObjDestStg, + "Copied object stg not released" + ); + } + } + } + + /* OLE2NOTE: after saving an OLE object it is possible that it sent + ** an OnViewChange notification because it had been modified. in + ** this situation it is possible that the extents of the object + ** have changed. if so we want to relayout the space for the + ** object immediately so that the extent information saved with + ** the ContainerLine match the data saved with the OLE object + ** itself. + */ + if (lpContainerLine->m_fDoGetExtent) { + BOOL fSizeChanged = ContainerLine_UpdateExtent(lpContainerLine, NULL); +#if defined( INPLACE_CNTR ) + /* if the extents of this ContainerLine have changed, then we + ** need to reset the fDoGetExtent flag to TRUE so that later + ** when ContainerDoc_UpdateExtentOfAllOleObjects is called + ** (when the WM_U_UPDATEOBJECTEXTENT message is processed), + ** it is recognized that the extents of this line have + ** changed. if any line changes size, then any in-place + ** active object below this line must be told to update the + ** position of their windows (via SetObjectRects -- see + ** ContainerDoc_UpdateInPlaceObjectRects function). + */ + lpContainerLine->m_fDoGetExtent = fSizeChanged; +#endif + } + + return TRUE; +} + + +/* ContainerLine_LoadFromStg +** ------------------------- +** Create a ContainerLine object and initialize it with data that +** was previously writen to an IStorage*. this function does not +** immediately OleLoad the associated OLE object, only the data of +** the ContainerLine object itself is loaded from the IStorage*. +*/ +LPLINE ContainerLine_LoadFromStg( + LPSTORAGE lpSrcStg, + LPSTREAM lpLLStm, + LPOUTLINEDOC lpDestDoc +) +{ + HDC hDC; + LPLINELIST lpDestLL = &lpDestDoc->m_LineList; + ULONG nRead; + HRESULT hrErr; + LPCONTAINERLINE lpContainerLine; + CONTAINERLINERECORD objLineRecord; + + lpContainerLine=(LPCONTAINERLINE) New((DWORD)sizeof(CONTAINERLINE)); + if (lpContainerLine == NULL) { + OleDbgAssertSz(lpContainerLine!=NULL,"Error allocating ContainerLine"); + return NULL; + } + + hDC = LineList_GetDC(lpDestLL); + ContainerLine_Init(lpContainerLine, 0, hDC); + LineList_ReleaseDC(lpDestLL, hDC); + + /* OLE2NOTE: In order to have a stable ContainerLine object we must + ** AddRef the object's refcnt. this will be later released when + ** the ContainerLine is deleted. + */ + ContainerLine_AddRef(lpContainerLine); + + lpContainerLine->m_lpDoc = (LPCONTAINERDOC) lpDestDoc; + + /* read line record */ + hrErr = lpLLStm->lpVtbl->Read( + lpLLStm, + (LPVOID)&objLineRecord, + sizeof(CONTAINERLINERECORD), + &nRead + ); + + if (hrErr != NOERROR) { + OleDbgAssertSz(hrErr==NOERROR, "Could not read from LineList stream"); + goto error; + } + + lstrcpy(lpContainerLine->m_szStgName, objLineRecord.m_szStgName); + lpContainerLine->m_fMonikerAssigned = objLineRecord.m_fMonikerAssigned; + lpContainerLine->m_dwDrawAspect = objLineRecord.m_dwDrawAspect; + lpContainerLine->m_sizeInHimetric = objLineRecord.m_sizeInHimetric; + lpContainerLine->m_dwLinkType = objLineRecord.m_dwLinkType; + lpContainerLine->m_fDoSetExtent = objLineRecord.m_fDoSetExtent; + + return (LPLINE)lpContainerLine; + +error: + // destroy partially created ContainerLine + if (lpContainerLine) + ContainerLine_Delete(lpContainerLine); + return NULL; +} + + +/* ContainerLine_GetTextLen + * ------------------------ + * + * Return length of the string representation of the ContainerLine + * (not considering the tab level). we will use the following as the + * string representation of a ContainerLine: + * "<" + user type name of OLE object + ">" + * eg: + * + */ +int ContainerLine_GetTextLen(LPCONTAINERLINE lpContainerLine) +{ + LPSTR lpszUserType = NULL; + HRESULT hrErr; + int nLen; + BOOL fIsLink = ContainerLine_IsOleLink(lpContainerLine); + + /* if object is not already loaded, then load it now. objects are + ** loaded lazily in this manner. + */ + if (! lpContainerLine->m_lpOleObj) + ContainerLine_LoadOleObject(lpContainerLine); + + OLEDBG_BEGIN2("IOleObject::GetUserType called\r\n") + + { + LPOLESTR polestr; + + hrErr = lpContainerLine->m_lpOleObj->lpVtbl->GetUserType( + lpContainerLine->m_lpOleObj, + USERCLASSTYPE_FULL, + &polestr + ); + + CopyAndFreeOLESTR(polestr, &lpszUserType); + } + + OLEDBG_END2 + + if (hrErr != NOERROR) { + // user type is NOT available + nLen = sizeof(UNKNOWN_OLEOBJ_TYPE) + 2; // allow space for '<' + '>' + nLen += lstrlen((LPSTR)(fIsLink ? szOLELINK : szOLEOBJECT)) + 1; + } else { + nLen = lstrlen(lpszUserType) + 2; // allow space for '<' + '>' + nLen += lstrlen((LPSTR)(fIsLink ? szOLELINK : szOLEOBJECT)) + 1; + + /* OLE2NOTE: we must free the string that was allocated by the + ** IOleObject::GetUserType method. + */ + OleStdFreeString(lpszUserType, NULL); + } + + return nLen; +} + + +/* ContainerLine_GetTextData + * ------------------------- + * + * Return the string representation of the ContainerLine + * (not considering the tab level). we will use the following as the + * string representation of a ContainerLine: + * "<" + user type name of OLE object + ">" + * eg: + * + */ +void ContainerLine_GetTextData(LPCONTAINERLINE lpContainerLine, LPSTR lpszBuf) +{ + LPSTR lpszUserType = NULL; + BOOL fIsLink = ContainerLine_IsOleLink(lpContainerLine); + HRESULT hrErr; + LPOLESTR polestr; + + /* if object is not already loaded, then load it now. objects are + ** loaded lazily in this manner. + */ + if (! lpContainerLine->m_lpOleObj) + ContainerLine_LoadOleObject(lpContainerLine); + + { + LPOLESTR polestr; + + hrErr = lpContainerLine->m_lpOleObj->lpVtbl->GetUserType( + lpContainerLine->m_lpOleObj, + USERCLASSTYPE_FULL, + &lpszUserType + ); + + CopyAndFree(polestr, &lpszUserType); + } + + // Convert output to mbs + CopyAndFree(polestr, &lpszUserType); + + if (hrErr != NOERROR) { + // user type is NOT available + wsprintf( + lpszBuf, + "<%s %s>", + UNKNOWN_OLEOBJ_TYPE, + (LPSTR)(fIsLink ? szOLELINK : szOLEOBJECT) + ); + } else { + wsprintf( + lpszBuf, + "<%s %s>", + lpszUserType, + (LPSTR)(fIsLink ? szOLELINK : szOLEOBJECT) + ); + + /* OLE2NOTE: we must free the string that was allocated by the + ** IOleObject::GetUserType method. + */ + OleStdFreeString(lpszUserType, NULL); + } +} + + +/* ContainerLine_GetOutlineData + * ---------------------------- + * + * Return the CF_OUTLINE format data for the ContainerLine. + */ +BOOL ContainerLine_GetOutlineData( + LPCONTAINERLINE lpContainerLine, + LPTEXTLINE lpBuf +) +{ + LPLINE lpLine = (LPLINE)lpContainerLine; + LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerLine->m_lpDoc)->m_LineList; + HDC hDC; + char szTmpBuf[MAXSTRLEN+1]; + LPTEXTLINE lpTmpTextLine; + + // Create a TextLine with the Text representation of the ContainerLine. + ContainerLine_GetTextData(lpContainerLine, (LPSTR)szTmpBuf); + + hDC = LineList_GetDC(lpLL); + lpTmpTextLine = TextLine_Create(hDC, lpLine->m_nTabLevel, szTmpBuf); + LineList_ReleaseDC(lpLL, hDC); + + TextLine_Copy(lpTmpTextLine, lpBuf); + + // Delete the temporary TextLine + TextLine_Delete(lpTmpTextLine); + return TRUE; +} + + +/* ContainerLine_GetPosRect +** ----------------------- +** Get the PosRect in client coordinates for the OLE object's window. +** +** OLE2NOTE: the PosRect must take into account the scroll postion of +** the document window. +*/ +void ContainerLine_GetPosRect( + LPCONTAINERLINE lpContainerLine, + LPRECT lprcPosRect +) +{ + ContainerLine_GetOleObjectRectInPixels(lpContainerLine,lprcPosRect); + + // shift rect for left margin + lprcPosRect->left += lpContainerLine->m_nHorizScrollShift; + lprcPosRect->right += lpContainerLine->m_nHorizScrollShift; +} + + +/* ContainerLine_GetOleObjectRectInPixels +** -------------------------------------- +** Get the extent of the OLE Object contained in the given Line in +** client coordinates after scaling. +*/ +void ContainerLine_GetOleObjectRectInPixels(LPCONTAINERLINE lpContainerLine, LPRECT lprc) +{ + LPOUTLINEDOC lpOutlineDoc; + LPSCALEFACTOR lpscale; + LPLINELIST lpLL; + LPLINE lpLine; + int nIndex; + HDC hdcLL; + + if (!lpContainerLine || !lprc) + return; + + lpOutlineDoc = (LPOUTLINEDOC)lpContainerLine->m_lpDoc; + lpscale = OutlineDoc_GetScaleFactor(lpOutlineDoc); + lpLL = OutlineDoc_GetLineList(lpOutlineDoc); + lpLine = (LPLINE)lpContainerLine; + nIndex = LineList_GetLineIndex(lpLL, lpLine); + + LineList_GetLineRect(lpLL, nIndex, lprc); + + hdcLL = GetDC(lpLL->m_hWndListBox); + + /* lprc is set to be size of Line Object (including the boundary) */ + lprc->left += (int)( + (long)XformWidthInHimetricToPixels(hdcLL, + lpLine->m_nTabWidthInHimetric + + LOWORD(OutlineDoc_GetMargin(lpOutlineDoc))) * + lpscale->dwSxN / lpscale->dwSxD); + lprc->right = (int)( + lprc->left + (long) + XformWidthInHimetricToPixels(hdcLL, lpLine->m_nWidthInHimetric) * + lpscale->dwSxN / lpscale->dwSxD); + + ReleaseDC(lpLL->m_hWndListBox, hdcLL); +} + + +/* ContainerLine_GetOleObjectSizeInHimetric +** ---------------------------------------- +** Get the size of the OLE Object contained in the given Line +*/ +void ContainerLine_GetOleObjectSizeInHimetric(LPCONTAINERLINE lpContainerLine, LPSIZEL lpsizel) +{ + if (!lpContainerLine || !lpsizel) + return; + + *lpsizel = lpContainerLine->m_sizeInHimetric; +} + + +/* ContainerLine_BindLinkIfLinkSrcIsRunning +** ---------------------------------------- +** Try to connect the OLE link object associated with the +** ContainerLine with its LinkSource if the LinkSource is already +** running and the link is an automatic link. we do not want to +** force the LinkSource to run. +** +** OLE2NOTE: a sophistocated container will want to continually +** attempt to connect its automatic links. OLE does NOT +** automatically connect links when link source become available. some +** containers will want to attempt to connect its links as part of +** idle time processing. another strategy is to attempt to connect +** an automatic link every time it is drawn on the screen. (this is +** the strategy used by this CntrOutl sample application.) +*/ +void ContainerLine_BindLinkIfLinkSrcIsRunning(LPCONTAINERLINE lpContainerLine) +{ + LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; + HRESULT hrErr; + BOOL fPrevEnable1; + BOOL fPrevEnable2; + + // if the link source is known to be un-bindable, then don't even try + if (lpContainerLine->m_fLinkUnavailable) + return; + + /* OLE2NOTE: we do not want to ever give the Busy/NotResponding + ** dialogs when we are attempting to BindIfRunning to the link + ** source. if the link source is currently busy, this could + ** cause the Busy dialog to come up. even if the link source is + ** busy, we do not want put up the busy dialog. thus we will + ** disable the dialog and later re-enable them + */ + OleApp_DisableBusyDialogs(lpOleApp, &fPrevEnable1, &fPrevEnable2); + + OLEDBG_BEGIN2("IOleLink::BindIfRunning called\r\n") + hrErr = lpContainerLine->m_lpOleLink->lpVtbl->BindIfRunning( + lpContainerLine->m_lpOleLink); + OLEDBG_END2 + + // re-enable the Busy/NotResponding dialogs + OleApp_EnableBusyDialogs(lpOleApp, fPrevEnable1, fPrevEnable2); +} diff --git a/private/oleutest/letest/outline/cntroutl.h b/private/oleutest/letest/outline/cntroutl.h new file mode 100644 index 000000000..48930f3b3 --- /dev/null +++ b/private/oleutest/letest/outline/cntroutl.h @@ -0,0 +1,855 @@ +/************************************************************************* +** +** OLE 2.0 Container Sample Code +** +** cntroutl.h +** +** This file contains file contains data structure defintions, +** function prototypes, constants, etc. used by the OLE 2.0 container +** app version of the Outline series of sample applications: +** Outline -- base version of the app (without OLE functionality) +** SvrOutl -- OLE 2.0 Server sample app +** CntrOutl -- OLE 2.0 Containter (Container) sample app +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + +#if !defined( _CNTROUTL_H_ ) +#define _CNTROUTL_H_ + +#ifndef RC_INVOKED +#pragma message ("INCLUDING CNTROUTL.H from " __FILE__) +#endif /* RC_INVOKED */ + +#include "oleoutl.h" +#include "cntrrc.h" + +// REVIEW: should load from string resource +#define DEFOBJNAMEPREFIX "Obj" // Prefix for auto-generated stg names +#define DEFOBJWIDTH 5000 // default size for embedded obj. +#define DEFOBJHEIGHT 5000 // default size for embedded obj. +#define UNKNOWN_OLEOBJ_TYPE "Unknown OLE Object Type" +#define szOLEOBJECT "Object" +#define szOLELINK "Link" + +#define CONTAINERDOCFORMAT "CntrOutl" // CF_CntrOutl format name + +/* Forward definition of types */ +typedef struct tagCONTAINERDOC FAR* LPCONTAINERDOC; +typedef struct tagCONTAINERLINE FAR* LPCONTAINERLINE; + + +// Flags to specify type of OLECREATE???FROMDATA call required +typedef enum tagOLECREATEFROMDATATYPE { + OLECREATEFROMDATA_LINK = 1, + OLECREATEFROMDATA_OBJECT = 2, + OLECREATEFROMDATA_STATIC = 3 +} OLECREATEFROMDATATYPE; + +/************************************************************************* +** class CONTAINERLINE : LINE +** The class CONTAINERLINE is a concrete subclass of the abstract base +** class LINE. The CONTAINERLINE maintains all information about the +** place within the CONTAINERDOC that an OLE object is embedded. This +** object implements the following OLE 2.0 interfaces: +** IOleClientSite +** IAdviseSink +** In the CntrOutl client app either CONTAINERLINE objects or TEXTLINE +** objects can be created. The CONTAINERLINE class inherits all fields +** from the LINE class. This inheritance is achieved by including a +** member variable of type LINE as the first field in the CONTAINERLINE +** structure. Thus a pointer to a CONTAINERLINE object can be cast to be +** a pointer to a LINE object. +** Each CONTAINERLINE object that is created in added to the LINELIST of +** the associated OUTLINEDOC document. +*************************************************************************/ + +typedef struct tagCONTAINERLINE { + LINE m_Line; // ContainerLine inherits fields of Line + ULONG m_cRef; // total ref count for line + char m_szStgName[CWCSTORAGENAME]; // stg name w/i cntr stg + BOOL m_fObjWinOpen; // is obj window open? if so, shade obj. + BOOL m_fMonikerAssigned; // has a moniker been assigned to obj + DWORD m_dwDrawAspect; // current display aspect for obj + // (either DVASPECT_CONTENT or + // DVASPECT_ICON) + BOOL m_fGuardObj; // Guard against re-entrancy while + // loading or creating an OLE object + BOOL m_fDoGetExtent; // indicates extents may have changed + BOOL m_fDoSetExtent; // obj was resized when not running + // IOO::SetExtent needed on next run + SIZEL m_sizeInHimetric; // extents of obj in himetric units + LPSTORAGE m_lpStg; // open pstg when obj is loaded + LPCONTAINERDOC m_lpDoc; // ptr to associated client doc + LPOLEOBJECT m_lpOleObj; // ptr to IOleObject* when obj is loaded + LPVIEWOBJECT2 m_lpViewObj2; // ptr to IViewObject2* when obj is loaded + LPPERSISTSTORAGE m_lpPersistStg;// ptr to IPersistStorage* when obj loaded + LPOLELINK m_lpOleLink; // ptr to IOleLink* if link is loaded + DWORD m_dwLinkType; // is it a linked object? + // 0 -- NOT a link + // OLEUPDATE_ALWAYS (1) -- auto link + // OLEUPDATE_ONCALL (3) -- man. link + BOOL m_fLinkUnavailable; // is the link unavailable? + LPSTR m_lpszShortType;// short type name of OLE object needed + // to make the Edit.Object.Verb menu + int m_nHorizScrollShift; // horiz scroll shift required + // for object's inplace window. + // (note: this is ICNTROTL specific) + +#if defined( INPLACE_CNTR ) + BOOL m_fIpActive; // is object in-place active (undo valid) + BOOL m_fUIActive; // is object UIActive + BOOL m_fIpVisible; // is object's in-place window visible + BOOL m_fInsideOutObj;// is obj inside-out (visible when loaded) + LPOLEINPLACEOBJECT m_lpOleIPObj; // IOleInPlaceObject* of in-place obj + BOOL m_fIpChangesUndoable; // can in-place object do undo + BOOL m_fIpServerRunning; // is in-place server running + HWND m_hWndIpObject; + + struct COleInPlaceSiteImpl { + IOleInPlaceSiteVtbl FAR* lpVtbl; + LPCONTAINERLINE lpContainerLine; + int cRef; // interface specific ref count. + } m_OleInPlaceSite; +#endif // INPLACE_CNTR + + struct CUnknownImpl { + IUnknownVtbl FAR* lpVtbl; + LPCONTAINERLINE lpContainerLine; + int cRef; // interface specific ref count. + } m_Unknown; + + struct COleClientSiteImpl { + IOleClientSiteVtbl FAR* lpVtbl; + LPCONTAINERLINE lpContainerLine; + int cRef; // interface specific ref count. + } m_OleClientSite; + + struct CAdviseSinkImpl { + IAdviseSinkVtbl FAR* lpVtbl; + LPCONTAINERLINE lpContainerLine; + int cRef; // interface specific ref count. + } m_AdviseSink; + +} CONTAINERLINE; + + +/* ContainerLine methods (functions) */ +void ContainerLine_Init(LPCONTAINERLINE lpContainerLine, int nTab, HDC hDC); +BOOL ContainerLine_SetupOleObject( + LPCONTAINERLINE lpContainerLine, + BOOL fDisplayAsIcon, + HGLOBAL hMetaPict +); +LPCONTAINERLINE ContainerLine_Create( + DWORD dwOleCreateType, + HDC hDC, + UINT nTab, + LPCONTAINERDOC lpContainerDoc, + LPCLSID lpclsid, + LPSTR lpszFileName, + BOOL fDisplayAsIcon, + HGLOBAL hMetaPict, + LPSTR lpszStgName +); +LPCONTAINERLINE ContainerLine_CreateFromData( + HDC hDC, + UINT nTab, + LPCONTAINERDOC lpContainerDoc, + LPDATAOBJECT lpSrcDataObj, + DWORD dwCreateType, + CLIPFORMAT cfFormat, + BOOL fDisplayAsIcon, + HGLOBAL hMetaPict, + LPSTR lpszStgName +); +ULONG ContainerLine_AddRef(LPCONTAINERLINE lpContainerLine); +ULONG ContainerLine_Release(LPCONTAINERLINE lpContainerLine); +HRESULT ContainerLine_QueryInterface( + LPCONTAINERLINE lpContainerLine, + REFIID riid, + LPVOID FAR* lplpUnk +); +BOOL ContainerLine_CloseOleObject( + LPCONTAINERLINE lpContainerLine, + DWORD dwSaveOption +); +void ContainerLine_UnloadOleObject( + LPCONTAINERLINE lpContainerLine, + DWORD dwSaveOption +); +void ContainerLine_Delete(LPCONTAINERLINE lpContainerLine); +void ContainerLine_Destroy(LPCONTAINERLINE lpContainerLine); +BOOL ContainerLine_CopyToDoc( + LPCONTAINERLINE lpSrcLine, + LPOUTLINEDOC lpDestDoc, + int nIndex +); +BOOL ContainerLine_LoadOleObject(LPCONTAINERLINE lpContainerLine); +BOOL ContainerLine_UpdateExtent( + LPCONTAINERLINE lpContainerLine, + LPSIZEL lpsizelHim +); +BOOL ContainerLine_DoVerb( + LPCONTAINERLINE lpContainerLine, + LONG iVerb, + LPMSG lpMsg, + BOOL fMessage, + BOOL fAction +); +LPUNKNOWN ContainerLine_GetOleObject( + LPCONTAINERLINE lpContainerLine, + REFIID riid +); +HRESULT ContainerLine_RunOleObject(LPCONTAINERLINE lpContainerLine); +BOOL ContainerLine_ProcessOleRunError( + LPCONTAINERLINE lpContainerLine, + HRESULT hrErr, + BOOL fAction, + BOOL fMenuInvoked +); +HRESULT ContainerLine_ReCreateLinkBecauseClassDiff( + LPCONTAINERLINE lpContainerLine +); +BOOL ContainerLine_IsOleLink(LPCONTAINERLINE lpContainerLine); +void ContainerLine_BindLinkIfLinkSrcIsRunning(LPCONTAINERLINE lpContainerLine); +void ContainerLine_Draw( + LPCONTAINERLINE lpContainerLine, + HDC hDC, + LPRECT lpRect, + LPRECT lpRectWBounds, + BOOL fHighlight + +); +void ContainerLine_DrawSelHilight( + LPCONTAINERLINE lpContainerLine, + HDC hDC, + LPRECT lpRect, + UINT itemAction, + UINT itemState +); +BOOL ContainerLine_Edit(LPCONTAINERLINE lpContainerLine,HWND hWndDoc,HDC hDC); +void ContainerLine_SetHeightInHimetric(LPCONTAINERLINE lpContainerLine, int nHeight); +void ContainerLine_SetLineHeightFromObjectExtent( + LPCONTAINERLINE lpContainerLine, + LPSIZEL lpsizelOleObject +); +BOOL ContainerLine_SaveToStm( + LPCONTAINERLINE lpContainerLine, + LPSTREAM lpLLStm +); +BOOL ContainerLine_SaveOleObjectToStg( + LPCONTAINERLINE lpContainerLine, + LPSTORAGE lpSrcStg, + LPSTORAGE lpDestStg, + BOOL fRemember +); +LPLINE ContainerLine_LoadFromStg( + LPSTORAGE lpSrcStg, + LPSTREAM lpLLStm, + LPOUTLINEDOC lpDestDoc +); +LPMONIKER ContainerLine_GetRelMoniker( + LPCONTAINERLINE lpContainerLine, + DWORD dwAssign +); +LPMONIKER ContainerLine_GetFullMoniker( + LPCONTAINERLINE lpContainerLine, + DWORD dwAssign +); +int ContainerLine_GetTextLen(LPCONTAINERLINE lpContainerLine); +void ContainerLine_GetTextData(LPCONTAINERLINE lpContainerLine,LPSTR lpszBuf); +BOOL ContainerLine_GetOutlineData( + LPCONTAINERLINE lpContainerLine, + LPTEXTLINE lpBuf +); +void ContainerLine_GetOleObjectRectInPixels( + LPCONTAINERLINE lpContainerLine, + LPRECT lprc +); +void ContainerLine_GetPosRect( + LPCONTAINERLINE lpContainerLine, + LPRECT lprcPosRect +); +void ContainerLine_GetOleObjectSizeInHimetric( + LPCONTAINERLINE lpContainerLine, + LPSIZEL lpsizel +); + +#if defined( INPLACE_CNTR ) +void ContainerLine_UIDeactivate(LPCONTAINERLINE lpContainerLine); +void ContainerLine_InPlaceDeactivate(LPCONTAINERLINE lpContainerLine); +void ContainerLine_UpdateInPlaceObjectRects( + LPCONTAINERLINE lpContainerLine, + LPRECT lprcClipRect +); +void ContainerLine_ContextSensitiveHelp( + LPCONTAINERLINE lpContainerLine, + BOOL fEnterMode +); +void ContainerLine_ForwardPaletteChangedMsg( + LPCONTAINERLINE lpContainerLine, + HWND hwndPalChg +); +void ContainerDoc_ContextSensitiveHelp( + LPCONTAINERDOC lpContainerDoc, + BOOL fEnterMode, + BOOL fInitiatedByObj +); +void ContainerDoc_ForwardPaletteChangedMsg( + LPCONTAINERDOC lpContainerDoc, + HWND hwndPalChg +); +#endif // INPLACE_CNTR + +/* ContainerLine::IUnknown methods (functions) */ +STDMETHODIMP CntrLine_Unk_QueryInterface( + LPUNKNOWN lpThis, + REFIID riid, + LPVOID FAR* lplpvObj +); +STDMETHODIMP_(ULONG) CntrLine_Unk_AddRef(LPUNKNOWN lpThis); +STDMETHODIMP_(ULONG) CntrLine_Unk_Release(LPUNKNOWN lpThis); + +/* ContainerLine::IOleClientSite methods (functions) */ +STDMETHODIMP CntrLine_CliSite_QueryInterface( + LPOLECLIENTSITE lpThis, + REFIID riid, + LPVOID FAR* lplpvObj +); +STDMETHODIMP_(ULONG) CntrLine_CliSite_AddRef(LPOLECLIENTSITE lpThis); +STDMETHODIMP_(ULONG) CntrLine_CliSite_Release(LPOLECLIENTSITE lpThis); +STDMETHODIMP CntrLine_CliSite_SaveObject(LPOLECLIENTSITE lpThis); +STDMETHODIMP CntrLine_CliSite_GetMoniker( + LPOLECLIENTSITE lpThis, + DWORD dwAssign, + DWORD dwWhichMoniker, + LPMONIKER FAR* lplpmk +); +STDMETHODIMP CntrLine_CliSite_GetContainer( + LPOLECLIENTSITE lpThis, + LPOLECONTAINER FAR* lplpContainer +); +STDMETHODIMP CntrLine_CliSite_ShowObject(LPOLECLIENTSITE lpThis); +STDMETHODIMP CntrLine_CliSite_OnShowWindow(LPOLECLIENTSITE lpThis,BOOL fShow); +STDMETHODIMP CntrLine_CliSite_RequestNewObjectLayout(LPOLECLIENTSITE lpThis); + +/* ContainerLine::IAdviseSink methods (functions) */ +STDMETHODIMP CntrLine_AdvSink_QueryInterface( + LPADVISESINK lpThis, + REFIID riid, + LPVOID FAR* lplpvObj +); +STDMETHODIMP_(ULONG) CntrLine_AdvSink_AddRef(LPADVISESINK lpThis); +STDMETHODIMP_(ULONG) CntrLine_AdvSink_Release (LPADVISESINK lpThis); +STDMETHODIMP_(void) CntrLine_AdvSink_OnDataChange( + LPADVISESINK lpThis, + FORMATETC FAR* lpFormatetc, + STGMEDIUM FAR* lpStgmed +); +STDMETHODIMP_(void) CntrLine_AdvSink_OnViewChange( + LPADVISESINK lpThis, + DWORD aspects, + LONG lindex +); +STDMETHODIMP_(void) CntrLine_AdvSink_OnRename( + LPADVISESINK lpThis, + LPMONIKER lpmk +); +STDMETHODIMP_(void) CntrLine_AdvSink_OnSave(LPADVISESINK lpThis); +STDMETHODIMP_(void) CntrLine_AdvSink_OnClose(LPADVISESINK lpThis); + +#if defined( INPLACE_CNTR ) +/* ContainerLine::IOleInPlaceSite methods (functions) */ + +STDMETHODIMP CntrLine_IPSite_QueryInterface( + LPOLEINPLACESITE lpThis, + REFIID riid, + LPVOID FAR* lplpvObj +); +STDMETHODIMP_(ULONG) CntrLine_IPSite_AddRef(LPOLEINPLACESITE lpThis); +STDMETHODIMP_(ULONG) CntrLine_IPSite_Release(LPOLEINPLACESITE lpThis); +STDMETHODIMP CntrLine_IPSite_GetWindow( + LPOLEINPLACESITE lpThis, + HWND FAR* lphwnd +); +STDMETHODIMP CntrLine_IPSite_ContextSensitiveHelp( + LPOLEINPLACESITE lpThis, + BOOL fEnterMode +); +STDMETHODIMP CntrLine_IPSite_CanInPlaceActivate(LPOLEINPLACESITE lpThis); +STDMETHODIMP CntrLine_IPSite_OnInPlaceActivate(LPOLEINPLACESITE lpThis); +STDMETHODIMP CntrLine_IPSite_OnUIActivate (LPOLEINPLACESITE lpThis); +STDMETHODIMP CntrLine_IPSite_GetWindowContext( + LPOLEINPLACESITE lpThis, + LPOLEINPLACEFRAME FAR* lplpFrame, + LPOLEINPLACEUIWINDOW FAR* lplpDoc, + LPRECT lprcPosRect, + LPRECT lprcClipRect, + LPOLEINPLACEFRAMEINFO lpFrameInfo +); +STDMETHODIMP CntrLine_IPSite_Scroll( + LPOLEINPLACESITE lpThis, + SIZE scrollExtent +); +STDMETHODIMP CntrLine_IPSite_OnUIDeactivate( + LPOLEINPLACESITE lpThis, + BOOL fUndoable +); +STDMETHODIMP CntrLine_IPSite_OnInPlaceDeactivate(LPOLEINPLACESITE lpThis); +STDMETHODIMP CntrLine_IPSite_DiscardUndoState(LPOLEINPLACESITE lpThis); +STDMETHODIMP CntrLine_IPSite_DeactivateAndUndo(LPOLEINPLACESITE lpThis); +STDMETHODIMP CntrLine_IPSite_OnPosRectChange( + LPOLEINPLACESITE lpThis, + LPCRECT lprcPosRect +); +#endif // INPLACE_CNTR + + +/* struct definition for persistant data storage of ContainerLine */ + +#pragma pack(push, 2) +typedef struct tagCONTAINERLINERECORD_ONDISK +{ + char m_szStgName[CWCSTORAGENAME]; // stg name w/i cntr stg + USHORT m_fMonikerAssigned; // has a moniker been assigned to obj + DWORD m_dwDrawAspect; // current display aspect for obj + // (either DVASPECT_CONTENT or + // DVASPECT_ICON) + SIZEL m_sizeInHimetric; // extents of obj in himetric units + DWORD m_dwLinkType; // is it a linked object? + // 0 -- NOT a link + // OLEUPDATE_ALWAYS (1) -- auto link + // OLEUPDATE_ONCALL (3) -- man. link + USHORT m_fDoSetExtent; // obj was resized when not running + // IOO::SetExtent needed on next run +} CONTAINERLINERECORD_ONDISK, FAR* LPCONTAINERLINERECORD_ONDISK; +#pragma pack(pop) + +typedef struct tagCONTAINERLINERECORD { + char m_szStgName[CWCSTORAGENAME]; // stg name w/i cntr stg + BOOL m_fMonikerAssigned; // has a moniker been assigned to obj + DWORD m_dwDrawAspect; // current display aspect for obj + // (either DVASPECT_CONTENT or + // DVASPECT_ICON) + SIZEL m_sizeInHimetric; // extents of obj in himetric units + DWORD m_dwLinkType; // is it a linked object? + // 0 -- NOT a link + // OLEUPDATE_ALWAYS (1) -- auto link + // OLEUPDATE_ONCALL (3) -- man. link + BOOL m_fDoSetExtent; // obj was resized when not running + // IOO::SetExtent needed on next run +} CONTAINERLINERECORD, FAR* LPCONTAINERLINERECORD; + + +/************************************************************************* +** class CONTAINERDOC : OUTLINEDOC +** CONTAINERDOC is an extention to the base OUTLINEDOC object (structure) +** that adds OLE 2.0 Container functionality. There is one instance of +** CONTAINERDOC object created per document open in the app. The SDI +** version of the app supports one CONTAINERDOC at a time. The MDI +** version of the app can manage multiple documents at one time. +** The CONTAINERDOC class inherits all fields +** from the OUTLINEDOC class. This inheritance is achieved by including a +** member variable of type OUTLINEDOC as the first field in the +** CONTAINERDOC structure. Thus a pointer to a CONTAINERDOC object +** can be cast to be a pointer to a OUTLINEDOC object. +*************************************************************************/ + +typedef struct tagCONTAINERDOC { + OLEDOC m_OleDoc; // ContainerDoc inherits all fields of OleDoc + ULONG m_nNextObjNo; // next available obj no. for stg name + LPSTORAGE m_lpNewStg; // holds new pStg when SaveAs is pending + BOOL m_fEmbeddedObjectAvail; // is single OLE embed copied to doc + CLSID m_clsidOleObjCopied; // if obj copied, CLSID of obj + DWORD m_dwAspectOleObjCopied; // if obj copied, draw aspect of obj + LPCONTAINERLINE m_lpSrcContainerLine; // src line if doc created for copy + BOOL m_fShowObject; // show object flag + +#if defined( INPLACE_CNTR ) + LPCONTAINERLINE m_lpLastIpActiveLine; // last in-place active line + LPCONTAINERLINE m_lpLastUIActiveLine; // last UIActive line + HWND m_hWndUIActiveObj; // HWND of UIActive obj. + BOOL m_fAddMyUI; // if adding tools/menu postponed + int m_cIPActiveObjects; + +#if defined( INPLACE_CNTRSVR ) + LPOLEINPLACEFRAME m_lpTopIPFrame; // ptr to Top In-place frame. + LPOLEINPLACEFRAME m_lpTopIPDoc; // ptr to Top In-place Doc window. + HMENU m_hSharedMenu; // combined obj/cntr menu + // NULL if we are top container + HOLEMENU m_hOleMenu; // returned by OleCreateMenuDesc. + // NULL if we are top container +#endif // INPLACE_CNTRSVR +#endif // INPLACE_CNTR + + struct CDocOleUILinkContainerImpl { + IOleUILinkContainerVtbl FAR* lpVtbl; + LPCONTAINERDOC lpContainerDoc; + int cRef; // interface specific ref count. + } m_OleUILinkContainer; + +} CONTAINERDOC; + +/* ContainerDoc methods (functions) */ +BOOL ContainerDoc_Init(LPCONTAINERDOC lpContainerDoc, BOOL fDataTransferDoc); +LPCONTAINERLINE ContainerDoc_GetNextLink( + LPCONTAINERDOC lpContainerDoc, + LPCONTAINERLINE lpContainerLine +); +void ContainerDoc_UpdateLinks(LPCONTAINERDOC lpContainerDoc); +void ContainerDoc_SetShowObjectFlag(LPCONTAINERDOC lpContainerDoc, BOOL fShow); +BOOL ContainerDoc_GetShowObjectFlag(LPCONTAINERDOC lpContainerDoc); +void ContainerDoc_InsertOleObjectCommand(LPCONTAINERDOC lpContainerDoc); +void ContainerDoc_EditLinksCommand(LPCONTAINERDOC lpContainerDoc); +void ContainerDoc_PasteLinkCommand(LPCONTAINERDOC lpContainerDoc); +void ContainerDoc_ConvertCommand( + LPCONTAINERDOC lpContainerDoc, + BOOL fServerNotRegistered +); +BOOL ContainerDoc_PasteFormatFromData( + LPCONTAINERDOC lpContainerDoc, + CLIPFORMAT cfFormat, + LPDATAOBJECT lpSrcDataObj, + BOOL fLocalDataObj, + BOOL fLink, + BOOL fDisplayAsIcon, + HGLOBAL hMetaPict, + LPSIZEL lpSizelInSrc +); +int ContainerDoc_PasteCntrOutlData( + LPCONTAINERDOC lpDestContainerDoc, + LPSTORAGE lpSrcStg, + int nStartIndex +); +BOOL ContainerDoc_QueryPasteFromData( + LPCONTAINERDOC lpContainerDoc, + LPDATAOBJECT lpSrcDataObj, + BOOL fLink +); +int ContainerDoc_PasteOleObject( + LPCONTAINERDOC lpContainerDoc, + LPDATAOBJECT lpSrcDataObj, + DWORD dwCreateType, + CLIPFORMAT cfFormat, + int nIndex, + BOOL fDisplayAsIcon, + HGLOBAL hMetaPict, + LPSIZEL lpSizelInSrc +); +BOOL ContainerDoc_CloseAllOleObjects( + LPCONTAINERDOC lpContainerDoc, + DWORD dwSaveOption +); +void ContainerDoc_UnloadAllOleObjectsOfClass( + LPCONTAINERDOC lpContainerDoc, + REFCLSID rClsid, + DWORD dwSaveOption +); +void ContainerDoc_InformAllOleObjectsDocRenamed( + LPCONTAINERDOC lpContainerDoc, + LPMONIKER lpmkDoc +); +void ContainerDoc_UpdateExtentOfAllOleObjects(LPCONTAINERDOC lpContainerDoc); +BOOL ContainerDoc_SaveToFile( + LPCONTAINERDOC lpContainerDoc, + LPCSTR lpszFileName, + UINT uFormat, + BOOL fRemember +); +void ContainerDoc_ContainerLineDoVerbCommand( + LPCONTAINERDOC lpContainerDoc, + LONG iVerb +); +void ContainerDoc_GetNextStgName( + LPCONTAINERDOC lpContainerDoc, + LPSTR lpszStgName, + int nLen +); +BOOL ContainerDoc_IsStgNameUsed( + LPCONTAINERDOC lpContainerDoc, + LPSTR lpszStgName +); +LPSTORAGE ContainerDoc_GetStg(LPCONTAINERDOC lpContainerDoc); +HRESULT ContainerDoc_GetObject( + LPCONTAINERDOC lpContainerDoc, + LPOLESTR lpszItem, + DWORD dwSpeedNeeded, + REFIID riid, + LPVOID FAR* lplpvObject +); +HRESULT ContainerDoc_GetObjectStorage( + LPCONTAINERDOC lpContainerDoc, + LPOLESTR lpszItem, + LPSTORAGE FAR* lplpStg +); +HRESULT ContainerDoc_IsRunning(LPCONTAINERDOC lpContainerDoc, LPOLESTR lpszItem); +LPUNKNOWN ContainerDoc_GetSingleOleObject( + LPCONTAINERDOC lpContainerDoc, + REFIID riid, + LPCONTAINERLINE FAR* lplpContainerLine +); +BOOL ContainerDoc_IsSelAnOleObject( + LPCONTAINERDOC lpContainerDoc, + REFIID riid, + LPUNKNOWN FAR* lplpvObj, + int FAR* lpnIndex, + LPCONTAINERLINE FAR* lplpContainerLine +); +HRESULT ContainerDoc_GetData ( + LPCONTAINERDOC lpContainerDoc, + LPFORMATETC lpformatetc, + LPSTGMEDIUM lpMedium +); +HRESULT ContainerDoc_GetDataHere ( + LPCONTAINERDOC lpContainerDoc, + LPFORMATETC lpformatetc, + LPSTGMEDIUM lpMedium +); +HRESULT ContainerDoc_QueryGetData ( + LPCONTAINERDOC lpContainerDoc, + LPFORMATETC lpformatetc +); +HRESULT ContainerDoc_SetData ( + LPCONTAINERDOC lpContainerDoc, + LPFORMATETC lpformatetc, + LPSTGMEDIUM lpmedium, + BOOL fRelease +); +HRESULT ContainerDoc_EnumFormatEtc( + LPCONTAINERDOC lpContainerDoc, + DWORD dwDirection, + LPENUMFORMATETC FAR* lplpenumFormatEtc +); +BOOL ContainerDoc_SetupDocGetFmts( + LPCONTAINERDOC lpContainerDoc, + LPCONTAINERLINE lpContainerLine +); + +#if defined( INPLACE_CNTR ) + +void ContainerDoc_ShutDownLastInPlaceServerIfNotNeeded( + LPCONTAINERDOC lpContainerDoc, + LPCONTAINERLINE lpNextActiveLine +); +BOOL ContainerDoc_IsUIDeactivateNeeded( + LPCONTAINERDOC lpContainerDoc, + POINT pt +); +HWND ContainerDoc_GetUIActiveWindow(LPCONTAINERDOC lpContainerDoc); +void ContainerDoc_UpdateInPlaceObjectRects(LPCONTAINERDOC lpContainerDoc, int nIndex); +void ContainerDoc_GetClipRect( + LPCONTAINERDOC lpContainerDoc, + LPRECT lprcClipRect +); +void ContainerDoc_FrameWindowResized(LPCONTAINERDOC lpContainerDoc); +LPOLEINPLACEFRAME ContainerDoc_GetTopInPlaceFrame( + LPCONTAINERDOC lpContainerDoc +); +void ContainerDoc_GetSharedMenuHandles( + LPCONTAINERDOC lpContainerDoc, + HMENU FAR* lphSharedMenu, + HOLEMENU FAR* lphOleMenu +); +void ContainerDoc_RemoveFrameLevelTools(LPCONTAINERDOC lpContainerDoc); +void ContainerDoc_AddFrameLevelUI(LPCONTAINERDOC lpContainerDoc); +void ContainerDoc_AddFrameLevelTools(LPCONTAINERDOC lpContainerDoc); + +#if defined( INPLACE_CNTRSVR ) || defined( INPLACE_MDICNTR ) + +LPOLEINPLACEUIWINDOW ContainerDoc_GetTopInPlaceDoc( + LPCONTAINERDOC lpContainerDoc +); +void ContainerDoc_RemoveDocLevelTools(LPCONTAINERDOC lpContainerDoc); +void ContainerDoc_AddDocLevelTools(LPCONTAINERDOC lpContainerDoc); + +#endif // INPLACE_CNTRSVR || INPLACE_MDICNTR +#endif // INPLACE_CNTR + +/* ContainerDoc::IOleUILinkContainer methods (functions) */ +STDMETHODIMP CntrDoc_LinkCont_QueryInterface( + LPOLEUILINKCONTAINER lpThis, + REFIID riid, + LPVOID FAR* lplpvObj +); +STDMETHODIMP_(ULONG) CntrDoc_LinkCont_AddRef(LPOLEUILINKCONTAINER lpThis); +STDMETHODIMP_(ULONG) CntrDoc_LinkCont_Release(LPOLEUILINKCONTAINER lpThis); +STDMETHODIMP_(DWORD) CntrDoc_LinkCont_GetNextLink( + LPOLEUILINKCONTAINER lpThis, + DWORD dwLink +); +STDMETHODIMP CntrDoc_LinkCont_SetLinkUpdateOptions( + LPOLEUILINKCONTAINER lpThis, + DWORD dwLink, + DWORD dwUpdateOpt +); +STDMETHODIMP CntrDoc_LinkCont_GetLinkUpdateOptions( + LPOLEUILINKCONTAINER lpThis, + DWORD dwLink, + DWORD FAR* dwUpdateOpt +); + +STDMETHODIMP CntrDoc_LinkCont_SetLinkSource( + LPOLEUILINKCONTAINER lpThis, + DWORD dwLink, + LPSTR lpszDisplayName, + ULONG clenFileName, + ULONG FAR* lpchEaten, + BOOL fValidateSource +); +STDMETHODIMP CntrDoc_LinkCont_GetLinkSource( + LPOLEUILINKCONTAINER lpThis, + DWORD dwLink, + LPSTR FAR* lplpszDisplayName, + ULONG FAR* lplenFileName, + LPSTR FAR* lplpszFullLinkType, + LPSTR FAR* lplpszShortLinkType, + BOOL FAR* lpfSourceAvailable, + BOOL FAR* lpfIsSelected +); +STDMETHODIMP CntrDoc_LinkCont_OpenLinkSource( + LPOLEUILINKCONTAINER lpThis, + DWORD dwLink +); +STDMETHODIMP CntrDoc_LinkCont_UpdateLink( + LPOLEUILINKCONTAINER lpThis, + DWORD dwLink, + BOOL fErrorMessage, + BOOL fErrorAction +); +STDMETHODIMP CntrDoc_LinkCont_CancelLink( + LPOLEUILINKCONTAINER lpThis, + DWORD dwLink +); + + + +/************************************************************************* +** class CONTAINERAPP : OLEAPP +** CONTAINERAPP is an extention to the base OLEAPP object (structure) +** that adds special Container functionality. There is one instance of +** CONTAINERApp object created per running application instance. This +** object holds many fields that could otherwise be organized as +** global variables. The CONTAINERAPP class inherits all fields +** from the OLEAPP class. This inheritance is achieved by including a +** member variable of type OLEAPP as the first field in the CONTAINERAPP +** structure. OLEAPP inherits from OUTLINEAPP. This inheritance is +** achieved in the same manner. Thus a pointer to a CONTAINERAPP object +** can be cast to be a pointer to an OLEAPP or an OUTLINEAPP object +*************************************************************************/ + +/* Forward definition of types */ +typedef struct tagCONTAINERAPP FAR* LPCONTAINERAPP; + +typedef struct tagCONTAINERAPP { + OLEAPP m_OleApp; // ContainerApp inherits all fields of OleApp + UINT m_cfCntrOutl; // clipboard format for CntrOutl (client ver) data + int m_nSingleObjGetFmts; // no. formats avail when single obj copied + FORMATETC m_arrSingleObjGetFmts[MAXNOFMTS]; + // array of FormatEtc's available via + // IDataObject::GetData when a single + // OLE object is copied. + +#if defined( INPLACE_CNTR ) + HACCEL m_hAccelIPCntr; // accelerators for container's workspace commands + HMENU m_hMenuFile; // handle to File menu of container app + HMENU m_hMenuView; // handle to View menu of container app + HMENU m_hMenuDebug; // handle to Debug menu of container app + LPOLEINPLACEACTIVEOBJECT m_lpIPActiveObj; // ptr to inplace active OLE obj + HWND m_hWndUIActiveObj; // HWND of UIActive obj. + BOOL m_fPendingUIDeactivate; // should app UIDeactivate on LBUTTONUP + BOOL m_fMustResizeClientArea;// if client area resize pending + // (see Doc_FrameWindowResized) + BOOL m_fMenuHelpMode;// is F1 pressed in menu, if so give help +#ifdef _DEBUG + BOOL m_fOutSideIn; +#endif + + struct COleInPlaceFrameImpl { + IOleInPlaceFrameVtbl FAR* lpVtbl; + LPCONTAINERAPP lpContainerApp; + int cRef; // interface specific ref count. + } m_OleInPlaceFrame; + +#endif // INPLACE_CNTR + +} CONTAINERAPP; + +/* ContainerApp methods (functions) */ +BOOL ContainerApp_InitInstance( + LPCONTAINERAPP lpContainerApp, + HINSTANCE hInst, + int nCmdShow +); +BOOL ContainerApp_InitVtbls(LPCONTAINERAPP lpApp); + +#if defined( INPLACE_CNTR ) + +/* ContainerApp::IOleInPlaceFrame methods (functions) */ + +STDMETHODIMP CntrApp_IPFrame_QueryInterface( + LPOLEINPLACEFRAME lpThis, + REFIID riid, + LPVOID FAR* lplpvObj +); +STDMETHODIMP_(ULONG) CntrApp_IPFrame_AddRef(LPOLEINPLACEFRAME lpThis); +STDMETHODIMP_(ULONG) CntrApp_IPFrame_Release(LPOLEINPLACEFRAME lpThis); +STDMETHODIMP CntrApp_IPFrame_GetWindow( + LPOLEINPLACEFRAME lpThis, + HWND FAR* lphwnd +); +STDMETHODIMP CntrApp_IPFrame_ContextSensitiveHelp( + LPOLEINPLACEFRAME lpThis, + BOOL fEnterMode +); +STDMETHODIMP CntrApp_IPFrame_GetBorder( + LPOLEINPLACEFRAME lpThis, + LPRECT lprectBorder +); +STDMETHODIMP CntrApp_IPFrame_RequestBorderSpace( + LPOLEINPLACEFRAME lpThis, + LPCBORDERWIDTHS lpWidths +); +STDMETHODIMP CntrApp_IPFrame_SetBorderSpace( + LPOLEINPLACEFRAME lpThis, + LPCBORDERWIDTHS lpWidths +); +STDMETHODIMP CntrApp_IPFrame_SetActiveObject( + LPOLEINPLACEFRAME lpThis, + LPOLEINPLACEACTIVEOBJECT lpActiveObject, + LPCOLESTR lpszObjName +); +STDMETHODIMP CntrApp_IPFrame_InsertMenus( + LPOLEINPLACEFRAME lpThis, + HMENU hmenu, + LPOLEMENUGROUPWIDTHS lpMenuWidths +); +STDMETHODIMP CntrApp_IPFrame_SetMenu( + LPOLEINPLACEFRAME lpThis, + HMENU hmenuShared, + HOLEMENU holemenu, + HWND hwndActiveObject +); +STDMETHODIMP CntrApp_IPFrame_RemoveMenus( + LPOLEINPLACEFRAME lpThis, + HMENU hmenu +); +STDMETHODIMP CntrApp_IPFrame_SetStatusText( + LPOLEINPLACEFRAME lpThis, + LPCOLESTR lpszStatusText +); +STDMETHODIMP CntrApp_IPFrame_EnableModeless( + LPOLEINPLACEFRAME lpThis, + BOOL fEnable +); +STDMETHODIMP CntrApp_IPFrame_TranslateAccelerator( + LPOLEINPLACEFRAME lpThis, + LPMSG lpmsg, + WORD wID +); + +#endif // INPLACE_CNTR + + +#endif // _CNTROUTL_H_ diff --git a/private/oleutest/letest/outline/cntroutl.ico b/private/oleutest/letest/outline/cntroutl.ico new file mode 100644 index 000000000..313a0000f Binary files /dev/null and b/private/oleutest/letest/outline/cntroutl.ico differ diff --git a/private/oleutest/letest/outline/cntroutl/cntroutl.rc b/private/oleutest/letest/outline/cntroutl/cntroutl.rc new file mode 100644 index 000000000..02679d04b --- /dev/null +++ b/private/oleutest/letest/outline/cntroutl/cntroutl.rc @@ -0,0 +1,179 @@ +/************************************************************************* +** +** OLE 2.0 Container Sample Code +** +** cntroutl.rc +** +** Resource file for cntroutl.exe +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + +#include "windows.h" +#include "outlrc.h" +#include "cntrrc.h" + +SelCur CURSOR selcross.cur +DragMoveCur CURSOR dragmove.cur + +#if defined( IF_SPECIAL_DD_CURSORS_NEEDED ) +DragNoneCur CURSOR dragnone.cur +DragCopyCur CURSOR dragcopy.cur +DragLinkCur CURSOR draglink.cur +#endif // IF_SPECIAL_DD_CURSORS_NEEDED + +CntrOutlMenu MENU + BEGIN + POPUP "&File" + BEGIN + MENUITEM "&New", IDM_F_NEW + MENUITEM "&Open...\t Ctrl+F12", IDM_F_OPEN + MENUITEM "&Save\t Shift+F12", IDM_F_SAVE + MENUITEM "Save &As...\t F12", IDM_F_SAVEAS + MENUITEM SEPARATOR + MENUITEM "&Print...\t Ctrl+Shift+F12", IDM_F_PRINT + MENUITEM "Printer Se&tup...", IDM_F_PRINTERSETUP + MENUITEM SEPARATOR + MENUITEM "E&xit\t Alt+F4", IDM_F_EXIT + END + POPUP "&Edit" + BEGIN + MENUITEM "&Undo", IDM_E_UNDO + MENUITEM SEPARATOR + MENUITEM "Cu&t\t Ctrl+X", IDM_E_CUT + MENUITEM "&Copy\t Ctrl+C", IDM_E_COPY + MENUITEM "&Paste\t Ctrl+V", IDM_E_PASTE + MENUITEM "Paste &Special...", IDM_E_PASTESPECIAL + MENUITEM "Paste &Link", IDM_E_PASTELINK + MENUITEM "Cl&ear\t Del", IDM_E_CLEAR + MENUITEM SEPARATOR + MENUITEM "&Insert Object...", IDM_E_INSERTOBJECT + MENUITEM "Li&nks...", IDM_E_EDITLINKS + MENUITEM "&Object", IDM_E_OBJECTVERBMIN + MENUITEM SEPARATOR + MENUITEM "Select &All\t Ctrl+A", IDM_E_SELECTALL + END + POPUP "O&utline" + BEGIN + POPUP "&Zoom" + BEGIN + MENUITEM "&100%", IDM_V_ZOOM_100 + MENUITEM "&75%", IDM_V_ZOOM_75 + MENUITEM "&50%", IDM_V_ZOOM_50 + MENUITEM "&25%", IDM_V_ZOOM_25 + END + POPUP "&Left and Right margins" + BEGIN + MENUITEM "&nil", IDM_V_SETMARGIN_0 + MENUITEM "&1 cm", IDM_V_SETMARGIN_1 + MENUITEM "&2 cm", IDM_V_SETMARGIN_2 + MENUITEM "&3 cm", IDM_V_SETMARGIN_3 + MENUITEM "&4 cm", IDM_V_SETMARGIN_4 + END + POPUP "Add &Top Line" + BEGIN + MENUITEM "&1 cm", IDM_V_ADDTOP_1 + MENUITEM "&2 cm", IDM_V_ADDTOP_2 + MENUITEM "&3 cm", IDM_V_ADDTOP_3 + MENUITEM "&4 cm", IDM_V_ADDTOP_4 + END + END + POPUP "&Line" + BEGIN + MENUITEM "&Add Line\t Enter", IDM_L_ADDLINE + MENUITEM "E&dit Line\t Alt+Enter", IDM_L_EDITLINE + MENUITEM SEPARATOR + MENUITEM "&Indent Line\t Tab", IDM_L_INDENTLINE + MENUITEM "U&nindent Line\t Shift+Tab", IDM_L_UNINDENTLINE + MENUITEM SEPARATOR + MENUITEM "&Set Line Height...", IDM_L_SETLINEHEIGHT + END + POPUP "&Name" + BEGIN + MENUITEM "&Define Name...", IDM_N_DEFINENAME + MENUITEM "&Goto Name...", IDM_N_GOTONAME + END + POPUP "&Options" + BEGIN + POPUP "&Button Bar Display" + BEGIN + MENUITEM "At &Top", IDM_O_BB_TOP + MENUITEM "At &Bottom", IDM_O_BB_BOTTOM + MENUITEM "&Popup", IDM_O_BB_POPUP + MENUITEM "&Hide", IDM_O_BB_HIDE + END + POPUP "&Formula Bar Display" + BEGIN + MENUITEM "At &Top", IDM_O_FB_TOP + MENUITEM "At &Bottom", IDM_O_FB_BOTTOM + MENUITEM "&Popup", IDM_O_FB_POPUP + END + POPUP "&Row and Column Heading" + BEGIN + MENUITEM "&Show", IDM_O_HEAD_SHOW + MENUITEM "&Hide", IDM_O_HEAD_HIDE + END + MENUITEM "&Show Object", IDM_O_SHOWOBJECT + END + POPUP "Dbg&Cntr" + BEGIN + MENUITEM "&Debug Level...", IDM_D_DEBUGLEVEL + MENUITEM "Register Message &Filter", IDM_D_INSTALLMSGFILTER + MENUITEM "&Reject Incoming Messages", IDM_D_REJECTINCOMING + END + POPUP "&Help" + BEGIN + MENUITEM "&About...", IDM_H_ABOUT + END + END + +CntrOutlAccel ACCELERATORS + BEGIN + VK_F12, IDM_F_OPEN, VIRTKEY, CONTROL + VK_F12, IDM_F_SAVE, VIRTKEY, SHIFT + VK_F12, IDM_F_SAVEAS, VIRTKEY + VK_F12, IDM_F_PRINT, VIRTKEY, CONTROL, SHIFT + + "x", IDM_E_CUT, VIRTKEY, CONTROL + "c", IDM_E_COPY, VIRTKEY, CONTROL + "v", IDM_E_PASTE, VIRTKEY, CONTROL + VK_DELETE, IDM_E_CLEAR, VIRTKEY + VK_RETURN, IDM_L_ADDLINE, VIRTKEY + VK_RETURN, IDM_L_EDITLINE, VIRTKEY, ALT + VK_TAB, IDM_L_INDENTLINE, VIRTKEY + VK_TAB, IDM_L_UNINDENTLINE, VIRTKEY, SHIFT + "a", IDM_E_SELECTALL, VIRTKEY, CONTROL + + ; old conventions for editing + VK_INSERT, IDM_E_COPY, VIRTKEY, CONTROL + VK_DELETE, IDM_E_CUT, VIRTKEY, SHIFT + VK_INSERT, IDM_E_PASTE, VIRTKEY, SHIFT + + VK_F2, IDM_F2, VIRTKEY + END + +; Same as CntrOutlAccel but without Delete and Backspace +; used when edit control of Formula Bar in focus +; +CntrOutlAccelFocusEdit ACCELERATORS + BEGIN + VK_F12, IDM_F_OPEN, VIRTKEY, CONTROL + VK_F12, IDM_F_SAVE, VIRTKEY, SHIFT + VK_F12, IDM_F_SAVEAS, VIRTKEY + VK_F12, IDM_F_PRINT, VIRTKEY, CONTROL, SHIFT + + VK_RETURN, IDM_L_ADDLINE, VIRTKEY + VK_RETURN, IDM_L_EDITLINE, VIRTKEY, ALT + + VK_ESCAPE, IDM_FB_CANCEL, VIRTKEY + END + +CntrOutlIcon ICON cntroutl.ico + +Image72 BITMAP image72.bmp +Image96 BITMAP image96.bmp +Image120 BITMAP image120.bmp +LogoBitmap BITMAP ole2.bmp + +#include "DIALOGS.DLG" diff --git a/private/oleutest/letest/outline/cntroutl/daytona/makefile b/private/oleutest/letest/outline/cntroutl/daytona/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/oleutest/letest/outline/cntroutl/daytona/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/oleutest/letest/outline/cntroutl/daytona/makefile.inc b/private/oleutest/letest/outline/cntroutl/daytona/makefile.inc new file mode 100644 index 000000000..462f38133 --- /dev/null +++ b/private/oleutest/letest/outline/cntroutl/daytona/makefile.inc @@ -0,0 +1,2 @@ +copyfiles: + xcopy ..\..\*.c . /D diff --git a/private/oleutest/letest/outline/cntroutl/daytona/sources b/private/oleutest/letest/outline/cntroutl/daytona/sources new file mode 100644 index 000000000..45f65e8c8 --- /dev/null +++ b/private/oleutest/letest/outline/cntroutl/daytona/sources @@ -0,0 +1,114 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + Kenneth MacLeod (Kennethm) 9-Mar-1994 + +!ENDIF + +MAJORCOMP = ctoleui +MINORCOMP = cntroutl + +# This links with "bttncur", "gizmobar", etc... Block multiprocessor +# threads here to assure that these are finished building before +# proceeding. This also protects the build of "icntrot", "isvrrotl", +# and "svroutl" which are build after this. + +SYNCHRONIZE_BLOCK=1 +SYNCHRONIZE_DRAIN=1 + +# +# This is the name of the target built from the source files specified +# below. The name should include neither the path nor the file extension. +# + +TARGETNAME= cntroutl + +# +# This specifies where the target is to be built. A private target of +# type LIBRARY or DYNLINK should go to obj, whereas a public target of +# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib. +# + +TARGETPATH= obj + +# +# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY, +# etc. +# + +TARGETTYPE= PROGRAM + +INCLUDES= ..\..\..\ole2ui; \ + ..\..\..\bttncur; \ + ..\..\..\gizmobar; \ + ..\..\..\..\inc; \ + ..\.. + +C_DEFINES= \ + $(C_DEFINES) \ + -DFLAT \ + -DWIN32=100 \ + -D_NT1X_=100 \ + -DUNICODE \ + -DNOEXCEPTIONS \ + -DOLE_CNTR + +SOURCES= \ + ..\cntroutl.rc \ + classfac.c \ + clipbrd.c \ + cntrbase.c \ + cntrline.c \ + debug.c \ + debug2.c \ + dialogs.c \ + dragdrop.c \ + frametls.c \ + heading.c \ + linking.c \ + main.c \ + memmgr.c \ + oleapp.c \ + oledoc.c \ + outlapp.c \ + outldoc.c \ + outlline.c \ + outllist.c \ + outlname.c \ + outlntbl.c \ + outltxtl.c \ + status.c \ + tests.c + +UMTYPE= windows +UMENTRY= winmain +USE_CRTDLL=1 +TARGETLIBS= \ + ..\..\..\ole2ui\daytona\obj\*\ole2u32a.lib \ + ..\..\..\gizmobar\daytona\obj\*\gizmobar.lib \ + ..\..\..\bttncur\daytona\obj\*\bttncur.lib \ + $(BASEDIR)\public\sdk\lib\*\ole32.lib \ + $(BASEDIR)\public\sdk\lib\*\shell32.lib \ + $(BASEDIR)\public\sdk\lib\*\gdi32.lib \ + $(BASEDIR)\public\sdk\lib\*\kernel32.lib \ + $(BASEDIR)\public\sdk\lib\*\user32.lib \ + $(BASEDIR)\public\sdk\lib\*\advapi32.lib \ + $(BASEDIR)\public\sdk\lib\*\comdlg32.lib \ + $(BASEDIR)\public\sdk\lib\*\uuid.lib + +NTTARGETFILE0=copyfiles diff --git a/private/oleutest/letest/outline/cntroutl/dirs b/private/oleutest/letest/outline/cntroutl/dirs new file mode 100644 index 000000000..515c134a8 --- /dev/null +++ b/private/oleutest/letest/outline/cntroutl/dirs @@ -0,0 +1,37 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + dirs. + +Abstract: + + This file specifies the subdirectories of the current directory that + contain component makefiles. + + +Author: + + Donna Liu (DonnaLi) 19-Dec-1993 + +!ENDIF + +# +# This is a list of all subdirectories that build required components. +# Each subdirectory name should appear on a line by itself. The build +# follows the order in which the subdirectories are specified. +# + +DIRS= + +# +# This is a list of all subdirectories that build optional components. +# Each subdirectory name should appear on a line by itself. The build +# follows the order in which the subdirectories are specified. +# + +OPTIONAL_DIRS= \ + \ + daytona diff --git a/private/oleutest/letest/outline/cntrrc.h b/private/oleutest/letest/outline/cntrrc.h new file mode 100644 index 000000000..455f9ff4b --- /dev/null +++ b/private/oleutest/letest/outline/cntrrc.h @@ -0,0 +1,30 @@ +/************************************************************************* +** +** OLE 2.0 Container Sample Code +** +** cntrrc.h +** +** This file contains constants used in rc file for CNTROUTL.EXE +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + +#if !defined( _CNTRRC_H_ ) +#define _CNTRRC_H_ + +#ifndef RC_INVOKED +#pragma message ("INCLUDING CNTRRC.H from " __FILE__) +#endif /* RC_INVOKED */ + +#define IDM_E_INSERTOBJECT 2700 +#define IDM_E_EDITLINKS 3300 +#define IDM_E_PASTELINK 2750 +#define IDM_E_CONVERTVERB 9000 +#define IDM_E_OBJECTVERBMIN 10000 + +#define IDM_D_INSIDEOUT 2755 + +#define WM_U_UPDATEOBJECTEXTENT WM_USER+1 + +#endif // _CNTRRC_H_ diff --git a/private/oleutest/letest/outline/debug.c b/private/oleutest/letest/outline/debug.c new file mode 100644 index 000000000..14fc4d2f2 --- /dev/null +++ b/private/oleutest/letest/outline/debug.c @@ -0,0 +1,100 @@ +/************************************************************************* +** +** OLE 2 Sample Code +** +** debug.c +** +** This file contains some functions for debugging support +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + +#include "outline.h" + +OLEDBGDATA + +extern LPOUTLINEAPP g_lpApp; + +void SetDebugLevelCommand(void) +{ + char szBuf[80]; + HWND hWndFrame = OutlineApp_GetFrameWindow(g_lpApp); + + wsprintf(szBuf, "%d", OleDbgGetDbgLevel()); + + if (InputTextDlg(hWndFrame, szBuf, "Debug Level [0-4]")) { + switch (szBuf[0]) { + case '0': + OleDbgSetDbgLevel(0); + break; + case '1': + OleDbgSetDbgLevel(1); + break; + case '2': + OleDbgSetDbgLevel(2); + break; + case '3': + OleDbgSetDbgLevel(3); + break; + case '4': + OleDbgSetDbgLevel(4); + break; + default: + OutlineApp_ErrorMessage(g_lpApp, "Valid Debug Level Range: 0-4"); + break; + } + } +} + + +#if defined( OLE_VERSION ) + +/* InstallMessageFilterCommand + * --------------------------- + * + * Handles the "Install Message Filter" menu item. If a message filter is + * already installed, this function de-installs it. If there is not one + * already installed, this function installs one. + * + */ + +void InstallMessageFilterCommand(void) +{ + LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; + + /* + ** Check to see if we've already installed a MessageFilter. + ** If so, uninstall it. + */ + if (lpOleApp->m_lpMsgFilter != NULL) + OleApp_RevokeMessageFilter(lpOleApp); + else + OleApp_RegisterMessageFilter(lpOleApp); +} + + +/* RejectIncomingCommand + * --------------------- + * + * Toggles between rejecting and not-handling in coming LRPC calls + * + */ + +void RejectIncomingCommand(void) +{ + DWORD dwOldStatus; + DWORD dwNewStatus; + LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; + + dwOldStatus = OleStdMsgFilter_GetInComingCallStatus(lpOleApp->m_lpMsgFilter); + + if (dwOldStatus == SERVERCALL_RETRYLATER) + dwNewStatus = SERVERCALL_ISHANDLED; + else + dwNewStatus = SERVERCALL_RETRYLATER; + + OleStdMsgFilter_SetInComingCallStatus(lpOleApp->m_lpMsgFilter, dwNewStatus); +} + +#endif // OLE_VERSION diff --git a/private/oleutest/letest/outline/debug.rc b/private/oleutest/letest/outline/debug.rc new file mode 100644 index 000000000..d7c712c0f --- /dev/null +++ b/private/oleutest/letest/outline/debug.rc @@ -0,0 +1,142 @@ +9999 RCDATA LOADONCALL DISCARDABLE +{ + "\327\324\335\270\252\270\313\371\365\350\364\375\270\333\367\374\375\270\334\375\356\375\364\367\350\365\375\366\354\270\314\375\371\365\0", + "\265\265\270\324\375\374\270\372\341\270\265\265\0", + "\333\266\270\334\367\355\377\364\371\353\270\320\367\374\377\375\353\0", + "\270\0", + "\325\371\352\363\270\332\371\374\375\352\0", + "\323\352\371\361\377\270\332\352\367\373\363\353\373\360\365\361\374\354\0", + "\326\371\354\270\332\352\367\357\366\0", + "\316\361\366\367\367\270\333\360\375\352\361\371\366\0", + "\312\367\372\375\352\354\270\333\367\367\363\0", + "\333\364\371\352\363\270\333\341\352\0", + "\314\375\352\352\375\366\373\375\270\320\355\371\366\377\0", + "\310\375\354\375\352\270\324\361\0", + "\312\361\373\360\371\352\374\270\325\373\334\371\366\361\375\364\0", + "\312\375\372\375\373\373\371\270\326\367\352\364\371\366\374\375\352\0", + "\313\373\367\354\354\270\313\363\367\352\355\350\371\0", + "\313\371\352\371\270\317\361\364\364\361\371\365\353\0", + "\334\371\356\361\374\270\317\367\352\354\375\366\374\341\363\375\0", + "\270\0", + "\270\0", + "\327\324\335\270\252\270\324\361\372\352\371\352\341\270\334\375\356\375\364\367\350\365\375\366\354\270\314\375\371\365\0", + "\265\265\270\324\375\374\270\372\341\270\265\265\265\0", + "\312\371\367\270\312\375\365\371\364\371\0", + "\270\0", + "\332\371\352\352\341\270\332\367\366\374\0", + "\334\352\375\357\270\332\364\361\353\353\0", + "\321\364\371\366\270\333\371\352\367\366\0", + "\331\364\371\366\270\333\371\352\354\375\352\0", + "\334\367\355\377\270\336\352\371\366\363\364\361\366\0", + "\322\371\353\367\366\270\336\355\364\364\375\352\0", + "\333\364\371\352\375\366\373\375\270\337\364\371\353\353\375\0", + "\310\375\354\375\352\270\337\367\364\374\375\0", + "\331\364\375\340\371\366\374\375\352\270\337\367\355\366\371\352\375\353\0", + "\310\360\361\364\361\350\270\324\371\376\367\352\366\371\352\371\0", + "\332\352\371\374\270\324\367\356\375\352\361\366\377\0", + "\313\371\365\270\323\360\367\0", + "\313\352\361\366\361\270\323\367\350\350\367\364\355\0", + "\312\371\362\361\356\270\323\355\365\371\352\0", + "\332\371\352\352\341\270\325\371\373\323\361\373\360\371\366\0", + "\313\354\375\356\375\366\270\326\367\352\371\364\364\0", + "\337\361\364\371\374\270\327\374\361\366\371\363\0", + "\335\352\361\373\270\327\375\365\361\377\0", + "\325\371\354\354\270\310\375\371\352\353\367\366\0", + "\322\367\360\371\366\366\270\310\367\353\373\360\0", + "\333\355\352\354\270\313\354\375\375\372\0", + "\314\367\365\270\314\375\366\377\0", + "\331\364\375\340\270\314\361\364\364\375\353\0", + "\333\352\371\361\377\270\317\361\354\354\375\366\372\375\352\377\0", + "\325\361\373\360\371\375\364\270\317\367\367\364\376\0", + "\270\0", + "\270\0", + "\327\324\335\270\252\270\314\375\353\354\361\366\377\270\314\375\371\365\0", + "\265\265\270\324\375\374\270\372\341\270\265\265\0", + "\322\375\376\376\270\310\371\373\363\0", + "\270\0", + "\334\371\366\361\375\364\270\332\367\367\366\375\0", + "\332\352\371\366\374\367\366\270\332\341\366\355\365\0", + "\331\366\377\375\364\371\270\333\360\371\366\0", + "\312\361\373\360\270\335\361\342\375\366\360\367\375\376\375\352\0", + "\312\367\377\375\352\270\337\352\371\365\372\361\360\364\375\352\0", + "\333\360\352\361\353\270\323\371\355\376\376\365\371\366\0", + "\313\371\366\362\371\341\270\323\367\360\364\361\0", + "\334\357\361\377\360\354\270\323\352\355\377\375\352\0", + "\314\367\365\270\324\371\341\353\367\366\0", + "\312\367\366\371\364\374\270\324\367\366\377\0", + "\331\364\364\371\366\270\325\373\334\371\366\361\375\364\0", + "\323\375\366\354\270\325\355\352\374\367\373\360\0", + "\314\352\371\356\361\353\270\310\352\355\361\354\354\0", + "\322\371\365\375\353\270\312\367\374\352\361\377\355\375\353\0", + "\312\367\353\353\270\313\365\361\354\360\0", + "\270\0", + "\270\0", + "\327\324\335\270\252\270\310\352\367\377\352\371\365\270\325\371\366\371\377\375\365\375\366\354\0", + "\265\265\270\324\375\374\270\372\341\270\265\265\0", + "\320\375\361\363\363\361\270\323\371\366\375\352\356\371\0", + "\270\0", + "\333\341\270\333\375\374\371\352\0", + "\335\374\374\361\375\270\337\361\364\372\375\352\354\0", + "\325\371\352\363\270\321\377\352\371\0", + "\334\371\356\361\374\270\324\371\366\361\366\377\0", + "\322\367\360\366\270\324\375\376\367\352\0", + "\313\373\367\354\354\270\317\361\364\354\371\365\355\354\360\0", + "\270\0", + "\270\0", + "\327\324\335\270\252\270\334\367\373\355\365\375\366\354\371\354\361\367\366\270\314\375\371\365\0", + "\265\265\270\324\375\374\270\372\341\270\265\265\0", + "\325\361\363\375\270\325\373\337\375\375\0", + "\270\0", + "\322\367\360\366\270\332\355\352\363\375\0", + "\334\361\373\363\270\325\367\353\375\364\375\341\0", + "\332\371\352\352\341\270\310\367\354\354\375\352\0", + "\324\341\366\366\375\270\317\371\353\353\367\366\0", + "\322\375\376\376\270\317\375\372\372\0", + "\270\0", + "\270\0", + "\327\324\335\270\252\270\334\375\356\375\364\367\350\375\352\270\312\375\364\371\354\361\367\366\353\270\337\352\367\355\350\0", + "\270\0", + "\331\364\361\353\354\371\361\352\270\332\371\366\363\353\0", + "\325\361\363\375\270\336\352\361\354\342\0", + "\316\361\363\354\367\352\270\337\352\371\372\366\375\352\0", + "\312\367\372\375\352\354\270\320\375\353\353\0", + "\314\361\365\270\325\373\333\371\376\376\352\375\341\0", + "\322\367\366\270\326\361\373\350\367\366\353\363\361\0", + "\322\371\365\375\353\270\310\364\371\365\367\366\374\367\366\0", + "\317\361\365\270\316\371\366\270\334\375\270\332\367\353\350\367\367\352\354\0", + "\331\374\371\365\270\317\371\371\364\363\375\353\0", + "\270\0", + "\270\0", + "\327\324\335\270\252\270\331\352\373\360\361\354\375\373\354\353\0", + "\270\0", + "\332\367\372\270\331\354\363\361\366\353\367\366\0", + "\314\367\366\341\270\317\361\364\364\361\371\365\353\0", + "\270\0", + "\270\0", + "\327\324\335\270\252\270\310\352\367\374\355\373\354\270\325\371\366\371\377\375\352\0", + "\270\0", + "\334\371\356\375\270\313\375\352\375\353\0", + "\270\0", + "\270\0", + "\327\324\335\270\252\270\337\352\367\355\350\270\325\371\366\371\377\375\352\0", + "\270\0", + "\320\371\352\375\364\270\323\367\374\375\353\360\0", + "\270\0", + "\270\0", + "\313\350\375\373\361\371\364\270\314\360\371\366\363\353\270\314\367\242\0", + "\270\0", + "\313\360\371\355\366\371\270\332\352\371\355\366\0", + "\334\371\366\270\334\375\376\376\375\0", + "\322\361\365\270\334\367\353\373\360\0", + "\332\375\356\375\352\364\375\341\270\336\364\367\357\375\352\0", + "\332\361\364\364\270\337\371\354\375\353\0", + "\322\367\366\361\270\320\371\366\353\367\366\0", + "\324\341\366\366\270\320\361\373\363\353\0", + "\326\367\352\365\371\366\270\320\367\374\366\375\0", + "\333\360\371\352\364\361\375\270\323\361\366\374\375\364\0", + "\331\366\374\341\270\324\375\375\0", + "\326\371\366\373\341\270\313\350\375\375\352\0", + "\310\371\355\364\270\313\354\371\376\376\367\352\374\0", + "\313\354\375\350\360\375\366\270\314\355\352\354\367\366\0", + 0x0000 +} diff --git a/private/oleutest/letest/outline/debug2.c b/private/oleutest/letest/outline/debug2.c new file mode 100644 index 000000000..a0d37b912 --- /dev/null +++ b/private/oleutest/letest/outline/debug2.c @@ -0,0 +1,329 @@ +/************************************************************************* +** +** OLE 2 Sample Code +** +** debug2.c +** +** This file contains various debug / subclass routines for the +** ABOUT dialog +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + +#include "outline.h" +#include +#include + +extern LPOUTLINEAPP g_lpApp; + +LONG CALLBACK EXPORT DebugAbout(HWND hWnd, unsigned uMsg, WORD wParam, LONG lParam); +void RandomizeStars(HDC hDC); +BOOL InitStrings(void); +BOOL DrawString(int iCount, HDC hDC, LPRECT rcDrawIn); + +static FARPROC lpRealAboutProc = 0L; +static int width, height; +static RECT rc; +static HANDLE hStrBlock = NULL; +static LPSTR lpStrings = NULL; +static WORD wLineHeight; + + +/* TraceDebug + * ---------- + * + * Called once when our About Box's gets the INITDIALOG message. Subclasses + * dialog. + */ + +void TraceDebug(HWND hDlg, int iControl) +{ + + // Load strings, if the strings aren't there, then don't subclass + // the dialog + if (InitStrings() != TRUE) + return; + + // Subclass the dialog + lpRealAboutProc = (FARPROC)(LONG)GetWindowLong(hDlg, GWL_WNDPROC); + SetWindowLong(hDlg, GWL_WNDPROC, (LONG)(FARPROC)DebugAbout); + + // Get rect of control in screen coords, and translate to our dialog + // box's coordinates + GetWindowRect(GetDlgItem(hDlg, iControl), &rc); + MapWindowPoints(NULL, hDlg, (LPPOINT)&rc, 2); + + width = rc.right - rc.left; + height = rc.bottom - rc.top; +} + +/* DebugAbout + * ---------- + * + * The subclassed About dialog's main window proc. + */ + +LONG CALLBACK EXPORT DebugAbout(HWND hWnd, unsigned uMsg, WORD wParam, LONG lParam) +{ + RECT rcOut; + static BOOL bTimerStarted = FALSE; + static int iTopLocation; + HDC hDCScr; + static HDC hDCMem; + static HBITMAP hBitmap; + static HBITMAP hBitmapOld; + static RECT rcMem; + static HFONT hFont; + + switch (uMsg) + { + + /* + * If we get a LBUTTONDBLCLICK in the upper left of + * the dialog, fire off the about box effects + */ + + case WM_LBUTTONDBLCLK: + if ((wParam & MK_CONTROL) && (wParam & MK_SHIFT) + && LOWORD(lParam) < 10 && HIWORD(lParam) < 10 && + bTimerStarted == FALSE) + { + if (SetTimer ( hWnd, 1, 10, NULL )) + { + LOGFONT lf; + int i; + + bTimerStarted = TRUE; + + // "Open up" the window + hDCScr = GetDC ( hWnd ); + hDCMem = CreateCompatibleDC ( hDCScr ); + + hBitmap = CreateCompatibleBitmap(hDCScr, width, height); + hBitmapOld = SelectObject(hDCMem, hBitmap); + + // Blt from dialog to memDC + BitBlt(hDCMem, 0, 0, width, height, + hDCScr, rc.left, rc.top, SRCCOPY); + + for (i=0;im_hInst, + MAKEINTRESOURCE(9999), + RT_RCDATA)) == NULL) + return FALSE; + if ((hStrBlock = LoadResource(g_lpApp->m_hInst, hResStrings)) == NULL) + return FALSE; + if ((lpStrings = LockResource(hStrBlock)) == NULL) + return FALSE; + + if (lpStrings && *(lpStrings+2)!=0x45) + { + lpWalk = lpStrings; + while (*(LPWORD)lpWalk != (WORD)0x0000) + { + if (*lpWalk != (char)0x00) + *lpWalk ^= 0x98; + lpWalk++; + } + } + return TRUE; +} + +/* DrawString + * ---------- + * + * Draws the next string on the specified hDC using the + * output rectangle. If iCount == 0, reset to start of list. + * + * Returns: TRUE to contine, FALSE if we're done + */ + +BOOL DrawString(int iCount, HDC hDC, LPRECT rcDrawIn) +{ + static LPSTR lpPtr = NULL; + + if (iCount == 0) + // First time, reset pointer + lpPtr = lpStrings; + + if (*lpPtr == '\0') // If we've hit a NULL string, we're done + return FALSE; + + // If we're drawing outside of visible box, don't call DrawText + if ((rcDrawIn->bottom > 0) && (rcDrawIn->top < height)) + DrawText(hDC, lpPtr, -1, rcDrawIn, DT_CENTER); + + // Advance pointer to next string + lpPtr += lstrlen(lpPtr) + 1; + + return TRUE; +} diff --git a/private/oleutest/letest/outline/defguid.h b/private/oleutest/letest/outline/defguid.h new file mode 100644 index 000000000..680323355 --- /dev/null +++ b/private/oleutest/letest/outline/defguid.h @@ -0,0 +1,44 @@ +/************************************************************************* +** +** OLE 2.0 Sample Code +** +** clsid.h +** +** This file contains file contains GUID definitions used for the +** OLE versions of OUTLINE. +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + +#if defined( OLE_SERVER ) || defined( OLE_CNTR ) +// OLE2NOTE: We need access to these GUIDs in modules other than +// where they are defined (MAIN.C). Even though the values of the +// GUIDs are duplicated here, they are not used. Refer to MAIN.C +// for the definition of these GUIDs. + +/* CLASS ID CONSTANTS (GUID's) +** OLE2NOTE: these class id values are allocated out of a private pool +** of GUID's allocated to the OLE 2.0 development team. GUID's of +** the following range have been allocated to OLE 2.0 sample code: +** 00000400-0000-0000-C000-000000000046 +** 000004FF-0000-0000-C000-000000000046 +** +** values reserved thus far: +** 00000400 -- Ole 2.0 Server Sample Outline +** 00000401 -- Ole 2.0 Container Sample Outline +** 00000402 -- Ole 2.0 In-Place Server Outline +** 00000403 -- Ole 2.0 In-Place Container Outline +** 00000404 : 000004FE -- reserved for OLE Sample code +** 000004FF -- IID_IOleUILinkContainer +*/ + +DEFINE_GUID(CLSID_SvrOutl, 0x00000400, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); +DEFINE_GUID(CLSID_CntrOutl, 0x00000401, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); +DEFINE_GUID(CLSID_ISvrOtl, 0x00000402, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); +DEFINE_GUID(CLSID_ICntrOtl, 0x00000403, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); + +#if defined( OLE_CNTR ) +DEFINE_GUID(IID_IOleUILinkContainer, 0x000004FF, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); +#endif +#endif diff --git a/private/oleutest/letest/outline/dialogs.c b/private/oleutest/letest/outline/dialogs.c new file mode 100644 index 000000000..bcd16b924 --- /dev/null +++ b/private/oleutest/letest/outline/dialogs.c @@ -0,0 +1,659 @@ +/************************************************************************* +** +** OLE 2 Sample Code +** +** dialogs.c +** +** This file contains dialog functions and support function +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + +#include "outline.h" + +OLEDBGDATA + +extern LPOUTLINEAPP g_lpApp; + +static char g_szBuf[MAXSTRLEN+1]; +static LPSTR g_lpszDlgTitle; + +// REVIEW: should use string resource for messages +static char ErrMsgInvalidRange[] = "Invalid Range entered!"; +static char ErrMsgInvalidValue[] = "Invalid Value entered!"; +static char ErrMsgInvalidName[] = "Invalid Name entered!"; +static char ErrMsgNullName[] = "NULL string disallowed!"; +static char ErrMsgNameNotFound[] = "Name doesn't exist!"; + +/* InputTextDlg + * ------------ + * + * Put up a dialog box to allow the user to edit text + */ +BOOL InputTextDlg(HWND hWnd, LPSTR lpszText, LPSTR lpszDlgTitle) +{ + int nResult; + + g_lpszDlgTitle = lpszDlgTitle; + lstrcpy((LPSTR)g_szBuf, lpszText); // preload dialog with input text + + nResult = DialogBox(g_lpApp->m_hInst, (LPSTR)"AddEditLine", hWnd, + (DLGPROC)AddEditDlgProc); + if (nResult) { + lstrcpy(lpszText, (LPSTR)g_szBuf); + return TRUE; + } else { + return FALSE; + } +} + + + +/* AddEditDlgProc + * -------------- + * + * This procedure is associated with the dialog box that is included in + * the function name of the procedure. It provides the service routines + * for the events (messages) that occur because the end user operates + * one of the dialog box's buttons, entry fields, or controls. + */ +BOOL CALLBACK EXPORT AddEditDlgProc(HWND hDlg, UINT Message, WPARAM wParam, LPARAM lParam) +{ + HWND hEdit; + + switch(Message) { + case WM_INITDIALOG: + /* initialize working variables */ + hEdit=GetDlgItem(hDlg,IDD_EDIT); + SendMessage(hEdit,EM_LIMITTEXT,(WPARAM)MAXSTRLEN,0L); + SetWindowText(hDlg, g_lpszDlgTitle); + SetDlgItemText(hDlg,IDD_EDIT, g_szBuf); + break; /* End of WM_INITDIALOG */ + + case WM_CLOSE: + /* Closing the Dialog behaves the same as Cancel */ + PostMessage(hDlg, WM_COMMAND, IDCANCEL, 0L); + break; /* End of WM_CLOSE */ + + case WM_COMMAND: + switch (wParam) { + case IDOK: + /* save data values entered into the controls + ** and dismiss the dialog box returning TRUE + */ + GetDlgItemText(hDlg,IDD_EDIT,(LPSTR)g_szBuf,MAXSTRLEN+1); + EndDialog(hDlg, TRUE); + break; + + case IDCANCEL: + /* ignore data values entered into the controls + ** and dismiss the dialog box returning FALSE + */ + EndDialog(hDlg, FALSE); + break; + } + break; /* End of WM_COMMAND */ + + default: + return FALSE; + } + + return TRUE; +} /* End of AddEditDlgProc */ + + +/* SetLineHeightDlgProc + * -------------------- + * + * Dialog procedure for set line height + */ +BOOL CALLBACK EXPORT SetLineHeightDlgProc(HWND hDlg, UINT Message, WPARAM wParam, LPARAM lParam) +{ + BOOL fTranslated; + BOOL fEnable; + static LPINT lpint; + int nHeight; + static int nMaxHeight; + + switch (Message) { + case WM_INITDIALOG: + { + char cBuf[80]; + + nMaxHeight = XformHeightInPixelsToHimetric(NULL, + LISTBOX_HEIGHT_LIMIT); + lpint = (LPINT)lParam; + SetDlgItemInt(hDlg, IDD_EDIT, *lpint, FALSE); + wsprintf(cBuf, "Maximum value is %d units", nMaxHeight); + SetDlgItemText(hDlg, IDD_LIMIT, (LPSTR)cBuf); + break; + } + + case WM_COMMAND: + switch (wParam) { + case IDOK: + if (IsDlgButtonChecked(hDlg, IDD_CHECK)) { + *lpint = -1; + } + else { + /* save the value in the edit control */ + nHeight = GetDlgItemInt(hDlg, IDD_EDIT, + (BOOL FAR*)&fTranslated, FALSE); + if (!fTranslated || !nHeight || (nHeight>nMaxHeight)){ + OutlineApp_ErrorMessage(g_lpApp, + ErrMsgInvalidValue); + break; + } + *lpint = nHeight; + } + EndDialog(hDlg, TRUE); + break; + + case IDCANCEL: + *lpint = 0; + EndDialog(hDlg, FALSE); + break; + + + case IDD_CHECK: + fEnable = !IsDlgButtonChecked(hDlg, IDD_CHECK); + EnableWindow(GetDlgItem(hDlg, IDD_EDIT), fEnable); + EnableWindow(GetDlgItem(hDlg, IDD_TEXT), fEnable); + break; + } + break; /* WM_COMMAND */ + + case WM_CLOSE: /* Closing the Dialog behaves the same as Cancel */ + PostMessage(hDlg, WM_COMMAND, IDCANCEL, 0L); + break; /* End of WM_CLOSE */ + + default: + return FALSE; + } + + return TRUE; + +} /* end of SetLineHeightProc */ + + + + + +/* DefineNameDlgProc + * ----------------- + * + * Dialog procedure for define name + */ +BOOL CALLBACK EXPORT DefineNameDlgProc(HWND hDlg, UINT Message, WPARAM wParam, LPARAM lParam) +{ + static HWND hCombo; + static LPOUTLINEDOC lpOutlineDoc = NULL; + static LPOUTLINENAMETABLE lpOutlineNameTable = NULL; + LPOUTLINENAME lpOutlineName = NULL; + UINT nIndex; + LINERANGE lrSel; + BOOL fTranslated; + + switch(Message) { + case WM_INITDIALOG: + /* initialize working variables */ + hCombo=GetDlgItem(hDlg,IDD_COMBO); + lpOutlineDoc = (LPOUTLINEDOC) lParam; + lpOutlineNameTable = OutlineDoc_GetNameTable(lpOutlineDoc); + + SendMessage(hCombo,CB_LIMITTEXT,(WPARAM)MAXNAMESIZE,0L); + NameDlg_LoadComboBox(lpOutlineNameTable, hCombo); + + OutlineDoc_GetSel(lpOutlineDoc, (LPLINERANGE)&lrSel); + lpOutlineName = OutlineNameTable_FindNamedRange( + lpOutlineNameTable, + &lrSel + ); + + /* if current selection already has a name, hilight it */ + if (lpOutlineName) { + nIndex = (int) SendMessage( + hCombo, + CB_FINDSTRINGEXACT, + (WPARAM)0xffff, + (LPARAM)(LPCSTR)lpOutlineName->m_szName + ); + if (nIndex != CB_ERR) { + SendMessage(hCombo, CB_SETCURSEL, (WPARAM)nIndex, 0L); + } + } + + SetDlgItemInt(hDlg, IDD_FROM, (UINT)lrSel.m_nStartLine+1,FALSE); + SetDlgItemInt(hDlg, IDD_TO, (UINT)lrSel.m_nEndLine+1, FALSE); + + break; /* End of WM_INITDIALOG */ + + case WM_CLOSE: + /* Closing the Dialog behaves the same as Cancel */ + PostMessage(hDlg, WM_COMMAND, IDD_CLOSE, 0L); + break; /* End of WM_CLOSE */ + + case WM_COMMAND: + switch(wParam) { + case IDOK: + GetDlgItemText(hDlg,IDD_COMBO,(LPSTR)g_szBuf,MAXNAMESIZE); + if(! SendMessage(hCombo,WM_GETTEXTLENGTH,0,0L)) { + MessageBox( + hDlg, + ErrMsgNullName, + NULL, + MB_ICONEXCLAMATION + ); + break; + } else if(SendMessage(hCombo,CB_GETCURSEL,0,0L)==CB_ERR && + _fstrchr(g_szBuf, ' ')) { + MessageBox( + hDlg, + ErrMsgInvalidName, + NULL, + MB_ICONEXCLAMATION + ); + break; + } else { + nIndex = (int) SendMessage(hCombo,CB_FINDSTRINGEXACT, + (WPARAM)0xffff,(LPARAM)(LPCSTR)g_szBuf); + + /* Line indices are 1 less than the number in + ** the row heading + */ + lrSel.m_nStartLine = GetDlgItemInt(hDlg, IDD_FROM, + (BOOL FAR*)&fTranslated, FALSE) - 1; + if(! fTranslated) { + OutlineApp_ErrorMessage(g_lpApp, + ErrMsgInvalidRange); + break; + } + lrSel.m_nEndLine = GetDlgItemInt(hDlg, IDD_TO, + (BOOL FAR*)&fTranslated, FALSE) - 1; + if (!fTranslated || + (lrSel.m_nStartLine < 0) || + (lrSel.m_nEndLine < lrSel.m_nStartLine) || + (lrSel.m_nEndLine >= OutlineDoc_GetLineCount( + lpOutlineDoc))) { + OutlineApp_ErrorMessage(g_lpApp, + ErrMsgInvalidRange); + break; + } + + if(nIndex != CB_ERR) { + NameDlg_UpdateName( + hCombo, + lpOutlineDoc, + nIndex, + g_szBuf, + &lrSel + ); + } else { + NameDlg_AddName( + hCombo, + lpOutlineDoc, + g_szBuf, + &lrSel + ); + } + } + // fall through + + case IDD_CLOSE: + /* Ignore data values entered into the controls */ + /* and dismiss the dialog window returning FALSE */ + EndDialog(hDlg,0); + break; + + case IDD_DELETE: + GetDlgItemText(hDlg,IDD_COMBO,(LPSTR)g_szBuf,MAXNAMESIZE); + if((nIndex=(int)SendMessage(hCombo,CB_FINDSTRINGEXACT, + (WPARAM)0xffff,(LPARAM)(LPCSTR)g_szBuf))==CB_ERR) + MessageBox(hDlg, ErrMsgNameNotFound, NULL, MB_ICONEXCLAMATION); + else { + NameDlg_DeleteName(hCombo, lpOutlineDoc, nIndex); + } + break; + + case IDD_COMBO: + if(HIWORD(lParam) == CBN_SELCHANGE) { + nIndex=(int)SendMessage(hCombo, CB_GETCURSEL, 0, 0L); + lpOutlineName = (LPOUTLINENAME)SendMessage( + hCombo, + CB_GETITEMDATA, + (WPARAM)nIndex, + 0L + ); + SetDlgItemInt( + hDlg, + IDD_FROM, + (UINT) lpOutlineName->m_nStartLine + 1, + FALSE + ); + SetDlgItemInt( + hDlg, + IDD_TO, + (UINT) lpOutlineName->m_nEndLine + 1, + FALSE + ); + } + } + break; /* End of WM_COMMAND */ + + default: + return FALSE; + } + + return TRUE; +} /* End of DefineNameDlgProc */ + + +/* GotoNameDlgProc + * --------------- + * + * Dialog procedure for goto name + */ +BOOL CALLBACK EXPORT GotoNameDlgProc(HWND hDlg, UINT Message, WPARAM wParam, LPARAM lParam) +{ + static HWND hLBName; + static LPOUTLINEDOC lpOutlineDoc = NULL; + static LPOUTLINENAMETABLE lpOutlineNameTable = NULL; + UINT nIndex; + LINERANGE lrLineRange; + LPOUTLINENAME lpOutlineName; + + switch(Message) { + case WM_INITDIALOG: + /* initialize working variables */ + lpOutlineDoc = (LPOUTLINEDOC) lParam; + lpOutlineNameTable = OutlineDoc_GetNameTable(lpOutlineDoc); + + hLBName=GetDlgItem(hDlg,IDD_LINELISTBOX); + NameDlg_LoadListBox(lpOutlineNameTable, hLBName); + + // highlight 1st item + SendMessage(hLBName, LB_SETCURSEL, 0, 0L); + // trigger to initialize edit control + SendMessage(hDlg, WM_COMMAND, (WPARAM)IDD_LINELISTBOX, + MAKELONG(hLBName, LBN_SELCHANGE)); + + break; /* End of WM_INITDIALOG */ + + case WM_CLOSE: + /* Closing the Dialog behaves the same as Cancel */ + PostMessage(hDlg, WM_COMMAND, IDCANCEL, 0L); + break; /* End of WM_CLOSE */ + + case WM_COMMAND: + switch(wParam) { + case IDD_LINELISTBOX: + if(HIWORD(lParam) == LBN_SELCHANGE) { + // update the line range display + nIndex=(int)SendMessage(hLBName, LB_GETCURSEL, 0, 0L); + lpOutlineName = (LPOUTLINENAME)SendMessage(hLBName, LB_GETITEMDATA, + (WPARAM)nIndex,0L); + if (lpOutlineName) { + SetDlgItemInt( + hDlg, + IDD_FROM, + (UINT) lpOutlineName->m_nStartLine + 1, + FALSE + ); + SetDlgItemInt( + hDlg, + IDD_TO, + (UINT) lpOutlineName->m_nEndLine + 1, + FALSE + ); + } + break; + } + // double click will fall through + else if(HIWORD(lParam) != LBN_DBLCLK) + break; + + case IDOK: + nIndex=(int)SendMessage(hLBName,LB_GETCURSEL,0,0L); + if(nIndex!=LB_ERR) { + lpOutlineName = (LPOUTLINENAME)SendMessage(hLBName, + LB_GETITEMDATA, (WPARAM)nIndex, 0L); + lrLineRange.m_nStartLine=lpOutlineName->m_nStartLine; + lrLineRange.m_nEndLine = lpOutlineName->m_nEndLine; + OutlineDoc_SetSel(lpOutlineDoc, &lrLineRange); + } // fall through + + case IDCANCEL: + /* Ignore data values entered into the controls */ + /* and dismiss the dialog window returning FALSE */ + EndDialog(hDlg,0); + break; + + } + break; /* End of WM_COMMAND */ + + default: + return FALSE; + } + + return TRUE; +} /* End of GotoNameDlgProc */ + + + +/* NameDlg_LoadComboBox + * -------------------- + * + * Load defined names into combo box + */ +void NameDlg_LoadComboBox(LPOUTLINENAMETABLE lpOutlineNameTable,HWND hCombo) +{ + LPOUTLINENAME lpOutlineName; + int i, nIndex; + int nCount; + + nCount=OutlineNameTable_GetCount((LPOUTLINENAMETABLE)lpOutlineNameTable); + if(!nCount) return; + + SendMessage(hCombo,WM_SETREDRAW,(WPARAM)FALSE,0L); + for(i=0; im_szName + ); + SendMessage(hCombo,CB_SETITEMDATA,(WPARAM)nIndex,(LPARAM)lpOutlineName); + } + SendMessage(hCombo,WM_SETREDRAW,(WPARAM)TRUE,0L); +} + + +/* NameDlg_LoadListBox + * ------------------- + * + * Load defined names into list box + */ +void NameDlg_LoadListBox(LPOUTLINENAMETABLE lpOutlineNameTable,HWND hListBox) +{ + int i; + int nCount; + int nIndex; + LPOUTLINENAME lpOutlineName; + + nCount=OutlineNameTable_GetCount((LPOUTLINENAMETABLE)lpOutlineNameTable); + + SendMessage(hListBox,WM_SETREDRAW,(WPARAM)FALSE,0L); + for(i=0; im_szName + ); + SendMessage(hListBox,LB_SETITEMDATA,(WPARAM)nIndex,(LPARAM)lpOutlineName); + } + SendMessage(hListBox,WM_SETREDRAW,(WPARAM)TRUE,0L); +} + + +/* NameDlg_AddName + * --------------- + * + * Add a name to the name table corresponding to the name dialog + * combo box. + */ +void NameDlg_AddName(HWND hCombo, LPOUTLINEDOC lpOutlineDoc, LPSTR lpszName, LPLINERANGE lplrSel) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + LPOUTLINENAME lpOutlineName; + + lpOutlineName = OutlineApp_CreateName(lpOutlineApp); + + if (lpOutlineName) { + lstrcpy(lpOutlineName->m_szName, lpszName); + lpOutlineName->m_nStartLine = lplrSel->m_nStartLine; + lpOutlineName->m_nEndLine = lplrSel->m_nEndLine; + OutlineDoc_AddName(lpOutlineDoc, lpOutlineName); + } else { + // REVIEW: do we need error message here? + } +} + + +/* NameDlg_UpdateName + * ------------------ + * + * Update a name in the name table corresponding to a name in + * the name dialog combo box. + */ +void NameDlg_UpdateName(HWND hCombo, LPOUTLINEDOC lpOutlineDoc, int nIndex, LPSTR lpszName, LPLINERANGE lplrSel) +{ + LPOUTLINENAME lpOutlineName; + + lpOutlineName = (LPOUTLINENAME)SendMessage( + hCombo, + CB_GETITEMDATA, + (WPARAM)nIndex, + 0L + ); + + OutlineName_SetName(lpOutlineName, lpszName); + OutlineName_SetSel(lpOutlineName, lplrSel, TRUE /* name modified */); + OutlineDoc_SetModified(lpOutlineDoc, TRUE, FALSE, FALSE); +} + + +/* NameDlg_DeleteName + * ------------------ + * + * Delete a name from the name dialog combo box and corresponding + * name table. + */ +void NameDlg_DeleteName(HWND hCombo, LPOUTLINEDOC lpOutlineDoc, UINT nIndex) +{ + SendMessage(hCombo,CB_DELETESTRING,(WPARAM)nIndex,0L); + OutlineDoc_DeleteName(lpOutlineDoc, nIndex); +} + +/* PlaceBitmap + * ----------- + * + * Places a bitmap centered in the specified control in the dialog on the + * specified DC. + * + */ + +PlaceBitmap(HWND hDlg, int control, HDC hDC, HBITMAP hBitmap) +{ + BITMAP bm; + HDC hdcmem; + HBITMAP hbmOld; + RECT rcControl; // Rect of dialog control + int width, height; + + GetObject(hBitmap, sizeof(BITMAP), &bm); + + hdcmem= CreateCompatibleDC(hDC); + hbmOld = SelectObject(hdcmem, hBitmap); + + // Get rect of control in screen coords, and translate to our dialog + // box's coordinates + GetWindowRect(GetDlgItem(hDlg, control), &rcControl); + MapWindowPoints(NULL, hDlg, (LPPOINT)&rcControl, 2); + + width = rcControl.right - rcControl.left; + height = rcControl.bottom - rcControl.top; + + BitBlt(hDC, rcControl.left + (width - bm.bmWidth) / 2, + rcControl.top + (height - bm.bmHeight) /2, + bm.bmWidth, bm.bmHeight, + hdcmem, 0, 0, SRCCOPY); + + SelectObject(hdcmem, hbmOld); + DeleteDC(hdcmem); + return 1; +} + + + +/* AboutDlgProc + * ------------ + * + * Dialog procedure for the About function + */ +BOOL CALLBACK EXPORT AboutDlgProc(HWND hDlg, UINT Message, WPARAM wParam, LPARAM lParam) +{ + int narrVersion[2]; + static HBITMAP hbmLogo; + + switch(Message) { + + case WM_INITDIALOG: + // get version number of app + wsprintf(g_szBuf, "About %s", (LPCSTR)APPNAME); + SetWindowText(hDlg, (LPCSTR)g_szBuf); + OutlineApp_GetAppVersionNo(g_lpApp, narrVersion); + wsprintf(g_szBuf, "%s version %d.%d", (LPSTR) APPDESC, + narrVersion[0], narrVersion[1]); + SetDlgItemText(hDlg, IDD_APPTEXT, (LPCSTR)g_szBuf); + + // Load bitmap for displaying later + hbmLogo = LoadBitmap(g_lpApp->m_hInst, "LogoBitmap"); + TraceDebug(hDlg, IDD_BITMAPLOCATION); + ShowWindow(GetDlgItem(hDlg, IDD_BITMAPLOCATION), SW_HIDE); + break; + + case WM_PAINT: + { + PAINTSTRUCT ps; + BeginPaint(hDlg, &ps); + + // Display bitmap in IDD_BITMAPLOCATION control area + PlaceBitmap(hDlg, IDD_BITMAPLOCATION, ps.hdc, hbmLogo); + EndPaint(hDlg, &ps); + } + break; + + case WM_CLOSE : + PostMessage(hDlg, WM_COMMAND, IDOK, 0L); + break; + + case WM_COMMAND : + switch(wParam) { + case IDOK: + case IDCANCEL: + if (hbmLogo) DeleteObject(hbmLogo); + EndDialog(hDlg,0); + break; + } + break; + + default : + return FALSE; + + } + return TRUE; +} diff --git a/private/oleutest/letest/outline/dialogs.dlg b/private/oleutest/letest/outline/dialogs.dlg new file mode 100644 index 000000000..a77bbde65 --- /dev/null +++ b/private/oleutest/letest/outline/dialogs.dlg @@ -0,0 +1,92 @@ +/************************************************************************* +** +** OLE 2.0 Sample Code +** +** dialogs.dlg +** +** Resource file for dialogs +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + +ADDEDITLINE DIALOG 6, 18, 225, 53 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +FONT 8, "MS Shell Dlg" +BEGIN + EDITTEXT IDD_EDIT, 5, 16, 212, 13, ES_AUTOHSCROLL + LTEXT "Enter text for the line", -1, 5, 4, 72, 8 + PUSHBUTTON "Cancel", IDCANCEL, 177, 35, 40, 14 + DEFPUSHBUTTON "OK", IDOK, 5, 35, 40, 14 +END + +DEFINENAME DIALOG 6, 18, 160, 100 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Define Name" +FONT 8, "MS Shell Dlg" +BEGIN + COMBOBOX IDD_COMBO, 5, 17, 98, 49, CBS_SIMPLE | CBS_AUTOHSCROLL | + CBS_SORT | WS_VSCROLL | WS_TABSTOP + DEFPUSHBUTTON "OK", IDOK, 114, 11, 40, 14 + PUSHBUTTON "Close", IDD_CLOSE, 114, 31, 40, 14 + PUSHBUTTON "Delete", IDD_DELETE, 114, 51, 40, 14 + LTEXT "Defined Names", -1, 5, 6, 57, 8 + LTEXT "Line Range : ", -1, 5, 76, 44, 8 + LTEXT "to", -1, 86, 76, 10, 8 + EDITTEXT IDD_FROM, 50, 75, 32, 12, ES_AUTOHSCROLL + EDITTEXT IDD_TO, 99, 75, 32, 12, ES_AUTOHSCROLL +END + +GOTONAME DIALOG 6, 18, 160, 93 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Goto Name" +FONT 8, "MS Shell Dlg" +BEGIN + LISTBOX IDD_LINELISTBOX, 5, 18, 99, 49, LBS_SORT | WS_VSCROLL | + WS_TABSTOP + LTEXT "Goto:", -1, 5, 7, 20, 8 + DEFPUSHBUTTON "OK", IDOK, 115, 18, 40, 14 + PUSHBUTTON "Cancel", IDCANCEL, 115, 38, 40, 14 + LTEXT "Line Range : ", -1, 5, 79, 44, 8 + LTEXT "to", -1, 79, 79, 10, 8 + LTEXT "", IDD_FROM, 55, 79, 19, 8 + LTEXT "", IDD_TO, 93, 79, 20, 8 +END + +PRINT DIALOG 69, 41, 109, 48 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION +CAPTION "Outline" +FONT 8, "MS Shell Dlg" +BEGIN + PUSHBUTTON "Cancel", IDCANCEL, 34, 28, 40, 14 + LTEXT "Printing...", -1, 17, 8, 72, 10 +END + +SETLINEHEIGHT DIALOG 52, 52, 160, 80 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Set Line Height" +FONT 8, "MS Shell Dlg" +BEGIN + EDITTEXT IDD_EDIT, 34, 42, 50, 12, ES_AUTOHSCROLL + LTEXT "Height:", IDD_TEXT, 6, 43, 28, 12 + CONTROL "Use Standard Height", IDD_CHECK, "Button", + BS_AUTOCHECKBOX | WS_TABSTOP, 6, 64, 80, 10 + LTEXT "Enter Line Height (100 units = 1mm)", -1, 6, 10, 121, + 10 + DEFPUSHBUTTON "OK", IDOK, 110, 40, 40, 14 + PUSHBUTTON "Cancel", IDCANCEL, 110, 62, 40, 14 + LTEXT "", IDD_LIMIT, 6, 24, 89, 8 +END + +ABOUT DIALOG DISCARDABLE 17, 21, 205, 138 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +FONT 8, "MS Shell Dlg" +BEGIN + CTEXT "",IDD_APPTEXT,5,90,195,10 + DEFPUSHBUTTON "OK",IDOK,81,117,45,15 + CTEXT "Copyright \2511992 - 1993, Microsoft Corporation", -1, + 25,103,156,8 + CONTROL "",IDD_BITMAPLOCATION,"Static",SS_BLACKFRAME,11,10,184, + 68 + CONTROL "",-1,"Static",SS_BLACKFRAME,6,5,194,78 +END diff --git a/private/oleutest/letest/outline/dirs b/private/oleutest/letest/outline/dirs new file mode 100644 index 000000000..0052409cb --- /dev/null +++ b/private/oleutest/letest/outline/dirs @@ -0,0 +1,32 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + dirs. + +Abstract: + + This file specifies the subdirectories of the current directory that + contain component makefiles. + + +Author: + + Rick Sailor (Ricksa) 15-Mar-1994 + +!ENDIF + +# +# This is a list of all subdirectories that build required components. +# Each subdirectory name should appear on a line by itself. The build +# follows the order in which the subdirectories are specified. +# + +DIRS= \ + \ + cntroutl \ + icntrotl \ + isvrotl \ + svroutl diff --git a/private/oleutest/letest/outline/dragcopy.cur b/private/oleutest/letest/outline/dragcopy.cur new file mode 100644 index 000000000..89c7c960d Binary files /dev/null and b/private/oleutest/letest/outline/dragcopy.cur differ diff --git a/private/oleutest/letest/outline/dragdrop.c b/private/oleutest/letest/outline/dragdrop.c new file mode 100644 index 000000000..ab4b95795 --- /dev/null +++ b/private/oleutest/letest/outline/dragdrop.c @@ -0,0 +1,674 @@ +/************************************************************************* +** +** OLE 2 Sample Code +** +** dragdrop.c +** +** This file contains the major interfaces, methods and related support +** functions for implementing Drag/Drop. The code contained in this +** file is used by BOTH the Container and Server (Object) versions +** of the Outline sample code. +** The Drag/Drop support includes the following implementation objects: +** +** OleDoc Object +** exposed interfaces: +** IDropSource +** IDropTarget +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + +#include "outline.h" + +OLEDBGDATA + +extern LPOUTLINEAPP g_lpApp; + + +#if defined( USE_DRAGDROP ) + +/* OleDoc_QueryDrag + * ---------------- + * Check to see if Drag operation should be initiated. A Drag operation + * should be initiated when the mouse in either the top 10 pixels of the + * selected list box entry or in the bottom 10 pixels of the last selected + * item. + */ + +BOOL OleDoc_QueryDrag(LPOLEDOC lpOleDoc, int y) +{ + LPLINELIST lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList; + LINERANGE LineRange; + + if ( LineList_GetSel( lpLL, (LPLINERANGE)&LineRange) ) { + RECT rect; + + if (!LineList_GetLineRect(lpLL,LineRange.m_nStartLine,(LPRECT)&rect)) + return FALSE ; + + if ( rect.top <= y && y <= rect.top + DD_SEL_THRESH ) + return TRUE; + + LineList_GetLineRect( lpLL, LineRange.m_nEndLine, (LPRECT)&rect ); + if ( rect.bottom >= y && y >= rect.bottom - DD_SEL_THRESH ) + return TRUE; + + } + + return FALSE; +} + +/* OleDoc_DoDragScroll + * ------------------- + * Check to see if Drag scroll operation should be initiated. A Drag scroll + * operation should be initiated when the mouse has remained in the active + * scroll area (11 pixels frame around border of window) for a specified + * amount of time (50ms). + */ + +BOOL OleDoc_DoDragScroll(LPOLEDOC lpOleDoc, POINTL pointl) +{ + LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; + LPLINELIST lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList; + HWND hWndListBox = LineList_GetWindow(lpLL); + DWORD dwScrollDir = SCROLLDIR_NULL; + DWORD dwTime = GetCurrentTime(); + int nScrollInset = lpOleApp->m_nScrollInset; + int nScrollDelay = lpOleApp->m_nScrollDelay; + int nScrollInterval = lpOleApp->m_nScrollInterval; + POINT point; + RECT rect; + + if ( lpLL->m_nNumLines == 0 ) + return FALSE; + + point.x = (int)pointl.x; + point.y = (int)pointl.y; + + ScreenToClient( hWndListBox, &point); + GetClientRect ( hWndListBox, (LPRECT) &rect ); + + if (rect.top <= point.y && point.y<=(rect.top+nScrollInset)) + dwScrollDir = SCROLLDIR_UP; + else if ((rect.bottom-nScrollInset) <= point.y && point.y <= rect.bottom) + dwScrollDir = SCROLLDIR_DOWN; + + if (lpOleDoc->m_dwTimeEnterScrollArea) { + + /* cursor was already in Scroll Area */ + + if (! dwScrollDir) { + /* cusor moved OUT of scroll area. + ** clear "EnterScrollArea" time. + */ + lpOleDoc->m_dwTimeEnterScrollArea = 0L; + lpOleDoc->m_dwNextScrollTime = 0L; + lpOleDoc->m_dwLastScrollDir = SCROLLDIR_NULL; + } else if (dwScrollDir != lpOleDoc->m_dwLastScrollDir) { + /* cusor moved into a different direction scroll area. + ** reset "EnterScrollArea" time to start a new 50ms delay. + */ + lpOleDoc->m_dwTimeEnterScrollArea = dwTime; + lpOleDoc->m_dwNextScrollTime = dwTime + (DWORD)nScrollDelay; + lpOleDoc->m_dwLastScrollDir = dwScrollDir; + } else if (dwTime && dwTime >= lpOleDoc->m_dwNextScrollTime) { + LineList_Scroll ( lpLL, dwScrollDir ); // Scroll doc NOW + lpOleDoc->m_dwNextScrollTime = dwTime + (DWORD)nScrollInterval; + } + } else { + if (dwScrollDir) { + /* cusor moved INTO a scroll area. + ** reset "EnterScrollArea" time to start a new 50ms delay. + */ + lpOleDoc->m_dwTimeEnterScrollArea = dwTime; + lpOleDoc->m_dwNextScrollTime = dwTime + (DWORD)nScrollDelay; + lpOleDoc->m_dwLastScrollDir = dwScrollDir; + } + } + + return (dwScrollDir ? TRUE : FALSE); +} + + +/* OleDoc_QueryDrop +** ---------------- +** Check if the desired drop operation (identified by the given key +** state) is possible at the current mouse position (pointl). +*/ +BOOL OleDoc_QueryDrop ( + LPOLEDOC lpOleDoc, + DWORD grfKeyState, + POINTL pointl, + BOOL fDragScroll, + LPDWORD lpdwEffect +) +{ + LPLINELIST lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList; + LINERANGE linerange; + short nIndex = LineList_GetLineIndexFromPointl( lpLL, pointl ); + DWORD dwScrollEffect = 0L; + DWORD dwOKEffects = *lpdwEffect; + + /* check if the cursor is in the active scroll area, if so need the + ** special scroll cursor. + */ + if (fDragScroll) + dwScrollEffect = DROPEFFECT_SCROLL; + + /* if we have already determined that the source does NOT have any + ** acceptable data for us, the return NO-DROP + */ + if (! lpOleDoc->m_fCanDropCopy && ! lpOleDoc->m_fCanDropLink) + goto dropeffect_none; + + /* if the Drag/Drop is local to our document, we can NOT accept a + ** drop in the middle of the current selection (which is the exact + ** data that is being dragged!). + */ + if (lpOleDoc->m_fLocalDrag) { + LineList_GetSel( lpLL, (LPLINERANGE)&linerange ); + + if (linerange.m_nStartLine <= nIndex && nIndexm_fCanDropCopy) + *lpdwEffect = DROPEFFECT_MOVE; + else if ((DROPEFFECT_COPY & dwOKEffects) && lpOleDoc->m_fCanDropCopy) + *lpdwEffect = DROPEFFECT_COPY; + else if ((DROPEFFECT_LINK & dwOKEffects) && lpOleDoc->m_fCanDropLink) + *lpdwEffect = DROPEFFECT_LINK; + else + goto dropeffect_none; + } else { + /* OLE2NOTE: we should check if the drag source application allows + ** the desired drop effect. + */ + if (!(*lpdwEffect & dwOKEffects)) + goto dropeffect_none; + + if ((*lpdwEffect == DROPEFFECT_COPY || *lpdwEffect == DROPEFFECT_MOVE) + && ! lpOleDoc->m_fCanDropCopy) + goto dropeffect_none; + + if (*lpdwEffect == DROPEFFECT_LINK && ! lpOleDoc->m_fCanDropLink) + goto dropeffect_none; + } + + *lpdwEffect |= dwScrollEffect; + return TRUE; + +dropeffect_none: + + *lpdwEffect = DROPEFFECT_NONE; + return FALSE; +} + +/* OleDoc_DoDragDrop + * ----------------- + * Actually perform a drag/drop operation with the current selection in + * the source document (lpSrcOleDoc). + * + * returns the result effect of the drag/drop operation: + * DROPEFFECT_NONE, + * DROPEFFECT_COPY, + * DROPEFFECT_MOVE, or + * DROPEFFECT_LINK + */ + +DWORD OleDoc_DoDragDrop (LPOLEDOC lpSrcOleDoc) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; + LPOUTLINEDOC lpSrcOutlineDoc = (LPOUTLINEDOC)lpSrcOleDoc; + LPOLEDOC lpDragDoc; + LPLINELIST lpSrcLL = + (LPLINELIST)&((LPOUTLINEDOC)lpSrcOleDoc)->m_LineList; + DWORD dwEffect = 0; + LPLINE lplineStart, lplineEnd; + LINERANGE linerange; + BOOL fPrevEnable1; + BOOL fPrevEnable2; + HRESULT hrErr; + + OLEDBG_BEGIN3("OleDoc_DoDragDrop\r\n") + + /* squirrel away a copy of the current selection to the ClipboardDoc */ + lpDragDoc = (LPOLEDOC)OutlineDoc_CreateDataTransferDoc(lpSrcOutlineDoc); + if ( ! lpDragDoc) { + dwEffect = DROPEFFECT_NONE; + goto error; + } + + /* OLE2NOTE: initially the DataTransferDoc is created with a 0 ref + ** count. in order to have a stable Doc object during the drag/ + ** drop operation, we intially AddRef the Doc ref cnt and later + ** Release it. This AddRef is artificial; it is simply + ** done to guarantee that a harmless QueryInterface followed by + ** a Release does not inadvertantly force our object to destroy + ** itself prematurely. + */ + OleDoc_AddRef(lpDragDoc); + + //NOTE: we need to keep the LPLINE pointers + // rather than the indexes because the + // indexes will not be the same after the + // drop occurs -- the drop adds new + // entries to the list thereby shifting + // the whole list. + LineList_GetSel( lpSrcLL, (LPLINERANGE)&linerange ); + lplineStart = LineList_GetLine ( lpSrcLL, linerange.m_nStartLine ); + lplineEnd = LineList_GetLine ( lpSrcLL, linerange.m_nEndLine ); + + if (! lplineStart || ! lplineEnd) { + dwEffect = DROPEFFECT_NONE; + goto error; + } + + lpSrcOleDoc->m_fLocalDrop = FALSE; + lpSrcOleDoc->m_fLocalDrag = TRUE; + + /* OLE2NOTE: it is VERY important to DISABLE the Busy/NotResponding + ** dialogs BEFORE calling DoDragDrop. The DoDragDrop API starts + ** a mouse capture modal loop. if the Busy/NotResponding comes + ** up in the middle of this loop (eg. if one of the remoted + ** calls like IDropTarget::DragOver call takes a long time, then + ** the NotResponding dialog may want to come up), then the mouse + ** capture is lost by OLE and things can get messed up. + */ + OleApp_DisableBusyDialogs(lpOleApp, &fPrevEnable1, &fPrevEnable2); + + OLEDBG_BEGIN2("DoDragDrop called\r\n") + hrErr = DoDragDrop ( (LPDATAOBJECT) &lpDragDoc->m_DataObject, + (LPDROPSOURCE) &lpSrcOleDoc->m_DropSource, + DROPEFFECT_MOVE | DROPEFFECT_COPY | DROPEFFECT_LINK, + (LPDWORD) &dwEffect + ); + OLEDBG_END2 + + // re-enable the Busy/NotResponding dialogs + OleApp_EnableBusyDialogs(lpOleApp, fPrevEnable1, fPrevEnable2); + +#if defined( _DEBUG ) + if (FAILED(hrErr)) + OleDbgOutHResult("DoDragDrop returned", hrErr); +#endif + lpSrcOleDoc->m_fLocalDrag = FALSE; + + /* OLE2NOTE: we need to guard the lifetime of our lpSrcOleDoc + ** object while we are deleting the lines that were drag + ** moved. it is possible that deleting these lines could + ** cause the deletion of a PseudoObj. the deletion of a + ** PseudoObj will cause the Doc to be unlock + ** (CoLockObjectExternal(FALSE,TRUE) called). each PseudoObj + ** holds a strong lock on the Doc. It is always best to have + ** a memory guard around such critical sections of code. in + ** this case, it is particularly important if we were an + ** in-place active server and this drag ended up in a drop + ** in our outer container. this scenario will lead to a + ** crash if we do not hold this memory guard. + */ + OleDoc_Lock(lpSrcOleDoc, TRUE, 0); + + /* if after the Drag/Drop modal (mouse capture) loop is finished + ** and a drag MOVE operation was performed, then we must delete + ** the lines that were dragged. + */ + if ( GetScode(hrErr) == DRAGDROP_S_DROP + && (dwEffect & DROPEFFECT_MOVE) != 0 ) { + + int i,j,iEnd; + LPLINE lplineFocusLine; + + /* disable repainting and sending data changed notifications + ** until after all lines have been deleted. + */ + OutlineDoc_SetRedraw ( (LPOUTLINEDOC)lpSrcOleDoc, FALSE ); + + /* if the drop was local to our document, then we must take + ** into account that the line indices of the original source + ** of the drag could have shifted because the dropped lines + ** have been inserted into our document. thus we will + ** re-determine the source line indices. + */ + if (lpSrcOleDoc->m_fLocalDrop) { + i = LineList_GetFocusLineIndex ( lpSrcLL ); + lplineFocusLine = LineList_GetLine ( lpSrcLL, i ); + } + + for ( i = j = LineList_GetLineIndex(lpSrcLL,lplineStart ) , + iEnd = LineList_GetLineIndex(lpSrcLL,lplineEnd ) ; + i <= iEnd ; + i++ + ) OutlineDoc_DeleteLine ((LPOUTLINEDOC)lpSrcOleDoc, j ); + + LineList_RecalcMaxLineWidthInHimetric(lpSrcLL, 0); + + if (lpSrcOleDoc->m_fLocalDrop) { + i = LineList_GetLineIndex ( lpSrcLL, lplineFocusLine ); + LineList_SetFocusLine ( lpSrcLL, (WORD)i ); + } + + OutlineDoc_SetRedraw ( (LPOUTLINEDOC)lpSrcOleDoc, TRUE ); + + /* if it is a local Drag/Drop move, we need to balance the + ** SetRedraw(FALSE) call that was made in the implementation + ** of IDropTarget::Drop. + */ + if (lpSrcOleDoc->m_fLocalDrop) + OutlineDoc_SetRedraw ( (LPOUTLINEDOC)lpSrcOleDoc, TRUE ); + + LineList_ForceRedraw ( lpSrcLL, FALSE ); + } + + OleDoc_Release(lpDragDoc); // rel artificial AddRef above + OleDoc_Lock(lpSrcOleDoc, FALSE, FALSE); // unlock artificial lock guard + + OLEDBG_END3 + return dwEffect; + +error: + OLEDBG_END3 + return dwEffect; +} + + + +/************************************************************************* +** OleDoc::IDropSource interface implementation +*************************************************************************/ + +STDMETHODIMP OleDoc_DropSource_QueryInterface( + LPDROPSOURCE lpThis, + REFIID riid, + LPVOID FAR* lplpvObj +) +{ + LPOLEDOC lpOleDoc = ((struct CDocDropSourceImpl FAR*)lpThis)->lpOleDoc; + + return OleDoc_QueryInterface(lpOleDoc, riid, lplpvObj); +} + + +STDMETHODIMP_(ULONG) OleDoc_DropSource_AddRef( LPDROPSOURCE lpThis ) +{ + LPOLEDOC lpOleDoc = ((struct CDocDropSourceImpl FAR*)lpThis)->lpOleDoc; + + OleDbgAddRefMethod(lpThis, "IDropSource"); + + return OleDoc_AddRef(lpOleDoc); +} + + +STDMETHODIMP_(ULONG) OleDoc_DropSource_Release ( LPDROPSOURCE lpThis) +{ + LPOLEDOC lpOleDoc = ((struct CDocDropSourceImpl FAR*)lpThis)->lpOleDoc; + + OleDbgReleaseMethod(lpThis, "IDropSource"); + + return OleDoc_Release(lpOleDoc); +} + + +STDMETHODIMP OleDoc_DropSource_QueryContinueDrag ( + LPDROPSOURCE lpThis, + BOOL fEscapePressed, + DWORD grfKeyState +){ + if (fEscapePressed) + return ResultFromScode(DRAGDROP_S_CANCEL); + else if (!(grfKeyState & MK_LBUTTON)) + return ResultFromScode(DRAGDROP_S_DROP); + else + return NOERROR; +} + + +STDMETHODIMP OleDoc_DropSource_GiveFeedback ( + LPDROPSOURCE lpThis, + DWORD dwEffect +) +{ + // Tell OLE to use the standard drag/drop feedback cursors + return ResultFromScode(DRAGDROP_S_USEDEFAULTCURSORS); + +#if defined( IF_SPECIAL_DD_CURSORS_NEEDED ) + switch (dwEffect) { + + case DROPEFFECT_NONE: + SetCursor ( ((LPOLEAPP)g_lpApp)->m_hcursorDragNone ); + break; + + case DROPEFFECT_COPY: + SetCursor ( ((LPOLEAPP)g_lpApp)->m_hcursorDragCopy ); + break; + + case DROPEFFECT_MOVE: + SetCursor ( ((LPOLEAPP)g_lpApp)->m_hcursorDragMove ); + break; + + case DROPEFFECT_LINK: + SetCursor ( ((LPOLEAPP)g_lpApp)->m_hcursorDragLink ); + break; + + } + + return NOERROR; +#endif + +} + +/************************************************************************* +** OleDoc::IDropTarget interface implementation +*************************************************************************/ + +STDMETHODIMP OleDoc_DropTarget_QueryInterface( + LPDROPTARGET lpThis, + REFIID riid, + LPVOID FAR* lplpvObj +) +{ + LPOLEDOC lpOleDoc = ((struct CDocDropTargetImpl FAR*)lpThis)->lpOleDoc; + + return OleDoc_QueryInterface(lpOleDoc, riid, lplpvObj); +} + + +STDMETHODIMP_(ULONG) OleDoc_DropTarget_AddRef(LPDROPTARGET lpThis) +{ + LPOLEDOC lpOleDoc = ((struct CDocDropTargetImpl FAR*)lpThis)->lpOleDoc; + + OleDbgAddRefMethod(lpThis, "IDropTarget"); + + return OleDoc_AddRef(lpOleDoc); +} + + +STDMETHODIMP_(ULONG) OleDoc_DropTarget_Release ( LPDROPTARGET lpThis) +{ + LPOLEDOC lpOleDoc = ((struct CDocDropTargetImpl FAR*)lpThis)->lpOleDoc; + + OleDbgReleaseMethod(lpThis, "IDropTarget"); + + return OleDoc_Release(lpOleDoc); +} + + +STDMETHODIMP OleDoc_DropTarget_DragEnter ( + LPDROPTARGET lpThis, + LPDATAOBJECT lpDataObj, + DWORD grfKeyState, + POINTL pointl, + LPDWORD lpdwEffect +) +{ + LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; + LPOLEDOC lpOleDoc = ((struct CDocDropTargetImpl FAR*)lpThis)->lpOleDoc; + LPLINELIST lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList; + BOOL fDragScroll; + + OLEDBG_BEGIN2("OleDoc_DropTarget_DragEnter\r\n") + + lpOleDoc->m_fDragLeave = FALSE; + lpOleDoc->m_dwTimeEnterScrollArea = 0; + lpOleDoc->m_dwLastScrollDir = SCROLLDIR_NULL; + + + /* Determine if the drag source data object offers a data format + ** that we can copy and/or link to. + */ + + lpOleDoc->m_fCanDropCopy = OleDoc_QueryPasteFromData( + lpOleDoc, + lpDataObj, + FALSE /* fLink */ + ); + + lpOleDoc->m_fCanDropLink = OleDoc_QueryPasteFromData( + lpOleDoc, + lpDataObj, + TRUE /* fLink */ + ); + + fDragScroll = OleDoc_DoDragScroll ( lpOleDoc, pointl ); + + if (OleDoc_QueryDrop(lpOleDoc,grfKeyState,pointl,fDragScroll,lpdwEffect)) + LineList_SetDragOverLineFromPointl( lpLL, pointl ); + + OLEDBG_END2 + return NOERROR; + +} + +STDMETHODIMP OleDoc_DropTarget_DragOver ( + LPDROPTARGET lpThis, + DWORD grfKeyState, + POINTL pointl, + LPDWORD lpdwEffect +) +{ + LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; + LPOLEDOC lpOleDoc = ((struct CDocDropTargetImpl FAR*)lpThis)->lpOleDoc; + LPLINELIST lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList; + BOOL fDragScroll; + + fDragScroll = OleDoc_DoDragScroll ( lpOleDoc, pointl ); + + if (OleDoc_QueryDrop(lpOleDoc,grfKeyState, pointl,fDragScroll,lpdwEffect)) + LineList_SetDragOverLineFromPointl( lpLL, pointl ); + else + LineList_RestoreDragFeedback( lpLL ); + + return NOERROR; +} + + +STDMETHODIMP OleDoc_DropTarget_DragLeave ( LPDROPTARGET lpThis) +{ + LPOLEDOC lpOleDoc = ((struct CDocDropTargetImpl FAR*)lpThis)->lpOleDoc; + LPLINELIST lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList; + + OLEDBG_BEGIN2("OleDoc_DropTarget_DragLeave\r\n") + + lpOleDoc->m_fDragLeave = TRUE; + + LineList_RestoreDragFeedback( lpLL ); + + OLEDBG_END2 + return NOERROR; + +} + +STDMETHODIMP OleDoc_DropTarget_Drop ( + LPDROPTARGET lpThis, + LPDATAOBJECT lpDataObj, + DWORD grfKeyState, + POINTL pointl, + LPDWORD lpdwEffect +) +{ + LPOLEDOC lpOleDoc = ((struct CDocDropTargetImpl FAR*)lpThis)->lpOleDoc; + LPLINELIST lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList; + + OLEDBG_BEGIN2("OleDoc_DropTarget_Drop\r\n") + + lpOleDoc->m_fDragLeave = TRUE; + lpOleDoc->m_fLocalDrop = TRUE; + + LineList_RestoreDragFeedback( lpLL ); + SetFocus( LineList_GetWindow( lpLL) ); + + if (OleDoc_QueryDrop(lpOleDoc, grfKeyState, pointl, FALSE, lpdwEffect)) { + BOOL fLink = (*lpdwEffect == DROPEFFECT_LINK); + int iFocusLine = LineList_GetFocusLineIndex( lpLL ); + BOOL fStatus; + + OutlineDoc_SetRedraw ( (LPOUTLINEDOC)lpOleDoc, FALSE ); + LineList_SetFocusLineFromPointl ( lpLL, pointl ); + + fStatus = OleDoc_PasteFromData( + lpOleDoc, + lpDataObj, + lpOleDoc->m_fLocalDrag, /* data source is local to app */ + fLink + ); + + // if drop was unsuccessfull, restore the original focus line + if (! fStatus) + LineList_SetFocusLine( lpLL, (WORD)iFocusLine ); + +#if defined( INPLACE_CNTR ) + { + LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOleDoc; + + /* OLE2NOTE: if there is currently a UIActive OLE object, + ** then we must tell it to UIDeactivate after + ** the drop has completed. + */ + if (lpContainerDoc->m_lpLastUIActiveLine) { + ContainerLine_UIDeactivate( + lpContainerDoc->m_lpLastUIActiveLine); + } + } +#endif + +#if defined( INPLACE_SVR ) + { + /* OLE2NOTE: if the drop was into a in-place visible + ** (in-place active but NOT UIActive object), then we + ** want to UIActivate the object after the drop is + ** complete. + */ + ServerDoc_UIActivate((LPSERVERDOC) lpOleDoc); + } +#endif + + + /* if it is a local Drag/Drop move, don't enable redraw. + ** after the source is done deleting the moved lines, it + ** will re-enable redraw + */ + if (! (lpOleDoc->m_fLocalDrag + && (*lpdwEffect & DROPEFFECT_MOVE) != 0 )) + OutlineDoc_SetRedraw ( (LPOUTLINEDOC)lpOleDoc, TRUE ); + } + + OLEDBG_END2 + return NOERROR; +} + + +#endif // USE_DRAGDROP diff --git a/private/oleutest/letest/outline/draglink.cur b/private/oleutest/letest/outline/draglink.cur new file mode 100644 index 000000000..fca1fc090 Binary files /dev/null and b/private/oleutest/letest/outline/draglink.cur differ diff --git a/private/oleutest/letest/outline/dragmove.cur b/private/oleutest/letest/outline/dragmove.cur new file mode 100644 index 000000000..a9a9bd636 Binary files /dev/null and b/private/oleutest/letest/outline/dragmove.cur differ diff --git a/private/oleutest/letest/outline/dragnone.cur b/private/oleutest/letest/outline/dragnone.cur new file mode 100644 index 000000000..b002e96b3 Binary files /dev/null and b/private/oleutest/letest/outline/dragnone.cur differ diff --git a/private/oleutest/letest/outline/frametls.c b/private/oleutest/letest/outline/frametls.c new file mode 100644 index 000000000..cb28d17ee --- /dev/null +++ b/private/oleutest/letest/outline/frametls.c @@ -0,0 +1,1075 @@ +/************************************************************************* +** +** OLE 2 Server Sample Code +** +** frametls.c +** +** This file contains all FrameTools methods and related support +** functions. The FrameTools object is an encapsulation of the apps +** formula bar and button bar. +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + +#include "outline.h" + +OLEDBGDATA + +/* private function prototype */ +static void Bar_Move(LPBAR lpbar, LPRECT lprcClient, LPRECT lprcPopup); +static void FB_ResizeEdit(LPBAR lpbar); + +extern LPOUTLINEAPP g_lpApp; +extern RECT g_rectNull; + +/* + * FrameToolsRegisterClass + * + * Purpose: + * Register the popup toolbar window class + * + * Parameters: + * hInst Process instance + * + * Return Value: + * TRUE if successful + * FALSE if failed + * + */ +BOOL FrameToolsRegisterClass(HINSTANCE hInst) +{ + WNDCLASS wc; + + // Register Tool Palette Class + wc.style = CS_BYTEALIGNWINDOW; + wc.lpfnWndProc = FrameToolsWndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 4; + wc.hInstance = hInst; + wc.hIcon = NULL; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wc.lpszMenuName = NULL; + wc.lpszClassName = CLASS_PALETTE; + + if (!RegisterClass(&wc)) + return FALSE; + else + return TRUE; +} + + +static BOOL FrameTools_CreatePopupPalette(LPFRAMETOOLS lpft, HWND hWndFrame) +{ + if (lpft->m_hWndPopupPalette) + DestroyWindow(lpft->m_hWndPopupPalette); + + lpft->m_hWndPopupPalette = CreateWindow( + CLASS_PALETTE, + "Tool Palette", + WS_POPUP | WS_CAPTION | WS_CLIPCHILDREN, + CW_USEDEFAULT, 0, 0, 0, + hWndFrame, + (HMENU)NULL, + g_lpApp->m_hInst, + 0L + ); + + if (!lpft->m_hWndPopupPalette) + return FALSE; + + SetWindowLong(lpft->m_hWndPopupPalette, 0, (LONG)lpft); + return TRUE; +} + + +/* + * FrameTools_Init + * + * Purpose: + * Init and create the toolbar + * + * Parameters: + * lpft FrameTools object + * hWndParent The window which owns the toolbar + * hInst Process instance + * + * Return Value: + * TRUE if successful + * FALSE if failed + * + */ +BOOL FrameTools_Init(LPFRAMETOOLS lpft, HWND hWndParent, HINSTANCE hInst) +{ + RECT rc; + UINT uPos; + UINT dx; + UINT dy; + + if (!lpft || !hWndParent || !hInst) + return FALSE; + + //Get BTTNCUR's display information + UIToolConfigureForDisplay(&lpft->m_tdd); + + dx=lpft->m_tdd.cxButton; + dy=lpft->m_tdd.cyButton; + + // 15 is calculated from the total number of buttons and separators + lpft->m_uPopupWidth = dx * 15; + + lpft->m_hWndApp = hWndParent; + lpft->m_ButtonBar.m_nState = BARSTATE_TOP; + lpft->m_FormulaBar.m_nState = BARSTATE_TOP; + lpft->m_fInFormulaBar = FALSE; + + lpft->m_fToolsDisabled = FALSE; + + lpft->m_ButtonBar.m_uHeight = lpft->m_tdd.cyBar; + lpft->m_FormulaBar.m_uHeight = lpft->m_tdd.cyBar; + + + //Get our image bitmaps for the display type we're on + if (72 == lpft->m_tdd.uDPI) + lpft->m_hBmp = LoadBitmap(hInst, (LPCSTR)"Image72"); + if (96 == lpft->m_tdd.uDPI) + lpft->m_hBmp = LoadBitmap(hInst, (LPCSTR)"Image96"); + if (120 == lpft->m_tdd.uDPI) + lpft->m_hBmp = LoadBitmap(hInst, (LPCSTR)"Image120"); + + if (!lpft->m_hBmp) + return FALSE; + + /* Create Popup Tool Palette window */ + lpft->m_hWndPopupPalette = NULL; + if (! FrameTools_CreatePopupPalette(lpft, hWndParent)) + return FALSE; + + uPos = 0; + //Create the GizmoBar and the client area window + GetClientRect(hWndParent, &rc); + lpft->m_ButtonBar.m_hWnd = CreateWindow( + CLASS_GIZMOBAR, + "ButtonBar", + WS_CHILD | WS_VISIBLE, + 0, 0, rc.right-rc.left, lpft->m_tdd.cyBar, + hWndParent, + (HMENU)IDC_GIZMOBAR, + hInst, + 0L + ); + + if (!lpft->m_ButtonBar.m_hWnd) + return FALSE; + + + SendMessage(lpft->m_ButtonBar.m_hWnd, WM_SETREDRAW, FALSE, 0L); + + //File new, open, save, print + GBGizmoAdd(lpft->m_ButtonBar.m_hWnd, GIZMOTYPE_BUTTONCOMMAND, uPos++, IDM_F_NEW, dx, dy, NULL, NULL, TOOLIMAGE_FILENEW, GIZMO_NORMAL); + GBGizmoAdd(lpft->m_ButtonBar.m_hWnd, GIZMOTYPE_BUTTONCOMMAND, uPos++, IDM_F_OPEN, dx, dy, NULL, NULL, TOOLIMAGE_FILEOPEN, GIZMO_NORMAL); + GBGizmoAdd(lpft->m_ButtonBar.m_hWnd, GIZMOTYPE_BUTTONCOMMAND, uPos++, IDM_F_SAVE, dx, dy, NULL, NULL, TOOLIMAGE_FILESAVE, GIZMO_NORMAL); + GBGizmoAdd(lpft->m_ButtonBar.m_hWnd, GIZMOTYPE_BUTTONCOMMAND, uPos++, IDM_F_PRINT, dx, dy, NULL, NULL, TOOLIMAGE_FILEPRINT, GIZMO_NORMAL); + + // separator + GBGizmoAdd(lpft->m_ButtonBar.m_hWnd, GIZMOTYPE_SEPARATOR, uPos++, 0, dx/2, dy, NULL, NULL, 0, GIZMO_NORMAL); + + // Edit cut, copy, paste + GBGizmoAdd(lpft->m_ButtonBar.m_hWnd, GIZMOTYPE_BUTTONCOMMAND, uPos++, IDM_E_CUT, dx, dy, NULL, NULL, TOOLIMAGE_EDITCUT, GIZMO_NORMAL); + GBGizmoAdd(lpft->m_ButtonBar.m_hWnd, GIZMOTYPE_BUTTONCOMMAND, uPos++, IDM_E_COPY, dx, dy, NULL, NULL, TOOLIMAGE_EDITCOPY, GIZMO_NORMAL); + GBGizmoAdd(lpft->m_ButtonBar.m_hWnd, GIZMOTYPE_BUTTONCOMMAND, uPos++, IDM_E_PASTE, dx, dy, NULL, NULL, TOOLIMAGE_EDITPASTE, GIZMO_NORMAL); + + // separator + GBGizmoAdd(lpft->m_ButtonBar.m_hWnd, GIZMOTYPE_SEPARATOR, uPos++, 0, dx/2, dy, NULL, NULL, 0, GIZMO_NORMAL); + + // Line indent, unindent + GBGizmoAdd(lpft->m_ButtonBar.m_hWnd, GIZMOTYPE_BUTTONCOMMAND, uPos++, IDM_L_UNINDENTLINE, dx, dy, NULL, lpft->m_hBmp, IDB_UNINDENTLINE, GIZMO_NORMAL); + GBGizmoAdd(lpft->m_ButtonBar.m_hWnd, GIZMOTYPE_BUTTONCOMMAND, uPos++, IDM_L_INDENTLINE, dx, dy, NULL, lpft->m_hBmp, IDB_INDENTLINE, GIZMO_NORMAL); + + // separator + GBGizmoAdd(lpft->m_ButtonBar.m_hWnd, GIZMOTYPE_SEPARATOR, uPos++, 0, dx/2, dy, NULL, NULL, 0, GIZMO_NORMAL); + + // Help + GBGizmoAdd(lpft->m_ButtonBar.m_hWnd, GIZMOTYPE_BUTTONCOMMAND, uPos++, IDM_H_ABOUT, dx, dy, NULL, NULL, TOOLIMAGE_HELP, GIZMO_NORMAL); + + SendMessage(lpft->m_ButtonBar.m_hWnd, WM_SETREDRAW, TRUE, 0L); + + + uPos = 0; + lpft->m_FormulaBar.m_hWnd = CreateWindow( + CLASS_GIZMOBAR, + "FormulaBar", + WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS, + 0, lpft->m_tdd.cyBar, rc.right-rc.left, lpft->m_tdd.cyBar, + hWndParent, + (HMENU)IDC_FORMULABAR, + hInst, + 0L + ); + + if (!lpft->m_FormulaBar.m_hWnd) + return FALSE; + + SendMessage(lpft->m_FormulaBar.m_hWnd, WM_SETREDRAW, FALSE, 0L); + + // Line add line + GBGizmoAdd(lpft->m_FormulaBar.m_hWnd, GIZMOTYPE_BUTTONCOMMAND, uPos++, IDM_L_ADDLINE, dx, dy, NULL, lpft->m_hBmp, IDB_ADDLINE, GIZMO_NORMAL); + + // separator + GBGizmoAdd(lpft->m_FormulaBar.m_hWnd, GIZMOTYPE_SEPARATOR, uPos++, 0, dx/2, dy, NULL, NULL, 0, GIZMO_NORMAL); + + // Line edit line, Cancel + GBGizmoAdd(lpft->m_FormulaBar.m_hWnd, GIZMOTYPE_BUTTONCOMMAND, uPos++, IDM_L_EDITLINE, dx, dy, NULL, lpft->m_hBmp, IDB_EDITLINE, GIZMO_NORMAL); + GBGizmoAdd(lpft->m_FormulaBar.m_hWnd, GIZMOTYPE_BUTTONCOMMAND, uPos++, IDM_FB_CANCEL, dx, dy, NULL, lpft->m_hBmp, IDB_CANCEL, GIZMO_NORMAL); + + // separator + GBGizmoAdd(lpft->m_FormulaBar.m_hWnd, GIZMOTYPE_SEPARATOR, uPos++, 0, dx/2, dy, NULL, NULL, 0, GIZMO_NORMAL); + + // Edit control for line input + GBGizmoAdd(lpft->m_FormulaBar.m_hWnd, GIZMOTYPE_EDIT, uPos++, IDM_FB_EDIT, dx*10, lpft->m_tdd.cyBar-5, NULL, NULL, 0, GIZMO_NORMAL); + + + SendMessage(lpft->m_FormulaBar.m_hWnd, WM_SETREDRAW, TRUE, 0L); + + // Limit the text lenght of edit control + GBGizmoSendMessage(lpft->m_FormulaBar.m_hWnd, IDM_FB_EDIT, EM_LIMITTEXT, + (WPARAM)MAXSTRLEN, 0L); + + //Set the GizmoBar's associate to be this client window + GBHwndAssociateSet(lpft->m_ButtonBar.m_hWnd, hWndParent); + + //Set the FormulaBar's associate to be this client window + GBHwndAssociateSet(lpft->m_FormulaBar.m_hWnd, hWndParent); + + return TRUE; +} + + +void FrameTools_AttachToFrame(LPFRAMETOOLS lpft, HWND hWndFrame) +{ + if (! lpft) + return; + + if (hWndFrame == NULL) + hWndFrame = OutlineApp_GetFrameWindow((LPOUTLINEAPP)g_lpApp); + + if (lpft->m_hWndApp == hWndFrame) + return; // already have this parent frame + + lpft->m_hWndApp = hWndFrame; + + /* parent the tool bars to the frame so we can safely + ** destroy/recreate the palette window. + */ + SetParent(lpft->m_ButtonBar.m_hWnd, hWndFrame); + SetParent(lpft->m_FormulaBar.m_hWnd, hWndFrame); + + // recreate popup palette so that it is owned by the hWndFrame + FrameTools_CreatePopupPalette(lpft, hWndFrame); + + // restore the correct parent for the tool bars + FrameTools_BB_SetState(lpft, lpft->m_ButtonBar.m_nState); + FrameTools_FB_SetState(lpft, lpft->m_FormulaBar.m_nState); +} + + +void FrameTools_AssociateDoc(LPFRAMETOOLS lpft, LPOUTLINEDOC lpOutlineDoc) +{ + HWND hWnd = OutlineDoc_GetWindow(lpOutlineDoc); + + if (! lpft) + return; + + // if no Doc is given, then associate with the App's frame window. + if (lpOutlineDoc) + hWnd = OutlineDoc_GetWindow(lpOutlineDoc); + else + hWnd = OutlineApp_GetWindow((LPOUTLINEAPP)g_lpApp); + + //Set the GizmoBar's associate to be this client window + GBHwndAssociateSet(lpft->m_ButtonBar.m_hWnd, hWnd); + + //Set the FormulaBar's associate to be this client window + GBHwndAssociateSet(lpft->m_FormulaBar.m_hWnd, hWnd); +} + + +/* + * FrameTools_Destroy + * + * Purpose: + * Destroy the toolbar + * + * Parameters: + * lpft FrameTools object + * + * Return Value: + * nil + */ +void FrameTools_Destroy(LPFRAMETOOLS lpft) +{ + if (!lpft) + return; + + if (IsWindow(lpft->m_ButtonBar.m_hWnd)) + DestroyWindow(lpft->m_ButtonBar.m_hWnd); + if (IsWindow(lpft->m_FormulaBar.m_hWnd)) + DestroyWindow(lpft->m_FormulaBar.m_hWnd); + if (IsWindow(lpft->m_hWndPopupPalette)) + DestroyWindow(lpft->m_hWndPopupPalette); + + if (lpft->m_hBmp) + DeleteObject(lpft->m_hBmp); +} + + +/* + * FrameTools_Move + * + * Purpose: + * Move and resize the toolbar + * + * Parameters: + * lpft FrameTools object + * lprc Pointer to client rectangle + * + * Return Value: + * nil + */ +void FrameTools_Move(LPFRAMETOOLS lpft, LPRECT lprcClient) +{ + RECT rcPopup; + LPRECT lprcPopup = (LPRECT)&rcPopup; + int nCmdShow = SW_HIDE; + + if (!lpft || lpft->m_fToolsDisabled) + return; + + lprcPopup->left = 0; + lprcPopup->top = 0; + lprcPopup->right = lpft->m_uPopupWidth; + lprcPopup->bottom = lpft->m_ButtonBar.m_uHeight + + lpft->m_FormulaBar.m_uHeight; + + switch (lpft->m_ButtonBar.m_nState) { + case BARSTATE_HIDE: + case BARSTATE_POPUP: + case BARSTATE_TOP: + Bar_Move(&lpft->m_ButtonBar, lprcClient, lprcPopup); + Bar_Move(&lpft->m_FormulaBar, lprcClient, lprcPopup); + break; + + case BARSTATE_BOTTOM: + Bar_Move(&lpft->m_FormulaBar, lprcClient, lprcPopup); + Bar_Move(&lpft->m_ButtonBar, lprcClient, lprcPopup); + break; + } + + if (lprcPopup->top) { + SetWindowPos(lpft->m_hWndPopupPalette, NULL, 0, 0, lprcPopup->right, + lprcPopup->top + GetSystemMetrics(SM_CYCAPTION), + SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_SHOWWINDOW); + } + else + ShowWindow(lpft->m_hWndPopupPalette, SW_HIDE); + + FB_ResizeEdit(&lpft->m_FormulaBar); + + InvalidateRect(lpft->m_ButtonBar.m_hWnd, NULL, TRUE); + InvalidateRect(lpft->m_FormulaBar.m_hWnd, NULL, TRUE); +} + + +/* + * FrameTools_PopupTools + * + * Purpose: + * Put both formula bar and button bar in Popup Window. + * + * Parameters: + * lpft FrameTools object + * + * Return Value: + * nil + */ +void FrameTools_PopupTools(LPFRAMETOOLS lpft) +{ + if (! lpft) + return; + + FrameTools_BB_SetState(lpft, BARSTATE_POPUP); + FrameTools_FB_SetState(lpft, BARSTATE_POPUP); + FrameTools_Move(lpft, NULL); +} + + +/* + * FrameTools_Enable + * + * Purpose: + * Enable/Disable(hide) all the tools of the toolbar. + * this will hide both the buttonbar and the + * formulabar independent of whether they are floating or anchored. + * + * Parameters: + * lpft FrameTools object + * fEnable + * + * Return Value: + * nil + */ +void FrameTools_Enable(LPFRAMETOOLS lpft, BOOL fEnable) +{ + lpft->m_fToolsDisabled = !fEnable; + if (lpft->m_fToolsDisabled) { + ShowWindow(lpft->m_hWndPopupPalette, SW_HIDE); + ShowWindow(lpft->m_ButtonBar.m_hWnd, SW_HIDE); + ShowWindow(lpft->m_FormulaBar.m_hWnd, SW_HIDE); + } +} + + +/* + * FrameTools_EnableWindow + * + * Purpose: + * EnableWindow for all the tools of the toolbar. + * this enables/disables mouse and keyboard input to the tools. + * while a modal dialog is up, it is inportant to disable the + * floating tool windows. + * this will NOT hide any windows; it will only call EnableWindow. + * + * Parameters: + * lpft FrameTools object + * fEnable + * + * Return Value: + * nil + */ +void FrameTools_EnableWindow(LPFRAMETOOLS lpft, BOOL fEnable) +{ + EnableWindow(lpft->m_hWndPopupPalette, fEnable); + EnableWindow(lpft->m_ButtonBar.m_hWnd, fEnable); + EnableWindow(lpft->m_FormulaBar.m_hWnd, fEnable); +} + + +#if defined( INPLACE_CNTR ) || defined( INPLACE_SVR ) + +/* + * FrameTools_NegotiateForSpaceAndShow + * + * Purpose: + * Negotiate for space for the toolbar tools with the given frame window. + * and make them visible. + * Negotiation steps: + * 1. try to get enough space at top/bottom of window + * 2. float the tools as a palette if space not available + * + * Parameters: + * lpft FrameTools object + * + * Return Value: + * none + */ +void FrameTools_NegotiateForSpaceAndShow( + LPFRAMETOOLS lpft, + LPRECT lprcFrameRect, + LPOLEINPLACEFRAME lpTopIPFrame +) +{ + BORDERWIDTHS borderwidths; + RECT rectBorder; + HRESULT hrErr; + + if (lprcFrameRect) + rectBorder = *lprcFrameRect; + else { + /* OLE2NOTE: by calling GetBorder, the server can find out the + ** size of the frame window. it can use this information to + ** make decisions about how to orient/organize it tools (eg. + ** if window is taller than wide put tools vertically at + ** left edge). + */ + OLEDBG_BEGIN2("IOleInPlaceFrame::GetBorder called\r\n") + hrErr = lpTopIPFrame->lpVtbl->GetBorder( + lpTopIPFrame, + (LPRECT)&rectBorder + ); + OLEDBG_END2 + } + + /* Try SetBorderSpace() with the space that you need. If it fails then + ** you can negotiate for space and then do the SetBorderSpace(). + */ + FrameTools_GetRequiredBorderSpace(lpft,(LPBORDERWIDTHS)&borderwidths); + OLEDBG_BEGIN2("IOleInPlaceFrame::SetBorderSpace called\r\n") + hrErr = lpTopIPFrame->lpVtbl->SetBorderSpace( + lpTopIPFrame, + (LPCBORDERWIDTHS)&borderwidths + ); + OLEDBG_END2 + +#if defined( LATER ) + if (hrErr != NOERROR) { + /* Frame did not give the toolsspace that we want. So negotiate */ + + // REVIEW: try a different placement of the tools here + + OLEDBG_BEGIN2("IOleInPlaceFrame::RequestBorderSpace called\r\n") + hrErr = lpTopIPFrame->lpVtbl->RequestBorderSpace( + lpTopIPFrame, + (LPCBORDERWIDTHS)&borderwidths + ); + OLEDBG_END2 + + if (hrErr == NOERROR) { + OLEDBG_BEGIN2("IOleInPlaceFrame::SetBorderSpace called\r\n") + hrErr = lpTopIPFrame->lpVtbl->SetBorderSpace( + lpTopIPFrame, + (LPCBORDERWIDTHS)&borderwidths + ); + OLEDBG_END2 + } + } +#endif + + if (hrErr == NOERROR) { + FrameTools_Move(lpft, (LPRECT)&rectBorder); // we got what we wanted + } else { + /* We did not get tool space, so POP them up. + /* OLE2NOTE: since we are poping up our tools, we MUST inform + ** the top in-place frame window that we need NO tool space + ** BUT that it should NOT put its own tools up. if we were + ** to pass NULL instead of (0,0,0,0), then the container + ** would have the option to leave its own tools up. + */ + OLEDBG_BEGIN2("IOleInPlaceFrame::SetBorderSpace(NULL) called\r\n") + hrErr = lpTopIPFrame->lpVtbl->SetBorderSpace( + lpTopIPFrame, + (LPCBORDERWIDTHS)&g_rectNull + ); + OLEDBG_END2 + FrameTools_PopupTools(lpft); + } +} + +#endif // INPLACE_CNTR || INPLACE_SVR + + +/* + * FrameTools_GetRequiredBorderSpace + * + * Purpose: + * Calculate the desired space for the toolbar tools. + * + * Parameters: + * lpft FrameTools object + * lpBorderWidths Widths required at top,bottom,left,right + * + * Return Value: + * nil + */ +void FrameTools_GetRequiredBorderSpace(LPFRAMETOOLS lpft, LPBORDERWIDTHS lpBorderWidths) +{ + *lpBorderWidths = g_rectNull; + + switch (lpft->m_ButtonBar.m_nState) { + case BARSTATE_TOP: + lpBorderWidths->top += lpft->m_ButtonBar.m_uHeight; + break; + + case BARSTATE_BOTTOM: + lpBorderWidths->bottom += lpft->m_ButtonBar.m_uHeight; + break; + } + + switch (lpft->m_FormulaBar.m_nState) { + case BARSTATE_TOP: + lpBorderWidths->top += lpft->m_FormulaBar.m_uHeight; + break; + + case BARSTATE_BOTTOM: + lpBorderWidths->bottom += lpft->m_FormulaBar.m_uHeight; + break; + } +} + + + +/* + * FrameTools_UpdateButtons + * + * Purpose: + * Enable/disable individual buttons of the toolbar according to the + * state of the app + * + * Parameters: + * lpft FrameTools object + * + * Return Value: + * nil + */ +void FrameTools_UpdateButtons(LPFRAMETOOLS lpft, LPOUTLINEDOC lpOutlineDoc) +{ + BOOL fEnable; + +#if defined( OLE_VERSION ) + LPDATAOBJECT lpClipboardDataObj; + HRESULT hrErr; + LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; + BOOL fPrevEnable1; + BOOL fPrevEnable2; +#endif + + if (!lpft) + return; + +#if defined( INPLACE_CNTR ) + { + LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOutlineDoc; + if (lpContainerDoc->m_lpLastUIActiveLine && + lpContainerDoc->m_lpLastUIActiveLine->m_fUIActive) { + + /* if there is a UIActive object, then we should disable + ** all of our "active editor" commands. we should enable + ** only those commands that are "workspace" commands. + */ + if (lpft->m_FormulaBar.m_nState != BARSTATE_HIDE) { + + GBGizmoEnable(lpft->m_FormulaBar.m_hWnd,IDM_L_EDITLINE,FALSE); + GBGizmoEnable(lpft->m_FormulaBar.m_hWnd,IDM_L_ADDLINE,FALSE); + GBGizmoEnable(lpft->m_FormulaBar.m_hWnd,IDM_FB_CANCEL,FALSE); + GBGizmoEnable(lpft->m_FormulaBar.m_hWnd,IDM_L_EDITLINE,FALSE); + } + + if (lpft->m_ButtonBar.m_nState != BARSTATE_HIDE) + { + GBGizmoEnable(lpft->m_ButtonBar.m_hWnd, IDM_E_CUT, FALSE); + GBGizmoEnable(lpft->m_ButtonBar.m_hWnd, IDM_E_COPY, FALSE); + GBGizmoEnable(lpft->m_ButtonBar.m_hWnd, IDM_E_PASTE, FALSE); + GBGizmoEnable(lpft->m_ButtonBar.m_hWnd,IDM_L_INDENTLINE,FALSE); + GBGizmoEnable(lpft->m_ButtonBar.m_hWnd, IDM_L_UNINDENTLINE, FALSE); + GBGizmoEnable(lpft->m_ButtonBar.m_hWnd, IDM_H_ABOUT, FALSE); + GBGizmoEnable(lpft->m_ButtonBar.m_hWnd, IDM_FB_EDIT, FALSE); + GBGizmoEnable(lpft->m_ButtonBar.m_hWnd, IDM_F_NEW, TRUE); + GBGizmoEnable(lpft->m_ButtonBar.m_hWnd, IDM_F_OPEN, TRUE); + GBGizmoEnable(lpft->m_ButtonBar.m_hWnd, IDM_F_SAVE, TRUE); + } + return; + } + } +#endif // INPLACE_CNTR + + fEnable = (BOOL)OutlineDoc_GetLineCount(lpOutlineDoc); + + if (lpft->m_FormulaBar.m_nState != BARSTATE_HIDE) { + + GBGizmoEnable(lpft->m_FormulaBar.m_hWnd, IDM_L_EDITLINE, fEnable); + + if (! lpft->m_fInFormulaBar) { + GBGizmoEnable(lpft->m_FormulaBar.m_hWnd, IDM_L_ADDLINE, FALSE); + GBGizmoEnable(lpft->m_FormulaBar.m_hWnd, IDM_FB_CANCEL, FALSE); + GBGizmoEnable(lpft->m_FormulaBar.m_hWnd, IDM_L_EDITLINE, FALSE); + if (!fEnable) { + GBGizmoTextSet(lpft->m_FormulaBar.m_hWnd, IDM_FB_EDIT, ""); + } + } else { + GBGizmoEnable(lpft->m_FormulaBar.m_hWnd, IDM_L_ADDLINE, TRUE); + GBGizmoEnable(lpft->m_FormulaBar.m_hWnd, IDM_FB_CANCEL, TRUE); + } + } + + if (lpft->m_ButtonBar.m_nState != BARSTATE_HIDE) + { + GBGizmoEnable(lpft->m_ButtonBar.m_hWnd, IDM_E_CUT, fEnable); + GBGizmoEnable(lpft->m_ButtonBar.m_hWnd, IDM_E_COPY, fEnable); + GBGizmoEnable(lpft->m_ButtonBar.m_hWnd, IDM_L_INDENTLINE, fEnable); + GBGizmoEnable(lpft->m_ButtonBar.m_hWnd, IDM_L_UNINDENTLINE, fEnable); + +#if defined( OLE_SERVER ) + + { + LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOutlineDoc; + +#if defined( INPLACE_SVR ) + fEnable = ((lpServerDoc->m_fUIActive) ? FALSE : TRUE); +#else + fEnable = (lpOutlineDoc->m_docInitType != DOCTYPE_EMBEDDED); +#endif // INPLACE_SVR + + GBGizmoEnable(lpft->m_ButtonBar.m_hWnd, IDM_F_NEW, fEnable); + GBGizmoEnable(lpft->m_ButtonBar.m_hWnd, IDM_F_OPEN, fEnable); + GBGizmoEnable(lpft->m_ButtonBar.m_hWnd, IDM_F_SAVE, fEnable); + } + +#endif // OLE_SERVER + +#if defined( OLE_VERSION ) + + /* OLE2NOTE: we do not want to ever give the busy dialog when we + ** are trying to enable or disable our tool bar buttons eg. + ** even if the source of data on the clipboard is busy, we do + ** not want put up the busy dialog. thus we will disable the + ** dialog and at the end re-enable it. + */ + OleApp_DisableBusyDialogs(lpOleApp, &fPrevEnable1, &fPrevEnable2); + + /* OLE2NOTE: perform OLE specific menu initialization. + ** the OLE versions use the OleGetClipboard mechanism for + ** clipboard handling. thus, they determine if the Paste + ** command should be enabled in an OLE specific manner. + */ + fEnable = FALSE; + hrErr = OleGetClipboard((LPDATAOBJECT FAR*)&lpClipboardDataObj); + + if (hrErr == NOERROR) { + int nFmtEtc; + + nFmtEtc = OleStdGetPriorityClipboardFormat( + lpClipboardDataObj, + lpOleApp->m_arrPasteEntries, + lpOleApp->m_nPasteEntries + ); + + fEnable = (nFmtEtc >= 0); // there IS a format we like + + OleStdRelease((LPUNKNOWN)lpClipboardDataObj); + } + + // re-enable the busy dialog + OleApp_EnableBusyDialogs(lpOleApp, fPrevEnable1, fPrevEnable2); + + GBGizmoEnable(lpft->m_ButtonBar.m_hWnd, IDM_E_PASTE, fEnable); + +#else + + // Base Outline version uses standard Windows clipboard handling + if(IsClipboardFormatAvailable(g_lpApp->m_cfOutline) || + IsClipboardFormatAvailable(CF_TEXT)) + GBGizmoEnable(lpft->m_ButtonBar.m_hWnd, IDM_E_PASTE, TRUE); + else + GBGizmoEnable(lpft->m_ButtonBar.m_hWnd, IDM_E_PASTE, FALSE); + +#endif // OLE_VERSION + + } +} + +/* + * FrameTools_FB_SetEditText + * + * Purpose: + * Set text in the edit control in FormulaBar + * + * Parameters: + * lpft FrameTools object + * lpsz pointer to string to be set + * + * Return Value: + * nil + */ +void FrameTools_FB_SetEditText(LPFRAMETOOLS lpft, LPSTR lpsz) +{ + GBGizmoTextSet(lpft->m_FormulaBar.m_hWnd, IDM_FB_EDIT, lpsz); +} + + +/* + * FrameTools_FB_GetEditText + * + * Purpose: + * Get text from the edit control in FormulaBar + * + * Parameters: + * lpft FrameTools object + * lpsz pointer to buffer to receive the text + * cch buffer size + * + * Return Value: + * nil + */ +void FrameTools_FB_GetEditText(LPFRAMETOOLS lpft, LPSTR lpsz, UINT cch) +{ + GBGizmoTextGet(lpft->m_FormulaBar.m_hWnd, IDM_FB_EDIT, lpsz, cch); +} + + +/* + * FrameTools_FB_FocusEdit + * + * Purpose: + * Set the focus in the edit control of FormulaBar + * + * Parameters: + * lpft FrameTools object + * + * Return Value: + * nil + */ +void FrameTools_FB_FocusEdit(LPFRAMETOOLS lpft) +{ + GBGizmoFocusSet(lpft->m_FormulaBar.m_hWnd, IDM_FB_EDIT); + + // select the whole text in the edit control + GBGizmoSendMessage(lpft->m_FormulaBar.m_hWnd, IDM_FB_EDIT, EM_SETSEL, + (WPARAM)TRUE, MAKELPARAM(0, -1)); +} + + +/* + * FrameTools_FB_SendMessage + * + * Purpose: + * Send a message to the FormulaBar window gizmo + * + * Parameters: + * lpft FrameTools object + * uID gizmo ID + * msg + * wParam + * lParam + * + * Return Value: + * nil + */ +void FrameTools_FB_SendMessage(LPFRAMETOOLS lpft, UINT uID, UINT msg, WPARAM wParam, LPARAM lParam) +{ + GBGizmoSendMessage(lpft->m_FormulaBar.m_hWnd, uID, msg, wParam, lParam); +} + + +/* + * FrameTools_FB_ForceRedraw + * + * Purpose: + * Force the toolbar to draw itself + * + * Parameters: + * lpft FrameTools object + * + * Return Value: + * nil + */ +void FrameTools_ForceRedraw(LPFRAMETOOLS lpft) +{ + InvalidateRect(lpft->m_ButtonBar.m_hWnd, NULL, TRUE); + InvalidateRect(lpft->m_FormulaBar.m_hWnd, NULL, TRUE); + InvalidateRect(lpft->m_hWndPopupPalette, NULL, TRUE); +} + + +/* + * FrameTools_BB_SetState + * + * Purpose: + * Set display state of ButtonBar + * + * Parameters: + * lpft FrameTools object + * nState new display state + * + * Return Value: + * nil + */ +void FrameTools_BB_SetState(LPFRAMETOOLS lpft, int nState) +{ + if (!lpft) { + return; + } + + lpft->m_ButtonBar.m_nState = nState; + + if (nState == BARSTATE_POPUP) + SetParent(lpft->m_ButtonBar.m_hWnd, lpft->m_hWndPopupPalette); + else + SetParent(lpft->m_ButtonBar.m_hWnd, lpft->m_hWndApp); +} + + +/* + * FrameTools_BB_GetState + * + * Purpose: + * Get display state of ButtonBar + * + * Parameters: + * lpft FrameTools object + * + * Return Value: + * nState current display state + */ +int FrameTools_BB_GetState(LPFRAMETOOLS lpft) +{ + return lpft->m_ButtonBar.m_nState; +} + + +/* + * FrameTools_FB_SetState + * + * Purpose: + * Set display state of FormulaBar + * + * Parameters: + * lpft FrameTools object + * nState new display state + * + * Return Value: +4 * nil + */ +void FrameTools_FB_SetState(LPFRAMETOOLS lpft, int nState) +{ + if (!lpft) { + return; + } + + lpft->m_FormulaBar.m_nState = nState; + + if (nState == BARSTATE_POPUP) + SetParent(lpft->m_FormulaBar.m_hWnd, lpft->m_hWndPopupPalette); + +#if defined( INPLACE_SVR ) + /* OLE2NOTE: it is dangerous for an in-place server to hide its + ** toolbar window and leave it parented to the hWndFrame of the + ** in-place container. if the in-place container call + ** ShowOwnedPopups, then it could inadvertantly be made visible. + ** to avoid this we will parent the toolbar window back to our + ** own application main window. if we are not in-place active + ** then this is the same as lpft->m_hWndApp. + */ + else if (nState == BARSTATE_HIDE) + SetParent(lpft->m_FormulaBar.m_hWnd, g_lpApp->m_hWndApp); +#endif + + else + SetParent(lpft->m_FormulaBar.m_hWnd, lpft->m_hWndApp); +} + + +/* + * FrameTools_FB_GetState + * + * Purpose: + * Get display state of FormulaBar + * + * Parameters: + * lpft FrameTools object + * + * Return Value: + * nState current display state + */ +int FrameTools_FB_GetState(LPFRAMETOOLS lpft) +{ + return lpft->m_FormulaBar.m_nState; +} + + +/* + * FrameToolsWndProc + * + * Purpose: + * WndProc for toolbar window + * + * Parameters: + * hWnd + * Message + * wParam + * lParam + * + * Return Value: + * message dependent + */ +LRESULT FAR PASCAL FrameToolsWndProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam) +{ + LPFRAMETOOLS lpft = (LPFRAMETOOLS)GetWindowLong(hWnd, 0); + + switch (Message) { + + case WM_MOUSEACTIVATE: + return MA_NOACTIVATE; + + default: + return DefWindowProc(hWnd, Message, wParam, lParam); + } + + return 0L; +} + + +/* + * Bar_Move + * + * Purpose: + * Resize and reposition a bar + * + * Parameters: + * lpbar Bar object + * lprcClient pointer to Client rect + * lprcPopup pointer to Popup rect + * + * Return Value: + * nil + */ +static void Bar_Move(LPBAR lpbar, LPRECT lprcClient, LPRECT lprcPopup) +{ + if (lpbar->m_nState == BARSTATE_HIDE) { + ShowWindow(lpbar->m_hWnd, SW_HIDE); + } + else { + ShowWindow(lpbar->m_hWnd, SW_SHOW); + switch (lpbar->m_nState) { + case BARSTATE_POPUP: + MoveWindow(lpbar->m_hWnd, lprcPopup->left, lprcPopup->top, + lprcPopup->right - lprcPopup->left, lpbar->m_uHeight, + TRUE); + lprcPopup->top += lpbar->m_uHeight; + break; + + case BARSTATE_TOP: + MoveWindow(lpbar->m_hWnd, lprcClient->left, lprcClient->top, + lprcClient->right - lprcClient->left, + lpbar->m_uHeight, TRUE); + lprcClient->top += lpbar->m_uHeight; + break; + + case BARSTATE_BOTTOM: + MoveWindow(lpbar->m_hWnd, lprcClient->left, + lprcClient->bottom - lpbar->m_uHeight, + lprcClient->right - lprcClient->left, + lpbar->m_uHeight, TRUE); + lprcClient->bottom -= lpbar->m_uHeight; + break; + } + } +} + + +/* + * FB_ResizeEdit + * + * Purpose: + * Resize the edit control in FormulaBar + * + * Parameters: + * lpft Bar object + * + * Return Value: + * nil + */ +static void FB_ResizeEdit(LPBAR lpbar) +{ + RECT rcClient; + RECT rcEdit; + HWND hwndEdit; + + GetClientRect(lpbar->m_hWnd, (LPRECT)&rcClient); + hwndEdit = GetDlgItem(lpbar->m_hWnd, IDM_FB_EDIT); + GetWindowRect(hwndEdit, (LPRECT)&rcEdit); + ScreenToClient(lpbar->m_hWnd, (LPPOINT)&rcEdit.left); + ScreenToClient(lpbar->m_hWnd, (LPPOINT)&rcEdit.right); + + SetWindowPos(hwndEdit, NULL, 0, 0, rcClient.right - rcEdit.left - SPACE, + rcEdit.bottom - rcEdit.top, SWP_NOMOVE | SWP_NOZORDER); +} diff --git a/private/oleutest/letest/outline/frametls.h b/private/oleutest/letest/outline/frametls.h new file mode 100644 index 000000000..c235c5567 --- /dev/null +++ b/private/oleutest/letest/outline/frametls.h @@ -0,0 +1,102 @@ +/************************************************************************* +** +** OLE 2 Sample Code +** +** frametls.h +** +** This file contains file contains data structure defintions, +** function prototypes, constants, etc. used by the frame level +** tools used by the Outline series of sample applications. The +** frame level tools include a formula bar and a button bar (toolbar) +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + +#if !defined( _FRAMETLS_H_ ) +#define _FRAMETLS_H_ + +#ifndef RC_INVOKED +#pragma message ("INCLUDING FRAMETLS.H from " __FILE__) +#endif /* RC_INVOKED */ + +#include "bttncur.h" +#include "gizmobar.h" + +#define SPACE 5 +#define POPUPSTUB_HEIGHT 5 + + +/* forward type references */ +typedef struct tagOUTLINEDOC FAR* LPOUTLINEDOC; + +#define IDC_GIZMOBAR 1000 +#define IDC_FORMULABAR 1001 + +#define IDB_CANCEL 0 +#define IDB_EDITLINE 1 +#define IDB_ADDLINE 2 +#define IDB_UNINDENTLINE 3 +#define IDB_INDENTLINE 4 + +#define BARSTATE_TOP 1 +#define BARSTATE_BOTTOM 2 +#define BARSTATE_POPUP 3 +#define BARSTATE_HIDE 4 + +#define CLASS_PALETTE "Tool Palette" + +typedef struct tagBAR{ + UINT m_uHeight; + HWND m_hWnd; + int m_nState; +} BAR, FAR* LPBAR; + +typedef struct tagFRAMETOOLS { + HWND m_hWndPopupPalette; // Popup Tool Palette window + HWND m_hWndApp; // App Frame window + UINT m_uPopupWidth; // Width of the popup palette + HBITMAP m_hBmp; // Image bitmaps + BOOL m_fInFormulaBar; // does formula bar have edit focus + BOOL m_fToolsDisabled; // when TRUE all tools are hidden + + BAR m_ButtonBar; // Button Bar + BAR m_FormulaBar; // Formula Bar + + TOOLDISPLAYDATA m_tdd; // from UIToolConfigureForDisplay +} FRAMETOOLS, FAR* LPFRAMETOOLS; + + +BOOL FrameToolsRegisterClass(HINSTANCE hInst); +BOOL FrameTools_Init(LPFRAMETOOLS lpft, HWND hWndParent, HINSTANCE hInst); +void FrameTools_AttachToFrame(LPFRAMETOOLS lpft, HWND hWndFrame); +void FrameTools_AssociateDoc(LPFRAMETOOLS lpft, LPOUTLINEDOC lpOutlineDoc); +void FrameTools_Destroy(LPFRAMETOOLS lpft); +void FrameTools_Move(LPFRAMETOOLS lpft, LPRECT lprcClient); +void FrameTools_PopupTools(LPFRAMETOOLS lpft); +void FrameTools_Enable(LPFRAMETOOLS lpft, BOOL fEnable); +void FrameTools_EnableWindow(LPFRAMETOOLS lpft, BOOL fEnable); + +#if defined( INPLACE_CNTR ) || defined( INPLACE_SVR ) +void FrameTools_NegotiateForSpaceAndShow( + LPFRAMETOOLS lpft, + LPRECT lprcFrameRect, + LPOLEINPLACEFRAME lpTopIPFrame +); +#endif // INPLACE_CNTR || INPLACE_SVR + +void FrameTools_GetRequiredBorderSpace(LPFRAMETOOLS lpft, LPBORDERWIDTHS lpBorderWidths); + +void FrameTools_UpdateButtons(LPFRAMETOOLS lpft, LPOUTLINEDOC lpOutlineDoc); +void FrameTools_FB_SetEditText(LPFRAMETOOLS lpft, LPSTR lpsz); +void FrameTools_FB_GetEditText(LPFRAMETOOLS lpft, LPSTR lpsz, UINT cch); +void FrameTools_FB_FocusEdit(LPFRAMETOOLS lpft); +void FrameTools_FB_SendMessage(LPFRAMETOOLS lpft, UINT uID, UINT msg, WPARAM wParam, LPARAM lParam); +void FrameTools_ForceRedraw(LPFRAMETOOLS lpft); +void FrameTools_BB_SetState(LPFRAMETOOLS lpft, int nState); +void FrameTools_FB_SetState(LPFRAMETOOLS lpft, int nState); +int FrameTools_BB_GetState(LPFRAMETOOLS lpft); +int FrameTools_FB_GetState(LPFRAMETOOLS lpft); +LRESULT FAR PASCAL FrameToolsWndProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam); + +#endif // _FRAMETLS_H_ diff --git a/private/oleutest/letest/outline/heading.c b/private/oleutest/letest/outline/heading.c new file mode 100644 index 000000000..d8cefde58 --- /dev/null +++ b/private/oleutest/letest/outline/heading.c @@ -0,0 +1,451 @@ +/************************************************************************* +** +** OLE 2 Sample Code +** +** heading.c +** +** This file contains functions and support for OutlineDoc's row and +** column headings. +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + +#include "outline.h" + +extern LPOUTLINEAPP g_lpApp; + + +BOOL Heading_Create(LPHEADING lphead, HWND hWndParent, HINSTANCE hInst) +{ + HDC hDC; + TEXTMETRIC tm; + + if (!lphead || !hWndParent || !hInst) + return FALSE; + + hDC = GetDC(hWndParent); + if (!hDC) + return FALSE; + + if (!GetTextMetrics(hDC, (TEXTMETRIC FAR*)&tm)) + return FALSE; + lphead->m_colhead.m_uHeight = tm.tmHeight; + lphead->m_rowhead.m_uWidth = 4 * tm.tmAveCharWidth; + lphead->m_fShow = TRUE; + + ReleaseDC(hWndParent, hDC); + + lphead->m_hfont = CreateFont( + tm.tmHeight, + 0,0,0,0,0,0,0,0, + OUT_TT_PRECIS, // use TrueType + CLIP_DEFAULT_PRECIS, + DEFAULT_QUALITY, + DEFAULT_PITCH | FF_DONTCARE, + HEADING_FONT + ); + + if (!lphead->m_hfont) + return FALSE; + + lphead->m_colhead.m_hWnd = CreateWindow( + "listbox", + "Column Heading", + WS_VISIBLE | WS_CHILD | WS_DISABLED | LBS_OWNERDRAWVARIABLE | + LBS_NOINTEGRALHEIGHT, + 0,0,0,0, // any values + hWndParent, + (HMENU)IDC_COLHEADING, + hInst, + NULL); + + if (!lphead->m_colhead.m_hWnd) + return FALSE; + + // add a dummy line to get WM_DRAWITEM message + SendMessage(lphead->m_colhead.m_hWnd, LB_ADDSTRING, 0, + MAKELPARAM(lphead->m_colhead.m_uHeight,0)); + + lphead->m_rowhead.m_hWnd = CreateWindow( + "listbox", + "Row Heading", + WS_VISIBLE | WS_CHILD | WS_DISABLED | LBS_OWNERDRAWVARIABLE, + 0,0,0,0, // any values + hWndParent, + (HMENU)IDC_ROWHEADING, + hInst, + NULL); + + if (!lphead->m_rowhead.m_hWnd) + return FALSE; + + SendMessage(lphead->m_rowhead.m_hWnd, LB_ADDSTRING, 0, + MAKELPARAM(lphead->m_colhead.m_uHeight,0)); + + lphead->m_rowhead.m_WndProc = + (FARPROC) GetWindowLong(lphead->m_rowhead.m_hWnd, GWL_WNDPROC ); + SetWindowLong(lphead->m_rowhead.m_hWnd, GWL_WNDPROC, + (LONG) RowHeadWndProc); + + lphead->m_hwndButton = CreateWindow( + "button", + NULL, + WS_VISIBLE | WS_CHILD, + 0,0,0,0, // any values + hWndParent, + (HMENU)IDC_BUTTON, + hInst, + NULL); + + if (!lphead->m_hwndButton) + return FALSE; + + return TRUE; +} + + +void Heading_Destroy(LPHEADING lphead) +{ + if (!lphead) + return; + + if (IsWindow(lphead->m_colhead.m_hWnd)) { + DestroyWindow(lphead->m_colhead.m_hWnd); + lphead->m_colhead.m_hWnd = NULL; + } + if (IsWindow(lphead->m_rowhead.m_hWnd)) { + DestroyWindow(lphead->m_rowhead.m_hWnd); + lphead->m_rowhead.m_hWnd = NULL; + } + if (IsWindow(lphead->m_hwndButton)) { + DestroyWindow(lphead->m_hwndButton); + lphead->m_hwndButton = NULL; + } +#ifdef WIN32 + if (GetObjectType(lphead->m_hfont)) { +#else + if (IsGDIObject(lphead->m_hfont)) { +#endif + DeleteObject(lphead->m_hfont); + lphead->m_hfont = NULL; + } + +} + + +void Heading_Move(LPHEADING lphead, HWND hwndDoc, LPSCALEFACTOR lpscale) +{ + int nOffsetX; + int nOffsetY; + RECT rcDoc; + + if (!lphead || !hwndDoc || !lpscale) + return; + + if (!lphead->m_fShow) + return; + + nOffsetX = (int) Heading_RH_GetWidth(lphead, lpscale); + nOffsetY = (int) Heading_CH_GetHeight(lphead, lpscale); + GetClientRect(hwndDoc, (LPRECT)&rcDoc); + + MoveWindow(lphead->m_hwndButton, 0, 0, nOffsetX, nOffsetY, TRUE); + + MoveWindow( + lphead->m_colhead.m_hWnd, + nOffsetX, 0, + rcDoc.right-rcDoc.left-nOffsetX, nOffsetY, + TRUE + ); + + MoveWindow(lphead->m_rowhead.m_hWnd, 0, nOffsetY, nOffsetX, + rcDoc.bottom-rcDoc.top-nOffsetY, TRUE); +} + + +void Heading_Show(LPHEADING lphead, BOOL fShow) +{ + int nCmdShow; + + if (!lphead) + return; + + lphead->m_fShow = fShow; + nCmdShow = fShow ? SW_SHOW : SW_HIDE; + + ShowWindow(lphead->m_hwndButton, nCmdShow); + ShowWindow(lphead->m_colhead.m_hWnd, nCmdShow); + ShowWindow(lphead->m_rowhead.m_hWnd, nCmdShow); +} + + +void Heading_ReScale(LPHEADING lphead, LPSCALEFACTOR lpscale) +{ + UINT uHeight; + + if (!lphead || !lpscale) + return; + + // Row heading is scaled with the LineList_Rescale. So, only + // Column heading needed to be scaled here. + uHeight = (UINT)(lphead->m_colhead.m_uHeight * lpscale->dwSyN / + lpscale->dwSyD); + SendMessage(lphead->m_colhead.m_hWnd, LB_SETITEMHEIGHT, 0, + MAKELPARAM(uHeight, 0)); +} + + +void Heading_CH_Draw(LPHEADING lphead, LPDRAWITEMSTRUCT lpdis, LPRECT lprcScreen, LPRECT lprcObject) +{ + HPEN hpenOld; + HPEN hpen; + HBRUSH hbr; + HFONT hfOld; + int nTabInPix; + char letter; + int i; + int nOldMapMode; + RECT rcWindowOld; + RECT rcViewportOld; + POINT point; + + if (!lpdis || !lphead) + return; + + hbr = GetStockObject(LTGRAY_BRUSH); + FillRect(lpdis->hDC, (LPRECT)&lpdis->rcItem, hbr); + + nOldMapMode = SetDCToAnisotropic(lpdis->hDC, lprcScreen, lprcObject, + (LPRECT)&rcWindowOld, (LPRECT)&rcViewportOld); + + hfOld = SelectObject(lpdis->hDC, lphead->m_hfont); + hpen = GetStockObject(BLACK_PEN); + hpenOld = SelectObject(lpdis->hDC, hpen); + + nTabInPix = XformWidthInHimetricToPixels(lpdis->hDC, TABWIDTH); + SetBkMode(lpdis->hDC, TRANSPARENT); + + letter = COLUMN_LETTER; + MoveToEx(lpdis->hDC, lprcObject->left, lprcObject->bottom,&point); + LineTo(lpdis->hDC, lprcObject->left, lprcObject->top); + + for (i = 0; i < COLUMN; i++) { + lprcObject->right = lprcObject->left + nTabInPix; + DrawText(lpdis->hDC, (LPCSTR)&letter, 1, lprcObject, + DT_SINGLELINE | DT_CENTER | DT_VCENTER); + MoveToEx(lpdis->hDC, lprcObject->right, lprcObject->bottom, &point); + LineTo(lpdis->hDC, lprcObject->right, lprcObject->top); + + letter++; + lprcObject->left += nTabInPix; + } + + SelectObject(lpdis->hDC, hpenOld); + SelectObject(lpdis->hDC, hfOld); + + ResetOrigDC(lpdis->hDC, nOldMapMode, (LPRECT)&rcWindowOld, + (LPRECT)&rcViewportOld); +} + + +void Heading_CH_SetHorizontalExtent(LPHEADING lphead, HWND hwndListBox) +{ + RECT rcLL; + RECT rcCH; + int nLLWidth; + int nCHWidth; + int nHorizExtent; + + if (!lphead || !hwndListBox) + return; + + nHorizExtent=(int)SendMessage(hwndListBox, LB_GETHORIZONTALEXTENT, 0, 0L); + GetClientRect(hwndListBox, (LPRECT)&rcLL); + GetClientRect(lphead->m_colhead.m_hWnd, (LPRECT)&rcCH); + + nLLWidth = rcLL.right - rcLL.left; + nCHWidth = rcCH.right - rcCH.left; + nHorizExtent += nCHWidth - nLLWidth; + + SendMessage(lphead->m_colhead.m_hWnd, LB_SETHORIZONTALEXTENT, + nHorizExtent, 0L); +} + + +UINT Heading_CH_GetHeight(LPHEADING lphead, LPSCALEFACTOR lpscale) +{ + if (!lphead || !lpscale) + return 0; + + if (lphead->m_fShow) + return (UINT)(lphead->m_colhead.m_uHeight * lpscale->dwSyN / + lpscale->dwSyD); + else + return 0; +} + + +LRESULT Heading_CH_SendMessage(LPHEADING lphead, UINT msg, WPARAM wParam, LPARAM lParam) +{ + if (!lphead) + return 0; + + if (lphead->m_colhead.m_hWnd) + return SendMessage(lphead->m_colhead.m_hWnd, msg, wParam, lParam); +} + + +void Heading_CH_ForceRedraw(LPHEADING lphead, BOOL fErase) +{ + if (!lphead) + return; + + InvalidateRect(lphead->m_colhead.m_hWnd, NULL, fErase); +} + +void Heading_RH_ForceRedraw(LPHEADING lphead, BOOL fErase) +{ + if (!lphead) + return; + + InvalidateRect(lphead->m_rowhead.m_hWnd, NULL, fErase); +} + +void Heading_RH_Draw(LPHEADING lphead, LPDRAWITEMSTRUCT lpdis) +{ + char cBuf[5]; + HPEN hpenOld; + HPEN hpen; + HBRUSH hbrOld; + HBRUSH hbr; + HFONT hfOld; + RECT rc; + RECT rcWindowOld; + RECT rcViewportOld; + int nMapModeOld; + + if (!lpdis || !lphead) + return; + + lpdis->rcItem; + + rc.left = 0; + rc.bottom = 0; + rc.top = (int)lpdis->itemData; + rc.right = lphead->m_rowhead.m_uWidth; + + nMapModeOld = SetDCToAnisotropic(lpdis->hDC, &lpdis->rcItem, &rc, + (LPRECT)&rcWindowOld, (LPRECT)&rcViewportOld); + + hpen = GetStockObject(BLACK_PEN); + hpenOld = SelectObject(lpdis->hDC, hpen); + hbr = GetStockObject(LTGRAY_BRUSH); + hbrOld = SelectObject(lpdis->hDC, hbr); + + Rectangle(lpdis->hDC, rc.left, rc.top, rc.right, + rc.bottom); + + hfOld = SelectObject(lpdis->hDC, lphead->m_hfont); + + SetBkMode(lpdis->hDC, TRANSPARENT); + + wsprintf(cBuf, "%d", lpdis->itemID + 1); + + DrawText(lpdis->hDC, (LPSTR)cBuf, lstrlen(cBuf), (LPRECT)&rc, + DT_SINGLELINE | DT_CENTER | DT_VCENTER); + + SelectObject(lpdis->hDC, hfOld); + + SelectObject(lpdis->hDC, hpenOld); + SelectObject(lpdis->hDC, hbrOld); + + ResetOrigDC(lpdis->hDC, nMapModeOld, (LPRECT)&rcWindowOld, + (LPRECT)&rcViewportOld); +} + +LRESULT Heading_RH_SendMessage(LPHEADING lphead, UINT msg, WPARAM wParam, LPARAM lParam) +{ + if (!lphead) + return 0; + + if (lphead->m_rowhead.m_hWnd) + return SendMessage(lphead->m_rowhead.m_hWnd, msg, wParam, lParam); +} + + +UINT Heading_RH_GetWidth(LPHEADING lphead, LPSCALEFACTOR lpscale) +{ + if (!lphead || !lpscale) + return 0; + + if (lphead->m_fShow) + return (UINT)(lphead->m_rowhead.m_uWidth * lpscale->dwSxN / + lpscale->dwSxD); + else + return 0; +} + + +void Heading_RH_Scroll(LPHEADING lphead, HWND hwndListBox) +{ + int nTopLL; + int nTopRH; + + if (!lphead || !hwndListBox) + return; + + nTopLL = (int)SendMessage(hwndListBox, LB_GETTOPINDEX, 0, 0L); + nTopRH = (int)SendMessage( + lphead->m_rowhead.m_hWnd, LB_GETTOPINDEX, 0, 0L); + + if (nTopLL != nTopRH) + SendMessage( + lphead->m_rowhead.m_hWnd,LB_SETTOPINDEX,(WPARAM)nTopLL,0L); +} + + +LRESULT FAR PASCAL RowHeadWndProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam) +{ + HWND hwndParent = GetParent (hWnd); + LPOUTLINEDOC lpDoc = (LPOUTLINEDOC)GetWindowLong(hwndParent, 0); + LPHEADING lphead = OutlineDoc_GetHeading(lpDoc); + + switch (Message) { + case WM_PAINT: + { + LPLINELIST lpLL = OutlineDoc_GetLineList(lpDoc); + PAINTSTRUCT ps; + + // If there is no line in listbox, trap the message and draw the + // background gray. Without this, the background will be painted + // as default color. + if (!LineList_GetCount(lpLL)) { + BeginPaint(hWnd, &ps); + EndPaint(hWnd, &ps); + return 0; + } + + break; + } + + case WM_ERASEBKGND: + { + HDC hDC = (HDC)wParam; + RECT rc; + + GetClientRect(hWnd, (LPRECT)&rc); + FillRect(hDC, (LPRECT)&rc, GetStockObject(GRAY_BRUSH)); + + return 1; + } + } + + return CallWindowProc( + (WNDPROC)lphead->m_rowhead.m_WndProc, + hWnd, + Message, + wParam, + lParam + ); +} diff --git a/private/oleutest/letest/outline/heading.h b/private/oleutest/letest/outline/heading.h new file mode 100644 index 000000000..b88f5ccff --- /dev/null +++ b/private/oleutest/letest/outline/heading.h @@ -0,0 +1,59 @@ +/************************************************************************* +** +** OLE 2 Sample Code +** +** heading.c +** +** This file contains definitions used by OutlineDoc's row and +** column headings. +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + +#define COLUMN 10 + +#define IDC_ROWHEADING 2000 +#define IDC_COLHEADING 2001 +#define IDC_BUTTON 2002 + +#define HEADING_FONT "Arial" + +#define COLUMN_LETTER 'A' + + +typedef struct tagCOLHEADING { + HWND m_hWnd; + UINT m_uHeight; +} COLHEADING, FAR* LPCOLHEADING; + +typedef struct tagROWHEADING { + HWND m_hWnd; + UINT m_uWidth; + FARPROC m_WndProc; +} ROWHEADING, FAR* LPROWHEADING; + +typedef struct tagHEADING { + COLHEADING m_colhead; + ROWHEADING m_rowhead; + HWND m_hwndButton; + BOOL m_fShow; + HFONT m_hfont; +} HEADING, FAR* LPHEADING; + +BOOL Heading_Create(LPHEADING lphead, HWND hWndParent, HINSTANCE hInst); +void Heading_Destroy(LPHEADING lphead); +void Heading_Move(LPHEADING lphead, HWND hwndListBox, LPSCALEFACTOR lpscale); +void Heading_Show(LPHEADING lphead, BOOL fShow); +void Heading_ReScale(LPHEADING lphead, LPSCALEFACTOR lpscale); +void Heading_CH_Draw(LPHEADING lphead, LPDRAWITEMSTRUCT lpdis, LPRECT lprcScreen, LPRECT lprcObject); +void Heading_CH_SetHorizontalExtent(LPHEADING lphead, HWND hwndListBox); +UINT Heading_CH_GetHeight(LPHEADING lphead, LPSCALEFACTOR lpscale); +LRESULT Heading_CH_SendMessage(LPHEADING lphead, UINT msg, WPARAM wParam, LPARAM lParam); +void Heading_CH_ForceRedraw(LPHEADING lphead, BOOL fErase); +void Heading_RH_ForceRedraw(LPHEADING lphead, BOOL fErase); +void Heading_RH_Draw(LPHEADING lphead, LPDRAWITEMSTRUCT lpdis); +LRESULT Heading_RH_SendMessage(LPHEADING lphead, UINT msg, WPARAM wParam, LPARAM lParam); +UINT Heading_RH_GetWidth(LPHEADING lphead, LPSCALEFACTOR lpscale); +void Heading_RH_Scroll(LPHEADING lphead, HWND hwndListBox); +LRESULT FAR PASCAL RowHeadWndProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam); diff --git a/private/oleutest/letest/outline/icntrotl.ico b/private/oleutest/letest/outline/icntrotl.ico new file mode 100644 index 000000000..7bd2931c5 Binary files /dev/null and b/private/oleutest/letest/outline/icntrotl.ico differ diff --git a/private/oleutest/letest/outline/icntrotl/daytona/makefile b/private/oleutest/letest/outline/icntrotl/daytona/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/oleutest/letest/outline/icntrotl/daytona/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/oleutest/letest/outline/icntrotl/daytona/makefile.inc b/private/oleutest/letest/outline/icntrotl/daytona/makefile.inc new file mode 100644 index 000000000..462f38133 --- /dev/null +++ b/private/oleutest/letest/outline/icntrotl/daytona/makefile.inc @@ -0,0 +1,2 @@ +copyfiles: + xcopy ..\..\*.c . /D diff --git a/private/oleutest/letest/outline/icntrotl/daytona/sources b/private/oleutest/letest/outline/icntrotl/daytona/sources new file mode 100644 index 000000000..c80247671 --- /dev/null +++ b/private/oleutest/letest/outline/icntrotl/daytona/sources @@ -0,0 +1,108 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + Kenneth MacLeod (Kennethm) 9-Mar-1994 + +!ENDIF + +MAJORCOMP = oleutest +MINORCOMP = letest + +# +# This is the name of the target built from the source files specified +# below. The name should include neither the path nor the file extension. +# + +TARGETNAME= icntrotl + +# +# This specifies where the target is to be built. A private target of +# type LIBRARY or DYNLINK should go to obj, whereas a public target of +# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib. +# + +TARGETPATH= obj + +# +# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY, +# etc. +# + +TARGETTYPE= PROGRAM + +INCLUDES= ..\..\..\ole2ui; \ + ..\..\..\bttncur; \ + ..\..\..\gizmobar; \ + ..\..\..\..\inc; \ + ..\.. + +C_DEFINES= \ + $(C_DEFINES) \ + -DFLAT \ + -DWIN32=100 \ + -D_NT1X_=100 \ + -DNOEXCEPTIONS \ + -DOLE_CNTR \ + -DINPLACE_CNTR + +SOURCES= \ + ..\icntrotl.rc \ + classfac.c \ + clipbrd.c \ + cntrbase.c \ + cntrinpl.c \ + cntrline.c \ + debug.c \ + debug2.c \ + dialogs.c \ + dragdrop.c \ + frametls.c \ + heading.c \ + linking.c \ + main.c \ + memmgr.c \ + oleapp.c \ + oledoc.c \ + outlapp.c \ + outldoc.c \ + outlline.c \ + outllist.c \ + outlname.c \ + outlntbl.c \ + outltxtl.c \ + status.c \ + tests.c + +UMTYPE= windows +UMENTRY= winmain + +USE_CRTDLL=1 +TARGETLIBS= \ + ..\..\..\ole2ui\daytona\obj\*\ole2u32a.lib \ + ..\..\..\gizmobar\daytona\obj\*\gizmobar.lib \ + ..\..\..\bttncur\daytona\obj\*\bttncur.lib \ + $(BASEDIR)\public\sdk\lib\*\ole32.lib \ + $(BASEDIR)\public\sdk\lib\*\shell32.lib \ + $(BASEDIR)\public\sdk\lib\*\gdi32.lib \ + $(BASEDIR)\public\sdk\lib\*\kernel32.lib \ + $(BASEDIR)\public\sdk\lib\*\user32.lib \ + $(BASEDIR)\public\sdk\lib\*\advapi32.lib \ + $(BASEDIR)\public\sdk\lib\*\comdlg32.lib \ + $(BASEDIR)\public\sdk\lib\*\uuid.lib + +NTTARGETFILE0=copyfiles diff --git a/private/oleutest/letest/outline/icntrotl/dirs b/private/oleutest/letest/outline/icntrotl/dirs new file mode 100644 index 000000000..515c134a8 --- /dev/null +++ b/private/oleutest/letest/outline/icntrotl/dirs @@ -0,0 +1,37 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + dirs. + +Abstract: + + This file specifies the subdirectories of the current directory that + contain component makefiles. + + +Author: + + Donna Liu (DonnaLi) 19-Dec-1993 + +!ENDIF + +# +# This is a list of all subdirectories that build required components. +# Each subdirectory name should appear on a line by itself. The build +# follows the order in which the subdirectories are specified. +# + +DIRS= + +# +# This is a list of all subdirectories that build optional components. +# Each subdirectory name should appear on a line by itself. The build +# follows the order in which the subdirectories are specified. +# + +OPTIONAL_DIRS= \ + \ + daytona diff --git a/private/oleutest/letest/outline/icntrotl/icntrotl.rc b/private/oleutest/letest/outline/icntrotl/icntrotl.rc new file mode 100644 index 000000000..160d51dfa --- /dev/null +++ b/private/oleutest/letest/outline/icntrotl/icntrotl.rc @@ -0,0 +1,210 @@ +/************************************************************************* +** +** OLE 2.0 Container Sample Code +** +** icntrotl.rc +** +** Resource file for icntrotl.exe +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + +#include "windows.h" +#include "outlrc.h" +#include "cntrrc.h" + +SelCur CURSOR selcross.cur +DragMoveCur CURSOR dragmove.cur + +#if defined( IF_SPECIAL_DD_CURSORS_NEEDED ) +DragNoneCur CURSOR dragnone.cur +DragCopyCur CURSOR dragcopy.cur +DragLinkCur CURSOR draglink.cur +#endif // IF_SPECIAL_DD_CURSORS_NEEDED + +CntrOutlMenu MENU + BEGIN + POPUP "&File" + BEGIN + MENUITEM "&New", IDM_F_NEW + MENUITEM "&Open...\t Ctrl+F12", IDM_F_OPEN + MENUITEM "&Save\t Shift+F12", IDM_F_SAVE + MENUITEM "Save &As...\t F12", IDM_F_SAVEAS + MENUITEM SEPARATOR + MENUITEM "&Print...\t Ctrl+Shift+F12", IDM_F_PRINT + MENUITEM "Printer Se&tup...", IDM_F_PRINTERSETUP + MENUITEM SEPARATOR + MENUITEM "E&xit\t Alt+F4", IDM_F_EXIT + END + POPUP "&Edit" + BEGIN + MENUITEM "&Undo", IDM_E_UNDO + MENUITEM SEPARATOR + MENUITEM "Cu&t\t Ctrl+X", IDM_E_CUT + MENUITEM "&Copy\t Ctrl+C", IDM_E_COPY + MENUITEM "&Paste\t Ctrl+V", IDM_E_PASTE + MENUITEM "Paste &Special...", IDM_E_PASTESPECIAL + MENUITEM "Paste &Link", IDM_E_PASTELINK + MENUITEM "Cl&ear\t Del", IDM_E_CLEAR + MENUITEM SEPARATOR + MENUITEM "&Insert Object...", IDM_E_INSERTOBJECT + MENUITEM "Li&nks...", IDM_E_EDITLINKS + MENUITEM "&Object", IDM_E_OBJECTVERBMIN + MENUITEM SEPARATOR + MENUITEM "Select &All\t Ctrl+A", IDM_E_SELECTALL + END + POPUP "O&utline" + BEGIN + POPUP "&Zoom" + BEGIN + MENUITEM "&100%\t Ctrl+1", IDM_V_ZOOM_100 + MENUITEM "&75%\t Ctrl+2", IDM_V_ZOOM_75 + MENUITEM "&50%\t Ctrl+3", IDM_V_ZOOM_50 + MENUITEM "&25%\t Ctrl+4", IDM_V_ZOOM_25 + END + POPUP "&Left and Right margins" + BEGIN + MENUITEM "&nil", IDM_V_SETMARGIN_0 + MENUITEM "&1 cm", IDM_V_SETMARGIN_1 + MENUITEM "&2 cm", IDM_V_SETMARGIN_2 + MENUITEM "&3 cm", IDM_V_SETMARGIN_3 + MENUITEM "&4 cm", IDM_V_SETMARGIN_4 + END + POPUP "Add &Top Line" + BEGIN + MENUITEM "&1 cm", IDM_V_ADDTOP_1 + MENUITEM "&2 cm", IDM_V_ADDTOP_2 + MENUITEM "&3 cm", IDM_V_ADDTOP_3 + MENUITEM "&4 cm", IDM_V_ADDTOP_4 + END + END + POPUP "&Line" + BEGIN + MENUITEM "&Add Line\t Enter", IDM_L_ADDLINE + MENUITEM "E&dit Line\t Alt+Enter", IDM_L_EDITLINE + MENUITEM SEPARATOR + MENUITEM "&Indent Line\t Tab", IDM_L_INDENTLINE + MENUITEM "U&nindent Line\t Shift+Tab", IDM_L_UNINDENTLINE + MENUITEM SEPARATOR + MENUITEM "&Set Line Height...", IDM_L_SETLINEHEIGHT + END + POPUP "&Name" + BEGIN + MENUITEM "&Define Name...", IDM_N_DEFINENAME + MENUITEM "&Goto Name...", IDM_N_GOTONAME + END + POPUP "&Options" + BEGIN + POPUP "&Button Bar Display" + BEGIN + MENUITEM "At &Top", IDM_O_BB_TOP + MENUITEM "At &Bottom", IDM_O_BB_BOTTOM + MENUITEM "&Popup", IDM_O_BB_POPUP + MENUITEM "&Hide", IDM_O_BB_HIDE + END + POPUP "&Formula Bar Display" + BEGIN + MENUITEM "At &Top", IDM_O_FB_TOP + MENUITEM "At &Bottom", IDM_O_FB_BOTTOM + MENUITEM "&Popup", IDM_O_FB_POPUP + END + POPUP "&Row and Column Heading" + BEGIN + MENUITEM "&Show", IDM_O_HEAD_SHOW + MENUITEM "&Hide", IDM_O_HEAD_HIDE + END + MENUITEM "&Show Object", IDM_O_SHOWOBJECT + END + POPUP "DbgI&Cntr" + BEGIN + MENUITEM "&Debug Level...", IDM_D_DEBUGLEVEL + MENUITEM "Register Message &Filter", IDM_D_INSTALLMSGFILTER + MENUITEM "&Reject Incoming Messages", IDM_D_REJECTINCOMING + MENUITEM "&Inside-out Activation", IDM_D_INSIDEOUT + END + POPUP "&Help" + BEGIN + MENUITEM "&About...", IDM_H_ABOUT + END + END + +CntrOutlAccel ACCELERATORS + BEGIN + VK_F12, IDM_F_OPEN, VIRTKEY, CONTROL + VK_F12, IDM_F_SAVE, VIRTKEY, SHIFT + VK_F12, IDM_F_SAVEAS, VIRTKEY + VK_F12, IDM_F_PRINT, VIRTKEY, CONTROL, SHIFT + + "x", IDM_E_CUT, VIRTKEY, CONTROL + "c", IDM_E_COPY, VIRTKEY, CONTROL + "v", IDM_E_PASTE, VIRTKEY, CONTROL + VK_DELETE, IDM_E_CLEAR, VIRTKEY + VK_RETURN, IDM_L_ADDLINE, VIRTKEY + VK_RETURN, IDM_L_EDITLINE, VIRTKEY, ALT + VK_TAB, IDM_L_INDENTLINE, VIRTKEY + VK_TAB, IDM_L_UNINDENTLINE, VIRTKEY, SHIFT + "a", IDM_E_SELECTALL, VIRTKEY, CONTROL + + ; old conventions for editing + VK_INSERT, IDM_E_COPY, VIRTKEY, CONTROL + VK_DELETE, IDM_E_CUT, VIRTKEY, SHIFT + VK_INSERT, IDM_E_PASTE, VIRTKEY, SHIFT + + VK_F2, IDM_F2, VIRTKEY + VK_ESCAPE, IDM_ESCAPE, VIRTKEY + + "1", IDM_V_ZOOM_100, VIRTKEY, CONTROL + "2", IDM_V_ZOOM_75, VIRTKEY, CONTROL + "3", IDM_V_ZOOM_50, VIRTKEY, CONTROL + "4", IDM_V_ZOOM_25, VIRTKEY, CONTROL + END + +; Same as CntrOutlAccel but without Delete and Backspace +; used when edit control of Formula Bar in focus +; +CntrOutlAccelFocusEdit ACCELERATORS + BEGIN + VK_F12, IDM_F_OPEN, VIRTKEY, CONTROL + VK_F12, IDM_F_SAVE, VIRTKEY, SHIFT + VK_F12, IDM_F_SAVEAS, VIRTKEY + VK_F12, IDM_F_PRINT, VIRTKEY, CONTROL, SHIFT + + "x", IDM_E_CUT, VIRTKEY, CONTROL + "c", IDM_E_COPY, VIRTKEY, CONTROL + "v", IDM_E_PASTE, VIRTKEY, CONTROL + VK_RETURN, IDM_L_ADDLINE, VIRTKEY + VK_RETURN, IDM_L_EDITLINE, VIRTKEY, ALT + VK_TAB, IDM_L_INDENTLINE, VIRTKEY + VK_TAB, IDM_L_UNINDENTLINE, VIRTKEY, SHIFT + "a", IDM_E_SELECTALL, VIRTKEY, CONTROL + + VK_ESCAPE, IDM_ESCAPE, VIRTKEY + + ; old conventions for editing + VK_INSERT, IDM_E_COPY, VIRTKEY, CONTROL + VK_DELETE, IDM_E_CUT, VIRTKEY, SHIFT + VK_INSERT, IDM_E_PASTE, VIRTKEY, SHIFT + END + +InPlaceCntrOutlAccel ACCELERATORS + BEGIN + VK_F12, IDM_F_OPEN, VIRTKEY, CONTROL + VK_F12, IDM_F_SAVE, VIRTKEY, SHIFT + VK_F12, IDM_F_SAVEAS, VIRTKEY + VK_F12, IDM_F_PRINT, VIRTKEY, CONTROL, SHIFT + VK_ESCAPE, IDM_ESCAPE, VIRTKEY + "1", IDM_V_ZOOM_100, VIRTKEY, CONTROL + "2", IDM_V_ZOOM_75, VIRTKEY, CONTROL + "3", IDM_V_ZOOM_50, VIRTKEY, CONTROL + "4", IDM_V_ZOOM_25, VIRTKEY, CONTROL + END + +CntrOutlIcon ICON icntrotl.ico + +Image72 BITMAP image72.bmp +Image96 BITMAP image96.bmp +Image120 BITMAP image120.bmp +LogoBitmap BITMAP ole2.bmp + +#include "DIALOGS.DLG" diff --git a/private/oleutest/letest/outline/image120.bmp b/private/oleutest/letest/outline/image120.bmp new file mode 100644 index 000000000..663f5234c Binary files /dev/null and b/private/oleutest/letest/outline/image120.bmp differ diff --git a/private/oleutest/letest/outline/image72.bmp b/private/oleutest/letest/outline/image72.bmp new file mode 100644 index 000000000..dd096bb2c Binary files /dev/null and b/private/oleutest/letest/outline/image72.bmp differ diff --git a/private/oleutest/letest/outline/image96.bmp b/private/oleutest/letest/outline/image96.bmp new file mode 100644 index 000000000..34af2948e Binary files /dev/null and b/private/oleutest/letest/outline/image96.bmp differ diff --git a/private/oleutest/letest/outline/install.bat b/private/oleutest/letest/outline/install.bat new file mode 100644 index 000000000..c06d27747 --- /dev/null +++ b/private/oleutest/letest/outline/install.bat @@ -0,0 +1,7 @@ +if "%OLEROOT%" == "" set OLEROOT=c:\ntole2 +copy cntroutl\cntroutl.exe %OLEROOT%\release\bin +copy svroutl\svroutl.exe %OLEROOT%\release\bin +copy icntrotl\icntrotl.exe %OLEROOT%\release\bin +copy isvrotl\isvrotl.exe %OLEROOT%\release\bin +@REM copy outline\outline.exe %OLEROOT%\release\bin +copy outline.reg %OLEROOT%\release\bin diff --git a/private/oleutest/letest/outline/isvrotl.ico b/private/oleutest/letest/outline/isvrotl.ico new file mode 100644 index 000000000..406bab9d8 Binary files /dev/null and b/private/oleutest/letest/outline/isvrotl.ico differ diff --git a/private/oleutest/letest/outline/isvrotl/daytona/makefile b/private/oleutest/letest/outline/isvrotl/daytona/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/oleutest/letest/outline/isvrotl/daytona/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/oleutest/letest/outline/isvrotl/daytona/makefile.inc b/private/oleutest/letest/outline/isvrotl/daytona/makefile.inc new file mode 100644 index 000000000..462f38133 --- /dev/null +++ b/private/oleutest/letest/outline/isvrotl/daytona/makefile.inc @@ -0,0 +1,2 @@ +copyfiles: + xcopy ..\..\*.c . /D diff --git a/private/oleutest/letest/outline/isvrotl/daytona/sources b/private/oleutest/letest/outline/isvrotl/daytona/sources new file mode 100644 index 000000000..d07604c50 --- /dev/null +++ b/private/oleutest/letest/outline/isvrotl/daytona/sources @@ -0,0 +1,108 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + Kenneth MacLeod (Kennethm) 9-Mar-1994 + +!ENDIF + +MAJORCOMP = oleutest +MINORCOMP = letest + +# +# This is the name of the target built from the source files specified +# below. The name should include neither the path nor the file extension. +# + +TARGETNAME= isvrotl + +# +# This specifies where the target is to be built. A private target of +# type LIBRARY or DYNLINK should go to obj, whereas a public target of +# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib. +# + +TARGETPATH= obj + +# +# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY, +# etc. +# + +TARGETTYPE= PROGRAM + +INCLUDES= ..\..\..\ole2ui; \ + ..\..\..\bttncur; \ + ..\..\..\gizmobar; \ + ..\..\..\..\inc; \ + ..\.. + +C_DEFINES= \ + $(C_DEFINES) \ + -DFLAT \ + -DWIN32=100 \ + -D_NT1X_=100 \ + -DNOEXCEPTIONS \ + -DOLE_SERVER \ + -DINPLACE_SVR + +SOURCES= \ + ..\isvrotl.rc \ + classfac.c \ + clipbrd.c \ + debug.c \ + debug2.c \ + dialogs.c \ + dragdrop.c \ + frametls.c \ + heading.c \ + linking.c \ + main.c \ + memmgr.c \ + oleapp.c \ + oledoc.c \ + outlapp.c \ + outldoc.c \ + outlline.c \ + outllist.c \ + outlname.c \ + outlntbl.c \ + outltxtl.c \ + svrbase.c \ + svrinpl.c \ + svrpsobj.c \ + status.c \ + tests.c + +UMTYPE= windows +UMENTRY= winmain + +USE_CRTDLL=1 +TARGETLIBS= \ + ..\..\..\ole2ui\daytona\obj\*\ole2u32a.lib \ + ..\..\..\gizmobar\daytona\obj\*\gizmobar.lib \ + ..\..\..\bttncur\daytona\obj\*\bttncur.lib \ + $(BASEDIR)\public\sdk\lib\*\ole32.lib \ + $(BASEDIR)\public\sdk\lib\*\shell32.lib \ + $(BASEDIR)\public\sdk\lib\*\gdi32.lib \ + $(BASEDIR)\public\sdk\lib\*\kernel32.lib \ + $(BASEDIR)\public\sdk\lib\*\user32.lib \ + $(BASEDIR)\public\sdk\lib\*\advapi32.lib \ + $(BASEDIR)\public\sdk\lib\*\comdlg32.lib \ + $(BASEDIR)\public\sdk\lib\*\uuid.lib + +NTTARGETFILE0=copyfiles diff --git a/private/oleutest/letest/outline/isvrotl/dirs b/private/oleutest/letest/outline/isvrotl/dirs new file mode 100644 index 000000000..515c134a8 --- /dev/null +++ b/private/oleutest/letest/outline/isvrotl/dirs @@ -0,0 +1,37 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + dirs. + +Abstract: + + This file specifies the subdirectories of the current directory that + contain component makefiles. + + +Author: + + Donna Liu (DonnaLi) 19-Dec-1993 + +!ENDIF + +# +# This is a list of all subdirectories that build required components. +# Each subdirectory name should appear on a line by itself. The build +# follows the order in which the subdirectories are specified. +# + +DIRS= + +# +# This is a list of all subdirectories that build optional components. +# Each subdirectory name should appear on a line by itself. The build +# follows the order in which the subdirectories are specified. +# + +OPTIONAL_DIRS= \ + \ + daytona diff --git a/private/oleutest/letest/outline/isvrotl/isvrotl.rc b/private/oleutest/letest/outline/isvrotl/isvrotl.rc new file mode 100644 index 000000000..2334521ec --- /dev/null +++ b/private/oleutest/letest/outline/isvrotl/isvrotl.rc @@ -0,0 +1,211 @@ +/************************************************************************* +** +** OLE 2.0 Server Sample Code +** +** isvrotl.rc +** +** Resource file for isvrotl.exe +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + +#include "windows.h" +#include "outlrc.h" + +SelCur CURSOR selcross.cur +DragMoveCur CURSOR dragmove.cur + +#if defined( IF_SPECIAL_DD_CURSORS_NEEDED ) +DragNoneCur CURSOR dragnone.cur +DragCopyCur CURSOR dragcopy.cur +DragLinkCur CURSOR draglink.cur +#endif // IF_SPECIAL_DD_CURSORS_NEEDED + +SvrOutlMenu MENU + BEGIN + POPUP "&File" + BEGIN + MENUITEM "&New", IDM_F_NEW + MENUITEM "&Open...\t Ctrl+F12", IDM_F_OPEN + MENUITEM "&Save\t Shift+F12", IDM_F_SAVE + MENUITEM "Save &As...\t F12", IDM_F_SAVEAS + MENUITEM SEPARATOR + MENUITEM "&Print...\t Ctrl+Shift+F12", IDM_F_PRINT + MENUITEM "Printer Se&tup...", IDM_F_PRINTERSETUP + MENUITEM SEPARATOR + MENUITEM "E&xit\t Alt+F4", IDM_F_EXIT + END + POPUP "&Edit" + BEGIN + MENUITEM "&Undo", IDM_E_UNDO + MENUITEM SEPARATOR + MENUITEM "Cu&t\t Ctrl+X", IDM_E_CUT + MENUITEM "&Copy\t Ctrl+C", IDM_E_COPY + MENUITEM "&Paste\t Ctrl+V", IDM_E_PASTE + MENUITEM "Paste &Special...", IDM_E_PASTESPECIAL + MENUITEM "Cl&ear\t Del", IDM_E_CLEAR + MENUITEM SEPARATOR + MENUITEM "Select A&ll\t Ctrl+A", IDM_E_SELECTALL + END + POPUP "O&utline" + BEGIN + POPUP "&Zoom" + BEGIN + MENUITEM "&400%", IDM_V_ZOOM_400 + MENUITEM "&300%", IDM_V_ZOOM_300 + MENUITEM "&200%", IDM_V_ZOOM_200 + MENUITEM "&100%", IDM_V_ZOOM_100 + MENUITEM "&75%", IDM_V_ZOOM_75 + MENUITEM "&50%", IDM_V_ZOOM_50 + MENUITEM "&25%", IDM_V_ZOOM_25 + END + POPUP "&Left and Right margins" + BEGIN + MENUITEM "&nil", IDM_V_SETMARGIN_0 + MENUITEM "&1 cm", IDM_V_SETMARGIN_1 + MENUITEM "&2 cm", IDM_V_SETMARGIN_2 + MENUITEM "&3 cm", IDM_V_SETMARGIN_3 + MENUITEM "&4 cm", IDM_V_SETMARGIN_4 + END + POPUP "Add &Top Line" + BEGIN + MENUITEM "&1 cm", IDM_V_ADDTOP_1 + MENUITEM "&2 cm", IDM_V_ADDTOP_2 + MENUITEM "&3 cm", IDM_V_ADDTOP_3 + MENUITEM "&4 cm", IDM_V_ADDTOP_4 + END + END + POPUP "&Line" + BEGIN + MENUITEM "&Add Line\t Enter", IDM_L_ADDLINE + MENUITEM "E&dit Line\t Alt+Enter", IDM_L_EDITLINE + MENUITEM SEPARATOR + MENUITEM "&Indent Line\t Tab", IDM_L_INDENTLINE + MENUITEM "U&nindent Line\t Shift+Tab", IDM_L_UNINDENTLINE + MENUITEM SEPARATOR + MENUITEM "&Set Line Height...", IDM_L_SETLINEHEIGHT + END + POPUP "&Name" + BEGIN + MENUITEM "&Define Name...", IDM_N_DEFINENAME + MENUITEM "&Goto Name...", IDM_N_GOTONAME + END + POPUP "&Options" + BEGIN + POPUP "&Button Bar Display" + BEGIN + MENUITEM "At &Top", IDM_O_BB_TOP + MENUITEM "At &Bottom", IDM_O_BB_BOTTOM + MENUITEM "&Popup", IDM_O_BB_POPUP + MENUITEM "&Hide", IDM_O_BB_HIDE + END + POPUP "&Formula Bar Display" + BEGIN + MENUITEM "At &Top", IDM_O_FB_TOP + MENUITEM "At &Bottom", IDM_O_FB_BOTTOM + MENUITEM "&Popup", IDM_O_FB_POPUP + END + POPUP "&Row and Column Heading" + BEGIN + MENUITEM "&Show", IDM_O_HEAD_SHOW + MENUITEM "&Hide", IDM_O_HEAD_HIDE + END + END + POPUP "DbgI&Svr" + BEGIN + MENUITEM "&Debug Level...", IDM_D_DEBUGLEVEL + MENUITEM "Register Message &Filter", IDM_D_INSTALLMSGFILTER + MENUITEM "&Reject Incoming Messages", IDM_D_REJECTINCOMING + END + POPUP "&Help" + BEGIN + MENUITEM "&About...", IDM_H_ABOUT + END + END + +SvrOutlAccel ACCELERATORS + BEGIN + VK_F12, IDM_F_OPEN, VIRTKEY, CONTROL + VK_F12, IDM_F_SAVE, VIRTKEY, SHIFT + VK_F12, IDM_F_SAVEAS, VIRTKEY + VK_F12, IDM_F_PRINT, VIRTKEY, CONTROL, SHIFT + + "x", IDM_E_CUT, VIRTKEY, CONTROL + "c", IDM_E_COPY, VIRTKEY, CONTROL + "v", IDM_E_PASTE, VIRTKEY, CONTROL + VK_DELETE, IDM_E_CLEAR, VIRTKEY + VK_RETURN, IDM_L_ADDLINE, VIRTKEY + VK_RETURN, IDM_L_EDITLINE, VIRTKEY, ALT + VK_TAB, IDM_L_INDENTLINE, VIRTKEY + VK_TAB, IDM_L_UNINDENTLINE, VIRTKEY, SHIFT + "a", IDM_E_SELECTALL, VIRTKEY, CONTROL + + ; old conventions for editing + VK_INSERT, IDM_E_COPY, VIRTKEY, CONTROL + VK_DELETE, IDM_E_CUT, VIRTKEY, SHIFT + VK_INSERT, IDM_E_PASTE, VIRTKEY, SHIFT + + VK_F2, IDM_F2, VIRTKEY + END + +; used when edit control of Formula Bar in focus +; +SvrOutlAccelFocusEdit ACCELERATORS + BEGIN + VK_F12, IDM_F_OPEN, VIRTKEY, CONTROL + VK_F12, IDM_F_SAVE, VIRTKEY, SHIFT + VK_F12, IDM_F_SAVEAS, VIRTKEY + VK_F12, IDM_F_PRINT, VIRTKEY, CONTROL, SHIFT + + VK_RETURN, IDM_L_ADDLINE, VIRTKEY + VK_RETURN, IDM_L_EDITLINE, VIRTKEY, ALT + + VK_ESCAPE, IDM_ESCAPE, VIRTKEY + END + + +InPlaceSvrOutlAccel ACCELERATORS + BEGIN + "x", IDM_E_CUT, VIRTKEY, CONTROL + "c", IDM_E_COPY, VIRTKEY, CONTROL + "v", IDM_E_PASTE, VIRTKEY, CONTROL + VK_DELETE, IDM_E_CLEAR, VIRTKEY + VK_RETURN, IDM_L_ADDLINE, VIRTKEY + VK_RETURN, IDM_L_EDITLINE, VIRTKEY, ALT + VK_TAB, IDM_L_INDENTLINE, VIRTKEY + VK_TAB, IDM_L_UNINDENTLINE, VIRTKEY, SHIFT + "a", IDM_E_SELECTALL, VIRTKEY, CONTROL + + ; old conventions for editing + VK_INSERT, IDM_E_COPY, VIRTKEY, CONTROL + VK_DELETE, IDM_E_CUT, VIRTKEY, SHIFT + VK_INSERT, IDM_E_PASTE, VIRTKEY, SHIFT + + VK_F2, IDM_F2, VIRTKEY + VK_ESCAPE, IDM_ESCAPE, VIRTKEY + END + +; used when edit control of Formula Bar in focus +; REVIEW: currently not properly used +InPlaceSvrOutlAccelFocusEdit ACCELERATORS + BEGIN + VK_F12, IDM_F_OPEN, VIRTKEY, CONTROL + VK_F12, IDM_F_SAVE, VIRTKEY, SHIFT + VK_F12, IDM_F_SAVEAS, VIRTKEY + VK_F12, IDM_F_PRINT, VIRTKEY, CONTROL, SHIFT + + VK_RETURN, IDM_L_ADDLINE, VIRTKEY + VK_RETURN, IDM_L_EDITLINE, VIRTKEY, ALT + + VK_ESCAPE, IDM_FB_CANCEL, VIRTKEY + END + +SvrOutlIcon ICON isvrotl.ico + +Image72 BITMAP image72.bmp +Image96 BITMAP image96.bmp +Image120 BITMAP image120.bmp +LogoBitmap BITMAP ole2.bmp + +#include "DIALOGS.DLG" diff --git a/private/oleutest/letest/outline/linking.c b/private/oleutest/letest/outline/linking.c new file mode 100644 index 000000000..cc0e91d72 --- /dev/null +++ b/private/oleutest/letest/outline/linking.c @@ -0,0 +1,2157 @@ +/************************************************************************* +** +** OLE 2 Sample Code +** +** linking.c +** +** This file contains the major interfaces, methods and related support +** functions for implementing linking to items. The code +** contained in this file is used by BOTH the Container and Server +** (Object) versions of the Outline sample code. +** +** As a server SVROUTL supports linking to the whole document object +** (either a file-based document or as an embedded object). It also +** supports linking to ranges (or PseudoObjects). +** +** As a container CNTROUTL supports linking to embedded objects. +** (see file svrpsobj.c for Pseudo Object implementation) +** +** OleDoc Object +** exposed interfaces: +** IPersistFile +** IOleItemContainer +** IExternalConnection +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + +#include "outline.h" + +OLEDBGDATA + +extern LPOUTLINEAPP g_lpApp; + + + +STDMETHODIMP OleDoc_ItemCont_GetObjectA( + LPOLEITEMCONTAINER lpThis, + LPSTR lpszItem, + DWORD dwSpeedNeeded, + LPBINDCTX lpbc, + REFIID riid, + LPVOID FAR*lplpvObject +); + +STDMETHODIMP OleDoc_ItemCont_GetObjectStorageA( + LPOLEITEMCONTAINER lpThis, + LPSTR lpszItem, + LPBINDCTX lpbc, + REFIID riid, + LPVOID FAR*lplpvStorage +); + +#if defined(OLE_CNTR) + +STDMETHODIMP OleDoc_ItemCont_IsRunningA( + LPOLEITEMCONTAINER lpThis, + LPSTR lpszItem +); + +HRESULT ContainerDoc_IsRunningA( + LPCONTAINERDOC lpContainerDoc, + LPSTR lpszItem); + +HRESULT ContainerDoc_GetObjectA( + LPCONTAINERDOC lpContainerDoc, + LPSTR lpszItem, + DWORD dwSpeedNeeded, + REFIID riid, + LPVOID FAR*lplpvObject +); + +HRESULT ContainerDoc_GetObjectStorageA( + LPCONTAINERDOC lpContainerDoc, + LPSTR lpszItem, + LPSTORAGE FAR*lplpStg); + +#endif // OLE_CNTR + +#if defined(OLE_SERVER) + +HRESULT ServerDoc_IsRunningA(LPSERVERDOC lpServerDoc, LPSTR lpszItem); + +HRESULT ServerDoc_GetObjectA( + LPSERVERDOC lpServerDoc, + LPSTR lpszItem, + REFIID riid, + LPVOID FAR*lplpvObject); + +#endif // OLE_SERVER + + + + + + +/************************************************************************* +** OleDoc::IPersistFile interface implementation +*************************************************************************/ + +// IPersistFile::QueryInterface +STDMETHODIMP OleDoc_PFile_QueryInterface( + LPPERSISTFILE lpThis, + REFIID riid, + LPVOID FAR* lplpvObj +) +{ + LPOLEDOC lpOleDoc = ((struct CDocPersistFileImpl FAR*)lpThis)->lpOleDoc; + + return OleDoc_QueryInterface(lpOleDoc, riid, lplpvObj); +} + + +// IPersistFile::AddRef +STDMETHODIMP_(ULONG) OleDoc_PFile_AddRef(LPPERSISTFILE lpThis) +{ + LPOLEDOC lpOleDoc = ((struct CDocPersistFileImpl FAR*)lpThis)->lpOleDoc; + + OleDbgAddRefMethod(lpThis, "IPersistFile"); + + return OleDoc_AddRef(lpOleDoc); +} + + +// IPersistFile::Release +STDMETHODIMP_(ULONG) OleDoc_PFile_Release (LPPERSISTFILE lpThis) +{ + LPOLEDOC lpOleDoc = ((struct CDocPersistFileImpl FAR*)lpThis)->lpOleDoc; + + OleDbgReleaseMethod(lpThis, "IPersistFile"); + + return OleDoc_Release(lpOleDoc); +} + + +// IPersistFile::GetClassID +STDMETHODIMP OleDoc_PFile_GetClassID ( + LPPERSISTFILE lpThis, + CLSID FAR* lpclsid +) +{ + LPOLEDOC lpOleDoc = ((struct CDocPersistFileImpl FAR*)lpThis)->lpOleDoc; + LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; + OleDbgOut2("OleDoc_PFile_GetClassID\r\n"); + +#if defined( OLE_SERVER ) && defined( SVR_TREATAS ) + + /* OLE2NOTE: we must be carefull to return the correct CLSID here. + ** if we are currently preforming a "TreatAs (aka. ActivateAs)" + ** operation then we need to return the class of the object + ** written in the storage of the object. otherwise we would + ** return our own class id. + */ + return ServerDoc_GetClassID((LPSERVERDOC)lpOleDoc, lpclsid); +#else + *lpclsid = CLSID_APP; +#endif + return NOERROR; +} + + +// IPersistFile::IsDirty +STDMETHODIMP OleDoc_PFile_IsDirty(LPPERSISTFILE lpThis) +{ + LPOLEDOC lpOleDoc = ((struct CDocPersistFileImpl FAR*)lpThis)->lpOleDoc; + OleDbgOut2("OleDoc_PFile_IsDirty\r\n"); + + if (OutlineDoc_IsModified((LPOUTLINEDOC)lpOleDoc)) + return NOERROR; + else + return ResultFromScode(S_FALSE); +} + + +// IPersistFile::Load +STDMETHODIMP OleDoc_PFile_LoadA( + LPPERSISTFILE lpThis, + LPCSTR lpszFileName, + DWORD grfMode +) +{ + LPOLEDOC lpOleDoc = ((struct CDocPersistFileImpl FAR*)lpThis)->lpOleDoc; + SCODE sc; + + OLEDBG_BEGIN2("OleDoc_PFile_Load\r\n") + + /* OLE2NOTE: grfMode passed from the caller indicates if the caller + ** needs Read or ReadWrite permissions. if appropriate the + ** callee should open the file with the requested permissions. + ** the caller will normally not impose sharing permissions. + ** + ** the sample code currently always opens its file ReadWrite. + */ + + if (OutlineDoc_LoadFromFile((LPOUTLINEDOC)lpOleDoc, (LPSTR)lpszFileName)) + sc = S_OK; + else + sc = E_FAIL; + + OLEDBG_END2 + return ResultFromScode(sc); +} + + + +// IPersistFile::Load +STDMETHODIMP OleDoc_PFile_Load ( + LPPERSISTFILE lpThis, + LPCOLESTR lpszFileName, + DWORD grfMode +) +{ + CREATESTR(lpsz, lpszFileName) + + HRESULT hr = OleDoc_PFile_LoadA(lpThis, lpsz, grfMode); + + FREESTR(lpsz) + + return hr; +} + + + +// IPersistFile::Save +STDMETHODIMP OleDoc_PFile_SaveA ( + LPPERSISTFILE lpThis, + LPCSTR lpszFileName, + BOOL fRemember +) +{ + LPOLEDOC lpOleDoc = ((struct CDocPersistFileImpl FAR*)lpThis)->lpOleDoc; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc; + SCODE sc; + + OLEDBG_BEGIN2("OleDoc_PFile_Save\r\n") + + /* OLE2NOTE: it is only legal to perform a Save or SaveAs operation + ** on a file-based document. if the document is an embedded + ** object then we can not be changed to a file-base object. + ** + ** fRemember lpszFileName Type of Save + ** ---------------------------------------------- + ** TRUE NULL SAVE + ** TRUE ! NULL SAVE AS + ** FALSE ! NULL SAVE COPY AS + ** FALSE NULL ***error*** + */ + if ( (lpszFileName==NULL || (lpszFileName != NULL && fRemember)) + && ((lpOutlineDoc->m_docInitType != DOCTYPE_FROMFILE + && lpOutlineDoc->m_docInitType != DOCTYPE_NEW)) ) { + OLEDBG_END2 + return ResultFromScode(E_INVALIDARG); + } + + if (OutlineDoc_SaveToFile( + (LPOUTLINEDOC)lpOleDoc, + lpszFileName, + lpOutlineDoc->m_cfSaveFormat, + fRemember)) { + sc = S_OK; + } else + sc = E_FAIL; + + OLEDBG_END2 + return ResultFromScode(sc); +} + + + +// IPersistFile::Save +STDMETHODIMP OleDoc_PFile_Save( + LPPERSISTFILE lpThis, + LPCOLESTR lpszFileName, + BOOL fRemember +) +{ + CREATESTR(lpsz, lpszFileName) + + HRESULT hr = OleDoc_PFile_SaveA(lpThis, lpsz, fRemember); + + FREESTR(lpsz) + + return hr; +} + + + + +// IPersistFile::SaveCompleted +STDMETHODIMP OleDoc_PFile_SaveCompletedA ( + LPPERSISTFILE lpThis, + LPCSTR lpszFileName +) +{ + LPOLEDOC lpOleDoc = ((struct CDocPersistFileImpl FAR*)lpThis)->lpOleDoc; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc; + + OleDbgOut2("OleDoc_PFile_SaveCompleted\r\n"); + + /* This method is called after IPersistFile::Save is called. during + ** the period between Save and SaveCompleted the object must + ** consider itself in NOSCRIBBLE mode (ie. it is NOT allowed to + ** write to its file. here the object can clear its NOSCRIBBLE + ** mode flag. the outline app never scribbles to its storage, so + ** we have nothing to do. + */ + return NOERROR; +} + + + +STDMETHODIMP OleDoc_PFile_SaveCompleted ( + LPPERSISTFILE lpThis, + LPCOLESTR lpszFileName +) +{ + CREATESTR(lpsz, lpszFileName) + + HRESULT hr = OleDoc_PFile_SaveCompletedA(lpThis, lpsz); + + FREESTR(lpsz) + + return hr; +} + + + +// IPersistFile::GetCurFile +STDMETHODIMP OleDoc_PFile_GetCurFileA ( + LPPERSISTFILE lpThis, + LPSTR FAR* lplpszFileName +) +{ + LPOLEDOC lpOleDoc = ((struct CDocPersistFileImpl FAR*)lpThis)->lpOleDoc; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc; + LPMALLOC lpMalloc; + LPSTR lpsz; + SCODE sc; + OleDbgOut2("OleDoc_PFile_GetCurFile\r\n"); + + /* OLE2NOTE: we must make sure to set all out ptr parameters to NULL. */ + *lplpszFileName = NULL; + + /********************************************************************* + ** OLE2NOTE: memory returned for the lplpszFileName must be + ** allocated appropriately using the current registered IMalloc + ** interface. the allows the ownership of the memory to be + ** passed to the caller (even if in another process). + *********************************************************************/ + + CoGetMalloc(MEMCTX_TASK, &lpMalloc); + if (! lpMalloc) { + return ResultFromScode(E_FAIL); + } + + if (lpOutlineDoc->m_docInitType == DOCTYPE_FROMFILE) { + /* valid filename associated; return file name */ + lpsz = (LPSTR)lpMalloc->lpVtbl->Alloc( + lpMalloc, + lstrlen((LPSTR)lpOutlineDoc->m_szFileName)+1 + ); + if (! lpsz) { + sc = E_OUTOFMEMORY; + goto error; + } + + lstrcpy(lpsz, (LPSTR)lpOutlineDoc->m_szFileName); + sc = S_OK; + } else { + /* no file associated; return default file name prompt */ + lpsz=(LPSTR)lpMalloc->lpVtbl->Alloc(lpMalloc, sizeof(DEFEXTENSION)+3); + wsprintf(lpsz, "*.%s", DEFEXTENSION); + sc = S_FALSE; + } + +error: + OleStdRelease((LPUNKNOWN)lpMalloc); + *lplpszFileName = lpsz; + return ResultFromScode(sc); +} + +STDMETHODIMP OleDoc_PFile_GetCurFile ( + LPPERSISTFILE lpThis, + LPOLESTR FAR* lplpszFileName +) +{ + LPSTR lpsz; + + HRESULT hr = OleDoc_PFile_GetCurFileA(lpThis, &lpsz); + + CopyAndFreeSTR(lpsz, lplpszFileName); + + return hr; +} + +/************************************************************************* +** OleDoc::IOleItemContainer interface implementation +*************************************************************************/ + +// IOleItemContainer::QueryInterface +STDMETHODIMP OleDoc_ItemCont_QueryInterface( + LPOLEITEMCONTAINER lpThis, + REFIID riid, + LPVOID FAR* lplpvObj +) +{ + LPOLEDOC lpOleDoc = + ((struct CDocOleItemContainerImpl FAR*)lpThis)->lpOleDoc; + + return OleDoc_QueryInterface(lpOleDoc, riid, lplpvObj); +} + + +// IOleItemContainer::AddRef +STDMETHODIMP_(ULONG) OleDoc_ItemCont_AddRef(LPOLEITEMCONTAINER lpThis) +{ + LPOLEDOC lpOleDoc = + ((struct CDocOleItemContainerImpl FAR*)lpThis)->lpOleDoc; + + OleDbgAddRefMethod(lpThis, "IOleItemContainer"); + + return OleDoc_AddRef((LPOLEDOC)lpOleDoc); +} + + +// IOleItemContainer::Release +STDMETHODIMP_(ULONG) OleDoc_ItemCont_Release(LPOLEITEMCONTAINER lpThis) +{ + LPOLEDOC lpOleDoc = + ((struct CDocOleItemContainerImpl FAR*)lpThis)->lpOleDoc; + + OleDbgReleaseMethod(lpThis, "IOleItemContainer"); + + return OleDoc_Release((LPOLEDOC)lpOleDoc); +} + + +// IOleItemContainer::ParseDisplayName +STDMETHODIMP OleDoc_ItemCont_ParseDisplayNameA( + LPOLEITEMCONTAINER lpThis, + LPBC lpbc, + LPSTR lpszDisplayName, + ULONG FAR* lpchEaten, + LPMONIKER FAR* lplpmkOut +) +{ + LPOLEDOC lpOleDoc = + ((struct CDocOleItemContainerImpl FAR*)lpThis)->lpOleDoc; + char szItemName[MAXNAMESIZE]; + LPUNKNOWN lpUnk; + HRESULT hrErr; + OleDbgOut2("OleDoc_ItemCont_ParseDisplayName\r\n"); + + /* OLE2NOTE: we must make sure to set all out ptr parameters to NULL. */ + *lplpmkOut = NULL; + + *lpchEaten = OleStdGetItemToken( + lpszDisplayName, + szItemName, + sizeof(szItemName) + ); + + /* OLE2NOTE: get a pointer to a running instance of the object. we + ** should force the object to go running if necessary (even if + ** this means launching its server EXE). this is the meaining of + ** BINDSPEED_INDEFINITE. Parsing a Moniker is known to be an + ** "EXPENSIVE" operation. + */ + hrErr = OleDoc_ItemCont_GetObjectA( + lpThis, + szItemName, + BINDSPEED_INDEFINITE, + lpbc, + &IID_IUnknown, + (LPVOID FAR*)&lpUnk + ); + + if (hrErr == NOERROR) { + OleStdRelease(lpUnk); // item name FOUND; don't need obj ptr. + + CreateItemMonikerA(OLESTDDELIM, szItemName, lplpmkOut); + + } else + *lpchEaten = 0; // item name is NOT valid + + return hrErr; +} + +STDMETHODIMP OleDoc_ItemCont_ParseDisplayName( + LPOLEITEMCONTAINER lpThis, + LPBC lpbc, + LPOLESTR lpszDisplayName, + ULONG FAR* lpchEaten, + LPMONIKER FAR* lplpmkOut +) +{ + CREATESTR(lpsz, lpszDisplayName) + + HRESULT hr = OleDoc_ItemCont_ParseDisplayNameA(lpThis, lpbc, + lpsz, lpchEaten, lplpmkOut); + + FREESTR(lpsz); + + return hr; +} + + +// IOleItemContainer::EnumObjects +STDMETHODIMP OleDoc_ItemCont_EnumObjects( + LPOLEITEMCONTAINER lpThis, + DWORD grfFlags, + LPENUMUNKNOWN FAR* lplpenumUnknown +) +{ + LPOLEDOC lpOleDoc = + ((struct CDocOleItemContainerImpl FAR*)lpThis)->lpOleDoc; + + OLEDBG_BEGIN2("OleDoc_ItemCont_EnumObjects\r\n") + + /* OLE2NOTE: we must make sure to set all out ptr parameters to NULL. */ + *lplpenumUnknown = NULL; + + /* OLE2NOTE: this method should be implemented to allow programatic + ** clients the ability to what elements the container holds. + ** this method is NOT called in the standard linking scenarios. + ** + ** grfFlags can be one of the following: + ** OLECONTF_EMBEDDINGS -- enumerate embedded objects + ** OLECONTF_LINKS -- enumerate linked objects + ** OLECONTF_OTHERS -- enumerate non-OLE compound doc objs + ** OLECONTF_ONLYUSER -- enumerate only objs named by user + ** OLECONTF_ONLYIFRUNNING-- enumerate only objs in running state + */ + + OleDbgAssertSz(0, "NOT YET IMPLEMENTED!"); + + OLEDBG_END2 + return ResultFromScode(E_NOTIMPL); +} + + +// IOleItemContainer::LockContainer +STDMETHODIMP OleDoc_ItemCont_LockContainer( + LPOLEITEMCONTAINER lpThis, + BOOL fLock +) +{ + LPOLEDOC lpOleDoc = + ((struct CDocOleItemContainerImpl FAR*)lpThis)->lpOleDoc; + HRESULT hrErr; + OLEDBG_BEGIN2("OleDoc_ItemCont_LockContainer\r\n") + +#if defined( _DEBUG ) + if (fLock) { + ++lpOleDoc->m_cCntrLock; + OleDbgOutRefCnt3( + "OleDoc_ItemCont_LockContainer: cLock++\r\n", + lpOleDoc, + lpOleDoc->m_cCntrLock + ); + } else { + /* OLE2NOTE: when there are no open documents and the app is not + ** under the control of the user and there are no outstanding + ** locks on the app, then revoke our ClassFactory to enable the + ** app to shut down. + */ + --lpOleDoc->m_cCntrLock; + OleDbgAssertSz ( + lpOleDoc->m_cCntrLock >= 0, + "OleDoc_ItemCont_LockContainer(FALSE) called with cLock == 0" + ); + + if (lpOleDoc->m_cCntrLock == 0) { + OleDbgOutRefCnt2( + "OleDoc_ItemCont_LockContainer: UNLOCKED\r\n", + lpOleDoc, lpOleDoc->m_cCntrLock); + } else { + OleDbgOutRefCnt3( + "OleDoc_ItemCont_LockContainer: cLock--\r\n", + lpOleDoc, lpOleDoc->m_cCntrLock); + } + } +#endif // _DEBUG + + /* OLE2NOTE: in order to hold the document alive we call + ** CoLockObjectExternal to add a strong reference to our Doc + ** object. this will keep the Doc alive when all other external + ** references release us. whenever an embedded object goes + ** running a LockContainer(TRUE) is called. when the embedded + ** object shuts down (ie. transitions from running to loaded) + ** LockContainer(FALSE) is called. if the user issues File.Close + ** the document will shut down in any case ignoring any + ** outstanding LockContainer locks because CoDisconnectObject is + ** called in OleDoc_Close. this will forceably break any + ** existing strong reference counts including counts that we add + ** ourselves by calling CoLockObjectExternal and guarantee that + ** the Doc object gets its final release (ie. cRefs goes to 0). + */ + hrErr = OleDoc_Lock(lpOleDoc, fLock, TRUE /* fLastUnlockReleases */); + + OLEDBG_END2 + return hrErr; +} + + +// IOleItemContainer::GetObject +STDMETHODIMP OleDoc_ItemCont_GetObjectA( + LPOLEITEMCONTAINER lpThis, + LPSTR lpszItem, + DWORD dwSpeedNeeded, + LPBINDCTX lpbc, + REFIID riid, + LPVOID FAR* lplpvObject +) +{ + LPOLEDOC lpOleDoc = + ((struct CDocOleItemContainerImpl FAR*)lpThis)->lpOleDoc; + HRESULT hrErr; + + OLEDBG_BEGIN2("OleDoc_ItemCont_GetObject\r\n") + + /* OLE2NOTE: we must make sure to set all out ptr parameters to NULL. */ + *lplpvObject = NULL; + +#if defined( OLE_SERVER ) + + /* OLE2NOTE: SERVER ONLY version should return PseudoObjects with + ** BINDSPEED_IMMEDIATE, thus the dwSpeedNeeded is not important + ** in the case of a pure server. + */ + hrErr = ServerDoc_GetObjectA( + (LPSERVERDOC)lpOleDoc, lpszItem,riid,lplpvObject); +#endif +#if defined( OLE_CNTR ) + + /* OLE2NOTE: dwSpeedNeeded indicates how long the caller is willing + ** to wait for us to get the object: + ** BINDSPEED_IMMEDIATE -- only if obj already loaded && IsRunning + ** BINDSPEED_MODERATE -- load obj if necessary && if IsRunning + ** BINDSPEED_INDEFINITE-- force obj to load and run if necessary + */ + hrErr = ContainerDoc_GetObjectA( + (LPCONTAINERDOC)lpOleDoc,lpszItem,dwSpeedNeeded,riid,lplpvObject); +#endif + + OLEDBG_END2 + return hrErr; +} + + + + +STDMETHODIMP OleDoc_ItemCont_GetObject( + LPOLEITEMCONTAINER lpThis, + LPOLESTR lpszItem, + DWORD dwSpeedNeeded, + LPBINDCTX lpbc, + REFIID riid, + LPVOID FAR* lplpvObject +) +{ + CREATESTR(lpsz, lpszItem) + + HRESULT hr = OleDoc_ItemCont_GetObjectA(lpThis, lpsz, dwSpeedNeeded, lpbc, + riid, lplpvObject); + + FREESTR(lpsz) + + return hr; +} + + +// IOleItemContainer::GetObjectStorage +STDMETHODIMP OleDoc_ItemCont_GetObjectStorageA( + LPOLEITEMCONTAINER lpThis, + LPSTR lpszItem, + LPBINDCTX lpbc, + REFIID riid, + LPVOID FAR* lplpvStorage +) +{ + LPOLEDOC lpOleDoc = + ((struct CDocOleItemContainerImpl FAR*)lpThis)->lpOleDoc; + OleDbgOut2("OleDoc_ItemCont_GetObjectStorage\r\n"); + + /* OLE2NOTE: we must make sure to set all out ptr parameters to NULL. */ + *lplpvStorage = NULL; + +#if defined( OLE_SERVER ) + /* OLE2NOTE: in the SERVER ONLY version, item names identify pseudo + ** objects. pseudo objects, do NOT have identifiable storage. + */ + return ResultFromScode(E_FAIL); +#endif +#if defined( OLE_CNTR ) + // We can only return an IStorage* type pointer + if (! IsEqualIID(riid, &IID_IStorage)) + return ResultFromScode(E_FAIL); + + return ContainerDoc_GetObjectStorageA( + (LPCONTAINERDOC)lpOleDoc, + lpszItem, + (LPSTORAGE FAR*)lplpvStorage + ); +#endif +} + +STDMETHODIMP OleDoc_ItemCont_GetObjectStorage( + LPOLEITEMCONTAINER lpThis, + LPOLESTR lpszItem, + LPBINDCTX lpbc, + REFIID riid, + LPVOID FAR* lplpvStorage +) +{ + CREATESTR(lpsz, lpszItem) + + HRESULT hr = OleDoc_ItemCont_GetObjectStorageA(lpThis, lpsz, lpbc, + riid, lplpvStorage); + + FREESTR(lpsz) + + return hr; +} + +// IOleItemContainer::IsRunning +STDMETHODIMP OleDoc_ItemCont_IsRunningA( + LPOLEITEMCONTAINER lpThis, + LPSTR lpszItem +) +{ + LPOLEDOC lpOleDoc = + ((struct CDocOleItemContainerImpl FAR*)lpThis)->lpOleDoc; + HRESULT hrErr; + + OLEDBG_BEGIN2("OleDoc_ItemCont_IsRunning\r\n") + + /* OLE2NOTE: Check if item name is valid. if so then return if + ** Object is running. PseudoObjects in the Server version are + ** always considered running. Ole objects in the container must + ** be checked if they are running. + */ + +#if defined( OLE_SERVER ) + hrErr = ServerDoc_IsRunningA((LPSERVERDOC)lpOleDoc, lpszItem); +#endif +#if defined( OLE_CNTR ) + hrErr = ContainerDoc_IsRunningA((LPCONTAINERDOC)lpOleDoc, lpszItem); +#endif + + OLEDBG_END2 + return hrErr; +} + +STDMETHODIMP OleDoc_ItemCont_IsRunning( + LPOLEITEMCONTAINER lpThis, + LPOLESTR lpszItem +) +{ + CREATESTR(lpsz, lpszItem) + + HRESULT hr = OleDoc_ItemCont_IsRunningA(lpThis,lpsz); + + FREESTR(lpsz) + + return hr; +} + +/************************************************************************* +** OleDoc::IExternalConnection interface implementation +*************************************************************************/ + +// IExternalConnection::QueryInterface +STDMETHODIMP OleDoc_ExtConn_QueryInterface( + LPEXTERNALCONNECTION lpThis, + REFIID riid, + LPVOID FAR* lplpvObj +) +{ + LPOLEDOC lpOleDoc = + ((struct CDocExternalConnectionImpl FAR*)lpThis)->lpOleDoc; + + return OleDoc_QueryInterface(lpOleDoc, riid, lplpvObj); +} + + +// IExternalConnection::AddRef +STDMETHODIMP_(ULONG) OleDoc_ExtConn_AddRef(LPEXTERNALCONNECTION lpThis) +{ + LPOLEDOC lpOleDoc = + ((struct CDocExternalConnectionImpl FAR*)lpThis)->lpOleDoc; + + OleDbgAddRefMethod(lpThis, "IExternalConnection"); + + return OleDoc_AddRef(lpOleDoc); +} + + +// IExternalConnection::Release +STDMETHODIMP_(ULONG) OleDoc_ExtConn_Release (LPEXTERNALCONNECTION lpThis) +{ + LPOLEDOC lpOleDoc = + ((struct CDocExternalConnectionImpl FAR*)lpThis)->lpOleDoc; + + OleDbgReleaseMethod(lpThis, "IExternalConnection"); + + return OleDoc_Release(lpOleDoc); +} + + +// IExternalConnection::AddConnection +STDMETHODIMP_(DWORD) OleDoc_ExtConn_AddConnection( + LPEXTERNALCONNECTION lpThis, + DWORD extconn, + DWORD reserved +) +{ + LPOLEDOC lpOleDoc = + ((struct CDocExternalConnectionImpl FAR*)lpThis)->lpOleDoc; + + if( extconn & EXTCONN_STRONG ) { + +#if defined( _DEBUG ) + OleDbgOutRefCnt3( + "OleDoc_ExtConn_AddConnection: dwStrongExtConn++\r\n", + lpOleDoc, + lpOleDoc->m_dwStrongExtConn + 1 + ); +#endif + return ++(lpOleDoc->m_dwStrongExtConn); + } else + return 0; +} + + +// IExternalConnection::ReleaseConnection +STDMETHODIMP_(DWORD) OleDoc_ExtConn_ReleaseConnection( + LPEXTERNALCONNECTION lpThis, + DWORD extconn, + DWORD reserved, + BOOL fLastReleaseCloses +) +{ + LPOLEDOC lpOleDoc = + ((struct CDocExternalConnectionImpl FAR*)lpThis)->lpOleDoc; + + if( extconn & EXTCONN_STRONG ){ + DWORD dwSave = --(lpOleDoc->m_dwStrongExtConn); +#if defined( _DEBUG ) + OLEDBG_BEGIN2( (fLastReleaseCloses ? + "OleDoc_ExtConn_ReleaseConnection(TRUE)\r\n" : + "OleDoc_ExtConn_ReleaseConnection(FALSE)\r\n") ) + OleDbgOutRefCnt3( + "OleDoc_ExtConn_ReleaseConnection: dwStrongExtConn--\r\n", + lpOleDoc, + lpOleDoc->m_dwStrongExtConn + ); + OleDbgAssertSz ( + lpOleDoc->m_dwStrongExtConn >= 0, + "OleDoc_ExtConn_ReleaseConnection called with dwStrong == 0" + ); +#endif // _DEBUG + + if( lpOleDoc->m_dwStrongExtConn == 0 && fLastReleaseCloses ) + OleDoc_Close(lpOleDoc, OLECLOSE_SAVEIFDIRTY); + + OLEDBG_END2 + return dwSave; + } else + return 0; +} + + +/************************************************************************* +** OleDoc Common Support Functions +*************************************************************************/ + + +/* OleDoc_GetFullMoniker +** --------------------- +** Return the full, absolute moniker of the document. +** +** NOTE: the caller must release the pointer returned when done. +*/ +LPMONIKER OleDoc_GetFullMoniker(LPOLEDOC lpOleDoc, DWORD dwAssign) +{ + LPMONIKER lpMoniker = NULL; + + OLEDBG_BEGIN3("OleDoc_GetFullMoniker\r\n") + + if (lpOleDoc->m_lpSrcDocOfCopy) { + /* CASE I: this document was created for a copy or drag/drop + ** operation. generate the moniker which identifies the + ** source document of the original copy. + */ + if (! lpOleDoc->m_fLinkSourceAvail) + goto done; // we already know a moniker is not available + + lpMoniker=OleDoc_GetFullMoniker(lpOleDoc->m_lpSrcDocOfCopy, dwAssign); + } + else if (lpOleDoc->m_lpFileMoniker) { + + /* CASE II: this document is a top-level user document (either + ** file-based or untitled). return the FileMoniker stored + ** with the document; it uniquely identifies the document. + */ + // we must AddRef the moniker to pass out a ptr + lpOleDoc->m_lpFileMoniker->lpVtbl->AddRef(lpOleDoc->m_lpFileMoniker); + + lpMoniker = lpOleDoc->m_lpFileMoniker; + } + +#if defined( OLE_SERVER ) + + else if (((LPSERVERDOC)lpOleDoc)->m_lpOleClientSite) { + + /* CASE III: this document is an embedded object, ask our + ** container for our moniker. + */ + OLEDBG_BEGIN2("IOleClientSite::GetMoniker called\r\n"); + ((LPSERVERDOC)lpOleDoc)->m_lpOleClientSite->lpVtbl->GetMoniker( + ((LPSERVERDOC)lpOleDoc)->m_lpOleClientSite, + dwAssign, + OLEWHICHMK_OBJFULL, + &lpMoniker + ); + OLEDBG_END2 + } + +#endif + + else { + lpMoniker = NULL; + } + +done: + OLEDBG_END3 + return lpMoniker; +} + + +/* OleDoc_DocRenamedUpdate +** ----------------------- +** Update the documents registration in the running object table (ROT). +** Also inform all embedded OLE objects (container only) and/or psedudo +** objects (server only) that the name of the document has changed. +*/ +void OleDoc_DocRenamedUpdate(LPOLEDOC lpOleDoc, LPMONIKER lpmkDoc) +{ + OLEDBG_BEGIN3("OleDoc_DocRenamedUpdate\r\n") + + OleDoc_AddRef(lpOleDoc); + + /* OLE2NOTE: we must re-register ourselves as running when we + ** get a new moniker assigned (ie. when we are renamed). + */ + OLEDBG_BEGIN3("OleStdRegisterAsRunning called\r\n") + OleStdRegisterAsRunning( + (LPUNKNOWN)&lpOleDoc->m_Unknown, + lpmkDoc, + &lpOleDoc->m_dwRegROT + ); + OLEDBG_END3 + +#if defined( OLE_SERVER ) + { + LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOleDoc; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc; + + /* OLE2NOTE: inform any linking clients that the document has been + ** renamed. + */ + ServerDoc_SendAdvise ( + lpServerDoc, + OLE_ONRENAME, + lpmkDoc, + 0 /* advf -- not relevant here */ + ); + + /* OLE2NOTE: inform any clients of pseudo objects + ** within our document, that our document's + ** Moniker has changed. + */ + ServerNameTable_InformAllPseudoObjectsDocRenamed( + (LPSERVERNAMETABLE)lpOutlineDoc->m_lpNameTable, lpmkDoc); + } +#endif +#if defined( OLE_CNTR ) + { + LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOleDoc; + + /* OLE2NOTE: must tell all OLE objects that our container + ** moniker changed. + */ + ContainerDoc_InformAllOleObjectsDocRenamed( + lpContainerDoc, + lpmkDoc + ); + } +#endif + + OleDoc_Release(lpOleDoc); // release artificial AddRef above + OLEDBG_END3 +} + + + +#if defined( OLE_SERVER ) + +/************************************************************************* +** ServerDoc Supprt Functions Used by Server versions +*************************************************************************/ + + +/* ServerDoc_PseudoObjLockDoc +** -------------------------- +** Add a lock on the Doc on behalf of the PseudoObject. the Doc may not +** close while the Doc exists. +** +** when a pseudo object is first created, it calls this method to +** guarantee that the document stays alive (PseudoObj_Init). +** when a pseudo object is destroyed, it call +** ServerDoc_PseudoObjUnlockDoc to release this hold on the document. +*/ +void ServerDoc_PseudoObjLockDoc(LPSERVERDOC lpServerDoc) +{ + LPOLEDOC lpOleDoc = (LPOLEDOC)lpServerDoc; + ULONG cPseudoObj; + + cPseudoObj = ++lpServerDoc->m_cPseudoObj; + +#if defined( _DEBUG ) + OleDbgOutRefCnt3( + "ServerDoc_PseudoObjLockDoc: cPseudoObj++\r\n", + lpServerDoc, + cPseudoObj + ); +#endif + OleDoc_Lock(lpOleDoc, TRUE /* fLock */, 0 /* not applicable */); + return; +} + + +/* ServerDoc_PseudoObjUnlockDoc +** ---------------------------- +** Release the lock on the Doc on behalf of the PseudoObject. if this was +** the last lock on the Doc, then it will shutdown. +*/ +void ServerDoc_PseudoObjUnlockDoc( + LPSERVERDOC lpServerDoc, + LPPSEUDOOBJ lpPseudoObj +) +{ + ULONG cPseudoObj; + LPOLEDOC lpOleDoc = (LPOLEDOC)lpServerDoc; + OLEDBG_BEGIN3("ServerDoc_PseudoObjUnlockDoc\r\n") + + /* OLE2NOTE: when there are no active pseudo objects in the Doc and + ** the Doc is not visible, and if there are no outstanding locks + ** on the Doc, then this is a "silent update" + ** situation. our Doc is being used programatically by some + ** client; it is NOT accessible to the user because it is + ** NOT visible. thus since all Locks have been released, we + ** will close the document. if the app is only running due + ** to the presence of this document, then the app will now + ** also shut down. + */ + cPseudoObj = --lpServerDoc->m_cPseudoObj; + +#if defined( _DEBUG ) + OleDbgAssertSz ( + lpServerDoc->m_cPseudoObj >= 0, + "PseudoObjUnlockDoc called with cPseudoObj == 0" + ); + + OleDbgOutRefCnt3( + "ServerDoc_PseudoObjUnlockDoc: cPseudoObj--\r\n", + lpServerDoc, + cPseudoObj + ); +#endif + OleDoc_Lock(lpOleDoc, FALSE /* fLock */, TRUE /* fLastUnlockReleases */); + + OLEDBG_END3 + return; +} + + +/* ServerDoc_GetObject +** ------------------- +** +** Return a pointer to an object identified by an item string +** (lpszItem). For a server-only app, the object returned will be a +** pseudo object. +*/ +HRESULT ServerDoc_GetObjectA( + LPSERVERDOC lpServerDoc, + LPSTR lpszItem, + REFIID riid, + LPVOID FAR* lplpvObject +) +{ + LPPSEUDOOBJ lpPseudoObj; + LPSERVERNAMETABLE lpServerNameTable = + (LPSERVERNAMETABLE)((LPOUTLINEDOC)lpServerDoc)->m_lpNameTable; + + *lplpvObject = NULL; + + /* Get the PseudoObj which corresponds to an item name. if the item + ** name does NOT exist in the name table then NO object is + ** returned. the ServerNameTable_GetPseudoObj routine finds a + ** name entry corresponding to the item name, it then checks if + ** a PseudoObj has already been allocated. if so, it returns the + ** existing object, otherwise it allocates a new PseudoObj. + */ + lpPseudoObj = ServerNameTable_GetPseudoObj( + lpServerNameTable, + lpszItem, + lpServerDoc + ); + + if (! lpPseudoObj) { + *lplpvObject = NULL; + return ResultFromScode(MK_E_NOOBJECT); + } + + // return the desired interface pointer of the pseudo object. + return PseudoObj_QueryInterface(lpPseudoObj, riid, lplpvObject); +} + + + +HRESULT ServerDoc_GetObject( + LPSERVERDOC lpServerDoc, + LPOLESTR lpszItem, + REFIID riid, + LPVOID FAR* lplpvObject +) +{ + CREATESTR(pstr, lpszItem) + + HRESULT hr = ServerDoc_GetObjectA(lpServerDoc, pstr, riid, lplpvObject); + + FREESTR(pstr) + + return hr; +} + + + +/* ServerDoc_IsRunning +** ------------------- +** +** Check if the object identified by an item string (lpszItem) is in +** the running state. For a server-only app, if the item name exists in +** in the NameTable then the item name is considered running. +** IOleItemContainer::GetObject would succeed. +*/ + +HRESULT ServerDoc_IsRunningA(LPSERVERDOC lpServerDoc, LPSTR lpszItem) +{ + LPOUTLINENAMETABLE lpOutlineNameTable = + ((LPOUTLINEDOC)lpServerDoc)->m_lpNameTable; + LPSERVERNAME lpServerName; + + lpServerName = (LPSERVERNAME)OutlineNameTable_FindName( + lpOutlineNameTable, + lpszItem + ); + + if (lpServerName) + return NOERROR; + else + return ResultFromScode(MK_E_NOOBJECT); +} + + +/* ServerDoc_GetSelRelMoniker +** -------------------------- +** Retrieve the relative item moniker which identifies the given +** selection (lplrSel). +** +** Returns NULL if a moniker can NOT be created. +*/ + +LPMONIKER ServerDoc_GetSelRelMoniker( + LPSERVERDOC lpServerDoc, + LPLINERANGE lplrSel, + DWORD dwAssign +) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; + LPSERVERNAMETABLE lpServerNameTable = + (LPSERVERNAMETABLE)lpOutlineDoc->m_lpNameTable; + LPOUTLINENAMETABLE lpOutlineNameTable = + (LPOUTLINENAMETABLE)lpServerNameTable; + LPOUTLINENAME lpOutlineName; + LPMONIKER lpmk; + + lpOutlineName=OutlineNameTable_FindNamedRange(lpOutlineNameTable,lplrSel); + + if (lpOutlineName) { + /* the selection range already has a name assigned */ + CreateItemMonikerA(OLESTDDELIM, lpOutlineName->m_szName, &lpmk); + } else { + char szbuf[MAXNAMESIZE]; + + switch (dwAssign) { + + case GETMONIKER_FORCEASSIGN: + + /* Force the assignment of the name. This is called when a + ** Paste Link actually occurs. At this point we want to + ** create a Name and add it to the NameTable in order to + ** track the source of the link. This name (as all + ** names) will be updated upon editing of the document. + */ + wsprintf( + szbuf, + "%s %ld", + (LPSTR)DEFRANGENAMEPREFIX, + ++(lpServerDoc->m_nNextRangeNo) + ); + + lpOutlineName = OutlineApp_CreateName(lpOutlineApp); + + if (lpOutlineName) { + lstrcpy(lpOutlineName->m_szName, szbuf); + lpOutlineName->m_nStartLine = lplrSel->m_nStartLine; + lpOutlineName->m_nEndLine = lplrSel->m_nEndLine; + OutlineDoc_AddName(lpOutlineDoc, lpOutlineName); + } else { + // REVIEW: do we need "Out-of-Memory" error message here? + } + break; + + case GETMONIKER_TEMPFORUSER: + + /* Create a name to show to the user in the Paste + ** Special dialog but do NOT yet incur the overhead + ** of adding a Name to the NameTable. The Moniker + ** generated should be useful to display to the user + ** to indicate the source of the copy, but will NOT + ** be used to create a link directly (the caller + ** should ask again for a moniker specifying FORCEASSIGN). + ** we will generate the name that would be the next + ** auto-generated range name, BUT will NOT actually + ** increment the range counter. + */ + wsprintf( + szbuf, + "%s %ld", + (LPSTR)DEFRANGENAMEPREFIX, + (lpServerDoc->m_nNextRangeNo)+1 + ); + break; + + case GETMONIKER_ONLYIFTHERE: + + /* the caller only wants a name if one has already been + ** assigned. we have already above checked if the + ** current selection has a name, so we will simply + ** return NULL here. + */ + return NULL; // no moniker is assigned + + default: + return NULL; // unknown flag given + } + + CreateItemMonikerA(OLESTDDELIM, szbuf, &lpmk); + } + return lpmk; +} + + +/* ServerDoc_GetSelFullMoniker +** --------------------------- +** Retrieve the full absolute moniker which identifies the given +** selection (lplrSel). +** this moniker is created as a composite of the absolute moniker for +** the entire document appended with an item moniker which identifies +** the selection relative to the document. +** Returns NULL if a moniker can NOT be created. +*/ +LPMONIKER ServerDoc_GetSelFullMoniker( + LPSERVERDOC lpServerDoc, + LPLINERANGE lplrSel, + DWORD dwAssign +) +{ + LPMONIKER lpmkDoc = NULL; + LPMONIKER lpmkItem = NULL; + LPMONIKER lpmkFull = NULL; + + lpmkDoc = OleDoc_GetFullMoniker( + (LPOLEDOC)lpServerDoc, + dwAssign + ); + if (! lpmkDoc) return NULL; + + lpmkItem = ServerDoc_GetSelRelMoniker( + lpServerDoc, + lplrSel, + dwAssign + ); + if (lpmkItem) { + CreateGenericComposite(lpmkDoc, lpmkItem, (LPMONIKER FAR*)&lpmkFull); + OleStdRelease((LPUNKNOWN)lpmkItem); + } + + if (lpmkDoc) + OleStdRelease((LPUNKNOWN)lpmkDoc); + + return lpmkFull; +} + + +/* ServerNameTable_EditLineUpdate + * ------------------------------- + * + * Update the table when a line at nEditIndex is edited. + */ +void ServerNameTable_EditLineUpdate( + LPSERVERNAMETABLE lpServerNameTable, + int nEditIndex +) +{ + LPOUTLINENAMETABLE lpOutlineNameTable = + (LPOUTLINENAMETABLE)lpServerNameTable; + LPOUTLINENAME lpOutlineName; + LINERANGE lrSel; + LPPSEUDOOBJ lpPseudoObj; + int i; + + for(i = 0; i < lpOutlineNameTable->m_nCount; i++) { + lpOutlineName=OutlineNameTable_GetName(lpOutlineNameTable, i); + + lpPseudoObj = ((LPSERVERNAME)lpOutlineName)->m_lpPseudoObj; + + /* if there is a pseudo object associated with this name, then + ** check if the line that was modified is included within + ** the named range. + */ + if (lpPseudoObj) { + OutlineName_GetSel(lpOutlineName, &lrSel); + + if(((int)lrSel.m_nStartLine <= nEditIndex) && + ((int)lrSel.m_nEndLine >= nEditIndex)) { + + // inform linking clients data has changed + PseudoObj_SendAdvise( + lpPseudoObj, + OLE_ONDATACHANGE, + NULL, /* lpmkDoc -- not relevant here */ + 0 /* advf -- no flags necessary */ + ); + } + + } + } +} + + +/* ServerNameTable_InformAllPseudoObjectsDocRenamed + * ------------------------------------------------ + * + * Inform all pseudo object clients that the name of the pseudo + * object has changed. + */ +void ServerNameTable_InformAllPseudoObjectsDocRenamed( + LPSERVERNAMETABLE lpServerNameTable, + LPMONIKER lpmkDoc +) +{ + LPOUTLINENAMETABLE lpOutlineNameTable = + (LPOUTLINENAMETABLE)lpServerNameTable; + LPOUTLINENAME lpOutlineName; + LPPSEUDOOBJ lpPseudoObj; + LPMONIKER lpmkObj; + int i; + + OLEDBG_BEGIN2("ServerNameTable_InformAllPseudoObjectsDocRenamed\r\n"); + + for(i = 0; i < lpOutlineNameTable->m_nCount; i++) { + lpOutlineName=OutlineNameTable_GetName(lpOutlineNameTable, i); + + lpPseudoObj = ((LPSERVERNAME)lpOutlineName)->m_lpPseudoObj; + + /* if there is a pseudo object associated with this name, then + ** send OnRename advise to its linking clients. + */ + if (lpPseudoObj && + ((lpmkObj=PseudoObj_GetFullMoniker(lpPseudoObj,lpmkDoc))!=NULL)) { + + // inform the clients that the name has changed + PseudoObj_SendAdvise ( + lpPseudoObj, + OLE_ONRENAME, + lpmkObj, + 0 /* advf -- not relevant here */ + ); + } + } + OLEDBG_END2 +} + + +/* ServerNameTable_InformAllPseudoObjectsDocSaved + * ------------------------------------------------ + * + * Inform all pseudo object clients that the name of the pseudo + * object has changed. + */ +void ServerNameTable_InformAllPseudoObjectsDocSaved( + LPSERVERNAMETABLE lpServerNameTable, + LPMONIKER lpmkDoc +) +{ + LPOUTLINENAMETABLE lpOutlineNameTable = + (LPOUTLINENAMETABLE)lpServerNameTable; + LPOUTLINENAME lpOutlineName; + LPPSEUDOOBJ lpPseudoObj; + LPMONIKER lpmkObj; + int i; + + OLEDBG_BEGIN2("ServerNameTable_InformAllPseudoObjectsDocSaved\r\n"); + + for(i = 0; i < lpOutlineNameTable->m_nCount; i++) { + lpOutlineName=OutlineNameTable_GetName(lpOutlineNameTable, i); + + lpPseudoObj = ((LPSERVERNAME)lpOutlineName)->m_lpPseudoObj; + + /* if there is a pseudo object associated with this name, then + ** send OnSave advise to its linking clients. + */ + if (lpPseudoObj && + ((lpmkObj=PseudoObj_GetFullMoniker(lpPseudoObj,lpmkDoc))!=NULL)) { + + // inform the clients that the name has been saved + PseudoObj_SendAdvise ( + lpPseudoObj, + OLE_ONSAVE, + NULL, /* lpmkDoc -- not relevant here */ + 0 /* advf -- not relevant here */ + ); + } + } + OLEDBG_END2 +} + + +/* ServerNameTable_SendPendingAdvises + * ---------------------------------- + * + * Send any pending change notifications for pseudo objects. + * while ReDraw is diabled on the ServerDoc, then change advise + * notifications are not sent to pseudo object clients. + */ +void ServerNameTable_SendPendingAdvises(LPSERVERNAMETABLE lpServerNameTable) +{ + LPOUTLINENAMETABLE lpOutlineNameTable = + (LPOUTLINENAMETABLE)lpServerNameTable; + LPSERVERNAME lpServerName; + int i; + + for(i = 0; i < lpOutlineNameTable->m_nCount; i++) { + lpServerName = (LPSERVERNAME)OutlineNameTable_GetName( + lpOutlineNameTable, + i + ); + ServerName_SendPendingAdvises(lpServerName); + } +} + + +/* ServerNameTable_GetPseudoObj +** ---------------------------- +** +** Return a pointer to a pseudo object identified by an item string +** (lpszItem). if the pseudo object already exists, then return the +** existing object, otherwise allocate a new pseudo object. +*/ +LPPSEUDOOBJ ServerNameTable_GetPseudoObj( + LPSERVERNAMETABLE lpServerNameTable, + LPSTR lpszItem, + LPSERVERDOC lpServerDoc +) +{ + LPSERVERNAME lpServerName; + + lpServerName = (LPSERVERNAME)OutlineNameTable_FindName( + (LPOUTLINENAMETABLE)lpServerNameTable, + lpszItem + ); + + if (lpServerName) + return ServerName_GetPseudoObj(lpServerName, lpServerDoc); + else + return NULL; +} + + +/* ServerNameTable_CloseAllPseudoObjs + * ---------------------------------- + * + * Force all pseudo objects to close. this results in sending OnClose + * notification to each pseudo object's linking clients. + */ +void ServerNameTable_CloseAllPseudoObjs(LPSERVERNAMETABLE lpServerNameTable) +{ + LPOUTLINENAMETABLE lpOutlineNameTable = + (LPOUTLINENAMETABLE)lpServerNameTable; + LPSERVERNAME lpServerName; + int i; + + OLEDBG_BEGIN3("ServerNameTable_CloseAllPseudoObjs\r\n") + + for(i = 0; i < lpOutlineNameTable->m_nCount; i++) { + lpServerName = (LPSERVERNAME)OutlineNameTable_GetName( + lpOutlineNameTable, + i + ); + ServerName_ClosePseudoObj(lpServerName); + } + + OLEDBG_END3 +} + + + +/* ServerName_SetSel + * ----------------- + * + * Change the line range of a name. + */ +void ServerName_SetSel( + LPSERVERNAME lpServerName, + LPLINERANGE lplrSel, + BOOL fRangeModified +) +{ + LPOUTLINENAME lpOutlineName = (LPOUTLINENAME)lpServerName; + BOOL fPseudoObjChanged = fRangeModified; + + if (lpOutlineName->m_nStartLine != lplrSel->m_nStartLine) { + lpOutlineName->m_nStartLine = lplrSel->m_nStartLine; + fPseudoObjChanged = TRUE; + } + + if (lpOutlineName->m_nEndLine != lplrSel->m_nEndLine) { + lpOutlineName->m_nEndLine = lplrSel->m_nEndLine; + fPseudoObjChanged = TRUE; + } + + /* OLE2NOTE: if the range of an active pseudo object has + ** changed, then inform any linking clients that the object + ** has changed. + */ + if (lpServerName->m_lpPseudoObj && fPseudoObjChanged) { + PseudoObj_SendAdvise( + lpServerName->m_lpPseudoObj, + OLE_ONDATACHANGE, + NULL, /* lpmkDoc -- not relevant here */ + 0 /* advf -- no flags necessary */ + ); + } +} + + +/* ServerName_SendPendingAdvises + * ----------------------------- + * + * Send any pending change notifications for the associated + * pseudo objects for this name (if one exists). + * while ReDraw is diabled on the ServerDoc, then change advise + * notifications are not sent to pseudo object clients. + */ +void ServerName_SendPendingAdvises(LPSERVERNAME lpServerName) +{ + if (! lpServerName->m_lpPseudoObj) + return; // no associated pseudo object + + if (lpServerName->m_lpPseudoObj->m_fDataChanged) + PseudoObj_SendAdvise( + lpServerName->m_lpPseudoObj, + OLE_ONDATACHANGE, + NULL, /* lpmkDoc -- not relevant here */ + 0 /* advf -- no flags necessary */ + ); +} + + +/* ServerName_GetPseudoObj +** ----------------------- +** +** Return a pointer to a pseudo object associated to a ServerName. +** if the pseudo object already exists, then return the +** existing object, otherwise allocate a new pseudo object. +** +** NOTE: the PseudoObj is returned with a 0 refcnt if first created, +** else the existing refcnt is unchanged. +*/ +LPPSEUDOOBJ ServerName_GetPseudoObj( + LPSERVERNAME lpServerName, + LPSERVERDOC lpServerDoc +) +{ + // Check if a PseudoObj already exists + if (lpServerName->m_lpPseudoObj) + return lpServerName->m_lpPseudoObj; + + // A PseudoObj does NOT already exist, allocate a new one. + lpServerName->m_lpPseudoObj=(LPPSEUDOOBJ) New((DWORD)sizeof(PSEUDOOBJ)); + if (lpServerName->m_lpPseudoObj == NULL) { + OleDbgAssertSz(lpServerName->m_lpPseudoObj != NULL, "Error allocating PseudoObj"); + return NULL; + } + + PseudoObj_Init(lpServerName->m_lpPseudoObj, lpServerName, lpServerDoc); + return lpServerName->m_lpPseudoObj; +} + + +/* ServerName_ClosePseudoObj + * ------------------------- + * + * if there is an associated pseudo objects for this name (if one + * exists), then close it. this results in sending OnClose + * notification to the pseudo object's linking clients. + */ +void ServerName_ClosePseudoObj(LPSERVERNAME lpServerName) +{ + if (!lpServerName || !lpServerName->m_lpPseudoObj) + return; // no associated pseudo object + + PseudoObj_Close(lpServerName->m_lpPseudoObj); +} + + +#endif // OLE_SERVER + + +#if defined( OLE_CNTR ) + + +/************************************************************************* +** ContainerDoc Supprt Functions Used by Container versions +*************************************************************************/ + + +/* ContainerLine_GetRelMoniker +** --------------------------- +** Retrieve the relative item moniker which identifies the OLE object +** relative to the container document. +** +** Returns NULL if a moniker can NOT be created. +*/ +LPMONIKER ContainerLine_GetRelMoniker( + LPCONTAINERLINE lpContainerLine, + DWORD dwAssign +) +{ + LPMONIKER lpmk = NULL; + + /* OLE2NOTE: we should only give out a moniker for the OLE object + ** if the object is allowed to be linked to from the inside. if + ** so we are allowed to give out a moniker which binds to the + ** running OLE object). if the object is an OLE 2.0 embedded + ** object then it is allowed to be linked to from the inside. if + ** the object is either an OleLink or an OLE 1.0 embedding + ** then it can not be linked to from the inside. + ** if we were a container/server app then we could offer linking + ** to the outside of the object (ie. a pseudo object within our + ** document). we are a container only app that does not support + ** linking to ranges of its data. + */ + + switch (dwAssign) { + + case GETMONIKER_FORCEASSIGN: + + /* Force the assignment of the name. This is called when a + ** Paste Link actually occurs. From now on we want + ** to inform the OLE object that its moniker is + ** assigned and is thus necessary to register itself + ** in the RunningObjectTable. + */ + CreateItemMonikerA( + OLESTDDELIM, lpContainerLine->m_szStgName, &lpmk); + + /* OLE2NOTE: if the OLE object is already loaded and it + ** is being assigned a moniker for the first time, + ** then we need to inform it that it now has a moniker + ** assigned by calling IOleObject::SetMoniker. this + ** will force the OLE object to register in the + ** RunningObjectTable when it enters the running + ** state. if the object is not currently loaded, + ** SetMoniker will be called automatically later when + ** the object is loaded by the function + ** ContainerLine_LoadOleObject. + */ + if (! lpContainerLine->m_fMonikerAssigned) { + + /* we must remember forever more that this object has a + ** moniker assigned. + */ + lpContainerLine->m_fMonikerAssigned = TRUE; + + // we are now dirty and must be saved + OutlineDoc_SetModified( + (LPOUTLINEDOC)lpContainerLine->m_lpDoc, + TRUE, /* fModified */ + FALSE, /* fDataChanged--N/A for container ver. */ + FALSE /* fSizeChanged--N/A for container ver. */ + ); + + if (lpContainerLine->m_lpOleObj) { + OLEDBG_BEGIN2("IOleObject::SetMoniker called\r\n") + lpContainerLine->m_lpOleObj->lpVtbl->SetMoniker( + lpContainerLine->m_lpOleObj, + OLEWHICHMK_OBJREL, + lpmk + ); + OLEDBG_END2 + } + } + break; + + case GETMONIKER_ONLYIFTHERE: + + /* If the OLE object currently has a moniker assigned, + ** then return it. + */ + if (lpContainerLine->m_fMonikerAssigned) { + + CreateItemMonikerA( + OLESTDDELIM, + lpContainerLine->m_szStgName, + &lpmk + ); + + } + break; + + case GETMONIKER_TEMPFORUSER: + + /* Return the moniker that would be used for the OLE + ** object but do NOT force moniker assignment at + ** this point. Since our strategy is to use the + ** storage name of the object as its item name, we + ** can simply create the corresponding ItemMoniker + ** (indepenedent of whether the moniker is currently + ** assigned or not). + */ + CreateItemMonikerA( + OLESTDDELIM, + lpContainerLine->m_szStgName, + &lpmk + ); + + break; + + case GETMONIKER_UNASSIGN: + + lpContainerLine->m_fMonikerAssigned = FALSE; + break; + + } + + return lpmk; +} + + +/* ContainerLine_GetFullMoniker +** ---------------------------- +** Retrieve the full absolute moniker which identifies the OLE object +** in the container document. +** this moniker is created as a composite of the absolute moniker for +** the entire document appended with an item moniker which identifies +** the OLE object relative to the document. +** Returns NULL if a moniker can NOT be created. +*/ +LPMONIKER ContainerLine_GetFullMoniker( + LPCONTAINERLINE lpContainerLine, + DWORD dwAssign +) +{ + LPMONIKER lpmkDoc = NULL; + LPMONIKER lpmkItem = NULL; + LPMONIKER lpmkFull = NULL; + + lpmkDoc = OleDoc_GetFullMoniker( + (LPOLEDOC)lpContainerLine->m_lpDoc, + dwAssign + ); + if (! lpmkDoc) return NULL; + + lpmkItem = ContainerLine_GetRelMoniker(lpContainerLine, dwAssign); + + if (lpmkItem) { + CreateGenericComposite(lpmkDoc, lpmkItem, (LPMONIKER FAR*)&lpmkFull); + OleStdRelease((LPUNKNOWN)lpmkItem); + } + + if (lpmkDoc) + OleStdRelease((LPUNKNOWN)lpmkDoc); + + return lpmkFull; +} + + +/* ContainerDoc_InformAllOleObjectsDocRenamed +** ------------------------------------------ +** Inform all OLE objects that the name of the ContainerDoc has changed. +*/ +void ContainerDoc_InformAllOleObjectsDocRenamed( + LPCONTAINERDOC lpContainerDoc, + LPMONIKER lpmkDoc +) +{ + LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList; + int i; + LPLINE lpLine; + + for (i = 0; i < lpLL->m_nNumLines; i++) { + lpLine=LineList_GetLine(lpLL, i); + + if (lpLine && (Line_GetLineType(lpLine)==CONTAINERLINETYPE)) { + LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)lpLine; + + /* OLE2NOTE: if the OLE object is already loaded AND the + ** object already has a moniker assigned, then we need + ** to inform it that the moniker of the ContainerDoc has + ** changed. of course, this means the full moniker of + ** the object has changed. to do this we call + ** IOleObject::SetMoniker. this will force the OLE + ** object to re-register in the RunningObjectTable if it + ** is currently in the running state. it is not in the + ** running state, the object handler can make not that + ** the object has a new moniker. if the object is not + ** currently loaded, SetMoniker will be called + ** automatically later when the object is loaded by the + ** function ContainerLine_LoadOleObject. + ** also if the object is a linked object, we always want + ** to call SetMoniker on the link so that in case the + ** link source is contained within our same container, + ** the link source will be tracked. the link rebuilds + ** its absolute moniker if it has a relative moniker. + */ + if (lpContainerLine->m_lpOleObj) { + if (lpContainerLine->m_fMonikerAssigned || + lpContainerLine->m_dwLinkType != 0) { + OLEDBG_BEGIN2("IOleObject::SetMoniker called\r\n") + lpContainerLine->m_lpOleObj->lpVtbl->SetMoniker( + lpContainerLine->m_lpOleObj, + OLEWHICHMK_CONTAINER, + lpmkDoc + ); + OLEDBG_END2 + } + + /* OLE2NOTE: we must call IOleObject::SetHostNames so + ** any open objects can update their window titles. + */ + OLEDBG_BEGIN2("IOleObject::SetHostNames called\r\n") + + CallIOleObjectSetHostNamesA( + lpContainerLine->m_lpOleObj, + APPNAME, + ((LPOUTLINEDOC)lpContainerDoc)->m_lpszDocTitle + ); + + OLEDBG_END2 + } + } + } +} + + +/* ContainerDoc_GetObject +** ---------------------- +** Return a pointer to the desired interface of an object identified +** by an item string (lpszItem). the object returned will be an OLE +** object (either link or embedding). +** +** OLE2NOTE: we must force the object to run because we are +** REQUIRED to return a pointer the OLE object in the +** RUNNING state. +** +** dwSpeedNeeded indicates how long the caller is willing +** to wait for us to get the object: +** BINDSPEED_IMMEDIATE -- only if obj already loaded && IsRunning +** BINDSPEED_MODERATE -- load obj if necessary && if IsRunning +** BINDSPEED_INDEFINITE-- force obj to load and run if necessary +*/ +HRESULT ContainerDoc_GetObjectA( + LPCONTAINERDOC lpContainerDoc, + LPSTR lpszItem, + DWORD dwSpeedNeeded, + REFIID riid, + LPVOID FAR* lplpvObject +) +{ + LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList; + int i; + LPLINE lpLine; + BOOL fMatchFound = FALSE; + DWORD dwStatus; + HRESULT hrErr; + + *lplpvObject = NULL; + + for (i = 0; i < lpLL->m_nNumLines; i++) { + lpLine=LineList_GetLine(lpLL, i); + + if (lpLine && (Line_GetLineType(lpLine)==CONTAINERLINETYPE)) { + LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)lpLine; + + if (lstrcmp(lpContainerLine->m_szStgName, lpszItem) == 0) { + + fMatchFound = TRUE; // valid item name + + // check if object is loaded. + if (lpContainerLine->m_lpOleObj == NULL) { + + // if BINDSPEED_IMMEDIATE is requested, object must + // ALREADY be loadded. + if (dwSpeedNeeded == BINDSPEED_IMMEDIATE) + return ResultFromScode(MK_E_EXCEEDEDDEADLINE); + + ContainerLine_LoadOleObject(lpContainerLine); + if (! lpContainerLine->m_lpOleObj) + return ResultFromScode(E_OUTOFMEMORY); + } + + /* OLE2NOTE: check if the object is allowed to be linked + ** to from the inside (ie. we are allowed to + ** give out a moniker which binds to the running + ** OLE object). if the object is an OLE + ** 2.0 embedded object then it is allowed to be + ** linked to from the inside. if the object is + ** either an OleLink or an OLE 1.0 embedding + ** then it can not be linked to from the inside. + ** if we were a container/server app then we + ** could offer linking to the outside of the + ** object (ie. a pseudo object within our + ** document). we are a container only app that + ** does not support linking to ranges of its data. + */ + OLEDBG_BEGIN2("IOleObject::GetMiscStatus called\r\n"); + lpContainerLine->m_lpOleObj->lpVtbl->GetMiscStatus( + lpContainerLine->m_lpOleObj, + DVASPECT_CONTENT, /* aspect is not important */ + (LPDWORD)&dwStatus + ); + OLEDBG_END2 + if (dwStatus & OLEMISC_CANTLINKINSIDE) + return ResultFromScode(MK_E_NOOBJECT); + + // check if object is running. + if (! OleIsRunning(lpContainerLine->m_lpOleObj)) { + + // if BINDSPEED_MODERATE is requested, object must + // ALREADY be running. + if (dwSpeedNeeded == BINDSPEED_MODERATE) + return ResultFromScode(MK_E_EXCEEDEDDEADLINE); + + /* OLE2NOTE: we have found a match for the item name. + ** now we must return a pointer to the desired + ** interface on the RUNNING object. we must + ** carefully load the object and initially ask for + ** an interface that we are sure the loaded form of + ** the object supports. if we immediately ask the + ** loaded object for the desired interface, the + ** QueryInterface call might fail if it is an + ** interface that is supported only when the object + ** is running. thus we force the object to load and + ** return its IUnknown*. then we force the object to + ** run, and then finally, we can ask for the + ** actually requested interface. + */ + hrErr = ContainerLine_RunOleObject(lpContainerLine); + if (hrErr != NOERROR) { + return hrErr; + } + } + + // Retrieve the requested interface + *lplpvObject = OleStdQueryInterface( + (LPUNKNOWN)lpContainerLine->m_lpOleObj, riid); + + break; // Match FOUND! + } + } + } + + if (*lplpvObject != NULL) { + return NOERROR; + } else + return (fMatchFound ? ResultFromScode(E_NOINTERFACE) + : ResultFromScode(MK_E_NOOBJECT)); +} + + +HRESULT ContainerDoc_GetObject( + LPCONTAINERDOC lpContainerDoc, + LPOLESTR lpszItem, + DWORD dwSpeedNeeded, + REFIID riid, + LPVOID FAR* lplpvObject +) +{ + CREATESTR(lpsz, lpszItem) + + HRESULT hr = ContainerDoc_GetObjectA(lpContainerDoc, lpsz, dwSpeedNeeded, + riid, lplpvObject); + + FREESTR(lpsz) + + return hr; +} + +/* ContainerDoc_GetObjectStorage +** ----------------------------- +** Return a pointer to the IStorage* used by the object identified +** by an item string (lpszItem). the object identified could be either +** an OLE object (either link or embedding). +*/ +HRESULT ContainerDoc_GetObjectStorageA( + LPCONTAINERDOC lpContainerDoc, + LPSTR lpszItem, + LPSTORAGE FAR* lplpStg +) +{ + LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList; + int i; + LPLINE lpLine; + + *lplpStg = NULL; + + for (i = 0; i < lpLL->m_nNumLines; i++) { + lpLine=LineList_GetLine(lpLL, i); + + if (lpLine && (Line_GetLineType(lpLine)==CONTAINERLINETYPE)) { + LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)lpLine; + + if (lstrcmp(lpContainerLine->m_szStgName, lpszItem) == 0) { + + *lplpStg = lpContainerLine->m_lpStg; + break; // Match FOUND! + } + } + } + + if (*lplpStg != NULL) { + return NOERROR; + } else + return ResultFromScode(MK_E_NOOBJECT); +} + +HRESULT ContainerDoc_GetObjectStorage( + LPCONTAINERDOC lpContainerDoc, + LPOLESTR lpszItem, + LPSTORAGE FAR* lplpStg +) +{ + CREATESTR(lpsz, lpszItem) + + HRESULT hr = ContainerDoc_GetObjectStorageA(lpContainerDoc, lpsz, lplpStg); + + FREESTR(lpsz) + + return hr; +} + +/* ContainerDoc_IsRunning +** ---------------------- +** Check if the object identified by an item string (lpszItem) is in +** the running state. +** For a container-only app, a check is made if the OLE object +** associated with the item name is running. +*/ +HRESULT ContainerDoc_IsRunningA(LPCONTAINERDOC lpContainerDoc, LPSTR lpszItem) +{ + LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList; + int i; + LPLINE lpLine; + DWORD dwStatus; + + for (i = 0; i < lpLL->m_nNumLines; i++) { + lpLine=LineList_GetLine(lpLL, i); + + if (lpLine && (Line_GetLineType(lpLine)==CONTAINERLINETYPE)) { + LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)lpLine; + + if (lstrcmp(lpContainerLine->m_szStgName, lpszItem) == 0) { + + /* OLE2NOTE: we have found a match for the item name. + ** now we must check if the OLE object is running. + ** we will load the object if not already loaded. + */ + if (! lpContainerLine->m_lpOleObj) { + ContainerLine_LoadOleObject(lpContainerLine); + if (! lpContainerLine->m_lpOleObj) + return ResultFromScode(E_OUTOFMEMORY); + } + + /* OLE2NOTE: check if the object is allowed to be linked + ** to from the inside (ie. we are allowed to + ** give out a moniker which binds to the running + ** OLE object). if the object is an OLE + ** 2.0 embedded object then it is allowed to be + ** linked to from the inside. if the object is + ** either an OleLink or an OLE 1.0 embedding + ** then it can not be linked to from the inside. + ** if we were a container/server app then we + ** could offer linking to the outside of the + ** object (ie. a pseudo object within our + ** document). we are a container only app that + ** does not support linking to ranges of its data. + */ + OLEDBG_BEGIN2("IOleObject::GetMiscStatus called\r\n") + lpContainerLine->m_lpOleObj->lpVtbl->GetMiscStatus( + lpContainerLine->m_lpOleObj, + DVASPECT_CONTENT, /* aspect is not important */ + (LPDWORD)&dwStatus + ); + OLEDBG_END2 + if (dwStatus & OLEMISC_CANTLINKINSIDE) + return ResultFromScode(MK_E_NOOBJECT); + + if (OleIsRunning(lpContainerLine->m_lpOleObj)) + return NOERROR; + else + return ResultFromScode(S_FALSE); + } + } + } + + // no object was found corresponding to the item name + return ResultFromScode(MK_E_NOOBJECT); +} + +HRESULT ContainerDoc_IsRunning(LPCONTAINERDOC lpContainerDoc, LPOLESTR lpszItem) +{ + CREATESTR(lpsz, lpszItem) + + HRESULT hr = ContainerDoc_IsRunningA(lpContainerDoc, lpsz); + + FREESTR(lpsz) + + return hr; +} + +#endif // OLE_CNTR diff --git a/private/oleutest/letest/outline/main.c b/private/oleutest/letest/outline/main.c new file mode 100644 index 000000000..58ba4b773 --- /dev/null +++ b/private/oleutest/letest/outline/main.c @@ -0,0 +1,2488 @@ +/************************************************************************* +** +** OLE 2 Sample Code +** +** main.c +** +** This file contains initialization functions which are WinMain, +** WndProc, and OutlineApp_InitalizeMenu. +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + +#include "outline.h" +#if defined( USE_STATUSBAR ) +#include "status.h" +#endif + +#if !defined( WIN32 ) +#if defined( USE_CTL3D ) +#include "ctl3d.h" +#endif // USE_CTL3D +#endif // !WIN32 + +#include "initguid.h" // forces our GUIDs to be initialized +#include "defguid.h" + +// OLETEST driver window handler +HWND g_hwndDriver; + +#if defined( OLE_CNTR ) +//************************************************************************* + +#if defined( INPLACE_CNTR ) +OLEDBGDATA_MAIN("ICNTR") +#else +OLEDBGDATA_MAIN("CNTR") +#endif + + +CONTAINERAPP g_OutlineApp; // Global App object maintains app instance state + +/* Global interface Vtbl's + * OLE2NOTE: we only need one copy of each Vtbl. When an object which + * exposes an interface is instantiated, its lpVtbl is intialized + * to point to one of these global Vtbl's. + */ +IUnknownVtbl g_OleApp_UnknownVtbl; +IClassFactoryVtbl g_OleApp_ClassFactoryVtbl; +IMessageFilterVtbl g_OleApp_MessageFilterVtbl; + +IUnknownVtbl g_OleDoc_UnknownVtbl; +IPersistFileVtbl g_OleDoc_PersistFileVtbl; +IOleItemContainerVtbl g_OleDoc_OleItemContainerVtbl; +IExternalConnectionVtbl g_OleDoc_ExternalConnectionVtbl; +IDataObjectVtbl g_OleDoc_DataObjectVtbl; + +#if defined( USE_DRAGDROP ) +IDropSourceVtbl g_OleDoc_DropSourceVtbl; +IDropTargetVtbl g_OleDoc_DropTargetVtbl; +#endif // USE_DRAGDROP + +IOleUILinkContainerVtbl g_CntrDoc_OleUILinkContainerVtbl; + +IOleClientSiteVtbl g_CntrLine_UnknownVtbl; +IOleClientSiteVtbl g_CntrLine_OleClientSiteVtbl; +IAdviseSinkVtbl g_CntrLine_AdviseSinkVtbl; + +#if defined( INPLACE_CNTR ) +IOleInPlaceSiteVtbl g_CntrLine_OleInPlaceSiteVtbl; +IOleInPlaceFrameVtbl g_CntrApp_OleInPlaceFrameVtbl; +BOOL g_fInsideOutContainer = FALSE; // default to outside-in activation +#endif // INPLACE_CNTR + +//************************************************************************* +#endif // OLE_CNTR + +#if defined( OLE_SERVER ) +//************************************************************************* + +#if defined( INPLACE_SVR ) +OLEDBGDATA_MAIN("ISVR") +#else +OLEDBGDATA_MAIN("SVR") +#endif + +SERVERAPP g_OutlineApp; // Global App object maintains app instance state + +/* Global interface Vtbl's + * OLE2NOTE: we only need one copy of each Vtbl. When an object which + * exposes an interface is instantiated, its lpVtbl is intialized + * to point to one of these global Vtbl's. + */ +IUnknownVtbl g_OleApp_UnknownVtbl; +IClassFactoryVtbl g_OleApp_ClassFactoryVtbl; +IMessageFilterVtbl g_OleApp_MessageFilterVtbl; + +IUnknownVtbl g_OleDoc_UnknownVtbl; +IPersistFileVtbl g_OleDoc_PersistFileVtbl; +IOleItemContainerVtbl g_OleDoc_OleItemContainerVtbl; +IExternalConnectionVtbl g_OleDoc_ExternalConnectionVtbl; +IDataObjectVtbl g_OleDoc_DataObjectVtbl; + +#if defined( USE_DRAGDROP ) +IDropSourceVtbl g_OleDoc_DropSourceVtbl; +IDropTargetVtbl g_OleDoc_DropTargetVtbl; +#endif // USE_DRAGDROP + +IOleObjectVtbl g_SvrDoc_OleObjectVtbl; +IPersistStorageVtbl g_SvrDoc_PersistStorageVtbl; + +#if defined( SVR_TREATAS ) +IStdMarshalInfoVtbl g_SvrDoc_StdMarshalInfoVtbl; +#endif // SVR_TREATAS + +#if defined( INPLACE_SVR ) +IOleInPlaceObjectVtbl g_SvrDoc_OleInPlaceObjectVtbl; +IOleInPlaceActiveObjectVtbl g_SvrDoc_OleInPlaceActiveObjectVtbl; +#endif // INPLACE_SVR + +IUnknownVtbl g_PseudoObj_UnknownVtbl; +IOleObjectVtbl g_PseudoObj_OleObjectVtbl; +IDataObjectVtbl g_PseudoObj_DataObjectVtbl; + +//************************************************************************* +#endif // OLE_SVR + +#if !defined( OLE_VERSION ) +OLEDBGDATA_MAIN("OUTL") +OUTLINEAPP g_OutlineApp; // Global App object maintains app instance state +#endif + +LPOUTLINEAPP g_lpApp=(LPOUTLINEAPP)&g_OutlineApp; // ptr to global app obj +RECT g_rectNull = {0, 0, 0, 0}; +UINT g_uMsgHelp = 0; // help msg from ole2ui dialogs +BOOL g_fAppActive = FALSE; + +/* WinMain +** ------- +** Main routine for the Windows application. +*/ +int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, + LPSTR lpszCmdLine, int nCmdShow) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + MSG msg; /* MSG structure to store your messages */ + LPSTR pszTemp; + +#if defined( OLE_VERSION ) + /* OLE2NOTE: it is recommended that all OLE applications to set + ** their message queue size to 96. this improves the capacity + ** and performance of OLE's LRPC mechanism. + */ + int cMsg = 96; // recommend msg queue size for OLE + while (cMsg && ! SetMessageQueue(cMsg)) // take largest size we can get. + cMsg -= 8; + if (! cMsg) + return -1; // ERROR: we got no message queue +#endif + +#if defined( USE_CTL3D ) + Ctl3dRegister(hInstance); + Ctl3dAutoSubclass(hInstance); +#endif + + if(! hPrevInstance) { + /* register window classes if first instance of application */ + if(! OutlineApp_InitApplication(lpOutlineApp, hInstance)) + return 0; + } + + /* Create App Frame window */ + if (! OutlineApp_InitInstance(lpOutlineApp, hInstance, nCmdShow)) + return 0; + + if( (pszTemp = strstr(lpszCmdLine, "-driver")) ) + { + //we were launched by the test driver + g_hwndDriver = (HWND)strtoul(pszTemp+8, &lpszCmdLine, 10); + } + else + { + g_hwndDriver = NULL; + } + + if (! OutlineApp_ParseCmdLine(lpOutlineApp, lpszCmdLine, nCmdShow)) + return 0; + + lpOutlineApp->m_hAccelApp = LoadAccelerators(hInstance, APPACCEL); + lpOutlineApp->m_hAccelFocusEdit = LoadAccelerators(hInstance, + FB_EDIT_ACCEL); + lpOutlineApp->m_hAccel = lpOutlineApp->m_hAccelApp; + lpOutlineApp->m_hWndAccelTarget = lpOutlineApp->m_hWndApp; + + if( g_hwndDriver ) + { + PostMessage(g_hwndDriver, WM_TESTREG, + (WPARAM)lpOutlineApp->m_hWndApp, 0); + } + + // Main message loop + while(GetMessage(&msg, NULL, 0, 0)) { /* Until WM_QUIT message */ + if(!MyTranslateAccelerator(&msg)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + +#if defined( OLE_VERSION ) + OleApp_TerminateApplication((LPOLEAPP)lpOutlineApp); +#else + /* OLE2NOTE: CoInitialize() is called in OutlineApp_InitInstance + ** and therefore we need to uninitialize it when exit. + */ + CoUninitialize(); +#endif + +#if defined( USE_CTL3D ) + Ctl3dUnregister(hInstance); +#endif + + return msg.wParam; + +} /* End of WinMain */ + +BOOL MyTranslateAccelerator(LPMSG lpmsg) +{ + // if it's not a keystroke it can not be an accelerator + if (lpmsg->message < WM_KEYFIRST || lpmsg->message > WM_KEYLAST) + return FALSE; + + if (g_lpApp->m_hWndAccelTarget && + TranslateAccelerator(g_lpApp->m_hWndAccelTarget, + g_lpApp->m_hAccel,lpmsg)) + return TRUE; + +#if defined( INPLACE_SVR ) + /* OLE2NOTE: if we are in-place active and we did not translate the + ** accelerator, we need to give the top-level (frame) in-place + ** container a chance to translate the accelerator. + ** we ONLY need to call OleTranslateAccelerator API if the + ** message is a keyboard message. otherwise it is harmless but + ** unnecessary. + ** + ** NOTE: even a in-place server that does NOT have any + ** Accelerators must still call OleTranslateAccelerator for all + ** keyboard messages so that the server's OWN menu mneumonics + ** (eg. &Edit -- Alt-e) function properly. + ** + ** NOTE: an in-place server MUST check that the accelerator is + ** NOT one of its own accelerators BEFORE calling + ** OleTranslateAccelerator which tries to see if it is a + ** container accelerator. if this is a server accelerator that + ** was not translateed because the associated menu command was + ** disabled, we MUST NOT call OleTranslateAccelerator. The + ** IsAccelerator helper API has been added to assist with this + ** check. + */ + if (g_OutlineApp.m_lpIPData && + !IsAccelerator(g_lpApp->m_hAccel, + GetAccelItemCount(g_lpApp->m_hAccel), lpmsg,NULL) && + OleTranslateAccelerator(g_OutlineApp.m_lpIPData->lpFrame, + (LPOLEINPLACEFRAMEINFO)&g_OutlineApp.m_lpIPData->frameInfo, + lpmsg) == NOERROR) { + return TRUE; + } +#endif + + return FALSE; +} + + +/************************************************************************/ +/* */ +/* Main Window Procedure */ +/* */ +/* This procedure provides service routines for the Windows events */ +/* (messages) that Windows sends to the window, as well as the user */ +/* initiated events (messages) that are generated when the user selects */ +/* the action bar and pulldown menu controls or the corresponding */ +/* keyboard accelerators. */ +/* */ +/************************************************************************/ + +LRESULT FAR PASCAL AppWndProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)GetWindowLong(hWnd, 0); + LPOUTLINEDOC lpOutlineDoc = NULL; +#if defined( OLE_VERSION ) + LPOLEAPP lpOleApp = (LPOLEAPP)lpOutlineApp; +#endif +#if defined( OLE_CNTR ) + LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)lpOutlineApp; +#endif + HWND hWndDoc = NULL; + +#if defined( USE_FRAMETOOLS ) + LPFRAMETOOLS lptb = OutlineApp_GetFrameTools(lpOutlineApp); +#endif + + if (lpOutlineApp) { + lpOutlineDoc = OutlineApp_GetActiveDoc(lpOutlineApp); + + if (lpOutlineDoc) + hWndDoc = OutlineDoc_GetWindow(lpOutlineDoc); + } + + switch (Message) { + case WM_TEST1: + StartClipboardTest1(lpOutlineApp); + break; + case WM_TEST2: + ContinueClipboardTest1(lpOutlineApp); + break; + case WM_COMMAND: + { +#ifdef WIN32 + WORD wID = LOWORD(wParam); +#else + WORD wID = wParam; +#endif + +#if defined( INPLACE_CNTR ) + LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOutlineDoc; + LPOLEDOC lpOleDoc = (LPOLEDOC)lpOutlineDoc; + + /* OLE2NOTE: see context sensitive help technote (CSHELP.DOC) + ** m_fMenuHelpMode flag is set when F1 is pressed when a + ** menu item is selected. this flag is set in + ** IOleInPlaceFrame::ContextSensitveHelp method. + ** m_fCSHelpMode flag is set when SHIFT-F1 context + ** sensitive help is entered. this flag is set in + ** IOleInPlaceSite::ContextSensitiveHelp method. + ** if either of these flags are set then the WM_COMMAND + ** message is received then, the corresponding command + ** should NOT executed; help can be given (if desired). + ** also the context sensitve help mode should be exited. + ** the two different cases have their own way to exit + ** the mode (please refer to the technote). + */ + if (lpOleDoc && + (lpContainerApp->m_fMenuHelpMode||lpOleDoc->m_fCSHelpMode) && + (wID > IDM_FILE) /* min wID for app command */ && + (wID!=IDM_FB_EDIT) /* special wID to control FormulaBar */ ) { + + if ((lpContainerApp->m_fMenuHelpMode)) { + LPOLEINPLACEACTIVEOBJECT lpIPActiveObj = + lpContainerApp->m_lpIPActiveObj; + + lpContainerApp->m_fMenuHelpMode = FALSE; + + // inform the in-place active object that we handled the + // menu help mode (F1) selection. + if (lpIPActiveObj) { + OLEDBG_BEGIN2("IOleInPlaceActiveObject::ContextSensitiveHelp(FALSE) called\r\n") + lpIPActiveObj->lpVtbl->ContextSensitiveHelp( + lpIPActiveObj, FALSE); + OLEDBG_END2 + } + } + + if ((lpOleDoc->m_fCSHelpMode)) { + LPOLEINPLACEOBJECT lpIPObj; + LPCONTAINERLINE lpLastIpActiveLine = + lpContainerDoc->m_lpLastIpActiveLine; + + lpOleDoc->m_fCSHelpMode = FALSE; + + /* inform immediate in-place container parent and, + ** if we were a container/server, immediate + ** in-place object children that we handled the + ** context sensitive help mode. + */ + if (lpLastIpActiveLine && + (lpIPObj=lpLastIpActiveLine->m_lpOleIPObj)!=NULL){ + OLEDBG_BEGIN2("IOleInPlaceObject::ContextSensitiveHelp(FALSE) called\r\n") + lpIPObj->lpVtbl->ContextSensitiveHelp(lpIPObj, FALSE); + OLEDBG_END2 + } + } + + // if we provided help, we would do it here... + + // remove context sensitive help cursor + SetCursor(LoadCursor(NULL,IDC_ARROW)); + return 0L; + } +#endif // INPLACE_CNTR + + switch (wID) { + + case IDM_F_NEW: + OleDbgIndent(-2); // Reset debug output indent level + OleDbgOutNoPrefix2("\r\n"); + + OLEDBG_BEGIN3("OutlineApp_NewCommand\r\n") + OutlineApp_NewCommand(lpOutlineApp); + OLEDBG_END3 + +#if defined( OLE_CNTR ) + /* OLE2NOTE: this call will attempt to recover + ** resources by unloading DLL's that were loaded + ** by OLE and are no longer being used. it is a + ** good idea to call this API now and then if + ** your app tends to run for a long time. + ** otherwise these DLL's will be unloaded when + ** the app exits. some apps may want to call + ** this as part of idle-time processing. this + ** call is optional. + */ + OLEDBG_BEGIN2("CoFreeUnusedLibraries called\r\n") + CoFreeUnusedLibraries(); + OLEDBG_END2 +#endif + +#if defined( USE_FRAMETOOLS ) + OutlineDoc_UpdateFrameToolButtons( + OutlineApp_GetActiveDoc(lpOutlineApp)); +#endif + break; + + case IDM_F_OPEN: + OleDbgOutNoPrefix2("\r\n"); + + OLEDBG_BEGIN3("OutlineApp_OpenCommand\r\n") + OutlineApp_OpenCommand(lpOutlineApp); + OLEDBG_END3 + +#if defined( OLE_CNTR ) + /* OLE2NOTE: this call will attempt to recover + ** resources by unloading DLL's that were loaded + ** by OLE and are no longer being used. it is a + ** good idea to call this API now and then if + ** your app tends to run for a long time. + ** otherwise these DLL's will be unloaded when + ** the app exits. some apps may want to call + ** this as part of idle-time processing. this + ** call is optional. + */ + OLEDBG_BEGIN2("CoFreeUnusedLibraries called\r\n") + CoFreeUnusedLibraries(); + OLEDBG_END2 +#endif + +#if defined( USE_FRAMETOOLS ) + OutlineDoc_UpdateFrameToolButtons( + OutlineApp_GetActiveDoc(lpOutlineApp)); +#endif + break; + + case IDM_F_SAVE: + OleDbgOutNoPrefix2("\r\n"); + + OLEDBG_BEGIN3("OutlineApp_SaveCommand\r\n") + OutlineApp_SaveCommand(lpOutlineApp); + OLEDBG_END3 + break; + + case IDM_F_SAVEAS: + OleDbgOutNoPrefix2("\r\n"); + + OLEDBG_BEGIN3("OutlineApp_SaveAsCommand\r\n") + OutlineApp_SaveAsCommand(lpOutlineApp); + OLEDBG_END3 + break; + + case IDM_F_PRINT: + OleDbgOutNoPrefix2("\r\n"); + + OLEDBG_BEGIN3("OutlineApp_PrintCommand\r\n") + OutlineApp_PrintCommand(lpOutlineApp); + OLEDBG_END3 + break; + + case IDM_F_PRINTERSETUP: + OleDbgOutNoPrefix2("\r\n"); + + OLEDBG_BEGIN3("OutlineApp_PrinterSetupCommand\r\n") + OutlineApp_PrinterSetupCommand(lpOutlineApp); + OLEDBG_END3 + break; + + case IDM_F_EXIT: + SendMessage(hWnd, WM_CLOSE, 0, 0L); + break; + + case IDM_H_ABOUT: + OutlineApp_AboutCommand(lpOutlineApp); + break; + +#if defined( INPLACE_CNTR ) + case IDM_ESCAPE: + { + /* ESCAPE key pressed */ + LPCONTAINERDOC lpContainerDoc = + (LPCONTAINERDOC)lpOutlineDoc; + + /* OLE2NOTE: The standard OLE 2.0 UI convention + ** is to have ESCAPE key exit in-place + ** activation (ie. UIDeactivate). If + ** possible it is recommended for both + ** in-place servers AND in-place containers + ** to take responsibility to handle the + ** ESCAPE key accelerator. The server has + ** the first crack at handling accelerator + ** keys and normally the server should do + ** the UIDeactivation. It is a good idea for + ** in-place containers, in order to + ** guarantee consistent behavior, to also + ** handle the ESCAPE key and UIDeactivate + ** the object in case the object does not do + ** it itself. normally this should be + ** unnecessary. + */ + if (lpContainerDoc->m_lpLastUIActiveLine && + lpContainerDoc->m_lpLastUIActiveLine->m_fUIActive) + { + ContainerLine_UIDeactivate( + lpContainerDoc->m_lpLastUIActiveLine); + } + break; + } +#endif // INPLACE_CNTR + + + default: + // forward message to document window + if (hWndDoc) { + return DocWndProc(hWndDoc, Message,wParam,lParam); + } + } + + break; /* End of WM_COMMAND */ + } + + case WM_INITMENU: + OutlineApp_InitMenu(lpOutlineApp, lpOutlineDoc, (HMENU)wParam); + break; + +#if defined( OLE_VERSION ) + + /* OLE2NOTE: WM_INITMENUPOPUP is trapped primarily for the Edit + ** menu. We didn't update the Edit menu until it is popped + ** up to avoid the overheads of the OLE calls which are + ** required to initialize some Edit menu items. + */ + case WM_INITMENUPOPUP: + { + HMENU hMenuEdit = GetSubMenu(lpOutlineApp->m_hMenuApp, 1); +#if defined( INPLACE_CNTR ) + LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOutlineDoc; + + /* OLE2NOTE: we must check if there is an object currently + ** in-place UIActive. if so, then our edit menu is not + ** on the menu; we do not want to bother updating the + ** edit menu when it is not even there. + */ + if (lpContainerDoc && lpContainerDoc->m_lpLastUIActiveLine && + lpContainerDoc->m_lpLastUIActiveLine->m_fUIActive) + break; // an object is in-place UI active +#endif + if ((HMENU)wParam == hMenuEdit && + (LOWORD(lParam) == POS_EDITMENU) && + OleDoc_GetUpdateEditMenuFlag((LPOLEDOC)lpOutlineDoc)) { + OleApp_UpdateEditMenu(lpOleApp, lpOutlineDoc, hMenuEdit); + } + break; + } +#endif // OLE_VERSION + + case WM_SIZE: + if (wParam != SIZE_MINIMIZED) + OutlineApp_ResizeWindows(lpOutlineApp); + break; + + + case WM_ACTIVATEAPP: +#if defined (OLE_CNTR) + if (g_fAppActive = (BOOL) wParam) + OleApp_QueryNewPalette(lpOleApp); +#endif + +#if defined( INPLACE_CNTR ) + { + BOOL fActivate = (BOOL)wParam; + LPOLEINPLACEACTIVEOBJECT lpIPActiveObj = + lpContainerApp->m_lpIPActiveObj; + + /* OLE2NOTE: the in-place container MUST inform the + ** inner most in-place active object (this is NOT + ** necessarily our immediate child if there are + ** nested levels of embedding) of the WM_ACTIVATEAPP + ** status. + */ + if (lpIPActiveObj) { +#if defined( _DEBUG ) + OLEDBG_BEGIN2((fActivate ? + "IOleInPlaceActiveObject::OnFrameWindowActivate(TRUE) called\r\n" : + "IOleInPlaceActiveObject::OnFrameWindowActivate(FALSE) called\r\n")) +#endif // _DEUBG + lpIPActiveObj->lpVtbl->OnFrameWindowActivate( + lpIPActiveObj, fActivate); + OLEDBG_END2 + } + } + +#endif // INPLACE_CNTR + + // OLE2NOTE: We can't call OutlineDoc_UpdateFrameToolButtons + // right away which + // would generate some OLE calls and eventually + // WM_ACTIVATEAPP and a loop was formed. Therefore, we + // should delay the frame tool initialization until + // WM_ACTIVATEAPP is finished by posting a message + // to ourselves. + // we want to ignore the WM_ACTIVATEAPP that comes + // as we bring up a modal dialog. + + /* Update enable/disable state of buttons in toolbar */ + if (wParam +#if defined( OLE_VERSION ) + && lpOleApp->m_cModalDlgActive == 0 +#endif + ) { + PostMessage(hWnd, WM_U_INITFRAMETOOLS, 0, 0L); + } + return 0L; + + case WM_SETFOCUS: + SetFocus(hWndDoc); + break; + + +#if defined( OLE_CNTR ) + case WM_QUERYNEWPALETTE: + if (!g_fAppActive) + return 0L; + + return OleApp_QueryNewPalette(lpOleApp); + + case WM_PALETTECHANGED: + { + HWND hWndPalChg = (HWND) wParam; + static BOOL fInPaletteChanged = FALSE; + + if (fInPaletteChanged) // Guard against recursion + return 0L; + + fInPaletteChanged = TRUE; + + if (hWnd != hWndPalChg) + wSelectPalette(hWnd, lpOleApp->m_hStdPal,TRUE/*fBackground*/); + +#if defined( INPLACE_CNTR ) + /* OLE2NOTE: always forward the WM_PALETTECHANGED message (via + ** SendMessage) to any in-place objects that currently have + ** their window visible. this gives these objects the chance + ** to select their palettes. this is + ** REQUIRED by all in-place containers independent of + ** whether they use color palettes themselves--their objects + ** may use color palettes. + ** (see ContainerDoc_ForwardPaletteChangedMsg for more info) + */ + if (lpOutlineDoc){ + ContainerDoc_ForwardPaletteChangedMsg( + (LPCONTAINERDOC)lpOutlineDoc, hWndPalChg); + } +#endif // INPLACE_CNTR + + fInPaletteChanged = FALSE; + return 0L; + } +#endif // OLE_CNTR + + case WM_DESTROY: + PostQuitMessage(0); + break; + + case WM_CLOSE: /* close the window */ + + /* Close all active documents. if successful, then exit */ + OleDbgOutNoPrefix2("\r\n"); + + OutlineApp_CloseAllDocsAndExitCommand(lpOutlineApp, FALSE); + break; + + case WM_QUERYENDSESSION: + { +#if defined( OLE_CNTR ) + /* OLE2NOTE: we are not able to make OLE LRPC calls when + ** WM_QUERYENDSESSION is recieved (this is a + ** SendMessage). this means, for example, that we are + ** NOT able to ask objects to save. thus the most we can + ** do is ask the user if he wants to exit with + ** discarding changes or else abort shutting down. + */ + + int nResponse = MessageBox( + hWnd, + "Discard changes?", + APPNAME, + MB_ICONQUESTION | MB_OKCANCEL + ); + if(nResponse == IDOK) + return 1L; /* can terminate */ + +#endif +#if defined( OLE_SERVER ) + /* OLE2NOTE: an embedded object should never prompt whether + ** it should be saved (according the OLE 2.0 User + ** Model). therefore, an embedded object will never + ** complain that it needs to be saved. it will always + ** allow the QueryEndSession to proceed. + */ + if (lpOutlineApp->m_lpDoc->m_docInitType == DOCTYPE_EMBEDDED) + return 1L; /* can terminate */ + else +#endif + { + /* this is not an embedded object; it is a user + ** document. we will prompt if the user wants to + ** save the document now in WM_QUERYENDSESSION. if + ** the user cancels then that would abort the + ** shutdown. if the user does not abort, then later + ** in WM_ENDSESSION the document will be actually + ** closed. + ** + ** Because this is an SDI app, there is only one + ** document. An MDI would need to loop through all + ** open documents. + */ + DWORD dwSaveOption = OLECLOSE_PROMPTSAVE; + if (OutlineDoc_CheckSaveChanges( + lpOutlineApp->m_lpDoc, &dwSaveOption)) + return 1L; /* can terminate */ + } + + /* else: can't terminate now */ + + break; + } + +#if defined( OLE_VERSION) + case WM_ENDSESSION: + { + BOOL fEndSession = (BOOL)wParam; + + if (fEndSession) { + OutlineApp_CloseAllDocsAndExitCommand(lpOutlineApp, TRUE); + return 0L; + } + } + break; +#endif // OLE_VERSION + + +#if defined( USE_STATUSBAR ) + case WM_MENUSELECT: + { + LPSTR lpszMessage; +#ifdef WIN32 + UINT fuFlags = (UINT)HIWORD(wParam); + UINT uItem = (UINT)LOWORD(wParam); +#else + UINT fuFlags = (UINT)LOWORD(lParam); + UINT uItem = (UINT)wParam; +#endif + + if (uItem == 0 && fuFlags == (UINT)-1) { + GetControlMessage(STATUS_READY, &lpszMessage); + OutlineApp_SetStatusText(lpOutlineApp, lpszMessage); + } + else if (fuFlags & MF_POPUP) { +#ifdef WIN32 + HMENU hMainMenu = (HMENU)lParam; + HMENU hPopupMenu = GetSubMenu(hMainMenu,uItem); +#else + HMENU hPopupMenu = (HMENU)wParam; +#endif + GetPopupMessage(hPopupMenu, &lpszMessage); + OutlineApp_SetStatusText(lpOutlineApp, lpszMessage); + } + else if (fuFlags & MF_SYSMENU) { + GetSysMenuMessage(uItem, &lpszMessage); + OutlineApp_SetStatusText(lpOutlineApp, lpszMessage); + } + else if (uItem != 0) { // Command Item + GetItemMessage(uItem, &lpszMessage); + OutlineApp_SetStatusText(lpOutlineApp, lpszMessage); + } + else { + GetControlMessage(STATUS_BLANK, &lpszMessage); + OutlineApp_SetStatusText(lpOutlineApp, lpszMessage); + } + break; + } +#endif // USE_STATUSBAR + + +#if defined( USE_FRAMETOOLS ) + case WM_U_INITFRAMETOOLS: + OutlineDoc_UpdateFrameToolButtons(lpOutlineDoc); + break; +#endif + + default: + /* For any message for which you don't specifically provide a */ + /* service routine, you should return the message to Windows */ + /* for default message processing. */ + + return DefWindowProc(hWnd, Message, wParam, lParam); + } + + return (LRESULT)0; +} /* End of AppWndProc */ + + +/************************************************************************/ +/* */ +/* Document Window Procedure */ +/* */ +/* The Document Window is the parent of the OwnerDraw Listbox which */ +/* maintains the list of lines in the current document. This window */ +/* receives the ownerdraw callback messages from the list box. */ +/************************************************************************/ + +LRESULT FAR PASCAL DocWndProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)GetWindowLong(hWnd, 0); + LPLINELIST lpLL = OutlineDoc_GetLineList(lpOutlineDoc); + LPSCALEFACTOR lpscale = OutlineDoc_GetScaleFactor(lpOutlineDoc); + +#if defined( OLE_VERSION ) + LPOLEAPP lpOleApp = (LPOLEAPP)lpOutlineApp; + LPOLEDOC lpOleDoc = (LPOLEDOC)lpOutlineDoc; +#if defined( OLE_CNTR ) + LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOutlineDoc; +#endif +#if defined( OLE_SERVER ) + LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOutlineDoc; +#endif +#if defined( INPLACE_CNTR ) + LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)lpOutlineApp; +#endif +#endif // OLE_VERSION + + switch(Message) { + +#if defined( INPLACE_SVR ) + + /* OLE2NOTE: ISVROTL doesn't use color palettes. The inplace objects + ** that use color palettes must implement the following + ** lines of code. + ** + case WM_QUERYNEWPALETTE: + return wSelectPalette(hWnd, hPal, FALSE); // foreground + + case WM_PALETTECHANGED: + if (hWnd != (HWND) wParam) + wSelectPalette(hWnd, hPal, TRUE); // background + break; + ** + ** + ** + */ +#endif + + case WM_MEASUREITEM: + { + LPMEASUREITEMSTRUCT lpmis = ((LPMEASUREITEMSTRUCT)lParam); + + switch (wParam) { + case IDC_LINELIST: + { + HDC hDC = LineList_GetDC(lpLL); + UINT uHeight; + + uHeight=Line_GetHeightInHimetric((LPLINE)lpmis->itemData); + uHeight = XformHeightInHimetricToPixels(hDC, uHeight); + uHeight = (UINT) (uHeight * lpscale->dwSyN / + lpscale->dwSyD); + + if (uHeight >LISTBOX_HEIGHT_LIMIT) + uHeight = LISTBOX_HEIGHT_LIMIT; + + lpmis->itemHeight = uHeight; + LineList_ReleaseDC(lpLL, hDC); + break; + } + + case IDC_NAMETABLE: + { + // NOTE: NameTable is never made visible. do nothing. + break; + } + +#if defined( USE_HEADING ) + case IDC_ROWHEADING: + { + UINT uHeight; + + uHeight = LOWORD(lpmis->itemData); + uHeight = (UINT) (uHeight * lpscale->dwSyN / + lpscale->dwSyD); + if (uHeight >LISTBOX_HEIGHT_LIMIT) + uHeight = LISTBOX_HEIGHT_LIMIT; + lpmis->itemHeight = uHeight; + break; + } + + case IDC_COLHEADING: + { + UINT uHeight; + + uHeight = LOWORD(lpmis->itemData); + uHeight = (UINT) (uHeight * lpscale->dwSyN / + lpscale->dwSyD); + if (uHeight > LISTBOX_HEIGHT_LIMIT) + uHeight = LISTBOX_HEIGHT_LIMIT; + lpmis->itemHeight = uHeight; + break; + } +#endif // USE_HEADING + + } + return (LRESULT)TRUE; + } + + case WM_DRAWITEM: + { + LPDRAWITEMSTRUCT lpdis = ((LPDRAWITEMSTRUCT)lParam); + + switch (lpdis->CtlID) { + + case IDC_LINELIST: + { + RECT rcClient; + RECT rcDevice; + HWND hWndLL = LineList_GetWindow(lpLL); + LPLINE lpLine = (LPLINE)lpdis->itemData; + + // NOTE: When itemID == -1, the listbox is empty. + // We are supposed to draw focus rect only + // But it is not done in this app. If this line is + // removed, the app will crash in Line_DrawToScreen + // because of invalid lpLine. + if (lpdis->itemID == -1) + break; + + GetClientRect(hWndLL, &rcClient); + + rcDevice = lpdis->rcItem; + + // shift the item rect to account for horizontal scrolling + + rcDevice.left += rcClient.right - lpdis->rcItem.right; + +#if defined( OLE_CNTR ) + /* we need to remember the horizontal scroll offset + ** needed for the in-place object's window. + ** (this is specific to ICNTROTL) + */ + if(lpdis->itemAction & ODA_DRAWENTIRE) { + if (Line_GetLineType(lpLine) == CONTAINERLINETYPE) + ((LPCONTAINERLINE)lpLine)->m_nHorizScrollShift = + rcDevice.left; + } +#endif // OLE_CNTR + + // shift rect for left margin + rcDevice.left += (int)(XformWidthInHimetricToPixels(NULL, + LOWORD(OutlineDoc_GetMargin(lpOutlineDoc))) * + lpscale->dwSxN / lpscale->dwSxD); + + rcDevice.right = rcDevice.left + + (int)(XformWidthInHimetricToPixels(lpdis->hDC, + Line_GetWidthInHimetric(lpLine)) * + lpscale->dwSxN / lpscale->dwSxD); + + Line_DrawToScreen( + lpLine, + lpdis->hDC, + &lpdis->rcItem, + lpdis->itemAction, + lpdis->itemState, + &rcDevice + ); + +#if defined( USE_FRAMETOOLS ) + if (lpdis->itemState & ODS_FOCUS) + OutlineDoc_SetFormulaBarEditText(lpOutlineDoc,lpLine); +#endif + break; + } + case IDC_NAMETABLE: + { + // NOTE: NameTable is never made visible. do nothing + break; + } + +#if defined( USE_HEADING ) + case IDC_ROWHEADING: + { + LPHEADING lphead; + + // Last dummy item shouldn't be drawn + if (lpdis->itemID == (UINT)LineList_GetCount(lpLL)) + break; + + // only DrawEntire need be trapped as window is disabled + if (lpdis->itemAction == ODA_DRAWENTIRE) { + lphead = OutlineDoc_GetHeading(lpOutlineDoc); + Heading_RH_Draw(lphead, lpdis); + } + break; + } + + case IDC_COLHEADING: + { + RECT rect; + RECT rcDevice; + RECT rcLogical; + LPHEADING lphead; + + // only DrawEntire need be trapped as window is disabled + if (lpdis->itemAction == ODA_DRAWENTIRE) { + lphead = OutlineDoc_GetHeading(lpOutlineDoc); + GetClientRect(lpdis->hwndItem, &rect); + + rcDevice = lpdis->rcItem; + + // shift the item rect to account for + // horizontal scrolling + rcDevice.left = -(rcDevice.right - rect.right); + + // shift rect for left margin + rcDevice.left += (int)(XformWidthInHimetricToPixels( + NULL, + LOWORD(OutlineDoc_GetMargin(lpOutlineDoc))) * + lpscale->dwSxN / lpscale->dwSxD); + + rcDevice.right = rcDevice.left + (int)lpscale->dwSxN; + rcLogical.left = 0; + rcLogical.bottom = 0; + rcLogical.right = (int)lpscale->dwSxD; + rcLogical.top = LOWORD(lpdis->itemData); + + Heading_CH_Draw(lphead, lpdis, &rcDevice, &rcLogical); + } + break; + } +#endif // USE_HEADING + + } + return (LRESULT)TRUE; + } + + case WM_SETFOCUS: + if (lpLL) + SetFocus(LineList_GetWindow(lpLL)); + break; + +#if !defined( OLE_VERSION ) + case WM_RENDERFORMAT: + { + LPOUTLINEDOC lpClipboardDoc = lpOutlineApp->m_lpClipboardDoc; + if (lpClipboardDoc) + OutlineDoc_RenderFormat(lpClipboardDoc, wParam); + + break; + } + case WM_RENDERALLFORMATS: + { + LPOUTLINEDOC lpClipboardDoc = lpOutlineApp->m_lpClipboardDoc; + if (lpClipboardDoc) + OutlineDoc_RenderAllFormats(lpClipboardDoc); + + break; + } + case WM_DESTROYCLIPBOARD: + if (g_lpApp->m_lpClipboardDoc) { + OutlineDoc_Destroy(g_lpApp->m_lpClipboardDoc); + g_lpApp->m_lpClipboardDoc = NULL; + } + break; + +#endif // OLE_VERSION + +#if defined( OLE_CNTR ) + case WM_U_UPDATEOBJECTEXTENT: + { + /* Update the extents of any OLE object that is marked that + ** its size may have changed. when an + ** IAdviseSink::OnViewChange notification is received, + ** the corresponding ContainerLine is marked + ** (m_fDoGetExtent==TRUE) and a message + ** (WM_U_UPDATEOBJECTEXTENT) is posted to the document + ** indicating that there are dirty objects. + */ + ContainerDoc_UpdateExtentOfAllOleObjects(lpContainerDoc); + break; + } +#endif // OLE_CNTR + +#if defined( INPLACE_SVR ) || defined( INPLACE_CNTR ) + /* OLE2NOTE: Any window that is used during in-place activation + ** must handle the WM_SETCURSOR message or else the cursor + ** of the in-place parent will be used. if WM_SETCURSOR is + ** not handled, then DefWindowProc sends the message to the + ** window's parent. + ** + ** see context sensitive help technote (CSHELP.DOC). + ** m_fCSHelpMode flag is set when SHIFT-F1 context + ** sensitive help is entered. + ** if this flag is set then the context sensitive help + ** cursor should be shown. + */ + case WM_SETCURSOR: + if (lpOleDoc->m_fCSHelpMode) + SetCursor(UICursorLoad(IDC_CONTEXTHELP)); + else + SetCursor(LoadCursor(NULL, IDC_ARROW) ); + return (LRESULT)TRUE; +#endif // INPLACE_SVR || INPLACE_CNTR + +#if defined( INPLACE_SVR ) + /* OLE2NOTE: when the in-place active, our in-place server + ** document window (passed to IOleInPlaceFrame::SetMenu) + ** will receive the WM_INITMENU and WM_INITMENUPOPUP messages. + */ + case WM_INITMENU: + OutlineApp_InitMenu(lpOutlineApp, lpOutlineDoc, (HMENU)wParam); + break; + + /* OLE2NOTE: WM_INITMENUPOPUP is trapped primarily for the Edit + ** menu. We didn't update the Edit menu until it is popped + ** up to avoid the overheads of the OLE calls which are + ** required to initialize some Edit menu items. + */ + case WM_INITMENUPOPUP: + { + HMENU hMenuEdit = GetSubMenu(lpOutlineApp->m_hMenuApp, 1); + if ((HMENU)wParam == hMenuEdit && + (LOWORD(lParam) == POS_EDITMENU) && + OleDoc_GetUpdateEditMenuFlag((LPOLEDOC)lpOutlineDoc)) { + OleApp_UpdateEditMenu( + (LPOLEAPP)lpOutlineApp, lpOutlineDoc, hMenuEdit); + } + break; + } +#endif // INPLACE_SVR + +#if defined( INPLACE_SVR ) && defined( USE_STATUSBAR ) + /* OLE2NOTE: when the server is in-place active the + ** WM_MENUSELECT message is sent to the object's window and + ** not the server app's frame window. processing this + ** message allows there in-place server to give status bar + ** help text for menu commands. + */ + case WM_MENUSELECT: + { + LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOleDoc; + LPSTR lpszMessage; +#ifdef WIN32 + UINT fuFlags = (UINT)HIWORD(wParam); + UINT uItem = (UINT)LOWORD(wParam); +#else + UINT fuFlags = (UINT)LOWORD(lParam); + UINT uItem = (UINT)wParam; +#endif + + if (uItem == 0 && fuFlags == (UINT)-1) { + GetControlMessage(STATUS_READY, &lpszMessage); + ServerDoc_SetStatusText(lpServerDoc, lpszMessage); + } + else if (fuFlags & MF_POPUP) { +#ifdef WIN32 + HMENU hMainMenu = (HMENU)lParam; + HMENU hPopupMenu = GetSubMenu(hMainMenu,uItem); +#else + HMENU hPopupMenu = (HMENU)wParam; +#endif + GetPopupMessage(hPopupMenu, &lpszMessage); + ServerDoc_SetStatusText(lpServerDoc, lpszMessage); + } + else if (uItem != 0) { // Command Item + GetItemMessage(uItem, &lpszMessage); + ServerDoc_SetStatusText(lpServerDoc, lpszMessage); + } + else { + GetControlMessage(STATUS_BLANK, &lpszMessage); + ServerDoc_SetStatusText(lpServerDoc, lpszMessage); + } + break; + } +#endif // INPLACE_SVR && USE_STATUSBAR +#if defined( INPLACE_SVR ) && defined( USE_FRAMETOOLS ) + + case WM_U_INITFRAMETOOLS: + OutlineDoc_UpdateFrameToolButtons(lpOutlineDoc); + break; +#endif // INPLACE_SVR && USE_FRAMETOOLS + + + case WM_COMMAND: + { +#ifdef WIN32 + WORD wNotifyCode = HIWORD(wParam); + WORD wID = LOWORD(wParam); + HWND hwndCtl = (HWND) lParam; +#else + WORD wNotifyCode = HIWORD(lParam); + WORD wID = wParam; + HWND hwndCtl = (HWND) LOWORD(lParam); +#endif + +#if defined( INPLACE_SVR ) + /* OLE2NOTE: see context sensitive help technote (CSHELP.DOC) + ** m_fMenuHelpMode flag is set when F1 is pressed when a + ** menu item is selected. this flag is set in + ** IOleInPlaceActiveObject::ContextSensitveHelp method. + ** m_fCSHelpMode flag is set when SHIFT-F1 context + ** sensitive help is entered. this flag is set in + ** IOleInPlaceObject::ContextSensitiveHelp method. + ** if either of these flags are set then the WM_COMMAND + ** message is received then, the corresponding command + ** should NOT executed; help can be given (if desired). + ** also the context sensitve help mode should be exited. + ** the two different cases have their own way to exit + ** the mode (please refer to the technote). + */ + if (lpOleDoc && + (lpServerDoc->m_fMenuHelpMode||lpOleDoc->m_fCSHelpMode) && + (wID > IDM_FILE) /* min wID for app command */ && + (wID!=IDM_FB_EDIT) /* special wID to control FormulaBar */ ) { + + if ((lpServerDoc->m_fMenuHelpMode)) { + LPOLEINPLACEFRAME lpFrame; + + lpServerDoc->m_fMenuHelpMode = FALSE; + + // inform top-level frame that we handled the + // menu help mode (F1) selection. + if (lpServerDoc->m_lpIPData && + (lpFrame=lpServerDoc->m_lpIPData->lpFrame)!=NULL){ + OLEDBG_BEGIN2("IOleInPlaceFrame::ContextSensitiveHelp(FALSE) called\r\n") + lpFrame->lpVtbl->ContextSensitiveHelp(lpFrame, FALSE); + OLEDBG_END2 + } + } + + if ((lpOleDoc->m_fCSHelpMode)) { + LPOLEINPLACESITE lpSite; + + lpOleDoc->m_fCSHelpMode = FALSE; + + /* inform immediate in-place container parent and, + ** if we were a container/server, immediate + ** in-place object children that we handled the + ** context sensitive help mode. + */ + if (lpServerDoc->m_lpIPData && + (lpSite=lpServerDoc->m_lpIPData->lpSite) !=NULL) { + OLEDBG_BEGIN2("IOleInPlaceSite::ContextSensitiveHelp(FALSE) called\r\n") + lpSite->lpVtbl->ContextSensitiveHelp(lpSite, FALSE); + OLEDBG_END2 + } + } + + // if we provided help, we would do it here... + + // remove context sensitive help cursor + SetCursor(LoadCursor(NULL,IDC_ARROW)); + return 0L; + } +#endif // INPLACE_SVR +#if defined( INPLACE_CNTR ) + + /* OLE2NOTE: see context sensitive help technote (CSHELP.DOC) + ** m_fMenuHelpMode flag is set when F1 is pressed when a + ** menu item is selected. this flag is set in + ** IOleInPlaceFrame::ContextSensitveHelp method. + ** m_fCSHelpMode flag is set when SHIFT-F1 context + ** sensitive help is entered. this flag is set in + ** IOleInPlaceSite::ContextSensitiveHelp method. + ** if either of these flags are set then the WM_COMMAND + ** message is received then, the corresponding command + ** should NOT executed; help can be given (if desired). + ** also the context sensitve help mode should be exited. + ** the two different cases have their own way to exit + ** the mode (please refer to the technote). + */ + if (lpOleDoc && + (lpContainerApp->m_fMenuHelpMode||lpOleDoc->m_fCSHelpMode) && + (wID > IDM_FILE) /* min wID for app command */ && + (wID!=IDM_FB_EDIT) /* special wID to control FormulaBar */ ) { + + if ((lpContainerApp->m_fMenuHelpMode)) { + LPOLEINPLACEACTIVEOBJECT lpIPActiveObj = + lpContainerApp->m_lpIPActiveObj; + + lpContainerApp->m_fMenuHelpMode = FALSE; + + // inform the in-place active object that we handled the + // menu help mode (F1) selection. + if (lpIPActiveObj) { + OLEDBG_BEGIN2("IOleInPlaceActiveObject::ContextSensitiveHelp(FALSE) called\r\n") + lpIPActiveObj->lpVtbl->ContextSensitiveHelp( + lpIPActiveObj, FALSE); + OLEDBG_END2 + } + } + + if ((lpOleDoc->m_fCSHelpMode)) { + LPOLEINPLACEOBJECT lpIPObj; + LPCONTAINERLINE lpLastIpActiveLine = + lpContainerDoc->m_lpLastIpActiveLine; + + lpOleDoc->m_fCSHelpMode = FALSE; + + /* inform immediate in-place container parent and, + ** if we were a container/server, immediate + ** in-place object children that we handled the + ** context sensitive help mode. + */ + if (lpLastIpActiveLine && + (lpIPObj=lpLastIpActiveLine->m_lpOleIPObj)!=NULL){ + OLEDBG_BEGIN2("IOleInPlaceObject::ContextSensitiveHelp(FALSE) called\r\n") + lpIPObj->lpVtbl->ContextSensitiveHelp(lpIPObj, FALSE); + OLEDBG_END2 + } + } + + // if we provided help, we would do it here... + + // remove context sensitive help cursor + SetCursor(LoadCursor(NULL,IDC_ARROW)); + return 0L; + } +#endif // INPLACE_CNTR + + switch (wID) { + + /********************************************************* + ** File new, open, save and print as well as Help about + ** are duplicated in this switch statement and they are + ** used to trap the message from the toolbar + ** + *********************************************************/ + + case IDM_F_NEW: + OleDbgIndent(-2); // Reset debug output indent level + OleDbgOutNoPrefix2("\r\n"); + + OLEDBG_BEGIN3("OutlineApp_NewCommand\r\n") + OutlineApp_NewCommand(lpOutlineApp); + OLEDBG_END3 + +#if defined( OLE_CNTR ) + /* OLE2NOTE: this call will attempt to recover + ** resources by unloading DLL's that were loaded + ** by OLE and are no longer being used. it is a + ** good idea to call this API now and then if + ** your app tends to run for a long time. + ** otherwise these DLL's will be unloaded when + ** the app exits. some apps may want to call + ** this as part of idle-time processing. this + ** call is optional. + */ + OLEDBG_BEGIN2("CoFreeUnusedLibraries called\r\n") + CoFreeUnusedLibraries(); + OLEDBG_END2 +#endif + +#if defined( USE_FRAMETOOLS ) + OutlineDoc_UpdateFrameToolButtons( + OutlineApp_GetActiveDoc(lpOutlineApp)); +#endif + break; + + case IDM_F_OPEN: + OleDbgOutNoPrefix2("\r\n"); + + OLEDBG_BEGIN3("OutlineApp_OpenCommand\r\n") + OutlineApp_OpenCommand(lpOutlineApp); + OLEDBG_END3 + +#if defined( OLE_CNTR ) + /* OLE2NOTE: this call will attempt to recover + ** resources by unloading DLL's that were loaded + ** by OLE and are no longer being used. it is a + ** good idea to call this API now and then if + ** your app tends to run for a long time. + ** otherwise these DLL's will be unloaded when + ** the app exits. some apps may want to call + ** this as part of idle-time processing. this + ** call is optional. + */ + OLEDBG_BEGIN2("CoFreeUnusedLibraries called\r\n") + CoFreeUnusedLibraries(); + OLEDBG_END2 +#endif + +#if defined( USE_FRAMETOOLS ) + OutlineDoc_UpdateFrameToolButtons( + OutlineApp_GetActiveDoc(lpOutlineApp)); +#endif + break; + + case IDM_F_SAVE: + OleDbgOutNoPrefix2("\r\n"); + + OLEDBG_BEGIN3("OutlineApp_SaveCommand\r\n") + OutlineApp_SaveCommand(lpOutlineApp); + OLEDBG_END3 + break; + + case IDM_F_PRINT: + OleDbgOutNoPrefix2("\r\n"); + + OLEDBG_BEGIN3("OutlineApp_PrintCommand\r\n") + OutlineApp_PrintCommand(lpOutlineApp); + OLEDBG_END3 + break; + + + case IDM_E_UNDO: + // SORRY. NOT IMPLEMENTED + break; + + case IDM_E_CUT: + OleDbgOutNoPrefix2("\r\n"); + + OLEDBG_BEGIN3("OutlineDoc_CutCommand\r\n") + OutlineDoc_CutCommand(lpOutlineDoc); + OLEDBG_END3 + +#if defined( USE_FRAMETOOLS ) + OutlineDoc_UpdateFrameToolButtons(lpOutlineDoc); +#endif + break; + + case IDM_E_COPY: + OleDbgOutNoPrefix2("\r\n"); + + OLEDBG_BEGIN3("OutlineDoc_CopyCommand\r\n") + OutlineDoc_CopyCommand(lpOutlineDoc); + OLEDBG_END3 + +#if defined( USE_FRAMETOOLS ) + OutlineDoc_UpdateFrameToolButtons(lpOutlineDoc); +#endif + break; + + case IDM_E_PASTE: + OleDbgOutNoPrefix2("\r\n"); + + OLEDBG_BEGIN3("OutlineDoc_PasteCommand\r\n") + OutlineDoc_PasteCommand(lpOutlineDoc); + OLEDBG_END3 + +#if defined( USE_FRAMETOOLS ) + OutlineDoc_UpdateFrameToolButtons(lpOutlineDoc); +#endif + break; + +#if defined( OLE_VERSION ) + case IDM_E_PASTESPECIAL: + OleDbgOutNoPrefix2("\r\n"); + + OLEDBG_BEGIN3("OleDoc_PasteSpecialCommand\r\n") + OleDoc_PasteSpecialCommand((LPOLEDOC)lpOutlineDoc); + OLEDBG_END3 + +#if defined( USE_FRAMETOOLS ) + OutlineDoc_UpdateFrameToolButtons(lpOutlineDoc); +#endif + break; + +#endif // OLE_VERSION + + case IDM_E_CLEAR: + OleDbgOutNoPrefix2("\r\n"); + + OLEDBG_BEGIN3("OutlineDoc_ClearCommand\r\n") + OutlineDoc_ClearCommand(lpOutlineDoc); + OLEDBG_END3 + +#if defined( OLE_CNTR ) + /* OLE2NOTE: this call will attempt to recover + ** resources by unloading DLL's that were loaded + ** by OLE and are no longer being used. it is a + ** good idea to call this API now and then if + ** your app tends to run for a long time. + ** otherwise these DLL's will be unloaded when + ** the app exits. some apps may want to call + ** this as part of idle-time processing. this + ** call is optional. + */ + OLEDBG_BEGIN2("CoFreeUnusedLibraries called\r\n") + CoFreeUnusedLibraries(); + OLEDBG_END2 +#endif + +#if defined( USE_FRAMETOOLS ) + OutlineDoc_UpdateFrameToolButtons(lpOutlineDoc); +#endif + break; + + case IDM_L_ADDLINE: + OleDbgOutNoPrefix2("\r\n"); + + OLEDBG_BEGIN3("OutlineDoc_AddTextLineCommand\r\n") + OutlineDoc_AddTextLineCommand(lpOutlineDoc); + OLEDBG_END3 + +#if defined( USE_FRAMETOOLS ) + OutlineDoc_UpdateFrameToolButtons(lpOutlineDoc); + SetFocus(LineList_GetWindow(lpLL)); +#endif + break; + + case IDM_L_EDITLINE: + OleDbgOutNoPrefix2("\r\n"); + + OLEDBG_BEGIN3("OutlineDoc_EditLineCommand\r\n") + OutlineDoc_EditLineCommand(lpOutlineDoc); + OLEDBG_END3 + SetFocus(LineList_GetWindow(lpLL)); + break; + + case IDM_L_INDENTLINE: + OleDbgOutNoPrefix2("\r\n"); + + OLEDBG_BEGIN3("OutlineDoc_IndentCommand\r\n") + OutlineDoc_IndentCommand(lpOutlineDoc); + OLEDBG_END3 + break; + + case IDM_L_UNINDENTLINE: + OleDbgOutNoPrefix2("\r\n"); + + OLEDBG_BEGIN3("OutlineDoc_UnindentCommand\r\n") + OutlineDoc_UnindentCommand(lpOutlineDoc); + OLEDBG_END3 + break; + + case IDM_L_SETLINEHEIGHT: + OleDbgOutNoPrefix2("\r\n"); + + OLEDBG_BEGIN3("OutlineDoc_SetLineHeight\r\n") + OutlineDoc_SetLineHeightCommand(lpOutlineDoc); + OLEDBG_END3 + break; + + case IDM_E_SELECTALL: + OleDbgOutNoPrefix2("\r\n"); + + OLEDBG_BEGIN3("OutlineDoc_SelectAllCommand\r\n") + OutlineDoc_SelectAllCommand(lpOutlineDoc); + OLEDBG_END3 + break; + +#if defined( OLE_CNTR ) + case IDM_E_INSERTOBJECT: + OleDbgOutNoPrefix2("\r\n"); + + OLEDBG_BEGIN3("ContainerDoc_InsertOleObjectCommand\r\n") + ContainerDoc_InsertOleObjectCommand(lpContainerDoc); + OLEDBG_END3 + +#if defined( USE_FRAMETOOLS ) + OutlineDoc_UpdateFrameToolButtons(lpOutlineDoc); +#endif + break; + + case IDM_E_EDITLINKS: + OleDbgOutNoPrefix2("\r\n"); + + OLEDBG_BEGIN3("ContainerDoc_EditLinksCommand\r\n") + ContainerDoc_EditLinksCommand(lpContainerDoc); + OLEDBG_END3 + break; + + case IDM_E_CONVERTVERB: + OleDbgOutNoPrefix2("\r\n"); + + OLEDBG_BEGIN3("ContainerDoc_ConvertCommand\r\n") + ContainerDoc_ConvertCommand( + lpContainerDoc, FALSE /*fMustActivate*/); + OLEDBG_END3 + break; + + + case IDM_E_PASTELINK: + OleDbgOutNoPrefix2("\r\n"); + + OLEDBG_BEGIN3("ContainerDoc_PasteLinkCommand\r\n") + ContainerDoc_PasteLinkCommand(lpContainerDoc); + OLEDBG_END3 + +#if defined( USE_FRAMETOOLS ) + OutlineDoc_UpdateFrameToolButtons(lpOutlineDoc); +#endif + break; + +#endif // OLE_CNTR + + case IDM_N_DEFINENAME: + OleDbgOutNoPrefix2("\r\n"); + + OLEDBG_BEGIN3("OutlineDoc_DefineNameCommand\r\n") + OutlineDoc_DefineNameCommand(lpOutlineDoc); + OLEDBG_END3 + break; + + case IDM_N_GOTONAME: + OleDbgOutNoPrefix2("\r\n"); + + OLEDBG_BEGIN3("OutlineDoc_GotoNameCommand\r\n") + OutlineDoc_GotoNameCommand(lpOutlineDoc); + OLEDBG_END3 + break; + +#if defined( USE_FRAMETOOLS ) + case IDM_O_BB_TOP: + FrameTools_BB_SetState( + lpOutlineDoc->m_lpFrameTools, BARSTATE_TOP); + OutlineDoc_AddFrameLevelTools(lpOutlineDoc); + break; + + case IDM_O_BB_BOTTOM: + FrameTools_BB_SetState( + lpOutlineDoc->m_lpFrameTools, BARSTATE_BOTTOM); + OutlineDoc_AddFrameLevelTools(lpOutlineDoc); + break; + + case IDM_O_BB_POPUP: + FrameTools_BB_SetState( + lpOutlineDoc->m_lpFrameTools, BARSTATE_POPUP); + OutlineDoc_AddFrameLevelTools(lpOutlineDoc); + break; + + case IDM_O_BB_HIDE: + FrameTools_BB_SetState( + lpOutlineDoc->m_lpFrameTools, BARSTATE_HIDE); + OutlineDoc_AddFrameLevelTools(lpOutlineDoc); + break; + + case IDM_O_FB_TOP: + FrameTools_FB_SetState( + lpOutlineDoc->m_lpFrameTools, BARSTATE_TOP); + OutlineDoc_AddFrameLevelTools(lpOutlineDoc); + break; + + case IDM_O_FB_BOTTOM: + FrameTools_FB_SetState( + lpOutlineDoc->m_lpFrameTools, BARSTATE_BOTTOM); + OutlineDoc_AddFrameLevelTools(lpOutlineDoc); + break; + + case IDM_O_FB_POPUP: + FrameTools_FB_SetState( + lpOutlineDoc->m_lpFrameTools, BARSTATE_POPUP); + OutlineDoc_AddFrameLevelTools(lpOutlineDoc); + break; + + case IDM_FB_EDIT: + + switch (wNotifyCode) { + case EN_SETFOCUS: + OutlineDoc_SetFormulaBarEditFocus( + lpOutlineDoc, TRUE); + OutlineDoc_UpdateFrameToolButtons(lpOutlineDoc); + break; + + case EN_KILLFOCUS: + OutlineDoc_SetFormulaBarEditFocus( + lpOutlineDoc, FALSE); + OutlineDoc_UpdateFrameToolButtons(lpOutlineDoc); + break; + } + break; + + case IDM_FB_CANCEL: + + SetFocus(hWnd); + break; + + + case IDM_F2: + SendMessage(hWnd, WM_COMMAND, (WPARAM)IDM_FB_EDIT, + MAKELONG(0, EN_SETFOCUS)); + break; +#endif // USE_FRAMETOOLS + + case IDM_ESCAPE: + /* ESCAPE key pressed */ + +#if defined( USE_FRAMETOOLS ) + if (OutlineDoc_IsEditFocusInFormulaBar(lpOutlineDoc)) + SendMessage( + hWnd, WM_COMMAND,(WPARAM)IDM_FB_CANCEL,(LPARAM)0); +#endif // USE_FRAMETOOLS + +#if defined( INPLACE_SVR ) + else { + LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOutlineDoc; + + /* OLE2NOTE: The standard OLE 2.0 UI convention + ** is to have ESCAPE key exit in-place + ** activation (ie. UIDeactivate). If + ** possible it is recommended for both + ** in-place servers AND in-place containers + ** to take responsibility to handle the + ** ESCAPE key accelerator. The server has + ** the first crack at handling accelerator + ** keys and normally the server should do + ** the UIDeactivation. + */ + if (lpServerDoc->m_fUIActive) { + SvrDoc_IPObj_UIDeactivate( (LPOLEINPLACEOBJECT)& + lpServerDoc->m_OleInPlaceObject); + } + } +#endif // INPLACE_SVR + + break; + + +#if defined( USE_HEADING ) + case IDC_BUTTON: + if (wNotifyCode == BN_CLICKED) { + SendMessage(hWnd, WM_COMMAND, IDM_E_SELECTALL, 0L); + SetFocus(hWnd); + } + break; + + case IDM_O_HEAD_SHOW: + OutlineDoc_ShowHeading(lpOutlineDoc, TRUE); + break; + + case IDM_O_HEAD_HIDE: + OutlineDoc_ShowHeading(lpOutlineDoc, FALSE); + break; +#endif // USE_HEADING + + +#if defined( OLE_CNTR ) + case IDM_O_SHOWOBJECT: + { + LPCONTAINERDOC lpContainerDoc = + (LPCONTAINERDOC)lpOutlineDoc; + BOOL fShowObject; + + fShowObject = !ContainerDoc_GetShowObjectFlag( + lpContainerDoc); + ContainerDoc_SetShowObjectFlag( + lpContainerDoc, fShowObject); + LineList_ForceRedraw(lpLL, TRUE); + + break; + } +#endif // OLE_CNTR + +#if !defined( OLE_CNTR ) + // Container does not allow zoom factors > 100% + case IDM_V_ZOOM_400: + case IDM_V_ZOOM_300: + case IDM_V_ZOOM_200: +#endif // !OLE_CNTR + + case IDM_V_ZOOM_100: + case IDM_V_ZOOM_75: + case IDM_V_ZOOM_50: + case IDM_V_ZOOM_25: + OutlineDoc_SetCurrentZoomCommand(lpOutlineDoc, wID); + break; + + case IDM_V_SETMARGIN_0: + case IDM_V_SETMARGIN_1: + case IDM_V_SETMARGIN_2: + case IDM_V_SETMARGIN_3: + case IDM_V_SETMARGIN_4: + OutlineDoc_SetCurrentMarginCommand(lpOutlineDoc, wID); + break; + + case IDM_V_ADDTOP_1: + case IDM_V_ADDTOP_2: + case IDM_V_ADDTOP_3: + case IDM_V_ADDTOP_4: + { + UINT nHeightInHimetric; + + switch (wID) { + case IDM_V_ADDTOP_1: + nHeightInHimetric = 1000; + break; + + case IDM_V_ADDTOP_2: + nHeightInHimetric = 2000; + break; + + case IDM_V_ADDTOP_3: + nHeightInHimetric = 3000; + break; + + case IDM_V_ADDTOP_4: + nHeightInHimetric = 4000; + break; + } + + OutlineDoc_AddTopLineCommand( + lpOutlineDoc, nHeightInHimetric); + break; + } + + + case IDM_H_ABOUT: + OutlineApp_AboutCommand(lpOutlineApp); + break; + + case IDM_D_DEBUGLEVEL: + SetDebugLevelCommand(); + break; + +#if defined( OLE_VERSION ) + case IDM_D_INSTALLMSGFILTER: + InstallMessageFilterCommand(); + break; + + case IDM_D_REJECTINCOMING: + RejectIncomingCommand(); + break; +#endif // OLE_VERSION + +#if defined( INPLACE_CNTR ) + case IDM_D_INSIDEOUT: + g_fInsideOutContainer = !g_fInsideOutContainer; + + // force all object to unload so they can start new + // activation behavior. + ContainerDoc_UnloadAllOleObjectsOfClass( + (LPCONTAINERDOC)lpOutlineDoc, + &CLSID_NULL, + OLECLOSE_SAVEIFDIRTY + ); + OutlineDoc_ForceRedraw(lpOutlineDoc, TRUE); + break; +#endif // INPLACE_CNTR + + +#if defined( OLE_CNTR ) + case IDC_LINELIST: { + + if (wNotifyCode == LBN_DBLCLK) { + + /* OLE2NOTE: a container should execute the + ** OLEIVERB_PRIMARY verb on an OLE object + ** when the user DBLCLK's the object. + */ + int nIndex = LineList_GetFocusLineIndex(lpLL); + LPLINE lpLine = LineList_GetLine(lpLL, nIndex); + + if (lpLine && + Line_GetLineType(lpLine)==CONTAINERLINETYPE) { + MSG msg; + + _fmemset((LPMSG)&msg,0,sizeof(msg)); + msg.hwnd = hWnd; + msg.message = Message; + msg.wParam = wParam; + msg.lParam = lParam; + + ContainerLine_DoVerb( + (LPCONTAINERLINE)lpLine, + OLEIVERB_PRIMARY, + (LPMSG)&msg, + TRUE, + TRUE + ); + } + +#if defined( INPLACE_CNTR ) + { // BEGIN BLOCK + LPCONTAINERDOC lpContainerDoc = + (LPCONTAINERDOC) lpOutlineDoc; + if (lpContainerDoc->m_fAddMyUI) { + /* OLE2NOTE: fAddMyUI is TRUE when + ** there was previously an in-place + ** active object which got + ** UIDeactivated as a result of this + ** DBLCLK AND the DBLCLK did NOT + ** result in in-place activating + ** another object. + ** (see IOleInPlaceSite::OnUIActivate and + ** IOleInPlaceSite::OnUIDeactivate + ** methods). + */ + + /* OLE2NOTE: You need to generate + ** QueryNewPalette only if you own + ** the top level frame (ie. you are + ** a top-level inplace container). + */ + + + OleApp_QueryNewPalette((LPOLEAPP)g_lpApp); + +#if defined( USE_DOCTOOLS ) + ContainerDoc_AddDocLevelTools(lpContainerDoc); +#endif + +#if defined( USE_FRAMETOOLS ) + ContainerDoc_AddFrameLevelUI(lpContainerDoc); +#endif + lpContainerDoc->m_fAddMyUI = FALSE; + } + } // END BLOCK +#endif // INPLACE_CNTR + } + break; + } +#endif // OLE_CNTR + + + default: + +#if defined( OLE_CNTR ) + if (wID >= IDM_E_OBJECTVERBMIN) { + + OleDbgOutNoPrefix2("\r\n"); + OLEDBG_BEGIN3("ContainerDoc_ContainerLineDoVerbCommand\r\n") + ContainerDoc_ContainerLineDoVerbCommand( + (LPCONTAINERDOC)lpOutlineDoc, + (LONG)(wID-IDM_E_OBJECTVERBMIN) + ); + OLEDBG_END3 + break; + } +#endif // OLE_CNTR + return DefWindowProc(hWnd, Message, wParam, lParam); + } + + break; /* End of WM_COMMAND */ + } + default: + + if (Message == g_uMsgHelp) { + /* Handle OLE2UI dialog's help messages. + ** We get the hDlg of the dialog that called us in the wParam + ** and the dialog type in the LOWORD of the lParam, + ** so we pass this along to our help function. + */ + OutlineDoc_DialogHelp((HWND)wParam, LOWORD(lParam)); + break; + } + + /* For any message for which you don't specifically provide a */ + /* service routine, you should return the message to Windows */ + /* for default message processing. */ + return DefWindowProc(hWnd, Message, wParam, lParam); + } + + return (LRESULT)0; + +} /* End of DocWndProc */ + + + +//*********************************************************************** +//* +//* LineListWndProc() Drag and Drop Listbox Window Proc Sub-Class +//* +//* Sub Class the Ownerdraw list box in order to activate the drag drop. +//*********************************************************************** + +LRESULT FAR PASCAL LineListWndProc( + HWND hWnd, + UINT Message, + WPARAM wParam, + LPARAM lParam +) +{ + HWND hwndParent = GetParent ( hWnd ); + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC) GetWindowLong( hwndParent, 0 ); + LPLINELIST lpLL = OutlineDoc_GetLineList(lpOutlineDoc); + +#if defined( OLE_VERSION ) + LPOLEAPP lpOleApp = (LPOLEAPP)lpOutlineApp; + LPOLEDOC lpOleDoc = (LPOLEDOC)lpOutlineDoc; +#endif // OLE_VERSION + +#if defined( INPLACE_SVR ) + LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOutlineDoc; + static BOOL fUIActivateClick = FALSE; + static BOOL fInWinPosChged = FALSE; +#endif // INPLACE_SVR + +#if defined( INPLACE_CNTR ) + LPCONTAINERAPP lpContainerApp=(LPCONTAINERAPP)lpOutlineApp; + LPCONTAINERDOC lpContainerDoc=(LPCONTAINERDOC)lpOutlineDoc; +#endif // INPLACE_CNTR + + switch (Message) { + + case WM_KILLFOCUS: + /* OLE2NOTE: when our window looses focus we + ** should not display any active selection + */ +#if defined( INPLACE_CNTR ) + if (! lpContainerApp->m_fPendingUIDeactivate) +#endif // INPLACE_CNTR + LineList_RemoveSel(lpLL); + break; + + case WM_SETFOCUS: + +#if defined( INPLACE_CNTR ) + { + HWND hWndObj=ContainerDoc_GetUIActiveWindow(lpContainerDoc); + + /* OLE2NOTE: if there is a UIActive in-place object, we must + ** forward focus to its window as long as there is + ** not a pending UIDeactivate. if the mouse is + ** clicked outside of the object and the object is + ** about to be deactivated then we do NOT want to + ** forward focus to the object. we do NOT want it to + ** restore its selection feedback. + */ + if (lpContainerApp->m_fPendingUIDeactivate) + break; + else if (hWndObj) { + SetFocus(hWndObj); + break; // do not restore containers selection state + } + } +#endif // INPLACE_CNTR + + /* OLE2NOTE: when our window gains focus we + ** should restore the previous selection + */ + LineList_RestoreSel(lpLL); + + break; + +#if defined( INPLACE_SVR ) + case WM_MOUSEACTIVATE: + { + if (lpServerDoc->m_fInPlaceActive && !lpServerDoc->m_fUIActive) { + fUIActivateClick = TRUE; + }; + break; + } + +#endif // INPLACE_SVR + + +#if defined( USE_FRAMETOOLS ) + case WM_CHAR: + { + OutlineDoc_SetFormulaBarEditFocus(lpOutlineDoc, TRUE); + FrameTools_FB_SetEditText(lpOutlineDoc->m_lpFrameTools, NULL); + FrameTools_FB_SendMessage( + lpOutlineDoc->m_lpFrameTools, + IDM_FB_EDIT, + Message, + wParam, + lParam + ); + + return (LRESULT)0; // don't do default listbox processing + } +#endif // USE_FRAMETOOLS + +#if defined( INPLACE_CNTR ) + case WM_VSCROLL: + { + if (wParam == SB_ENDSCROLL) { + /* OLE2NOTE: after scrolling finishes, update position of + ** in-place visible windows. + ** (ICNTROTL specific) we first let the ListBox + ** perform it normal processing with the EndScroll + ** message. also we let the ListBox handle all other + ** scroll messages. + */ + LRESULT lResult = CallWindowProc( + (WNDPROC)lpOutlineApp->m_ListBoxWndProc, + hWnd, + Message, + wParam, + lParam + ); + ContainerDoc_UpdateInPlaceObjectRects(lpContainerDoc, 0); + return lResult; + } + + break; + } +#endif // INPLACR_CNTR + +#if defined( USE_HEADING ) + case WM_HSCROLL: + { + LPHEADING lphead = OutlineDoc_GetHeading(lpOutlineDoc); + + Heading_CH_SendMessage(lphead, Message, wParam, lParam); + + break; + } + + /* NOTE: WM_PAINT trapped in order to track vertical scrolling + ** that has taken place so the row headings can be + ** coordinated with the LineList. we wanted to trap instead + ** but it is not generated from scrolling without using + ** scroll bar (e.g. use keyboard). + */ + case WM_PAINT: + { + Heading_RH_Scroll(OutlineDoc_GetHeading(lpOutlineDoc), hWnd); + break; + } + +#endif // USE_HEADING + + case WM_LBUTTONUP: + { + +#if defined( USE_DRAGDROP ) + if (lpOleDoc->m_fPendingDrag) { + /* ButtonUP came BEFORE distance/time threshholds were + ** exceeded. clear fPendingDrag state. + */ + ReleaseCapture(); + KillTimer(hWnd, 1); + lpOleDoc->m_fPendingDrag = FALSE; + } +#endif // USE_DRAGDROP + +#if defined( INPLACE_SVR ) + if (fUIActivateClick) { + fUIActivateClick = FALSE; + ServerDoc_UIActivate((LPSERVERDOC) lpOleDoc); + } +#endif // INPLACE_SVR + +#if defined( INPLACE_CNTR ) + { + /* check if a UIDeactivate is pending. + ** (see comment in WM_LBUTTONDOWN) + */ + if ( lpContainerApp->m_fPendingUIDeactivate ) { + ContainerLine_UIDeactivate( + lpContainerDoc->m_lpLastUIActiveLine); + + lpContainerApp->m_fPendingUIDeactivate = FALSE; + } + } +#endif // INPLACE_CNTR + + break; + } + + case WM_LBUTTONDOWN: + { + POINT pt; + + pt.x = (int)(short)LOWORD (lParam ); + pt.y = (int)(short)HIWORD (lParam ); + +#if defined( INPLACE_SVR ) || defined( INPLACE_CNTR ) + /* OLE2NOTE: see context sensitive help technote (CSHELP.DOC) + ** m_fCSHelpMode flag is set when SHIFT-F1 context + ** sensitive help is entered. + ** if this flag is set then the button click should not + ** cause any action. if the application implements a + ** help system, then context sensitive help should be + ** given for the location clicked by the user. + */ + if (lpOleDoc->m_fCSHelpMode) { + return (LRESULT)0; // eat the button click because we do + // not give any help. + } +#endif // INPLACE_SVR || INPLACE_CNTR + +#if defined( INPLACE_CNTR ) + { + /* OLE2NOTE: both inside-out and outside-in style + ** containers must check if the mouse click is + ** outside of the current UIActive object (if + ** any). If so, then set the flag indicating that + ** there is a pending UIDeactivate needed. We do NOT + ** want to do it now, + ** because that would result in un-wanted movement of + ** the data on the screen as frame adornments (eg. + ** toolbar) and/or object adornments (eg. ruler) would + ** be removed from the screen. we want to defer the + ** UIDeactivate till the mouse up event. The listbox's + ** default processing captures the mouse on button down + ** so that it is sure to get the button up message. + ** + ** SPECIAL NOTE: there is potential interaction here + ** with Drag/Drop. if this button down event actually + ** starts a Drag/Drop operation, then OLE does the mouse + ** capture. in this situation we will NOT get our button + ** up event. we must instead perform the UIDeactivate + ** when the drop operation finishes + */ + lpContainerApp->m_fPendingUIDeactivate = + ContainerDoc_IsUIDeactivateNeeded(lpContainerDoc, pt); + } +#endif // INPLACE_CNTR + +#if defined( USE_DRAGDROP ) + + /* OLE2NOTE: check if this is a button down on the region + ** that is a handle to start a drag operation. for us, + ** this this the top/bottom border of the selection. + ** do NOT want to start a drag immediately; we want to + ** wait until the mouse moves a certain threshold. if + ** LButtonUp comes before mouse move to start drag, then + ** the fPendingDrag state is cleared. we must capture + ** the mouse to ensure the modal state is handled + ** properly. + */ + if ( OleDoc_QueryDrag(lpOleDoc, pt.y) ) { + lpOleDoc->m_fPendingDrag = TRUE; + lpOleDoc->m_ptButDown = pt; + SetTimer(hWnd, 1, lpOleApp->m_nDragDelay, NULL); + SetCapture(hWnd); + + /* We do NOT want to do the listbox's default + ** processing which would be to capture the mouse + ** and enter a modal multiple selection state until + ** a mouse up occurs. we have just finished a modal + ** drag/drop operation where OLE has captured the + ** mouse. thus by now the mouse up has already occured. + */ + + return (LRESULT)0; // don't do default listbox processing + } +#endif // USE_DRAGDROP + + break; + } + + + case WM_MOUSEMOVE: { + +#if defined( USE_DRAGDROP ) + + int x = (int)(short)LOWORD (lParam ); + int y = (int)(short)HIWORD (lParam ); + POINT pt = lpOleDoc->m_ptButDown; + int nDragMinDist = lpOleApp->m_nDragMinDist; + + if (lpOleDoc->m_fPendingDrag) { + + if (! ( ((pt.x - nDragMinDist) <= x) + && (x <= (pt.x + nDragMinDist)) + && ((pt.y - nDragMinDist) <= y) + && (y <= (pt.y + nDragMinDist)) ) ) { + + DWORD dwEffect; + + // mouse moved beyond threshhold to start drag + ReleaseCapture(); + KillTimer(hWnd, 1); + lpOleDoc->m_fPendingDrag = FALSE; + + // perform the modal drag/drop operation. + dwEffect = OleDoc_DoDragDrop( lpOleDoc ); + +#if defined( INPLACE_CNTR ) + { + /* if necessary UIDeactive the in-place object. + ** this applies to outside-in style + ** container only. + ** (see comment above) + */ + if (lpContainerApp->m_fPendingUIDeactivate) { + lpContainerApp->m_fPendingUIDeactivate = FALSE; + + // do not UIDeactivate if drag/drop was canceled + if (dwEffect != DROPEFFECT_NONE) + ContainerLine_UIDeactivate( + lpContainerDoc->m_lpLastUIActiveLine + ); + } + } +#endif // INPLACE_CNTR + + return (LRESULT)0; // don't do default listbox process + } + else { + /* cursor did not move from initial mouse down + ** (pending drag) point. + */ + return (LRESULT)0; // don't do default listbox process + } + } + +#endif // USE_DRAGDROP + +#if defined( INPLACE_CNTR ) + { // BEGIN BLOCK + if (lpContainerDoc->m_fAddMyUI) { + /* OLE2NOTE: fAddMyUI is TRUE when + ** there was previously an in-place + ** active object which got + ** UIDeactivated as a result of a + ** DBLCLK AND the DBLCLK did NOT + ** result in in-place activating + ** another object. + ** (see IOleInPlaceSite::OnUIActivate and + ** IOleInPlaceSite::OnUIDeactivate + ** methods). + */ +#if defined( USE_DOCTOOLS ) + ContainerDoc_AddDocLevelTools(lpContainerDoc); +#endif + +#if defined( USE_FRAMETOOLS ) + ContainerDoc_AddFrameLevelUI(lpContainerDoc); +#endif + lpContainerDoc->m_fAddMyUI = FALSE; + } + } // END BLOCK +#endif // INPLACE_CNTR + + break; + } + + +#if defined( USE_DRAGDROP ) + case WM_TIMER: + { + DWORD dwEffect; + + // drag time delay threshhold exceeded -- start drag + ReleaseCapture(); + KillTimer(hWnd, 1); + lpOleDoc->m_fPendingDrag = FALSE; + + // perform the modal drag/drop operation. + dwEffect = OleDoc_DoDragDrop( lpOleDoc ); + +#if defined( INPLACE_CNTR ) + /* if necessary UIDeactive the in-place object. + ** this applies to outside-in style + ** container only. + ** (see comment above) + */ + if (lpContainerApp->m_fPendingUIDeactivate) { + lpContainerApp->m_fPendingUIDeactivate = FALSE; + + // do not UIDeactivate if drag/drop was canceled + if (dwEffect != DROPEFFECT_NONE) + ContainerLine_UIDeactivate( + lpContainerDoc->m_lpLastUIActiveLine); + } +#endif // INPLACE_CNTR + break; + } +#endif // USE_DRAGDROP + + case WM_SETCURSOR: + { + RECT rc; + POINT ptCursor; +#if defined( INPLACE_SVR ) || defined( INPLACE_CNTR ) + /* OLE2NOTE: see context sensitive help technote (CSHELP.DOC) + ** m_fCSHelpMode flag is set when SHIFT-F1 context + ** sensitive help is entered. + ** if this flag is set then the context sensitive help + ** cursor should be shown. + */ + if (lpOleDoc->m_fCSHelpMode) { + SetCursor(UICursorLoad(IDC_CONTEXTHELP)); + return (LRESULT)TRUE; + } +#endif // INPLACE_SVR || INPLACE_CNTR + + GetCursorPos((POINT FAR*)&ptCursor); + ScreenToClient(hWnd, (POINT FAR*)&ptCursor); + GetClientRect(hWnd, (LPRECT)&rc); + + // use arrow cursor if in scroll bar + if (! PtInRect((LPRECT)&rc, ptCursor) ) + SetCursor(LoadCursor(NULL, IDC_ARROW) ); + +#if defined( USE_DRAGDROP ) + // use arrow cursor if on drag handle (top/bottom of selection) + else if ( OleDoc_QueryDrag ( lpOleDoc, ptCursor.y) ) + SetCursor(LoadCursor(NULL, IDC_ARROW) ); +#endif // USE_DRAGDROP + + else + SetCursor(lpOutlineApp->m_hcursorSelCur); + + return (LRESULT)TRUE; + } + +#if defined( INPLACE_SVR ) + + /* The handling of WM_WINDOWPOSCHANGED message is ISVROTL + ** application specific. The nature of the owner-draw list + ** box used by the ISVROTL application causes a recursive + ** call to this message in some situations when in-place + ** active. in order not to crash this recursive call must be + ** guarded. + */ + case WM_WINDOWPOSCHANGED: + { + WINDOWPOS FAR* lpWinPos = (WINDOWPOS FAR*) lParam; + LRESULT lResult; + + // guard against recursive call + if (fInWinPosChged) + return (LRESULT)0; + + fInWinPosChged = TRUE; + lResult = CallWindowProc( + (WNDPROC)lpOutlineApp->m_ListBoxWndProc, + hWnd, + Message, + wParam, + lParam + ); + fInWinPosChged = FALSE; + + return lResult; + } +#endif // INPLACE_SVR + + } + + return CallWindowProc( + (WNDPROC)lpOutlineApp->m_ListBoxWndProc, + hWnd, + Message, + wParam, + lParam + ); + +} + +// Utility function to count the number of accelerator items in an +// accelerator table. A number of OLE APIs need this count, so +// this can be quite handy. +// (code shamelessly stolen from the Microsoft Foundation Classes) + +int GetAccelItemCount(HACCEL hAccel) +{ +#if defined( WIN32 ) + return CopyAcceleratorTable(hAccel, NULL, 0); +#else + #pragma pack(1) + typedef struct tagACCELERATOR + { + BYTE fFlags; + WORD wEvent; + WORD wID; + } ACCELERATOR; + #pragma pack() + + // attempt to lock down the accelerator resource + ACCELERATOR FAR* pAccel; + int cAccelItems = 1; + if (hAccel == NULL || + (pAccel = (ACCELERATOR FAR*)LockResource((HGLOBAL)hAccel)) == NULL) + { + // NULL accerator table or LockResource failed on the HACCEL, + // no accelerators + return 0; + } + // otherwise, count them -- last entry in accel table has 0x80 bit set + while ((pAccel->fFlags & 0x80) == 0) + { + ++cAccelItems; + ++pAccel; + } + UnlockResource((HGLOBAL)hAccel); + return cAccelItems; +#endif +} diff --git a/private/oleutest/letest/outline/memmgr.c b/private/oleutest/letest/outline/memmgr.c new file mode 100644 index 000000000..0f9b4cc68 --- /dev/null +++ b/private/oleutest/letest/outline/memmgr.c @@ -0,0 +1,38 @@ +/************************************************************************* +** +** OLE 2 Sample Code +** +** memmgr.c +** +** This file contains memory management functions. +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + + +#include "outline.h" + + +/* New + * --- + * + * Allocate memory for a new structure + */ +LPVOID New(DWORD lSize) +{ + LPVOID lp = OleStdMalloc((ULONG)lSize); + + return lp; +} + + +/* Delete + * ------ + * + * Free memory allocated for a structure + */ +void Delete(LPVOID lp) +{ + OleStdFree(lp); +} diff --git a/private/oleutest/letest/outline/message.h b/private/oleutest/letest/outline/message.h new file mode 100644 index 000000000..f8aa7f580 --- /dev/null +++ b/private/oleutest/letest/outline/message.h @@ -0,0 +1,109 @@ +/************************************************************************* +** +** OLE 2.0 Server Sample Code +** +** message.h +** +** This file is a user customizable list of status messages associated +** with menu items. +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + +// Status bar messages and associated data. + +// Message type for status bar messages. +typedef struct { + UINT wIDItem; + char *string; +} STATMESG; + +/* + * CUSTOMIZATION NOTE: Be sure to change NUM_POPUP if you + * change the number of popup messages. + */ + +// REVIEW: these messages should be loaded from a string resource + +// List of all menu item messages. +STATMESG MesgList[] = +{ + { IDM_F_NEW, "Creates a new outline" }, + { IDM_F_OPEN, "Opens an existing outline file" }, + { IDM_F_SAVE, "Saves the outline" }, + { IDM_F_SAVEAS, "Saves the outline with a new name" }, + { IDM_F_PRINT, "Prints the outline" }, + { IDM_F_PRINTERSETUP, "Changes the printer and the printing options" }, + { IDM_F_EXIT, "Quits the application, prompting to save changes" }, + + { IDM_E_UNDO, "Undo not yet implemented" }, + { IDM_E_CUT, "Cuts the selection and puts it on the Clipboard" }, + { IDM_E_COPY, "Copies the selection and puts it on the Clipboard" }, + { IDM_E_PASTE, "Inserts the Clipboard contents after current line" }, + { IDM_E_PASTESPECIAL,"Allows pasting Clipboard data using a special format" }, + { IDM_E_CLEAR, "Clears the selection" }, + { IDM_E_SELECTALL, "Selects the entire outline" }, +#if defined( OLE_CNTR ) + { IDM_E_INSERTOBJECT, "Inserts new object after current line" }, + { IDM_E_EDITLINKS, "Edit and view links contained in the document" }, + { IDM_E_CONVERTVERB, "Converts or activates an object as another type" }, + { IDM_E_OBJECTVERBMIN, "Opens, edits or interacts with an object" }, + { IDM_E_OBJECTVERBMIN+1, "Opens, edits or interacts with an object1" }, + { IDM_E_OBJECTVERBMIN+2, "Opens, edits or interacts with an object2" }, + { IDM_E_OBJECTVERBMIN+3, "Opens, edits or interacts with an object3" }, + { IDM_E_OBJECTVERBMIN+4, "Opens, edits or interacts with an object4" }, + { IDM_E_OBJECTVERBMIN+5, "Opens, edits or interacts with an object5" }, +#endif + + { IDM_L_ADDLINE, "Adds a new line after current line" }, + { IDM_L_EDITLINE, "Edits the current line" }, + { IDM_L_INDENTLINE, "Indents the selection" }, + { IDM_L_UNINDENTLINE, "Unindents the selection" }, + { IDM_L_SETLINEHEIGHT, "Modify the height of a line" }, + + { IDM_N_DEFINENAME, "Assigns a name to the selection" }, + { IDM_N_GOTONAME, "Jumps to a specified place in the outline" }, + + { IDM_H_ABOUT, "Displays program info, version no., and copyright" }, + + { IDM_D_DEBUGLEVEL, "Set debug level (0-4)" }, + { IDM_D_INSTALLMSGFILTER,"Install/deinstall the IMessageFilter" }, + { IDM_D_REJECTINCOMING, "Return RETRYLATER to incoming method calls" }, + + { IDM_O_BB_TOP, "Position ButtonBar at top of window" }, + { IDM_O_BB_BOTTOM, "Position ButtonBar at botttom of window" }, + { IDM_O_BB_POPUP, "Put ButtonBar in popup pallet" }, + { IDM_O_BB_HIDE, "Hide ButtonBar" }, + + { IDM_O_FB_TOP, "Position FormulaBar at top of window" }, + { IDM_O_FB_BOTTOM, "Position FormulaBar at botttom of window" }, + { IDM_O_FB_POPUP, "Put FormulaBar in popup pallet" }, + + { IDM_O_HEAD_SHOW, "Show row/column headings" }, + { IDM_O_HEAD_HIDE, "Hide row/column headings" }, + { IDM_O_SHOWOBJECT, "Show border around objects/links" }, + + { IDM_V_ZOOM_400, "Set document zoom level" }, + { IDM_V_ZOOM_300, "Set document zoom level" }, + { IDM_V_ZOOM_200, "Set document zoom level" }, + { IDM_V_ZOOM_100, "Set document zoom level" }, + { IDM_V_ZOOM_75, "Set document zoom level" }, + { IDM_V_ZOOM_50, "Set document zoom level" }, + { IDM_V_ZOOM_25, "Set document zoom level" }, + + { IDM_V_SETMARGIN_0, "Remove left/right document margins" }, + { IDM_V_SETMARGIN_1, "Set left/right document margins" }, + { IDM_V_SETMARGIN_2, "Set left/right document margins" }, + { IDM_V_SETMARGIN_3, "Set left/right document margins" }, + { IDM_V_SETMARGIN_4, "Set left/right document margins" }, + + { IDM_V_ADDTOP_1, "Add top line" }, + { IDM_V_ADDTOP_2, "Add top line" }, + { IDM_V_ADDTOP_3, "Add top line" }, + { IDM_V_ADDTOP_4, "Add top line" } +}; + +#define NUM_STATS sizeof(MesgList)/sizeof(MesgList[0]) +#define NUM_POPUP 10 // Maximum number of popup messages. +#define MAX_MESSAGE 100 // Maximum characters in a popup message. diff --git a/private/oleutest/letest/outline/ole2.bmp b/private/oleutest/letest/outline/ole2.bmp new file mode 100644 index 000000000..f1d0cbbf7 Binary files /dev/null and b/private/oleutest/letest/outline/ole2.bmp differ diff --git a/private/oleutest/letest/outline/oleapp.c b/private/oleutest/letest/outline/oleapp.c new file mode 100644 index 000000000..0f355307b --- /dev/null +++ b/private/oleutest/letest/outline/oleapp.c @@ -0,0 +1,2989 @@ +/************************************************************************* +** +** OLE 2 Sample Code +** +** oleapp.c +** +** This file contains functions and methods that are common to +** server and the client version of the app. This includes the class +** factory methods and all OleApp functions. +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + +#include "outline.h" +#include + +OLEDBGDATA + +extern LPOUTLINEAPP g_lpApp; + +extern IUnknownVtbl g_OleApp_UnknownVtbl; + +extern IUnknownVtbl g_OleDoc_UnknownVtbl; +extern IPersistFileVtbl g_OleDoc_PersistFileVtbl; +extern IOleItemContainerVtbl g_OleDoc_OleItemContainerVtbl; +extern IExternalConnectionVtbl g_OleDoc_ExternalConnectionVtbl; +extern IDataObjectVtbl g_OleDoc_DataObjectVtbl; + +#if defined( USE_DRAGDROP ) +extern IDropTargetVtbl g_OleDoc_DropTargetVtbl; +extern IDropSourceVtbl g_OleDoc_DropSourceVtbl; +#endif // USE_DRAGDROP + +#if defined( OLE_SERVER ) +extern IOleObjectVtbl g_SvrDoc_OleObjectVtbl; +extern IPersistStorageVtbl g_SvrDoc_PersistStorageVtbl; + +#if defined( SVR_TREATAS ) +extern IStdMarshalInfoVtbl g_SvrDoc_StdMarshalInfoVtbl; +#endif // SVR_TREATAS + +extern IUnknownVtbl g_PseudoObj_UnknownVtbl; +extern IOleObjectVtbl g_PseudoObj_OleObjectVtbl; +extern IDataObjectVtbl g_PseudoObj_DataObjectVtbl; + +#if defined( INPLACE_SVR ) +extern IOleInPlaceObjectVtbl g_SvrDoc_OleInPlaceObjectVtbl; +extern IOleInPlaceActiveObjectVtbl g_SvrDoc_OleInPlaceActiveObjectVtbl; +#endif // INPLACE_SVR + +#endif // OLE_SERVER + +#if defined( OLE_CNTR ) + +extern IOleUILinkContainerVtbl g_CntrDoc_OleUILinkContainerVtbl; +extern IUnknownVtbl g_CntrLine_UnknownVtbl; +extern IOleClientSiteVtbl g_CntrLine_OleClientSiteVtbl; +extern IAdviseSinkVtbl g_CntrLine_AdviseSinkVtbl; + +#if defined( INPLACE_CNTR ) +extern IOleInPlaceSiteVtbl g_CntrLine_OleInPlaceSiteVtbl; +extern IOleInPlaceFrameVtbl g_CntrApp_OleInPlaceFrameVtbl; +extern BOOL g_fInsideOutContainer; +#endif // INPLACE_CNTR + +#endif // OLE_CNTR + +// REVIEW: these are NOT useful end-user messages +static char ErrMsgCreateCF[] = "Can't create Class Factory!"; +static char ErrMsgRegCF[] = "Can't register Class Factory!"; +static char ErrMsgRegMF[] = "Can't register Message Filter!"; + +extern UINT g_uMsgHelp; + + +/* OleApp_InitInstance + * ------------------- + * + * Initialize the app instance by creating the main frame window and + * performing app instance specific initializations + * (eg. initializing interface Vtbls). + * + * RETURNS: TRUE if the memory could be allocated, and the server app + * was properly initialized. + * FALSE otherwise + * + */ +BOOL OleApp_InitInstance(LPOLEAPP lpOleApp, HINSTANCE hInst, int nCmdShow) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpOleApp; + HRESULT hrErr; + DWORD dwBuildVersion = OleBuildVersion(); + LPMALLOC lpMalloc = NULL; + + OLEDBG_BEGIN3("OleApp_InitInstance\r\n") + + lpOleApp->m_fOleInitialized = FALSE; + + /* OLE2NOTE: check if the build version of the OLE2 DLL's match + ** what our application is expecting. + */ + if (HIWORD(dwBuildVersion) != rmm || LOWORD(dwBuildVersion) < rup) { + OleDbgAssertSz(0, "ERROR: OLE 2.0 DLL's are NOT compatible!"); + +#if !defined( _DEBUG ) + return FALSE; // Wrong version of DLL's +#endif + } + +#if defined( _DEBUG ) + /* OLE2NOTE: Use a special debug allocator to help track down + ** memory leaks. + */ + OleStdCreateDbAlloc(0, &lpMalloc); +#endif + /* OLE2NOTE: the OLE libraries must be properly initialized before + ** making any calls. OleInitialize automatically calls + ** CoInitialize. we will use the default task memory allocator + ** therefore we pass NULL to OleInitialize. + */ + OLEDBG_BEGIN2("OleInitialize called\r\n") + hrErr = OleInitialize(lpMalloc); + + if (FAILED(hrErr)) + { + // Replacing the allocator may not be legal - try initializing + // without overriding the allocator + hrErr = OleInitialize(NULL); + } + + OLEDBG_END2 + +#if defined( _DEBUG ) + /* OLE2NOTE: release the special debug allocator so that only OLE is + ** holding on to it. later when OleUninitialize is called, then + ** the debug allocator object will be destroyed. when the debug + ** allocator object is destoyed, it will report (to the Output + ** Debug Terminal) whether there are any memory leaks. + */ + if (lpMalloc) lpMalloc->lpVtbl->Release(lpMalloc); +#endif + + if (hrErr != NOERROR) { + OutlineApp_ErrorMessage(lpOutlineApp,"OLE initialization failed!"); + goto error; + } + + /***************************************************************** + ** OLE2NOTE: we must remember the fact that OleInitialize has + ** been call successfully. the very last thing an app must + ** be do is properly shut down OLE by calling + ** OleUninitialize. This call MUST be guarded! it is only + ** allowable to call OleUninitialize if OleInitialize has + ** been called SUCCESSFULLY. + *****************************************************************/ + + lpOleApp->m_fOleInitialized = TRUE; + + // Initialize the OLE 2.0 interface method tables. + if (! OleApp_InitVtbls(lpOleApp)) + goto error; + + // Register OLE 2.0 clipboard formats. + lpOleApp->m_cfEmbedSource = RegisterClipboardFormat(CF_EMBEDSOURCE); + lpOleApp->m_cfEmbeddedObject = RegisterClipboardFormat( + CF_EMBEDDEDOBJECT + ); + lpOleApp->m_cfLinkSource = RegisterClipboardFormat(CF_LINKSOURCE); + lpOleApp->m_cfFileName = RegisterClipboardFormat(CF_FILENAME); + lpOleApp->m_cfObjectDescriptor = + RegisterClipboardFormat(CF_OBJECTDESCRIPTOR); + lpOleApp->m_cfLinkSrcDescriptor = + RegisterClipboardFormat(CF_LINKSRCDESCRIPTOR); + + lpOleApp->m_cRef = 0; + lpOleApp->m_cDoc = 0; + lpOleApp->m_fUserCtrl = FALSE; + lpOleApp->m_dwRegClassFac = 0; + lpOleApp->m_lpClassFactory = NULL; + lpOleApp->m_cModalDlgActive = 0; + + INIT_INTERFACEIMPL( + &lpOleApp->m_Unknown, + &g_OleApp_UnknownVtbl, + lpOleApp + ); + +#if defined( USE_DRAGDROP ) + + // delay before dragging should start, in milliseconds + lpOleApp->m_nDragDelay = GetProfileInt( + "windows", + "DragDelay", + DD_DEFDRAGDELAY + ); + + // minimum distance (radius) before drag should start, in pixels + lpOleApp->m_nDragMinDist = GetProfileInt( + "windows", + "DragMinDist", + DD_DEFDRAGMINDIST + ); + + // delay before scrolling, in milliseconds + lpOleApp->m_nScrollDelay = GetProfileInt( + "windows", + "DragScrollDelay", + DD_DEFSCROLLDELAY + ); + + // inset-width of the hot zone, in pixels + lpOleApp->m_nScrollInset = GetProfileInt( + "windows", + "DragScrollInset", + DD_DEFSCROLLINSET + ); + + // scroll interval, in milliseconds + lpOleApp->m_nScrollInterval = GetProfileInt( + "windows", + "DragScrollInterval", + DD_DEFSCROLLINTERVAL + ); + +#if defined( IF_SPECIAL_DD_CURSORS_NEEDED ) + // This would be used if the app wanted to have custom drag/drop cursors + lpOleApp->m_hcursorDragNone = LoadCursor ( hInst, "DragNoneCur" ); + lpOleApp->m_hcursorDragCopy = LoadCursor ( hInst, "DragCopyCur" ); + lpOleApp->m_hcursorDragMove = LoadCursor ( hInst, "DragMoveCur" ); + lpOleApp->m_hcursorDragLink = LoadCursor ( hInst, "DragLinkCur" ); +#endif // IF_SPECIAL_DD_CURSORS_NEEDED + +#endif // USE_DRAGDROP + + lpOleApp->m_lpMsgFilter = NULL; + +#if defined( USE_MSGFILTER ) + /* OLE2NOTE: Register our message filter upon app startup. the + ** message filter is used to handle concurrency. + ** we will use a standard implementation of IMessageFilter that + ** is included as part of the OLE2UI library. + */ + lpOleApp->m_lpMsgFilter = NULL; + if (! OleApp_RegisterMessageFilter(lpOleApp)) + goto error; + + /* OLE2NOTE: because our app is initially INVISIBLE, we must + ** DISABLE the busy dialog. we should NOT put up any dialogs if + ** our app is invisible. when our app window is made visible, + ** then the busy dialog will be enabled. + */ + OleStdMsgFilter_EnableBusyDialog(lpOleApp->m_lpMsgFilter, FALSE); +#endif // USE_MSGFILTER + +#if defined( OLE_SERVER ) + /* OLE2NOTE: perform initialization specific for an OLE server */ + if (! ServerApp_InitInstance((LPSERVERAPP)lpOutlineApp, hInst, nCmdShow)) + goto error; +#endif +#if defined( OLE_CNTR ) + /* OLE2NOTE: perform initialization specific for an OLE container */ + + // Register help message + g_uMsgHelp = RegisterWindowMessage(SZOLEUI_MSG_HELP); + + if (! ContainerApp_InitInstance((LPCONTAINERAPP)lpOutlineApp, hInst, nCmdShow)) + goto error; +#endif + +#if defined( OLE_CNTR ) + lpOleApp->m_hStdPal = OleStdCreateStandardPalette(); +#endif + + OLEDBG_END3 + return TRUE; + +error: + OLEDBG_END3 + return FALSE; +} + + +/* + * OleApp_TerminateApplication + * --------------------------- + * Perform proper OLE application cleanup before shutting down + */ +void OleApp_TerminateApplication(LPOLEAPP lpOleApp) +{ + OLEDBG_BEGIN3("OleApp_TerminateApplication\r\n") + + /* OLE2NOTE: perform a clean shut down for OLE. at this point our + ** App refcnt should be 0, or else we should never have reached + ** this point! + */ + OleDbgAssertSz(lpOleApp->m_cRef == 0, "App NOT shut down properly"); + + if(lpOleApp->m_fOleInitialized) { + OLEDBG_BEGIN2("OleUninitialize called\r\n") + OleUninitialize(); + OLEDBG_END2 + } + OLEDBG_END3 +} + + +/* OleApp_ParseCmdLine + * ------------------- + * + * Parse the command line for any execution flags/arguments. + * OLE2NOTE: check if "-Embedding" switch is given. + */ +BOOL OleApp_ParseCmdLine(LPOLEAPP lpOleApp, LPSTR lpszCmdLine, int nCmdShow) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpOleApp; + char szFileName[256]; /* buffer for filename in command line */ + BOOL fStatus = TRUE; + BOOL fEmbedding = FALSE; + + OLEDBG_BEGIN3("OleApp_ParseCmdLine\r\n") + + szFileName[0] = '\0'; + ParseCmdLine(lpszCmdLine, &fEmbedding, (LPSTR)szFileName); + +#if defined( MDI_VERSION ) + /* OLE2NOTE: an MDI app would ALWAYS register its ClassFactory. it + ** can handle multiple objects at the same time, while an SDI + ** application can only handle a single embedded or file-based + ** object at a time. + */ + fStatus = OleApp_RegisterClassFactory(lpOleApp); +#endif + + if(fEmbedding) { + + if (szFileName[0] == '\0') { + + /***************************************************************** + ** App was launched with /Embedding. + ** We must register our ClassFactory with OLE, remain hidden + ** (the app window is initially created not visible), and + ** wait for OLE to call IClassFactory::CreateInstance + ** method. We do not automatically create a document as we + ** do when the app is launched by the user from the + ** FileManager. We must NOT make our app window visible + ** until told to do so by our container. + ** + ** OLE2NOTE: Because we are an SDI app, we only register our + ** ClassFactory if we are launched with the /Embedding + ** flag WITHOUT a filename. an MDI app would ALWAYS + ** register its ClassFactory. it can handle multiple + ** objects at the same time, while an SDI application + ** can only handle a single embedded or file-based + ** object at a time. + *****************************************************************/ + +#if defined( SDI_VERSION ) + fStatus = OleApp_RegisterClassFactory(lpOleApp); +#endif + } else { + + /***************************************************************** + ** App was launched with /Embedding . + ** We must create a document and load the file and + ** register it in the RunningObjectTable BEFORE we + ** enter our GetMessage loop (ie. before we yield). + ** One way to perform these tasks is to call the same + ** interface methods that OLE 2.0 calls for linking to a + ** file: + ** IClassFactory::CreateInstance + ** IPersistFile::Load + ** + ** We must NOT make our app window visible until told to + ** do so by our container. An application will be + ** launched in this manner by an OLE 1.0 application + ** link situation (eg. double clicking a linked object + ** or OleCreateLinkFromFile called). + ** + ** OLE2NOTE: Because we are an SDI app, we should NOT + ** register our ClassFactory when we are launched with the + ** /Embedding flag. our SDI instance can only + ** handle a single embedded or file-based object. + ** an MDI app WOULD register its ClassFactory at all + ** times because it can handle multiple objects. + *****************************************************************/ + + // allocate a new document object + lpOutlineApp->m_lpDoc = OutlineApp_CreateDoc(lpOutlineApp, FALSE); + if (! lpOutlineApp->m_lpDoc) { + OLEDBG_END3 + return FALSE; + } + + /* OLE2NOTE: initially the Doc object is created with a 0 ref + ** count. in order to have a stable Doc object during the + ** process of initializing the new Doc instance, + ** we intially AddRef the Doc ref cnt and later + ** Release it. This initial AddRef is artificial; it is simply + ** done to guarantee that a harmless QueryInterface followed by + ** a Release does not inadvertantly force our object to destroy + ** itself prematurely. + */ + OleDoc_AddRef((LPOLEDOC)lpOutlineApp->m_lpDoc); + + /* OLE2NOTE: OutlineDoc_LoadFromFile will register our document + ** in the RunningObjectTable. this registration will + ** AddRef our document. therefore our document will not + ** be destroyed when we release the artificial AddRef + */ + fStatus = OutlineDoc_LoadFromFile( + lpOutlineApp->m_lpDoc, (LPSTR)szFileName); + + OleDoc_Release((LPOLEDOC)lpOutlineApp->m_lpDoc); // rel AddRef + + OLEDBG_END3 + return fStatus; + } + } else { + + /***************************************************************** + ** App was launched by the user (without /Embedding) and + ** therefore is marked to be under user control. + ** In this case, because we are an SDI app, we do NOT + ** register our ClassFactory with OLE. This app instance can + ** only manage one document at a time (either a user + ** document or an embedded object document). An MDI app + ** would register its ClassFactory here. + ** + ** We must create a document for the user (either + ** initialized from a file given on the command line or + ** initialized as an untitled document. We must also make + ** our app window visible to the user. + *****************************************************************/ + + // allocate a new document object + lpOutlineApp->m_lpDoc = OutlineApp_CreateDoc(lpOutlineApp, FALSE); + if (! lpOutlineApp->m_lpDoc) goto error; + + /* OLE2NOTE: initially the Doc object is created with a 0 ref + ** count. in order to have a stable Doc object during the + ** process of initializing the new Doc instance, + ** we intially AddRef the Doc ref cnt and later + ** Release it. This initial AddRef is artificial; it is simply + ** done to guarantee that a harmless QueryInterface followed by + ** a Release does not inadvertantly force our object to destroy + ** itself prematurely. + */ + OleDoc_AddRef((LPOLEDOC)lpOutlineApp->m_lpDoc); + + if(*szFileName) { + // initialize the document from the specified file + if (! OutlineDoc_LoadFromFile(lpOutlineApp->m_lpDoc, szFileName)) + goto error; + } else { + // set the doc to an (Untitled) doc. + if (! OutlineDoc_InitNewFile(lpOutlineApp->m_lpDoc)) + goto error; + } + + // position and size the new doc window + OutlineApp_ResizeWindows(lpOutlineApp); + OutlineDoc_ShowWindow(lpOutlineApp->m_lpDoc); // calls OleDoc_Lock + OleDoc_Release((LPOLEDOC)lpOutlineApp->m_lpDoc);// rel AddRef above + + // show main app window + ShowWindow(lpOutlineApp->m_hWndApp, nCmdShow); + UpdateWindow(lpOutlineApp->m_hWndApp); + +#if defined( OLE_CNTR ) + ContainerDoc_UpdateLinks((LPCONTAINERDOC)lpOutlineApp->m_lpDoc); +#endif + + } + + OLEDBG_END3 + return fStatus; + +error: + // REVIEW: should load string from string resource + OutlineApp_ErrorMessage( + lpOutlineApp, + "Could not create document--Out of Memory" + ); + if (lpOutlineApp->m_lpDoc) // rel artificial AddRef above + OleDoc_Release((LPOLEDOC)lpOutlineApp->m_lpDoc); + + OLEDBG_END3 + return FALSE; +} + + +/* OleApp_CloseAllDocsAndExitCommand + * --------------------------------- + * + * Close all active documents and exit the app. + * Because this is an SDI, there is only one document + * If the doc was modified, prompt the user if he wants to save it. + * + * Returns: + * TRUE if the app is successfully closed + * FALSE if failed or aborted + * + * OLE2NOTE: in the OLE version, we can NOT directly + * destroy the App object. we can only take all + * necessary actions to ensure that our object receives + * all of its Releases from clients holding onto + * pointers (eg. closing all docs and flushing the + * clipboard) and then we must hide our window and wait + * actually for our refcnt to reach 0. when it reaches 0, + * our destructor (OutlineApp_Destroy) will be called. + * each document addref's the app object in order to + * guarentee that the app does not shut down while the doc + * is still open. closing all docs, will release these + * refcnt's. if there are now more open documents AND the + * app is not under the control of the user (ie. launched by + * OLE) then the app will now shut down. the OleApp_Release + * function executes this shut down procedure. after closing + * all docs, then releasing the user refcnt will force the + * app to shut down. + */ +BOOL OleApp_CloseAllDocsAndExitCommand( + LPOLEAPP lpOleApp, + BOOL fForceEndSession +) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpOleApp; + DWORD dwSaveOption = (fForceEndSession ? + OLECLOSE_NOSAVE : OLECLOSE_PROMPTSAVE); + + /* OLE2NOTE: in order to have a stable App object during the + ** process of closing, we intially AddRef the App ref cnt and + ** later Release it. This initial AddRef is artificial; it is + ** simply done to guarantee that our App object does not + ** destroy itself until the end of this routine. + */ + OleApp_AddRef(lpOleApp); + + /* Because this is an SDI app, there is only one document. + ** Close the doc. if it is successfully closed and the app will + ** not automatically exit, then also exit the app. + ** if this were an MDI app, we would loop through and close all + ** open MDI child documents. + */ + +#if defined( OLE_SERVER ) + if (!fForceEndSession && + lpOutlineApp->m_lpDoc->m_docInitType == DOCTYPE_EMBEDDED) + dwSaveOption = OLECLOSE_SAVEIFDIRTY; +#endif + + if (! OutlineDoc_Close(lpOutlineApp->m_lpDoc, dwSaveOption)) { + OleApp_Release(lpOleApp); + return FALSE; // User Aborted shutdown + } +#if defined( _DEBUG ) + OleDbgAssertSz( + lpOutlineApp->m_lpDoc==NULL, + "Closed doc NOT properly destroyed" + ); +#endif + +#if defined( OLE_CNTR ) + /* if we currently have data on the clipboard then we must tell + ** the clipboard to release our clipboard data object + ** (document) + */ + if (lpOutlineApp->m_lpClipboardDoc) + OleApp_FlushClipboard(lpOleApp); +#endif + + OleApp_HideWindow(lpOleApp); + + /* OLE2NOTE: this call forces all external connections to our + ** object to close down and therefore guarantees that we receive + ** all releases associated with those external connections. + */ + OLEDBG_BEGIN2("CoDisconnectObject(lpApp) called\r\n") + CoDisconnectObject((LPUNKNOWN)&lpOleApp->m_Unknown, 0); + OLEDBG_END2 + + OleApp_Release(lpOleApp); // release artificial AddRef above + + return TRUE; +} + + +/* OleApp_ShowWindow + * ----------------- + * + * Show the window of the app to the user. + * make sure app window is visible and bring the app to the top. + * IF fGiveUserCtrl == TRUE + * THEN give the user the control over the life-time of the app. + */ +void OleApp_ShowWindow(LPOLEAPP lpOleApp, BOOL fGiveUserCtrl) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpOleApp; + + OLEDBG_BEGIN3("OleApp_ShowWindow\r\n") + + /* OLE2NOTE: while the application is visible and under user + ** control, we do NOT want it to be prematurely destroyed when + ** the user closes a document. thus we must inform OLE to hold + ** an external lock on our application on behalf of the user. + ** this arranges that OLE holds at least 1 reference to our + ** application that will NOT be released until we release this + ** external lock. later, when the application window is hidden, we + ** will release this external lock. + */ + if (fGiveUserCtrl && ! lpOleApp->m_fUserCtrl) { + lpOleApp->m_fUserCtrl = TRUE; + OleApp_Lock(lpOleApp, TRUE /* fLock */, 0 /* not applicable */); + } + + // we must show our App window and force it to have input focus + ShowWindow(lpOutlineApp->m_hWndApp, SW_SHOWNORMAL); + SetFocus(lpOutlineApp->m_hWndApp); + + /* OLE2NOTE: because our app is now visible, we can enable the busy + ** dialog. we should NOT put up any dialogs if our app is + ** invisible. + */ + OleApp_EnableBusyDialogs(lpOleApp, TRUE, TRUE); + + OLEDBG_END3 +} + + +/* OleApp_HideWindow + * ----------------- + * + * Hide the window of the app from the user. + * take away the control of the app by the user. + */ +void OleApp_HideWindow(LPOLEAPP lpOleApp) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpOleApp; + + OLEDBG_BEGIN3("OleApp_HideWindow\r\n") + + /* OLE2NOTE: the application is now being hidden, so we must release + ** the external lock that was made on behalf of the user. + ** if this is that last external lock on our application, thus + ** enabling our application to complete its shutdown operation. + */ + if (lpOleApp->m_fUserCtrl) { + lpOleApp->m_fUserCtrl = FALSE; + OleApp_Lock(lpOleApp, FALSE /*fLock*/, TRUE /*fLastUnlockReleases*/); + } + + ShowWindow(lpOutlineApp->m_hWndApp, SW_HIDE); + + /* OLE2NOTE: because our app is now INVISIBLE, we must DISABLE the busy + ** dialog. we should NOT put up any dialogs if our app is + ** invisible. + */ + OleApp_EnableBusyDialogs(lpOleApp, FALSE, FALSE); + OLEDBG_END3 +} + + +/* OleApp_Lock +** ----------- +** Lock/Unlock the App object. if the last lock is unlocked and +** fLastUnlockReleases == TRUE, then the app object will shut down +** (ie. it will recieve its final release and its refcnt will go to 0). +*/ +HRESULT OleApp_Lock(LPOLEAPP lpOleApp, BOOL fLock, BOOL fLastUnlockReleases) +{ + HRESULT hrErr; + +#if defined( _DEBUG ) + if (fLock) { + OLEDBG_BEGIN2("CoLockObjectExternal(lpApp,TRUE) called\r\n") + } else { + if (fLastUnlockReleases) + OLEDBG_BEGIN2("CoLockObjectExternal(lpApp,FALSE,TRUE) called\r\n") + else + OLEDBG_BEGIN2("CoLockObjectExternal(lpApp,FALSE,FALSE) called\r\n") + } +#endif // _DEBUG + + OleApp_AddRef(lpOleApp); // artificial AddRef to make object stable + + hrErr = CoLockObjectExternal( + (LPUNKNOWN)&lpOleApp->m_Unknown, fLock, fLastUnlockReleases); + + OleApp_Release(lpOleApp); // release artificial AddRef above + + OLEDBG_END2 + return hrErr; +} + + +/* OleApp_Destroy + * -------------- + * + * Free all OLE related resources that had been allocated for the app. + */ +void OleApp_Destroy(LPOLEAPP lpOleApp) +{ + // OLE2NOTE: Revoke our message filter upon app shutdown. + OleApp_RevokeMessageFilter(lpOleApp); + + // OLE2NOTE: Revoke our ClassFactory upon app shutdown. + OleApp_RevokeClassFactory(lpOleApp); + +#if defined( IF_SPECIAL_DD_CURSORS_NEEDED ) + // This would be used if the app wanted to have custom drag/drop cursors + DestroyCursor(lpOleApp->m_hcursorDragNone); + DestroyCursor(lpOleApp->m_hcursorDragCopy); + DestroyCursor(lpOleApp->m_hcursorDragLink); + DestroyCursor(lpOleApp->m_hcursorDragMove); +#endif // IF_SPECIAL_DD_CURSORS_NEEDED + +#if defined( OLE_CNTR ) + if (lpOleApp->m_hStdPal) { + DeleteObject(lpOleApp->m_hStdPal); + lpOleApp->m_hStdPal = NULL; + } +#endif +} + + +/* OleApp_DocLockApp +** ----------------- +** Add a lock on the App on behalf of the Doc. the App may not close +** while the Doc exists. +** +** when a document is first created, it calls this method to +** guarantee that the application stays alive (OleDoc_Init). +** when a document is destroyed, it calls +** OleApp_DocUnlockApp to release this hold on the app. +*/ +void OleApp_DocLockApp(LPOLEAPP lpOleApp) +{ + ULONG cDoc; + + OLEDBG_BEGIN3("OleApp_DocLockApp\r\n") + + cDoc = ++lpOleApp->m_cDoc; + + OleDbgOutRefCnt3("OleApp_DocLockApp: cDoc++\r\n", lpOleApp, cDoc); + + OleApp_Lock(lpOleApp, TRUE /* fLock */, 0 /* not applicable */); + + OLEDBG_END3 + return; +} + + +/* OleApp_DocUnlockApp +** ------------------- +** Forget all references to a closed document. +** Release the lock on the App on behalf of the Doc. if this was the +** last lock on the app, then it will shutdown. +*/ +void OleApp_DocUnlockApp(LPOLEAPP lpOleApp, LPOUTLINEDOC lpOutlineDoc) +{ + ULONG cDoc; + + OLEDBG_BEGIN3("OleApp_DocUnlockApp\r\n") + + /* OLE2NOTE: when there are no open documents and the app is not + ** under the control of the user then revoke our ClassFactory to + ** enable the app to shut down. + */ + cDoc = --lpOleApp->m_cDoc; + +#if defined( _DEBUG ) + OleDbgAssertSz ( + lpOleApp->m_cDoc >= 0, "DocUnlockApp called with cDoc == 0"); + + OleDbgOutRefCnt3( + "OleApp_DocUnlockApp: cDoc--\r\n", lpOleApp, cDoc); +#endif + + OleApp_Lock(lpOleApp, FALSE /* fLock */, TRUE /* fLastUnlockReleases */); + + OLEDBG_END3 + return; +} + + +/* OleApp_HideIfNoReasonToStayVisible +** ---------------------------------- +** +** if there are no more documents visible to the user and the app +** itself is not under user control, then it has no reason to stay +** visible. we thus should hide the app. we can not directly destroy +** the app, because it may be validly being used programatically by +** another client application and should remain running. the app +** should simply be hidden from the user. +*/ +void OleApp_HideIfNoReasonToStayVisible(LPOLEAPP lpOleApp) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpOleApp; + LPOUTLINEDOC lpOutlineDoc; + + OLEDBG_BEGIN3("OleApp_HideIfNoReasonToStayVisible\r\n") + + if (lpOleApp->m_fUserCtrl) { + OLEDBG_END3 + return; // remain visible; user in control of app + } + + /* Because this is an SDI app, there is only one user document. + ** check if it is visible to the user. an MDI app would loop over + ** all open MDI child documents to see if any are visible. + */ + lpOutlineDoc = (LPOUTLINEDOC)lpOutlineApp->m_lpDoc; + if (lpOutlineDoc && IsWindowVisible(lpOutlineDoc->m_hWndDoc)) + return; // remain visible; the doc is visible to the user + + // if we reached here, the app should be hidden + OleApp_HideWindow(lpOleApp); + + OLEDBG_END3 +} + + +/* OleApp_AddRef +** ------------- +** +** increment the ref count of the App object. +** +** Returns the new ref count on the object +*/ +ULONG OleApp_AddRef(LPOLEAPP lpOleApp) +{ + ++lpOleApp->m_cRef; + +#if defined( _DEBUG ) + OleDbgOutRefCnt4( + "OleApp_AddRef: cRef++\r\n", + lpOleApp, + lpOleApp->m_cRef + ); +#endif + return lpOleApp->m_cRef; +} + + +/* OleApp_Release +** -------------- +** +** decrement the ref count of the App object. +** if the ref count goes to 0, then the app object is destroyed. +** +** Returns the remaining ref count on the object +*/ +ULONG OleApp_Release (LPOLEAPP lpOleApp) +{ + ULONG cRef; + + cRef = --lpOleApp->m_cRef; + +#if defined( _DEBUG ) + OleDbgAssertSz (lpOleApp->m_cRef >= 0, "Release called with cRef == 0"); + + OleDbgOutRefCnt4( + "OleApp_AddRef: cRef--\r\n", lpOleApp, cRef); +#endif // _DEBUG + /********************************************************************* + ** OLE2NOTE: when the ClassFactory refcnt == 0, then destroy it. ** + ** otherwise the ClassFactory is still in use. ** + *********************************************************************/ + + if(cRef == 0) + OutlineApp_Destroy((LPOUTLINEAPP)lpOleApp); + + return cRef; +} + + + +/* OleApp_QueryInterface +** --------------------- +** +** Retrieve a pointer to an interface on the app object. +** +** OLE2NOTE: this function will AddRef the ref cnt of the object. +** +** Returns NOERROR if interface is successfully retrieved. +** E_NOINTERFACE if the interface is not supported +*/ +HRESULT OleApp_QueryInterface ( + LPOLEAPP lpOleApp, + REFIID riid, + LPVOID FAR* lplpvObj +) +{ + SCODE sc; + + /* OLE2NOTE: we must make sure to set all out ptr parameters to NULL. */ + *lplpvObj = NULL; + + if (IsEqualIID(riid, &IID_IUnknown)) { + OleDbgOut4("OleApp_QueryInterface: IUnknown* RETURNED\r\n"); + + *lplpvObj = (LPVOID) &lpOleApp->m_Unknown; + OleApp_AddRef(lpOleApp); + sc = S_OK; + } + else { + sc = E_NOINTERFACE; + } + + OleDbgQueryInterfaceMethod(*lplpvObj); + return ResultFromScode(sc); +} + + +/* OleApp_RejectInComingCalls +** ------------------------- +** Reject/Handle in coming OLE (LRPC) calls. +** +** OLE2NOTE: if the app is in a state when it can NOT handle in +** coming OLE method calls from an external process (eg. the app has +** an application modal dialog up), then it should call +** OleApp_RejectInComingCalls(TRUE). in this state the +** IMessageFilter::HandleInComingCall method will return +** SERVERCALL_RETRYLATER. this tells the caller to try again in a +** little while. normally the calling app will put up a dialog (see +** OleUIBusy dialog) in this situation informing the user of the +** situation. the user then is normally given the option to +** "Switch To..." the busy application, retry, or cancel the +** operation. when the app is ready to continue processing such +** calls, it should call OleApp_RejectInComingCalls(FALSE). in this +** state, SERVERCALL_ISHANDLED is returned by +** IMessageFilter::HandleInComingCall. +*/ +void OleApp_RejectInComingCalls(LPOLEAPP lpOleApp, BOOL fReject) +{ +#if defined( _DEBUG ) + if (fReject) + OleDbgOut3("OleApp_RejectInComingCalls(TRUE)\r\n"); + else + OleDbgOut3("OleApp_RejectInComingCalls(FALSE)\r\n"); +#endif // _DEBUG + + OleDbgAssert(lpOleApp->m_lpMsgFilter != NULL); + if (! lpOleApp->m_lpMsgFilter) + return; + + OleStdMsgFilter_SetInComingCallStatus( + lpOleApp->m_lpMsgFilter, + (fReject ? SERVERCALL_RETRYLATER : SERVERCALL_ISHANDLED) + ); +} + + +/* OleApp_DisableBusyDialogs +** ------------------------- +** Disable the Busy and NotResponding dialogs. +** +** Returns previous enable state so that it can be restored by +** calling OleApp_ReEnableBusyDialogs. +*/ +void OleApp_DisableBusyDialogs( + LPOLEAPP lpOleApp, + BOOL FAR* lpfPrevBusyEnable, + BOOL FAR* lpfPrevNREnable +) +{ + if (lpOleApp->m_lpMsgFilter) { + *lpfPrevNREnable = OleStdMsgFilter_EnableNotRespondingDialog( + lpOleApp->m_lpMsgFilter, FALSE); + *lpfPrevBusyEnable = OleStdMsgFilter_EnableBusyDialog( + lpOleApp->m_lpMsgFilter, FALSE); + } +} + + +/* OleApp_EnableBusyDialogs +** ------------------------ +** Set the enable state of the Busy and NotResponding dialogs. +** +** This function is typically used after a call to +** OleApp_DisableBusyDialogs in order to restore the previous enable +** state of the dialogs. +*/ +void OleApp_EnableBusyDialogs( + LPOLEAPP lpOleApp, + BOOL fPrevBusyEnable, + BOOL fPrevNREnable +) +{ + if (lpOleApp->m_lpMsgFilter) { + OleStdMsgFilter_EnableNotRespondingDialog( + lpOleApp->m_lpMsgFilter, fPrevNREnable); + OleStdMsgFilter_EnableBusyDialog( + lpOleApp->m_lpMsgFilter, fPrevBusyEnable); + } +} + + +/* OleApp_PreModalDialog +** --------------------- +** Keep track that a modal dialog is about to be brought up. +** +** while a modal dialog is up we need to take special actions: +** 1. we do NOT want to initialize our tool bar buttons on +** WM_ACTIVATEAPP. the tool bar is not accessible. +** 2. we want to reject new top-level, incoming LRPC calls +** (return SERVERCALL_RETRYLATER from IMessageFilter:: +** HandleInComingCall). +** 3. (IN-PLACE SERVER) tell our in-place container to disable +** modeless dialogs by calling IOleInPlaceFrame:: +** EnableModeless(FALSE). +** 4. (IN-PLACE CONTAINER) tell our UIActive in-place object to +** disable modeless dialogs by calling IOleInPlaceActiveObject:: +** EnableModeless(FALSE). +*/ +void OleApp_PreModalDialog(LPOLEAPP lpOleApp, LPOLEDOC lpOleDoc) +{ + if (lpOleApp->m_cModalDlgActive == 0) { + // top-level modal dialog is being brought up + +#if defined( USE_FRAMETOOLS ) + LPFRAMETOOLS lptb; + + if (lpOleDoc) + lptb = ((LPOUTLINEDOC)lpOleDoc)->m_lpFrameTools; + else + lptb = OutlineApp_GetFrameTools((LPOUTLINEAPP)lpOleApp); + if (lptb) + FrameTools_EnableWindow(lptb, FALSE); +#endif // USE_FRAMETOOLS + + OleApp_RejectInComingCalls(lpOleApp, TRUE); + +#if defined( INPLACE_SVR ) + { + LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOleDoc; + + /* if the document bringing up the modal dialog is + ** currently a UIActive in-place object, then tell the + ** top-level in-place frame to disable its modeless + ** dialogs. + */ + if (lpServerDoc && lpServerDoc->m_fUIActive && + lpServerDoc->m_lpIPData && + lpServerDoc->m_lpIPData->lpFrame) { + OLEDBG_BEGIN2("IOleInPlaceFrame::EnableModless(FALSE) called\r\n"); + lpServerDoc->m_lpIPData->lpFrame->lpVtbl->EnableModeless( + lpServerDoc->m_lpIPData->lpFrame, FALSE); + OLEDBG_END2 + } + } +#endif // INPLACE_SVR +#if defined( INPLACE_CNTR ) + { + LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)lpOleApp; + + /* if the document bringing up the modal dialog is an + ** in-place container that has a UIActive object, then + ** tell the UIActive object to disable its modeless + ** dialogs. + */ + if (lpContainerApp->m_lpIPActiveObj) { + OLEDBG_BEGIN2("IOleInPlaceActiveObject::EnableModless(FALSE) called\r\n"); + lpContainerApp->m_lpIPActiveObj->lpVtbl->EnableModeless( + lpContainerApp->m_lpIPActiveObj, FALSE); + OLEDBG_END2 + } + } +#endif // INPLACE_CNTR + } + + lpOleApp->m_cModalDlgActive++; +} + + +/* OleApp_PostModalDialog +** ---------------------- +** Keep track that a modal dialog is being brought down. this call +** balances the OleApp_PreModalDialog call. +*/ +void OleApp_PostModalDialog(LPOLEAPP lpOleApp, LPOLEDOC lpOleDoc) +{ + lpOleApp->m_cModalDlgActive--; + + if (lpOleApp->m_cModalDlgActive == 0) { + // last modal dialog is being brought down + +#if defined( USE_FRAMETOOLS ) + LPFRAMETOOLS lptb; + + if (lpOleDoc) + lptb = ((LPOUTLINEDOC)lpOleDoc)->m_lpFrameTools; + else + lptb = OutlineApp_GetFrameTools((LPOUTLINEAPP)lpOleApp); + if (lptb) { + FrameTools_EnableWindow(lptb, TRUE); + FrameTools_UpdateButtons(lptb, (LPOUTLINEDOC)lpOleDoc); + } +#endif // USE_FRAMETOOLS + + OleApp_RejectInComingCalls(lpOleApp, FALSE); + +#if defined( INPLACE_SVR ) + { + LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOleDoc; + + /* if the document bringing down the modal dialog is + ** currently a UIActive in-place object, then tell the + ** top-level in-place frame it can re-enable its + ** modeless dialogs. + */ + if (lpServerDoc && lpServerDoc->m_fUIActive && + lpServerDoc->m_lpIPData && + lpServerDoc->m_lpIPData->lpFrame) { + OLEDBG_BEGIN2("IOleInPlaceFrame::EnableModless(TRUE) called\r\n"); + lpServerDoc->m_lpIPData->lpFrame->lpVtbl->EnableModeless( + lpServerDoc->m_lpIPData->lpFrame, TRUE); + OLEDBG_END2 + } + } +#endif // INPLACE_SVR +#if defined( INPLACE_CNTR ) + { + LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)lpOleApp; + + /* if the document bringing down the modal dialog is an + ** in-place container that has a UIActive object, then + ** tell the UIActive object it can re-enable its + ** modeless dialogs. + */ + if (lpContainerApp->m_lpIPActiveObj) { + OLEDBG_BEGIN2("IOleInPlaceActiveObject::EnableModless(TRUE) called\r\n"); + lpContainerApp->m_lpIPActiveObj->lpVtbl->EnableModeless( + lpContainerApp->m_lpIPActiveObj, TRUE); + OLEDBG_END2 + } + } +#endif // INPLACE_CNTR + } +} + + +/* OleApp_InitVtbls + * ---------------- + * + * initialize the methods in all of the interface Vtbl's + * + * OLE2NOTE: we only need one copy of each Vtbl. When an object which + * exposes an interface is instantiated, its lpVtbl is intialized + * to point to the single copy of the Vtbl. + * + */ +BOOL OleApp_InitVtbls (LPOLEAPP lpOleApp) +{ + BOOL fStatus; + + // OleApp::IUnknown method table + OleStdInitVtbl(&g_OleApp_UnknownVtbl, sizeof(IUnknownVtbl)); + g_OleApp_UnknownVtbl.QueryInterface = OleApp_Unk_QueryInterface; + g_OleApp_UnknownVtbl.AddRef = OleApp_Unk_AddRef; + g_OleApp_UnknownVtbl.Release = OleApp_Unk_Release; + fStatus = OleStdCheckVtbl( + &g_OleApp_UnknownVtbl, + sizeof(IUnknownVtbl), + "IUnknown" + ); + if (! fStatus) return FALSE; + + // OleDoc::IUnknown method table + OleStdInitVtbl(&g_OleDoc_UnknownVtbl, sizeof(IUnknownVtbl)); + g_OleDoc_UnknownVtbl.QueryInterface = OleDoc_Unk_QueryInterface; + g_OleDoc_UnknownVtbl.AddRef = OleDoc_Unk_AddRef; + g_OleDoc_UnknownVtbl.Release = OleDoc_Unk_Release; + fStatus = OleStdCheckVtbl( + &g_OleDoc_UnknownVtbl, + sizeof(IUnknownVtbl), + "IUnknown" + ); + if (! fStatus) return FALSE; + + // OleDoc::IPersistFile method table + OleStdInitVtbl(&g_OleDoc_PersistFileVtbl, sizeof(IPersistFileVtbl)); + g_OleDoc_PersistFileVtbl.QueryInterface = OleDoc_PFile_QueryInterface; + g_OleDoc_PersistFileVtbl.AddRef = OleDoc_PFile_AddRef; + g_OleDoc_PersistFileVtbl.Release = OleDoc_PFile_Release; + g_OleDoc_PersistFileVtbl.GetClassID = OleDoc_PFile_GetClassID; + g_OleDoc_PersistFileVtbl.IsDirty = OleDoc_PFile_IsDirty; + g_OleDoc_PersistFileVtbl.Load = OleDoc_PFile_Load; + g_OleDoc_PersistFileVtbl.Save = OleDoc_PFile_Save; + g_OleDoc_PersistFileVtbl.SaveCompleted = OleDoc_PFile_SaveCompleted; + g_OleDoc_PersistFileVtbl.GetCurFile = OleDoc_PFile_GetCurFile; + fStatus = OleStdCheckVtbl( + &g_OleDoc_PersistFileVtbl, + sizeof(IPersistFileVtbl), + "IPersistFile" + ); + if (! fStatus) return FALSE; + + // OleDoc::IOleItemContainer method table + OleStdInitVtbl(&g_OleDoc_OleItemContainerVtbl, sizeof(IOleItemContainerVtbl)); + g_OleDoc_OleItemContainerVtbl.QueryInterface = + OleDoc_ItemCont_QueryInterface; + g_OleDoc_OleItemContainerVtbl.AddRef = OleDoc_ItemCont_AddRef; + g_OleDoc_OleItemContainerVtbl.Release = OleDoc_ItemCont_Release; + g_OleDoc_OleItemContainerVtbl.ParseDisplayName = + OleDoc_ItemCont_ParseDisplayName; + g_OleDoc_OleItemContainerVtbl.EnumObjects= OleDoc_ItemCont_EnumObjects; + g_OleDoc_OleItemContainerVtbl.LockContainer = + OleDoc_ItemCont_LockContainer; + g_OleDoc_OleItemContainerVtbl.GetObject = OleDoc_ItemCont_GetObject; + g_OleDoc_OleItemContainerVtbl.GetObjectStorage = + OleDoc_ItemCont_GetObjectStorage; + g_OleDoc_OleItemContainerVtbl.IsRunning = OleDoc_ItemCont_IsRunning; + fStatus = OleStdCheckVtbl( + &g_OleDoc_OleItemContainerVtbl, + sizeof(IOleItemContainerVtbl), + "IOleItemContainer" + ); + if (! fStatus) return FALSE; + + // OleDoc::IExternalConnection method table + OleStdInitVtbl( + &g_OleDoc_ExternalConnectionVtbl,sizeof(IExternalConnectionVtbl)); + g_OleDoc_ExternalConnectionVtbl.QueryInterface = + OleDoc_ExtConn_QueryInterface; + g_OleDoc_ExternalConnectionVtbl.AddRef = OleDoc_ExtConn_AddRef; + g_OleDoc_ExternalConnectionVtbl.Release = OleDoc_ExtConn_Release; + g_OleDoc_ExternalConnectionVtbl.AddConnection = + OleDoc_ExtConn_AddConnection; + g_OleDoc_ExternalConnectionVtbl.ReleaseConnection = + OleDoc_ExtConn_ReleaseConnection; + fStatus = OleStdCheckVtbl( + &g_OleDoc_ExternalConnectionVtbl, + sizeof(IExternalConnectionVtbl), + "IExternalConnection" + ); + if (! fStatus) return FALSE; + + // OleDoc::IDataObject method table + OleStdInitVtbl(&g_OleDoc_DataObjectVtbl, sizeof(IDataObjectVtbl)); + g_OleDoc_DataObjectVtbl.QueryInterface = OleDoc_DataObj_QueryInterface; + g_OleDoc_DataObjectVtbl.AddRef = OleDoc_DataObj_AddRef; + g_OleDoc_DataObjectVtbl.Release = OleDoc_DataObj_Release; + g_OleDoc_DataObjectVtbl.GetData = OleDoc_DataObj_GetData; + g_OleDoc_DataObjectVtbl.GetDataHere = OleDoc_DataObj_GetDataHere; + g_OleDoc_DataObjectVtbl.QueryGetData = OleDoc_DataObj_QueryGetData; + g_OleDoc_DataObjectVtbl.GetCanonicalFormatEtc = + OleDoc_DataObj_GetCanonicalFormatEtc; + g_OleDoc_DataObjectVtbl.SetData = OleDoc_DataObj_SetData; + g_OleDoc_DataObjectVtbl.EnumFormatEtc = OleDoc_DataObj_EnumFormatEtc; + g_OleDoc_DataObjectVtbl.DAdvise = OleDoc_DataObj_DAdvise; + g_OleDoc_DataObjectVtbl.DUnadvise = OleDoc_DataObj_DUnadvise; + g_OleDoc_DataObjectVtbl.EnumDAdvise = OleDoc_DataObj_EnumDAdvise; + + fStatus = OleStdCheckVtbl( + &g_OleDoc_DataObjectVtbl, + sizeof(IDataObjectVtbl), + "IDataObject" + ); + if (! fStatus) return FALSE; + +#if defined( USE_DRAGDROP ) + + // OleDoc::IDropTarget method table + OleStdInitVtbl(&g_OleDoc_DropTargetVtbl, sizeof(IDropTargetVtbl)); + g_OleDoc_DropTargetVtbl.QueryInterface= OleDoc_DropTarget_QueryInterface; + g_OleDoc_DropTargetVtbl.AddRef = OleDoc_DropTarget_AddRef; + g_OleDoc_DropTargetVtbl.Release = OleDoc_DropTarget_Release; + + g_OleDoc_DropTargetVtbl.DragEnter = OleDoc_DropTarget_DragEnter; + g_OleDoc_DropTargetVtbl.DragOver = OleDoc_DropTarget_DragOver; + g_OleDoc_DropTargetVtbl.DragLeave = OleDoc_DropTarget_DragLeave; + g_OleDoc_DropTargetVtbl.Drop = OleDoc_DropTarget_Drop; + + fStatus = OleStdCheckVtbl( + &g_OleDoc_DropTargetVtbl, + sizeof(IDropTargetVtbl), + "IDropTarget" + ); + if (! fStatus) + return FALSE; + + // OleDoc::IDropSource method table + OleStdInitVtbl(&g_OleDoc_DropSourceVtbl, sizeof(IDropSourceVtbl)); + g_OleDoc_DropSourceVtbl.QueryInterface = + OleDoc_DropSource_QueryInterface; + g_OleDoc_DropSourceVtbl.AddRef = OleDoc_DropSource_AddRef; + g_OleDoc_DropSourceVtbl.Release = OleDoc_DropSource_Release; + + g_OleDoc_DropSourceVtbl.QueryContinueDrag = + OleDoc_DropSource_QueryContinueDrag; + g_OleDoc_DropSourceVtbl.GiveFeedback = OleDoc_DropSource_GiveFeedback; + + fStatus = OleStdCheckVtbl( + &g_OleDoc_DropSourceVtbl, + sizeof(IDropSourceVtbl), + "IDropSource" + ); + if (! fStatus) return FALSE; +#endif // USE_DRAGDROP + +#if defined( OLE_SERVER ) + + // Initialize the server specific interface method tables. + if (! ServerApp_InitVtbls((LPSERVERAPP)lpOleApp)) + return FALSE; +#endif +#if defined( OLE_CNTR ) + + // Initialize the container specific interface method tables. + if (! ContainerApp_InitVtbls((LPCONTAINERAPP)lpOleApp)) + return FALSE; +#endif + return TRUE; +}; + + + +/* OleApp_InitMenu + * --------------- + * + * Enable or Disable menu items depending on the state of + * the appliation. + * The OLE versions of the Outline sample app add a PasteSpecial command. + * Also, the container version add InsertObject and ObjectVerb menu items. + */ +void OleApp_InitMenu( + LPOLEAPP lpOleApp, + LPOLEDOC lpOleDoc, + HMENU hMenu +) +{ + BOOL bMsgFilterInstalled = FALSE; + BOOL bRejecting = FALSE; + + if (!lpOleApp || !hMenu) + return; + + OLEDBG_BEGIN3("OleApp_InitMenu\r\n") + + /* + ** Enable/disable menu items for Message Filter + */ + bMsgFilterInstalled = (lpOleApp->m_lpMsgFilter != NULL); + bRejecting = bMsgFilterInstalled && + OleStdMsgFilter_GetInComingCallStatus(lpOleApp->m_lpMsgFilter) != SERVERCALL_ISHANDLED; + + CheckMenuItem(hMenu, + IDM_D_INSTALLMSGFILTER, + bMsgFilterInstalled ? MF_CHECKED : MF_UNCHECKED); + + EnableMenuItem(hMenu, + IDM_D_REJECTINCOMING, + bMsgFilterInstalled ? MF_ENABLED : MF_GRAYED); + + CheckMenuItem(hMenu, + IDM_D_REJECTINCOMING, + bRejecting ? MF_CHECKED : MF_UNCHECKED); + +#if defined( OLE_CNTR ) + { + LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOleDoc; + BOOL fShowObject; + + fShowObject = ContainerDoc_GetShowObjectFlag(lpContainerDoc); + CheckMenuItem( + hMenu, + IDM_O_SHOWOBJECT, + (fShowObject ? MF_CHECKED : MF_UNCHECKED) + ); + +#if defined( INPLACE_CNTR ) && defined( _DEBUG ) + CheckMenuItem( + hMenu, + IDM_D_INSIDEOUT, + g_fInsideOutContainer ? MF_CHECKED:MF_UNCHECKED); +#endif // INPLACE_CNTR && _DEBUG + + } +#endif // OLE_CNTR + + OLEDBG_END3 +} + + + +/* OleApp_UpdateEditMenu + * --------------------- + * + * Purpose: + * Update the Edit menuitems of the App according to the state of + * OutlineDoc + * + * Parameter: + * lpOutlineDoc pointer to the document + * hMenuEdit edit menu handle + */ +void OleApp_UpdateEditMenu( + LPOLEAPP lpOleApp, + LPOUTLINEDOC lpOutlineDoc, + HMENU hMenuEdit +) +{ + int nFmtEtc; + UINT uEnablePaste = MF_GRAYED; + UINT uEnablePasteLink = MF_GRAYED; + LPDATAOBJECT lpClipboardDataObj; + LPOLEDOC lpOleDoc = (LPOLEDOC)lpOutlineDoc; + HRESULT hrErr; + BOOL fPrevEnable1; + BOOL fPrevEnable2; + + if (!lpOleApp || !lpOutlineDoc || !hMenuEdit) + return; + + if (!OleDoc_GetUpdateEditMenuFlag(lpOleDoc)) + /* OLE2NOTE: if the flag is not set, we don't have to update + ** the edit menu again. This blocks repetitive updating when + ** the user move the mouse across Edit menu while holding + ** down the button + */ + return; + + OLEDBG_BEGIN3("OleApp_InitEditMenu\r\n") + + /* OLE2NOTE: we do not want to ever give the busy dialog when we + ** are trying to put up our menus. eg. even if the source of + ** data on the clipboard is busy, we do not want put up the busy + ** dialog. thus we will disable the dialog and at the end + ** re-enable it. + */ + OleApp_DisableBusyDialogs(lpOleApp, &fPrevEnable1, &fPrevEnable2); + + // check if there is data on the clipboard that we can paste/paste link + + OLEDBG_BEGIN2("OleGetClipboard called\r\n") + hrErr = OleGetClipboard((LPDATAOBJECT FAR*)&lpClipboardDataObj); + OLEDBG_END2 + + if (hrErr == NOERROR) { + nFmtEtc = OleStdGetPriorityClipboardFormat( + lpClipboardDataObj, + lpOleApp->m_arrPasteEntries, + lpOleApp->m_nPasteEntries + ); + + if (nFmtEtc >= 0) + uEnablePaste = MF_ENABLED; // there IS a format we like + + OLEDBG_BEGIN2("OleQueryLinkFromData called\r\n") + hrErr = OleQueryLinkFromData(lpClipboardDataObj); + OLEDBG_END2 + + if(hrErr == NOERROR) + uEnablePasteLink = MF_ENABLED; + + OleStdRelease((LPUNKNOWN)lpClipboardDataObj); + } + + EnableMenuItem(hMenuEdit, IDM_E_PASTE, uEnablePaste); + EnableMenuItem(hMenuEdit, IDM_E_PASTESPECIAL, uEnablePaste); + + +#if defined( OLE_CNTR ) + if (ContainerDoc_GetNextLink((LPCONTAINERDOC)lpOutlineDoc, NULL)) + EnableMenuItem(hMenuEdit, IDM_E_EDITLINKS, MF_ENABLED); + else + EnableMenuItem(hMenuEdit, IDM_E_EDITLINKS, MF_GRAYED); + + + { + LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)lpOleApp; + HMENU hMenuVerb = NULL; + LPOLEOBJECT lpOleObj = NULL; + LPCONTAINERLINE lpContainerLine = NULL; + BOOL fSelIsOleObject; + + EnableMenuItem(hMenuEdit, IDM_E_PASTELINK, uEnablePasteLink); + + /* check if selection is a single line that contains an OleObject */ + + fSelIsOleObject = ContainerDoc_IsSelAnOleObject( + (LPCONTAINERDOC)lpOutlineDoc, + &IID_IOleObject, + (LPUNKNOWN FAR*)&lpOleObj, + NULL, /* we don't need the line index */ + (LPCONTAINERLINE FAR*)&lpContainerLine + ); + + if (hMenuEdit != NULL) { + + /* If the current line is an ContainerLine, add the object + ** verb sub menu to the Edit menu. if the line is not an + ** ContainerLine, (lpOleObj==NULL) then disable the + ** Edit.Object command. this helper API takes care of + ** building the verb menu as appropriate. + */ + OleUIAddVerbMenu( + (LPOLEOBJECT)lpOleObj, + (lpContainerLine ? lpContainerLine->m_lpszShortType:NULL), + hMenuEdit, + POS_OBJECT, + IDM_E_OBJECTVERBMIN, + 0, // no uIDVerbMax enforced + TRUE, // Add Convert menu item + IDM_E_CONVERTVERB, // ID for Convert menu item + (HMENU FAR*) &hMenuVerb + ); + +#if defined( USE_STATUSBAR_LATER ) + /* setup status messages for the object verb menu */ + if (hMenuVerb) { + // REVIEW: this string should come from a string resource. + // REVIEW: this doesn't work for dynamically created menus + AssignPopupMessage( + hMenuVerb, + "Open, edit or interact with an object" + ); + } +#endif // USE_STATUSBAR_LATER + } + + if (lpOleObj) + OleStdRelease((LPUNKNOWN)lpOleObj); + } + +#endif // OLE_CNTR + + // re-enable the Busy/NotResponding dialogs + OleApp_EnableBusyDialogs(lpOleApp, fPrevEnable1, fPrevEnable2); + + OleDoc_SetUpdateEditMenuFlag(lpOleDoc, FALSE); + + OLEDBG_END3 +} + + +/* OleApp_RegisterClassFactory + * --------------------------- + * + * Register our app's ClassFactory with OLE. + * + */ +BOOL OleApp_RegisterClassFactory(LPOLEAPP lpOleApp) +{ + HRESULT hrErr; + + if (lpOleApp->m_lpClassFactory) + return TRUE; // already registered + + OLEDBG_BEGIN3("OleApp_RegisterClassFactory\r\n") + + /****************************************************************** + ** An SDI app must register its ClassFactory if it is launched + ** for embedding (/Embedding command line option specified). + ** An MDI app must register its ClassFactory in all cases, + ******************************************************************/ + + lpOleApp->m_lpClassFactory = AppClassFactory_Create(); + if (! lpOleApp->m_lpClassFactory) { + OutlineApp_ErrorMessage(g_lpApp, ErrMsgCreateCF); + goto error; + } + + OLEDBG_BEGIN2("CoRegisterClassObject called\r\n") + hrErr = CoRegisterClassObject( + &CLSID_APP, + (LPUNKNOWN)lpOleApp->m_lpClassFactory, + CLSCTX_LOCAL_SERVER, + REGCLS_SINGLEUSE, + &lpOleApp->m_dwRegClassFac + ); + OLEDBG_END2 + + if(hrErr != NOERROR) { + OleDbgOutHResult("CoRegisterClassObject returned", hrErr); + OutlineApp_ErrorMessage(g_lpApp, ErrMsgRegCF); + goto error; + } + + OLEDBG_END3 + return TRUE; + +error: + + if (lpOleApp->m_lpClassFactory) { + OleStdRelease((LPUNKNOWN)lpOleApp->m_lpClassFactory); + lpOleApp->m_lpClassFactory = NULL; + } + OLEDBG_END3 + return FALSE; +} + + +/* OleApp_RevokeClassFactory + * ------------------------- + * + * Revoke our app's ClassFactory. + * + */ +void OleApp_RevokeClassFactory(LPOLEAPP lpOleApp) +{ + HRESULT hrErr; + + if (lpOleApp->m_lpClassFactory) { + + OLEDBG_BEGIN2("CoRevokeClassObject called\r\n") + hrErr = CoRevokeClassObject(lpOleApp->m_dwRegClassFac); + OLEDBG_END2 + +#if defined( _DEBUG ) + if (hrErr != NOERROR) { + OleDbgOutHResult("CoRevokeClassObject returned", hrErr); + } +#endif + + // we just release here; other folks may still have + // a pointer to our class factory, so we can't + // do any checks on the reference count. + OleStdRelease((LPUNKNOWN)lpOleApp->m_lpClassFactory); + lpOleApp->m_lpClassFactory = NULL; + } +} + + +#if defined( USE_MSGFILTER ) + +/* OleApp_RegisterMessageFilter + * ---------------------------- + * Register our IMessageFilter*. the message filter is used to handle + * concurrency. we will use a standard implementation of IMessageFilter + * that is included as part of the OLE2UI library. + */ +BOOL OleApp_RegisterMessageFilter(LPOLEAPP lpOleApp) +{ + HRESULT hrErr; + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpOleApp; + + if (lpOleApp->m_lpMsgFilter == NULL) { + // Register our message filter. + lpOleApp->m_lpfnMsgPending = (MSGPENDINGPROC)MessagePendingProc; + lpOleApp->m_lpMsgFilter = OleStdMsgFilter_Create( + g_lpApp->m_hWndApp, + (LPSTR)APPNAME, + lpOleApp->m_lpfnMsgPending, + NULL /* Busy dialog callback hook function */ + ); + + OLEDBG_BEGIN2("CoRegisterMessageFilter called\r\n") + hrErr = CoRegisterMessageFilter( + lpOleApp->m_lpMsgFilter, + NULL /* don't need previous message filter */ + ); + OLEDBG_END2 + + if(hrErr != NOERROR) { + OutlineApp_ErrorMessage(lpOutlineApp, ErrMsgRegMF); + return FALSE; + } + } + return TRUE; +} + + +/* OleApp_RevokeMessageFilter + * -------------------------- + * Revoke our IMessageFilter*. the message filter is used to handle + * concurrency. we will use a standard implementation of IMessageFilter + * that is included as part of the OLE2UI library. + */ +void OleApp_RevokeMessageFilter(LPOLEAPP lpOleApp) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + + if (lpOleApp->m_lpMsgFilter != NULL) { + // Revoke our message filter + OLEDBG_BEGIN2("CoRegisterMessageFilter(NULL) called\r\n") + CoRegisterMessageFilter(NULL, NULL); + OLEDBG_END2 + + if (lpOleApp->m_lpfnMsgPending) { + lpOleApp->m_lpfnMsgPending = NULL; + } + + OleStdVerifyRelease( + (LPUNKNOWN)lpOleApp->m_lpMsgFilter, + "Release MessageFilter FAILED!" + ); + lpOleApp->m_lpMsgFilter = NULL; + } +} + + +/* MessagePendingProc + * ------------------ + * + * Callback function for the IMessageFilter::MessagePending procedure. This + * function is called when a message is received by our application while + * we are waiting for an OLE call to complete. We are essentially + * blocked at this point, waiting for a response from the other OLE application. + * We should not process any messages which might cause another OLE call + * to become blocked, or any other call which might cause re-entrancy problems. + * + * For this application, only process WM_PAINT messages. A more sophisticated + * application might allow certain menu messages and menu items to be processed + * also. + * + * RETURNS: TRUE if we processed the message, FALSE if we did not. + */ + +BOOL FAR PASCAL EXPORT MessagePendingProc(MSG FAR *lpMsg) +{ + // Our application is only handling WM_PAINT messages when we are blocked + switch (lpMsg->message) { + case WM_PAINT: + OleDbgOut2("WM_PAINT dispatched while blocked\r\n"); + + DispatchMessage(lpMsg); + break; + } + + return FALSE; // return PENDINGMSG_WAITDEFPROCESS from MessagePending +} +#endif // USE_MSGFILTER + + +/* OleApp_FlushClipboard + * --------------------- + * + * Force the Windows clipboard to release our clipboard DataObject. + */ +void OleApp_FlushClipboard(LPOLEAPP lpOleApp) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpOleApp; + LPOLEDOC lpClipboardDoc = (LPOLEDOC)lpOutlineApp->m_lpClipboardDoc; + OLEDBG_BEGIN3("OleApp_FlushClipboard\r\n") + + /* OLE2NOTE: if for some reason our clipboard data transfer + ** document is still held on to by an external client, we want + ** to forceably break all external connections. + */ + OLEDBG_BEGIN2("CoDisconnectObject called\r\n") + CoDisconnectObject((LPUNKNOWN)&lpClipboardDoc->m_Unknown, 0); + OLEDBG_END2 + + OLEDBG_BEGIN2("OleFlushClipboard called\r\n") + OleFlushClipboard(); + OLEDBG_END2 + + lpOutlineApp->m_lpClipboardDoc = NULL; + + OLEDBG_END3 +} + + +/* OleApp_NewCommand + * ----------------- + * + * Start a new untitled document (File.New command). + */ +void OleApp_NewCommand(LPOLEAPP lpOleApp) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpOleApp; + LPOUTLINEDOC lpOutlineDoc = lpOutlineApp->m_lpDoc; + + if (! OutlineDoc_Close(lpOutlineDoc, OLECLOSE_PROMPTSAVE)) + return; + + OleDbgAssertSz(lpOutlineApp->m_lpDoc==NULL,"Closed doc NOT properly destroyed"); + lpOutlineApp->m_lpDoc = OutlineApp_CreateDoc(lpOutlineApp, FALSE); + if (! lpOutlineApp->m_lpDoc) goto error; + + /* OLE2NOTE: initially the Doc object is created with a 0 ref + ** count. in order to have a stable Doc object during the + ** process of initializing the new Doc instance, + ** we intially AddRef the Doc ref cnt and later + ** Release it. This initial AddRef is artificial; it is simply + ** done to guarantee that a harmless QueryInterface followed by + ** a Release does not inadvertantly force our object to destroy + ** itself prematurely. + */ + OleDoc_AddRef((LPOLEDOC)lpOutlineApp->m_lpDoc); + + // set the doc to an (Untitled) doc. + if (! OutlineDoc_InitNewFile(lpOutlineApp->m_lpDoc)) + goto error; + + // position and size the new doc window + OutlineApp_ResizeWindows(lpOutlineApp); + OutlineDoc_ShowWindow(lpOutlineApp->m_lpDoc); // calls OleDoc_Lock + + OleDoc_Release((LPOLEDOC)lpOutlineApp->m_lpDoc); // rel artificial AddRef + + return; + +error: + // REVIEW: should load string from string resource + OutlineApp_ErrorMessage(lpOutlineApp, "Could not create new document"); + + if (lpOutlineApp->m_lpDoc) { + // releasing the artificial AddRef above will destroy the document + OleDoc_Release((LPOLEDOC)lpOutlineApp->m_lpDoc); + lpOutlineApp->m_lpDoc = NULL; + } + + return; +} + + +/* OleApp_OpenCommand + * ------------------ + * + * Load a document from file (File.Open command). + */ +void OleApp_OpenCommand(LPOLEAPP lpOleApp) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpOleApp; + LPOUTLINEDOC lpOutlineDoc = lpOutlineApp->m_lpDoc; + OPENFILENAME ofn; + char szFilter[]=APPFILENAMEFILTER; + char szFileName[256]; + UINT i; + DWORD dwSaveOption = OLECLOSE_PROMPTSAVE; + BOOL fStatus = TRUE; + + if (! OutlineDoc_CheckSaveChanges(lpOutlineDoc, &dwSaveOption)) + return; // abort opening new doc + + for(i=0; szFilter[i]; i++) + if(szFilter[i]=='|') szFilter[i]='\0'; + + _fmemset((LPOPENFILENAME)&ofn,0,sizeof(OPENFILENAME)); + + szFileName[0]='\0'; + + ofn.lStructSize=sizeof(OPENFILENAME); + ofn.hwndOwner=lpOutlineApp->m_hWndApp; + ofn.lpstrFilter=(LPSTR)szFilter; + ofn.lpstrFile=(LPSTR)szFileName; + ofn.nMaxFile=sizeof(szFileName); + ofn.Flags=OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; + ofn.lpstrDefExt=DEFEXTENSION; + + OleApp_PreModalDialog(lpOleApp, (LPOLEDOC)lpOutlineApp->m_lpDoc); + + fStatus = GetOpenFileName((LPOPENFILENAME)&ofn); + + OleApp_PostModalDialog(lpOleApp, (LPOLEDOC)lpOutlineApp->m_lpDoc); + + if(! fStatus) + return; // user canceled file open dialog + + OutlineDoc_Close(lpOutlineDoc, OLECLOSE_NOSAVE); + OleDbgAssertSz(lpOutlineApp->m_lpDoc==NULL,"Closed doc NOT properly destroyed"); + + lpOutlineApp->m_lpDoc = OutlineApp_CreateDoc(lpOutlineApp, FALSE); + if (! lpOutlineApp->m_lpDoc) goto error; + + /* OLE2NOTE: initially the Doc object is created with a 0 ref + ** count. in order to have a stable Doc object during the + ** process of initializing the new Doc instance, + ** we intially AddRef the Doc ref cnt and later + ** Release it. This initial AddRef is artificial; it is simply + ** done to guarantee that a harmless QueryInterface followed by + ** a Release does not inadvertantly force our object to destroy + ** itself prematurely. + */ + OleDoc_AddRef((LPOLEDOC)lpOutlineApp->m_lpDoc); + + fStatus=OutlineDoc_LoadFromFile(lpOutlineApp->m_lpDoc, (LPSTR)szFileName); + + if (! fStatus) { + // loading the doc failed; create an untitled instead + + // releasing the artificial AddRef above will destroy the document + OleDoc_Release((LPOLEDOC)lpOutlineApp->m_lpDoc); + + lpOutlineApp->m_lpDoc = OutlineApp_CreateDoc(lpOutlineApp, FALSE); + if (! lpOutlineApp->m_lpDoc) goto error; + OleDoc_AddRef((LPOLEDOC)lpOutlineApp->m_lpDoc); + + if (! OutlineDoc_InitNewFile(lpOutlineApp->m_lpDoc)) + goto error; + } + + // position and size the new doc window + OutlineApp_ResizeWindows(lpOutlineApp); + OutlineDoc_ShowWindow(lpOutlineApp->m_lpDoc); + +#if defined( OLE_CNTR ) + UpdateWindow(lpOutlineApp->m_hWndApp); + ContainerDoc_UpdateLinks((LPCONTAINERDOC)lpOutlineApp->m_lpDoc); +#endif + + OleDoc_Release((LPOLEDOC)lpOutlineApp->m_lpDoc); // rel artificial AddRef + + return; + +error: + // REVIEW: should load string from string resource + OutlineApp_ErrorMessage(lpOutlineApp, "Could not create new document"); + + if (lpOutlineApp->m_lpDoc) { + // releasing the artificial AddRef above will destroy the document + OleDoc_Release((LPOLEDOC)lpOutlineApp->m_lpDoc); + lpOutlineApp->m_lpDoc = NULL; + } + + return; +} + + + +#if defined( OLE_CNTR ) + +/* OLE2NOTE: forward the WM_QUERYNEWPALETTE message (via +** SendMessage) to UIActive in-place object if there is one. +** this gives the UIActive object the opportunity to select +** and realize its color palette as the FOREGROUND palette. +** this is optional for in-place containers. if a container +** prefers to force its color palette as the foreground +** palette then it should NOT forward the this message. or +** the container can give the UIActive object priority; if +** the UIActive object returns 0 from the WM_QUERYNEWPALETTE +** message (ie. it did not realize its own palette), then +** the container can realize its palette. +** (see ContainerDoc_ForwardPaletteChangedMsg for more info) +** +** (It is a good idea for containers to use the standard +** palette even if they do not use colors themselves. this +** will allow embedded object to get a good distribution of +** colors when they are being drawn by the container) +** +*/ + +LRESULT OleApp_QueryNewPalette(LPOLEAPP lpOleApp) +{ +#if defined( INPLACE_CNTR ) + LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)lpOleApp; + + if (lpContainerApp && lpContainerApp->m_hWndUIActiveObj) { + if (SendMessage(lpContainerApp->m_hWndUIActiveObj, WM_QUERYNEWPALETTE, + (WPARAM)0, (LPARAM)0)) { + /* Object selected its palette as foreground palette */ + return (LRESULT)1; + } + } +#endif // INPLACE_CNTR + + + return wSelectPalette(((LPOUTLINEAPP)lpOleApp)->m_hWndApp, + lpOleApp->m_hStdPal, FALSE/*fBackground*/); +} + +#endif // OLE_CNTR + + + +/* This is just a helper routine */ + +LRESULT wSelectPalette(HWND hWnd, HPALETTE hPal, BOOL fBackground) +{ + HDC hdc; + HPALETTE hOldPal; + UINT iPalChg = 0; + + if (hPal == 0) + return (LRESULT)0; + + hdc = GetDC(hWnd); + hOldPal = SelectPalette(hdc, hPal, fBackground); + iPalChg = RealizePalette(hdc); + SelectPalette(hdc, hOldPal, TRUE /*fBackground*/); + ReleaseDC(hWnd, hdc); + + if (iPalChg > 0) + InvalidateRect(hWnd, NULL, TRUE); + + return (LRESULT)1; +} + + + + +/************************************************************************* +** OleApp::IUnknown interface implementation +*************************************************************************/ + +STDMETHODIMP OleApp_Unk_QueryInterface( + LPUNKNOWN lpThis, + REFIID riid, + LPVOID FAR* lplpvObj +) +{ + LPOLEAPP lpOleApp = ((struct CAppUnknownImpl FAR*)lpThis)->lpOleApp; + + return OleApp_QueryInterface(lpOleApp, riid, lplpvObj); +} + + +STDMETHODIMP_(ULONG) OleApp_Unk_AddRef(LPUNKNOWN lpThis) +{ + LPOLEAPP lpOleApp = ((struct CAppUnknownImpl FAR*)lpThis)->lpOleApp; + + OleDbgAddRefMethod(lpThis, "IUnknown"); + + return OleApp_AddRef(lpOleApp); +} + + +STDMETHODIMP_(ULONG) OleApp_Unk_Release (LPUNKNOWN lpThis) +{ + LPOLEAPP lpOleApp = ((struct CAppUnknownImpl FAR*)lpThis)->lpOleApp; + + OleDbgReleaseMethod(lpThis, "IUnknown"); + + return OleApp_Release(lpOleApp); +} + + + + +#if defined( OLE_SERVER ) + +/************************************************************************* +** ServerDoc Supprt Functions Used by Server versions +*************************************************************************/ + +/* ServerApp_InitInstance + * ---------------------- + * + * Initialize the app instance by creating the main frame window and + * performing app instance specific initializations + * (eg. initializing interface Vtbls). + * + * RETURNS: TRUE if the memory could be allocated, and the server app + * was properly initialized. + * FALSE otherwise + * + */ + +BOOL ServerApp_InitInstance( + LPSERVERAPP lpServerApp, + HINSTANCE hInst, + int nCmdShow +) +{ + LPOLEAPP lpOleApp = (LPOLEAPP)lpServerApp; + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpServerApp; + + /* Setup arrays used by IDataObject::EnumFormatEtc. + ** + ** OLE2NOTE: The order that the formats are listed for GetData is very + ** significant. It should be listed in order of highest fidelity + ** formats to least fidelity formats. A common ordering will be: + ** 1. private app formats + ** 2. EmbedSource + ** 3. lower fidelity interchange formats + ** 4. pictures (metafile, dib, etc.) + ** (graphic-related apps offer pictures 1st!) + ** 5. LinkSource + */ + + /* m_arrDocGetFmts array enumerates the formats that a ServerDoc + ** DataTransferDoc object can offer (give) through a + ** IDataObject::GetData call. a ServerDoc DataTransferDoc offers + ** data formats in the following order: + ** 1. CF_OUTLINE + ** 2. CF_EMBEDSOURCE + ** 3. CF_OBJECTDESCRIPTOR + ** 4. CF_TEXT + ** 5. CF_METAFILEPICT + ** 6. CF_LINKSOURCE * + ** 7. CF_LINKSRCDESCRIPTOR * + ** + ** * NOTE: CF_LINKSOURCE and CF_LINKSRCDESCRIPTOR is only + ** offered if the doc is able to give + ** a Moniker which references the data. CF_LINKSOURCE is + ** deliberately listed last in this array of possible formats. + ** if the doc does not have a Moniker then the last element of + ** this array is not used. (see SvrDoc_DataObj_EnumFormatEtc). + ** + ** NOTE: The list of formats that a USER ServerDoc document can + ** offer is a static list and is registered in the registration + ** database for the SVROUTL class. The + ** IDataObject::EnumFormatEtc method returns OLE_S_USEREG in the + ** case the document is a user docuemt (ie. created via + ** File.New, File.Open, InsertObject in a container, or + ** IPersistFile::Load during binding a link source). this tells + ** OLE to enumerate the formats automatically using the data the + ** the REGDB. + */ + + lpOleApp->m_arrDocGetFmts[0].cfFormat = lpOutlineApp->m_cfOutline; + lpOleApp->m_arrDocGetFmts[0].ptd = NULL; + lpOleApp->m_arrDocGetFmts[0].dwAspect = DVASPECT_CONTENT; + lpOleApp->m_arrDocGetFmts[0].tymed = TYMED_HGLOBAL; + lpOleApp->m_arrDocGetFmts[0].lindex = -1; + + lpOleApp->m_arrDocGetFmts[1].cfFormat = lpOleApp->m_cfEmbedSource; + lpOleApp->m_arrDocGetFmts[1].ptd = NULL; + lpOleApp->m_arrDocGetFmts[1].dwAspect = DVASPECT_CONTENT; + lpOleApp->m_arrDocGetFmts[1].tymed = TYMED_ISTORAGE; + lpOleApp->m_arrDocGetFmts[1].lindex = -1; + + lpOleApp->m_arrDocGetFmts[2].cfFormat = CF_TEXT; + lpOleApp->m_arrDocGetFmts[2].ptd = NULL; + lpOleApp->m_arrDocGetFmts[2].dwAspect = DVASPECT_CONTENT; + lpOleApp->m_arrDocGetFmts[2].tymed = TYMED_HGLOBAL; + lpOleApp->m_arrDocGetFmts[2].lindex = -1; + + lpOleApp->m_arrDocGetFmts[3].cfFormat = CF_METAFILEPICT; + lpOleApp->m_arrDocGetFmts[3].ptd = NULL; + lpOleApp->m_arrDocGetFmts[3].dwAspect = DVASPECT_CONTENT; + lpOleApp->m_arrDocGetFmts[3].tymed = TYMED_MFPICT; + lpOleApp->m_arrDocGetFmts[3].lindex = -1; + + lpOleApp->m_arrDocGetFmts[4].cfFormat = lpOleApp->m_cfObjectDescriptor; + lpOleApp->m_arrDocGetFmts[4].ptd = NULL; + lpOleApp->m_arrDocGetFmts[4].dwAspect = DVASPECT_CONTENT; + lpOleApp->m_arrDocGetFmts[4].tymed = TYMED_HGLOBAL; + lpOleApp->m_arrDocGetFmts[4].lindex = -1; + + lpOleApp->m_arrDocGetFmts[5].cfFormat = lpOleApp->m_cfLinkSource; + lpOleApp->m_arrDocGetFmts[5].ptd = NULL; + lpOleApp->m_arrDocGetFmts[5].dwAspect = DVASPECT_CONTENT; + lpOleApp->m_arrDocGetFmts[5].tymed = TYMED_ISTREAM; + lpOleApp->m_arrDocGetFmts[5].lindex = -1; + + lpOleApp->m_arrDocGetFmts[6].cfFormat = lpOleApp->m_cfLinkSrcDescriptor; + lpOleApp->m_arrDocGetFmts[6].ptd = NULL; + lpOleApp->m_arrDocGetFmts[6].dwAspect = DVASPECT_CONTENT; + lpOleApp->m_arrDocGetFmts[6].tymed = TYMED_HGLOBAL; + lpOleApp->m_arrDocGetFmts[6].lindex = -1; + + lpOleApp->m_nDocGetFmts = 7; + + /* m_arrPasteEntries array enumerates the formats that a ServerDoc + ** object can accept (get) from the clipboard. + ** The formats are listed in priority order. + ** ServerDoc accept data formats in the following order: + ** 1. CF_OUTLINE + ** 2. CF_TEXT + */ + // REVIEW: strings should be loaded from string resource + lpOleApp->m_arrPasteEntries[0].fmtetc.cfFormat =lpOutlineApp->m_cfOutline; + lpOleApp->m_arrPasteEntries[0].fmtetc.ptd = NULL; + lpOleApp->m_arrPasteEntries[0].fmtetc.dwAspect = DVASPECT_CONTENT; + lpOleApp->m_arrPasteEntries[0].fmtetc.tymed = TYMED_HGLOBAL; + lpOleApp->m_arrPasteEntries[0].fmtetc.lindex = -1; + lpOleApp->m_arrPasteEntries[0].lpstrFormatName = "Outline Data"; + lpOleApp->m_arrPasteEntries[0].lpstrResultText = "Outline Data"; + lpOleApp->m_arrPasteEntries[0].dwFlags = OLEUIPASTE_PASTEONLY; + + lpOleApp->m_arrPasteEntries[1].fmtetc.cfFormat = CF_TEXT; + lpOleApp->m_arrPasteEntries[1].fmtetc.ptd = NULL; + lpOleApp->m_arrPasteEntries[1].fmtetc.dwAspect = DVASPECT_CONTENT; + lpOleApp->m_arrPasteEntries[1].fmtetc.tymed = TYMED_HGLOBAL; + lpOleApp->m_arrPasteEntries[1].fmtetc.lindex = -1; + lpOleApp->m_arrPasteEntries[1].lpstrFormatName = "Text"; + lpOleApp->m_arrPasteEntries[1].lpstrResultText = "text"; + lpOleApp->m_arrPasteEntries[1].dwFlags = OLEUIPASTE_PASTEONLY; + + lpOleApp->m_nPasteEntries = 2; + + /** m_arrLinkTypes array enumerates the link types that a ServerDoc + ** object can accept from the clipboard. ServerDoc does NOT + ** accept any type of link from the clipboard. ServerDoc can + ** only be the source of a link. it can not contain links. + */ + + lpOleApp->m_nLinkTypes = 0; + +#if defined( INPLACE_SVR ) + + lpServerApp->m_hAccelBaseApp = NULL; + lpServerApp->m_hAccelIPSvr = LoadAccelerators( + hInst, + "InPlaceSvrOutlAccel" + ); + + lpServerApp->m_lpIPData = NULL; + + lpServerApp->m_hMenuEdit = GetSubMenu ( + lpOutlineApp->m_hMenuApp, + POS_EDITMENU + ); + lpServerApp->m_hMenuLine = GetSubMenu ( + lpOutlineApp->m_hMenuApp, + POS_LINEMENU + ); + lpServerApp->m_hMenuName = GetSubMenu ( + lpOutlineApp->m_hMenuApp, + POS_NAMEMENU + ); + lpServerApp->m_hMenuOptions = GetSubMenu ( + lpOutlineApp->m_hMenuApp, + POS_OPTIONSMENU + ); + lpServerApp->m_hMenuDebug = GetSubMenu ( + lpOutlineApp->m_hMenuApp, + POS_DEBUGMENU + ); + lpServerApp->m_hMenuHelp = GetSubMenu ( + lpOutlineApp->m_hMenuApp, + POS_HELPMENU + ); + +#endif // INPLACE_SVR + + return TRUE; +} + + +/* ServerApp_InitVtbls + * ------------------- + * + * initialize the methods in all of the interface Vtbl's + * + * OLE2NOTE: we only need one copy of each Vtbl. When an object which + * exposes an interface is instantiated, its lpVtbl is intialized + * to point to the single copy of the Vtbl. + * + */ +BOOL ServerApp_InitVtbls (LPSERVERAPP lpServerApp) +{ + BOOL fStatus; + + // ServerDoc::IOleObject method table + OleStdInitVtbl(&g_SvrDoc_OleObjectVtbl, sizeof(IOleObjectVtbl)); + g_SvrDoc_OleObjectVtbl.QueryInterface = SvrDoc_OleObj_QueryInterface; + g_SvrDoc_OleObjectVtbl.AddRef = SvrDoc_OleObj_AddRef; + g_SvrDoc_OleObjectVtbl.Release = SvrDoc_OleObj_Release; + g_SvrDoc_OleObjectVtbl.SetClientSite = SvrDoc_OleObj_SetClientSite; + g_SvrDoc_OleObjectVtbl.GetClientSite = SvrDoc_OleObj_GetClientSite; + g_SvrDoc_OleObjectVtbl.SetHostNames = SvrDoc_OleObj_SetHostNames; + g_SvrDoc_OleObjectVtbl.Close = SvrDoc_OleObj_Close; + g_SvrDoc_OleObjectVtbl.SetMoniker = SvrDoc_OleObj_SetMoniker; + g_SvrDoc_OleObjectVtbl.GetMoniker = SvrDoc_OleObj_GetMoniker; + g_SvrDoc_OleObjectVtbl.InitFromData = SvrDoc_OleObj_InitFromData; + g_SvrDoc_OleObjectVtbl.GetClipboardData = SvrDoc_OleObj_GetClipboardData; + g_SvrDoc_OleObjectVtbl.DoVerb = SvrDoc_OleObj_DoVerb; + g_SvrDoc_OleObjectVtbl.EnumVerbs = SvrDoc_OleObj_EnumVerbs; + g_SvrDoc_OleObjectVtbl.Update = SvrDoc_OleObj_Update; + g_SvrDoc_OleObjectVtbl.IsUpToDate = SvrDoc_OleObj_IsUpToDate; + g_SvrDoc_OleObjectVtbl.GetUserClassID = SvrDoc_OleObj_GetUserClassID; + g_SvrDoc_OleObjectVtbl.GetUserType = SvrDoc_OleObj_GetUserType; + g_SvrDoc_OleObjectVtbl.SetExtent = SvrDoc_OleObj_SetExtent; + g_SvrDoc_OleObjectVtbl.GetExtent = SvrDoc_OleObj_GetExtent; + g_SvrDoc_OleObjectVtbl.Advise = SvrDoc_OleObj_Advise; + g_SvrDoc_OleObjectVtbl.Unadvise = SvrDoc_OleObj_Unadvise; + g_SvrDoc_OleObjectVtbl.EnumAdvise = SvrDoc_OleObj_EnumAdvise; + g_SvrDoc_OleObjectVtbl.GetMiscStatus = SvrDoc_OleObj_GetMiscStatus; + g_SvrDoc_OleObjectVtbl.SetColorScheme = SvrDoc_OleObj_SetColorScheme; + fStatus = OleStdCheckVtbl( + &g_SvrDoc_OleObjectVtbl, + sizeof(IOleObjectVtbl), + "IOleObject" + ); + if (! fStatus) return FALSE; + + // ServerDoc::IPersistStorage method table + OleStdInitVtbl(&g_SvrDoc_PersistStorageVtbl, sizeof(IPersistStorageVtbl)); + g_SvrDoc_PersistStorageVtbl.QueryInterface = SvrDoc_PStg_QueryInterface; + g_SvrDoc_PersistStorageVtbl.AddRef = SvrDoc_PStg_AddRef; + g_SvrDoc_PersistStorageVtbl.Release = SvrDoc_PStg_Release; + g_SvrDoc_PersistStorageVtbl.GetClassID = SvrDoc_PStg_GetClassID; + g_SvrDoc_PersistStorageVtbl.IsDirty = SvrDoc_PStg_IsDirty; + g_SvrDoc_PersistStorageVtbl.InitNew = SvrDoc_PStg_InitNew; + g_SvrDoc_PersistStorageVtbl.Load = SvrDoc_PStg_Load; + g_SvrDoc_PersistStorageVtbl.Save = SvrDoc_PStg_Save; + g_SvrDoc_PersistStorageVtbl.SaveCompleted = SvrDoc_PStg_SaveCompleted; + g_SvrDoc_PersistStorageVtbl.HandsOffStorage = SvrDoc_PStg_HandsOffStorage; + fStatus = OleStdCheckVtbl( + &g_SvrDoc_PersistStorageVtbl, + sizeof(IPersistStorageVtbl), + "IPersistStorage" + ); + if (! fStatus) return FALSE; + +#if defined( SVR_TREATAS ) + // ServerDoc::IStdMarshalInfo method table + OleStdInitVtbl( + &g_SvrDoc_StdMarshalInfoVtbl, sizeof(IStdMarshalInfoVtbl)); + g_SvrDoc_StdMarshalInfoVtbl.QueryInterface = + SvrDoc_StdMshl_QueryInterface; + g_SvrDoc_StdMarshalInfoVtbl.AddRef = SvrDoc_StdMshl_AddRef; + g_SvrDoc_StdMarshalInfoVtbl.Release = SvrDoc_StdMshl_Release; + g_SvrDoc_StdMarshalInfoVtbl.GetClassForHandler = + SvrDoc_StdMshl_GetClassForHandler; + fStatus = OleStdCheckVtbl( + &g_SvrDoc_StdMarshalInfoVtbl, + sizeof(IStdMarshalInfoVtbl), + "IStdMarshalInfo" + ); + if (! fStatus) return FALSE; +#endif // SVR_TREATAS + +#if defined( INPLACE_SVR ) + // ServerDoc::IOleInPlaceObject method table + OleStdInitVtbl( + &g_SvrDoc_OleInPlaceObjectVtbl, + sizeof(IOleInPlaceObjectVtbl) + ); + g_SvrDoc_OleInPlaceObjectVtbl.QueryInterface + = SvrDoc_IPObj_QueryInterface; + g_SvrDoc_OleInPlaceObjectVtbl.AddRef + = SvrDoc_IPObj_AddRef; + g_SvrDoc_OleInPlaceObjectVtbl.Release + = SvrDoc_IPObj_Release; + g_SvrDoc_OleInPlaceObjectVtbl.GetWindow + = SvrDoc_IPObj_GetWindow; + g_SvrDoc_OleInPlaceObjectVtbl.ContextSensitiveHelp + = SvrDoc_IPObj_ContextSensitiveHelp; + g_SvrDoc_OleInPlaceObjectVtbl.InPlaceDeactivate + = SvrDoc_IPObj_InPlaceDeactivate; + g_SvrDoc_OleInPlaceObjectVtbl.UIDeactivate + = SvrDoc_IPObj_UIDeactivate; + g_SvrDoc_OleInPlaceObjectVtbl.SetObjectRects + = SvrDoc_IPObj_SetObjectRects; + g_SvrDoc_OleInPlaceObjectVtbl.ReactivateAndUndo + = SvrDoc_IPObj_ReactivateAndUndo; + fStatus = OleStdCheckVtbl( + &g_SvrDoc_OleInPlaceObjectVtbl, + sizeof(IOleInPlaceObjectVtbl), + "IOleInPlaceObject" + ); + if (! fStatus) return FALSE; + + // ServerDoc::IOleInPlaceActiveObject method table + OleStdInitVtbl( + &g_SvrDoc_OleInPlaceActiveObjectVtbl, + sizeof(IOleInPlaceActiveObjectVtbl) + ); + g_SvrDoc_OleInPlaceActiveObjectVtbl.QueryInterface + = SvrDoc_IPActiveObj_QueryInterface; + g_SvrDoc_OleInPlaceActiveObjectVtbl.AddRef + = SvrDoc_IPActiveObj_AddRef; + g_SvrDoc_OleInPlaceActiveObjectVtbl.Release + = SvrDoc_IPActiveObj_Release; + g_SvrDoc_OleInPlaceActiveObjectVtbl.GetWindow + = SvrDoc_IPActiveObj_GetWindow; + g_SvrDoc_OleInPlaceActiveObjectVtbl.ContextSensitiveHelp + = SvrDoc_IPActiveObj_ContextSensitiveHelp; + g_SvrDoc_OleInPlaceActiveObjectVtbl.TranslateAccelerator + = SvrDoc_IPActiveObj_TranslateAccelerator; + g_SvrDoc_OleInPlaceActiveObjectVtbl.OnFrameWindowActivate + = SvrDoc_IPActiveObj_OnFrameWindowActivate; + g_SvrDoc_OleInPlaceActiveObjectVtbl.OnDocWindowActivate + = SvrDoc_IPActiveObj_OnDocWindowActivate; + g_SvrDoc_OleInPlaceActiveObjectVtbl.ResizeBorder + = SvrDoc_IPActiveObj_ResizeBorder; + g_SvrDoc_OleInPlaceActiveObjectVtbl.EnableModeless + = SvrDoc_IPActiveObj_EnableModeless; + fStatus = OleStdCheckVtbl( + &g_SvrDoc_OleInPlaceActiveObjectVtbl, + sizeof(IOleInPlaceActiveObjectVtbl), + "IOleInPlaceActiveObject" + ); + if (! fStatus) return FALSE; + +#endif + + + // PseudoObj::IUnknown method table + OleStdInitVtbl(&g_PseudoObj_UnknownVtbl, sizeof(IUnknownVtbl)); + g_PseudoObj_UnknownVtbl.QueryInterface = PseudoObj_Unk_QueryInterface; + g_PseudoObj_UnknownVtbl.AddRef = PseudoObj_Unk_AddRef; + g_PseudoObj_UnknownVtbl.Release = PseudoObj_Unk_Release; + fStatus = OleStdCheckVtbl( + &g_PseudoObj_UnknownVtbl, + sizeof(IUnknownVtbl), + "IUnknown" + ); + if (! fStatus) return FALSE; + + // PseudoObj::IOleObject method table + OleStdInitVtbl(&g_PseudoObj_OleObjectVtbl, sizeof(IOleObjectVtbl)); + g_PseudoObj_OleObjectVtbl.QueryInterface= PseudoObj_OleObj_QueryInterface; + g_PseudoObj_OleObjectVtbl.AddRef = PseudoObj_OleObj_AddRef; + g_PseudoObj_OleObjectVtbl.Release = PseudoObj_OleObj_Release; + g_PseudoObj_OleObjectVtbl.SetClientSite = PseudoObj_OleObj_SetClientSite; + g_PseudoObj_OleObjectVtbl.GetClientSite = PseudoObj_OleObj_GetClientSite; + g_PseudoObj_OleObjectVtbl.SetHostNames = PseudoObj_OleObj_SetHostNames; + g_PseudoObj_OleObjectVtbl.Close = PseudoObj_OleObj_Close; + g_PseudoObj_OleObjectVtbl.SetMoniker = PseudoObj_OleObj_SetMoniker; + g_PseudoObj_OleObjectVtbl.GetMoniker = PseudoObj_OleObj_GetMoniker; + g_PseudoObj_OleObjectVtbl.InitFromData = PseudoObj_OleObj_InitFromData; + g_PseudoObj_OleObjectVtbl.GetClipboardData = + PseudoObj_OleObj_GetClipboardData; + g_PseudoObj_OleObjectVtbl.DoVerb = PseudoObj_OleObj_DoVerb; + g_PseudoObj_OleObjectVtbl.EnumVerbs = PseudoObj_OleObj_EnumVerbs; + g_PseudoObj_OleObjectVtbl.Update = PseudoObj_OleObj_Update; + g_PseudoObj_OleObjectVtbl.IsUpToDate = PseudoObj_OleObj_IsUpToDate; + g_PseudoObj_OleObjectVtbl.GetUserType = PseudoObj_OleObj_GetUserType; + g_PseudoObj_OleObjectVtbl.GetUserClassID= PseudoObj_OleObj_GetUserClassID; + g_PseudoObj_OleObjectVtbl.SetExtent = PseudoObj_OleObj_SetExtent; + g_PseudoObj_OleObjectVtbl.GetExtent = PseudoObj_OleObj_GetExtent; + g_PseudoObj_OleObjectVtbl.Advise = PseudoObj_OleObj_Advise; + g_PseudoObj_OleObjectVtbl.Unadvise = PseudoObj_OleObj_Unadvise; + g_PseudoObj_OleObjectVtbl.EnumAdvise = PseudoObj_OleObj_EnumAdvise; + g_PseudoObj_OleObjectVtbl.GetMiscStatus = PseudoObj_OleObj_GetMiscStatus; + g_PseudoObj_OleObjectVtbl.SetColorScheme= PseudoObj_OleObj_SetColorScheme; + fStatus = OleStdCheckVtbl( + &g_PseudoObj_OleObjectVtbl, + sizeof(IOleObjectVtbl), + "IOleObject" + ); + if (! fStatus) return FALSE; + + // ServerDoc::IDataObject method table + OleStdInitVtbl(&g_PseudoObj_DataObjectVtbl, sizeof(IDataObjectVtbl)); + g_PseudoObj_DataObjectVtbl.QueryInterface = + PseudoObj_DataObj_QueryInterface; + g_PseudoObj_DataObjectVtbl.AddRef = PseudoObj_DataObj_AddRef; + g_PseudoObj_DataObjectVtbl.Release = PseudoObj_DataObj_Release; + g_PseudoObj_DataObjectVtbl.GetData = PseudoObj_DataObj_GetData; + g_PseudoObj_DataObjectVtbl.GetDataHere = PseudoObj_DataObj_GetDataHere; + g_PseudoObj_DataObjectVtbl.QueryGetData = PseudoObj_DataObj_QueryGetData; + g_PseudoObj_DataObjectVtbl.GetCanonicalFormatEtc = + PseudoObj_DataObj_GetCanonicalFormatEtc; + g_PseudoObj_DataObjectVtbl.SetData = PseudoObj_DataObj_SetData; + g_PseudoObj_DataObjectVtbl.EnumFormatEtc= PseudoObj_DataObj_EnumFormatEtc; + g_PseudoObj_DataObjectVtbl.DAdvise = PseudoObj_DataObj_DAdvise; + g_PseudoObj_DataObjectVtbl.DUnadvise = PseudoObj_DataObj_DUnadvise; + g_PseudoObj_DataObjectVtbl.EnumDAdvise = PseudoObj_DataObj_EnumAdvise; + + fStatus = OleStdCheckVtbl( + &g_PseudoObj_DataObjectVtbl, + sizeof(IDataObjectVtbl), + "IDataObject" + ); + if (! fStatus) return FALSE; + + return TRUE; +} + +#endif // OLE_SERVER + + + +#if defined( OLE_CNTR ) + +/************************************************************************* +** ContainerDoc Supprt Functions Used by Container versions +*************************************************************************/ + + +/* ContainerApp_InitInstance + * ------------------------- + * + * Initialize the app instance by creating the main frame window and + * performing app instance specific initializations + * (eg. initializing interface Vtbls). + * + * RETURNS: TRUE if the memory could be allocated, and the server app + * was properly initialized. + * FALSE otherwise + * + */ + +BOOL ContainerApp_InitInstance( + LPCONTAINERAPP lpContainerApp, + HINSTANCE hInst, + int nCmdShow +) +{ + LPOLEAPP lpOleApp = (LPOLEAPP)lpContainerApp; + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpContainerApp; + + lpContainerApp->m_cfCntrOutl=RegisterClipboardFormat(CONTAINERDOCFORMAT); + if(! lpContainerApp->m_cfCntrOutl) { + // REVIEW: should load string from string resource + OutlineApp_ErrorMessage(lpOutlineApp, "Can't register clipboard format!"); + return FALSE; + } + +#if defined( INPLACE_CNTR ) + + lpContainerApp->m_fPendingUIDeactivate = FALSE; + lpContainerApp->m_fMustResizeClientArea = FALSE; + lpContainerApp->m_lpIPActiveObj = NULL; + lpContainerApp->m_hWndUIActiveObj = NULL; + lpContainerApp->m_hAccelIPCntr = LoadAccelerators( + hInst, + "InPlaceCntrOutlAccel" + ); + lpContainerApp->m_hMenuFile = GetSubMenu ( + lpOutlineApp->m_hMenuApp, + POS_FILEMENU + ); + lpContainerApp->m_hMenuView = GetSubMenu ( + lpOutlineApp->m_hMenuApp, + POS_VIEWMENU + ); + lpContainerApp->m_hMenuDebug = GetSubMenu ( + lpOutlineApp->m_hMenuApp, + POS_DEBUGMENU + ); + + INIT_INTERFACEIMPL( + &lpContainerApp->m_OleInPlaceFrame, + &g_CntrApp_OleInPlaceFrameVtbl, + lpContainerApp + ); + +#endif + + /* Setup arrays used by IDataObject::EnumFormatEtc. This is used to + ** support copy/paste and drag/drop operations. + ** + ** OLE2NOTE: The order that the formats are listed for GetData is very + ** significant. It should be listed in order of highest fidelity + ** formats to least fidelity formats. A common ordering will be: + ** 1. private app formats + ** 2. CF_EMBEDSOURCE or CF_EMBEDOBJECT (as appropriate) + ** 3. lower fidelity interchange formats + ** 4. CF_METAFILEPICT + ** (graphic-related apps might offer picture 1st!) + ** 5. CF_OBJECTDESCRIPTOR + ** 6. CF_LINKSOURCE + ** 6. CF_LINKSRCDESCRIPTOR + */ + + /* m_arrDocGetFmts array enumerates the formats that a ContainerDoc + ** object can offer (give) through a IDataObject::GetData call + ** when the selection copied is NOT a single embedded object. + ** when a single embedded object this list of formats available + ** is built dynamically depending on the object copied. (see + ** ContainerDoc_SetupDocGetFmts). + ** The formats are listed in priority order. + ** ContainerDoc objects accept data formats in the following order: + ** 1. CF_CNTROUTL + ** 2. CF_OUTLINE + ** 3. CF_TEXT + ** 4. CF_OBJECTDESCRIPTOR + ** + ** OLE2NOTE: CF_OBJECTDESCRIPTOR format is used to describe the + ** data on the clipboard. this information is intended to be + ** used, for example, to drive the PasteSpecial dialog. it is + ** useful to render CF_OBJECTDESCRIPTOR format even when the + ** data on the clipboard does NOT include CF_EMBEDDEDOBJECT + ** format or CF_EMBEDSOURCE format as when a selection that is + ** not a single OLE object is copied from the container only + ** version CNTROUTL. by rendering CF_OBJECTDESCRIPTOR format the + ** app can indicate a useful string to identifiy the source of + ** the copy to the user. + */ + + lpOleApp->m_arrDocGetFmts[0].cfFormat = lpContainerApp->m_cfCntrOutl; + lpOleApp->m_arrDocGetFmts[0].ptd = NULL; + lpOleApp->m_arrDocGetFmts[0].dwAspect = DVASPECT_CONTENT; + lpOleApp->m_arrDocGetFmts[0].tymed = TYMED_ISTORAGE; + lpOleApp->m_arrDocGetFmts[0].lindex = -1; + + lpOleApp->m_arrDocGetFmts[1].cfFormat = lpOutlineApp->m_cfOutline; + lpOleApp->m_arrDocGetFmts[1].ptd = NULL; + lpOleApp->m_arrDocGetFmts[1].dwAspect = DVASPECT_CONTENT; + lpOleApp->m_arrDocGetFmts[1].tymed = TYMED_HGLOBAL; + lpOleApp->m_arrDocGetFmts[1].lindex = -1; + + lpOleApp->m_arrDocGetFmts[2].cfFormat = CF_TEXT; + lpOleApp->m_arrDocGetFmts[2].ptd = NULL; + lpOleApp->m_arrDocGetFmts[2].dwAspect = DVASPECT_CONTENT; + lpOleApp->m_arrDocGetFmts[2].tymed = TYMED_HGLOBAL; + lpOleApp->m_arrDocGetFmts[2].lindex = -1; + + lpOleApp->m_arrDocGetFmts[3].cfFormat = lpOleApp->m_cfObjectDescriptor; + lpOleApp->m_arrDocGetFmts[3].ptd = NULL; + lpOleApp->m_arrDocGetFmts[3].dwAspect = DVASPECT_CONTENT; + lpOleApp->m_arrDocGetFmts[3].tymed = TYMED_HGLOBAL; + lpOleApp->m_arrDocGetFmts[3].lindex = -1; + + lpOleApp->m_nDocGetFmts = 4; + + /* m_arrSingleObjGetFmts array enumerates the formats that a + ** ContainerDoc object can offer (give) through a + ** IDataObject::GetData call when the selection copied IS a + ** single OLE object. + ** ContainerDoc objects accept data formats in the following order: + ** 1. CF_CNTROUTL + ** 2. CF_EMBEDDEDOBJECT + ** 3. CF_OBJECTDESCRIPTOR + ** 4. CF_METAFILEPICT (note DVASPECT will vary) + ** 5. CF_LINKSOURCE * + ** 6. CF_LINKSRCDESCRIPTOR * + ** + ** * OLE2NOTE: CF_LINKSOURCE and CF_LINKSRCDESCRIPTOR is only + ** offered if the OLE object is allowed to be linked to from the + ** inside (ie. we are allowed to give out a moniker which binds + ** to the running OLE object), then we want to offer + ** CF_LINKSOURCE format. if the object is an OLE 2.0 embedded + ** object then it is allowed to be linked to from the inside. if + ** the object is either an OleLink or an OLE 1.0 embedding then + ** it can not be linked to from the inside. if we were a + ** container/server app then we could offer linking to the + ** outside of the object (ie. a pseudo object within our + ** document). we are a container only app that does not support + ** linking to ranges of its data. + ** the simplest way to determine if an object can be linked to + ** on the inside is to call IOleObject::GetMiscStatus and test + ** to see if the OLEMISC_CANTLINKINSIDE bit is NOT set. + ** + ** OLE2NOTE: optionally, a container that wants to have a + ** potentially richer data transfer, can enumerate the data + ** formats from the OLE object's cache and offer them too. if + ** the object has a special handler, then it might be able to + ** render additional data formats. + */ + lpContainerApp->m_arrSingleObjGetFmts[0].cfFormat = + lpContainerApp->m_cfCntrOutl; + lpContainerApp->m_arrSingleObjGetFmts[0].ptd = NULL; + lpContainerApp->m_arrSingleObjGetFmts[0].dwAspect = DVASPECT_CONTENT; + lpContainerApp->m_arrSingleObjGetFmts[0].tymed = TYMED_ISTORAGE; + lpContainerApp->m_arrSingleObjGetFmts[0].lindex = -1; + + lpContainerApp->m_arrSingleObjGetFmts[1].cfFormat = + lpOleApp->m_cfEmbeddedObject; + lpContainerApp->m_arrSingleObjGetFmts[1].ptd = NULL; + lpContainerApp->m_arrSingleObjGetFmts[1].dwAspect = DVASPECT_CONTENT; + lpContainerApp->m_arrSingleObjGetFmts[1].tymed = TYMED_ISTORAGE; + lpContainerApp->m_arrSingleObjGetFmts[1].lindex = -1; + + lpContainerApp->m_arrSingleObjGetFmts[2].cfFormat = + lpOleApp->m_cfObjectDescriptor; + lpContainerApp->m_arrSingleObjGetFmts[2].ptd = NULL; + lpContainerApp->m_arrSingleObjGetFmts[2].dwAspect = DVASPECT_CONTENT; + lpContainerApp->m_arrSingleObjGetFmts[2].tymed = TYMED_HGLOBAL; + lpContainerApp->m_arrSingleObjGetFmts[2].lindex = -1; + + lpContainerApp->m_arrSingleObjGetFmts[3].cfFormat = CF_METAFILEPICT; + lpContainerApp->m_arrSingleObjGetFmts[3].ptd = NULL; + lpContainerApp->m_arrSingleObjGetFmts[3].dwAspect = DVASPECT_CONTENT; + lpContainerApp->m_arrSingleObjGetFmts[3].tymed = TYMED_MFPICT; + lpContainerApp->m_arrSingleObjGetFmts[3].lindex = -1; + + lpContainerApp->m_arrSingleObjGetFmts[4].cfFormat = + lpOleApp->m_cfLinkSource; + lpContainerApp->m_arrSingleObjGetFmts[4].ptd = NULL; + lpContainerApp->m_arrSingleObjGetFmts[4].dwAspect = DVASPECT_CONTENT; + lpContainerApp->m_arrSingleObjGetFmts[4].tymed = TYMED_ISTREAM; + lpContainerApp->m_arrSingleObjGetFmts[4].lindex = -1; + + lpContainerApp->m_arrSingleObjGetFmts[5].cfFormat = + lpOleApp->m_cfLinkSrcDescriptor; + lpContainerApp->m_arrSingleObjGetFmts[5].ptd = NULL; + lpContainerApp->m_arrSingleObjGetFmts[5].dwAspect = DVASPECT_CONTENT; + lpContainerApp->m_arrSingleObjGetFmts[5].tymed = TYMED_HGLOBAL; + lpContainerApp->m_arrSingleObjGetFmts[5].lindex = -1; + + lpContainerApp->m_nSingleObjGetFmts = 6; + + /* NOTE: the Container-Only version of Outline does NOT offer + ** IDataObject interface from its User documents and the + ** IDataObject interface available from DataTransferDoc's do NOT + ** support SetData. IDataObject interface is required by objects + ** which can be embedded or linked. the Container-only app only + ** allows linking to its contained objects, NOT the data of the + ** container itself. + */ + + /* m_arrPasteEntries array enumerates the formats that a ContainerDoc + ** object can accept from the clipboard. this array is used to + ** support the PasteSpecial dialog. + ** The formats are listed in priority order. + ** ContainerDoc objects accept data formats in the following order: + ** 1. CF_CNTROUTL + ** 2. CF_OUTLINE + ** 3. CF_EMBEDDEDOBJECT + ** 4. CF_TEXT + ** 5. CF_METAFILEPICT + ** 6. CF_DIB + ** 7. CF_BITMAP + ** 8. CF_LINKSOURCE + ** + ** NOTE: specifying CF_EMBEDDEDOBJECT in the PasteEntry array + ** indicates that the caller is interested in pasting OLE + ** objects (ie. the caller calls OleCreateFromData). the + ** OleUIPasteSpecial dialog and OleStdGetPriorityClipboardFormat + ** call OleQueryCreateFromData to see if an OLE object format is + ** available. thus, in fact if CF_EMBEDSOURCE or CF_FILENAME are + ** available from the data source then and OLE object can be + ** created and this entry will be matched. the caller should + ** only specify one object type format. + ** CF_FILENAME format (as generated by copying a file to + ** the clipboard from the FileManager) is considered an object + ** format; OleCreatFromData creates an object if the file has an + ** associated class (see GetClassFile API) or if no class it + ** creates an OLE 1.0 Package object. this format can also be + ** paste linked by calling OleCreateLinkFromData. + */ + // REVIEW: strings should be loaded from string resource + + lpOleApp->m_arrPasteEntries[0].fmtetc.cfFormat = + lpContainerApp->m_cfCntrOutl; + lpOleApp->m_arrPasteEntries[0].fmtetc.ptd = NULL; + lpOleApp->m_arrPasteEntries[0].fmtetc.dwAspect = DVASPECT_CONTENT; + lpOleApp->m_arrPasteEntries[0].fmtetc.tymed = TYMED_ISTORAGE; + lpOleApp->m_arrPasteEntries[0].fmtetc.lindex = -1; + lpOleApp->m_arrPasteEntries[0].lpstrFormatName = "Container Outline Data"; + lpOleApp->m_arrPasteEntries[0].lpstrResultText = + "Container Outline Data"; + lpOleApp->m_arrPasteEntries[0].dwFlags = OLEUIPASTE_PASTEONLY; + + lpOleApp->m_arrPasteEntries[1].fmtetc.cfFormat =lpOutlineApp->m_cfOutline; + lpOleApp->m_arrPasteEntries[1].fmtetc.ptd = NULL; + lpOleApp->m_arrPasteEntries[1].fmtetc.dwAspect = DVASPECT_CONTENT; + lpOleApp->m_arrPasteEntries[1].fmtetc.tymed = TYMED_HGLOBAL; + lpOleApp->m_arrPasteEntries[1].fmtetc.lindex = -1; + lpOleApp->m_arrPasteEntries[1].lpstrFormatName = "Outline Data"; + lpOleApp->m_arrPasteEntries[1].lpstrResultText = "Outline Data"; + lpOleApp->m_arrPasteEntries[1].dwFlags = OLEUIPASTE_PASTEONLY; + + lpOleApp->m_arrPasteEntries[2].fmtetc.cfFormat = + lpOleApp->m_cfEmbeddedObject; + lpOleApp->m_arrPasteEntries[2].fmtetc.ptd = NULL; + lpOleApp->m_arrPasteEntries[2].fmtetc.dwAspect = DVASPECT_CONTENT; + lpOleApp->m_arrPasteEntries[2].fmtetc.tymed = TYMED_ISTORAGE; + lpOleApp->m_arrPasteEntries[2].fmtetc.lindex = -1; + lpOleApp->m_arrPasteEntries[2].lpstrFormatName = "%s"; + lpOleApp->m_arrPasteEntries[2].lpstrResultText = "%s"; + lpOleApp->m_arrPasteEntries[2].dwFlags = + OLEUIPASTE_PASTE | OLEUIPASTE_ENABLEICON; + + lpOleApp->m_arrPasteEntries[3].fmtetc.cfFormat = CF_TEXT; + lpOleApp->m_arrPasteEntries[3].fmtetc.ptd = NULL; + lpOleApp->m_arrPasteEntries[3].fmtetc.dwAspect = DVASPECT_CONTENT; + lpOleApp->m_arrPasteEntries[3].fmtetc.tymed = TYMED_HGLOBAL; + lpOleApp->m_arrPasteEntries[3].fmtetc.lindex = -1; + lpOleApp->m_arrPasteEntries[3].lpstrFormatName = "Text"; + lpOleApp->m_arrPasteEntries[3].lpstrResultText = "text"; + lpOleApp->m_arrPasteEntries[3].dwFlags = OLEUIPASTE_PASTEONLY; + + lpOleApp->m_arrPasteEntries[4].fmtetc.cfFormat = CF_METAFILEPICT; + lpOleApp->m_arrPasteEntries[4].fmtetc.ptd = NULL; + lpOleApp->m_arrPasteEntries[4].fmtetc.dwAspect = DVASPECT_CONTENT; + lpOleApp->m_arrPasteEntries[4].fmtetc.tymed = TYMED_MFPICT; + lpOleApp->m_arrPasteEntries[4].fmtetc.lindex = -1; + lpOleApp->m_arrPasteEntries[4].lpstrFormatName = "Picture (Metafile)"; + lpOleApp->m_arrPasteEntries[4].lpstrResultText = "a static picture"; + lpOleApp->m_arrPasteEntries[4].dwFlags = OLEUIPASTE_PASTEONLY; + + lpOleApp->m_arrPasteEntries[5].fmtetc.cfFormat = CF_DIB; + lpOleApp->m_arrPasteEntries[5].fmtetc.ptd = NULL; + lpOleApp->m_arrPasteEntries[5].fmtetc.dwAspect = DVASPECT_CONTENT; + lpOleApp->m_arrPasteEntries[5].fmtetc.tymed = TYMED_HGLOBAL; + lpOleApp->m_arrPasteEntries[5].fmtetc.lindex = -1; + lpOleApp->m_arrPasteEntries[5].lpstrFormatName = "Picture (DIB)"; + lpOleApp->m_arrPasteEntries[5].lpstrResultText = "a static picture"; + lpOleApp->m_arrPasteEntries[5].dwFlags = OLEUIPASTE_PASTEONLY; + + lpOleApp->m_arrPasteEntries[6].fmtetc.cfFormat = CF_BITMAP; + lpOleApp->m_arrPasteEntries[6].fmtetc.ptd = NULL; + lpOleApp->m_arrPasteEntries[6].fmtetc.dwAspect = DVASPECT_CONTENT; + lpOleApp->m_arrPasteEntries[6].fmtetc.tymed = TYMED_GDI; + lpOleApp->m_arrPasteEntries[6].fmtetc.lindex = -1; + lpOleApp->m_arrPasteEntries[6].lpstrFormatName = "Picture (Bitmap)"; + lpOleApp->m_arrPasteEntries[6].lpstrResultText = "a static picture"; + lpOleApp->m_arrPasteEntries[6].dwFlags = OLEUIPASTE_PASTEONLY; + + lpOleApp->m_arrPasteEntries[7].fmtetc.cfFormat = lpOleApp->m_cfLinkSource; + lpOleApp->m_arrPasteEntries[7].fmtetc.ptd = NULL; + lpOleApp->m_arrPasteEntries[7].fmtetc.dwAspect = DVASPECT_CONTENT; + lpOleApp->m_arrPasteEntries[7].fmtetc.tymed = TYMED_ISTREAM; + lpOleApp->m_arrPasteEntries[7].fmtetc.lindex = -1; + lpOleApp->m_arrPasteEntries[7].lpstrFormatName = "%s"; + lpOleApp->m_arrPasteEntries[7].lpstrResultText = "%s"; + lpOleApp->m_arrPasteEntries[7].dwFlags = + OLEUIPASTE_LINKTYPE1 | OLEUIPASTE_ENABLEICON; + + lpOleApp->m_nPasteEntries = 8; + + /* m_arrLinkTypes array enumerates the link types that a ContainerDoc + ** object can accept from the clipboard + */ + + lpOleApp->m_arrLinkTypes[0] = lpOleApp->m_cfLinkSource; + lpOleApp->m_nLinkTypes = 1; + + return TRUE; +} + + +/* ContainerApp_InitVtbls +** ---------------------- +** +** initialize the interface Vtbl's used to support the OLE 2.0 +** Container functionality. +*/ + +BOOL ContainerApp_InitVtbls(LPCONTAINERAPP lpApp) +{ + BOOL fStatus; + + // ContainerDoc::IOleUILinkContainer method table + OleStdInitVtbl( + &g_CntrDoc_OleUILinkContainerVtbl, + sizeof(IOleUILinkContainerVtbl) + ); + g_CntrDoc_OleUILinkContainerVtbl.QueryInterface = + CntrDoc_LinkCont_QueryInterface; + g_CntrDoc_OleUILinkContainerVtbl.AddRef = CntrDoc_LinkCont_AddRef; + g_CntrDoc_OleUILinkContainerVtbl.Release = CntrDoc_LinkCont_Release; + g_CntrDoc_OleUILinkContainerVtbl.GetNextLink = + CntrDoc_LinkCont_GetNextLink; + g_CntrDoc_OleUILinkContainerVtbl.SetLinkUpdateOptions = + CntrDoc_LinkCont_SetLinkUpdateOptions; + g_CntrDoc_OleUILinkContainerVtbl.GetLinkUpdateOptions = + CntrDoc_LinkCont_GetLinkUpdateOptions; + g_CntrDoc_OleUILinkContainerVtbl.SetLinkSource = + CntrDoc_LinkCont_SetLinkSource; + g_CntrDoc_OleUILinkContainerVtbl.GetLinkSource = + CntrDoc_LinkCont_GetLinkSource; + g_CntrDoc_OleUILinkContainerVtbl.OpenLinkSource = + CntrDoc_LinkCont_OpenLinkSource; + g_CntrDoc_OleUILinkContainerVtbl.UpdateLink = + CntrDoc_LinkCont_UpdateLink; + g_CntrDoc_OleUILinkContainerVtbl.CancelLink = + CntrDoc_LinkCont_CancelLink; + fStatus = OleStdCheckVtbl( + &g_CntrDoc_OleUILinkContainerVtbl, + sizeof(IOleUILinkContainerVtbl), + "IOleUILinkContainer" + ); + if (! fStatus) return FALSE; + +#if defined( INPLACE_CNTR ) + + // ContainerApp::IOleInPlaceFrame interface method table + OleStdInitVtbl( + &g_CntrApp_OleInPlaceFrameVtbl, + sizeof(g_CntrApp_OleInPlaceFrameVtbl) + ); + + g_CntrApp_OleInPlaceFrameVtbl.QueryInterface + = CntrApp_IPFrame_QueryInterface; + g_CntrApp_OleInPlaceFrameVtbl.AddRef + = CntrApp_IPFrame_AddRef; + g_CntrApp_OleInPlaceFrameVtbl.Release + = CntrApp_IPFrame_Release; + g_CntrApp_OleInPlaceFrameVtbl.GetWindow + = CntrApp_IPFrame_GetWindow; + g_CntrApp_OleInPlaceFrameVtbl.ContextSensitiveHelp + = CntrApp_IPFrame_ContextSensitiveHelp; + + g_CntrApp_OleInPlaceFrameVtbl.GetBorder + = CntrApp_IPFrame_GetBorder; + g_CntrApp_OleInPlaceFrameVtbl.RequestBorderSpace + = CntrApp_IPFrame_RequestBorderSpace; + g_CntrApp_OleInPlaceFrameVtbl.SetBorderSpace + = CntrApp_IPFrame_SetBorderSpace; + g_CntrApp_OleInPlaceFrameVtbl.SetActiveObject + = CntrApp_IPFrame_SetActiveObject; + g_CntrApp_OleInPlaceFrameVtbl.InsertMenus + = CntrApp_IPFrame_InsertMenus; + g_CntrApp_OleInPlaceFrameVtbl.SetMenu + = CntrApp_IPFrame_SetMenu; + g_CntrApp_OleInPlaceFrameVtbl.RemoveMenus + = CntrApp_IPFrame_RemoveMenus; + g_CntrApp_OleInPlaceFrameVtbl.SetStatusText + = CntrApp_IPFrame_SetStatusText; + g_CntrApp_OleInPlaceFrameVtbl.EnableModeless + = CntrApp_IPFrame_EnableModeless; + g_CntrApp_OleInPlaceFrameVtbl.TranslateAccelerator + = CntrApp_IPFrame_TranslateAccelerator; + + fStatus = OleStdCheckVtbl( + &g_CntrApp_OleInPlaceFrameVtbl, + sizeof(g_CntrApp_OleInPlaceFrameVtbl), + "IOleInPlaceFrame" + ); + if (! fStatus) return FALSE; + +#endif // INPLACE_CNTR + + + // ContainerLine::IUnknown interface method table + OleStdInitVtbl( + &g_CntrLine_UnknownVtbl, + sizeof(g_CntrLine_UnknownVtbl) + ); + g_CntrLine_UnknownVtbl.QueryInterface = CntrLine_Unk_QueryInterface; + g_CntrLine_UnknownVtbl.AddRef = CntrLine_Unk_AddRef; + g_CntrLine_UnknownVtbl.Release = CntrLine_Unk_Release; + fStatus = OleStdCheckVtbl( + &g_CntrLine_UnknownVtbl, + sizeof(g_CntrLine_UnknownVtbl), + "IUnknown" + ); + if (! fStatus) return FALSE; + + // ContainerLine::IOleClientSite interface method table + OleStdInitVtbl( + &g_CntrLine_OleClientSiteVtbl, + sizeof(g_CntrLine_OleClientSiteVtbl) + ); + g_CntrLine_OleClientSiteVtbl.QueryInterface = + CntrLine_CliSite_QueryInterface; + g_CntrLine_OleClientSiteVtbl.AddRef = CntrLine_CliSite_AddRef; + g_CntrLine_OleClientSiteVtbl.Release = CntrLine_CliSite_Release; + g_CntrLine_OleClientSiteVtbl.SaveObject = CntrLine_CliSite_SaveObject; + g_CntrLine_OleClientSiteVtbl.GetMoniker = CntrLine_CliSite_GetMoniker; + g_CntrLine_OleClientSiteVtbl.GetContainer = CntrLine_CliSite_GetContainer; + g_CntrLine_OleClientSiteVtbl.ShowObject = CntrLine_CliSite_ShowObject; + g_CntrLine_OleClientSiteVtbl.OnShowWindow = CntrLine_CliSite_OnShowWindow; + g_CntrLine_OleClientSiteVtbl.RequestNewObjectLayout = + CntrLine_CliSite_RequestNewObjectLayout; + fStatus = OleStdCheckVtbl( + &g_CntrLine_OleClientSiteVtbl, + sizeof(g_CntrLine_OleClientSiteVtbl), + "IOleClientSite" + ); + if (! fStatus) return FALSE; + + // ContainerLine::IAdviseSink interface method table + OleStdInitVtbl( + &g_CntrLine_AdviseSinkVtbl, + sizeof(g_CntrLine_AdviseSinkVtbl) + ); + g_CntrLine_AdviseSinkVtbl.QueryInterface= CntrLine_AdvSink_QueryInterface; + g_CntrLine_AdviseSinkVtbl.AddRef = CntrLine_AdvSink_AddRef; + g_CntrLine_AdviseSinkVtbl.Release = CntrLine_AdvSink_Release; + g_CntrLine_AdviseSinkVtbl.OnDataChange = CntrLine_AdvSink_OnDataChange; + g_CntrLine_AdviseSinkVtbl.OnViewChange = CntrLine_AdvSink_OnViewChange; + g_CntrLine_AdviseSinkVtbl.OnRename = CntrLine_AdvSink_OnRename; + g_CntrLine_AdviseSinkVtbl.OnSave = CntrLine_AdvSink_OnSave; + g_CntrLine_AdviseSinkVtbl.OnClose = CntrLine_AdvSink_OnClose; + fStatus = OleStdCheckVtbl( + &g_CntrLine_AdviseSinkVtbl, + sizeof(g_CntrLine_AdviseSinkVtbl), + "IAdviseSink" + ); + if (! fStatus) return FALSE; + + +#if defined( INPLACE_CNTR ) + + // ContainerLine::IOleInPlaceSite interface method table + OleStdInitVtbl( + &g_CntrLine_OleInPlaceSiteVtbl, + sizeof(g_CntrLine_OleInPlaceSiteVtbl) + ); + + g_CntrLine_OleInPlaceSiteVtbl.QueryInterface + = CntrLine_IPSite_QueryInterface; + g_CntrLine_OleInPlaceSiteVtbl.AddRef + = CntrLine_IPSite_AddRef; + g_CntrLine_OleInPlaceSiteVtbl.Release + = CntrLine_IPSite_Release; + g_CntrLine_OleInPlaceSiteVtbl.GetWindow + = CntrLine_IPSite_GetWindow; + g_CntrLine_OleInPlaceSiteVtbl.ContextSensitiveHelp + = CntrLine_IPSite_ContextSensitiveHelp; + g_CntrLine_OleInPlaceSiteVtbl.CanInPlaceActivate + = CntrLine_IPSite_CanInPlaceActivate; + g_CntrLine_OleInPlaceSiteVtbl.OnInPlaceActivate + = CntrLine_IPSite_OnInPlaceActivate; + g_CntrLine_OleInPlaceSiteVtbl.OnUIActivate + = CntrLine_IPSite_OnUIActivate; + g_CntrLine_OleInPlaceSiteVtbl.GetWindowContext + = CntrLine_IPSite_GetWindowContext; + g_CntrLine_OleInPlaceSiteVtbl.Scroll + = CntrLine_IPSite_Scroll; + g_CntrLine_OleInPlaceSiteVtbl.OnUIDeactivate + = CntrLine_IPSite_OnUIDeactivate; + + g_CntrLine_OleInPlaceSiteVtbl.OnInPlaceDeactivate + = CntrLine_IPSite_OnInPlaceDeactivate; + g_CntrLine_OleInPlaceSiteVtbl.DiscardUndoState + = CntrLine_IPSite_DiscardUndoState; + g_CntrLine_OleInPlaceSiteVtbl.DeactivateAndUndo + = CntrLine_IPSite_DeactivateAndUndo; + g_CntrLine_OleInPlaceSiteVtbl.OnPosRectChange + = CntrLine_IPSite_OnPosRectChange; + + fStatus = OleStdCheckVtbl( + &g_CntrLine_OleInPlaceSiteVtbl, + sizeof(g_CntrLine_OleInPlaceSiteVtbl), + "IOleInPlaceSite" + ); + if (! fStatus) return FALSE; + +#endif // INPLACE_CNTR + + return TRUE; +} + + +#endif // OLE_CNTR diff --git a/private/oleutest/letest/outline/oledoc.c b/private/oleutest/letest/outline/oledoc.c new file mode 100644 index 000000000..53bbe08e5 --- /dev/null +++ b/private/oleutest/letest/outline/oledoc.c @@ -0,0 +1,1179 @@ +/************************************************************************* +** +** OLE 2 Server Sample Code +** +** oledoc.c +** +** This file contains general OleDoc methods and related support +** functions. OleDoc implementation is used by both the Container +** versions and the Server (Object) versions of the Outline Sample. +** +** This file includes general support for the following: +** 1. show/hide doc window +** 2. QueryInterface, AddRef, Release +** 3. document locking (calls CoLockObjectExternal) +** 4. document shutdown (Close, Destroy) +** 5. clipboard support +** +** OleDoc Object +** exposed interfaces: +** IUnknown +** IPersistFile +** IOleItemContainer +** IDataObject +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + + +#include "outline.h" + +OLEDBGDATA + +extern LPOUTLINEAPP g_lpApp; + +extern IUnknownVtbl g_OleDoc_UnknownVtbl; +extern IPersistFileVtbl g_OleDoc_PersistFileVtbl; +extern IOleItemContainerVtbl g_OleDoc_OleItemContainerVtbl; +extern IExternalConnectionVtbl g_OleDoc_ExternalConnectionVtbl; +extern IDataObjectVtbl g_OleDoc_DataObjectVtbl; + +#if defined( USE_DRAGDROP ) +extern IDropTargetVtbl g_OleDoc_DropTargetVtbl; +extern IDropSourceVtbl g_OleDoc_DropSourceVtbl; +#endif // USE_DRAGDROP + +#if defined( INPLACE_CNTR ) +extern BOOL g_fInsideOutContainer; +#endif + + +/* OleDoc_Init + * ----------- + * + * Initialize the fields of a new OleDoc object. The object is initially + * not associated with a file or an (Untitled) document. This function sets + * the docInitType to DOCTYPE_UNKNOWN. After calling this function the + * caller should call: + * 1.) Doc_InitNewFile to set the OleDoc to (Untitled) + * 2.) Doc_LoadFromFile to associate the OleDoc with a file. + * This function creates a new window for the document. + * + * NOTE: the window is initially created with a NIL size. it must be + * sized and positioned by the caller. also the document is initially + * created invisible. the caller must call OutlineDoc_ShowWindow + * after sizing it to make the document window visible. + */ +BOOL OleDoc_Init(LPOLEDOC lpOleDoc, BOOL fDataTransferDoc) +{ + LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; + LPLINELIST lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList; + + lpOleDoc->m_cRef = 0; + lpOleDoc->m_dwStrongExtConn = 0; +#if defined( _DEBUG ) + lpOleDoc->m_cCntrLock = 0; +#endif + lpOleDoc->m_lpStg = NULL; + lpOleDoc->m_lpLLStm = NULL; + lpOleDoc->m_lpNTStm = NULL; + lpOleDoc->m_dwRegROT = 0; + lpOleDoc->m_lpFileMoniker = NULL; + lpOleDoc->m_fLinkSourceAvail = FALSE; + lpOleDoc->m_lpSrcDocOfCopy = NULL; + lpOleDoc->m_fObjIsClosing = FALSE; + lpOleDoc->m_fObjIsDestroying = FALSE; + lpOleDoc->m_fUpdateEditMenu = FALSE; + +#if defined( USE_DRAGDROP ) + lpOleDoc->m_dwTimeEnterScrollArea = 0L; + lpOleDoc->m_dwNextScrollTime = 0L; + lpOleDoc->m_dwLastScrollDir = SCROLLDIR_NULL; + lpOleDoc->m_fRegDragDrop = FALSE; + lpOleDoc->m_fLocalDrag = FALSE; + lpOleDoc->m_fCanDropCopy = FALSE; + lpOleDoc->m_fCanDropLink = FALSE; + lpOleDoc->m_fLocalDrop = FALSE; + lpOleDoc->m_fDragLeave = FALSE; + lpOleDoc->m_fPendingDrag = FALSE; +#endif +#if defined( INPLACE_SVR ) || defined( INPLACE_CNTR ) + lpOleDoc->m_fCSHelpMode = FALSE; // Shift-F1 context + // sensitive help mode +#endif + + INIT_INTERFACEIMPL( + &lpOleDoc->m_Unknown, + &g_OleDoc_UnknownVtbl, + lpOleDoc + ); + + INIT_INTERFACEIMPL( + &lpOleDoc->m_PersistFile, + &g_OleDoc_PersistFileVtbl, + lpOleDoc + ); + + INIT_INTERFACEIMPL( + &lpOleDoc->m_OleItemContainer, + &g_OleDoc_OleItemContainerVtbl, + lpOleDoc + ); + + INIT_INTERFACEIMPL( + &lpOleDoc->m_ExternalConnection, + &g_OleDoc_ExternalConnectionVtbl, + lpOleDoc + ); + + INIT_INTERFACEIMPL( + &lpOleDoc->m_DataObject, + &g_OleDoc_DataObjectVtbl, + lpOleDoc + ); + +#if defined( USE_DRAGDROP ) + INIT_INTERFACEIMPL( + &lpOleDoc->m_DropSource, + &g_OleDoc_DropSourceVtbl, + lpOleDoc + ); + + INIT_INTERFACEIMPL( + &lpOleDoc->m_DropTarget, + &g_OleDoc_DropTargetVtbl, + lpOleDoc + ); +#endif // USE_DRAGDROP + + /* + ** OLE2NOTE: each user level document addref's the app object in + ** order to guarentee that the app does not shut down while the + ** doc is still open. + */ + + // OLE2NOTE: data transfer documents should not hold the app alive + if (! fDataTransferDoc) + OleApp_DocLockApp(lpOleApp); + +#if defined( OLE_SERVER ) + /* OLE2NOTE: perform initialization specific for an OLE server */ + if (! ServerDoc_Init((LPSERVERDOC)lpOleDoc, fDataTransferDoc)) + return FALSE; +#endif +#if defined( OLE_CNTR ) + + /* OLE2NOTE: perform initialization specific for an OLE container */ + if (! ContainerDoc_Init((LPCONTAINERDOC)lpOleDoc, fDataTransferDoc)) + return FALSE; +#endif + + return TRUE; +} + + + +/* OleDoc_InitNewFile + * ------------------ + * + * Initialize the document to be a new (Untitled) document. + * This function sets the docInitType to DOCTYPE_NEW. + * + * OLE2NOTE: if this is a visible user document then generate a unique + * untitled name that we can use to register in the RunningObjectTable. + * We need a unique name so that clients can link to data in this document + * even when the document is in the un-saved (untitled) state. it would be + * ambiguous to register two documents titled "Outline1" in the ROT. we + * thus generate the lowest numbered document that is not already + * registered in the ROT. + */ +BOOL OleDoc_InitNewFile(LPOLEDOC lpOleDoc) +{ + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc; + + static UINT uUnique = 1; + + OleDbgAssert(lpOutlineDoc->m_docInitType == DOCTYPE_UNKNOWN); + +#if defined( OLE_CNTR ) + { + LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOleDoc; +#if defined( _DEBUG ) + OleDbgAssertSz(lpOleDoc->m_lpStg == NULL, + "Setting to untitled with current file open" + ); +#endif + + /* Create a temp, (delete-on-release) file base storage + ** for the untitled document. + */ + lpOleDoc->m_lpStg = OleStdCreateRootStorage( + NULL, + STGM_SHARE_EXCLUSIVE + ); + if (! lpOleDoc->m_lpStg) return FALSE; + } +#endif + + lpOutlineDoc->m_docInitType = DOCTYPE_NEW; + + if (! lpOutlineDoc->m_fDataTransferDoc) { + /* OLE2NOTE: choose a unique name for a Moniker so that + ** potential clients can link to our new, untitled document. + ** if links are established (and currently are connected), + ** then they will be notified that we have been renamed when + ** this document is saved to a file. + */ + + lpOleDoc->m_fLinkSourceAvail = TRUE; + + // REVIEW: should load UNTITLED string from string resource + OleStdCreateTempFileMoniker( + UNTITLED, + (UINT FAR*)&uUnique, + lpOutlineDoc->m_szFileName, + &lpOleDoc->m_lpFileMoniker + ); + + OLEDBG_BEGIN3("OleStdRegisterAsRunning called\r\n") + OleStdRegisterAsRunning( + (LPUNKNOWN)&lpOleDoc->m_PersistFile, + (LPMONIKER)lpOleDoc->m_lpFileMoniker, + &lpOleDoc->m_dwRegROT + ); + OLEDBG_END3 + + lpOutlineDoc->m_lpszDocTitle = lpOutlineDoc->m_szFileName; + OutlineDoc_SetTitle(lpOutlineDoc, FALSE /*fMakeUpperCase*/); + } else { + lstrcpy(lpOutlineDoc->m_szFileName, UNTITLED); + lpOutlineDoc->m_lpszDocTitle = lpOutlineDoc->m_szFileName; + } + + return TRUE; +} + + +/* OleDoc_ShowWindow + * ----------------- + * + * Show the window of the document to the user. + * make sure app window is visible and bring the document to the top. + * if the document is a file-based document or a new untitled + * document, give the user the control over the life-time of the doc. + */ +void OleDoc_ShowWindow(LPOLEDOC lpOleDoc) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc; + LPLINELIST lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList; +#if defined( OLE_SERVER ) + LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOleDoc; +#endif // OLE_SERVER + + OLEDBG_BEGIN3("OleDoc_ShowWindow\r\n") + + /* OLE2NOTE: while the document is visible, we do NOT want it to be + ** prematurely destroyed when a linking client disconnects. thus + ** we must inform OLE to hold an external lock on our document. + ** this arranges that OLE holds at least 1 reference to our + ** document that will NOT be released until we release this + ** external lock. later, when the document window is hidden, we + ** will release this external lock. + */ + if (! IsWindowVisible(lpOutlineDoc->m_hWndDoc)) + OleDoc_Lock(lpOleDoc, TRUE /* fLock */, 0 /* not applicable */); + +#if defined( USE_DRAGDROP ) + /* OLE2NOTE: since our window is now being made visible, we will + ** register our window as a potential drop target. when the + ** window is hidden there is no reason to be registered as a + ** drop target. + */ + if (! lpOleDoc->m_fRegDragDrop) { + OLEDBG_BEGIN2("RegisterDragDrop called\r\n") + RegisterDragDrop( + LineList_GetWindow(lpLL), + (LPDROPTARGET)&lpOleDoc->m_DropTarget + ); + OLEDBG_END2 + lpOleDoc->m_fRegDragDrop = TRUE; + } +#endif // USE_DRAGDROP + +#if defined( USE_FRAMETOOLS ) + { + /* OLE2NOTE: we need to enable our frame level tools + */ + FrameTools_Enable(lpOutlineDoc->m_lpFrameTools, TRUE); + } +#endif // USE_FRAMETOOLS + +#if defined( OLE_SERVER ) + + if (lpOutlineDoc->m_docInitType == DOCTYPE_EMBEDDED && + lpServerDoc->m_lpOleClientSite != NULL) { + + /* OLE2NOTE: we must also ask our container to show itself if + ** it is not already visible and to scroll us into view. we + ** must make sure to call this BEFORE showing our server's + ** window and taking focus. we do not want our container's + ** window to end up on top. + */ + OLEDBG_BEGIN2("IOleClientSite::ShowObject called\r\n"); + lpServerDoc->m_lpOleClientSite->lpVtbl->ShowObject( + lpServerDoc->m_lpOleClientSite + ); + OLEDBG_END2 + + /* OLE2NOTE: if we are an embedded object and we are not + ** in-place active in our containers window, we must inform our + ** embedding container that our window is opening. + ** the container must now hatch our object. + */ + +#if defined( INPLACE_SVR ) + if (! lpServerDoc->m_fInPlaceActive) +#endif + { + OLEDBG_BEGIN2("IOleClientSite::OnShowWindow(TRUE) called\r\n"); + lpServerDoc->m_lpOleClientSite->lpVtbl->OnShowWindow( + lpServerDoc->m_lpOleClientSite, + TRUE + ); + OLEDBG_END2 + } + + /* OLE2NOTE: the life-time of our document is controlled by our + ** client and NOT by the user. we are not an independent + ** file-level object. we simply want to show our window here. + ** + ** if we are not in-place active (ie. we are opening + ** our own window), we must make sure our main app window is + ** visible. we do not, however, want to give the user + ** control of the App window; we do not want OleApp_ShowWindow + ** to call OleApp_Lock on behalf of the user. + */ + if (! IsWindowVisible(lpOutlineApp->m_hWndApp) || + IsIconic(lpOutlineApp->m_hWndApp)) { +#if defined( INPLACE_SVR ) + if (! ((LPSERVERDOC)lpOleDoc)->m_fInPlaceActive) +#endif + OleApp_ShowWindow(lpOleApp, FALSE /* fGiveUserCtrl */); + SetFocus(lpOutlineDoc->m_hWndDoc); + } + + } else +#endif // OLE_SERVER + + { // DOCTYPE_NEW || DOCTYPE_FROMFILE + + // we must make sure our app window is visible + OleApp_ShowWindow(lpOleApp, TRUE /* fGiveUserCtrl */); + } + + // make document window visible and make sure it is not minimized + ShowWindow(lpOutlineDoc->m_hWndDoc, SW_SHOWNORMAL); + SetFocus(lpOutlineDoc->m_hWndDoc); + + OLEDBG_END3 +} + + +/* OleDoc_HideWindow + * ----------------- + * + * Hide the window of the document from the user. + * take away the control of the document by the user. + */ +void OleDoc_HideWindow(LPOLEDOC lpOleDoc, BOOL fShutdown) +{ + LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc; + LPLINELIST lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList; + + if (! IsWindowVisible(lpOutlineDoc->m_hWndDoc)) + return; // already visible + + OLEDBG_BEGIN3("OleDoc_HideWindow\r\n") + +#if defined( USE_DRAGDROP ) + // The document's window is being hidden, revoke it as a DropTarget + if (lpOleDoc->m_fRegDragDrop) { + OLEDBG_BEGIN2("RevokeDragDrop called\r\n"); + RevokeDragDrop(LineList_GetWindow(lpLL)); + OLEDBG_END2 + + lpOleDoc->m_fRegDragDrop = FALSE ; + } +#endif // USE_DRAGDROP + + /* OLE2NOTE: the document is now being hidden, so we must release + ** the external lock made when the document was made visible. + ** if this is a shutdown situation (fShutdown==TRUE), then OLE + ** is instructed to release our document. if this is that last + ** external lock on our document, thus enabling our document to + ** complete its shutdown operation. If This is not a shutdown + ** situation (eg. in-place server hiding its window when + ** UIDeactivating or IOleObject::DoVerb(OLEVERB_HIDE) is called), + ** then OLE is told to NOT immediately release the document. + ** this leaves the document in an unstable state where the next + ** Lock/Unlock sequence will shut the document down (eg. a + ** linking client connecting and disconnecting). + */ + if (IsWindowVisible(lpOutlineDoc->m_hWndDoc)) + OleDoc_Lock(lpOleDoc, FALSE /* fLock */, fShutdown); + + ShowWindow(((LPOUTLINEDOC)lpOleDoc)->m_hWndDoc, SW_HIDE); + +#if defined( OLE_SERVER ) + { + LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOleDoc; + + /* OLE2NOTE: if we are an embedded object and we are not + ** in-place active, we must inform our + ** embedding container that our window is hiding (closing + ** from the user's perspective). the container must now + ** un-hatch our object. + */ + if (lpServerDoc->m_lpOleClientSite != NULL +#if defined( INPLACE_SVR ) + && !lpServerDoc->m_fInPlaceVisible +#endif + ) { + OLEDBG_BEGIN2("IOleClientSite::OnShowWindow(FALSE) called\r\n"); + lpServerDoc->m_lpOleClientSite->lpVtbl->OnShowWindow( + lpServerDoc->m_lpOleClientSite, + FALSE + ); + OLEDBG_END2 + } + } +#endif + + /* OLE2NOTE: if there are no more documents visible to the user. + ** and the app itself is not under user control, then + ** it has no reason to stay visible. we thus should hide the + ** app. we can not directly destroy the app, because it may be + ** validly being used programatically by another client + ** application and should remain running. it should simply be + ** hidded from the user. + */ + OleApp_HideIfNoReasonToStayVisible(lpOleApp); + OLEDBG_END3 +} + + +/* OleDoc_Lock +** ----------- +** Lock/Unlock the Doc object. if the last lock is unlocked and +** fLastUnlockReleases == TRUE, then the Doc object will shut down +** (ie. it will recieve its final release and its refcnt will go to 0). +*/ +HRESULT OleDoc_Lock(LPOLEDOC lpOleDoc, BOOL fLock, BOOL fLastUnlockReleases) +{ + HRESULT hrErr; + +#if defined( _DEBUG ) + if (fLock) { + OLEDBG_BEGIN2("CoLockObjectExternal(lpDoc,TRUE) called\r\n") + } else { + if (fLastUnlockReleases) + OLEDBG_BEGIN2("CoLockObjectExternal(lpDoc,FALSE,TRUE) called\r\n") + else + OLEDBG_BEGIN2("CoLockObjectExternal(lpDoc,FALSE,FALSE) called\r\n") + } +#endif // _DEBUG + + hrErr = CoLockObjectExternal( + (LPUNKNOWN)&lpOleDoc->m_Unknown, fLock, fLastUnlockReleases); + + OLEDBG_END2 + return hrErr; +} + + +/* OleDoc_AddRef +** ------------- +** +** increment the ref count of the document object. +** +** Returns the new ref count on the object +*/ +ULONG OleDoc_AddRef(LPOLEDOC lpOleDoc) +{ + ++lpOleDoc->m_cRef; + +#if defined( _DEBUG ) + OleDbgOutRefCnt4( + "OleDoc_AddRef: cRef++\r\n", + lpOleDoc, + lpOleDoc->m_cRef + ); +#endif + return lpOleDoc->m_cRef; +} + + +/* OleDoc_Release +** -------------- +** +** decrement the ref count of the document object. +** if the ref count goes to 0, then the document is destroyed. +** +** Returns the remaining ref count on the object +*/ +ULONG OleDoc_Release (LPOLEDOC lpOleDoc) +{ + ULONG cRef; + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; + + /********************************************************************* + ** OLE2NOTE: when the obj refcnt == 0, then destroy the object. ** + ** otherwise the object is still in use. ** + *********************************************************************/ + + cRef = --lpOleDoc->m_cRef; + +#if defined( _DEBUG ) + OleDbgAssertSz (lpOleDoc->m_cRef >= 0, "Release called with cRef == 0"); + + OleDbgOutRefCnt4( + "OleDoc_Release: cRef--\r\n", lpOleDoc, cRef); +#endif + if (cRef == 0) + OutlineDoc_Destroy((LPOUTLINEDOC)lpOleDoc); + + return cRef; +} + + +/* OleDoc_QueryInterface +** --------------------- +** +** Retrieve a pointer to an interface on the document object. +** +** OLE2NOTE: this function will AddRef the ref cnt of the object. +** +** Returns S_OK if interface is successfully retrieved. +** E_NOINTERFACE if the interface is not supported +*/ +HRESULT OleDoc_QueryInterface( + LPOLEDOC lpOleDoc, + REFIID riid, + LPVOID FAR* lplpvObj +) +{ + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc; + SCODE sc = E_NOINTERFACE; + + /* OLE2NOTE: we must make sure to set all out ptr parameters to NULL. */ + *lplpvObj = NULL; + + if (IsEqualIID(riid, &IID_IUnknown)) { + OleDbgOut4("OleDoc_QueryInterface: IUnknown* RETURNED\r\n"); + + *lplpvObj = (LPVOID) &lpOleDoc->m_Unknown; + OleDoc_AddRef(lpOleDoc); + sc = S_OK; + } + else if(lpOutlineDoc->m_fDataTransferDoc + && IsEqualIID(riid, &IID_IDataObject)) { + OleDbgOut4("OleDoc_QueryInterface: IDataObject* RETURNED\r\n"); + + *lplpvObj = (LPVOID) &lpOleDoc->m_DataObject; + OleDoc_AddRef(lpOleDoc); + sc = S_OK; + } + + /* OLE2NOTE: if this document is a DataTransferDocument used to + ** support a clipboard or drag/drop operation, then it should + ** only expose IUnknown, IDataObject, and IDropSource + ** interfaces. if the document is a normal user document, then + ** we will also continue to consider our other interfaces. + */ + if (lpOutlineDoc->m_fDataTransferDoc) + goto done; + + if(IsEqualIID(riid,&IID_IPersist) || IsEqualIID(riid,&IID_IPersistFile)) { + OleDbgOut4("OleDoc_QueryInterface: IPersistFile* RETURNED\r\n"); + + *lplpvObj = (LPVOID) &lpOleDoc->m_PersistFile; + OleDoc_AddRef(lpOleDoc); + sc = S_OK; + } + else if(IsEqualIID(riid, &IID_IOleItemContainer) || + IsEqualIID(riid, &IID_IOleContainer) || + IsEqualIID(riid, &IID_IParseDisplayName) ) { + OleDbgOut4("OleDoc_QueryInterface: IOleItemContainer* RETURNED\r\n"); + + *lplpvObj = (LPVOID) &lpOleDoc->m_OleItemContainer; + OleDoc_AddRef(lpOleDoc); + sc = S_OK; + } + else if(IsEqualIID(riid, &IID_IExternalConnection)) { + OleDbgOut4("OleDoc_QueryInterface: IExternalConnection* RETURNED\r\n"); + + *lplpvObj = (LPVOID) &lpOleDoc->m_ExternalConnection; + OleDoc_AddRef(lpOleDoc); + sc = S_OK; + } + +#if defined( USE_DRAGDROP ) + else if(IsEqualIID(riid, &IID_IDropTarget)) { + OleDbgOut4("OleDoc_QueryInterface: IDropTarget* RETURNED\r\n"); + + *lplpvObj = (LPVOID) &lpOleDoc->m_DropTarget; + OleDoc_AddRef(lpOleDoc); + sc = S_OK; + } + else if(IsEqualIID(riid, &IID_IDropSource)) { + OleDbgOut4("OleDoc_QueryInterface: IDropSource* RETURNED\r\n"); + + *lplpvObj = (LPVOID) &lpOleDoc->m_DropSource; + OleDoc_AddRef(lpOleDoc); + sc = S_OK; + } +#endif + +#if defined( OLE_CNTR ) + else if (IsEqualIID(riid, &IID_IOleUILinkContainer)) { + OleDbgOut4("OleDoc_QueryInterface: IOleUILinkContainer* RETURNED\r\n"); + + *lplpvObj=(LPVOID)&((LPCONTAINERDOC)lpOleDoc)->m_OleUILinkContainer; + OleDoc_AddRef(lpOleDoc); + sc = S_OK; + } +#endif + +#if defined( OLE_SERVER ) + + /* OLE2NOTE: if OLE server version, than also offer the server + ** specific interfaces: IOleObject and IPersistStorage. + */ + else if (IsEqualIID(riid, &IID_IOleObject)) { + OleDbgOut4("OleDoc_QueryInterface: IOleObject* RETURNED\r\n"); + + *lplpvObj = (LPVOID) &((LPSERVERDOC)lpOleDoc)->m_OleObject; + OleDoc_AddRef(lpOleDoc); + sc = S_OK; + } + else if(IsEqualIID(riid, &IID_IPersistStorage)) { + OleDbgOut4("OleDoc_QueryInterface: IPersistStorage* RETURNED\r\n"); + + *lplpvObj = (LPVOID) &((LPSERVERDOC)lpOleDoc)->m_PersistStorage; + OleDoc_AddRef(lpOleDoc); + sc = S_OK; + } + else if(IsEqualIID(riid, &IID_IDataObject)) { + OleDbgOut4("OleDoc_QueryInterface: IDataObject* RETURNED\r\n"); + + *lplpvObj = (LPVOID) &lpOleDoc->m_DataObject; + OleDoc_AddRef(lpOleDoc); + sc = S_OK; + } + +#if defined( SVR_TREATAS ) + else if(IsEqualIID(riid, &IID_IStdMarshalInfo)) { + OleDbgOut4("OleDoc_QueryInterface: IStdMarshalInfo* RETURNED\r\n"); + + *lplpvObj = (LPVOID) &((LPSERVERDOC)lpOleDoc)->m_StdMarshalInfo; + OleDoc_AddRef(lpOleDoc); + sc = S_OK; + } +#endif // SVR_TREATAS + +#if defined( INPLACE_SVR ) + else if (IsEqualIID(riid, &IID_IOleWindow) || + IsEqualIID(riid, &IID_IOleInPlaceObject)) { + OleDbgOut4("OleDoc_QueryInterface: IOleInPlaceObject* RETURNED\r\n"); + + *lplpvObj = (LPVOID) &((LPSERVERDOC)lpOleDoc)->m_OleInPlaceObject; + OleDoc_AddRef(lpOleDoc); + sc = S_OK; + } +#endif // INPLACE_SVR +#endif // OLE_SERVER + +done: + OleDbgQueryInterfaceMethod(*lplpvObj); + + return ResultFromScode(sc); +} + + +/* OleDoc_Close + * ------------ + * + * Close the document. + * This functions performs the actions that are in common to all + * document types which derive from OleDoc (eg. ContainerDoc and + * ServerDoc) which are required to close a document. + * + * Returns: + * FALSE -- user canceled the closing of the doc. + * TRUE -- the doc was successfully closed + */ + +BOOL OleDoc_Close(LPOLEDOC lpOleDoc, DWORD dwSaveOption) +{ + LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + LPOLEDOC lpClipboardDoc; + LPLINELIST lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList; + BOOL fAbortIfSaveCanceled = (dwSaveOption == OLECLOSE_PROMPTSAVE); + + if (! lpOleDoc) + return TRUE; // active doc's are already destroyed + + if (lpOleDoc->m_fObjIsClosing) + return TRUE; // Closing is already in progress + + OLEDBG_BEGIN3("OleDoc_Close\r\n") + + if (! OutlineDoc_CheckSaveChanges((LPOUTLINEDOC)lpOleDoc,&dwSaveOption) + && fAbortIfSaveCanceled) { + OLEDBG_END3 + return FALSE; // cancel closing the doc + } + + lpOleDoc->m_fObjIsClosing = TRUE; // guard against recursive call + + /* OLE2NOTE: in order to have a stable app and doc during the + ** process of closing, we intially AddRef the App and Doc ref + ** cnts and later Release them. These initial AddRefs are + ** artificial; they simply guarantee that these objects do not + ** get destroyed until the end of this routine. + */ + OleApp_AddRef(lpOleApp); + OleDoc_AddRef(lpOleDoc); + +#if defined( OLE_CNTR ) + { + LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOleDoc; + + /* OLE2NOTE: force all OLE objects to close. this forces all + ** OLE object to transition from running to loaded. we can + ** NOT exit if any embeddings are still running. + ** if an object can't be closed and this close operation was + ** started by the user, then we will abort closing our document. + */ + if (! ContainerDoc_CloseAllOleObjects(lpContainerDoc, OLECLOSE_NOSAVE) + && fAbortIfSaveCanceled) { + OleDoc_Release(lpOleDoc); // release artificial AddRef above + OleApp_Release(lpOleApp); // release artificial AddRef above + lpOleDoc->m_fObjIsClosing = FALSE; // clear recursion guard + + OLEDBG_END3 + return FALSE; // Closing is aborted + } + } +#endif + +#if defined( INPLACE_SVR ) + /* OLE2NOTE: if the server is currently in-place active we must + ** deactivate it now before closing + */ + ServerDoc_DoInPlaceDeactivate((LPSERVERDOC)lpOleDoc); +#endif + + /* OLE2NOTE: if this document is the source of data for the + ** clipboard, then flush the clipboard. it is important to flush + ** the clipboard BEFORE calling sending any notifications to + ** clients (eg. IOleClientSite::OnShowWindow(FALSE)) which could + ** give them a chance to run and try to get our clipboard data + ** object that we want to destroy. (eg. our app tries to + ** update the paste button of the toolbar when + ** WM_ACTIVATEAPP is received.) + */ + lpClipboardDoc = (LPOLEDOC)lpOutlineApp->m_lpClipboardDoc; + if (lpClipboardDoc && + lpClipboardDoc->m_lpSrcDocOfCopy == lpOleDoc) { + OleApp_FlushClipboard(lpOleApp); + } + + /* OLE2NOTE: Revoke the object from the Running Object Table. it is + ** best if the object is revoke prior to calling + ** COLockObjectExternal(FALSE,TRUE) which is called when the + ** document window is hidden from the user. + */ + OLEDBG_BEGIN3("OleStdRevokeAsRunning called\r\n") + OleStdRevokeAsRunning(&lpOleDoc->m_dwRegROT); + OLEDBG_END3 + + /* OLE2NOTE: if the user is in control of the document, the user + ** accounts for one refcnt on the document. Closing the + ** document is achieved by releasing the object on behalf of + ** the user. if the document is not referenced by any other + ** clients, then the document will also be destroyed. if it + ** is referenced by other clients, then it will remain until + ** they release it. it is important to hide the window and call + ** IOleClientSite::OnShowWindow(FALSE) BEFORE sending OnClose + ** notification. + */ + OleDoc_HideWindow(lpOleDoc, TRUE); + +#if defined( OLE_SERVER ) + { + LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOleDoc; + LPSERVERNAMETABLE lpServerNameTable = + (LPSERVERNAMETABLE)((LPOUTLINEDOC)lpOleDoc)->m_lpNameTable; + + /* OLE2NOTE: force all pseudo objects to close. this informs all + ** linking clients of pseudo objects to release their PseudoObj. + */ + ServerNameTable_CloseAllPseudoObjs(lpServerNameTable); + + /* OLE2NOTE: send last OnDataChange notification to clients + ** that have registered for data notifications when object + ** stops running (ADVF_DATAONSTOP), if the data in our + ** object has ever changed. it is best to only send this + ** notification if necessary. + */ + if (lpServerDoc->m_lpDataAdviseHldr) { + if (lpServerDoc->m_fSendDataOnStop) { + ServerDoc_SendAdvise( + (LPSERVERDOC)lpOleDoc, + OLE_ONDATACHANGE, + NULL, /* lpmkDoc -- not relevant here */ + ADVF_DATAONSTOP + ); + } + /* OLE2NOTE: we just sent the last data notification that we + ** need to send; release our DataAdviseHolder. we SHOULD be + ** the only one using it. + */ + + OleStdVerifyRelease( + (LPUNKNOWN)lpServerDoc->m_lpDataAdviseHldr, + "DataAdviseHldr not released properly" + ); + lpServerDoc->m_lpDataAdviseHldr = NULL; + } + + // OLE2NOTE: inform all of our linking clients that we are closing. + + + if (lpServerDoc->m_lpOleAdviseHldr) { + ServerDoc_SendAdvise( + (LPSERVERDOC)lpOleDoc, + OLE_ONCLOSE, + NULL, /* lpmkDoc -- not relevant here */ + 0 /* advf -- not relevant here */ + ); + + /* OLE2NOTE: OnClose is the last notification that we need to + ** send; release our OleAdviseHolder. we SHOULD be the only + ** one using it. this will make our destructor realize that + ** OnClose notification has already been sent. + */ + OleStdVerifyRelease( + (LPUNKNOWN)lpServerDoc->m_lpOleAdviseHldr, + "OleAdviseHldr not released properly" + ); + lpServerDoc->m_lpOleAdviseHldr = NULL; + } + + /* release our Container's ClientSite. */ + if(lpServerDoc->m_lpOleClientSite) { + OleStdRelease((LPUNKNOWN)lpServerDoc->m_lpOleClientSite); + lpServerDoc->m_lpOleClientSite = NULL; + } + } +#endif + + if (lpOleDoc->m_lpLLStm) { + /* release our LineList stream. */ + OleStdRelease((LPUNKNOWN)lpOleDoc->m_lpLLStm); + lpOleDoc->m_lpLLStm = NULL; + } + + if (lpOleDoc->m_lpNTStm) { + /* release our NameTable stream. */ + OleStdRelease((LPUNKNOWN)lpOleDoc->m_lpNTStm); + lpOleDoc->m_lpNTStm = NULL; + } + + if (lpOleDoc->m_lpStg) { + /* release our doc storage. */ + OleStdRelease((LPUNKNOWN)lpOleDoc->m_lpStg); + lpOleDoc->m_lpStg = NULL; + } + + if (lpOleDoc->m_lpFileMoniker) { + OleStdRelease((LPUNKNOWN)lpOleDoc->m_lpFileMoniker); + lpOleDoc->m_lpFileMoniker = NULL; + } + + /* OLE2NOTE: this call forces all external connections to our + ** object to close down and therefore guarantees that we receive + ** all releases associated with those external connections. + */ + OLEDBG_BEGIN2("CoDisconnectObject(lpDoc) called\r\n") + CoDisconnectObject((LPUNKNOWN)&lpOleDoc->m_Unknown, 0); + OLEDBG_END2 + + OleDoc_Release(lpOleDoc); // release artificial AddRef above + OleApp_Release(lpOleApp); // release artificial AddRef above + + OLEDBG_END3 + return TRUE; +} + + +/* OleDoc_Destroy + * -------------- + * + * Free all OLE related resources that had been allocated for a document. + */ +void OleDoc_Destroy(LPOLEDOC lpOleDoc) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc; + + if (lpOleDoc->m_fObjIsDestroying) + return; // Doc destruction is already in progress + + lpOleDoc->m_fObjIsDestroying = TRUE; // guard against recursive call + +#if defined( OLE_SERVER ) + + /* OLE2NOTE: it is ALWAYS necessary to make sure that the work we + ** do in our OleDoc_Close function is performed before we + ** destroy our document object. this includes revoking from the + ** Running Object Table (ROT), sending OnClose notification, + ** revoking from Drag/Drop, closing all pseudo objects, etc. + ** There are some tricky scenarios involving linking and + ** when IOleObject::Close is called versus when we get our + ** final release causing us to call our OleDoc_Destroy + ** (destructor) function. + ** + ** SCENARIO 1 -- closing from server (File.Exit or File.Close) + ** OleDoc_Close function is called directly by the + ** server in response to the menu command + ** (WM_COMMAND processing). + ** + ** SCENARIO 2 -- closed by embedding container + ** our embedding container calls IOleObject::Close + ** directly. + ** + ** SCENARIO 3 -- silent-update final release + ** THIS IS THE TRICKY ONE!!! + ** in the case that our object is launched because + ** a linking client calls IOleObject::Update on + ** its link, then our object will be run + ** invisibly, typically GetData will be called, + ** and then the connection from the linking client + ** will be released. the release of this last + ** linking connection should cause our object to + ** shut down. + ** there are 2 strategies to deal with this scenario: + ** + ** STRATEGY 1 -- implement IExternalConnection. + ** IExternalConnection::AddConnection will be + ** called (by the StubManager) every time that an + ** external (linking) connection is created or + ** CoLockObjectExternal is called. the object + ** should maintain a count of strong connections + ** (m_dwStrongExtConn). IExternalConnection:: + ** ReleaseConnection will be called when these + ** connections are released. when the + ** m_dwStrongExtConn transistions to 0, the object + ** should call its IOleObject::Close function. + ** this assumes that CoLockObjectExternal is used + ** to manage locks by the object itself (eg. when + ** the object is visible to the user--fUserCtrl, + ** and when PseudoObjects are created, etc.) + ** this is the strategy implemented by SVROUTL. + ** + ** STRATEGY 2 -- guard both the destructor + ** function and the Close function. if the + ** destructor is called directly without Close + ** first being called, then call Close before + ** proceeding with the destruction code. + ** previously SVROUTL was organized in this + ** manner. that old code is conditionaly compiled + ** away with "#ifdef OBSOLETE" below. this + ** method has the disadvantage that external + ** remoting is no longer possible by the time the + ** Close is called making it impossible for + ** the object to ask its container to save the + ** object if the object is dirty. this can result + ** in data loss. thus STRATEGY 1 is safer. + ** consider the scenario where an in-place + ** container UIDeactivates an object but does NOT + ** keep the object locked running (this is + ** required--see CntrLine_IPSite_OnInPlaceActivate + ** in cntrline.c), then, if a linking client binds + ** and unbinds from the object, the object will be + ** destroyed and will NOT have an opportunity to + ** be saved. by implementing IExternalConnection, + ** a server can insulate itself from a poorly + ** written container. + */ +#if defined( _DEBUG ) + +#ifndef WIN32 + // this is not a valid assert in Ole32; if file moniker binding + // fails, for example, we will only get releases coming in + // (no external connections are involved because OLE32 does a + // private rpc to the server (us) where the IPersistFile::Load is + // done. + + OleDbgAssertSz( + (lpOutlineDoc->m_fDataTransferDoc || lpOleDoc->m_fObjIsClosing), + "Destroy called without Close being called\r\n" + ); +#endif //!WIN32 + +#endif // _DEBUG +#if defined( OBSOLETE ) + /* OLE2NOTE: if the document destructor is called directly because + ** the object's refcnt went to 0 (ie. without OleDoc_Close first + ** being called), then we need to make sure that the document is + ** properly closed before destroying the object. this scenario + ** could arise during a silent-update of a link. calling + ** OleDoc_Close here guarantees that the clipboard will be + ** properly flushed, the doc's moniker will be properly revoked, + ** the document will be saved if necessary, etc. + */ + if (!lpOutlineDoc->m_fDataTransferDoc && !lpOleDoc->m_fObjIsClosing) + OleDoc_Close(lpOleDoc, OLECLOSE_NOSAVE); +#endif + + { + LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOleDoc; + /* OLE2NOTE: perform processing specific for an OLE server */ + +#if defined( SVR_TREATAS ) + if (lpServerDoc->m_lpszTreatAsType) { + OleStdFreeString(lpServerDoc->m_lpszTreatAsType, NULL); + lpServerDoc->m_lpszTreatAsType = NULL; + } +#endif // SVR_TREATAS + +#if defined( INPLACE_SVR ) + if (IsWindow(lpServerDoc->m_hWndHatch)) + DestroyWindow(lpServerDoc->m_hWndHatch); +#endif // INPLACE_SVR + } +#endif // OLE_SERVER + + if (lpOleDoc->m_lpLLStm) { + /* release our LineList stream. */ + OleStdRelease((LPUNKNOWN)lpOleDoc->m_lpLLStm); + lpOleDoc->m_lpLLStm = NULL; + } + + if (lpOleDoc->m_lpNTStm) { + /* release our NameTable stream. */ + OleStdRelease((LPUNKNOWN)lpOleDoc->m_lpNTStm); + lpOleDoc->m_lpNTStm = NULL; + } + + if (lpOleDoc->m_lpStg) { + /* release our doc storage. */ + OleStdRelease((LPUNKNOWN)lpOleDoc->m_lpStg); + lpOleDoc->m_lpStg = NULL; + } + + if (lpOleDoc->m_lpFileMoniker) { + OleStdRelease((LPUNKNOWN)lpOleDoc->m_lpFileMoniker); + lpOleDoc->m_lpFileMoniker = NULL; + } + + /***************************************************************** + ** OLE2NOTE: each document addref's the app object in order to ** + ** guarentee that the app does not shut down while the doc ** + ** is still open. since this doc is now destroyed, we will ** + ** release this refcnt now. if there are now more open ** + ** documents AND the app is not under the control of the ** + ** user (ie. launched by OLE) then the app will revoke its ** + ** ClassFactory. if there are no more references to the ** + ** ClassFactory after it is revoked, then the app will shut ** + ** down. this whole procedure is triggered by calling ** + ** OutlineApp_DocUnlockApp. ** + *****************************************************************/ + + OutlineApp_DocUnlockApp(lpOutlineApp, lpOutlineDoc); +} + + +/* OleDoc_SetUpdateEditMenuFlag + * ---------------------------- + * + * Purpose: + * Set/clear the UpdateEditMenuFlag in OleDoc. + * + * Parameters: + * fUpdate new value of the flag + * + * Returns: + */ +void OleDoc_SetUpdateEditMenuFlag(LPOLEDOC lpOleDoc, BOOL fUpdate) +{ + if (!lpOleDoc) + return; + + lpOleDoc->m_fUpdateEditMenu = fUpdate; +} + + +/* OleDoc_GetUpdateEditMenuFlag + * ---------------------------- + * + * Purpose: + * Get the value of the UpdateEditMenuFlag in OleDoc + * + * Parameters: + * + * Returns: + * value of the flag + */ +BOOL OleDoc_GetUpdateEditMenuFlag(LPOLEDOC lpOleDoc) +{ + if (!lpOleDoc) + return FALSE; + + return lpOleDoc->m_fUpdateEditMenu; +} + + + +/************************************************************************* +** OleDoc::IUnknown interface implementation +*************************************************************************/ + +STDMETHODIMP OleDoc_Unk_QueryInterface( + LPUNKNOWN lpThis, + REFIID riid, + LPVOID FAR* lplpvObj +) +{ + LPOLEDOC lpOleDoc = ((struct CDocUnknownImpl FAR*)lpThis)->lpOleDoc; + + return OleDoc_QueryInterface(lpOleDoc, riid, lplpvObj); +} + + +STDMETHODIMP_(ULONG) OleDoc_Unk_AddRef(LPUNKNOWN lpThis) +{ + LPOLEDOC lpOleDoc = ((struct CDocUnknownImpl FAR*)lpThis)->lpOleDoc; + + OleDbgAddRefMethod(lpThis, "IUnknown"); + + return OleDoc_AddRef(lpOleDoc); +} + + +STDMETHODIMP_(ULONG) OleDoc_Unk_Release (LPUNKNOWN lpThis) +{ + LPOLEDOC lpOleDoc = ((struct CDocUnknownImpl FAR*)lpThis)->lpOleDoc; + + OleDbgReleaseMethod(lpThis, "IUnknown"); + + return OleDoc_Release(lpOleDoc); +} diff --git a/private/oleutest/letest/outline/oleoutl.h b/private/oleutest/letest/outline/oleoutl.h new file mode 100644 index 000000000..f936295cc --- /dev/null +++ b/private/oleutest/letest/outline/oleoutl.h @@ -0,0 +1,734 @@ +/************************************************************************* +** +** OLE 2.0 Sample Code +** +** oleoutl.h +** +** This file contains file contains data structure defintions, +** function prototypes, constants, etc. which are common to the +** server version and the container version of the app. +** app version of the Outline series of sample applications: +** Outline -- base version of the app (without OLE functionality) +** SvrOutl -- OLE 2.0 Server sample app +** CntrOutl -- OLE 2.0 Containter sample app +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + +#if !defined( _OLEOUTL_H_ ) +#define _OLEOUTL_H_ + +#ifndef RC_INVOKED +#pragma message ("INCLUDING OLEOUTL.H from " __FILE__) +// make 'different levels of inderection' considered an error +#pragma warning (error:4047) +#endif /* RC_INVOKED */ + +#if defined( USE_MSGFILTER ) +#include "msgfiltr.h" +#endif // USE_MSGFILTER + +#include "defguid.h" + +/* Defines */ + +/* OLE2NOTE: these strings should correspond to the strings registered +** in the registration database. +*/ +// REVIEW: should load strings from resource file +#if defined( INPLACE_SVR ) +#define CLSID_APP CLSID_ISvrOtl +#define FULLUSERTYPENAME "Ole 2.0 In-Place Server Outline" +#define SHORTUSERTYPENAME "Outline" // max 15 chars +#undef APPFILENAMEFILTER +#define APPFILENAMEFILTER "Outline Files (*.OLN)|*.oln|All files (*.*)|*.*|" +#undef DEFEXTENSION +#define DEFEXTENSION "oln" // Default file extension +#endif // INPLACE_SVR + +#if defined( INPLACE_CNTR ) +#define CLSID_APP CLSID_ICntrOtl +#define FULLUSERTYPENAME "Ole 2.0 In-Place Container Outline" +// #define SHORTUSERTYPENAME "Outline" // max 15 chars +#undef APPFILENAMEFILTER +#define APPFILENAMEFILTER "CntrOutl Files (*.OLC)|*.olc|Outline Files (*.OLN)|*.oln|All files (*.*)|*.*|" +#undef DEFEXTENSION +#define DEFEXTENSION "olc" // Default file extension +#endif // INPLACE_CNTR + +#if defined( OLE_SERVER ) && !defined( INPLACE_SVR ) +#define CLSID_APP CLSID_SvrOutl +#define FULLUSERTYPENAME "Ole 2.0 Server Sample Outline" +#define SHORTUSERTYPENAME "Outline" +#undef APPFILENAMEFILTER +#define APPFILENAMEFILTER "Outline Files (*.OLN)|*.oln|All files (*.*)|*.*|" +#undef DEFEXTENSION +#define DEFEXTENSION "oln" // Default file extension +#endif // OLE_SERVER && ! INPLACE_SVR + +#if defined( OLE_CNTR ) && !defined( INPLACE_CNTR ) +#define CLSID_APP CLSID_CntrOutl +#define FULLUSERTYPENAME "Ole 2.0 Container Sample Outline" +// #define SHORTUSERTYPENAME "Outline" // max 15 chars +#undef APPFILENAMEFILTER +#define APPFILENAMEFILTER "CntrOutl Files (*.OLC)|*.olc|Outline Files (*.OLN)|*.oln|All files (*.*)|*.*|" +#undef DEFEXTENSION +#define DEFEXTENSION "olc" // Default file extension +#endif // OLE_CNTR && ! INPLACE_CNTR + +// Maximum number of formats offered by IDataObject::GetData/SetData +#define MAXNOFMTS 10 +#define MAXNOLINKTYPES 3 + +#if defined( USE_DRAGDROP ) +#define DD_SEL_THRESH HITTESTDELTA // Border threshold to start drag +#define MAX_SEL_ITEMS 0x0080 +#endif // USE_DRAGDROP + +/* Positions of the various menus */ +#define POS_FILEMENU 0 +#define POS_EDITMENU 1 +#define POS_VIEWMENU 2 +#define POS_LINEMENU 3 +#define POS_NAMEMENU 4 +#define POS_OPTIONSMENU 5 +#define POS_DEBUGMENU 6 +#define POS_HELPMENU 7 + + +#define POS_OBJECT 11 + + +/* Types */ + +// Document initialization type +#define DOCTYPE_EMBEDDED 3 // init from an IStorage* of an embedded obj +#define DOCTYPE_FROMSTG 4 // init from an IStorage* with doc bit set + +/* Forward type definitions */ +typedef struct tagOLEAPP FAR* LPOLEAPP; +typedef struct tagOLEDOC FAR* LPOLEDOC; + +/* Flags to control Moniker assignment for OleDoc_GetFullMoniker */ +// REVIEW: should use official OLEGETMONIKER type for final version +typedef enum tagGETMONIKERTYPE { + GETMONIKER_ONLYIFTHERE = 1, + GETMONIKER_FORCEASSIGN = 2, + GETMONIKER_UNASSIGN = 3, + GETMONIKER_TEMPFORUSER = 4 +} GETMONIKERTYPE; + +/* Flags to control direction for drag scrolling */ +typedef enum tagSCROLLDIR { + SCROLLDIR_NULL = 0, + SCROLLDIR_UP = 1, + SCROLLDIR_DOWN = 2, + SCROLLDIR_RIGHT = 3, // currently not used + SCROLLDIR_LEFT = 4 // currently not used +} SCROLLDIR; + + +/************************************************************************* +** class OLEDOC : OUTLINEDOC +** OLEDOC is an extention to the base OUTLINEDOC object (structure) +** that adds common OLE 2.0 functionality used by both the server +** and container versions. This is an abstract class. You do not +** instantiate an instance of OLEDOC directly but instead +** instantiate one of its concrete subclasses: SERVERDOC or +** CONTAINERDOC. There is one instance of an document +** object created per document open in the app. The SDI +** version of the app supports one ServerDoc at a time. The MDI +** version of the app can manage multiple documents at one time. +** The OLEDOC class inherits all fields from the OUTLINEDOC class. +** This inheritance is achieved by including a member variable of +** type OUTLINEDOC as the first field in the OLEDOC +** structure. Thus a pointer to an OLEDOC object can be cast to be +** a pointer to a OUTLINEDOC object. +*************************************************************************/ + +typedef struct tagOLEDOC { + OUTLINEDOC m_OutlineDoc; // ServerDoc inherits from OutlineDoc + ULONG m_cRef; // total ref count for document + ULONG m_dwStrongExtConn; // total strong connection count + // (from IExternalConnection) + // when this count transitions to 0 + // and fLastUnlockCloses==TRUE, then + // IOleObject::Close is called to + // close the document. +#if defined( _DEBUG ) + ULONG m_cCntrLock; // total count of LockContainer locks + // (for debugging purposes only) +#endif + LPSTORAGE m_lpStg; // OleDoc must keep its stg open + // even in-memory server doc should + // keep Stg open for low memory save + LPSTREAM m_lpLLStm; // Hold LineList IStream* open for + // low memory save + LPSTREAM m_lpNTStm; // Hold NameTable IStream* open for + // low memory save + BOOL m_fObjIsClosing; // flag to guard recursive close call + BOOL m_fObjIsDestroying; // flag to guard recursiv destroy call + DWORD m_dwRegROT; // key if doc registered as running + LPMONIKER m_lpFileMoniker; // moniker if file-based/untitled doc + BOOL m_fLinkSourceAvail; // can doc offer CF_LINKSOURCE + LPOLEDOC m_lpSrcDocOfCopy; // src doc if doc created for copy + BOOL m_fUpdateEditMenu; // need to update edit menu?? + +#if defined( USE_DRAGDROP ) + DWORD m_dwTimeEnterScrollArea; // time entering scroll region + DWORD m_dwLastScrollDir; // current dir for drag scroll + DWORD m_dwNextScrollTime; // time for next scroll + BOOL m_fRegDragDrop; // is doc registered as drop target? + BOOL m_fLocalDrag; // is doc source of the drag + BOOL m_fLocalDrop; // was doc target of the drop + BOOL m_fCanDropCopy; // is Drag/Drop copy/move possible? + BOOL m_fCanDropLink; // is Drag/Drop link possible? + BOOL m_fDragLeave; // has drag left + BOOL m_fPendingDrag; // LButtonDown--possible drag pending + POINT m_ptButDown; // LButtonDown coordinates +#endif // USE_DRAGDROP + +#if defined( INPLACE_SVR ) || defined( INPLACE_CNTR ) + BOOL m_fCSHelpMode; // Shift-F1 context help mode +#endif + + struct CDocUnknownImpl { + IUnknownVtbl FAR* lpVtbl; + LPOLEDOC lpOleDoc; + int cRef; // interface specific ref count. + } m_Unknown; + + struct CDocPersistFileImpl { + IPersistFileVtbl FAR* lpVtbl; + LPOLEDOC lpOleDoc; + int cRef; // interface specific ref count. + } m_PersistFile; + + struct CDocOleItemContainerImpl { + IOleItemContainerVtbl FAR* lpVtbl; + LPOLEDOC lpOleDoc; + int cRef; // interface specific ref count. + } m_OleItemContainer; + + struct CDocExternalConnectionImpl { + IExternalConnectionVtbl FAR* lpVtbl; + LPOLEDOC lpOleDoc; + int cRef; // interface specific ref count. + } m_ExternalConnection; + + struct CDocDataObjectImpl { + IDataObjectVtbl FAR* lpVtbl; + LPOLEDOC lpOleDoc; + int cRef; // interface specific ref count. + } m_DataObject; + +#ifdef USE_DRAGDROP + struct CDocDropSourceImpl { + IDropSourceVtbl FAR* lpVtbl; + LPOLEDOC lpOleDoc; + int cRef; // interface specific ref count. + } m_DropSource; + + struct CDocDropTargetImpl { + IDropTargetVtbl FAR* lpVtbl; + LPOLEDOC lpOleDoc; + int cRef; // interface specific ref count. + } m_DropTarget; +#endif // USE_DRAGDROP + +} OLEDOC; + +/* OleDoc methods (functions) */ +BOOL OleDoc_Init(LPOLEDOC lpOleDoc, BOOL fDataTransferDoc); +BOOL OleDoc_InitNewFile(LPOLEDOC lpOleDoc); +void OleDoc_ShowWindow(LPOLEDOC lpOleDoc); +void OleDoc_HideWindow(LPOLEDOC lpOleDoc, BOOL fShutDown); +HRESULT OleDoc_Lock(LPOLEDOC lpOleDoc, BOOL fLock, BOOL fLastUnlockReleases); +ULONG OleDoc_AddRef(LPOLEDOC lpOleDoc); +ULONG OleDoc_Release (LPOLEDOC lpOleDoc); +HRESULT OleDoc_QueryInterface( + LPOLEDOC lpOleDoc, + REFIID riid, + LPVOID FAR* lplpUnk +); +BOOL OleDoc_Close(LPOLEDOC lpOleDoc, DWORD dwSaveOption); +void OleDoc_Destroy(LPOLEDOC lpOleDoc); +void OleDoc_SetUpdateEditMenuFlag(LPOLEDOC lpOleDoc, BOOL fUpdate); +BOOL OleDoc_GetUpdateEditMenuFlag(LPOLEDOC lpOleDoc); +void OleDoc_GetExtent(LPOLEDOC lpOleDoc, LPSIZEL lpsizel); +HGLOBAL OleDoc_GetObjectDescriptorData( + LPOLEDOC lpOleDoc, + LPLINERANGE lplrSel +); +LPMONIKER OleDoc_GetFullMoniker(LPOLEDOC lpOleDoc, DWORD dwAssign); +void OleDoc_GetExtent(LPOLEDOC lpOleDoc, LPSIZEL lpsizel); +void OleDoc_DocRenamedUpdate(LPOLEDOC lpOleDoc, LPMONIKER lpmkDoc); +void OleDoc_CopyCommand(LPOLEDOC lpSrcOleDoc); +void OleDoc_PasteCommand(LPOLEDOC lpOleDoc); +void OleDoc_PasteSpecialCommand(LPOLEDOC lpOleDoc); +LPOUTLINEDOC OleDoc_CreateDataTransferDoc(LPOLEDOC lpSrcOleDoc); +BOOL OleDoc_PasteFromData( + LPOLEDOC lpOleDoc, + LPDATAOBJECT lpSrcDataObj, + BOOL fLocalDataObj, + BOOL fLink +); +BOOL OleDoc_PasteFormatFromData( + LPOLEDOC lpOleDoc, + CLIPFORMAT cfFormat, + LPDATAOBJECT lpSrcDataObj, + BOOL fLocalDataObj, + BOOL fLink, + BOOL fDisplayAsIcon, + HGLOBAL hMetaPict, + LPSIZEL lpSizelInSrc +); +BOOL OleDoc_QueryPasteFromData( + LPOLEDOC lpOleDoc, + LPDATAOBJECT lpSrcDataObj, + BOOL fLink +); + +#if defined( USE_DRAGDROP ) + +BOOL OleDoc_QueryDrag( LPOLEDOC lpOleDoc, int y ); +BOOL OleDoc_QueryDrop ( + LPOLEDOC lpOleDoc, + DWORD grfKeyState, + POINTL pointl, + BOOL fDragScroll, + LPDWORD lpdwEffect +); +DWORD OleDoc_DoDragDrop (LPOLEDOC lpSrcOleDoc); +BOOL OleDoc_DoDragScroll(LPOLEDOC lpOleDoc, POINTL pointl); + +#endif // USE_DRAGDROP + +/* OleDoc::IUnknown methods (functions) */ +STDMETHODIMP OleDoc_Unk_QueryInterface( + LPUNKNOWN lpThis, + REFIID riid, + LPVOID FAR* lplpvObj +); +STDMETHODIMP_(ULONG) OleDoc_Unk_AddRef(LPUNKNOWN lpThis); +STDMETHODIMP_(ULONG) OleDoc_Unk_Release (LPUNKNOWN lpThis); + +/* OleDoc::IPersistFile methods (functions) */ +STDMETHODIMP OleDoc_PFile_QueryInterface( + LPPERSISTFILE lpThis, + REFIID riid, + LPVOID FAR* lplpvObj +); +STDMETHODIMP_(ULONG) OleDoc_PFile_AddRef(LPPERSISTFILE lpThis); +STDMETHODIMP_(ULONG) OleDoc_PFile_Release (LPPERSISTFILE lpThis); +STDMETHODIMP OleDoc_PFile_GetClassID ( + LPPERSISTFILE lpThis, + CLSID FAR* lpclsid +); +STDMETHODIMP OleDoc_PFile_IsDirty(LPPERSISTFILE lpThis); +STDMETHODIMP OleDoc_PFile_Load ( + LPPERSISTFILE lpThis, + LPCOLESTR lpszFileName, + DWORD grfMode +); +STDMETHODIMP OleDoc_PFile_Save ( + LPPERSISTFILE lpThis, + LPCOLESTR lpszFileName, + BOOL fRemember +); +STDMETHODIMP OleDoc_PFile_SaveCompleted ( + LPPERSISTFILE lpThis, + LPCOLESTR lpszFileName +); +STDMETHODIMP OleDoc_PFile_GetCurFile ( + LPPERSISTFILE lpThis, + LPOLESTR FAR* lplpszFileName +); + +/* OleDoc::IOleItemContainer methods (functions) */ +STDMETHODIMP OleDoc_ItemCont_QueryInterface( + LPOLEITEMCONTAINER lpThis, + REFIID riid, + LPVOID FAR* lplpvObj +); +STDMETHODIMP_(ULONG) OleDoc_ItemCont_AddRef(LPOLEITEMCONTAINER lpThis); +STDMETHODIMP_(ULONG) OleDoc_ItemCont_Release(LPOLEITEMCONTAINER lpThis); +STDMETHODIMP OleDoc_ItemCont_ParseDisplayName( + LPOLEITEMCONTAINER lpThis, + LPBC lpbc, + LPOLESTR lpszDisplayName, + ULONG FAR* lpchEaten, + LPMONIKER FAR* lplpmkOut +); + +STDMETHODIMP OleDoc_ItemCont_EnumObjects( + LPOLEITEMCONTAINER lpThis, + DWORD grfFlags, + LPENUMUNKNOWN FAR* lplpenumUnknown +); +STDMETHODIMP OleDoc_ItemCont_LockContainer( + LPOLEITEMCONTAINER lpThis, + BOOL fLock +); +STDMETHODIMP OleDoc_ItemCont_GetObject( + LPOLEITEMCONTAINER lpThis, + LPOLESTR lpszItem, + DWORD dwSpeedNeeded, + LPBINDCTX lpbc, + REFIID riid, + LPVOID FAR* lplpvObject +); +STDMETHODIMP OleDoc_ItemCont_GetObjectStorage( + LPOLEITEMCONTAINER lpThis, + LPOLESTR lpszItem, + LPBINDCTX lpbc, + REFIID riid, + LPVOID FAR* lplpvStorage +); +STDMETHODIMP OleDoc_ItemCont_IsRunning( + LPOLEITEMCONTAINER lpThis, + LPOLESTR lpszItem +); + +/* OleDoc::IPersistFile methods (functions) */ +STDMETHODIMP OleDoc_ExtConn_QueryInterface( + LPEXTERNALCONNECTION lpThis, + REFIID riid, + LPVOID FAR* lplpvObj +); +STDMETHODIMP_(ULONG) OleDoc_ExtConn_AddRef(LPEXTERNALCONNECTION lpThis); +STDMETHODIMP_(ULONG) OleDoc_ExtConn_Release (LPEXTERNALCONNECTION lpThis); +STDMETHODIMP_(DWORD) OleDoc_ExtConn_AddConnection( + LPEXTERNALCONNECTION lpThis, + DWORD extconn, + DWORD reserved +); +STDMETHODIMP_(DWORD) OleDoc_ExtConn_ReleaseConnection( + LPEXTERNALCONNECTION lpThis, + DWORD extconn, + DWORD reserved, + BOOL fLastReleaseCloses +); + +/* OleDoc::IDataObject methods (functions) */ +STDMETHODIMP OleDoc_DataObj_QueryInterface ( + LPDATAOBJECT lpThis, + REFIID riid, + LPVOID FAR* lplpvObj +); +STDMETHODIMP_(ULONG) OleDoc_DataObj_AddRef(LPDATAOBJECT lpThis); +STDMETHODIMP_(ULONG) OleDoc_DataObj_Release (LPDATAOBJECT lpThis); +STDMETHODIMP OleDoc_DataObj_GetData ( + LPDATAOBJECT lpThis, + LPFORMATETC lpFormatetc, + LPSTGMEDIUM lpMedium +); +STDMETHODIMP OleDoc_DataObj_GetDataHere ( + LPDATAOBJECT lpThis, + LPFORMATETC lpFormatetc, + LPSTGMEDIUM lpMedium +); +STDMETHODIMP OleDoc_DataObj_QueryGetData ( + LPDATAOBJECT lpThis, + LPFORMATETC lpFormatetc +); +STDMETHODIMP OleDoc_DataObj_GetCanonicalFormatEtc( + LPDATAOBJECT lpThis, + LPFORMATETC lpformatetc, + LPFORMATETC lpformatetcOut +); +STDMETHODIMP OleDoc_DataObj_SetData ( + LPDATAOBJECT lpThis, + LPFORMATETC lpFormatetc, + LPSTGMEDIUM lpMedium, + BOOL fRelease +); +STDMETHODIMP OleDoc_DataObj_EnumFormatEtc( + LPDATAOBJECT lpThis, + DWORD dwDirection, + LPENUMFORMATETC FAR* lplpenumFormatEtc +); +STDMETHODIMP OleDoc_DataObj_DAdvise( + LPDATAOBJECT lpThis, + FORMATETC FAR* lpFormatetc, + DWORD advf, + LPADVISESINK lpAdvSink, + DWORD FAR* lpdwConnection +); +STDMETHODIMP OleDoc_DataObj_DUnadvise(LPDATAOBJECT lpThis,DWORD dwConnection); +STDMETHODIMP OleDoc_DataObj_EnumDAdvise( + LPDATAOBJECT lpThis, + LPENUMSTATDATA FAR* lplpenumAdvise +); + + +#ifdef USE_DRAGDROP + +/* OleDoc::IDropSource methods (functions) */ +STDMETHODIMP OleDoc_DropSource_QueryInterface( + LPDROPSOURCE lpThis, + REFIID riid, + LPVOID FAR* lplpvObj +); +STDMETHODIMP_(ULONG) OleDoc_DropSource_AddRef( LPDROPSOURCE lpThis ); +STDMETHODIMP_(ULONG) OleDoc_DropSource_Release ( LPDROPSOURCE lpThis); +STDMETHODIMP OleDoc_DropSource_QueryContinueDrag ( + LPDROPSOURCE lpThis, + BOOL fEscapePressed, + DWORD grfKeyState +); +STDMETHODIMP OleDoc_DropSource_GiveFeedback ( + LPDROPSOURCE lpThis, + DWORD dwEffect +); + +/* OleDoc::IDropTarget methods (functions) */ +STDMETHODIMP OleDoc_DropTarget_QueryInterface( + LPDROPTARGET lpThis, + REFIID riid, + LPVOID FAR* lplpvObj +); +STDMETHODIMP_(ULONG) OleDoc_DropTarget_AddRef(LPDROPTARGET lpThis); +STDMETHODIMP_(ULONG) OleDoc_DropTarget_Release ( LPDROPTARGET lpThis); +STDMETHODIMP OleDoc_DropTarget_DragEnter ( + LPDROPTARGET lpThis, + LPDATAOBJECT lpDataObj, + DWORD grfKeyState, + POINTL pointl, + LPDWORD lpdwEffect +); +STDMETHODIMP OleDoc_DropTarget_DragOver ( + LPDROPTARGET lpThis, + DWORD grfKeyState, + POINTL pointl, + LPDWORD lpdwEffect +); +STDMETHODIMP OleDoc_DropTarget_DragLeave ( LPDROPTARGET lpThis); +STDMETHODIMP OleDoc_DropTarget_Drop ( + LPDROPTARGET lpThis, + LPDATAOBJECT lpDataObj, + DWORD grfKeyState, + POINTL pointl, + LPDWORD lpdwEffect +); + +#endif // USE_DRAGDROP + + +/************************************************************************* +** class APPCLASSFACTORY +** APPCLASSFACTORY implements the IClassFactory interface. it +** instantiates document instances of the correct type depending on +** how the application is compiled (either ServerDoc or ContainerDoc +** instances). by implementing this +** interface in a seperate interface from the App object itself, it +** is easier to manage when the IClassFactory should be +** registered/revoked. when the OleApp object is first initialized +** in OleApp_InitInstance an instance of APPCLASSFACTORY is created +** and registered (CoRegisterClassObject called). when the App +** object gets destroyed (in OleApp_Destroy) this APPCLASSFACTORY is +** revoked (CoRevokeClassObject called) and released. the simple +** fact that the IClassFactory is registered does not on its own keep +** the application alive. +*************************************************************************/ + +typedef struct tagAPPCLASSFACTORY { + IClassFactoryVtbl FAR* m_lpVtbl; + UINT m_cRef; +#if defined( _DEBUG ) + LONG m_cSvrLock; // total count of LockServer locks + // (for debugging purposes only) +#endif + } APPCLASSFACTORY, FAR* LPAPPCLASSFACTORY; + +/* PUBLIC FUNCTIONS */ +LPCLASSFACTORY WINAPI AppClassFactory_Create(void); + +/* interface IClassFactory implementation */ +STDMETHODIMP AppClassFactory_QueryInterface( + LPCLASSFACTORY lpThis, REFIID riid, LPVOID FAR* ppvObj); +STDMETHODIMP_(ULONG) AppClassFactory_AddRef(LPCLASSFACTORY lpThis); +STDMETHODIMP_(ULONG) AppClassFactory_Release(LPCLASSFACTORY lpThis); +STDMETHODIMP AppClassFactory_CreateInstance ( + LPCLASSFACTORY lpThis, + LPUNKNOWN lpUnkOuter, + REFIID riid, + LPVOID FAR* lplpvObj +); +STDMETHODIMP AppClassFactory_LockServer ( + LPCLASSFACTORY lpThis, + BOOL fLock +); + + +/************************************************************************* +** class OLEAPP : OUTLINEAPP +** OLEAPP is an extention to the base OUTLINEAPP object (structure) +** that adds common OLE 2.0 functionality used by both the server +** and container versions. This is an abstract class. You do not +** instantiate an instance of OLEAPP directly but instead +** instantiate one of its concrete subclasses: SERVERAPP or +** CONTAINERAPP. There is one instance of an document application +** object created per running application instance. This +** object holds many fields that could otherwise be organized as +** global variables. The OLEAPP class inherits all fields +** from the OUTLINEAPP class. This inheritance is achieved by including a +** member variable of type OUTLINEAPP as the first field in the OLEAPP +** structure. Thus a pointer to a OLEAPP object can be cast to be +** a pointer to a OUTLINEAPP object. +*************************************************************************/ + +typedef struct tagOLEAPP { + OUTLINEAPP m_OutlineApp; // inherits all fields of OutlineApp + ULONG m_cRef; // total ref count for app + ULONG m_cDoc; // total count of open documents + BOOL m_fUserCtrl; // does user control life-time of app? + DWORD m_dwRegClassFac; // value returned by CoRegisterClassObject + LPCLASSFACTORY m_lpClassFactory;// ptr to allocated ClassFactory instance +#if defined( USE_MSGFILTER ) + LPMESSAGEFILTER m_lpMsgFilter; // ptr to allocated MsgFilter instance + MSGPENDINGPROC m_lpfnMsgPending;// ptr to msg pending callback function +#endif // USE_MSGFILTER + BOOL m_fOleInitialized; // was OleInitialize called + UINT m_cModalDlgActive; // count of modal dialogs up; 0 = no dlg. + UINT m_cfEmbedSource; // OLE 2.0 clipboard format + UINT m_cfEmbeddedObject; // OLE 2.0 clipboard format + UINT m_cfLinkSource; // OLE 2.0 clipboard format + UINT m_cfObjectDescriptor; // OLE 2.0 clipboard format + UINT m_cfLinkSrcDescriptor; // OLE 2.0 clipboard format + UINT m_cfFileName; // std Windows clipboard format + FORMATETC m_arrDocGetFmts[MAXNOFMTS]; // fmts offered by copy & GetData + UINT m_nDocGetFmts; // no of fmtetc's for GetData + + OLEUIPASTEENTRY m_arrPasteEntries[MAXNOFMTS]; // input for PasteSpl. + int m_nPasteEntries; // input for PasteSpl. + UINT m_arrLinkTypes[MAXNOLINKTYPES]; // input for PasteSpl. + int m_nLinkTypes; // input for PasteSpl. + +#if defined( USE_DRAGDROP ) + int m_nDragDelay; // time delay (in msec) before drag should start + int m_nDragMinDist; // min. distance (radius) before drag should start + int m_nScrollDelay; // time delay (in msec) before scroll should start + int m_nScrollInset; // Border inset distance to start drag scroll + int m_nScrollInterval; // scroll interval time (in msec) + +#if defined( IF_SPECIAL_DD_CURSORS_NEEDED ) + // This would be used if the app wanted to have custom drag/drop cursors + HCURSOR m_hcursorDragNone; + HCURSOR m_hcursorDragCopy; + HCURSOR m_hcursorDragLink; +#endif // IF_SPECIAL_DD_CURSORS_NEEDED +#endif // USE_DRAGDROP + + +#if defined( OLE_CNTR ) + HPALETTE m_hStdPal; // standard color palette for OLE + // it is a good idea for containers + // to use this standard palette + // even if they do not use colors + // themselves. this will allow + // embedded object to get a good + // distribution of colors when they + // are being drawn by the container. + // +#endif + + struct CAppUnknownImpl { + IUnknownVtbl FAR* lpVtbl; + LPOLEAPP lpOleApp; + int cRef; // interface specific ref count. + } m_Unknown; + +} OLEAPP; + +/* ServerApp methods (functions) */ +BOOL OleApp_InitInstance(LPOLEAPP lpOleApp, HINSTANCE hInst, int nCmdShow); +void OleApp_TerminateApplication(LPOLEAPP lpOleApp); +BOOL OleApp_ParseCmdLine(LPOLEAPP lpOleApp, LPSTR lpszCmdLine, int nCmdShow); +void OleApp_Destroy(LPOLEAPP lpOleApp); +BOOL OleApp_CloseAllDocsAndExitCommand( + LPOLEAPP lpOleApp, + BOOL fForceEndSession +); +void OleApp_ShowWindow(LPOLEAPP lpOleApp, BOOL fGiveUserCtrl); +void OleApp_HideWindow(LPOLEAPP lpOleApp); +void OleApp_HideIfNoReasonToStayVisible(LPOLEAPP lpOleApp); +void OleApp_DocLockApp(LPOLEAPP lpOleApp); +void OleApp_DocUnlockApp(LPOLEAPP lpOleApp, LPOUTLINEDOC lpOutlineDoc); +HRESULT OleApp_Lock(LPOLEAPP lpOleApp, BOOL fLock, BOOL fLastUnlockReleases); +ULONG OleApp_AddRef(LPOLEAPP lpOleApp); +ULONG OleApp_Release (LPOLEAPP lpOleApp); +HRESULT OleApp_QueryInterface ( + LPOLEAPP lpOleApp, + REFIID riid, + LPVOID FAR* lplpUnk +); +void OleApp_RejectInComingCalls(LPOLEAPP lpOleApp, BOOL fReject); +void OleApp_DisableBusyDialogs( + LPOLEAPP lpOleApp, + BOOL FAR* lpfPrevBusyEnable, + BOOL FAR* lpfPrevNREnable +); +void OleApp_EnableBusyDialogs( + LPOLEAPP lpOleApp, + BOOL fPrevBusyEnable, + BOOL fPrevNREnable +); +void OleApp_PreModalDialog(LPOLEAPP lpOleApp, LPOLEDOC lpActiveOleDoc); +void OleApp_PostModalDialog(LPOLEAPP lpOleApp, LPOLEDOC lpActiveOleDoc); +BOOL OleApp_InitVtbls (LPOLEAPP lpOleApp); +void OleApp_InitMenu( + LPOLEAPP lpOleApp, + LPOLEDOC lpOleDoc, + HMENU hMenu +); +void OleApp_UpdateEditMenu( + LPOLEAPP lpOleApp, + LPOUTLINEDOC lpOutlineDoc, + HMENU hMenuEdit +); +BOOL OleApp_RegisterClassFactory(LPOLEAPP lpOleApp); +void OleApp_RevokeClassFactory(LPOLEAPP lpOleApp); + +#if defined( USE_MSGFILTER ) +BOOL OleApp_RegisterMessageFilter(LPOLEAPP lpOleApp); +void OleApp_RevokeMessageFilter(LPOLEAPP lpOleApp); +BOOL FAR PASCAL EXPORT MessagePendingProc(MSG FAR *lpMsg); +#endif // USE_MSGFILTER + +void OleApp_FlushClipboard(LPOLEAPP lpOleApp); +void OleApp_NewCommand(LPOLEAPP lpOleApp); +void OleApp_OpenCommand(LPOLEAPP lpOleApp); + +#if defined( OLE_CNTR ) +LRESULT OleApp_QueryNewPalette(LPOLEAPP lpOleApp); +#endif // OLE_CNTR + +LRESULT wSelectPalette(HWND hWnd, HPALETTE hPal, BOOL fBackground); + + +/* OleApp::IUnknown methods (functions) */ +STDMETHODIMP OleApp_Unk_QueryInterface( + LPUNKNOWN lpThis, + REFIID riid, + LPVOID FAR* lplpvObj +); +STDMETHODIMP_(ULONG) OleApp_Unk_AddRef(LPUNKNOWN lpThis); +STDMETHODIMP_(ULONG) OleApp_Unk_Release (LPUNKNOWN lpThis); + + +/* Function prototypes in debug.c */ +void InstallMessageFilterCommand(void); +void RejectIncomingCommand(void); + + +#if defined( OLE_SERVER ) +#include "svroutl.h" +#endif +#if defined( OLE_CNTR ) +#include "cntroutl.h" +#endif + +#endif // _OLEOUTL_H_ + diff --git a/private/oleutest/letest/outline/outlapp.c b/private/oleutest/letest/outline/outlapp.c new file mode 100644 index 000000000..caa5da006 --- /dev/null +++ b/private/oleutest/letest/outline/outlapp.c @@ -0,0 +1,1514 @@ +/************************************************************************* +** +** OLE 2 Sample Code +** +** outlapp.c +** +** This file contains OutlineApp functions. +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + +#include "outline.h" + +#if defined( USE_STATUSBAR ) +#include "status.h" +#endif + +#if !defined( WIN32 ) +#include +#endif + +OLEDBGDATA + +extern LPOUTLINEAPP g_lpApp; +extern RECT g_rectNull; + + +// REVIEW: should use string resource for messages +char ErrMsgClass[] = "Can't register window classes!"; +char ErrMsgFrame[] = "Can't create Frame Window!"; +char ErrMsgPrinting[] = "Can't access printer!"; + + +/* OutlineApp_InitApplication +** -------------------------- +** Sets up the class data structures and does a one-time +** initialization of the app by registering the window classes. +** Returns TRUE if initialization is successful +** FALSE otherwise +*/ + +BOOL OutlineApp_InitApplication(LPOUTLINEAPP lpOutlineApp, HINSTANCE hInst) +{ + WNDCLASS wndclass; + + // REVIEW: should load msg strings from string resource + + /* Register the app frame class */ + wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_BYTEALIGNWINDOW; + wndclass.lpfnWndProc = AppWndProc; + /* Extra storage for Class and Window objects */ + wndclass.cbClsExtra = 0; + wndclass.cbWndExtra = sizeof(LPOUTLINEAPP); /* to store lpApp */ + wndclass.hInstance = hInst; + wndclass.hIcon = LoadIcon(hInst, APPICON); + wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); + /* Create brush for erasing background */ + wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); + wndclass.lpszMenuName = APPMENU; /* Menu Name is App Name */ + wndclass.lpszClassName = APPWNDCLASS; /* Class Name is App Name */ + + if(! RegisterClass(&wndclass)) { + OutlineApp_ErrorMessage(lpOutlineApp, ErrMsgFrame); + return FALSE; + } + + /* Register the document window class */ + wndclass.style = CS_BYTEALIGNWINDOW; + wndclass.lpfnWndProc = DocWndProc; + wndclass.hIcon = NULL; + wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); + wndclass.lpszMenuName = NULL; + wndclass.lpszClassName = DOCWNDCLASS; + wndclass.cbWndExtra = sizeof(LPOUTLINEDOC); /* to store lpDoc */ + if(! RegisterClass(&wndclass)) { + OutlineApp_ErrorMessage(lpOutlineApp, ErrMsgClass); + return FALSE; + } + +#if defined( USE_STATUSBAR ) + if (! RegisterStatusClass(hInst)) + return FALSE; +#endif + +#if defined( USE_FRAMETOOLS ) + if (! FrameToolsRegisterClass(hInst)) { + return FALSE; + } +#endif + +#if defined( INPLACE_SVR ) + // We should only register the hatch window class + // in the UI Library once per application. + RegisterHatchWindowClass(hInst); + +#endif + + return TRUE; +} + + +/* OutlineApp_InitInstance + * ----------------------- + * + * Performs a per-instance initialization of app. + * This method creates the frame window. + * + * RETURNS : TRUE - If initialization was successful. + * FALSE - otherwise. + */ + +BOOL OutlineApp_InitInstance(LPOUTLINEAPP lpOutlineApp, HINSTANCE hInst, int nCmdShow) +{ + lpOutlineApp->m_hInst = hInst; + + /* create application's Frame window */ + lpOutlineApp->m_hWndApp = CreateWindow( + APPWNDCLASS, /* Window class name */ + APPNAME, /* initial Window title */ + WS_OVERLAPPEDWINDOW| + WS_CLIPCHILDREN, + CW_USEDEFAULT, 0, /* Use default X, Y */ + CW_USEDEFAULT, 0, /* Use default X, Y */ + HWND_DESKTOP, /* Parent window's handle */ + NULL, /* Default to Class Menu */ + hInst, /* Instance of window */ + NULL /* Create struct for WM_CREATE */ + ); + + if(! lpOutlineApp->m_hWndApp) { + // REVIEW: should load string from string resource + OutlineApp_ErrorMessage(lpOutlineApp, ErrMsgFrame); + return FALSE; + } + + SetWindowLong(lpOutlineApp->m_hWndApp, 0, (LONG) lpOutlineApp); + + /* defer creating the user's SDI document until we parse the cmd line. */ + lpOutlineApp->m_lpDoc = NULL; + + /* Initialize clipboard. + */ + lpOutlineApp->m_lpClipboardDoc = NULL; + if(!(lpOutlineApp->m_cfOutline = RegisterClipboardFormat(OUTLINEDOCFORMAT))) { + // REVIEW: should load string from string resource + OutlineApp_ErrorMessage(lpOutlineApp, "Can't register clipboard format!"); + return FALSE; + } + + /* init the standard font to be used for drawing/printing text + * request a Roman style True Type font of the desired size + */ + lpOutlineApp->m_hStdFont = CreateFont( + -DEFFONTSIZE, + 0,0,0,0,0,0,0,0, + OUT_TT_PRECIS, // use TrueType + CLIP_DEFAULT_PRECIS, + DEFAULT_QUALITY, + VARIABLE_PITCH | FF_ROMAN, + DEFFONTFACE + ); + + // Load special cursor for selection of Lines in ListBox. + lpOutlineApp->m_hcursorSelCur = LoadCursor ( hInst, "SelCur" ); + + /* init the Print Dialog structure */ + _fmemset((LPVOID)&lpOutlineApp->m_PrintDlg,0,sizeof(PRINTDLG)); + lpOutlineApp->m_PrintDlg.lStructSize = sizeof(PRINTDLG); + lpOutlineApp->m_PrintDlg.hDevMode = NULL; + lpOutlineApp->m_PrintDlg.hDevNames = NULL; + lpOutlineApp->m_PrintDlg.Flags = PD_RETURNDC | PD_NOSELECTION | PD_NOPAGENUMS | + PD_HIDEPRINTTOFILE; + lpOutlineApp->m_PrintDlg.nCopies = 1; + lpOutlineApp->m_PrintDlg.hwndOwner = lpOutlineApp->m_hWndApp; + +#if defined( USE_STATUSBAR ) + lpOutlineApp->m_hWndStatusBar = CreateStatusWindow(lpOutlineApp->m_hWndApp, hInst); + if (! lpOutlineApp->m_hWndStatusBar) + return FALSE; + + lpOutlineApp->m_hMenuApp = GetMenu(lpOutlineApp->m_hWndApp); + + /* setup status messages for the application menus */ + { + HMENU hMenuFile = GetSubMenu(lpOutlineApp->m_hMenuApp, 0); + HMENU hMenuEdit = GetSubMenu(lpOutlineApp->m_hMenuApp, 1); + HMENU hMenuOutline = GetSubMenu(lpOutlineApp->m_hMenuApp, 2); + HMENU hMenuLine = GetSubMenu(lpOutlineApp->m_hMenuApp, 3); + HMENU hMenuName = GetSubMenu(lpOutlineApp->m_hMenuApp, 4); + HMENU hMenuOptions = GetSubMenu(lpOutlineApp->m_hMenuApp, 5); + HMENU hMenuDebug = GetSubMenu(lpOutlineApp->m_hMenuApp, 6); + HMENU hMenuHelp = GetSubMenu(lpOutlineApp->m_hMenuApp, 7); + HMENU hMenuSys = GetSystemMenu(lpOutlineApp->m_hWndApp, FALSE); + + AssignPopupMessage(hMenuFile, "Create, open, save, print outlines or quit application"); + AssignPopupMessage(hMenuEdit, "Cut, copy, paste or clear selection"); + AssignPopupMessage(hMenuOutline, "Set zoom and margins"); + AssignPopupMessage(hMenuLine, "Create, edit, and indent lines"); + AssignPopupMessage(hMenuName, "Create, edit, delete and goto names"); + AssignPopupMessage(hMenuOptions, "Modify tools, row/col headings, display options"); + AssignPopupMessage(hMenuDebug, "Set debug trace level and other debug options"); + AssignPopupMessage(hMenuHelp, "Get help on using the application"); + AssignPopupMessage(hMenuSys,"Move, size or close application window"); + } +#endif + +#if defined ( USE_FRAMETOOLS ) || defined ( INPLACE_CNTR ) + lpOutlineApp->m_FrameToolWidths = g_rectNull; +#endif // USE_FRAMETOOLS || INPLACE_CNTR + +#if defined( USE_FRAMETOOLS ) + if (! FrameTools_Init(&lpOutlineApp->m_frametools, + lpOutlineApp->m_hWndApp, lpOutlineApp->m_hInst)) + return FALSE; +#endif + +#if defined( OLE_VERSION ) + + /* OLE2NOTE: perform initialization required for OLE */ + if (! OleApp_InitInstance((LPOLEAPP)lpOutlineApp, hInst, nCmdShow)) + return FALSE; +#else + /* OLE2NOTE: Although no OLE call is made in the base outline, + ** OLE memory allocator is used and thus CoInitialize() needs to + ** be called. + */ + { + HRESULT hrErr; + + hrErr = CoInitialize(NULL); + if (hrErr != NOERROR) { + OutlineApp_ErrorMessage(lpOutlineApp, + "CoInitialize initialization failed!"); + return FALSE; + } + } +#endif + + return TRUE; +} + + +/* OutlineApp_ParseCmdLine + * ----------------------- + * + * Parse the command line for any execution flags/arguments. + */ +BOOL OutlineApp_ParseCmdLine(LPOUTLINEAPP lpOutlineApp, LPSTR lpszCmdLine, int nCmdShow) +{ + +#if defined( OLE_VERSION ) + // Call OLE version of this function instead + return OleApp_ParseCmdLine((LPOLEAPP)lpOutlineApp,lpszCmdLine,nCmdShow); + +#else + + BOOL fStatus = TRUE; + char szFileName[256]; /* buffer for filename in command line */ + + szFileName[0] = '\0'; + ParseCmdLine(lpszCmdLine, NULL, (LPSTR)szFileName); + + if(*szFileName) { + // allocate a new document + lpOutlineApp->m_lpDoc = OutlineApp_CreateDoc(lpOutlineApp, FALSE); + if (! lpOutlineApp->m_lpDoc) goto error; + + // open the specified file + if (! OutlineDoc_LoadFromFile(lpOutlineApp->m_lpDoc, szFileName)) + goto error; + } else { + // create a new document + lpOutlineApp->m_lpDoc = OutlineApp_CreateDoc(lpOutlineApp, FALSE); + if (! lpOutlineApp->m_lpDoc) goto error; + + // set the doc to an (Untitled) doc. + if (! OutlineDoc_InitNewFile(lpOutlineApp->m_lpDoc)) + goto error; + } + + // position and size the new doc window + OutlineApp_ResizeWindows(lpOutlineApp); + OutlineDoc_ShowWindow(lpOutlineApp->m_lpDoc); + + // show main app window + ShowWindow(lpOutlineApp->m_hWndApp, nCmdShow); + UpdateWindow(lpOutlineApp->m_hWndApp); + + return TRUE; + +error: + // REVIEW: should load string from string resource + OutlineApp_ErrorMessage(lpOutlineApp, "Could not create new document"); + + if (lpOutlineApp->m_lpDoc) { + OutlineDoc_Destroy(lpOutlineApp->m_lpDoc); + lpOutlineApp->m_lpDoc = NULL; + } + + return FALSE; + +#endif +} + + +/* OutlineApp_InitMenu + * ------------------- + * + * Enable or Disable menu items depending on the state of + * the appliation + */ +void OutlineApp_InitMenu(LPOUTLINEAPP lpOutlineApp, LPOUTLINEDOC lpOutlineDoc, HMENU hMenu) +{ + WORD status; + static UINT uCurrentZoom = (UINT)-1; + static UINT uCurrentMargin = (UINT)-1; + static UINT uBBState = (UINT)-1; + static UINT uFBState = (UINT)-1; + + if (!lpOutlineApp || !lpOutlineDoc || !hMenu) + return; + + EnableMenuItem(lpOutlineApp->m_hMenuApp, IDM_E_UNDO, MF_GRAYED); + + status = (WORD)(OutlineDoc_GetLineCount(lpOutlineDoc) ? MF_ENABLED : MF_GRAYED); + + EnableMenuItem(lpOutlineApp->m_hMenuApp, IDM_E_CUT ,status); + EnableMenuItem(lpOutlineApp->m_hMenuApp, IDM_E_COPY ,status); + EnableMenuItem(lpOutlineApp->m_hMenuApp, IDM_E_CLEAR ,status); + EnableMenuItem(lpOutlineApp->m_hMenuApp, IDM_E_SELECTALL ,status); + + EnableMenuItem(lpOutlineApp->m_hMenuApp, IDM_L_EDITLINE ,status); + EnableMenuItem(lpOutlineApp->m_hMenuApp, IDM_L_INDENTLINE ,status); + EnableMenuItem(lpOutlineApp->m_hMenuApp, IDM_L_UNINDENTLINE ,status); + EnableMenuItem(lpOutlineApp->m_hMenuApp, IDM_L_SETLINEHEIGHT ,status); + + EnableMenuItem(lpOutlineApp->m_hMenuApp, IDM_N_DEFINENAME ,status); + + status = (WORD)(OutlineDoc_GetNameCount(lpOutlineDoc) ? MF_ENABLED : MF_GRAYED); + + EnableMenuItem(lpOutlineApp->m_hMenuApp, IDM_N_GOTONAME, status); + + if (uCurrentZoom != (UINT)-1) + CheckMenuItem(lpOutlineApp->m_hMenuApp, uCurrentZoom, MF_UNCHECKED); + uCurrentZoom = OutlineDoc_GetCurrentZoomMenuCheck(lpOutlineDoc); + CheckMenuItem(lpOutlineApp->m_hMenuApp, uCurrentZoom, MF_CHECKED); + + if (uCurrentMargin != (UINT)-1) + CheckMenuItem(lpOutlineApp->m_hMenuApp, uCurrentMargin, MF_UNCHECKED); + uCurrentMargin = OutlineDoc_GetCurrentMarginMenuCheck(lpOutlineDoc); + CheckMenuItem(lpOutlineApp->m_hMenuApp, uCurrentMargin, MF_CHECKED); + +#if defined( USE_FRAMETOOLS ) + if (uBBState != (UINT)-1) + CheckMenuItem(lpOutlineApp->m_hMenuApp, uBBState, MF_UNCHECKED); + if (lpOutlineDoc->m_lpFrameTools) { + switch (FrameTools_BB_GetState(lpOutlineDoc->m_lpFrameTools)) { + case BARSTATE_TOP: + uBBState = IDM_O_BB_TOP; + break; + case BARSTATE_BOTTOM: + uBBState = IDM_O_BB_BOTTOM; + break; + case BARSTATE_POPUP: + uBBState = IDM_O_BB_POPUP; + break; + case BARSTATE_HIDE: + uBBState = IDM_O_BB_HIDE; + break; + } + CheckMenuItem(lpOutlineApp->m_hMenuApp, uBBState, MF_CHECKED); + } + + if (uFBState != (UINT)-1) + CheckMenuItem(lpOutlineApp->m_hMenuApp, uFBState, MF_UNCHECKED); + if (lpOutlineDoc->m_lpFrameTools) { + switch (FrameTools_FB_GetState(lpOutlineDoc->m_lpFrameTools)) { + case BARSTATE_TOP: + uFBState = IDM_O_FB_TOP; + break; + case BARSTATE_BOTTOM: + uFBState = IDM_O_FB_BOTTOM; + break; + case BARSTATE_POPUP: + uFBState = IDM_O_FB_POPUP; + break; + } + CheckMenuItem(lpOutlineApp->m_hMenuApp, uFBState, MF_CHECKED); + } +#endif // USE_FRAMETOOLS + +#if defined( OLE_VERSION ) + /* OLE2NOTE: perform OLE specific menu initialization. + ** the OLE versions use the OleGetClipboard mechanism for + ** clipboard handling. thus, they determine if the Paste and + ** PasteSpecial commands should be enabled in an OLE specific + ** manner. + ** (Container only) build the OLE object verb menu if necessary. + */ + OleApp_InitMenu( + (LPOLEAPP)lpOutlineApp, + (LPOLEDOC)lpOutlineDoc, + lpOutlineApp->m_hMenuApp + ); + + /* OLE2NOTE: To avoid the overhead of initializing the Edit menu, + ** we do it only when it is popped up. Thus we just set a flag + ** in the OleDoc saying that the Edit menu needs to be updated + ** but we don't do it immediately + */ + OleDoc_SetUpdateEditMenuFlag((LPOLEDOC)lpOutlineDoc, TRUE); + +#else + // Base Outline version uses standard Windows clipboard handling + if(IsClipboardFormatAvailable(lpOutlineApp->m_cfOutline) || + IsClipboardFormatAvailable(CF_TEXT)) + status = MF_ENABLED; + else + status = MF_GRAYED; + EnableMenuItem(lpOutlineApp->m_hMenuApp, IDM_E_PASTE, status); + +#endif + +#if defined( USE_FRAMETOOLS ) + if (! OutlineDoc_IsEditFocusInFormulaBar(lpOutlineDoc)) { + EnableMenuItem(lpOutlineApp->m_hMenuApp, IDM_L_ADDLINE, MF_GRAYED); + EnableMenuItem(lpOutlineApp->m_hMenuApp, IDM_L_EDITLINE, MF_GRAYED); + } + else + EnableMenuItem(lpOutlineApp->m_hMenuApp, IDM_L_ADDLINE, MF_ENABLED); + +#endif // USE_FRAMETOOLS + +} + + +/* OutlineApp_GetWindow + * -------------------- + * + * Get the window handle of the application frame. + */ +HWND OutlineApp_GetWindow(LPOUTLINEAPP lpOutlineApp) +{ + if (!lpOutlineApp) + return NULL; + + return lpOutlineApp->m_hWndApp; +} + + +/* OutlineApp_GetFrameWindow +** ------------------------- +** Gets the current frame window to use as a parent to any dialogs +** this app uses. +** +** OLE2NOTE: normally this is simply the main hWnd of the app. but, +** if the app is currently supporting an in-place server document, +** then the frame window of the top in-place container must be used. +*/ +HWND OutlineApp_GetFrameWindow(LPOUTLINEAPP lpOutlineApp) +{ + HWND hWndApp = OutlineApp_GetWindow(lpOutlineApp); + +#if defined( INPLACE_SVR ) + LPSERVERDOC lpServerDoc = + (LPSERVERDOC)OutlineApp_GetActiveDoc(lpOutlineApp); + if (lpServerDoc && lpServerDoc->m_fUIActive) + return lpServerDoc->m_lpIPData->frameInfo.hwndFrame; +#endif + + return hWndApp; +} + + +/* OutlineApp_GetInstance + * ---------------------- + * + * Get the process instance of the application. + */ +HINSTANCE OutlineApp_GetInstance(LPOUTLINEAPP lpOutlineApp) +{ + if (!lpOutlineApp) + return NULL; + + return lpOutlineApp->m_hInst; +} + + +/* OutlineApp_CreateDoc + * -------------------- + * + * Allocate a new document of the appropriate type. + * OutlineApp --> creates OutlineDoc type documents + * + * Returns lpOutlineDoc for successful, NULL if error. + */ +LPOUTLINEDOC OutlineApp_CreateDoc( + LPOUTLINEAPP lpOutlineApp, + BOOL fDataTransferDoc +) +{ + LPOUTLINEDOC lpOutlineDoc; + + OLEDBG_BEGIN3("OutlineApp_CreateDoc\r\n") + +#if defined( OLE_SERVER ) + lpOutlineDoc = (LPOUTLINEDOC)New((DWORD)sizeof(SERVERDOC)); + _fmemset(lpOutlineDoc, 0, sizeof(SERVERDOC)); +#endif +#if defined( OLE_CNTR ) + lpOutlineDoc = (LPOUTLINEDOC)New((DWORD)sizeof(CONTAINERDOC)); + _fmemset(lpOutlineDoc, 0, sizeof(CONTAINERDOC)); +#endif +#if !defined( OLE_VERSION ) + lpOutlineDoc = (LPOUTLINEDOC)New((DWORD)sizeof(OUTLINEDOC)); + _fmemset(lpOutlineDoc, 0, sizeof(OUTLINEDOC)); +#endif + + OleDbgAssertSz(lpOutlineDoc != NULL, "Error allocating OutlineDoc"); + if (lpOutlineDoc == NULL) + return NULL; + + // initialize new document + if (! OutlineDoc_Init(lpOutlineDoc, fDataTransferDoc)) + goto error; + + OLEDBG_END3 + return lpOutlineDoc; + +error: + if (lpOutlineDoc) + Delete(lpOutlineDoc); + + OLEDBG_END3 + return NULL; +} + + +/* OutlineApp_CreateName + * --------------------- + * + * Allocate a new Name of the appropriate type. + * OutlineApp --> creates standard OutlineName type names. + * ServerApp --> creates enhanced SeverName type names. + * + * Returns lpOutlineName for successful, NULL if error. + */ +LPOUTLINENAME OutlineApp_CreateName(LPOUTLINEAPP lpOutlineApp) +{ + LPOUTLINENAME lpOutlineName; + +#if defined( OLE_SERVER ) + lpOutlineName = (LPOUTLINENAME)New((DWORD)sizeof(SERVERNAME)); +#else + lpOutlineName = (LPOUTLINENAME)New((DWORD)sizeof(OUTLINENAME)); +#endif + + OleDbgAssertSz(lpOutlineName != NULL, "Error allocating Name"); + if (lpOutlineName == NULL) + return NULL; + +#if defined( OLE_SERVER ) + _fmemset((LPVOID)lpOutlineName,0,sizeof(SERVERNAME)); +#else + _fmemset((LPVOID)lpOutlineName,0,sizeof(OUTLINENAME)); +#endif + + return lpOutlineName; +} + + +/* OutlineApp_DocUnlockApp +** ----------------------- +** Forget all references to a closed document. +*/ +void OutlineApp_DocUnlockApp(LPOUTLINEAPP lpOutlineApp, LPOUTLINEDOC lpOutlineDoc) +{ + /* forget pointers to destroyed document */ + if (lpOutlineApp->m_lpDoc == lpOutlineDoc) + lpOutlineApp->m_lpDoc = NULL; + else if (lpOutlineApp->m_lpClipboardDoc == lpOutlineDoc) + lpOutlineApp->m_lpClipboardDoc = NULL; + +#if defined( OLE_VERSION ) + /* OLE2NOTE: when there are no open documents and the app is not + ** under the control of the user then revoke our ClassFactory to + ** enable the app to shut down. + ** + ** NOTE: data transfer documents (non-user documents) do NOT + ** hold the app alive. therefore they do not Lock the app. + */ + if (! lpOutlineDoc->m_fDataTransferDoc) + OleApp_DocUnlockApp((LPOLEAPP)lpOutlineApp, lpOutlineDoc); +#endif +} + + +/* OutlineApp_NewCommand + * --------------------- + * + * Start a new untitled document (File.New command). + */ +void OutlineApp_NewCommand(LPOUTLINEAPP lpOutlineApp) +{ +#if defined( OLE_VERSION ) + // Call OLE version of this function instead + OleApp_NewCommand((LPOLEAPP)lpOutlineApp); + +#else + + LPOUTLINEDOC lpOutlineDoc = lpOutlineApp->m_lpDoc; + + if (! OutlineDoc_Close(lpOutlineDoc, OLECLOSE_PROMPTSAVE)) + return; + + OleDbgAssertSz(lpOutlineApp->m_lpDoc==NULL,"Closed doc NOT properly destroyed"); + + lpOutlineApp->m_lpDoc = OutlineApp_CreateDoc(lpOutlineApp, FALSE); + if (! lpOutlineApp->m_lpDoc) goto error; + + // set the doc to an (Untitled) doc. + if (! OutlineDoc_InitNewFile(lpOutlineApp->m_lpDoc)) + goto error; + + // position and size the new doc window + OutlineApp_ResizeWindows(lpOutlineApp); + OutlineDoc_ShowWindow(lpOutlineApp->m_lpDoc); // calls OleDoc_Lock + + return; + +error: + // REVIEW: should load string from string resource + OutlineApp_ErrorMessage(lpOutlineApp, "Could not create new document"); + + if (lpOutlineApp->m_lpDoc) { + OutlineDoc_Destroy(lpOutlineApp->m_lpDoc); + lpOutlineApp->m_lpDoc = NULL; + } + + return; + +#endif +} + + +/* OutlineApp_OpenCommand + * ---------------------- + * + * Load a document from file (File.Open command). + */ +void OutlineApp_OpenCommand(LPOUTLINEAPP lpOutlineApp) +{ +#if defined( OLE_VERSION ) + // Call OLE version of this function instead + OleApp_OpenCommand((LPOLEAPP)lpOutlineApp); + +#else + + OPENFILENAME ofn; + char szFilter[]=APPFILENAMEFILTER; + char szFileName[256]; + UINT i; + DWORD dwSaveOption = OLECLOSE_PROMPTSAVE; + BOOL fStatus = TRUE; + + if (! OutlineDoc_CheckSaveChanges(lpOutlineApp->m_lpDoc, &dwSaveOption)) + return; // abort opening new doc + + for(i=0; szFilter[i]; i++) + if(szFilter[i]=='|') szFilter[i]='\0'; + + _fmemset((LPOPENFILENAME)&ofn,0,sizeof(OPENFILENAME)); + + szFileName[0]='\0'; + + ofn.lStructSize=sizeof(OPENFILENAME); + ofn.hwndOwner=lpOutlineApp->m_hWndApp; + ofn.lpstrFilter=(LPSTR)szFilter; + ofn.lpstrFile=(LPSTR)szFileName; + ofn.nMaxFile=sizeof(szFileName); + ofn.Flags=OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; + ofn.lpstrDefExt=DEFEXTENSION; + + if(! GetOpenFileName((LPOPENFILENAME)&ofn)) + return; // user canceled file open dialog + + OutlineDoc_Close(lpOutlineApp->m_lpDoc, OLECLOSE_NOSAVE); + OleDbgAssertSz(lpOutlineApp->m_lpDoc==NULL,"Closed doc NOT properly destroyed"); + + lpOutlineApp->m_lpDoc = OutlineApp_CreateDoc(lpOutlineApp, FALSE); + if (! lpOutlineApp->m_lpDoc) goto error; + + fStatus=OutlineDoc_LoadFromFile(lpOutlineApp->m_lpDoc, (LPSTR)szFileName); + + if (! fStatus) { + // loading the doc failed; create an untitled instead + OutlineDoc_Destroy(lpOutlineApp->m_lpDoc); // destroy unused doc + lpOutlineApp->m_lpDoc = OutlineApp_CreateDoc(lpOutlineApp, FALSE); + if (! lpOutlineApp->m_lpDoc) goto error; + if (! OutlineDoc_InitNewFile(lpOutlineApp->m_lpDoc)) + goto error; + } + + // position and size the new doc window + OutlineApp_ResizeWindows(lpOutlineApp); + OutlineDoc_ShowWindow(lpOutlineApp->m_lpDoc); + + return; + +error: + // REVIEW: should load string from string resource + OutlineApp_ErrorMessage(lpOutlineApp, "Could not create new document"); + + if (lpOutlineApp->m_lpDoc) { + OutlineDoc_Destroy(lpOutlineApp->m_lpDoc); + lpOutlineApp->m_lpDoc = NULL; + } + + return; + +#endif +} + + +/* OutlineApp_PrintCommand + * ----------------------- + * + * Print the document + */ +void OutlineApp_PrintCommand(LPOUTLINEAPP lpOutlineApp) +{ + LPOUTLINEDOC lpOutlineDoc = lpOutlineApp->m_lpDoc; + HDC hDC=NULL; + BOOL fMustDeleteDC = FALSE; + BOOL fStatus; + +#if defined( OLE_VERSION ) + OleApp_PreModalDialog( + (LPOLEAPP)lpOutlineApp, (LPOLEDOC)lpOutlineApp->m_lpDoc); +#endif + + fStatus = PrintDlg((LPPRINTDLG)&lpOutlineApp->m_PrintDlg); + +#if defined( OLE_VERSION ) + OleApp_PostModalDialog( + (LPOLEAPP)lpOutlineApp, (LPOLEDOC)lpOutlineApp->m_lpDoc); +#endif + + if (!fStatus) { + if (!CommDlgExtendedError()) { // Cancel button pressed + return; + } + } + else { + hDC = OutlineApp_GetPrinterDC(lpOutlineApp); + if (hDC) { + +#if defined( OLE_VERSION ) + /* OLE2NOTE: while we are printing we do NOT want to + ** receive any OnDataChange notifications or other OLE + ** interface calls which could disturb the printing of + ** the document. we will temporarily reply + ** SERVERCALL_RETRYLATER + */ + OleApp_RejectInComingCalls((LPOLEAPP)lpOutlineApp, TRUE); +#endif + + OutlineDoc_Print(lpOutlineDoc, hDC); + DeleteDC(hDC); + +#if defined( OLE_VERSION ) + // re-enable LRPC calls + OleApp_RejectInComingCalls((LPOLEAPP)lpOutlineApp, FALSE); +#endif + + return; // Printing completed + } + } + + // REVIEW: should load string from string resource + OutlineApp_ErrorMessage(lpOutlineApp, ErrMsgPrinting); +} + + +/* OutlineApp_PrinterSetupCommand + * ------------------------------ + * + * Setup a different printer for printing + */ +void OutlineApp_PrinterSetupCommand(LPOUTLINEAPP lpOutlineApp) +{ + DWORD FlagSave; + + FlagSave = lpOutlineApp->m_PrintDlg.Flags; + lpOutlineApp->m_PrintDlg.Flags |= PD_PRINTSETUP; + +#if defined( OLE_VERSION ) + OleApp_PreModalDialog( + (LPOLEAPP)lpOutlineApp, (LPOLEDOC)lpOutlineApp->m_lpDoc); +#endif + + PrintDlg((LPPRINTDLG)&lpOutlineApp->m_PrintDlg); + +#if defined( OLE_VERSION ) + OleApp_PostModalDialog( + (LPOLEAPP)lpOutlineApp, (LPOLEDOC)lpOutlineApp->m_lpDoc); +#endif + + lpOutlineApp->m_PrintDlg.Flags = FlagSave; +} + +/* + * FUNCTION : OutlineApp_GetPrinterDC () + * + * PURPOSE : Creates a printer display context for the printer + * + * RETURNS : HDC - A handle to printer DC. + */ +HDC OutlineApp_GetPrinterDC(LPOUTLINEAPP lpApp) +{ + + HDC hDC; + LPDEVMODE lpDevMode = NULL; + LPDEVNAMES lpDevNames; + LPSTR lpszDriverName; + LPSTR lpszDeviceName; + LPSTR lpszPortName; + + if(lpApp->m_PrintDlg.hDC) { + hDC = lpApp->m_PrintDlg.hDC; + } else { + if(! lpApp->m_PrintDlg.hDevNames) + return(NULL); + lpDevNames = (LPDEVNAMES)GlobalLock(lpApp->m_PrintDlg.hDevNames); + lpszDriverName = (LPSTR)lpDevNames + lpDevNames->wDriverOffset; + lpszDeviceName = (LPSTR)lpDevNames + lpDevNames->wDeviceOffset; + lpszPortName = (LPSTR)lpDevNames + lpDevNames->wOutputOffset; + GlobalUnlock(lpApp->m_PrintDlg.hDevNames); + + if(lpApp->m_PrintDlg.hDevMode) + lpDevMode = (LPDEVMODE)GlobalLock(lpApp->m_PrintDlg.hDevMode); +#if defined( WIN32 ) + hDC = CreateDC( + lpszDriverName, + lpszDeviceName, + lpszPortName, + (CONST DEVMODE FAR*)lpDevMode); +#else + hDC = CreateDC( + lpszDriverName, + lpszDeviceName, + lpszPortName, + (LPSTR)lpDevMode); +#endif + + if(lpApp->m_PrintDlg.hDevMode && lpDevMode) + GlobalUnlock(lpApp->m_PrintDlg.hDevMode); + } + + return(hDC); +} + + +/* OutlineApp_SaveCommand + * ---------------------- + * + * Save the document with same name. If no name exists, prompt the user + * for a name (via SaveAsCommand) + * + * Parameters: + * + * Returns: + * TRUE if succesfully + * FALSE if failed or aborted + */ +BOOL OutlineApp_SaveCommand(LPOUTLINEAPP lpOutlineApp) +{ + LPOUTLINEDOC lpOutlineDoc = OutlineApp_GetActiveDoc(lpOutlineApp); + + if(lpOutlineDoc->m_docInitType == DOCTYPE_NEW) /* file with no name */ + return OutlineApp_SaveAsCommand(lpOutlineApp); + + + if(OutlineDoc_IsModified(lpOutlineDoc)) { + +#if defined( OLE_SERVER ) + + if (lpOutlineDoc->m_docInitType == DOCTYPE_EMBEDDED) { + LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOutlineDoc; + HRESULT hrErr; + + /* OLE2NOTE: if the document is an embedded object, then + ** the "File.Save" command is changed to "File.Update". + ** in order to update our container, we must ask our + ** container to save us. + */ + OleDbgAssert(lpServerDoc->m_lpOleClientSite != NULL); + OLEDBG_BEGIN2("IOleClientSite::SaveObject called\r\n") + hrErr = lpServerDoc->m_lpOleClientSite->lpVtbl->SaveObject( + lpServerDoc->m_lpOleClientSite + ); + OLEDBG_END2 + + if (hrErr != NOERROR) { + OleDbgOutHResult("IOleClientSite::SaveObject returned",hrErr); + return FALSE; + } + } else + // document is file-base user document, save it to its file. + +#endif // OLE_SERVER + + (void)OutlineDoc_SaveToFile( + lpOutlineDoc, + NULL, + lpOutlineDoc->m_cfSaveFormat, + TRUE + ); + } + + return TRUE; +} + + +/* OutlineApp_SaveAsCommand + * ------------------------ + * + * Save the document as another name + * + * Parameters: + * + * Returns: + * TRUE if saved successful + * FALSE if failed or aborted + */ +BOOL OutlineApp_SaveAsCommand(LPOUTLINEAPP lpOutlineApp) +{ + LPOUTLINEDOC lpOutlineDoc = lpOutlineApp->m_lpDoc; + OPENFILENAME ofn; + char szFilter[]=APPFILENAMEFILTER; + char szFileName[256]=""; + int i; + UINT uFormat; + BOOL fNoError = TRUE; + BOOL fRemember = TRUE; + BOOL fStatus; + + for(i=0; szFilter[i]; i++) + if(szFilter[i]=='|') szFilter[i]='\0'; + + _fmemset((LPOPENFILENAME)&ofn,0,sizeof(OPENFILENAME)); + + ofn.lStructSize=sizeof(OPENFILENAME); + ofn.hwndOwner=lpOutlineDoc->m_hWndDoc; + ofn.lpstrFilter=(LPSTR)szFilter; + ofn.lpstrFile=(LPSTR)szFileName; + ofn.nMaxFile=sizeof(szFileName); + + ofn.Flags=OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY; + ofn.lpstrDefExt=DEFEXTENSION; + +#if defined( OLE_VERSION ) + OleApp_PreModalDialog( + (LPOLEAPP)lpOutlineApp, (LPOLEDOC)lpOutlineApp->m_lpDoc); +#endif + + fStatus = GetSaveFileName((LPOPENFILENAME)&ofn); + +#if defined( OLE_VERSION ) + OleApp_PostModalDialog( + (LPOLEAPP)lpOutlineApp, (LPOLEDOC)lpOutlineApp->m_lpDoc); +#endif + + if (fStatus) { + +#if defined( OLE_CNTR ) + // determine which file type the user selected. + switch (ofn.nFilterIndex) { + case 1: + uFormat = ((LPCONTAINERAPP)lpOutlineApp)->m_cfCntrOutl; + break; + case 2: + uFormat = lpOutlineApp->m_cfOutline; + break; + default: + uFormat = ((LPCONTAINERAPP)lpOutlineApp)->m_cfCntrOutl; + break; + } +#else + uFormat = lpOutlineApp->m_cfOutline; +#endif + +#if defined( OLE_SERVER ) + /* OLE2NOTE: if the document is an embedded object, then the + ** File.SaveAs command is changed to File.SaveCopyAs. with the + ** Save Copy As operation, the document does NOT remember the + ** saved file as the associated file for the document. + */ + if (lpOutlineDoc->m_docInitType == DOCTYPE_EMBEDDED) + fRemember = FALSE; +#endif + + (void)OutlineDoc_SaveToFile( + lpOutlineDoc, + szFileName, + uFormat, + fRemember + ); + + } + else + fNoError = FALSE; + + return fNoError; + +} + + +/* OutlineApp_AboutCommand + * ----------------------- + * + * Show the About dialog box + */ +void OutlineApp_AboutCommand(LPOUTLINEAPP lpOutlineApp) +{ +#if defined( OLE_VERSION ) + OleApp_PreModalDialog( + (LPOLEAPP)lpOutlineApp, (LPOLEDOC)lpOutlineApp->m_lpDoc); +#endif + + DialogBox( + lpOutlineApp->m_hInst, + (LPSTR)"About", + OutlineApp_GetFrameWindow(lpOutlineApp), + (DLGPROC)AboutDlgProc + ); + +#if defined( OLE_VERSION ) + OleApp_PostModalDialog( + (LPOLEAPP)lpOutlineApp, (LPOLEDOC)lpOutlineApp->m_lpDoc); +#endif +} + + +/* OutlineApp_CloseAllDocsAndExitCommand + * ------------------------------------- + * + * Close all active documents and exit the app. + * Because this is an SDI, there is only one document + * If the doc was modified, prompt the user if he wants to save it. + * + * Returns: + * TRUE if the app is successfully closed + * FALSE if failed or aborted + */ +BOOL OutlineApp_CloseAllDocsAndExitCommand( + LPOUTLINEAPP lpOutlineApp, + BOOL fForceEndSession +) +{ + BOOL fResult; + + OLEDBG_BEGIN2("OutlineApp_CloseAllDocsAndExitCommand\r\n") + +#if defined( OLE_VERSION ) + // Call OLE specific version of this function + fResult = OleApp_CloseAllDocsAndExitCommand( + (LPOLEAPP)lpOutlineApp, fForceEndSession); + +#else + + /* Because this is an SDI app, there is only one document. + ** Close the doc. if it is successfully closed and the app will + ** not automatically exit, then also exit the app. + ** if this were an MDI app, we would loop through and close all + ** open MDI child documents. + */ + if (OutlineDoc_Close(lpOutlineApp->m_lpDoc, OLECLOSE_PROMPTSAVE)) { + +#if defined( _DEBUG ) + OleDbgAssertSz( + lpOutlineApp->m_lpDoc==NULL, + "Closed doc NOT properly destroyed" + ); +#endif + + OutlineApp_Destroy(lpOutlineApp); + fResult = TRUE; + + } // else User Canceled shutdown + else + fResult = FALSE; + +#endif + + OLEDBG_END2 + + return fResult; +} + + +/* OutlineApp_Destroy + * ------------------ + * + * Destroy all data structures used by the app and force the + * app to shut down. This should be called after all documents have + * been closed. + */ +void OutlineApp_Destroy(LPOUTLINEAPP lpOutlineApp) +{ + OLEDBG_BEGIN3("OutlineApp_Destroy\r\n"); + +#if defined( OLE_VERSION ) + /* OLE2NOTE: perform processing required for OLE */ + OleApp_Destroy((LPOLEAPP)lpOutlineApp); +#endif + + SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW))); + DestroyCursor(lpOutlineApp->m_hcursorSelCur); + +#if defined( USE_FRAMETOOLS ) + FrameTools_Destroy(&lpOutlineApp->m_frametools); +#endif + + if (lpOutlineApp->m_hStdFont) + DeleteObject(lpOutlineApp->m_hStdFont); + + if(lpOutlineApp->m_PrintDlg.hDevMode) + GlobalFree(lpOutlineApp->m_PrintDlg.hDevMode); + if(lpOutlineApp->m_PrintDlg.hDevNames) + GlobalFree(lpOutlineApp->m_PrintDlg.hDevNames); + +#if defined( USE_STATUSBAR ) + if(lpOutlineApp->m_hWndStatusBar) { + DestroyStatusWindow(lpOutlineApp->m_hWndStatusBar); + lpOutlineApp->m_hWndStatusBar = NULL; + } +#endif + + OutlineApp_DestroyWindow(lpOutlineApp); + OleDbgOut1("@@@@ APP DESTROYED\r\n"); + + OLEDBG_END3 +} + + +/* OutlineApp_DestroyWindow + * ------------------------ + * + * Destroy all windows created by the App. + */ +void OutlineApp_DestroyWindow(LPOUTLINEAPP lpOutlineApp) +{ + HWND hWndApp = lpOutlineApp->m_hWndApp; + + if(hWndApp) { + lpOutlineApp->m_hWndApp = NULL; + lpOutlineApp->m_hWndAccelTarget = NULL; + DestroyWindow(hWndApp); /* Quit the app */ + } +} + + +/* OutlineApp_GetFrameRect +** ----------------------- +** Get the rectangle of the app frame window EXCLUDING space for the +** status line. +** +** OLE2NOTE: this is the rectangle that an in-place container can +** offer to an in-place active object from which to get frame tool +** space. +*/ +void OutlineApp_GetFrameRect(LPOUTLINEAPP lpOutlineApp, LPRECT lprcFrameRect) +{ + GetClientRect(lpOutlineApp->m_hWndApp, lprcFrameRect); + +#if defined( USE_STATUSBAR ) + lprcFrameRect->bottom -= STATUS_HEIGHT; +#endif + +} + + +/* OutlineApp_GetClientAreaRect +** ---------------------------- +** Get the rectangle of the app frame window EXCLUDING space for the +** status line AND EXCLUDING space for any frame-level tools. +** +** OLE2NOTE: this is the rectangle that an in-place container gives +** to its in-place active object as the lpClipRect in +** IOleInPlaceSite::GetWindowContext. +*/ +void OutlineApp_GetClientAreaRect( + LPOUTLINEAPP lpOutlineApp, + LPRECT lprcClientAreaRect +) +{ + OutlineApp_GetFrameRect(lpOutlineApp, lprcClientAreaRect); + + /* if the app either uses frame-level tools itself or, as in-place + ** container, is prepared to allow an in-place active object to + ** have space for tools, then it must subtract away the space + ** required for the tools. + */ +#if defined ( USE_FRAMETOOLS ) || defined ( INPLACE_CNTR ) + + lprcClientAreaRect->top += lpOutlineApp->m_FrameToolWidths.top; + lprcClientAreaRect->left += lpOutlineApp->m_FrameToolWidths.left; + lprcClientAreaRect->right -= lpOutlineApp->m_FrameToolWidths.right; + lprcClientAreaRect->bottom -= lpOutlineApp->m_FrameToolWidths.bottom; +#endif // USE_FRAMETOOLS || INPLACE_CNTR + +} + + +/* OutlineApp_GetStatusLineRect +** ---------------------------- +** Get the rectangle required for the status line. +** +** OLE2NOTE: the top frame-level in-place container displays its +** status line even when an object is active in-place. +*/ +void OutlineApp_GetStatusLineRect( + LPOUTLINEAPP lpOutlineApp, + LPRECT lprcStatusLineRect +) +{ + RECT rcFrameRect; + GetClientRect(lpOutlineApp->m_hWndApp, (LPRECT)&rcFrameRect); + lprcStatusLineRect->left = rcFrameRect.left; + lprcStatusLineRect->top = rcFrameRect.bottom - STATUS_HEIGHT; + lprcStatusLineRect->right = rcFrameRect.right; + lprcStatusLineRect->bottom = rcFrameRect.bottom; +} + + +/* OutlineApp_ResizeWindows + * ------------------------ + * + * Changes the size and position of the SDI document and tool windows. + * Normally called on a WM_SIZE message. + * + * Currently the app supports a status bar and a single SDI document window. + * In the future it will have a formula bar and possibly multiple MDI + * document windows. + * + * CUSTOMIZATION: Change positions of windows. + */ +void OutlineApp_ResizeWindows(LPOUTLINEAPP lpOutlineApp) +{ + LPOUTLINEDOC lpOutlineDoc = OutlineApp_GetActiveDoc(lpOutlineApp); + RECT rcStatusLineRect; + + if (! lpOutlineApp) + return; + +#if defined( INPLACE_CNTR ) + if (lpOutlineDoc) + ContainerDoc_FrameWindowResized((LPCONTAINERDOC)lpOutlineDoc); +#else +#if defined( USE_FRAMETOOLS ) + if (lpOutlineDoc) + OutlineDoc_AddFrameLevelTools(lpOutlineDoc); +#else + OutlineApp_ResizeClientArea(lpOutlineApp); +#endif // ! USE_FRAMETOOLS +#endif // ! INPLACE_CNTR + +#if defined( USE_STATUSBAR ) + if (lpOutlineApp->m_hWndStatusBar) { + OutlineApp_GetStatusLineRect(lpOutlineApp, (LPRECT)&rcStatusLineRect); + MoveWindow( + lpOutlineApp->m_hWndStatusBar, + rcStatusLineRect.left, + rcStatusLineRect.top, + rcStatusLineRect.right - rcStatusLineRect.left, + rcStatusLineRect.bottom - rcStatusLineRect.top, + TRUE /* fRepaint */ + ); + } +#endif // USE_STATUSBAR +} + + +#if defined( USE_FRAMETOOLS ) || defined( INPLACE_CNTR ) + +void OutlineApp_SetBorderSpace( + LPOUTLINEAPP lpOutlineApp, + LPBORDERWIDTHS lpBorderWidths +) +{ + lpOutlineApp->m_FrameToolWidths = *lpBorderWidths; + OutlineApp_ResizeClientArea(lpOutlineApp); +} +#endif // USE_FRAMETOOLS || INPLACE_CNTR + + +void OutlineApp_ResizeClientArea(LPOUTLINEAPP lpOutlineApp) +{ + RECT rcClientAreaRect; + +#if defined( MDI_VERSION ) + + // Resize MDI Client Area Window here + +#else + + if (lpOutlineApp->m_lpDoc) { + OutlineApp_GetClientAreaRect( + lpOutlineApp, (LPRECT)&rcClientAreaRect); + OutlineDoc_Resize(lpOutlineApp->m_lpDoc, + (LPRECT)&rcClientAreaRect); + } + +#endif + +} + + +/* OutlineApp_GetActiveDoc + * ----------------------- + * + * Return the document in focus. For SDI, the same (only one) document is + * always returned. + */ +LPOUTLINEDOC OutlineApp_GetActiveDoc(LPOUTLINEAPP lpOutlineApp) +{ + return lpOutlineApp->m_lpDoc; +} + +/* OutlineApp_GetMenu + * ------------------ + * + * Return the menu handle of the app + */ +HMENU OutlineApp_GetMenu(LPOUTLINEAPP lpOutlineApp) +{ + if (!lpOutlineApp) { + return NULL; + } + + return lpOutlineApp->m_hMenuApp; +} + + +#if defined( USE_FRAMETOOLS ) + +/* OutlineApp_GetFrameTools + * --------------------- + * + * Return the pointer to the toolbar object + */ +LPFRAMETOOLS OutlineApp_GetFrameTools(LPOUTLINEAPP lpOutlineApp) +{ + return (LPFRAMETOOLS)&lpOutlineApp->m_frametools; +} +#endif + + +/* OutlineApp_SetStatusText + * ------------------------ + * + * Show the given string in the status line + */ +void OutlineApp_SetStatusText(LPOUTLINEAPP lpOutlineApp, LPSTR lpszMessage) +{ + SetStatusText(lpOutlineApp->m_hWndStatusBar, lpszMessage); +} + + +/* OutlineApp_GetActiveFont + * ------------------------ + * + * Return the font used by the application + */ +HFONT OutlineApp_GetActiveFont(LPOUTLINEAPP lpOutlineApp) +{ + return lpOutlineApp->m_hStdFont; +} + + +/* OutlineApp_GetAppName + * --------------------- + * + * Retrieve the application name + */ +void OutlineApp_GetAppName(LPOUTLINEAPP lpOutlineApp, LPSTR lpszAppName) +{ + lstrcpy(lpszAppName, APPNAME); +} + + +/* OutlineApp_GetAppVersionNo + * -------------------------- + * + * Get the version number (major and minor) of the application + */ +void OutlineApp_GetAppVersionNo(LPOUTLINEAPP lpOutlineApp, int narrAppVersionNo[]) +{ + narrAppVersionNo[0] = APPMAJORVERSIONNO; + narrAppVersionNo[1] = APPMINORVERSIONNO; +} + + +/* OutlineApp_VersionNoCheck + * ------------------------- + * + * Check if the version stamp read from a file is compatible + * with the current instance of the application. + * returns TRUE if the file can be read, else FALSE. + */ +BOOL OutlineApp_VersionNoCheck(LPOUTLINEAPP lpOutlineApp, LPSTR lpszFormatName, int narrAppVersionNo[]) +{ +#if defined( OLE_CNTR ) + + /* ContainerApp accepts both CF_OUTLINE and CF_CONTAINEROUTLINE formats */ + if (lstrcmp(lpszFormatName, CONTAINERDOCFORMAT) != 0 && + lstrcmp(lpszFormatName, OUTLINEDOCFORMAT) != 0) { + // REVIEW: should load string from string resource + OutlineApp_ErrorMessage( + lpOutlineApp, + "File is either corrupted or not of proper type." + ); + return FALSE; + } + +#else + + /* OutlineApp accepts CF_OUTLINE format only */ + if (lstrcmp(lpszFormatName, OUTLINEDOCFORMAT) != 0) { + // REVIEW: should load string from string resource + OutlineApp_ErrorMessage( + lpOutlineApp, + "File is either corrupted or not of proper type." + ); + return FALSE; + } +#endif + + if (narrAppVersionNo[0] < APPMAJORVERSIONNO) { + // REVIEW: should load string from string resource + OutlineApp_ErrorMessage( + lpOutlineApp, + "File was created by an older version; it can not be read." + ); + return FALSE; + } + + return TRUE; +} + + +/* OutlineApp_ErrorMessage + * ----------------------- + * + * Display an error message box + */ +void OutlineApp_ErrorMessage(LPOUTLINEAPP lpOutlineApp, LPSTR lpszErrMsg) +{ + HWND hWndFrame = OutlineApp_GetFrameWindow(lpOutlineApp); + + // OLE2NOTE: only put up user message boxes if app is visible + if (IsWindowVisible(hWndFrame)) { +#if defined( OLE_VERSION ) + OleApp_PreModalDialog( + (LPOLEAPP)lpOutlineApp, (LPOLEDOC)lpOutlineApp->m_lpDoc); +#endif + + MessageBox(hWndFrame, lpszErrMsg, NULL, MB_ICONEXCLAMATION | MB_OK); + +#if defined( OLE_VERSION ) + OleApp_PostModalDialog( + (LPOLEAPP)lpOutlineApp, (LPOLEDOC)lpOutlineApp->m_lpDoc); +#endif + } +} + + +#if defined( USE_FRAMETOOLS ) + +/* OutlineApp_SetFormulaBarAccel + * ----------------------------- + * + * Set accelerator table based on state of formula bar. + */ +void OutlineApp_SetFormulaBarAccel( + LPOUTLINEAPP lpOutlineApp, + BOOL fEditFocus +) +{ + if (fEditFocus) + lpOutlineApp->m_hAccel = lpOutlineApp->m_hAccelFocusEdit; + else + lpOutlineApp->m_hAccel = lpOutlineApp->m_hAccelApp; +} + +#endif // USE_FRAMETOOLS + + + + +/* OutlineApp_ForceRedraw + * ---------------------- + * + * Force the Application window to repaint. + */ +void OutlineApp_ForceRedraw(LPOUTLINEAPP lpOutlineApp, BOOL fErase) +{ + if (!lpOutlineApp) + return; + + InvalidateRect(lpOutlineApp->m_hWndApp, NULL, fErase); +} diff --git a/private/oleutest/letest/outline/outldoc.c b/private/oleutest/letest/outline/outldoc.c new file mode 100644 index 000000000..8e36101f0 --- /dev/null +++ b/private/oleutest/letest/outline/outldoc.c @@ -0,0 +1,3247 @@ +/************************************************************************* +** +** OLE 2 Sample Code +** +** outldoc.c +** +** This file contains OutlineDoc functions. +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + +#include "outline.h" + +#if !defined( OLE_VERSION ) +#include +#endif + + +OLEDBGDATA + +extern LPOUTLINEAPP g_lpApp; + +// REVIEW: should use string resource for messages +char ErrMsgDocWnd[] = "Can't create Document Window!"; +char ErrMsgFormatNotSupported[] = "Clipboard format not supported!"; +char MsgSaveFile[] = "Save existing file ?"; +char ErrMsgSaving[] = "Error in saving file!"; +char ErrMsgOpening[] = "Error in opening file!"; +char ErrMsgFormat[] = "Improper file format!"; +char ErrOutOfMemory[] = "Error: out of memory!"; +static char ErrMsgPrint[] = "Printing Error!"; + +static BOOL fCancelPrint; // TRUE if the user has canceled the print job +static HWND hWndPDlg; // Handle to the cancel print dialog + + +/* OutlineDoc_Init + * --------------- + * + * Initialize the fields of a new OutlineDoc object. The object is initially + * not associated with a file or an (Untitled) document. This function sets + * the docInitType to DOCTYPE_UNKNOWN. After calling this function the + * caller should call: + * 1. OutlineDoc_InitNewFile to set the OutlineDoc to (Untitled) + * 2. OutlineDoc_LoadFromFile to associate the OutlineDoc with a file. + * This function creates a new window for the document. + * + * NOTE: the window is initially created with a NIL size. it must be + * sized and positioned by the caller. also the document is initially + * created invisible. the caller must call OutlineDoc_ShowWindow + * after sizing it to make the document window visible. + */ +BOOL OutlineDoc_Init(LPOUTLINEDOC lpOutlineDoc, BOOL fDataTransferDoc) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + +#if defined( INPLACE_CNTR ) + lpOutlineDoc->m_hWndDoc = CreateWindow( + DOCWNDCLASS, // Window class name + NULL, // Window's title + + /* OLE2NOTE: an in-place contanier MUST use + ** WS_CLIPCHILDREN window style for the window + ** that it uses as the parent for the server's + ** in-place active window so that its + ** painting does NOT interfere with the painting + ** of the server's in-place active child window. + */ + + WS_CLIPCHILDREN | WS_CLIPSIBLINGS | + WS_CHILDWINDOW, + 0, 0, + 0, 0, + lpOutlineApp->m_hWndApp,// Parent window's handle + (HMENU)1, // child window id + lpOutlineApp->m_hInst, // Instance of window + NULL); // Create struct for WM_CREATE + +#else + + lpOutlineDoc->m_hWndDoc = CreateWindow( + DOCWNDCLASS, // Window class name + NULL, // Window's title + WS_CHILDWINDOW, + 0, 0, + 0, 0, + lpOutlineApp->m_hWndApp,// Parent window's handle + (HMENU)1, // child window id + lpOutlineApp->m_hInst, // Instance of window + NULL); // Create struct for WM_CREATE +#endif + + if(! lpOutlineDoc->m_hWndDoc) { + OutlineApp_ErrorMessage(lpOutlineApp, ErrMsgDocWnd); + return FALSE; + } + + SetWindowLong(lpOutlineDoc->m_hWndDoc, 0, (LONG) lpOutlineDoc); + + if (! LineList_Init(&lpOutlineDoc->m_LineList, lpOutlineDoc)) + return FALSE; + + lpOutlineDoc->m_lpNameTable = OutlineDoc_CreateNameTable(lpOutlineDoc); + if (! lpOutlineDoc->m_lpNameTable ) + return FALSE; + + lpOutlineDoc->m_docInitType = DOCTYPE_UNKNOWN; + lpOutlineDoc->m_cfSaveFormat = lpOutlineApp->m_cfOutline; + lpOutlineDoc->m_szFileName[0] = '\0'; + lpOutlineDoc->m_lpszDocTitle = lpOutlineDoc->m_szFileName; + lpOutlineDoc->m_fDataTransferDoc = fDataTransferDoc; + lpOutlineDoc->m_uCurrentZoom = IDM_V_ZOOM_100; + lpOutlineDoc->m_scale.dwSxN = (DWORD) 1; + lpOutlineDoc->m_scale.dwSxD = (DWORD) 1; + lpOutlineDoc->m_scale.dwSyN = (DWORD) 1; + lpOutlineDoc->m_scale.dwSyD = (DWORD) 1; + lpOutlineDoc->m_uCurrentMargin = IDM_V_SETMARGIN_0; + lpOutlineDoc->m_nLeftMargin = 0; + lpOutlineDoc->m_nRightMargin = 0; + lpOutlineDoc->m_nDisableDraw = 0; + OutlineDoc_SetModified(lpOutlineDoc, FALSE, FALSE, FALSE); + +#if defined( USE_HEADING ) + if (! fDataTransferDoc) { + if (!Heading_Create((LPHEADING)&lpOutlineDoc->m_heading, + lpOutlineDoc->m_hWndDoc, lpOutlineApp->m_hInst)) { + return FALSE; + + } + } +#endif // USE_HEADING + +#if defined( USE_FRAMETOOLS ) + if (! fDataTransferDoc) { + lpOutlineDoc->m_lpFrameTools = OutlineApp_GetFrameTools(lpOutlineApp); + FrameTools_AssociateDoc( + lpOutlineDoc->m_lpFrameTools, + lpOutlineDoc + ); + } +#endif // USE_FRAMETOOLS + +#if defined( OLE_VERSION ) + /* OLE2NOTE: perform initialization required for OLE */ + if (! OleDoc_Init((LPOLEDOC)lpOutlineDoc, fDataTransferDoc)) + return FALSE; +#endif // OLE_VERSION + + return TRUE; +} + + +/* OutlineDoc_InitNewFile + * ---------------------- + * + * Initialize the OutlineDoc object to be a new (Untitled) document. + * This function sets the docInitType to DOCTYPE_NEW. + */ +BOOL OutlineDoc_InitNewFile(LPOUTLINEDOC lpOutlineDoc) +{ +#if defined( OLE_VERSION ) + // OLE2NOTE: call OLE version of this function instead + return OleDoc_InitNewFile((LPOLEDOC)lpOutlineDoc); + +#else + + OleDbgAssert(lpOutlineDoc->m_docInitType == DOCTYPE_UNKNOWN); + + // set file name to untitled + // REVIEW: should load from string resource + lstrcpy(lpOutlineDoc->m_szFileName, UNTITLED); + lpOutlineDoc->m_lpszDocTitle = lpOutlineDoc->m_szFileName; + lpOutlineDoc->m_docInitType = DOCTYPE_NEW; + + if (! lpOutlineDoc->m_fDataTransferDoc) + OutlineDoc_SetTitle(lpOutlineDoc, FALSE /*fMakeUpperCase*/); + + return TRUE; + +#endif // BASE OUTLINE VERSION +} + + +/* OutlineDoc_CreateNameTable + * -------------------------- + * + * Allocate a new NameTable of the appropriate type. Each document has + * a NameTable and a LineList. + * OutlineDoc --> creates standard OutlineNameTable type name tables. + * ServerDoc --> creates enhanced SeverNameTable type name tables. + * + * Returns lpNameTable for successful, NULL if error. + */ +LPOUTLINENAMETABLE OutlineDoc_CreateNameTable(LPOUTLINEDOC lpOutlineDoc) +{ + LPOUTLINENAMETABLE lpOutlineNameTable; + + lpOutlineNameTable = (LPOUTLINENAMETABLE)New( + (DWORD)sizeof(OUTLINENAMETABLE) + ); + + OleDbgAssertSz(lpOutlineNameTable != NULL,"Error allocating NameTable"); + if (lpOutlineNameTable == NULL) + return NULL; + + // initialize new NameTable + if (! OutlineNameTable_Init(lpOutlineNameTable, lpOutlineDoc) ) + goto error; + + return lpOutlineNameTable; + +error: + if (lpOutlineNameTable) + Delete(lpOutlineNameTable); + return NULL; +} + + +/* OutlineDoc_ClearCommand + * ----------------------- + * + * Delete selection in list box by calling OutlineDoc_Delete + */ +void OutlineDoc_ClearCommand(LPOUTLINEDOC lpOutlineDoc) +{ + LPLINELIST lpLL = &lpOutlineDoc->m_LineList; + int i; + int nNumSel; + LINERANGE lrSel; + + nNumSel=LineList_GetSel(lpLL, (LPLINERANGE)&lrSel); + + OutlineDoc_SetRedraw ( lpOutlineDoc, FALSE ); + for(i = 0; i < nNumSel; i++) + OutlineDoc_DeleteLine(lpOutlineDoc, lrSel.m_nStartLine); + + OutlineDoc_SetRedraw ( lpOutlineDoc, TRUE ); + + LineList_RecalcMaxLineWidthInHimetric(lpLL, 0); +} + + +/* OutlineDoc_CutCommand + * --------------------- + * + * Cut selection to clipboard + */ +void OutlineDoc_CutCommand(LPOUTLINEDOC lpOutlineDoc) +{ + OutlineDoc_CopyCommand(lpOutlineDoc); + OutlineDoc_ClearCommand(lpOutlineDoc); +} + + +/* OutlineDoc_CopyCommand + * ---------------------- + * Copy selection to clipboard. + * Post to the clipboard the formats that the app can render. + * the actual data is not rendered at this time. using the + * delayed rendering technique, Windows will send the clipboard + * owner window either a WM_RENDERALLFORMATS or a WM_RENDERFORMAT + * message when the actual data is requested. + * + * OLE2NOTE: the normal delayed rendering technique where Windows + * sends the clipboard owner window either a WM_RENDERALLFORMATS or + * a WM_RENDERFORMAT message when the actual data is requested is + * NOT exposed to the app calling OleSetClipboard. OLE internally + * creates its own window as the clipboard owner and thus our app + * will NOT get these WM_RENDER messages. + */ +void OutlineDoc_CopyCommand(LPOUTLINEDOC lpSrcOutlineDoc) +{ +#if defined( OLE_VERSION ) + // Call OLE version of this function instead + OleDoc_CopyCommand((LPOLEDOC)lpSrcOutlineDoc); + +#else + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + LPOUTLINEDOC lpClipboardDoc; + + OpenClipboard(lpSrcOutlineDoc->m_hWndDoc); + EmptyClipboard(); + + /* squirrel away a copy of the current selection to the ClipboardDoc */ + lpClipboardDoc = OutlineDoc_CreateDataTransferDoc(lpSrcOutlineDoc); + + if (! lpClipboardDoc) + return; // Error: could not create DataTransferDoc + + lpOutlineApp->m_lpClipboardDoc = (LPOUTLINEDOC)lpClipboardDoc; + + SetClipboardData(lpOutlineApp->m_cfOutline, NULL); + SetClipboardData(CF_TEXT, NULL); + + CloseClipboard(); + +#endif // ! OLE_VERSION +} + + +/* OutlineDoc_ClearAllLines + * ------------------------ + * + * Delete all lines in the document. + */ +void OutlineDoc_ClearAllLines(LPOUTLINEDOC lpOutlineDoc) +{ + LPLINELIST lpLL = &lpOutlineDoc->m_LineList; + int i; + + for(i = 0; i < lpLL->m_nNumLines; i++) + OutlineDoc_DeleteLine(lpOutlineDoc, 0); + + LineList_RecalcMaxLineWidthInHimetric(lpLL, 0); +} + + +/* OutlineDoc_CreateDataTransferDoc + * -------------------------------- + * + * Create a document to be use to transfer data (either via a + * drag/drop operation of the clipboard). Copy the selection of the + * source doc to the data transfer document. A data transfer document is + * the same as a document that is created by the user except that it is + * NOT made visible to the user. it is specially used to hold a copy of + * data that the user should not be able to change. + * + * OLE2NOTE: in the OLE version the data transfer document is used + * specifically to provide an IDataObject* that renders the data copied. + */ +LPOUTLINEDOC OutlineDoc_CreateDataTransferDoc(LPOUTLINEDOC lpSrcOutlineDoc) +{ +#if defined( OLE_VERSION ) + // Call OLE version of this function instead + return OleDoc_CreateDataTransferDoc((LPOLEDOC)lpSrcOutlineDoc); + +#else + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + LPOUTLINEDOC lpDestOutlineDoc; + LPLINELIST lpSrcLL = &lpSrcOutlineDoc->m_LineList; + LINERANGE lrSel; + int nCopied; + + lpDestOutlineDoc = OutlineApp_CreateDoc(lpOutlineApp, TRUE); + if (! lpDestOutlineDoc) return NULL; + + // set the ClipboardDoc to an (Untitled) doc. + if (! OutlineDoc_InitNewFile(lpDestOutlineDoc)) + goto error; + + LineList_GetSel(lpSrcLL, (LPLINERANGE)&lrSel); + nCopied = LineList_CopySelToDoc( + lpSrcLL, + (LPLINERANGE)&lrSel, + lpDestOutlineDoc + ); + + return lpDestOutlineDoc; + +error: + if (lpDestOutlineDoc) + OutlineDoc_Destroy(lpDestOutlineDoc); + + return NULL; + +#endif // ! OLE_VERSION +} + + +/* OutlineDoc_PasteCommand + * ----------------------- + * + * Paste lines from clipboard + */ +void OutlineDoc_PasteCommand(LPOUTLINEDOC lpOutlineDoc) +{ +#if defined( OLE_VERSION ) + // Call OLE version of this function instead + OleDoc_PasteCommand((LPOLEDOC)lpOutlineDoc); + +#else + + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + LPLINELIST lpLL = (LPLINELIST)&lpOutlineDoc->m_LineList; + int nIndex; + int nCount; + HGLOBAL hData; + LINERANGE lrSel; + UINT uFormat; + + if (LineList_GetCount(lpLL) == 0) + nIndex = -1; // pasting to empty list + else + nIndex=LineList_GetFocusLineIndex(lpLL); + + OutlineDoc_SetRedraw ( lpOutlineDoc, FALSE ); + + OpenClipboard(lpOutlineDoc->m_hWndDoc); + + uFormat = 0; + while(uFormat = EnumClipboardFormats(uFormat)) { + if(uFormat == lpOutlineApp->m_cfOutline) { + hData = GetClipboardData(lpOutlineApp->m_cfOutline); + nCount = OutlineDoc_PasteOutlineData(lpOutlineDoc, hData, nIndex); + break; + } + if(uFormat == CF_TEXT) { + hData = GetClipboardData(CF_TEXT); + nCount = OutlineDoc_PasteTextData(lpOutlineDoc, hData, nIndex); + break; + } + } + + lrSel.m_nStartLine = nIndex + nCount; + lrSel.m_nEndLine = nIndex + 1; + LineList_SetSel(lpLL, &lrSel); + OutlineDoc_SetRedraw ( lpOutlineDoc, TRUE ); + + CloseClipboard(); + +#endif // ! OLE_VERSION +} + + +/* OutlineDoc_PasteOutlineData + * --------------------------- + * + * Put an array of Line Objects (stored in hOutline) into the document + * + * Return the number of items added + */ +int OutlineDoc_PasteOutlineData(LPOUTLINEDOC lpOutlineDoc, HGLOBAL hOutline, int nStartIndex) +{ + int nCount; + int i; + LPTEXTLINE arrLine; + + nCount = (int) GlobalSize(hOutline) / sizeof(TEXTLINE); + arrLine = (LPTEXTLINE)GlobalLock(hOutline); + if (!arrLine) + return 0; + + for(i = 0; i < nCount; i++) + Line_CopyToDoc((LPLINE)&arrLine[i], lpOutlineDoc, nStartIndex+i); + + GlobalUnlock(hOutline); + + return nCount; +} + + +/* OutlineDoc_PasteTextData + * ------------------------ + * + * Build Line Objects from the strings (separated by '\n') in hText + * and put them into the document + */ +int OutlineDoc_PasteTextData(LPOUTLINEDOC lpOutlineDoc, HGLOBAL hText, int nStartIndex) +{ + LPLINELIST lpLL = (LPLINELIST)&lpOutlineDoc->m_LineList; + HDC hDC; + LPSTR lpszText; + LPSTR lpszEnd; + LPTEXTLINE lpLine; + int nLineCount; + int i; + UINT nTab; + char szBuf[MAXSTRLEN+1]; + + lpszText=(LPSTR)GlobalLock(hText); + if(!lpszText) + return 0; + + lpszEnd = lpszText + lstrlen(lpszText); + nLineCount=0; + + while(*lpszText && (lpszText 0) && (szBuf[i-1] == '\r')) + szBuf[i-1] = 0; // remove carriage return at the end + + hDC = LineList_GetDC(lpLL); + lpLine = TextLine_Create(hDC, nTab, szBuf); + LineList_ReleaseDC(lpLL, hDC); + + OutlineDoc_AddLine( + lpOutlineDoc, + (LPLINE)lpLine, + nStartIndex + nLineCount + ); + nLineCount++; + + } + + GlobalUnlock(hText); + + return nLineCount; +} + + +/* OutlineDoc_AddTextLineCommand + * ----------------------------- + * + * Add a new text line following the current focus line. + */ +void OutlineDoc_AddTextLineCommand(LPOUTLINEDOC lpOutlineDoc) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + LPLINELIST lpLL = &lpOutlineDoc->m_LineList; + HDC hDC; + int nIndex = LineList_GetFocusLineIndex(lpLL); + char szBuf[MAXSTRLEN+1]; + UINT nTab = 0; + LPLINE lpLine; + LPTEXTLINE lpTextLine; + + szBuf[0] = '\0'; + +#if defined( USE_FRAMETOOLS ) + FrameTools_FB_GetEditText( + lpOutlineDoc->m_lpFrameTools, szBuf, sizeof(szBuf)); +#else + if (! InputTextDlg(lpOutlineDoc->m_hWndDoc, szBuf, "Add Line")) + return; +#endif + + hDC = LineList_GetDC(lpLL); + lpLine = LineList_GetLine(lpLL, nIndex); + if (lpLine) + nTab = Line_GetTabLevel(lpLine); + + lpTextLine=TextLine_Create(hDC, nTab, szBuf); + LineList_ReleaseDC(lpLL, hDC); + + if (! lpTextLine) { + OutlineApp_ErrorMessage(lpOutlineApp, ErrOutOfMemory); + return; + } + OutlineDoc_AddLine(lpOutlineDoc, (LPLINE)lpTextLine, nIndex); +} + + +/* OutlineDoc_AddTopLineCommand + * ---------------------------- + * + * Add a top (margin) line as the first line in the LineList. + * (do not change the current selection) + */ +void OutlineDoc_AddTopLineCommand( + LPOUTLINEDOC lpOutlineDoc, + UINT nHeightInHimetric +) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + LPLINELIST lpLL = &lpOutlineDoc->m_LineList; + HDC hDC = LineList_GetDC(lpLL); + LPTEXTLINE lpTextLine = TextLine_Create(hDC, 0, NULL); + LPLINE lpLine = (LPLINE)lpTextLine; + LINERANGE lrSel; + int nNumSel; + + LineList_ReleaseDC(lpLL, hDC); + + if (! lpTextLine) { + OutlineApp_ErrorMessage(lpOutlineApp, ErrOutOfMemory); + return; + } + + Line_SetHeightInHimetric(lpLine, nHeightInHimetric); + + nNumSel=LineList_GetSel(lpLL, (LPLINERANGE)&lrSel); + if (nNumSel > 0) { + // adjust current selection to keep equivalent selection + lrSel.m_nStartLine += 1; + lrSel.m_nEndLine += 1; + } + OutlineDoc_AddLine(lpOutlineDoc, lpLine, -1); + if (nNumSel > 0) + LineList_SetSel(lpLL, (LPLINERANGE)&lrSel); +} + + +#if defined( USE_FRAMETOOLS ) + + +/* OutlineDoc_SetFormulaBarEditText + * -------------------------------- + * + * Fill the edit control in the formula with the text string from a + * TextLine in focus. + */ +void OutlineDoc_SetFormulaBarEditText( + LPOUTLINEDOC lpOutlineDoc, + LPLINE lpLine +) +{ + LPLINELIST lpLL = &lpOutlineDoc->m_LineList; + char cBuf[MAXSTRLEN+1]; + + if (! lpOutlineDoc || ! lpOutlineDoc->m_lpFrameTools) + return; + + if (Line_GetLineType(lpLine) != TEXTLINETYPE) { + FrameTools_FB_SetEditText(lpOutlineDoc->m_lpFrameTools, NULL); + } else { + TextLine_GetTextData((LPTEXTLINE)lpLine, (LPSTR)cBuf); + FrameTools_FB_SetEditText(lpOutlineDoc->m_lpFrameTools, (LPSTR)cBuf); + } +} + + +/* OutlineDoc_SetFormulaBarEditFocus + * --------------------------------- + * + * Setup for formula bar to gain or loose edit focus. + * if gaining focus, setup up special accelerator table and scroll line + * into view. + * else restore normal accelerator table. + */ +void OutlineDoc_SetFormulaBarEditFocus( + LPOUTLINEDOC lpOutlineDoc, + BOOL fEditFocus +) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + LPLINELIST lpLL; + int nFocusIndex; + + if (! lpOutlineDoc || ! lpOutlineDoc->m_lpFrameTools) + return; + + lpOutlineDoc->m_lpFrameTools->m_fInFormulaBar = fEditFocus; + + if (fEditFocus && lpOutlineDoc->m_lpFrameTools) { + lpLL = OutlineDoc_GetLineList(lpOutlineDoc); + + nFocusIndex = LineList_GetFocusLineIndex(lpLL); + LineList_ScrollLineIntoView(lpLL, nFocusIndex); + FrameTools_FB_FocusEdit(lpOutlineDoc->m_lpFrameTools); + } + + OutlineApp_SetFormulaBarAccel(lpOutlineApp, fEditFocus); +} + + +/* OutlineDoc_IsEditFocusInFormulaBar +** ---------------------------------- +** Returns TRUE if edit focus is currently in the formula bar +** else FALSE if not. +*/ +BOOL OutlineDoc_IsEditFocusInFormulaBar(LPOUTLINEDOC lpOutlineDoc) +{ + if (! lpOutlineDoc || ! lpOutlineDoc->m_lpFrameTools) + return FALSE; + + return lpOutlineDoc->m_lpFrameTools->m_fInFormulaBar; +} + + +/* OutlineDoc_UpdateFrameToolButtons +** --------------------------------- +** Update the Enable/Disable states of the buttons in the formula +** bar and button bar. +*/ +void OutlineDoc_UpdateFrameToolButtons(LPOUTLINEDOC lpOutlineDoc) +{ + if (! lpOutlineDoc || ! lpOutlineDoc->m_lpFrameTools) + return; + FrameTools_UpdateButtons(lpOutlineDoc->m_lpFrameTools, lpOutlineDoc); +} +#endif // USE_FRAMETOOLS + + +/* OutlineDoc_EditLineCommand + * -------------------------- + * + * Edit the current focus line. + */ +void OutlineDoc_EditLineCommand(LPOUTLINEDOC lpOutlineDoc) +{ + LPLINELIST lpLL = &lpOutlineDoc->m_LineList; + HDC hDC = LineList_GetDC(lpLL); + int nIndex = LineList_GetFocusLineIndex(lpLL); + LPLINE lpLine = LineList_GetLine(lpLL, nIndex); + int nOrgLineWidthInHimetric; + int nNewLineWidthInHimetric; + BOOL fSizeChanged; + + if (!lpLine) + return; + + nOrgLineWidthInHimetric = Line_GetTotalWidthInHimetric(lpLine); + if (Line_Edit(lpLine, lpOutlineDoc->m_hWndDoc, hDC)) { + nNewLineWidthInHimetric = Line_GetTotalWidthInHimetric(lpLine); + + if (nNewLineWidthInHimetric > nOrgLineWidthInHimetric) { + fSizeChanged = LineList_SetMaxLineWidthInHimetric( + lpLL, + nNewLineWidthInHimetric + ); + } else { + fSizeChanged = LineList_RecalcMaxLineWidthInHimetric( + lpLL, + nOrgLineWidthInHimetric + ); + } + +#if defined( OLE_SERVER ) + /* Update Name Table */ + ServerNameTable_EditLineUpdate( + (LPSERVERNAMETABLE)lpOutlineDoc->m_lpNameTable, + nIndex + ); +#endif + + OutlineDoc_SetModified(lpOutlineDoc, TRUE, TRUE, fSizeChanged); + + LineList_ForceLineRedraw(lpLL, nIndex, TRUE); + } + LineList_ReleaseDC(lpLL, hDC); +} + + +/* OutlineDoc_IndentCommand + * ------------------------ + * + * Indent selection of lines + */ +void OutlineDoc_IndentCommand(LPOUTLINEDOC lpOutlineDoc) +{ + LPLINELIST lpLL = &lpOutlineDoc->m_LineList; + LPLINE lpLine; + HDC hDC = LineList_GetDC(lpLL); + int i; + int nIndex; + int nNumSel; + LINERANGE lrSel; + BOOL fSizeChanged = FALSE; + + nNumSel=LineList_GetSel(lpLL, (LPLINERANGE)&lrSel); + + OutlineDoc_SetRedraw ( lpOutlineDoc, FALSE ); + + for(i = 0; i < nNumSel; i++) { + nIndex = lrSel.m_nStartLine + i; + lpLine=LineList_GetLine(lpLL, nIndex); + if (! lpLine) + continue; + + Line_Indent(lpLine, hDC); + if (LineList_SetMaxLineWidthInHimetric(lpLL, + Line_GetTotalWidthInHimetric(lpLine))) { + fSizeChanged = TRUE; + } + LineList_ForceLineRedraw(lpLL, nIndex, TRUE); + +#if defined( OLE_SERVER ) + /* Update Name Table */ + ServerNameTable_EditLineUpdate( + (LPSERVERNAMETABLE)lpOutlineDoc->m_lpNameTable, + nIndex + ); +#endif + + } + + LineList_ReleaseDC(lpLL, hDC); + + OutlineDoc_SetModified(lpOutlineDoc, TRUE, TRUE, fSizeChanged); + OutlineDoc_SetRedraw ( lpOutlineDoc, TRUE ); +} + + +/* OutlineDoc_UnindentCommand + * -------------------------- + * + * Unindent selection of lines + */ +void OutlineDoc_UnindentCommand(LPOUTLINEDOC lpOutlineDoc) +{ + LPLINELIST lpLL = &lpOutlineDoc->m_LineList; + LPLINE lpLine; + HDC hDC = LineList_GetDC(lpLL); + int nOrgLineWidthInHimetric; + int nOrgMaxLineWidthInHimetric = 0; + int i; + int nIndex; + int nNumSel; + LINERANGE lrSel; + BOOL fSizeChanged; + + nNumSel=LineList_GetSel(lpLL, (LPLINERANGE)&lrSel); + + OutlineDoc_SetRedraw ( lpOutlineDoc, FALSE ); + + for(i = 0; i < nNumSel; i++) { + nIndex = lrSel.m_nStartLine + i; + lpLine=LineList_GetLine(lpLL, nIndex); + if (!lpLine) + continue; + + nOrgLineWidthInHimetric = Line_GetTotalWidthInHimetric(lpLine); + nOrgMaxLineWidthInHimetric = + (nOrgLineWidthInHimetric > nOrgMaxLineWidthInHimetric ? + nOrgLineWidthInHimetric : nOrgMaxLineWidthInHimetric); + Line_Unindent(lpLine, hDC); + LineList_ForceLineRedraw(lpLL, nIndex, TRUE); + +#if defined( OLE_SERVER ) + /* Update Name Table */ + ServerNameTable_EditLineUpdate( + (LPSERVERNAMETABLE)lpOutlineDoc->m_lpNameTable, + nIndex + ); +#endif + + } + + LineList_ReleaseDC(lpLL, hDC); + + fSizeChanged = LineList_RecalcMaxLineWidthInHimetric( + lpLL, + nOrgMaxLineWidthInHimetric + ); + + OutlineDoc_SetModified(lpOutlineDoc, TRUE, TRUE, fSizeChanged); + OutlineDoc_SetRedraw ( lpOutlineDoc, TRUE ); +} + + +/* OutlineDoc_SetLineHeightCommand + * ------------------------------- + * + * Set height of the selection of lines + */ +void OutlineDoc_SetLineHeightCommand(LPOUTLINEDOC lpOutlineDoc) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + LPLINELIST lpLL; + HDC hDC; + LPLINE lpLine; + int nNewHeight; + int i; + int nIndex; + int nNumSel; + LINERANGE lrSel; + + if (!lpOutlineDoc) + return; + + lpLL = &lpOutlineDoc->m_LineList; + nNumSel=LineList_GetSel(lpLL, (LPLINERANGE)&lrSel); + lpLine = LineList_GetLine(lpLL, lrSel.m_nStartLine); + if (!lpLine) + return; + + nNewHeight = Line_GetHeightInHimetric(lpLine); + +#if defined( OLE_VERSION ) + OleApp_PreModalDialog((LPOLEAPP)lpOutlineApp, (LPOLEDOC)lpOutlineDoc); +#endif + + DialogBoxParam( + lpOutlineApp->m_hInst, + (LPSTR)"SetLineHeight", + lpOutlineDoc->m_hWndDoc, + (DLGPROC)SetLineHeightDlgProc, + (LPARAM)(LPINT)&nNewHeight + ); + +#if defined( OLE_VERSION ) + OleApp_PostModalDialog((LPOLEAPP)lpOutlineApp, (LPOLEDOC)lpOutlineDoc); +#endif + + if (nNewHeight == 0) + return; /* user hit cancel */ + + hDC = LineList_GetDC(lpLL); + + for (i = 0; i < nNumSel; i++) { + nIndex = lrSel.m_nStartLine + i; + lpLine=LineList_GetLine(lpLL, nIndex); + if (nNewHeight == -1) { + switch (Line_GetLineType(lpLine)) { + + case TEXTLINETYPE: + + TextLine_CalcExtents((LPTEXTLINE)lpLine, hDC); + break; + +#if defined( OLE_CNTR ) + case CONTAINERLINETYPE: + + ContainerLine_SetHeightInHimetric( + (LPCONTAINERLINE)lpLine, -1); + break; +#endif + + } + } + else + Line_SetHeightInHimetric(lpLine, nNewHeight); + + + LineList_SetLineHeight(lpLL, nIndex, + Line_GetHeightInHimetric(lpLine)); + } + + LineList_ReleaseDC(lpLL, hDC); + + OutlineDoc_SetModified(lpOutlineDoc, TRUE, TRUE, TRUE); + LineList_ForceRedraw(lpLL, TRUE); +} + + + +/* OutlineDoc_SelectAllCommand + * --------------------------- + * + * Select all the lines in the document. + */ +void OutlineDoc_SelectAllCommand(LPOUTLINEDOC lpOutlineDoc) +{ + LPLINELIST lpLL = &lpOutlineDoc->m_LineList; + LINERANGE lrSel; + + lrSel.m_nStartLine = 0; + lrSel.m_nEndLine = LineList_GetCount(lpLL) - 1; + LineList_SetSel(lpLL, &lrSel); +} + + +/* OutlineDoc_DefineNameCommand + * ---------------------------- + * + * Define a name in the document + */ +void OutlineDoc_DefineNameCommand(LPOUTLINEDOC lpOutlineDoc) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + +#if defined( OLE_VERSION ) + OleApp_PreModalDialog((LPOLEAPP)lpOutlineApp, (LPOLEDOC)lpOutlineDoc); +#endif + + DialogBoxParam( + lpOutlineApp->m_hInst, + (LPSTR)"DefineName", + lpOutlineDoc->m_hWndDoc, + (DLGPROC)DefineNameDlgProc, + (LPARAM) lpOutlineDoc + ); + +#if defined( OLE_VERSION ) + OleApp_PostModalDialog((LPOLEAPP)lpOutlineApp, (LPOLEDOC)lpOutlineDoc); +#endif +} + + +/* OutlineDoc_GotoNameCommand + * -------------------------- + * + * Goto a predefined name in the document + */ +void OutlineDoc_GotoNameCommand(LPOUTLINEDOC lpOutlineDoc) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + +#if defined( OLE_VERSION ) + OleApp_PreModalDialog((LPOLEAPP)lpOutlineApp, (LPOLEDOC)lpOutlineDoc); +#endif + + DialogBoxParam( + lpOutlineApp->m_hInst, + (LPSTR)"GotoName", + lpOutlineDoc->m_hWndDoc, + (DLGPROC)GotoNameDlgProc, + (LPARAM)lpOutlineDoc + ); + +#if defined( OLE_VERSION ) + OleApp_PostModalDialog((LPOLEAPP)lpOutlineApp, (LPOLEDOC)lpOutlineDoc); +#endif +} + + +/* OutlineDoc_ShowWindow + * --------------------- + * + * Show the window of the document to the user. + */ +void OutlineDoc_ShowWindow(LPOUTLINEDOC lpOutlineDoc) +{ +#if defined( _DEBUG ) + OleDbgAssertSz(lpOutlineDoc->m_docInitType != DOCTYPE_UNKNOWN, + "OutlineDoc_ShowWindow: can't show unitialized document\r\n"); +#endif + if (lpOutlineDoc->m_docInitType == DOCTYPE_UNKNOWN) + return; + +#if defined( OLE_VERSION ) + // Call OLE version of this function instead + OleDoc_ShowWindow((LPOLEDOC)lpOutlineDoc); +#else + ShowWindow(lpOutlineDoc->m_hWndDoc, SW_SHOWNORMAL); + SetFocus(lpOutlineDoc->m_hWndDoc); +#endif +} + + +#if defined( USE_FRAMETOOLS ) + +void OutlineDoc_AddFrameLevelTools(LPOUTLINEDOC lpOutlineDoc) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; +#if defined( INPLACE_CNTR ) + // Call OLE In-Place Container version of this function instead + ContainerDoc_AddFrameLevelTools((LPCONTAINERDOC)lpOutlineDoc); + +#else // ! INPLACE_CNTR + RECT rcFrameRect; + BORDERWIDTHS frameToolWidths; + +#if defined( INPLACE_SVR ) + LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOutlineDoc; + LPOLEINPLACEFRAME lpTopIPFrame=ServerDoc_GetTopInPlaceFrame(lpServerDoc); + + // if in-place active, add our tools to our in-place container's frame. + if (lpTopIPFrame) { + ServerDoc_AddFrameLevelTools(lpServerDoc); + return; + } +#endif // INPLACE_SVR + + OutlineApp_GetFrameRect(g_lpApp, (LPRECT)&rcFrameRect); + FrameTools_GetRequiredBorderSpace( + lpOutlineDoc->m_lpFrameTools, + (LPBORDERWIDTHS)&frameToolWidths + ); + OutlineApp_SetBorderSpace(g_lpApp, (LPBORDERWIDTHS)&frameToolWidths); + FrameTools_AttachToFrame( + lpOutlineDoc->m_lpFrameTools, OutlineApp_GetWindow(lpOutlineApp)); + FrameTools_Move(lpOutlineDoc->m_lpFrameTools, (LPRECT)&rcFrameRect); +#endif // ! INPLACE_CNTR + +} + +#endif // USE_FRAMETOOLS + + +/* OutlineDoc_GetWindow + * -------------------- + * + * Get the window handle of the document. + */ +HWND OutlineDoc_GetWindow(LPOUTLINEDOC lpOutlineDoc) +{ + if(! lpOutlineDoc) return NULL; + return lpOutlineDoc->m_hWndDoc; +} + + +/* OutlineDoc_AddLine + * ------------------ + * + * Add one line to the Document's LineList + */ +void OutlineDoc_AddLine(LPOUTLINEDOC lpOutlineDoc, LPLINE lpLine, int nIndex) +{ + LPLINELIST lpLL = &lpOutlineDoc->m_LineList; + + LineList_AddLine(lpLL, lpLine, nIndex); + + /* Update Name Table */ + OutlineNameTable_AddLineUpdate(lpOutlineDoc->m_lpNameTable, nIndex); + +#if defined( INPLACE_CNTR ) + { + LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOutlineDoc; + /* OLE2NOTE: after adding a line we need to + ** update the PosRect of the In-Place active + ** objects (if any) that follow the added line. + ** NOTE: nIndex is index of line before new line. + ** nIndex+1 is index of new line + ** nIndex+2 is index of line after new line. + */ + ContainerDoc_UpdateInPlaceObjectRects(lpContainerDoc, nIndex+2); + } +#endif + + OutlineDoc_SetModified(lpOutlineDoc, TRUE, TRUE, TRUE); +} + + +/* OutlineDoc_DeleteLine + * --------------------- + * + * + * Delete one line from the document's LineList + */ +void OutlineDoc_DeleteLine(LPOUTLINEDOC lpOutlineDoc, int nIndex) +{ + LPLINELIST lpLL = &lpOutlineDoc->m_LineList; + +#if defined( OLE_CNTR ) + LPLINE lpLine = LineList_GetLine(lpLL, nIndex); + LPSTORAGE lpStgDoc = NULL; + char szSaveStgName[CWCSTORAGENAME]; + BOOL fDeleteChildStg = FALSE; + + if (lpLine && (Line_GetLineType(lpLine) == CONTAINERLINETYPE) ) { + + /* OLE2NOTE: when a ContainerLine is being deleted by the user, + ** it is important to delete the object's sub-storage + ** otherwise it wastes space in the ContainerDoc's file. + ** this function is called when lines are deleted by the + ** Clear command and when lines are deleted by a DRAGMOVE + ** operation. + */ + LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)lpLine; + + // save name of child storage + LSTRCPYN(szSaveStgName, lpContainerLine->m_szStgName, + sizeof(szSaveStgName)); + lpStgDoc = ((LPOLEDOC)lpContainerLine->m_lpDoc)->m_lpStg; + fDeleteChildStg = TRUE; + } +#endif // OLE_CNTR + + LineList_DeleteLine(lpLL, nIndex); + +#if defined( OLE_CNTR ) + if (fDeleteChildStg && lpStgDoc) { + HRESULT hrErr; + + // delete the obsolete child storage. it is NOT fatal if this fails + + hrErr = CallIStorageDestroyElementA(lpStgDoc, szSaveStgName); + +#if defined( _DEBUG ) + if (hrErr != NOERROR) { + OleDbgOutHResult("IStorage::DestroyElement return", hrErr); + } +#endif + } +#endif // OLE_CNTR + + /* Update Name Table */ + OutlineNameTable_DeleteLineUpdate(lpOutlineDoc->m_lpNameTable, nIndex); + +#if defined( INPLACE_CNTR ) + { + LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOutlineDoc; + /* OLE2NOTE: after deleting a line we need to + ** update the PosRect of the In-Place active + ** objects (if any). + */ + ContainerDoc_UpdateInPlaceObjectRects(lpContainerDoc, nIndex); + } +#endif + + OutlineDoc_SetModified(lpOutlineDoc, TRUE, TRUE, TRUE); + +#if defined( OLE_VERSION ) + { + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + LPOLEDOC lpClipboardDoc = (LPOLEDOC)lpOutlineApp->m_lpClipboardDoc; + + /* OLE2NOTE: if the document that is the source of data on the + ** clipborad has just had lines deleted, then the copied data + ** is no longer considered a valid potential link source. + ** disable the offering of CF_LINKSOURCE from the clipboard + ** document. this avoids problems that arise when the + ** editing operation changes or deletes the original data + ** copied. we will not go to the trouble of determining if + ** the deleted line actually is part of the link source. + */ + if (lpClipboardDoc + && lpClipboardDoc->m_fLinkSourceAvail + && lpClipboardDoc->m_lpSrcDocOfCopy == (LPOLEDOC)lpOutlineDoc) { + lpClipboardDoc->m_fLinkSourceAvail = FALSE; + + /* OLE2NOTE: since we are changing the list of formats on + ** the clipboard (ie. removing CF_LINKSOURCE), we must + ** call OleSetClipboard again. to be sure that the + ** clipboard datatransfer document object does not get + ** destroyed we will guard the call to OleSetClipboard + ** within a pair of AddRef/Release. + */ + OleDoc_AddRef((LPOLEDOC)lpClipboardDoc); // guard obj life-time + + OLEDBG_BEGIN2("OleSetClipboard called\r\n") + OleSetClipboard( + (LPDATAOBJECT)&((LPOLEDOC)lpClipboardDoc)->m_DataObject); + OLEDBG_END2 + + OleDoc_Release((LPOLEDOC)lpClipboardDoc); // rel. AddRef above + } + } +#endif // OLE_VERSION +} + + +/* OutlineDoc_AddName + * ------------------ + * + * Add a Name to the Document's NameTable + */ +void OutlineDoc_AddName(LPOUTLINEDOC lpOutlineDoc, LPOUTLINENAME lpOutlineName) +{ + LPOUTLINENAMETABLE lpOutlineNameTable = lpOutlineDoc->m_lpNameTable; + + OutlineNameTable_AddName(lpOutlineNameTable, lpOutlineName); + + OutlineDoc_SetModified(lpOutlineDoc, TRUE, FALSE, FALSE); +} + + +/* OutlineDoc_DeleteName + * --------------------- + * + * + * Delete Name from the document's NameTable + */ +void OutlineDoc_DeleteName(LPOUTLINEDOC lpOutlineDoc, int nIndex) +{ + LPOUTLINENAMETABLE lpOutlineNameTable = lpOutlineDoc->m_lpNameTable; + + OutlineNameTable_DeleteName(lpOutlineNameTable, nIndex); + + OutlineDoc_SetModified(lpOutlineDoc, TRUE, FALSE, FALSE); +} + + +/* OutlineDoc_Destroy + * ------------------ + * + * Free all memory that had been allocated for a document. + * this destroys the LineList & NameTable of the document. + */ +void OutlineDoc_Destroy(LPOUTLINEDOC lpOutlineDoc) +{ + LPLINELIST lpLL = &lpOutlineDoc->m_LineList; +#if defined( OLE_VERSION ) + LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; + LPOLEDOC lpOleDoc = (LPOLEDOC)lpOutlineDoc; + + if (lpOleDoc->m_fObjIsDestroying) + return; // doc destruction is in progress +#endif // OLE_VERSION + + OLEDBG_BEGIN3("OutlineDoc_Destroy\r\n"); + +#if defined( OLE_VERSION ) + + /* OLE2NOTE: in order to guarantee that the application does not + ** prematurely exit before the destruction of the document is + ** complete, we intially AddRef the App refcnt later Release it. + ** This initial AddRef is artificial; it simply guarantees that + ** the app object does not get destroyed until the end of this + ** routine. + */ + OleApp_AddRef(lpOleApp); + + /* OLE2NOTE: perform processing required for OLE */ + OleDoc_Destroy(lpOleDoc); +#endif + + LineList_Destroy(lpLL); + OutlineNameTable_Destroy(lpOutlineDoc->m_lpNameTable); + +#if defined( USE_HEADING ) + if (! lpOutlineDoc->m_fDataTransferDoc) + Heading_Destroy((LPHEADING)&lpOutlineDoc->m_heading); +#endif + +#if defined( USE_FRAMETOOLS ) + if (! lpOutlineDoc->m_fDataTransferDoc) + FrameTools_AssociateDoc(lpOutlineDoc->m_lpFrameTools, NULL); +#endif // USE_FRAMETOOLS + + DestroyWindow(lpOutlineDoc->m_hWndDoc); + Delete(lpOutlineDoc); // free memory for doc itself + OleDbgOut1("@@@@ DOC DESTROYED\r\n"); + +#if defined( OLE_VERSION ) + OleApp_Release(lpOleApp); // release artificial AddRef above +#endif + + OLEDBG_END3 +} + + +/* OutlineDoc_ReSize + * ----------------- + * + * Resize the document and its components + * + * Parameter: + * lpRect the new size of the document. Use current size if NULL + */ +void OutlineDoc_Resize(LPOUTLINEDOC lpOutlineDoc, LPRECT lpRect) +{ + RECT rect; + LPLINELIST lpLL; + +#if defined( USE_HEADING ) + LPHEADING lphead; +#endif // USE_HEADING + + LPSCALEFACTOR lpscale; + HWND hWndLL; + + if (!lpOutlineDoc) + return; + + lpLL = (LPLINELIST)&lpOutlineDoc->m_LineList; + lpscale = (LPSCALEFACTOR)&lpOutlineDoc->m_scale; + hWndLL = LineList_GetWindow(lpLL); + + if (lpRect) { + CopyRect((LPRECT)&rect, lpRect); + MoveWindow(lpOutlineDoc->m_hWndDoc, rect.left, rect.top, + rect.right-rect.left, rect.bottom-rect.top, TRUE); + } + + GetClientRect(lpOutlineDoc->m_hWndDoc, (LPRECT)&rect); + +#if defined( USE_HEADING ) + lphead = OutlineDoc_GetHeading(lpOutlineDoc); + rect.left += Heading_RH_GetWidth(lphead, lpscale); + rect.top += Heading_CH_GetHeight(lphead, lpscale); +#endif // USE_HEADING + + if (lpLL) { + MoveWindow(hWndLL, rect.left, rect.top, + rect.right-rect.left, rect.bottom-rect.top, TRUE); + } + +#if defined( USE_HEADING ) + if (lphead) + Heading_Move(lphead, lpOutlineDoc->m_hWndDoc, lpscale); +#endif // USE_HEADING + +#if defined( INPLACE_CNTR ) + ContainerDoc_UpdateInPlaceObjectRects((LPCONTAINERDOC)lpOutlineDoc, 0); +#endif +} + + +/* OutlineDoc_GetNameTable + * ----------------------- + * + * Get nametable associated with the line list + */ +LPOUTLINENAMETABLE OutlineDoc_GetNameTable(LPOUTLINEDOC lpOutlineDoc) +{ + if (!lpOutlineDoc) + return NULL; + else + return lpOutlineDoc->m_lpNameTable; +} + + +/* OutlineDoc_GetLineList + * ---------------------- + * + * Get listlist associated with the OutlineDoc + */ +LPLINELIST OutlineDoc_GetLineList(LPOUTLINEDOC lpOutlineDoc) +{ + if (!lpOutlineDoc) + return NULL; + else + return (LPLINELIST)&lpOutlineDoc->m_LineList; +} + + +/* OutlineDoc_GetNameCount + * ----------------------- + * + * Return number of names in table + */ +int OutlineDoc_GetNameCount(LPOUTLINEDOC lpOutlineDoc) +{ + return OutlineNameTable_GetCount(lpOutlineDoc->m_lpNameTable); +} + + +/* OutlineDoc_GetLineCount + * ----------------------- + * + * Return number of lines in the LineList + */ +int OutlineDoc_GetLineCount(LPOUTLINEDOC lpOutlineDoc) +{ + return LineList_GetCount(&lpOutlineDoc->m_LineList); +} + + +/* OutlineDoc_SetFileName + * ---------------------- + * + * Set the filename of a document. + * + * OLE2NOTE: If the ServerDoc has a valid filename then, the object is + * registered in the running object table (ROT). if the name of the doc + * changes (eg. via SaveAs) then the previous registration must be revoked + * and the document re-registered under the new name. + */ +BOOL OutlineDoc_SetFileName(LPOUTLINEDOC lpOutlineDoc, LPSTR lpszNewFileName, LPSTORAGE lpNewStg) +{ + OleDbgAssertSz(lpszNewFileName != NULL, "Can't reset doc to Untitled!"); + if (lpszNewFileName == NULL) + return FALSE; + + AnsiLowerBuff(lpszNewFileName, (UINT)lstrlen(lpszNewFileName)); + +#if defined( OLE_CNTR ) + { + LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOutlineDoc; + LPOLEDOC lpOleDoc = (LPOLEDOC)lpOutlineDoc; + + /* OLE2NOTE: the container version of the application keeps its + ** storage open at all times. if the document's storage is not + ** open, then open it. + */ + + if (lpNewStg) { + + /* CASE 1 -- document is being loaded from a file. lpNewStg is + ** still open from the OutlineDoc_LoadFromFile function. + */ + + lpOutlineDoc->m_docInitType = DOCTYPE_FROMFILE; + + } else { + + /* CASE 2 -- document is being associated with a valid file + ** that is not yet open. thus we must now open the file. + */ + + if (lpOutlineDoc->m_docInitType == DOCTYPE_FROMFILE && + lstrcmp(lpOutlineDoc->m_szFileName,lpszNewFileName)==0) { + + /* CASE 2a -- new filename is same as current file. if the + ** stg is already open, then the lpStg is still valid. + ** if it is not open, then open it. + */ + if (! lpOleDoc->m_lpStg) { + lpOleDoc->m_lpStg = OleStdOpenRootStorage( + lpszNewFileName, + STGM_READWRITE | STGM_SHARE_DENY_WRITE + ); + if (! lpOleDoc->m_lpStg) return FALSE; + } + + } else { + + /* CASE 2b -- new filename is NOT same as current file. + ** a SaveAs operation is pending. open the new file and + ** hold the storage pointer in m_lpNewStg. the + ** subsequent call to Doc_SaveToFile will save the + ** document into the new storage pointer and release the + ** old storage pointer. + */ + + lpOutlineDoc->m_docInitType = DOCTYPE_FROMFILE; + + lpContainerDoc->m_lpNewStg = OleStdCreateRootStorage( + lpszNewFileName, + STGM_READWRITE | STGM_SHARE_DENY_WRITE | STGM_CREATE + ); + if (! lpContainerDoc->m_lpNewStg) return FALSE; + } + } + } +#endif // OLE_CNTR + + if (lpOutlineDoc->m_docInitType != DOCTYPE_FROMFILE || + lstrcmp(lpOutlineDoc->m_szFileName, lpszNewFileName) != 0) { + + /* A new valid file name is being associated with the document */ + + lstrcpy(lpOutlineDoc->m_szFileName, lpszNewFileName); + lpOutlineDoc->m_docInitType = DOCTYPE_FROMFILE; + + // set lpszDocTitle to point to filename without path + lpOutlineDoc->m_lpszDocTitle = lpOutlineDoc->m_szFileName + + lstrlen(lpOutlineDoc->m_szFileName) - 1; + while (lpOutlineDoc->m_lpszDocTitle > lpOutlineDoc->m_szFileName + && ! IS_FILENAME_DELIM(lpOutlineDoc->m_lpszDocTitle[-1])) { + lpOutlineDoc->m_lpszDocTitle--; + } + + OutlineDoc_SetTitle(lpOutlineDoc, TRUE /*fMakeUpperCase*/); + +#if defined( OLE_VERSION ) + { + /* OLE2NOTE: both containers and servers must properly + ** register in the RunningObjectTable. if the document + ** is performing a SaveAs operation, then it must + ** re-register in the ROT with the new moniker. in + ** addition any embedded object, pseudo objects, and/or + ** linking clients must be informed that the document's + ** moniker has changed. + */ + + LPOLEDOC lpOleDoc = (LPOLEDOC)lpOutlineDoc; + + if (lpOleDoc->m_lpFileMoniker) { + OleStdRelease((LPUNKNOWN)lpOleDoc->m_lpFileMoniker); + lpOleDoc->m_lpFileMoniker = NULL; + } + + CreateFileMonikerA(lpszNewFileName, + &lpOleDoc->m_lpFileMoniker); + + OleDoc_DocRenamedUpdate(lpOleDoc, lpOleDoc->m_lpFileMoniker); + } +#endif // OLE_VERSION + + } + + return TRUE; +} + + +/* OutlineDoc_SetTitle + * ------------------- + * + * Set window text to be current filename. + * The following window hierarchy exits: + * hWndApp + * hWndDoc + * hWndListBox + * The frame window is the window which gets the title. + */ +void OutlineDoc_SetTitle(LPOUTLINEDOC lpOutlineDoc, BOOL fMakeUpperCase) +{ + HWND hWnd; + LPSTR lpszText; + + if (!lpOutlineDoc->m_hWndDoc) return; + if ((hWnd = GetParent(lpOutlineDoc->m_hWndDoc)) == NULL) return; + + lpszText = OleStdMalloc((UINT)(lstrlen(APPNAME) + 4 + + lstrlen(lpOutlineDoc->m_lpszDocTitle))); + if (!lpszText) return; + + lstrcpy(lpszText, APPNAME); + lstrcat(lpszText," - "); + lstrcat(lpszText, (LPSTR)lpOutlineDoc->m_lpszDocTitle); + + if (fMakeUpperCase) + AnsiUpperBuff(lpszText, (UINT)lstrlen(lpszText)); + + SetWindowText(hWnd,lpszText); + OleStdFree(lpszText); +} + + +/* OutlineDoc_Close + * ---------------- + * + * Close active document. If modified, prompt the user if + * he wants to save. + * + * Returns: + * FALSE -- user canceled the closing of the doc. + * TRUE -- the doc was successfully closed + */ +BOOL OutlineDoc_Close(LPOUTLINEDOC lpOutlineDoc, DWORD dwSaveOption) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + +#if defined( OLE_VERSION ) + /* OLE2NOTE: call OLE specific function instead */ + return OleDoc_Close((LPOLEDOC)lpOutlineDoc, dwSaveOption); + +#else + + if (! lpOutlineDoc) + return TRUE; // active doc's are already destroyed + + if (! OutlineDoc_CheckSaveChanges(lpOutlineDoc, &dwSaveOption)) + return FALSE; // abort closing the doc + + OutlineDoc_Destroy(lpOutlineDoc); + + OutlineApp_DocUnlockApp(lpOutlineApp, lpOutlineDoc); + + return TRUE; + +#endif // ! OLE_VERSION +} + + +/* OutlineDoc_CheckSaveChanges + * --------------------------- + * + * Check if the document has been modified. if so, prompt the user if + * the changes should be saved. if yes save them. + * Returns TRUE if the doc is safe to close (user answered Yes or No) + * FALSE if the user canceled the save changes option. + */ +BOOL OutlineDoc_CheckSaveChanges( + LPOUTLINEDOC lpOutlineDoc, + LPDWORD lpdwSaveOption +) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + int nResponse; + + if (*lpdwSaveOption == OLECLOSE_NOSAVE) + return TRUE; + + if(! OutlineDoc_IsModified(lpOutlineDoc)) + return TRUE; // saving is not necessary + + /* OLE2NOTE: our document is dirty so it needs to be saved. if + ** OLECLOSE_PROMPTSAVE the user should be prompted to see if the + ** document should be saved. is specified but the document is NOT + ** visible to the user, then the user can NOT be prompted. in + ** the situation the document should be saved without prompting. + ** if OLECLOSE_SAVEIFDIRTY is specified then, the document + ** should also be saved without prompting. + */ + if (*lpdwSaveOption == OLECLOSE_PROMPTSAVE && + IsWindowVisible(lpOutlineDoc->m_hWndDoc)) { + + // prompt the user to see if changes should be saved. +#if defined( OLE_VERSION ) + OleApp_PreModalDialog( + (LPOLEAPP)lpOutlineApp, (LPOLEDOC)lpOutlineApp->m_lpDoc); +#endif + nResponse = MessageBox( + lpOutlineApp->m_hWndApp, + MsgSaveFile, + APPNAME, + MB_ICONQUESTION | MB_YESNOCANCEL + ); +#if defined( OLE_VERSION ) + OleApp_PostModalDialog( + (LPOLEAPP)lpOutlineApp, (LPOLEDOC)lpOutlineApp->m_lpDoc); +#endif + if(nResponse==IDCANCEL) + return FALSE; // close is canceled + if(nResponse==IDNO) { + // Reset the save option to NOSAVE per user choice + *lpdwSaveOption = OLECLOSE_NOSAVE; + return TRUE; // don't save, but is ok to close + } + } else if (*lpdwSaveOption != OLECLOSE_SAVEIFDIRTY) { + OleDbgAssertSz(FALSE, "Invalid dwSaveOption\r\n"); + *lpdwSaveOption = OLECLOSE_NOSAVE; + return TRUE; // unknown *lpdwSaveOption; close w/o saving + } + +#if defined( OLE_SERVER ) + if (lpOutlineDoc->m_docInitType == DOCTYPE_EMBEDDED) { + LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOutlineDoc; + HRESULT hrErr; + + /* OLE2NOTE: Update the container before closing without prompting + ** the user. To update the container, we must ask our container + ** to save us. + */ + OleDbgAssert(lpServerDoc->m_lpOleClientSite != NULL); + OLEDBG_BEGIN2("IOleClientSite::SaveObject called\r\n") + hrErr = lpServerDoc->m_lpOleClientSite->lpVtbl->SaveObject( + lpServerDoc->m_lpOleClientSite + ); + OLEDBG_END2 + + if (hrErr != NOERROR) { + OleDbgOutHResult("IOleClientSite::SaveObject returned", hrErr); + return FALSE; + } + + return TRUE; // doc is safe to be closed + + } else +#endif // OLE_SERVER + { + return OutlineApp_SaveCommand(lpOutlineApp); + } +} + + +/* OutlineDoc_IsModified + * --------------------- + * + * Return modify flag of OUTLINEDOC + */ +BOOL OutlineDoc_IsModified(LPOUTLINEDOC lpOutlineDoc) +{ + if (lpOutlineDoc->m_fModified) + return lpOutlineDoc->m_fModified; + +#if defined( OLE_CNTR ) + { + /* OLE2NOTE: if there are OLE objects, then we must ask if any of + ** them are dirty. if so we must consider our document + ** as modified. + */ + LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOutlineDoc; + LPLINELIST lpLL; + int nLines; + int nIndex; + LPLINE lpLine; + HRESULT hrErr; + + lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpContainerDoc)->m_LineList; + nLines = LineList_GetCount(lpLL); + + for (nIndex = 0; nIndex < nLines; nIndex++) { + lpLine = LineList_GetLine(lpLL, nIndex); + if (!lpLine) + break; + if (Line_GetLineType(lpLine) == CONTAINERLINETYPE) { + LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)lpLine; + if (lpContainerLine->m_lpPersistStg) { + hrErr = lpContainerLine->m_lpPersistStg->lpVtbl->IsDirty( + lpContainerLine->m_lpPersistStg); + /* OLE2NOTE: we will only accept an explicit "no i + ** am NOT dirty statement" (ie. S_FALSE) as an + ** indication that the object is clean. eg. if + ** the object returns E_NOTIMPL we must + ** interpret it as the object IS dirty. + */ + if (GetScode(hrErr) != S_FALSE) + return TRUE; + } + } + } + } +#endif + return FALSE; +} + + +/* OutlineDoc_SetModified + * ---------------------- + * + * Set the modified flag of the document + * + */ +void OutlineDoc_SetModified(LPOUTLINEDOC lpOutlineDoc, BOOL fModified, BOOL fDataChanged, BOOL fSizeChanged) +{ + lpOutlineDoc->m_fModified = fModified; + +#if defined( OLE_SERVER ) + if (! lpOutlineDoc->m_fDataTransferDoc) { + LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOutlineDoc; + + /* OLE2NOTE: if the document has changed, then broadcast the change + ** to all clients who have set up Advise connections. notify + ** them that our data (and possibly also our extents) have + ** changed. + */ + if (fDataChanged) { + lpServerDoc->m_fDataChanged = TRUE; + lpServerDoc->m_fSizeChanged = fSizeChanged; + lpServerDoc->m_fSendDataOnStop = TRUE; + + ServerDoc_SendAdvise( + lpServerDoc, + OLE_ONDATACHANGE, + NULL, /* lpmkDoc -- not relevant here */ + 0 /* advf -- no flags necessary */ + ); + } + } +#endif // OLE_SERVER +} + + +/* OutlineDoc_SetRedraw + * -------------------- + * + * Enable/Disable the redraw of the document on screen. + * The calls to SetRedraw counted so that nested calls can be handled + * properly. calls to SetRedraw must be balanced. + * + * fEnbaleDraw = TRUE - enable redraw + * FALSE - disable redraw + */ +void OutlineDoc_SetRedraw(LPOUTLINEDOC lpOutlineDoc, BOOL fEnableDraw) +{ + static HCURSOR hPrevCursor = NULL; + + if (fEnableDraw) { + if (lpOutlineDoc->m_nDisableDraw == 0) + return; // already enabled; no state transition + + if (--lpOutlineDoc->m_nDisableDraw > 0) + return; // drawing should still be disabled + } else { + if (lpOutlineDoc->m_nDisableDraw++ > 0) + return; // already disabled; no state transition + } + + if (lpOutlineDoc->m_nDisableDraw > 0) { + // this may take a while, put up hourglass cursor + hPrevCursor = SetCursor(LoadCursor(NULL, IDC_WAIT)); + } else { + if (hPrevCursor) { + SetCursor(hPrevCursor); // restore original cursor + hPrevCursor = NULL; + } + } + +#if defined( OLE_SERVER ) + /* OLE2NOTE: for the Server version, while Redraw is disabled + ** postpone sending advise notifications until Redraw is re-enabled. + */ + { + LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOutlineDoc; + LPSERVERNAMETABLE lpServerNameTable = + (LPSERVERNAMETABLE)lpOutlineDoc->m_lpNameTable; + + if (lpOutlineDoc->m_nDisableDraw == 0) { + /* drawing is being Enabled. if changes occurred while drawing + ** was disabled, then notify clients now. + */ + if (lpServerDoc->m_fDataChanged) + ServerDoc_SendAdvise( + lpServerDoc, + OLE_ONDATACHANGE, + NULL, /* lpmkDoc -- not relevant here */ + 0 /* advf -- no flags necessary */ + ); + + /* OLE2NOTE: send pending change notifications for pseudo objs. */ + ServerNameTable_SendPendingAdvises(lpServerNameTable); + + } + } +#endif // OLE_SERVER + +#if defined( OLE_CNTR ) + /* OLE2NOTE: for the Container version, while Redraw is disabled + ** postpone updating the extents of OLE objects until Redraw is + ** re-enabled. + */ + { + LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOutlineDoc; + + /* Update the extents of any OLE object that is marked that + ** its size may have changed. when an + ** IAdviseSink::OnViewChange notification is received, + ** the corresponding ContainerLine is marked + ** (m_fDoGetExtent==TRUE) and a message + ** (WM_U_UPDATEOBJECTEXTENT) is posted to the document + ** indicating that there are dirty objects. + */ + if (lpOutlineDoc->m_nDisableDraw == 0) + ContainerDoc_UpdateExtentOfAllOleObjects(lpContainerDoc); + } +#endif // OLE_CNTR + + // enable/disable redraw of the LineList listbox + LineList_SetRedraw(&lpOutlineDoc->m_LineList, fEnableDraw); +} + + +/* OutlineDoc_SetSel + * ----------------- + * + * Set the selection in the documents's LineList + */ +void OutlineDoc_SetSel(LPOUTLINEDOC lpOutlineDoc, LPLINERANGE lplrSel) +{ + LineList_SetSel(&lpOutlineDoc->m_LineList, lplrSel); +} + + +/* OutlineDoc_GetSel + * ----------------- + * + * Get the selection in the documents's LineList. + * + * Returns the count of items selected + */ +int OutlineDoc_GetSel(LPOUTLINEDOC lpOutlineDoc, LPLINERANGE lplrSel) +{ + return LineList_GetSel(&lpOutlineDoc->m_LineList, lplrSel); +} + + +/* OutlineDoc_ForceRedraw + * ---------------------- + * + * Force the document window to repaint. + */ +void OutlineDoc_ForceRedraw(LPOUTLINEDOC lpOutlineDoc, BOOL fErase) +{ + if (!lpOutlineDoc) + return; + + LineList_ForceRedraw(&lpOutlineDoc->m_LineList, fErase); + Heading_CH_ForceRedraw(&lpOutlineDoc->m_heading, fErase); + Heading_RH_ForceRedraw(&lpOutlineDoc->m_heading, fErase); +} + + +/* OutlineDoc_RenderFormat + * ----------------------- + * + * Render a clipboard format supported by ClipboardDoc + */ +void OutlineDoc_RenderFormat(LPOUTLINEDOC lpOutlineDoc, UINT uFormat) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + HGLOBAL hData = NULL; + + if (uFormat == lpOutlineApp->m_cfOutline) + hData = OutlineDoc_GetOutlineData(lpOutlineDoc, NULL); + + else if (uFormat == CF_TEXT) + hData = OutlineDoc_GetTextData(lpOutlineDoc, NULL); + + else { + OutlineApp_ErrorMessage(lpOutlineApp, ErrMsgFormatNotSupported); + return; + } + + SetClipboardData(uFormat, hData); +} + + +/* OutlineDoc_RenderAllFormats + * --------------------------- + * + * Render all formats supported by ClipboardDoc + */ +void OutlineDoc_RenderAllFormats(LPOUTLINEDOC lpOutlineDoc) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + HGLOBAL hData = NULL; + + OpenClipboard(lpOutlineDoc->m_hWndDoc); + + hData = OutlineDoc_GetOutlineData(lpOutlineDoc, NULL); + SetClipboardData(lpOutlineApp->m_cfOutline, hData); + + hData = OutlineDoc_GetTextData(lpOutlineDoc, NULL); + SetClipboardData(CF_TEXT, hData); + + CloseClipboard(); +} + + + +/* OutlineDoc_GetOutlineData + * ------------------------- + * + * Return a handle to an array of TextLine objects for the desired line + * range. + * NOTE: if lplrSel == NULL, then all lines are returned + * + */ +HGLOBAL OutlineDoc_GetOutlineData(LPOUTLINEDOC lpOutlineDoc, LPLINERANGE lplrSel) +{ + HGLOBAL hOutline = NULL; + LPLINELIST lpLL=(LPLINELIST)&lpOutlineDoc->m_LineList; + LPLINE lpLine; + LPTEXTLINE arrLine; + int i; + int nStart = (lplrSel ? lplrSel->m_nStartLine : 0); + int nEnd =(lplrSel ? lplrSel->m_nEndLine : LineList_GetCount(lpLL)-1); + int nLines = nEnd - nStart + 1; + int nCopied = 0; + + hOutline=GlobalAlloc(GMEM_SHARE | GMEM_ZEROINIT,sizeof(TEXTLINE)*nLines); + + if (! hOutline) return NULL; + + arrLine=(LPTEXTLINE)GlobalLock(hOutline); + + for (i = nStart; i <= nEnd; i++) { + lpLine=LineList_GetLine(lpLL, i); + if (lpLine && Line_GetOutlineData(lpLine, &arrLine[nCopied])) + nCopied++; + } + + GlobalUnlock(hOutline); + + return hOutline; +} + + + +/* OutlineDoc_GetTextData + * ---------------------- + * + * Return a handle to an object's data in text form for the desired line + * range. + * NOTE: if lplrSel == NULL, then all lines are returned + * + */ +HGLOBAL OutlineDoc_GetTextData(LPOUTLINEDOC lpOutlineDoc, LPLINERANGE lplrSel) +{ + LPLINELIST lpLL=(LPLINELIST)&lpOutlineDoc->m_LineList; + LPLINE lpLine; + HGLOBAL hText = NULL; + LPSTR lpszText = NULL; + DWORD dwMemSize=0; + int i,j; + int nStart = (lplrSel ? lplrSel->m_nStartLine : 0); + int nEnd =(lplrSel ? lplrSel->m_nEndLine : LineList_GetCount(lpLL)-1); + int nTabLevel; + + // calculate memory size required + for(i = nStart; i <= nEnd; i++) { + lpLine=LineList_GetLine(lpLL, i); + if (! lpLine) + continue; + + dwMemSize += Line_GetTabLevel(lpLine); + dwMemSize += Line_GetTextLen(lpLine); + + dwMemSize += 2; // add 1 for '\r\n' at the end of each line + } + dwMemSize++; // add 1 for '\0' at the end of string + + if(!(hText = GlobalAlloc(GMEM_SHARE | GMEM_ZEROINIT, dwMemSize))) + return NULL; + + if(!(lpszText = (LPSTR)GlobalLock(hText))) + return NULL; + + // put line text to memory + for(i = nStart; i <= nEnd; i++) { + lpLine=LineList_GetLine(lpLL, i); + if (! lpLine) + continue; + + nTabLevel=Line_GetTabLevel(lpLine); + for(j = 0; j < nTabLevel; j++) + *lpszText++='\t'; + + Line_GetTextData(lpLine, lpszText); + while(*lpszText) + lpszText++; // advance to end of string + + *lpszText++ = '\r'; + *lpszText++ = '\n'; + } + + GlobalUnlock (hText); + + return hText; +} + + +/* OutlineDoc_SaveToFile + * --------------------- + * + * Save the document to a file with the same name as stored in the + * document + */ +BOOL OutlineDoc_SaveToFile(LPOUTLINEDOC lpOutlineDoc, LPCSTR lpszFileName, UINT uFormat, BOOL fRemember) +{ +#if defined( OLE_CNTR ) + // Call OLE container specific function instead + return ContainerDoc_SaveToFile( + (LPCONTAINERDOC)lpOutlineDoc, + lpszFileName, + uFormat, + fRemember + ); + +#else + + LPSTORAGE lpDestStg = NULL; + HRESULT hrErr; + BOOL fStatus; + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + + if (fRemember) { + if (lpszFileName) { + fStatus = OutlineDoc_SetFileName( + lpOutlineDoc, + (LPSTR)lpszFileName, + NULL + ); + if (! fStatus) goto error; + } else + lpszFileName = lpOutlineDoc->m_szFileName; // use cur. file name + } else if (! lpszFileName) { + goto error; + } + + hrErr = StgCreateDocfileA( + lpszFileName, + STGM_READWRITE|STGM_DIRECT|STGM_SHARE_EXCLUSIVE|STGM_CREATE, + 0, + &lpDestStg + ); + + OleDbgAssertSz(hrErr == NOERROR, "Could not create Docfile"); + if (hrErr != NOERROR) + goto error; + +#if defined( OLE_SERVER ) + + /* OLE2NOTE: we must be sure to write our class ID into our + ** storage. this information is used by OLE to determine the + ** class of the data stored in our storage. Even for top + ** "file-level" objects this information should be written to + ** the file. + */ + if(WriteClassStg(lpDestStg, &CLSID_APP) != NOERROR) + goto error; +#endif + + fStatus = OutlineDoc_SaveSelToStg( + lpOutlineDoc, + NULL, + uFormat, + lpDestStg, + FALSE, /* fSameAsLoad */ + fRemember + ); + if (! fStatus) goto error; + + OleStdRelease((LPUNKNOWN)lpDestStg); + + if (fRemember) + OutlineDoc_SetModified(lpOutlineDoc, FALSE, FALSE, FALSE); + +#if defined( OLE_SERVER ) + + /* OLE2NOTE: (SERVER-ONLY) inform any linking clients that the + ** document has been saved. in addition, any currently active + ** pseudo objects should also inform their clients. + */ + ServerDoc_SendAdvise ( + (LPSERVERDOC)lpOutlineDoc, + OLE_ONSAVE, + NULL, /* lpmkDoc -- not relevant here */ + 0 /* advf -- not relevant here */ + ); + +#endif + + return TRUE; + +error: + if (lpDestStg) + OleStdRelease((LPUNKNOWN)lpDestStg); + + OutlineApp_ErrorMessage(lpOutlineApp, ErrMsgSaving); + return FALSE; + +#endif // ! OLE_CNTR +} + + +/* OutlineDoc_LoadFromFile + * ----------------------- + * + * Load a document from a file + */ +BOOL OutlineDoc_LoadFromFile(LPOUTLINEDOC lpOutlineDoc, LPSTR lpszFileName) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + LPLINELIST lpLL = &lpOutlineDoc->m_LineList; + HRESULT hrErr; + SCODE sc; + LPSTORAGE lpSrcStg; + BOOL fStatus; + + hrErr = StgOpenStorageA(lpszFileName, + NULL, +#if defined( OLE_CNTR ) + STGM_READWRITE | STGM_TRANSACTED | STGM_SHARE_DENY_WRITE, +#else + STGM_READ | STGM_SHARE_DENY_WRITE, +#endif + NULL, + 0, + &lpSrcStg + ); + + if ((sc = GetScode(hrErr)) == STG_E_FILENOTFOUND) { + OutlineApp_ErrorMessage(lpOutlineApp, "File not found"); + return FALSE; + } else if (sc == STG_E_FILEALREADYEXISTS) { + OutlineApp_ErrorMessage(lpOutlineApp, ErrMsgFormat); + return FALSE; + } else if (sc != S_OK) { + OleDbgOutScode("StgOpenStorage returned", sc); + OutlineApp_ErrorMessage( + lpOutlineApp, + "File already in use--could not be opened" + ); + return FALSE; + } + + if(! OutlineDoc_LoadFromStg(lpOutlineDoc, lpSrcStg)) goto error; + + fStatus = OutlineDoc_SetFileName(lpOutlineDoc, lpszFileName, lpSrcStg); + if (! fStatus) goto error; + + OleStdRelease((LPUNKNOWN)lpSrcStg); + + return TRUE; + +error: + OleStdRelease((LPUNKNOWN)lpSrcStg); + OutlineApp_ErrorMessage(lpOutlineApp, ErrMsgOpening); + return FALSE; +} + + + +/* OutlineDoc_LoadFromStg + * ---------------------- + * + * Load entire document from an open IStorage pointer (lpSrcStg) + * Return TRUE if ok, FALSE if error. + */ +BOOL OutlineDoc_LoadFromStg(LPOUTLINEDOC lpOutlineDoc, LPSTORAGE lpSrcStg) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + HRESULT hrErr; + BOOL fStatus; + ULONG nRead; + LINERANGE lrSel = { 0, 0 }; + LPSTREAM lpLLStm; + OUTLINEDOCHEADER_ONDISK docRecordOnDisk; + OUTLINEDOCHEADER docRecord; + + hrErr = CallIStorageOpenStreamA( + lpSrcStg, + "LineList", + NULL, + STGM_READ | STGM_SHARE_EXCLUSIVE, + 0, + &lpLLStm + ); + + if (hrErr != NOERROR) { + OleDbgOutHResult("Open LineList Stream returned", hrErr); + goto error; + } + + /* read OutlineDoc header record */ + hrErr = lpLLStm->lpVtbl->Read( + lpLLStm, + (LPVOID)&docRecordOnDisk, + sizeof(docRecordOnDisk), + &nRead + ); + + if (hrErr != NOERROR) { + OleDbgOutHResult("Read OutlineDoc header returned", hrErr); + goto error; + } + + // Transform docRecordOnDisk into docRecord + // Compilers should handle aligment correctly + strcpy(docRecord.m_szFormatName, docRecordOnDisk.m_szFormatName); + docRecord.m_narrAppVersionNo[0] = (int) docRecordOnDisk.m_narrAppVersionNo[0]; + docRecord.m_narrAppVersionNo[1] = (int) docRecordOnDisk.m_narrAppVersionNo[1]; + docRecord.m_fShowHeading = (BOOL) docRecordOnDisk.m_fShowHeading; + docRecord.m_reserved1 = docRecordOnDisk.m_reserved1; + docRecord.m_reserved2 = docRecordOnDisk.m_reserved2; + docRecord.m_reserved3 = docRecordOnDisk.m_reserved3; + docRecord.m_reserved4 = docRecordOnDisk.m_reserved4; + + fStatus = OutlineApp_VersionNoCheck( + lpOutlineApp, + docRecord.m_szFormatName, + docRecord.m_narrAppVersionNo + ); + + /* storage is an incompatible version; file can not be read */ + if (! fStatus) + goto error; + + lpOutlineDoc->m_heading.m_fShow = docRecord.m_fShowHeading; + +#if defined( OLE_SERVER ) + { + // Load ServerDoc specific data + LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOutlineDoc; +#if defined( SVR_TREATAS ) + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + CLSID clsid; + CLIPFORMAT cfFmt; + LPSTR lpszType; +#endif // SVR_TREATAS + + lpServerDoc->m_nNextRangeNo = (ULONG)docRecord.m_reserved1; + +#if defined( SVR_TREATAS ) + /* OLE2NOTE: if the Server is capable of supporting "TreatAs" + ** (aka. ActivateAs), it must read the class that is written + ** into the storage. if this class is NOT the app's own + ** class ID, then this is a TreatAs operation. the server + ** then must faithfully pretend to be the class that is + ** written into the storage. it must also faithfully write + ** the data back to the storage in the SAME format as is + ** written in the storage. + ** + ** SVROUTL and ISVROTL can emulate each other. they have the + ** simplification that they both read/write the identical + ** format. thus for these apps no actual conversion of the + ** native bits is actually required. + */ + lpServerDoc->m_clsidTreatAs = CLSID_NULL; + if (OleStdGetTreatAsFmtUserType(&CLSID_APP, lpSrcStg, &clsid, + (CLIPFORMAT FAR*)&cfFmt, (LPSTR FAR*)&lpszType)) { + + if (cfFmt == lpOutlineApp->m_cfOutline) { + // We should perform TreatAs operation + if (lpServerDoc->m_lpszTreatAsType) + OleStdFreeString(lpServerDoc->m_lpszTreatAsType, NULL); + + lpServerDoc->m_clsidTreatAs = clsid; + ((LPOUTLINEDOC)lpServerDoc)->m_cfSaveFormat = cfFmt; + lpServerDoc->m_lpszTreatAsType = lpszType; + + OleDbgOut3("OutlineDoc_LoadFromStg: TreateAs ==> '"); + OleDbgOutNoPrefix3(lpServerDoc->m_lpszTreatAsType); + OleDbgOutNoPrefix3("'\r\n"); + } else { + // ERROR: we ONLY support TreatAs for CF_OUTLINE format + OleDbgOut("SvrDoc_PStg_InitNew: INVALID TreatAs Format\r\n"); + OleStdFreeString(lpszType, NULL); + } + } +#endif // SVR_TREATAS + } +#endif // OLE_SVR +#if defined( OLE_CNTR ) + { + // Load ContainerDoc specific data + LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOutlineDoc; + + lpContainerDoc->m_nNextObjNo = (ULONG)docRecord.m_reserved2; + } +#endif // OLE_CNTR + + OutlineDoc_SetRedraw ( lpOutlineDoc, FALSE ); + + if(! LineList_LoadFromStg(&lpOutlineDoc->m_LineList, lpSrcStg, lpLLStm)) + goto error; + if(! OutlineNameTable_LoadFromStg(lpOutlineDoc->m_lpNameTable, lpSrcStg)) + goto error; + + OutlineDoc_SetModified(lpOutlineDoc, FALSE, FALSE, FALSE); + OutlineDoc_SetSel(lpOutlineDoc, &lrSel); + + OutlineDoc_SetRedraw ( lpOutlineDoc, TRUE ); + + OleStdRelease((LPUNKNOWN)lpLLStm); + +#if defined( OLE_CNTR ) + { + LPOLEDOC lpOleDoc = (LPOLEDOC)lpOutlineDoc; + + /* A ContainerDoc keeps its storage open at all times. it is necessary + * to AddRef the lpSrcStg in order to hang on to it. + */ + if (lpOleDoc->m_lpStg) { + OleStdVerifyRelease((LPUNKNOWN)lpOleDoc->m_lpStg, + "Doc Storage not released properly"); + } + lpSrcStg->lpVtbl->AddRef(lpSrcStg); + lpOleDoc->m_lpStg = lpSrcStg; + } +#endif // OLE_CNTR + + return TRUE; + +error: + OutlineDoc_SetRedraw ( lpOutlineDoc, TRUE ); + if (lpLLStm) + OleStdRelease((LPUNKNOWN)lpLLStm); + return FALSE; +} + +BOOL Booga(void) +{ + return FALSE; +} + + +/* OutlineDoc_SaveSelToStg + * ----------------------- + * + * Save the specified selection of document into an IStorage*. All lines + * within the selection along with any names completely contained within the + * selection will be written + * + * Return TRUE if ok, FALSE if error + */ +BOOL OutlineDoc_SaveSelToStg( + LPOUTLINEDOC lpOutlineDoc, + LPLINERANGE lplrSel, + UINT uFormat, + LPSTORAGE lpDestStg, + BOOL fSameAsLoad, + BOOL fRemember +) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + HRESULT hrErr = NOERROR; + LPSTREAM lpLLStm = NULL; + LPSTREAM lpNTStm = NULL; + ULONG nWritten; + BOOL fStatus; + OUTLINEDOCHEADER docRecord; + OUTLINEDOCHEADER_ONDISK docRecordOnDisk; + HCURSOR hPrevCursor; + +#if defined( OLE_VERSION ) + LPSTR lpszUserType; + LPOLEDOC lpOleDoc = (LPOLEDOC)lpOutlineDoc; + + /* OLE2NOTE: we must be sure to write the information required for + ** OLE into our docfile. this includes user type + ** name, data format, etc. Even for top "file-level" objects + ** this information should be written to the file. Both + ** containters and servers should write this information. + */ + +#if defined( OLE_SERVER ) && defined( SVR_TREATAS ) + LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOutlineDoc; + + /* OLE2NOTE: if the Server is emulating another class (ie. + ** "TreatAs" aka. ActivateAs), it must write the same user type + ** name and format that was was originally written into the + ** storage rather than its own user type name. + ** + ** SVROUTL and ISVROTL can emulate each other. they have the + ** simplification that they both read/write the identical + ** format. thus for these apps no actual conversion of the + ** native bits is actually required. + */ + if (! IsEqualCLSID(&lpServerDoc->m_clsidTreatAs, &CLSID_NULL)) + lpszUserType = lpServerDoc->m_lpszTreatAsType; + else +#endif // OLE_SERVER && SVR_TREATAS + + lpszUserType = (LPSTR)FULLUSERTYPENAME; + + hrErr = WriteFmtUserTypeStgA(lpDestStg, (CLIPFORMAT) uFormat, + lpszUserType); + + if(hrErr != NOERROR) goto error; + + if (fSameAsLoad) { + /* OLE2NOTE: we are saving into to same storage that we were + ** passed an load time. we deliberatly opened the streams we + ** need (lpLLStm and lpNTStm) at load time, so that we can + ** robustly save at save time in a low-memory situation. + ** this is particulary important the embedded objects do NOT + ** consume additional memory when + ** IPersistStorage::Save(fSameAsLoad==TRUE) is called. + */ + LARGE_INTEGER libZero; + ULARGE_INTEGER ulibZero; + LISet32( libZero, 0 ); + LISet32( ulibZero, 0 ); + lpLLStm = lpOleDoc->m_lpLLStm; + + /* because this is the fSameAsLoad==TRUE case, we will save + ** into the streams that we hold open. we will AddRef the + ** stream here so that the release below will NOT close the + ** stream. + */ + lpLLStm->lpVtbl->AddRef(lpLLStm); + + // truncate the current stream and seek to beginning + lpLLStm->lpVtbl->SetSize(lpLLStm, ulibZero); + lpLLStm->lpVtbl->Seek( + lpLLStm, libZero, STREAM_SEEK_SET, NULL); + + lpNTStm = lpOleDoc->m_lpNTStm; + lpNTStm->lpVtbl->AddRef(lpNTStm); // (see comment above) + + // truncate the current stream and seek to beginning + lpNTStm->lpVtbl->SetSize(lpNTStm, ulibZero); + lpNTStm->lpVtbl->Seek( + lpNTStm, libZero, STREAM_SEEK_SET, NULL); + } else +#endif // OLE_VERSION + { + hrErr = CallIStorageCreateStreamA( + lpDestStg, + "LineList", + STGM_WRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE, + 0, + 0, + &lpLLStm + ); + + if (hrErr != NOERROR) { + OleDbgAssertSz(hrErr==NOERROR,"Could not create LineList stream"); + OleDbgOutHResult("LineList CreateStream returned", hrErr); + goto error; + } + + hrErr = CallIStorageCreateStreamA( + lpDestStg, + "NameTable", + STGM_WRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE, + 0, + 0, + &lpNTStm + ); + + if (hrErr != NOERROR) { + OleDbgAssertSz(hrErr==NOERROR,"Could not create NameTable stream"); + OleDbgOutHResult("NameTable CreateStream returned", hrErr); + goto error; + } + } + + // this may take a while, put up hourglass cursor + hPrevCursor = SetCursor(LoadCursor(NULL, IDC_WAIT)); + + _fmemset((LPOUTLINEDOCHEADER)&docRecord,0,sizeof(OUTLINEDOCHEADER)); + GetClipboardFormatName( + uFormat, + docRecord.m_szFormatName, + sizeof(docRecord.m_szFormatName) + ); + OutlineApp_GetAppVersionNo(lpOutlineApp, docRecord.m_narrAppVersionNo); + + docRecord.m_fShowHeading = lpOutlineDoc->m_heading.m_fShow; + +#if defined( OLE_SERVER ) + { + // Store ServerDoc specific data + LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOutlineDoc; + + docRecord.m_reserved1 = (DWORD)lpServerDoc->m_nNextRangeNo; + } +#endif +#if defined( OLE_CNTR ) + { + // Store ContainerDoc specific data + LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOutlineDoc; + + docRecord.m_reserved2 = (DWORD)lpContainerDoc->m_nNextObjNo; + } +#endif + + /* write OutlineDoc header record */ + + // Transform docRecord into docRecordOnDisk + // Compilers should handle aligment correctly + strcpy(docRecordOnDisk.m_szFormatName, docRecord.m_szFormatName); + docRecordOnDisk.m_narrAppVersionNo[0] = (short) docRecord.m_narrAppVersionNo[0]; + docRecordOnDisk.m_narrAppVersionNo[1] = (short) docRecord.m_narrAppVersionNo[1]; + docRecordOnDisk.m_fShowHeading = (USHORT) docRecord.m_fShowHeading; + docRecordOnDisk.m_reserved1 = docRecord.m_reserved1; + docRecordOnDisk.m_reserved2 = docRecord.m_reserved2; + docRecordOnDisk.m_reserved3 = docRecord.m_reserved3; + docRecordOnDisk.m_reserved4 = docRecord.m_reserved4; + + hrErr = lpLLStm->lpVtbl->Write( + lpLLStm, + (LPVOID)&docRecordOnDisk, + sizeof(docRecordOnDisk), + &nWritten + ); + + if (hrErr != NOERROR) { + OleDbgOutHResult("Write OutlineDoc header returned", hrErr); + goto error; + } + + // Save LineList + /* OLE2NOTE: A ContainerDoc keeps its storage open at all times. It is + ** necessary to pass the current open storage (lpOleDoc->m_lpStg) + ** to the LineList_SaveSelToStg method so that currently written data + ** for any embeddings is also saved to the new destination + ** storage. The data required by a contained object is both the + ** ContainerLine information and the associated sub-storage that is + ** written directly by the embedded object. + */ + fStatus = LineList_SaveSelToStg( + &lpOutlineDoc->m_LineList, + lplrSel, + uFormat, +#if defined( OLE_CNTR ) + lpOleDoc->m_lpStg, +#else + NULL, +#endif + lpDestStg, + lpLLStm, + fRemember + ); + if (! fStatus) goto error; + + // Save associated NameTable + fStatus = OutlineNameTable_SaveSelToStg( + lpOutlineDoc->m_lpNameTable, + lplrSel, + uFormat, + lpNTStm + ); + + if (! fStatus) goto error; + + OleStdRelease((LPUNKNOWN)lpLLStm); + lpOutlineDoc->m_cfSaveFormat = uFormat; // remember format used to save + + SetCursor(hPrevCursor); // restore original cursor + return TRUE; + +error: + if (lpLLStm) + OleStdRelease((LPUNKNOWN)lpLLStm); + + SetCursor(hPrevCursor); // restore original cursor + return FALSE; +} + + +/* OutlineDoc_Print + * ---------------- + * Prints the contents of the list box in HIMETRIC mapping mode. Origin + * remains to be the upper left corner and the print proceeds down the + * page using a negative y-cordinate. + * + */ +void OutlineDoc_Print(LPOUTLINEDOC lpOutlineDoc, HDC hDC) +{ + LPLINELIST lpLL = &lpOutlineDoc->m_LineList; + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + WORD nIndex; + WORD nTotal; + int dy; + BOOL fError = FALSE; + LPLINE lpLine; + RECT rcLine; + RECT rcPix; + RECT rcHim; + RECT rcWindowOld; + RECT rcViewportOld; + HFONT hOldFont; + DOCINFO di; /* Document information for StartDoc function */ + + /* Get dimension of page */ + rcPix.left = 0; + rcPix.top = 0; + rcPix.right = GetDeviceCaps(hDC, HORZRES); + rcPix.bottom = GetDeviceCaps(hDC, VERTRES); + + SetDCToDrawInHimetricRect(hDC, (LPRECT)&rcPix, (LPRECT)&rcHim, + (LPRECT)&rcWindowOld, (LPRECT)&rcViewportOld); + + // Set the default font size, and font face name + hOldFont = SelectObject(hDC, lpOutlineApp->m_hStdFont); + + /* Get the lines in document */ + nIndex = 0; + nTotal = LineList_GetCount(lpLL); + + /* Create the Cancel dialog */ + // REVIEW: should load dialog title from string resource file + hWndPDlg = CreateDialog ( + lpOutlineApp->m_hInst, + "Print", + lpOutlineApp->m_hWndApp, + (DLGPROC)PrintDlgProc + ); + + if(!hWndPDlg) + goto getout; + + /* Allow the app. to inform GDI of the abort function to call */ + if(SetAbortProc(hDC, (ABORTPROC)AbortProc) < 0) { + fError = TRUE; + goto getout3; + } + + /* Disable the main application window */ + EnableWindow (lpOutlineApp->m_hWndApp, FALSE); + + // initialize the rectangle for the first line + rcLine.left = rcHim.left; + rcLine.bottom = rcHim.top; + + /* Initialize the document */ + fCancelPrint = FALSE; + + di.cbSize = sizeof(di); + di.lpszDocName = lpOutlineDoc->m_lpszDocTitle; + di.lpszOutput = NULL; + + if(StartDoc(hDC, (DOCINFO FAR*)&di) <= 0) { + fError = TRUE; + OleDbgOut2("StartDoc error\n"); + goto getout5; + } + + if(StartPage(hDC) <= 0) { // start first page + fError = TRUE; + OleDbgOut2("StartPage error\n"); + goto getout2; + } + + /* While more lines print out the text */ + while(nIndex < nTotal) { + lpLine = LineList_GetLine(lpLL, nIndex); + if (! lpLine) + continue; + + dy = Line_GetHeightInHimetric(lpLine); + + /* Reached end of page. Tell the device driver to eject a page */ + if(rcLine.bottom - dy < rcHim.bottom) { + if (EndPage(hDC) < 0) { + fError=TRUE; + OleDbgOut2("EndPage error\n"); + goto getout2; + } + + // NOTE: Reset the Mapping mode of DC + SetDCToDrawInHimetricRect(hDC, (LPRECT)&rcPix, (LPRECT)&rcHim, + (LPRECT)&rcWindowOld, (LPRECT)&rcViewportOld); + + // Set the default font size, and font face name + SelectObject(hDC, lpOutlineApp->m_hStdFont); + + if (StartPage(hDC) <= 0) { + fError=TRUE; + OleDbgOut2("StartPage error\n"); + goto getout2; + } + + rcLine.bottom = rcHim.top; + } + + rcLine.top = rcLine.bottom; + rcLine.bottom -= dy; + rcLine.right = rcLine.left + Line_GetWidthInHimetric(lpLine); + + /* Print the line */ + Line_Draw(lpLine, hDC, &rcLine, NULL, FALSE /*fHighlight*/); + + OleDbgOut2("a line is drawn\n"); + + /* Test and see if the Abort flag has been set. If yes, exit. */ + if (fCancelPrint) + goto getout2; + + /* Move down the page */ + nIndex++; + } + + { + int nCode; + + /* Eject the last page. */ + if((nCode = EndPage(hDC)) < 0) { +#if defined( _DEBUG ) + char szBuf[255]; + wsprintf(szBuf, "EndPage error code is %d\n", nCode); + OleDbgOut2(szBuf); +#endif + fError=TRUE; + goto getout2; + } + } + + + /* Complete the document. */ + if(EndDoc(hDC) < 0) { + fError=TRUE; + OleDbgOut2("EndDoc error\n"); + +getout2: + /* Ran into a problem before NEWFRAME? Abort the document */ + AbortDoc(hDC); + } + +getout5: + /* Re-enable main app. window */ + EnableWindow (lpOutlineApp->m_hWndApp, TRUE); + +getout3: + /* Close the cancel dialog */ + DestroyWindow (hWndPDlg); + +getout: + + /* Error? make sure the user knows... */ + if(fError || CommDlgExtendedError()) + OutlineApp_ErrorMessage(lpOutlineApp, ErrMsgPrint); + + SelectObject(hDC, hOldFont); +} + + + + + +/* OutlineDoc_DialogHelp + * --------------------- + * + * Show help message for ole2ui dialogs. + * + * Parameters: + * + * hDlg HWND to the dialog the help message came from - use + * this in the call to WinHelp/MessageBox so that + * activation/focus goes back to the dialog, and not the + * main window. + * + * wParam ID of the dialog (so we know what type of dialog it is). + */ +void OutlineDoc_DialogHelp(HWND hDlg, WPARAM wDlgID) +{ + + char szMessageBoxText[64]; + + if (!IsWindow(hDlg)) // don't do anything if we've got a bogus hDlg. + return; + + lstrcpy(szMessageBoxText, "Help Message for "); + + switch (wDlgID) + { + + case IDD_CONVERT: + lstrcat(szMessageBoxText, "Convert"); + break; + + case IDD_CHANGEICON: + lstrcat(szMessageBoxText, "Change Icon"); + break; + + case IDD_INSERTOBJECT: + lstrcat(szMessageBoxText, "Insert Object"); + break; + + case IDD_PASTESPECIAL: + lstrcat(szMessageBoxText, "Paste Special"); + break; + + case IDD_EDITLINKS: + lstrcat(szMessageBoxText, "Edit Links"); + break; + + case IDD_CHANGESOURCE: + lstrcat(szMessageBoxText, "Change Source"); + break; + + case IDD_INSERTFILEBROWSE: + lstrcat(szMessageBoxText, "Insert From File Browse"); + break; + + case IDD_CHANGEICONBROWSE: + lstrcat(szMessageBoxText, "Change Icon Browse"); + break; + + default: + lstrcat(szMessageBoxText, "Unknown"); + break; + } + + lstrcat(szMessageBoxText, " Dialog."); + + // You'd probably really a call to WinHelp here. + MessageBox(hDlg, szMessageBoxText, "Help", MB_OK); + + return; +} + + +/* OutlineDoc_SetCurrentZoomCommand + * -------------------------------- + * + * Set current zoom level to be checked in the menu. + * Set the corresponding scalefactor for the document. + */ +void OutlineDoc_SetCurrentZoomCommand( + LPOUTLINEDOC lpOutlineDoc, + UINT uCurrentZoom +) +{ + SCALEFACTOR scale; + + if (!lpOutlineDoc) + return; + + lpOutlineDoc->m_uCurrentZoom = uCurrentZoom; + + switch (uCurrentZoom) { + +#if !defined( OLE_CNTR ) + case IDM_V_ZOOM_400: + scale.dwSxN = (DWORD) 4; + scale.dwSxD = (DWORD) 1; + scale.dwSyN = (DWORD) 4; + scale.dwSyD = (DWORD) 1; + break; + + case IDM_V_ZOOM_300: + scale.dwSxN = (DWORD) 3; + scale.dwSxD = (DWORD) 1; + scale.dwSyN = (DWORD) 3; + scale.dwSyD = (DWORD) 1; + break; + + case IDM_V_ZOOM_200: + scale.dwSxN = (DWORD) 2; + scale.dwSxD = (DWORD) 1; + scale.dwSyN = (DWORD) 2; + scale.dwSyD = (DWORD) 1; + break; +#endif // !OLE_CNTR + + case IDM_V_ZOOM_100: + scale.dwSxN = (DWORD) 1; + scale.dwSxD = (DWORD) 1; + scale.dwSyN = (DWORD) 1; + scale.dwSyD = (DWORD) 1; + break; + + case IDM_V_ZOOM_75: + scale.dwSxN = (DWORD) 3; + scale.dwSxD = (DWORD) 4; + scale.dwSyN = (DWORD) 3; + scale.dwSyD = (DWORD) 4; + break; + + case IDM_V_ZOOM_50: + scale.dwSxN = (DWORD) 1; + scale.dwSxD = (DWORD) 2; + scale.dwSyN = (DWORD) 1; + scale.dwSyD = (DWORD) 2; + break; + + case IDM_V_ZOOM_25: + scale.dwSxN = (DWORD) 1; + scale.dwSxD = (DWORD) 4; + scale.dwSyN = (DWORD) 1; + scale.dwSyD = (DWORD) 4; + break; + } + + OutlineDoc_SetScaleFactor(lpOutlineDoc, (LPSCALEFACTOR)&scale, NULL); +} + + +/* OutlineDoc_GetCurrentZoomMenuCheck + * ---------------------------------- + * + * Get current zoom level to be checked in the menu. + */ +UINT OutlineDoc_GetCurrentZoomMenuCheck(LPOUTLINEDOC lpOutlineDoc) +{ + return lpOutlineDoc->m_uCurrentZoom; +} + + +/* OutlineDoc_SetScaleFactor + * ------------------------- + * + * Set the scale factor of the document which will affect the + * size of the document on the screen + * + * Parameters: + * + * scale structure containing x and y scales + */ +void OutlineDoc_SetScaleFactor( + LPOUTLINEDOC lpOutlineDoc, + LPSCALEFACTOR lpscale, + LPRECT lprcDoc +) +{ + LPLINELIST lpLL = OutlineDoc_GetLineList(lpOutlineDoc); + HWND hWndLL = LineList_GetWindow(lpLL); + + if (!lpOutlineDoc || !lpscale) + return; + + InvalidateRect(hWndLL, NULL, TRUE); + + lpOutlineDoc->m_scale = *lpscale; + LineList_ReScale((LPLINELIST)&lpOutlineDoc->m_LineList, lpscale); + +#if defined( USE_HEADING ) + Heading_ReScale((LPHEADING)&lpOutlineDoc->m_heading, lpscale); +#endif + + OutlineDoc_Resize(lpOutlineDoc, lprcDoc); +} + + +/* OutlineDoc_GetScaleFactor + * ------------------------- + * + * Retrieve the scale factor of the document + * + * Parameters: + * + */ +LPSCALEFACTOR OutlineDoc_GetScaleFactor(LPOUTLINEDOC lpOutlineDoc) +{ + if (!lpOutlineDoc) + return NULL; + + return (LPSCALEFACTOR)&lpOutlineDoc->m_scale; +} + + +/* OutlineDoc_SetCurrentMarginCommand + * ---------------------------------- + * + * Set current Margin level to be checked in the menu. + */ +void OutlineDoc_SetCurrentMarginCommand( + LPOUTLINEDOC lpOutlineDoc, + UINT uCurrentMargin +) +{ + if (!lpOutlineDoc) + return; + + lpOutlineDoc->m_uCurrentMargin = uCurrentMargin; + + switch (uCurrentMargin) { + case IDM_V_SETMARGIN_0: + OutlineDoc_SetMargin(lpOutlineDoc, 0, 0); + break; + + case IDM_V_SETMARGIN_1: + OutlineDoc_SetMargin(lpOutlineDoc, 1000, 1000); + break; + + case IDM_V_SETMARGIN_2: + OutlineDoc_SetMargin(lpOutlineDoc, 2000, 2000); + break; + + case IDM_V_SETMARGIN_3: + OutlineDoc_SetMargin(lpOutlineDoc, 3000, 3000); + break; + + case IDM_V_SETMARGIN_4: + OutlineDoc_SetMargin(lpOutlineDoc, 4000, 4000); + break; + } +} + + +/* OutlineDoc_GetCurrentMarginMenuCheck + * ------------------------------------ + * + * Get current Margin level to be checked in the menu. + */ +UINT OutlineDoc_GetCurrentMarginMenuCheck(LPOUTLINEDOC lpOutlineDoc) +{ + return lpOutlineDoc->m_uCurrentMargin; +} + + +/* OutlineDoc_SetMargin + * -------------------- + * + * Set the left and right margin of the document + * + * Parameters: + * nLeftMargin - left margin in Himetric values + * nRightMargin - right margin in Himetric values + */ +void OutlineDoc_SetMargin(LPOUTLINEDOC lpOutlineDoc, int nLeftMargin, int nRightMargin) +{ + LPLINELIST lpLL; + int nMaxWidthInHim; + + if (!lpOutlineDoc) + return; + + lpOutlineDoc->m_nLeftMargin = nLeftMargin; + lpOutlineDoc->m_nRightMargin = nRightMargin; + lpLL = OutlineDoc_GetLineList(lpOutlineDoc); + + // Force recalculation of Horizontal extent + nMaxWidthInHim = LineList_GetMaxLineWidthInHimetric(lpLL); + LineList_SetMaxLineWidthInHimetric(lpLL, -nMaxWidthInHim); + +#if defined( INPLACE_CNTR ) + ContainerDoc_UpdateInPlaceObjectRects((LPCONTAINERDOC)lpOutlineDoc, 0); +#endif + + OutlineDoc_ForceRedraw(lpOutlineDoc, TRUE); +} + + +/* OutlineDoc_GetMargin + * -------------------- + * + * Get the left and right margin of the document + * + * Parameters: + * nLeftMargin - left margin in Himetric values + * nRightMargin - right margin in Himetric values + * + * Returns: + * low order word - left margin + * high order word - right margin + */ +LONG OutlineDoc_GetMargin(LPOUTLINEDOC lpOutlineDoc) +{ + if (!lpOutlineDoc) + return 0; + + return MAKELONG(lpOutlineDoc->m_nLeftMargin, lpOutlineDoc->m_nRightMargin); +} + +#if defined( USE_HEADING ) + +/* OutlineDoc_GetHeading + * --------------------- + * + * Get Heading Object in OutlineDoc + */ +LPHEADING OutlineDoc_GetHeading(LPOUTLINEDOC lpOutlineDoc) +{ + if (!lpOutlineDoc || lpOutlineDoc->m_fDataTransferDoc) + return NULL; + else + return (LPHEADING)&lpOutlineDoc->m_heading; +} + + +/* OutlineDoc_ShowHeading + * ---------------------- + * + * Show/Hide document row/column headings. + */ +void OutlineDoc_ShowHeading(LPOUTLINEDOC lpOutlineDoc, BOOL fShow) +{ + LPHEADING lphead = OutlineDoc_GetHeading(lpOutlineDoc); +#if defined( INPLACE_SVR ) + LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOutlineDoc; +#endif + + if (! lphead) + return; + + Heading_Show(lphead, fShow); + +#if defined( INPLACE_SVR ) + if (lpServerDoc->m_fUIActive) { + LPINPLACEDATA lpIPData = lpServerDoc->m_lpIPData; + + /* OLE2NOTE: our extents have NOT changed; only our the size of + ** our object-frame adornments is changing. we can use the + ** current PosRect and ClipRect and simply resize our + ** windows WITHOUT informing our in-place container. + */ + ServerDoc_ResizeInPlaceWindow( + lpServerDoc, + (LPRECT)&(lpIPData->rcPosRect), + (LPRECT)&(lpIPData->rcClipRect) + ); + } else +#else // !INPLACE_SVR + + OutlineDoc_Resize(lpOutlineDoc, NULL); + +#if defined( INPLACE_CNTR ) + ContainerDoc_UpdateInPlaceObjectRects((LPCONTAINERDOC)lpOutlineDoc, 0); +#endif // INPLACE_CNTR + +#endif // INPLACE_SVR + + OutlineDoc_ForceRedraw(lpOutlineDoc, TRUE); +} + +#endif // USE_HEADING + + +/* AbortProc + * --------- + * AborProc is called by GDI print code to check for user abort. + */ +BOOL FAR PASCAL EXPORT AbortProc (HDC hdc, WORD reserved) +{ + MSG msg; + + /* Allow other apps to run, or get abort messages */ + while(! fCancelPrint && PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) { + if(!hWndPDlg || !IsDialogMessage (hWndPDlg, &msg)) { + TranslateMessage (&msg); + DispatchMessage (&msg); + } + } + return !fCancelPrint; +} + + +/* PrintDlgProc + * ------------ + * Dialog function for the print cancel dialog box. + * + * RETURNS : TRUE - OK to abort/ not OK to abort + * FALSE - otherwise. + */ +BOOL FAR PASCAL EXPORT PrintDlgProc( + HWND hwnd, + WORD msg, + WORD wParam, + LONG lParam +) +{ + switch (msg) { + case WM_COMMAND: + /* abort printing if the only button gets hit */ + fCancelPrint = TRUE; + return TRUE; + } + + return FALSE; +} diff --git a/private/oleutest/letest/outline/outline.h b/private/oleutest/letest/outline/outline.h new file mode 100644 index 000000000..4c3f4b88c --- /dev/null +++ b/private/oleutest/letest/outline/outline.h @@ -0,0 +1,790 @@ +/************************************************************************* +** +** OLE 2 Sample Code +** +** outline.h +** +** This file contains file contains data structure defintions, +** function prototypes, constants, etc. used by the Outline series +** of sample applications: +** Outline -- base version of the app (without OLE functionality) +** SvrOutl -- OLE 2.0 Server sample app +** CntrOutl -- OLE 2.0 Containter (Container) sample app +** ISvrOtl -- OLE 2.0 Server sample app +** CntrOutl -- OLE 2.0 Containter (Container) sample app +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +** For structures which we read from and write to disk we define shadow +** structures (with the _ONDISK suffix) that allow us to maintain +** 16-bit Windows and Macintosh compatibility. +** +*************************************************************************/ + +#if !defined( _OUTLINE_H_ ) +#define _OUTLINE_H_ + +#include + + +#if !defined( RC_INVOKED ) +#pragma message ("INCLUDING OUTLINE.H from " __FILE__) +#endif /* RC_INVOKED */ + +// use strict ANSI standard (for DVOBJ.H) +//#define NONAMELESSUNION + +// use system defined bitmap, this line must go before windows.h +#define OEMRESOURCE + +#ifdef WIN32 +#define _INC_OLE +// #define __RPC_H__ +#define EXPORT + +#define _fstrchr strchr + +#else +#define EXPORT _export +#endif + +#define SDI_VERSION 1 // ONLY SDI version is currently supported + +#if defined( OLE_SERVER ) || defined( OLE_CNTR ) +#define OLE_VERSION 1 +#define USE_DRAGDROP 1 // enable drag/drop code in OLE versions +#define USE_MSGFILTER 1 // enable IMessageFilter implementation +#endif + +#define USE_HEADING 1 // enable the row/col headings +#define USE_STATUSBAR 1 // enable status bar window +#define USE_FRAMETOOLS 1 // enable the toolbar +#ifndef WIN32 //BUGBUG32 +#define USE_CTL3D 1 // enable 3D looking dialogs +#endif + +#define STRICT 1 +#undef UNICODE +#include +#include +#include +#include +#include +#include +#include "outlrc.h" + + +#define APPMAJORVERSIONNO 3 // major no. incremented for major releases + // (eg. when an incompatible change is made + // to the storage format) +#define APPMINORVERSIONNO 5 // minor no. incremented for minor releases + + +/* Definition of SCALEFACTOR */ +typedef struct tagSCALEFACTOR { + ULONG dwSxN; // numerator in x direction + ULONG dwSxD; // denominator in x direction + ULONG dwSyN; // numerator in y direction + ULONG dwSyD; // denominator in y direction +} SCALEFACTOR, FAR* LPSCALEFACTOR; + + +#if defined( USE_FRAMETOOLS ) +#include "frametls.h" +#endif + +#if defined( USE_HEADING ) +#include "heading.h" +#endif + +/* max line height (in pixels) allowed in a listbox */ +#define LISTBOX_HEIGHT_LIMIT 255 + + +#define MAXSTRLEN 80 // max string len in bytes +#define MAXNAMESIZE 30 // max length of names +#define MAXFORMATSIZE 10 // max length of DEFDOCFORMAT (actually size is 5) +#define TABWIDTH 2000 // 2000 in Himetric units, i.e. 2cm +#define DEFFONTPTSIZE 12 +#define DEFFONTSIZE ((DEFFONTPTSIZE*HIMETRIC_PER_INCH)/PTS_PER_INCH) +#define DEFFONTFACE "Times New Roman" + +#define OUTLINEDOCFORMAT "Outline" // CF_Outline format name +#define IS_FILENAME_DELIM(c) ( (c) == '\\' || (c) == '/' || (c) == ':' ) +// REVIEW: some of these strings should be loaded from a resource file +#define UNTITLED "Outline" // title used for untitled document +#define HITTESTDELTA 5 + +/* Macro to get a random integer within a specified range */ +#define getrandom( min, max ) ((rand() % (int)(((max)+1) - (min))) + (min)) + + +// REVIEW: should load strings from string resource file + +#define APPFILENAMEFILTER "Outline Files (*.OLN)|*.oln|All files (*.*)|*.*|" +#define DEFEXTENSION "oln" // Default file extension + + +/* forward type references */ +typedef struct tagOUTLINEDOC FAR* LPOUTLINEDOC; +typedef struct tagTEXTLINE FAR* LPTEXTLINE; + + +typedef enum tagLINETYPE { + UNKNOWNLINETYPE, + TEXTLINETYPE, + CONTAINERLINETYPE +} LINETYPE; + + +/************************************************************************* +** class LINE +** The class LINE is an abstract base class. Instances of class LINE +** are NOT created; only instances of the concrete subclasses of +** LINE can be created. In the base app version and the OLE 2.0 +** server-only version only TEXTLINE objects can be created. In the +** OLE 2.0 client app version either TEXTLINE objects or CONTAINERLINE +** objects can be created. The LINE class has all fields and methods +** that are common independent of which subclass of LINE is used. +** Each LINE object that is created in added to the LINELIST of the +** OUTLINEDOC document. +*************************************************************************/ + +typedef struct tagLINE { + LINETYPE m_lineType; + UINT m_nTabLevel; + UINT m_nTabWidthInHimetric; + UINT m_nWidthInHimetric; + UINT m_nHeightInHimetric; + BOOL m_fSelected; // does line have selection feedback + +#if defined( USE_DRAGDROP ) + BOOL m_fDragOverLine; // does line have drop target feedback +#endif +} LINE, FAR* LPLINE; + +/* Line methods (functions) */ +void Line_Init(LPLINE lpLine, int nTab, HDC hDC); +void Line_Delete(LPLINE lpLine); +BOOL Line_CopyToDoc(LPLINE lpSrcLine, LPOUTLINEDOC lpDestDoc, int nIndex); +BOOL Line_Edit(LPLINE lpLine, HWND hWndDoc, HDC hDC); +void Line_Draw( + LPLINE lpLine, + HDC hDC, + LPRECT lpRect, + LPRECT lpRectWBounds, + BOOL fHighlight +); +void Line_DrawToScreen( + LPLINE lpLine, + HDC hDC, + LPRECT lprcPix, + UINT itemAction, + UINT itemState, + LPRECT lprcDevice +); +void Line_DrawSelHilight(LPLINE lpLine, HDC hDC, LPRECT lpRect, UINT itemAction, UINT itemState); +void Line_DrawFocusRect(LPLINE lpLine, HDC hDC, LPRECT lpRect, UINT itemAction, UINT itemState); +void Line_Unindent(LPLINE lpLine, HDC hDC); +void Line_Indent(LPLINE lpLine, HDC hDC); +LINETYPE Line_GetLineType(LPLINE lpLine); +UINT Line_GetTotalWidthInHimetric(LPLINE lpLine); +void Line_SetWidthInHimetric(LPLINE lpLine, int nWidth); +UINT Line_GetWidthInHimetric(LPLINE lpLine); +UINT Line_GetHeightInHimetric(LPLINE lpLine); +void Line_SetHeightInHimetric(LPLINE lpLine, int nHeight); +UINT Line_GetTabLevel(LPLINE lpLine); +int Line_GetTextLen(LPLINE lpLine); +void Line_GetTextData(LPLINE lpLine, LPSTR lpszBuf); +BOOL Line_GetOutlineData(LPLINE lpLine, LPTEXTLINE lpBuf); +int Line_CalcTabWidthInHimetric(LPLINE lpLine, HDC hDC); +BOOL Line_SaveToStg(LPLINE lpLine, UINT uFormat, LPSTORAGE lpSrcStg, LPSTORAGE lpDestStg, LPSTREAM lpLLStm, BOOL fRemember); +LPLINE Line_LoadFromStg(LPSTORAGE lpSrcStg, LPSTREAM lpLLStm, LPOUTLINEDOC lpDestDoc); +void Line_DrawDragFeedback(LPLINE lpLine, HDC hDC, LPRECT lpRect, UINT itemState ); +BOOL Line_IsSelected(LPLINE lpLine); + + +/************************************************************************* +** class TEXTLINE : LINE +** The class TEXTLINE is a concrete subclass of the abstract base +** class LINE. The TEXTLINE class holds a string that can be edited +** by the user. In the base app version and the OLE 2.0 +** server-only version only TEXTLINE objects can be created. In the +** OLE 2.0 client app version either TEXTLINE objects or CONTAINERLINE +** objects can be created. The TEXTLINE class inherits all fields +** from the LINE class. This inheritance is achieved by including a +** member variable of type LINE as the first field in the TEXTLINE +** structure. Thus a pointer to a TEXTLINE object can be cast to be +** a pointer to a LINE object. +** Each TEXTLINE object that is created in added to the LINELIST of +** the associated OUTLINEDOC document. +*************************************************************************/ + +typedef struct tagTEXTLINE { + LINE m_Line; // TextLine inherits all fields of Line + + UINT m_nLength; + char m_szText[MAXSTRLEN+1]; +} TEXTLINE; + +LPTEXTLINE TextLine_Create(HDC hDC, UINT nTab, LPSTR szText); +void TextLine_Init(LPTEXTLINE lpTextLine, int nTab, HDC hDC); +void TextLine_CalcExtents(LPTEXTLINE lpLine, HDC hDC); +void TextLine_SetHeightInHimetric(LPTEXTLINE lpTextLine, int nHeight); +void TextLine_Delete(LPTEXTLINE lpLine); +BOOL TextLine_Edit(LPTEXTLINE lpLine, HWND hWndDoc, HDC hDC); +void TextLine_Draw( + LPTEXTLINE lpTextLine, + HDC hDC, + LPRECT lpRect, + LPRECT lpRectWBounds, + BOOL fHighlight +); +void TextLine_DrawSelHilight(LPTEXTLINE lpTextLine, HDC hDC, LPRECT lpRect, UINT itemAction, UINT itemState); +BOOL TextLine_Copy(LPTEXTLINE lpSrcLine, LPTEXTLINE lpDestLine); +BOOL TextLine_CopyToDoc(LPTEXTLINE lpSrcLine, LPOUTLINEDOC lpDestDoc, int nIndex); +int TextLine_GetTextLen(LPTEXTLINE lpTextLine); +void TextLine_GetTextData(LPTEXTLINE lpTextLine, LPSTR lpszBuf); +BOOL TextLine_GetOutlineData(LPTEXTLINE lpTextLine, LPTEXTLINE lpBuf); +BOOL TextLine_SaveToStm(LPTEXTLINE lpLine, LPSTREAM lpLLStm); +LPLINE TextLine_LoadFromStg(LPSTORAGE lpSrcStg, LPSTREAM lpLLStm, LPOUTLINEDOC lpDestDoc); + + + +/************************************************************************* +** class LINERANGE +** The class LINERANGE is a supporting object used to describe a +** particular range in an OUTLINEDOC. A range is defined by a starting +** line index and an ending line index. +*************************************************************************/ + +typedef struct tagLINERANGE { + signed short m_nStartLine; + signed short m_nEndLine; +} LINERANGE, FAR* LPLINERANGE; + + +/************************************************************************* +** class OUTLINENAME +** The class OUTLINENAME stores a particular named selection in the +** OUTLINEDOC document. The NAMETABLE class holds all of the names +** defined in a particular OUTLINEDOC document. Each OUTLINENAME +** object has a string as its key and a starting line index and an +** ending line index for the named range. +*************************************************************************/ + +#pragma pack(push, 2) +typedef struct tagOUTLINENAME { + char m_szName[MAXNAMESIZE+1]; + signed short m_nStartLine; // must be signed for table update + signed short m_nEndLine; // functions to work +} OUTLINENAME, FAR* LPOUTLINENAME; +#pragma pack(pop) + +void OutlineName_SetName(LPOUTLINENAME lpOutlineName, LPSTR lpszName); +void OutlineName_SetSel(LPOUTLINENAME lpOutlineName, LPLINERANGE lplrSel, BOOL fRangeModified); +void OutlineName_GetSel(LPOUTLINENAME lpOutlineName, LPLINERANGE lplrSel); +BOOL OutlineName_SaveToStg(LPOUTLINENAME lpOutlineName, LPLINERANGE lplrSel, UINT uFormat, LPSTREAM lpNTStm, BOOL FAR* lpfNameSaved); + +BOOL OutlineName_SaveToStg(LPOUTLINENAME lpOutlineName, LPLINERANGE lplrSel, UINT uFormat, LPSTREAM lpNTStm, BOOL FAR* lpfNameSaved); +BOOL OutlineName_LoadFromStg(LPOUTLINENAME lpOutlineName, LPSTREAM lpNTStm); + + +/************************************************************************* +** class OUTLINENAMETABLE +** OUTLINENAMETABLE manages the table of named selections in the +** OUTLINEDOC document. Each OUTLINENAMETABLE entry has a string as its key +** and a starting line index and an ending line index for the +** named range. There is always one instance of OUTLINENAMETABLE for each +** OUTLINEDOC created. +*************************************************************************/ + +typedef struct tagOUTLINENAMETABLE { + HWND m_hWndListBox; + int m_nCount; +} OUTLINENAMETABLE, FAR* LPOUTLINENAMETABLE; + +/* OutlineNameTable methods (functions) */ +BOOL OutlineNameTable_Init(LPOUTLINENAMETABLE lpOutlineNameTable, LPOUTLINEDOC lpOutlineDoc); +void OutlineNameTable_Destroy(LPOUTLINENAMETABLE lpOutlineNameTable); +void OutlineNameTable_ClearAll(LPOUTLINENAMETABLE lpOutlineNameTable); +LPOUTLINENAME OutlineNameTable_CreateName(LPOUTLINENAMETABLE lpOutlineNameTable); +void OutlineNameTable_AddName(LPOUTLINENAMETABLE lpOutlineNameTable, LPOUTLINENAME lpOutlineName); +void OutlineNameTable_DeleteName(LPOUTLINENAMETABLE lpOutlineNameTable, int nIndex); +int OutlineNameTable_GetNameIndex(LPOUTLINENAMETABLE lpOutlineNameTable, LPOUTLINENAME lpOutlineName); +LPOUTLINENAME OutlineNameTable_GetName(LPOUTLINENAMETABLE lpOutlineNameTable, int nIndex); +LPOUTLINENAME OutlineNameTable_FindName(LPOUTLINENAMETABLE lpOutlineNameTable, LPSTR lpszName); +LPOUTLINENAME OutlineNameTable_FindNamedRange(LPOUTLINENAMETABLE lpOutlineNameTable, LPLINERANGE lplrSel); +int OutlineNameTable_GetCount(LPOUTLINENAMETABLE lpOutlineNameTable); +void OutlineNameTable_AddLineUpdate(LPOUTLINENAMETABLE lpOutlineNameTable, int nAddIndex); +void OutlineNameTable_DeleteLineUpdate(LPOUTLINENAMETABLE lpOutlineNameTable, int nDeleteIndex); +BOOL OutlineNameTable_LoadFromStg(LPOUTLINENAMETABLE lpOutlineNameTable, LPSTORAGE lpSrcStg); +BOOL OutlineNameTable_SaveSelToStg( + LPOUTLINENAMETABLE lpOutlineNameTable, + LPLINERANGE lplrSel, + UINT uFormat, + LPSTREAM lpNTStm +); + + +/************************************************************************* +** class LINELIST +** The class LINELIST manages the list of Line objects in the +** OUTLINEDOC document. This class uses a Window's Owner-draw ListBox +** to hold the list of LINE objects. There is always one instance of +** LINELIST for each OUTLINEDOC created. +*************************************************************************/ + +typedef struct tagLINELIST { + HWND m_hWndListBox; // hWnd of OwnerDraw listbox + int m_nNumLines; // number of lines in LineList + int m_nMaxLineWidthInHimetric; // max width of listbox + LPOUTLINEDOC m_lpDoc; // ptr to associated OutlineDoc + LINERANGE m_lrSaveSel; // selection saved on WM_KILLFOCUS + +#if defined( USE_DRAGDROP ) + int m_iDragOverLine; // line index w/ drop target feedback +#endif +} LINELIST, FAR* LPLINELIST; + +/* LineList methods (functions) */ +BOOL LineList_Init(LPLINELIST lpLL, LPOUTLINEDOC lpOutlineDoc); +void LineList_Destroy(LPLINELIST lpLL); +void LineList_AddLine(LPLINELIST lpLL, LPLINE lpLine, int nIndex); +void LineList_DeleteLine(LPLINELIST lpLL, int nIndex); +void LineList_ReplaceLine(LPLINELIST lpLL, LPLINE lpLine, int nIndex); +int LineList_GetLineIndex(LPLINELIST lpLL, LPLINE lpLine); +LPLINE LineList_GetLine(LPLINELIST lpLL, int nIndex); +void LineList_SetFocusLine ( LPLINELIST lpLL, WORD wIndex ); +BOOL LineList_GetLineRect(LPLINELIST lpLL, int nIndex, LPRECT lpRect); +int LineList_GetFocusLineIndex(LPLINELIST lpLL); +int LineList_GetCount(LPLINELIST lpLL); +BOOL LineList_SetMaxLineWidthInHimetric( + LPLINELIST lpLL, + int nWidthInHimetric +); +void LineList_ScrollLineIntoView(LPLINELIST lpLL, int nIndex); +int LineList_GetMaxLineWidthInHimetric(LPLINELIST lpLL); +BOOL LineList_RecalcMaxLineWidthInHimetric( + LPLINELIST lpLL, + int nWidthInHimetric +); +void LineList_CalcSelExtentInHimetric( + LPLINELIST lpLL, + LPLINERANGE lplrSel, + LPSIZEL lpsizel +); +HWND LineList_GetWindow(LPLINELIST lpLL); +HDC LineList_GetDC(LPLINELIST lpLL); +void LineList_ReleaseDC(LPLINELIST lpLL, HDC hDC); +void LineList_SetLineHeight(LPLINELIST lpLL,int nIndex,int nHeightInHimetric); +void LineList_ReScale(LPLINELIST lpLL, LPSCALEFACTOR lpscale); +void LineList_SetSel(LPLINELIST lpLL, LPLINERANGE lplrSel); +int LineList_GetSel(LPLINELIST lpLL, LPLINERANGE lplrSel); +void LineList_RemoveSel(LPLINELIST lpLL); +void LineList_RestoreSel(LPLINELIST lpLL); +void LineList_SetRedraw(LPLINELIST lpLL, BOOL fEnableDraw); +void LineList_ForceRedraw(LPLINELIST lpLL, BOOL fErase); +void LineList_ForceLineRedraw(LPLINELIST lpLL, int nIndex, BOOL fErase); +int LineList_CopySelToDoc( + LPLINELIST lpSrcLL, + LPLINERANGE lplrSel, + LPOUTLINEDOC lpDestDoc +); +BOOL LineList_SaveSelToStg( + LPLINELIST lpLL, + LPLINERANGE lplrSel, + UINT uFormat, + LPSTORAGE lpSrcStg, + LPSTORAGE lpDestStg, + LPSTREAM lpLLStm, + BOOL fRemember +); +BOOL LineList_LoadFromStg( + LPLINELIST lpLL, + LPSTORAGE lpSrcStg, + LPSTREAM lpLLStm +); + +#if defined( USE_DRAGDROP ) +void LineList_SetFocusLineFromPointl( LPLINELIST lpLL, POINTL pointl ); +void LineList_SetDragOverLineFromPointl ( LPLINELIST lpLL, POINTL pointl ); +void LineList_Scroll(LPLINELIST lpLL, DWORD dwScrollDir); +int LineList_GetLineIndexFromPointl(LPLINELIST lpLL, POINTL pointl); +void LineList_RestoreDragFeedback(LPLINELIST lpLL); +#endif + +LRESULT FAR PASCAL LineListWndProc( + HWND hWnd, + UINT Message, + WPARAM wParam, + LPARAM lParam +); + + +// Document initialization type +#define DOCTYPE_UNKNOWN 0 // new doc created but not yet initialized +#define DOCTYPE_NEW 1 // init from scratch (new doc) +#define DOCTYPE_FROMFILE 2 // init from a file (open doc) + + + +/************************************************************************* +** class OUTLINEDOC +** There is one instance of the OutlineDoc class created per +** document open in the app. The SDI version of the app supports one +** OUTLINEDOC at a time. The MDI version of the app can manage +** multiple documents at one time. +*************************************************************************/ + +/* Definition of OUTLINEDOC */ +typedef struct tagOUTLINEDOC { + LINELIST m_LineList; // list of lines in the doc + LPOUTLINENAMETABLE m_lpNameTable; // table of names in the doc + HWND m_hWndDoc; // client area window for the Doc + int m_docInitType; // is doc new or loaded from a file? + BOOL m_fDataTransferDoc; // is doc created for copy | drag/drop + CLIPFORMAT m_cfSaveFormat; // format used to save the doc + char m_szFileName[256]; // associated file; "(Untitled)" if none + LPSTR m_lpszDocTitle; // name of doc to appear in window title + BOOL m_fModified; // is the doc dirty (needs to be saved)? + UINT m_nDisableDraw; // enable/disable updating the display + SCALEFACTOR m_scale; // current scale factor of the doc + int m_nLeftMargin; // left margin in Himetric + int m_nRightMargin; // right margin in Himetric + UINT m_uCurrentZoom; // cur. zoom (used for menu checking) + UINT m_uCurrentMargin; // cur. margin (used for menu checking) +#if defined( USE_HEADING ) + HEADING m_heading; +#endif + +#if defined( USE_FRAMETOOLS ) + LPFRAMETOOLS m_lpFrameTools; // ptr to frame tools used by this doc +#endif + +} OUTLINEDOC; + +/* OutlineDoc methods (functions) */ + +BOOL OutlineDoc_Init(LPOUTLINEDOC lpOutlineDoc, BOOL fDataTransferDoc); +BOOL OutlineDoc_InitNewFile(LPOUTLINEDOC lpOutlineDoc); +LPOUTLINENAMETABLE OutlineDoc_CreateNameTable(LPOUTLINEDOC lpOutlineDoc); +void OutlineDoc_Destroy(LPOUTLINEDOC lpOutlineDoc); +BOOL OutlineDoc_Close(LPOUTLINEDOC lpOutlineDoc, DWORD dwSaveOption); +void OutlineDoc_ShowWindow(LPOUTLINEDOC lpOutlineDoc); +void OutlineDoc_FrameWindowResized( + LPOUTLINEDOC lpOutlineDoc, + LPRECT lprcFrameRect, + LPBORDERWIDTHS lpFrameToolWidths +); + +void OutlineDoc_ClearCommand(LPOUTLINEDOC lpOutlineDoc); +void OutlineDoc_CutCommand(LPOUTLINEDOC lpOutlineDoc); +void OutlineDoc_CopyCommand(LPOUTLINEDOC lpOutlineDoc); +void OutlineDoc_ClearAllLines(LPOUTLINEDOC lpOutlineDoc); +LPOUTLINEDOC OutlineDoc_CreateDataTransferDoc(LPOUTLINEDOC lpSrcOutlineDoc); +void OutlineDoc_PasteCommand(LPOUTLINEDOC lpOutlineDoc); +int OutlineDoc_PasteOutlineData(LPOUTLINEDOC lpOutlineDoc, HGLOBAL hOutline, int nStartIndex); +int OutlineDoc_PasteTextData(LPOUTLINEDOC lpOutlineDoc, HGLOBAL hText, int nStartIndex); +void OutlineDoc_AddTextLineCommand(LPOUTLINEDOC lpOutlineDoc); +void OutlineDoc_AddTopLineCommand( + LPOUTLINEDOC lpOutlineDoc, + UINT nHeightInHimetric +); +void OutlineDoc_EditLineCommand(LPOUTLINEDOC lpOutlineDoc); +void OutlineDoc_IndentCommand(LPOUTLINEDOC lpOutlineDoc); +void OutlineDoc_UnindentCommand(LPOUTLINEDOC lpOutlineDoc); +void OutlineDoc_SetLineHeightCommand(LPOUTLINEDOC lpDoc); +void OutlineDoc_SelectAllCommand(LPOUTLINEDOC lpOutlineDoc); +void OutlineDoc_DefineNameCommand(LPOUTLINEDOC lpOutlineDoc); +void OutlineDoc_GotoNameCommand(LPOUTLINEDOC lpOutlineDoc); + +void OutlineDoc_Print(LPOUTLINEDOC lpOutlineDoc, HDC hDC); +BOOL OutlineDoc_SaveToFile(LPOUTLINEDOC lpOutlineDoc, LPCSTR lpszFileName, UINT uFormat, BOOL fRemember); +void OutlineDoc_AddLine(LPOUTLINEDOC lpOutlineDoc, LPLINE lpLine, int nIndex); +void OutlineDoc_DeleteLine(LPOUTLINEDOC lpOutlineDoc, int nIndex); +void OutlineDoc_AddName(LPOUTLINEDOC lpOutlineDoc, LPOUTLINENAME lpOutlineName); +void OutlineDoc_DeleteName(LPOUTLINEDOC lpOutlineDoc, int nIndex); +void OutlineDoc_Resize(LPOUTLINEDOC lpDoc, LPRECT lpRect); +LPOUTLINENAMETABLE OutlineDoc_GetNameTable(LPOUTLINEDOC lpOutlineDoc); +LPLINELIST OutlineDoc_GetLineList(LPOUTLINEDOC lpOutlineDoc); +int OutlineDoc_GetNameCount(LPOUTLINEDOC lpOutlineDoc); +int OutlineDoc_GetLineCount(LPOUTLINEDOC lpOutlineDoc); +void OutlineDoc_SetTitle(LPOUTLINEDOC lpOutlineDoc, BOOL fMakeUpperCase); +BOOL OutlineDoc_CheckSaveChanges( + LPOUTLINEDOC lpOutlineDoc, + LPDWORD lpdwSaveOption +); +BOOL OutlineDoc_IsModified(LPOUTLINEDOC lpOutlineDoc); +void OutlineDoc_SetModified(LPOUTLINEDOC lpOutlineDoc, BOOL fModified, BOOL fDataChanged, BOOL fSizeChanged); +void OutlineDoc_SetRedraw(LPOUTLINEDOC lpOutlineDoc, BOOL fEnableDraw); +BOOL OutlineDoc_LoadFromFile(LPOUTLINEDOC lpOutlineDoc, LPSTR szFileName); +BOOL OutlineDoc_SaveSelToStg( + LPOUTLINEDOC lpOutlineDoc, + LPLINERANGE lplrSel, + UINT uFormat, + LPSTORAGE lpDestStg, + BOOL fSameAsLoad, + BOOL fRemember +); +BOOL OutlineDoc_LoadFromStg(LPOUTLINEDOC lpOutlineDoc, LPSTORAGE lpSrcStg); +BOOL OutlineDoc_SetFileName(LPOUTLINEDOC lpOutlineDoc, LPSTR lpszFileName, LPSTORAGE lpNewStg); +HWND OutlineDoc_GetWindow(LPOUTLINEDOC lpOutlineDoc); +void OutlineDoc_SetSel(LPOUTLINEDOC lpOutlineDoc, LPLINERANGE lplrSel); +int OutlineDoc_GetSel(LPOUTLINEDOC lpOutlineDoc, LPLINERANGE lplrSel); +void OutlineDoc_ForceRedraw(LPOUTLINEDOC lpOutlineDoc, BOOL fErase); +void OutlineDoc_RenderFormat(LPOUTLINEDOC lpOutlineDoc, UINT uFormat); +void OutlineDoc_RenderAllFormats(LPOUTLINEDOC lpOutlineDoc); +HGLOBAL OutlineDoc_GetOutlineData(LPOUTLINEDOC lpOutlineDoc, LPLINERANGE lplrSel); +HGLOBAL OutlineDoc_GetTextData(LPOUTLINEDOC lpOutlineDoc, LPLINERANGE lplrSel); +void OutlineDoc_DialogHelp(HWND hDlg, WPARAM wDlgID); +void OutlineDoc_SetCurrentZoomCommand( + LPOUTLINEDOC lpOutlineDoc, + UINT uCurrentZoom +); +UINT OutlineDoc_GetCurrentZoomMenuCheck(LPOUTLINEDOC lpOutlineDoc); +void OutlineDoc_SetScaleFactor( + LPOUTLINEDOC lpOutlineDoc, + LPSCALEFACTOR lpscale, + LPRECT lprcDoc +); +LPSCALEFACTOR OutlineDoc_GetScaleFactor(LPOUTLINEDOC lpDoc); +void OutlineDoc_SetCurrentMarginCommand( + LPOUTLINEDOC lpOutlineDoc, + UINT uCurrentMargin +); +UINT OutlineDoc_GetCurrentMarginMenuCheck(LPOUTLINEDOC lpOutlineDoc); +void OutlineDoc_SetMargin(LPOUTLINEDOC lpDoc, int nLeftMargin, int nRightMargin); +LONG OutlineDoc_GetMargin(LPOUTLINEDOC lpDoc); + + +#if defined( USE_FRAMETOOLS ) +void OutlineDoc_AddFrameLevelTools(LPOUTLINEDOC lpOutlineDoc); +void OutlineDoc_SetFormulaBarEditText( + LPOUTLINEDOC lpOutlineDoc, + LPLINE lpLine +); +void OutlineDoc_SetFormulaBarEditFocus( + LPOUTLINEDOC lpOutlineDoc, + BOOL fEditFocus +); +BOOL OutlineDoc_IsEditFocusInFormulaBar(LPOUTLINEDOC lpOutlineDoc); +void OutlineDoc_UpdateFrameToolButtons(LPOUTLINEDOC lpOutlineDoc); +#endif // USE_FRAMETOOLS + +#if defined( USE_HEADING ) +LPHEADING OutlineDoc_GetHeading(LPOUTLINEDOC lpOutlineDoc); +void OutlineDoc_ShowHeading(LPOUTLINEDOC lpOutlineDoc, BOOL fShow); +#endif // USE_HEADING + +/************************************************************************* +** class OUTLINEAPP +** There is one instance of the OUTLINEAPP class created per running +** application instance. This object holds many fields that could +** otherwise be organized as global variables. +*************************************************************************/ + +/* Definition of OUTLINEAPP */ +typedef struct tagOUTLINEAPP { + HWND m_hWndApp; // top-level frame window for the App + HMENU m_hMenuApp; // handle to frame level menu for App + HACCEL m_hAccelApp; + HACCEL m_hAccelFocusEdit;// Accelerator when Edit in Focus + LPOUTLINEDOC m_lpDoc; // main SDI document visible to user + LPOUTLINEDOC m_lpClipboardDoc; // hidden doc for snapshot of copied sel + HWND m_hWndStatusBar; // window for the status bar + HCURSOR m_hcursorSelCur; // cursor used to select lines + HINSTANCE m_hInst; + PRINTDLG m_PrintDlg; + HFONT m_hStdFont; // font used for TextLines + UINT m_cfOutline; // clipboard format for Outline data + HACCEL m_hAccel; + HWND m_hWndAccelTarget; + FARPROC m_ListBoxWndProc; // orig listbox WndProc for subclassing + +#if defined ( USE_FRAMETOOLS ) || defined ( INPLACE_CNTR ) + BORDERWIDTHS m_FrameToolWidths; // space required by frame-level tools +#endif // USE_FRAMETOOLS || INPLACE_CNTR + +#if defined( USE_FRAMETOOLS ) + FRAMETOOLS m_frametools; // frame tools (button & formula bars) +#endif // USE_FRAMETOOLS + +} OUTLINEAPP, FAR* LPOUTLINEAPP; + +/* OutlineApp methods (functions) */ +BOOL OutlineApp_InitApplication(LPOUTLINEAPP lpOutlineApp, HINSTANCE hInst); +BOOL OutlineApp_InitInstance(LPOUTLINEAPP lpOutlineApp, HINSTANCE hInst, int nCmdShow); +BOOL OutlineApp_ParseCmdLine(LPOUTLINEAPP lpOutlineApp, LPSTR lpszCmdLine, int nCmdShow); +void OutlineApp_Destroy(LPOUTLINEAPP lpOutlineApp); +LPOUTLINEDOC OutlineApp_CreateDoc( + LPOUTLINEAPP lpOutlineApp, + BOOL fDataTransferDoc +); +HWND OutlineApp_GetWindow(LPOUTLINEAPP lpOutlineApp); +HWND OutlineApp_GetFrameWindow(LPOUTLINEAPP lpOutlineApp); +HINSTANCE OutlineApp_GetInstance(LPOUTLINEAPP lpOutlineApp); +LPOUTLINENAME OutlineApp_CreateName(LPOUTLINEAPP lpOutlineApp); +void OutlineApp_DocUnlockApp(LPOUTLINEAPP lpOutlineApp, LPOUTLINEDOC lpOutlineDoc); +void OutlineApp_InitMenu(LPOUTLINEAPP lpOutlineApp, LPOUTLINEDOC lpDoc, HMENU hMenu); +void OutlineApp_GetFrameRect(LPOUTLINEAPP lpOutlineApp, LPRECT lprcFrameRect); +void OutlineApp_GetClientAreaRect( + LPOUTLINEAPP lpOutlineApp, + LPRECT lprcClientAreaRect +); +void OutlineApp_GetStatusLineRect( + LPOUTLINEAPP lpOutlineApp, + LPRECT lprcStatusLineRect +); +void OutlineApp_ResizeWindows(LPOUTLINEAPP lpOutlineApp); +void OutlineApp_ResizeClientArea(LPOUTLINEAPP lpOutlineApp); +void OutlineApp_AboutCommand(LPOUTLINEAPP lpOutlineApp); +void OutlineApp_NewCommand(LPOUTLINEAPP lpOutlineApp); +void OutlineApp_OpenCommand(LPOUTLINEAPP lpOutlineApp); +void OutlineApp_PrintCommand(LPOUTLINEAPP lpOutlineApp); +BOOL OutlineApp_SaveCommand(LPOUTLINEAPP lpOutlineApp); +BOOL OutlineApp_SaveAsCommand(LPOUTLINEAPP lpOutlineApp); +BOOL OutlineApp_CloseAllDocsAndExitCommand( + LPOUTLINEAPP lpOutlineApp, + BOOL fForceEndSession +); +void OutlineApp_DestroyWindow(LPOUTLINEAPP lpOutlineApp); + +#if defined( USE_FRAMETOOLS ) +void OutlineApp_SetBorderSpace( + LPOUTLINEAPP lpOutlineApp, + LPBORDERWIDTHS lpBorderWidths +); +LPFRAMETOOLS OutlineApp_GetFrameTools(LPOUTLINEAPP lpOutlineApp); +void OutlineApp_SetFormulaBarAccel( + LPOUTLINEAPP lpOutlineApp, + BOOL fEditFocus +); +#endif // USE_FRAMETOOLS + +void OutlineApp_SetStatusText(LPOUTLINEAPP lpOutlineApp, LPSTR lpszMessage); +LPOUTLINEDOC OutlineApp_GetActiveDoc(LPOUTLINEAPP lpOutlineApp); +HMENU OutlineApp_GetMenu(LPOUTLINEAPP lpOutlineApp); +HFONT OutlineApp_GetActiveFont(LPOUTLINEAPP lpOutlineApp); +HDC OutlineApp_GetPrinterDC(LPOUTLINEAPP lpApp); +void OutlineApp_PrinterSetupCommand(LPOUTLINEAPP lpOutlineApp); +void OutlineApp_ErrorMessage(LPOUTLINEAPP lpOutlineApp, LPSTR lpszMsg); +void OutlineApp_GetAppVersionNo(LPOUTLINEAPP lpOutlineApp, int narrAppVersionNo[]); +void OutlineApp_GetAppName(LPOUTLINEAPP lpOutlineApp, LPSTR lpszAppName); +BOOL OutlineApp_VersionNoCheck(LPOUTLINEAPP lpOutlineApp, LPSTR lpszAppName, int narrAppVersionNo[]); +void OutlineApp_SetEditText(LPOUTLINEAPP lpApp); +void OutlineApp_SetFocusEdit(LPOUTLINEAPP lpApp, BOOL bFocusEdit); +BOOL OutlineApp_GetFocusEdit(LPOUTLINEAPP lpApp); +void OutlineApp_ForceRedraw(LPOUTLINEAPP lpOutlineApp, BOOL fErase); + +/* struct definition for persistant data storage of OutlineDoc data */ + +#pragma pack(push, 2) +typedef struct tagOUTLINEDOCHEADER_ONDISK { + char m_szFormatName[32]; + short m_narrAppVersionNo[2]; + USHORT m_fShowHeading; + DWORD m_reserved1; // space reserved for future use + DWORD m_reserved2; // space reserved for future use + DWORD m_reserved3; // space reserved for future use + DWORD m_reserved4; // space reserved for future use +} OUTLINEDOCHEADER_ONDISK, FAR* LPOUTLINEDOCHEADER_ONDISK; +#pragma pack(pop) + +typedef struct tagOUTLINEDOCHEADER { + char m_szFormatName[32]; + int m_narrAppVersionNo[2]; + BOOL m_fShowHeading; + DWORD m_reserved1; // space reserved for future use + DWORD m_reserved2; // space reserved for future use + DWORD m_reserved3; // space reserved for future use + DWORD m_reserved4; // space reserved for future use +} OUTLINEDOCHEADER, FAR* LPOUTLINEDOCHEADER; + +#pragma pack(push,2) +typedef struct tagLINELISTHEADER_ONDISK { + USHORT m_nNumLines; + DWORD m_reserved1; // space reserved for future use + DWORD m_reserved2; // space reserved for future use +} LINELISTHEADER_ONDISK, FAR* LPLINELISTHEADER_ONDISK; +#pragma pack(pop) + +typedef struct tagLINELISTHEADER { + int m_nNumLines; + DWORD m_reserved1; // space reserved for future use + DWORD m_reserved2; // space reserved for future use +} LINELISTHEADER, FAR* LPLINELISTHEADER; + +#pragma pack(push,2) +typedef struct tagLINERECORD_ONDISK { + USHORT m_lineType; + USHORT m_nTabLevel; + USHORT m_nTabWidthInHimetric; + USHORT m_nWidthInHimetric; + USHORT m_nHeightInHimetric; + DWORD m_reserved; // space reserved for future use +} LINERECORD_ONDISK, FAR* LPLINERECORD_ONDISK; +#pragma pack(pop) + +typedef struct tagLINERECORD { + LINETYPE m_lineType; + UINT m_nTabLevel; + UINT m_nTabWidthInHimetric; + UINT m_nWidthInHimetric; + UINT m_nHeightInHimetric; + DWORD m_reserved; // space reserved for future use +} LINERECORD, FAR* LPLINERECORD; + + +/* Function prototypes in main.c */ +int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, + LPSTR lpszCmdLine, int nCmdShow); +BOOL MyTranslateAccelerator(LPMSG lpmsg); +int GetAccelItemCount(HACCEL hAccel); + +LRESULT CALLBACK EXPORT AppWndProc(HWND hWnd, UINT Message, WPARAM wParam, + LPARAM lParam); +LRESULT CALLBACK EXPORT DocWndProc(HWND hWnd, UINT Message, WPARAM wParam, + LPARAM lParam); + +/* Function prototypes in outldlgs.c */ +BOOL InputTextDlg(HWND hWnd, LPSTR lpszText, LPSTR lpszDlgTitle); +BOOL CALLBACK EXPORT AddEditDlgProc(HWND, UINT, WPARAM, LPARAM); +BOOL CALLBACK EXPORT SetLineHeightDlgProc(HWND hDlg, UINT Message, WPARAM wParam, LPARAM lParam); +BOOL CALLBACK EXPORT DefineNameDlgProc(HWND, UINT, WPARAM, LPARAM); +BOOL CALLBACK EXPORT GotoNameDlgProc(HWND, UINT, WPARAM, LPARAM); +void NameDlg_LoadComboBox(LPOUTLINENAMETABLE lpOutlineNameTable,HWND hCombo); +void NameDlg_LoadListBox(LPOUTLINENAMETABLE lpOutlineNameTable,HWND hListBox); +void NameDlg_AddName(HWND hCombo, LPOUTLINEDOC lpOutlineDoc, LPSTR lpszName, LPLINERANGE lplrSel); +void NameDlg_UpdateName(HWND hCombo, LPOUTLINEDOC lpOutlineDoc, int nIndex, LPSTR lpszName, LPLINERANGE lplrSel); +void NameDlg_DeleteName(HWND hCombo, LPOUTLINEDOC lpOutlineDoc, UINT nIndex); +BOOL CALLBACK EXPORT AboutDlgProc(HWND hDlg, UINT Message, WPARAM wParam, LPARAM lParam); + +/* Function prototypes in outldata.c */ +LPVOID New(DWORD lSize); +void Delete(LPVOID p); + +/* Function prototypes in outlprnt.c */ +BOOL CALLBACK EXPORT AbortProc (HDC hdc, WORD reserved); +BOOL CALLBACK EXPORT PrintDlgProc(HWND hwnd, WORD msg, WORD wParam, LONG lParam); + +/* Function prototypes in debug.c */ +void SetDebugLevelCommand(void); +void TraceDebug(HWND, int); + + +// now declare test functions + +extern HWND g_hwndDriver; + +void StartClipboardTest1( LPOUTLINEAPP lpOutlineApp ); +void ContinueClipboardTest1( LPOUTLINEAPP lpOutlineApp ); + +#if defined( OLE_VERSION ) +#include "oleoutl.h" + +#endif // OLE_VERSION + + +#endif // _OUTLINE_H_ + diff --git a/private/oleutest/letest/outline/outline.ico b/private/oleutest/letest/outline/outline.ico new file mode 100644 index 000000000..bb5d483ee Binary files /dev/null and b/private/oleutest/letest/outline/outline.ico differ diff --git a/private/oleutest/letest/outline/outline.mst b/private/oleutest/letest/outline/outline.mst new file mode 100644 index 000000000..319b3e006 --- /dev/null +++ b/private/oleutest/letest/outline/outline.mst @@ -0,0 +1,469 @@ +'******************************** TUTOR.MST ********************************** +'Demonstrates: This will test the OLE 2.0 sample app: OLine.EXE +' +'Required Files: MSTEST.INC, OUTLINE.EXE +' +'Uses: TESTSCRN, TESTCTRL, TESTEVENT. +' +'Notes: Assumes all exe's are in the PATH. +' +'****************************************************************************** + +Declare Sub Init +Declare Sub Windows +Declare Sub AddLines +Declare Sub NewDoc +Declare Sub ClearAll +Declare Sub TestNames +Declare Sub TestClip +Declare Sub EndTest + +Declare SUB LogPrint(szString$) +Declare SUB CheckAppExists(szAppName$, szErrMessage$) +Declare SUB CheckAppNotExists(szAppName$, szErrMessage$) +Declare FUNCTION CheckWndIsActive(szAppName$, szErrMessage$) AS INTEGER +Declare SUB IsDllLoaded(szDllName$) +Declare FUNCTION GetDllUsage(szDllName$) AS INTEGER +Declare SUB CheckDllUsage(szDllName$, nExpectedUsage%) + +'****************************************************************************** +' CONST +'****************************************************************************** + +Const DefAppName$ = "outline" +Const RootAppDir$ = "c:\ole2samp\outline\" +Const SDemo1AppName$ = "sdemo1" +Const SDemo1ClassName$ = "SDemo1" +Const EllipseWTClassName$ = "EllipseWT" +Const BELL = 7 + +Global WinHandle%, DbWinHandle%, logfile%, ErrCount, fSlaveMode%, fAutoMode%, AppName$, AppWndName$, AppDir$ + +Const nDll = 4 +GLOBAL DllList$(nDll) +GLOBAL DllExpectedUsage%(nDll) + +DllList(0) = "OLE2.DLL" +DllList(1) = "OLECLASS.DLL" +DllList(2) = "OLEREM.DLL" +DllList(3) = "OLEPROXY.DLL" +DllList(4) = "DOCFILE.DLL" + +'****************************************************************************** +' DEFINES +'****************************************************************************** + +'$DEFINE TESTSCRN +'$DEFINE TESTCTRL +'$DEFINE TESTEVNT + +'****************************************************************************** +' INCLUDES +'****************************************************************************** + +'$INCLUDE 'mstest.inc' +'$INCLUDE 'fasttest.inc' +'$INCLUDE 'winkern.inc' + +'****************************************************************************** +' Main program code +'****************************************************************************** + +ON ERROR GOTO ErrorTrap + + Init '*** Initialize logging, global constants. + Windows '*** Test various windowing features of app. + NewDoc '*** start a new document + AddLines '*** Add some lines to document + TestNames '*** Test naming functionality + TestClip '*** Test clipboard functionality + EndTest '*** Shut down. + +END + +'****************************************************************************** +' TRAPS +'****************************************************************************** + +ErrorTrap: + + ErrCount = ErrCount + 1 + SELECT CASE Err + CASE ERR_INVALID_PATH + LogPrint "Path not found. Error number " + STR$(Err) + LogPrint " on line " + STR$(ERL) + LogPrint " in script " + ERF + LogPrint ERROR$ ' The error message. + END + CASE ERR_CANT_OPEN_FILE + LogPrint "Can't Open File. Error number " + STR$(Err) + LogPrint " on line " + STR$(ERL) + LogPrint " in script " + ERF + LogPrint ERROR$ ' The error message. + END + CASE ERR_ILLEGAL_FUNCTION_CALL + LogPrint "Illegal function call. Error number " + STR$(Err) + LogPrint " on line " + STR$(ERL) + LogPrint " in script " + ERF + LogPrint ERROR$ ' The error message. + LogPrint " (NOTE: Check if OLETEST.EXE & SDEMO1.EXE are on your PATH)" + END + CASE ELSE + LogPrint "Unexpected error: Number " + STR$(Err) + LogPrint " on line " + STR$(ERL) + LogPrint " in script " +ERF + LogPrint ERROR$ ' The error message. + END + END SELECT + +'*** trap UAE from an application + +'TRAP UAETrap FROM "TESTDRVR.EXE" +' LogPrint "!!!!!! UNRECOVERERABLE APPLICATION ERROR ENCOUNTERED!" +' LogPrint " ABORT TESTING!" +' ErrCount = ErrCount + 1 +' EndTest +'END TRAP + +'****************************************************************************** +' SUBs and FUNCTIONs +'****************************************************************************** + + + +'****************************************************************************** +' SUB Init sets up several variables that are used thoughout the test. +'****************************************************************************** +SUB Init STATIC + + Viewport On + Viewport Clear + ErrCount = 0 + fSlaveMode = 0 + fAutoMode = 0 + IF TESTMODE$ = "auto" OR TESTMODE$ = "AUTO" THEN + fAutoMode = 1 + ENDIF + + '*** Determine name of app to run. this can be given with "/C appname" cmd line opt. + IF COMMAND$ = "" THEN + AppName$ = DefAppName$ + ELSE + AppName$ = COMMAND$ + ENDIF + AppWndName$ = AppName$ + " -" + + logfile = FREEFILE + OPEN "mstest.log" FOR OUTPUT AS # logfile + 'Set log file and write header to file. + + LogPrint "**********************************************" + LogPrint "STARTING TEST OF " + AppName$ + " APPLICATION" + LogPrint " " + DATETIME$ + LogPrint "**********************************************" + + 'Record the initial usage counts for all OLE2 related DLLs + FOR I = 0 TO nDll + DllExpectedUsage(I) = GetDllUsage(DllLIst(I)) + NEXT I + + 'Run the program and get its window handle. + + WinHandle = WFndWnd(AppWndName$, FW_PART or FW_FOCUS or FW_ALL) + IF WinHandle = 0 THEN + LogPrint "Launching new instance of " + AppName$ + " app--running test in slave mode" + LogPrint "NOTE: Running test in slave mode -- app will automatically shut down" + RUN "dbwin", NOWAIT '*** start up debug messages window + DbWinHandle = WGetActWnd(0) + DoKeys "%(e)e" '*** Edit.Clear buffer + RUN RootAppDir$ + AppName$ + "\" + AppName$, NOWAIT + WinHandle = WGetActWnd(0) + fSlaveMode = 1 '*** Test is run in slave mode, shut down afterwards + ELSE + LogPrint "Using existing instance of " + AppName$ + ENDIF + + IF CheckWndIsActive("Debug Messages", "") <> 0 THEN + DoKeys "%(o)t" '*** Toggle off 'always on top' mode of debug window + WSetActWnd WinHandle '*** activate app + ENDIF + + x = CheckWndIsActive(AppWndName$, AppName$ + " Test not launched successfully") + +END SUB + +'****************************************************************************** +' SUB Window will size app window and set it's position. +'****************************************************************************** + +SUB Windows STATIC + + DIM i% + + 'Position and size the form. + + WSetWndPos WinHandle, 200, 200 + WSetWndSiz WinHandle, 50, 60 + + 'Adjust the window to several locations. + + For i = 1 to 10 + WAdjWndSiz WinHandle, 4*i, 4*i + Next i + +END SUB + +'****************************************************************************** +' SUB NewDoc -- start a new doc. +'****************************************************************************** + +SUB NewDoc STATIC + + LogPrint "--- BEGIN NewDoc" + WSetActWnd WinHandle '*** activate app + DoKeys "%(l)axxxx" '*** add a line so doc is dirty + WButtonClick "OK" '*** Close input dialog box + DoKeys "%(f)n" '*** New command + WButtonClick "No" '*** Do not save + x = CheckWndIsActive(AppWndName$, "Unknown Error") + + LogPrint "--- END" + +END SUB + +'****************************************************************************** +' SUB ClearAll -- clear all lines. +'****************************************************************************** + +SUB ClearAll STATIC + + LogPrint "--- BEGIN ClearALL" + WSetActWnd WinHandle '*** activate app + DoKeys "%(e)l" '*** select all + DoKeys "%(e)e" '*** clear selection + x = CheckWndIsActive(AppWndName$, "Unknown Error") + + LogPrint "--- END" + +END SUB + +'****************************************************************************** +' SUB AddLines -- add text lines. +'****************************************************************************** + +SUB AddLines STATIC + + LogPrint "--- BEGIN AddLines" + WSetActWnd WinHandle '*** activate app + DoKeys "%(l)aLine 1: This is a test" '*** add a line + WButtonClick "OK" '*** Close input dialog box + DoKeys "%(l)aLine 2: This is a test" '*** add a line + WButtonClick "OK" '*** Close input dialog box + DoKeys "%(l)aLine 3: This is a test" '*** add a line + WButtonClick "OK" '*** Close input dialog box + DoKeys "%(l)aLine 3.1: This is a sub point" '*** add a line + WButtonClick "OK" '*** Close input dialog box + DoKeys "%(l)i" '*** indent line + DoKeys "%(l)aLine 3.2: This is a sub point" '*** add a line + WButtonClick "OK" '*** Close input dialog box + DoKeys "%(l)aLine 3.3: This is a sub point" '*** add a line + WButtonClick "OK" '*** Close input dialog box + DoKeys "%(l)i" '*** indent line + DoKeys "%(l)i" '*** indent line + DoKeys "%(l)i" '*** indent line + DoKeys "%(l)i" '*** indent line + DoKeys "%(l)i" '*** indent line + DoKeys "%(l)i" '*** indent line + DoKeys "%(l)n" '*** un-indent line + DoKeys "%(l)n" '*** un-indent line + DoKeys "%(l)n" '*** un-indent line + DoKeys "%(l)n" '*** un-indent line + DoKeys "%(l)n" '*** un-indent line + DoKeys "%(l)n" '*** un-indent line + x = CheckWndIsActive(AppWndName$, "Unknown Error") + + LogPrint "--- END" + +END SUB + +'****************************************************************************** +' SUB TestNames -- test the naming functionality. +'****************************************************************************** + +SUB TestNames STATIC + + LogPrint "--- BEGIN TestNames" + WSetActWnd WinHandle '*** activate app + DoKeys "{UP}" + DoKeys "{Down}" + DoKeys "+({UP})+({UP})+({UP})" '*** select some lines + DoKeys "%(n)dx" '*** define a name + WButtonClick "Ok" '*** Close define name dialog box + DoKeys "%(l)aLine 4: This should be part of name x" '*** add a line + WButtonClick "OK" '*** Close input dialog box + DoKeys "%(l)aLine 5: This should be part of name x" '*** add a line + WButtonClick "OK" '*** Close input dialog box + DoKeys "%(n)gx" '*** goto name + WButtonClick "OK" '*** Close define name dialog box + DoKeys "{Down}" + DoKeys "+{Down}" '*** select the 2 lines that were added + DoKeys "%(e)e" '*** delete the selection + DoKeys "%(n)gx" '*** goto name + WButtonClick "OK" '*** Close define name dialog box + x = CheckWndIsActive(AppWndName$, "Unknown Error") + + LogPrint "--- END" + +END SUB + +'****************************************************************************** +' SUB TestClip -- test the clipboard functionality. +'****************************************************************************** + +SUB TestClip STATIC + + LogPrint "--- BEGIN TestClip" + WSetActWnd WinHandle '*** activate app + DoKeys "%(e)t" '*** cut the selection + DoKeys "%(e)p" '*** paste + DoKeys "%(e)p" '*** paste + x = CheckWndIsActive(AppWndName$, "Unknown Error") + + LogPrint "--- END" + +END SUB + +SUB EndTest STATIC + + IF fSlaveMode <> 0 THEN + LogPrint "*** EndTest" + IF CheckWndIsActive(AppWndName$, AppName$ + " can NOT be closed properly") THEN + DoKeys "%FX" '*** shut down OLETEST + WButtonClick "No" '*** Do not save + ENDIF + WMinWnd(DbWinHandle) '*** minimize debug messages window + CheckAppNotExists AppWndName$, AppName$ + " NOT shut down properly" + ENDIF + + 'Check that all OLE2 related DLLs have the expected usage counts + FOR I = 0 TO nDll + CheckDllUsage DllList(I), DllExpectedUsage(I) + NEXT I + + LogPrint "**********************************************" + LogPrint "SUCCESSFULLY COMPLETED " + AppName$ + "TEST" + LogPrint " " + DATETIME$ + LogPrint "Total of " + STR$(ErrCount) + " errors detected" + LogPrint "**********************************************" + + CLOSE # logfile + + IF fAutoMode = 0 THEN + PRINT, CHR$(BELL) '*** sound a BEEP, we are done! + IF ErrCount = 0 THEN + PAUSE "Test seems successful" + ELSE + PAUSE "*** TEST FAILED -- (" + STR$(ErrCount) + " Errors). See mstest.log" + ENDIF + ENDIF +END SUB + +'****************************************************************************** +' SUB LogPrint prints a string to the logfile and to the Viewport. +'****************************************************************************** + +SUB LogPrint(szString$) STATIC + + PRINT #logfile, szString$ + PRINT, szString$ + +END SUB + +SUB CheckAppExists(szAppName$, szErrMessage$) STATIC + + hWnd = WFndWnd(szAppName, FW_PART or FW_ALL or FW_NOCASE) + IF hWnd = 0 THEN + LogPrint "!!!!!! Operation FAILED..." + LogPrint " " + szErrMessage$ + ErrCount = ErrCount + 1 + ENDIF + +END SUB + +SUB CheckAppNotExists(szAppName$, szErrMessage$) STATIC + + hWnd = WFndWnd(szAppName, FW_PART or FW_ALL or FW_NOCASE) + IF hWnd <> 0 THEN + LogPrint "!!!!!! Operation FAILED..." + LogPrint " " + szErrMessage$ + ErrCount = ErrCount + 1 + ENDIF + +END SUB + +STATIC FUNCTION CheckWndIsActive(szAppName$, szErrMessage$) AS INTEGER + hWnd = WFndWnd(szAppName, FW_PART or FW_ALL or FW_NOCASE) + CheckWndIsActive = hWnd + IF hWnd <> WGetActWnd(0) THEN + CheckWndIsActive = 0 + + '*** if no message is given, then it is not considered an error + IF szErrMessage <> "" THEN + LogPrint "!!!!!! Operation FAILED..." + LogPrint " " + szErrMessage$ + LogPrint " <" + GetText(0) + "> Window is Active" + + IF fAutoMode = 0 THEN + PAUSE "<" + szAppName + "> Window expected.... " + "<" + GetText(0) + "> Window is Active" + ENDIF + + '*** if a dialog is active, then close it. it is probably an error message + IF WButtonExists("Ignore") THEN + WButtonClick "OK" '*** Close err message box + ELSEIF WButtonExists("OK") THEN + WButtonClick "OK" '*** Close err message box + ELSEIF WButtonExists("Ok") THEN + WButtonClick "Ok" '*** Close err message box + ELSEIF WButtonExists("Cancel") THEN + WButtonClick "Cancel" '*** Close err message box + ELSEIF WButtonExists("CANCEL") THEN + WButtonClick "CANCEL" '*** Close err message box + ELSEIF WButtonExists("Close") THEN + WButtonClick "Close" '*** Close err message box + ENDIF + ErrCount = ErrCount + 1 + ENDIF + ENDIF + +END FUNCTION + + +'****************************************************************************** +' FUNCTION GetDllUsage gets the usage count of a DLL. +'****************************************************************************** + +STATIC FUNCTION GetDllUsage(szDllName$) AS INTEGER + + hDll% = GetModuleHandle(szDllName) + GetDllUsage = GetModuleUsage(hDll) + +END FUNCTION + + +'****************************************************************************** +' SUB CheckDllUsage checks if a DLL is loaded the expected number of times. +'****************************************************************************** + +SUB CheckDllUsage(szDllName$, nExpectedUsage%) STATIC + + usage% = GetDllUsage(szDllName) + LogPrint "DLL: " + szDllName + " loadded" + STR$(usage) + " times (expected" + STR$(nExpectedUsage) + " times)" + + '*** can only reliably report an error when expected usage is 0 + IF usage <> nExpectedUsage AND nExpectedUsage = 0 THEN + LogPrint "!!!!!! " + szDllName + " NOT UNLOADED PROPERLY!" + ErrCount = ErrCount + 1 + ENDIF + +END SUB + diff --git a/private/oleutest/letest/outline/outline.rc b/private/oleutest/letest/outline/outline.rc new file mode 100644 index 000000000..795aa8124 --- /dev/null +++ b/private/oleutest/letest/outline/outline.rc @@ -0,0 +1,173 @@ +/************************************************************************* +** +** OLE 2.0 Sample Code +** +** outline.rc +** +** Resource file for outline.exe +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + +#include "windows.h" +#include "outlrc.h" + +SelCur CURSOR selcross.cur + +OutlineMenu MENU + BEGIN + POPUP "&File" + BEGIN + MENUITEM "&New", IDM_F_NEW + MENUITEM "&Open...\t Ctrl+F12", IDM_F_OPEN + MENUITEM "&Save\t Shift+F12", IDM_F_SAVE + MENUITEM "Save &As...\t F12", IDM_F_SAVEAS + MENUITEM SEPARATOR + MENUITEM "&Print...\t Ctrl+Shift+F12", IDM_F_PRINT + MENUITEM "Printer Se&tup...", IDM_F_PRINTERSETUP + MENUITEM SEPARATOR + MENUITEM "E&xit\t Alt+F4", IDM_F_EXIT + END + POPUP "&Edit" + BEGIN + MENUITEM "&Undo", IDM_E_UNDO + MENUITEM SEPARATOR + MENUITEM "Cu&t\t Ctrl+X", IDM_E_CUT + MENUITEM "&Copy\t Ctrl+C", IDM_E_COPY + MENUITEM "&Paste\t Ctrl+V", IDM_E_PASTE + MENUITEM "Cl&ear\t Del", IDM_E_CLEAR + MENUITEM SEPARATOR + MENUITEM "Select A&ll\t Ctrl+A", IDM_E_SELECTALL + END + POPUP "O&utline" + BEGIN + POPUP "&Zoom" + BEGIN + MENUITEM "&400%", IDM_V_ZOOM_400 + MENUITEM "&300%", IDM_V_ZOOM_300 + MENUITEM "&200%", IDM_V_ZOOM_200 + MENUITEM "&100%", IDM_V_ZOOM_100 + MENUITEM "&75%", IDM_V_ZOOM_75 + MENUITEM "&50%", IDM_V_ZOOM_50 + MENUITEM "&25%", IDM_V_ZOOM_25 + END + POPUP "&Left and Right margins" + BEGIN + MENUITEM "&nil", IDM_V_SETMARGIN_0 + MENUITEM "&1 cm", IDM_V_SETMARGIN_1 + MENUITEM "&2 cm", IDM_V_SETMARGIN_2 + MENUITEM "&3 cm", IDM_V_SETMARGIN_3 + MENUITEM "&4 cm", IDM_V_SETMARGIN_4 + END + POPUP "Add &Top Line" + BEGIN + MENUITEM "&1 cm", IDM_V_ADDTOP_1 + MENUITEM "&2 cm", IDM_V_ADDTOP_2 + MENUITEM "&3 cm", IDM_V_ADDTOP_3 + MENUITEM "&4 cm", IDM_V_ADDTOP_4 + END + END + POPUP "&Line" + BEGIN + MENUITEM "&Add Line\t Enter", IDM_L_ADDLINE + MENUITEM "E&dit Line\t Alt+Enter", IDM_L_EDITLINE + MENUITEM SEPARATOR + MENUITEM "&Indent Line\t Tab", IDM_L_INDENTLINE + MENUITEM "U&nindent Line\t Shift+Tab", IDM_L_UNINDENTLINE + MENUITEM SEPARATOR + MENUITEM "&Set Line Height...", IDM_L_SETLINEHEIGHT + END + POPUP "&Name" + BEGIN + MENUITEM "&Define Name...", IDM_N_DEFINENAME + MENUITEM "&Goto Name...", IDM_N_GOTONAME + END + POPUP "&Options" + BEGIN + POPUP "&Button Bar Display" + BEGIN + MENUITEM "At &Top", IDM_O_BB_TOP + MENUITEM "At &Bottom", IDM_O_BB_BOTTOM + MENUITEM "&Popup", IDM_O_BB_POPUP + MENUITEM "&Hide", IDM_O_BB_HIDE + END + POPUP "&Formula Bar Display" + BEGIN + MENUITEM "At &Top", IDM_O_FB_TOP + MENUITEM "At &Bottom", IDM_O_FB_BOTTOM + MENUITEM "&Popup", IDM_O_FB_POPUP + END + POPUP "&Row and Column Heading" + BEGIN + MENUITEM "&Show", IDM_O_HEAD_SHOW + MENUITEM "&Hide", IDM_O_HEAD_HIDE + END + END + POPUP "&Help" + BEGIN + MENUITEM "&About...", IDM_H_ABOUT + END + END + +OutlineAccel ACCELERATORS + BEGIN + VK_F12, IDM_F_OPEN, VIRTKEY, CONTROL + VK_F12, IDM_F_SAVE, VIRTKEY, SHIFT + VK_F12, IDM_F_SAVEAS, VIRTKEY + VK_F12, IDM_F_PRINT, VIRTKEY, CONTROL, SHIFT + + "x", IDM_E_CUT, VIRTKEY, CONTROL + "c", IDM_E_COPY, VIRTKEY, CONTROL + "v", IDM_E_PASTE, VIRTKEY, CONTROL + VK_DELETE, IDM_E_CLEAR, VIRTKEY + VK_RETURN, IDM_L_ADDLINE, VIRTKEY + VK_RETURN, IDM_L_EDITLINE, VIRTKEY, ALT + VK_TAB, IDM_L_INDENTLINE, VIRTKEY + VK_TAB, IDM_L_UNINDENTLINE, VIRTKEY, SHIFT + "a", IDM_E_SELECTALL, VIRTKEY, CONTROL + + ; old conventions for editing + VK_INSERT, IDM_E_COPY, VIRTKEY, CONTROL + VK_DELETE, IDM_E_CUT, VIRTKEY, SHIFT + VK_INSERT, IDM_E_PASTE, VIRTKEY, SHIFT + + VK_F2, IDM_F2, VIRTKEY + END + + +; Same as OutlineAccel but without Delete +; used when edit control of Formula Bar in focus +; +OutlineAccelFocusEdit ACCELERATORS + BEGIN + VK_F12, IDM_F_OPEN, VIRTKEY, CONTROL + VK_F12, IDM_F_SAVE, VIRTKEY, SHIFT + VK_F12, IDM_F_SAVEAS, VIRTKEY + VK_F12, IDM_F_PRINT, VIRTKEY, CONTROL, SHIFT + + "x", IDM_E_CUT, VIRTKEY, CONTROL + "c", IDM_E_COPY, VIRTKEY, CONTROL + "v", IDM_E_PASTE, VIRTKEY, CONTROL + VK_RETURN, IDM_L_ADDLINE, VIRTKEY + VK_RETURN, IDM_L_EDITLINE, VIRTKEY, ALT + VK_TAB, IDM_L_INDENTLINE, VIRTKEY + VK_TAB, IDM_L_UNINDENTLINE, VIRTKEY, SHIFT + "a", IDM_E_SELECTALL, VIRTKEY, CONTROL + + VK_ESCAPE, IDM_FB_CANCEL, VIRTKEY + + ; old conventions for editing + VK_INSERT, IDM_E_COPY, VIRTKEY, CONTROL + VK_DELETE, IDM_E_CUT, VIRTKEY, SHIFT + VK_INSERT, IDM_E_PASTE, VIRTKEY, SHIFT + END + +OutlineIcon ICON outline.ico + +Image72 BITMAP image72.bmp +Image96 BITMAP image96.bmp +Image120 BITMAP image120.bmp +LogoBitmap BITMAP ole2.bmp + +#include "DIALOGS.DLG" diff --git a/private/oleutest/letest/outline/outlline.c b/private/oleutest/letest/outline/outlline.c new file mode 100644 index 000000000..f0416a415 --- /dev/null +++ b/private/oleutest/letest/outline/outlline.c @@ -0,0 +1,731 @@ +/************************************************************************* +** +** OLE 2 Sample Code +** +** outlline.c +** +** This file contains Line functions. +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + + +#include "outline.h" + + +OLEDBGDATA + +extern LPOUTLINEAPP g_lpApp; + + +/* Line_Init + * --------- + * + * Init the calculated data of a line object + */ +void Line_Init(LPLINE lpLine, int nTab, HDC hDC) +{ + lpLine->m_lineType = UNKNOWNLINETYPE; + lpLine->m_nTabLevel = nTab; + lpLine->m_nTabWidthInHimetric = Line_CalcTabWidthInHimetric(lpLine,hDC); + lpLine->m_nWidthInHimetric = 0; + lpLine->m_nHeightInHimetric = 0; + lpLine->m_fSelected = FALSE; + +#if defined( USE_DRAGDROP ) + lpLine->m_fDragOverLine = FALSE; +#endif +} + + +/* Line_Edit + * --------- + * + * Edit the line object. + * + * Returns TRUE if line was changed + * FALSE if the line was NOT changed + */ +BOOL Line_Edit(LPLINE lpLine, HWND hWndDoc, HDC hDC) +{ + switch (lpLine->m_lineType) { + case TEXTLINETYPE: + return TextLine_Edit((LPTEXTLINE)lpLine, hWndDoc, hDC); + +#if defined( OLE_CNTR ) + case CONTAINERLINETYPE: + ContainerLine_Edit((LPCONTAINERLINE)lpLine, hWndDoc, hDC); + break; +#endif + + default: + return FALSE; // unknown line type + } +} + + +/* Line_GetLineType + * ---------------- + * + * Return type of the line + */ +LINETYPE Line_GetLineType(LPLINE lpLine) +{ + if (! lpLine) return 0; + + return lpLine->m_lineType; +} + + +/* Line_GetTextLen + * --------------- + * + * Return length of string representation of the Line + * (not considering the tab level). + */ +int Line_GetTextLen(LPLINE lpLine) +{ + switch (lpLine->m_lineType) { + case TEXTLINETYPE: + return TextLine_GetTextLen((LPTEXTLINE)lpLine); + +#if defined( OLE_CNTR ) + case CONTAINERLINETYPE: + return ContainerLine_GetTextLen((LPCONTAINERLINE)lpLine); +#endif + + default: + return 0; // unknown line type + } +} + + +/* Line_GetTextData + * ---------------- + * + * Return the string representation of the Line. + * (not considering the tab level). + */ +void Line_GetTextData(LPLINE lpLine, LPSTR lpszBuf) +{ + switch (lpLine->m_lineType) { + case TEXTLINETYPE: + TextLine_GetTextData((LPTEXTLINE)lpLine, lpszBuf); + break; + +#if defined( OLE_CNTR ) + case CONTAINERLINETYPE: + ContainerLine_GetTextData((LPCONTAINERLINE)lpLine, lpszBuf); + break; +#endif + + default: + *lpszBuf = '\0'; + return; // unknown line type + } +} + + +/* Line_GetOutlineData + * ------------------- + * + * Return the CF_OUTLINE format representation of the Line. + */ +BOOL Line_GetOutlineData(LPLINE lpLine, LPTEXTLINE lpBuf) +{ + switch (lpLine->m_lineType) { + case TEXTLINETYPE: + return TextLine_GetOutlineData((LPTEXTLINE)lpLine, lpBuf); + +#if defined( OLE_CNTR ) + case CONTAINERLINETYPE: + return ContainerLine_GetOutlineData( + (LPCONTAINERLINE)lpLine, + lpBuf + ); +#endif + + default: + return FALSE; // unknown line type + } +} + + +/* Line_CalcTabWidthInHimetric + * --------------------------- + * + * Recalculate the width for the line's current tab level + */ +static int Line_CalcTabWidthInHimetric(LPLINE lpLine, HDC hDC) +{ + int nTabWidthInHimetric; + + nTabWidthInHimetric=lpLine->m_nTabLevel * TABWIDTH; + return nTabWidthInHimetric; +} + + +/* Line_Indent + * ----------- + * + * Increment the tab level for the line + */ +void Line_Indent(LPLINE lpLine, HDC hDC) +{ + lpLine->m_nTabLevel++; + lpLine->m_nTabWidthInHimetric = Line_CalcTabWidthInHimetric(lpLine, hDC); + +#if defined( INPLACE_CNTR ) + if (Line_GetLineType(lpLine) == CONTAINERLINETYPE) + ContainerLine_UpdateInPlaceObjectRects((LPCONTAINERLINE)lpLine, NULL); +#endif +} + + +/* Line_Unindent + * ------------- + * + * Decrement the tab level for the line + */ +void Line_Unindent(LPLINE lpLine, HDC hDC) +{ + if(lpLine->m_nTabLevel > 0) { + lpLine->m_nTabLevel--; + lpLine->m_nTabWidthInHimetric = Line_CalcTabWidthInHimetric(lpLine, hDC); + } + +#if defined( INPLACE_CNTR ) + if (Line_GetLineType(lpLine) == CONTAINERLINETYPE) + ContainerLine_UpdateInPlaceObjectRects((LPCONTAINERLINE)lpLine, NULL); +#endif +} + + +/* Line_GetTotalWidthInHimetric + * ---------------------------- + * + * Calculate the total width of the line + */ +UINT Line_GetTotalWidthInHimetric(LPLINE lpLine) +{ + return lpLine->m_nWidthInHimetric + lpLine->m_nTabWidthInHimetric; +} + + +/* Line_SetWidthInHimetric + * ----------------------- + * + * Set the width of the line + */ +void Line_SetWidthInHimetric(LPLINE lpLine, int nWidth) +{ + if (!lpLine) + return; + + lpLine->m_nWidthInHimetric = nWidth; +} + + +/* Line_GetWidthInHimetric + * ----------------------- + * + * Return the width of the line + */ +UINT Line_GetWidthInHimetric(LPLINE lpLine) +{ + if (!lpLine) + return 0; + + return lpLine->m_nWidthInHimetric; +} + + + + + +/* Line_GetTabLevel + * ---------------- + * + * Return the tab level of a line object. + */ +UINT Line_GetTabLevel(LPLINE lpLine) +{ + return lpLine->m_nTabLevel; +} + + +/* Line_DrawToScreen + * ----------------- + * + * Draw the item in the owner-draw listbox + */ +void Line_DrawToScreen( + LPLINE lpLine, + HDC hDC, + LPRECT lprcPix, + UINT itemAction, + UINT itemState, + LPRECT lprcDevice +) +{ + if (!lpLine || !hDC || !lprcPix || !lprcDevice) + return; + + /* Draw a list box item in its normal drawing action. + * Then check if it is selected or has the focus state, and call + * functions to handle drawing for these states if necessary. + */ + if(itemAction & (ODA_SELECT | ODA_DRAWENTIRE)) { + HFONT hfontOld; + int nMapModeOld; + RECT rcWindowOld; + RECT rcViewportOld; + RECT rcLogical; + + // NOTE: we have to set the device context to HIMETRIC in order + // draw the line; however, we have to restore the HDC before + // we draw focus or dragfeedback... + + rcLogical.left = 0; + rcLogical.bottom = 0; + rcLogical.right = lpLine->m_nWidthInHimetric; + rcLogical.top = lpLine->m_nHeightInHimetric; + + { + HBRUSH hbr; + RECT rcDraw; + + lpLine->m_fSelected = (BOOL)(itemState & ODS_SELECTED); + + if (ODS_SELECTED & itemState) { + /*Get proper txt colors */ + hbr = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT)); + } + else { + hbr = CreateSolidBrush(GetSysColor(COLOR_WINDOW)); + } + + rcDraw = *lprcPix; + rcDraw.right = lprcDevice->left; + FillRect(hDC, lprcPix, hbr); + + rcDraw = *lprcPix; + rcDraw.left = lprcDevice->right; + FillRect(hDC, lprcPix, hbr); + + DeleteObject(hbr); + } + + nMapModeOld=SetDCToAnisotropic(hDC, lprcDevice, &rcLogical, + (LPRECT)&rcWindowOld, (LPRECT)&rcViewportOld); + + // Set the default font size, and font face name + hfontOld = SelectObject(hDC, OutlineApp_GetActiveFont(g_lpApp)); + + Line_Draw(lpLine, hDC, &rcLogical, NULL, (ODS_SELECTED & itemState)); + + SelectObject(hDC, hfontOld); + + ResetOrigDC(hDC, nMapModeOld, (LPRECT)&rcWindowOld, + (LPRECT)&rcViewportOld); + +#if defined( OLE_CNTR ) + if ((itemState & ODS_SELECTED) && + (Line_GetLineType(lpLine)==CONTAINERLINETYPE)) + ContainerLine_DrawSelHilight( + (LPCONTAINERLINE)lpLine, + hDC, + lprcPix, + ODA_SELECT, + ODS_SELECTED + ); +#endif + + } + + /* If a list box item just gained or lost the focus, + * call function (which could check if ODS_FOCUS bit is set) + * and draws item in focus or non-focus state. + */ + if(itemAction & ODA_FOCUS ) + Line_DrawFocusRect(lpLine, hDC, lprcPix, itemAction, itemState); + + +#if defined( OLE_CNTR ) + if (Line_GetLineType(lpLine) == CONTAINERLINETYPE) { + LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)lpLine; + LPCONTAINERDOC lpDoc = lpContainerLine->m_lpDoc; + BOOL fIsLink; + RECT rcObj; + + if (ContainerDoc_GetShowObjectFlag(lpDoc)) { + ContainerLine_GetOleObjectRectInPixels(lpContainerLine, &rcObj); + fIsLink = ContainerLine_IsOleLink(lpContainerLine); + OleUIShowObject(&rcObj, hDC, fIsLink); + } + } +#endif + +#if defined( USE_DRAGDROP ) + if (lpLine->m_fDragOverLine) + Line_DrawDragFeedback(lpLine, hDC, lprcPix, itemState ); +#endif + +} + + +/* Line_Draw + * --------- + * + * Draw a line on a DC. + * + * Parameters: + * hDC - DC to which the line will be drawn + * lpRect - the object rect in logical coordinates + */ +void Line_Draw( + LPLINE lpLine, + HDC hDC, + LPRECT lpRect, + LPRECT lpRectWBounds, + BOOL fHighlight +) +{ + switch (lpLine->m_lineType) { + case TEXTLINETYPE: + TextLine_Draw( + (LPTEXTLINE)lpLine, hDC, lpRect,lpRectWBounds,fHighlight); + break; + +#if defined( OLE_CNTR ) + case CONTAINERLINETYPE: + ContainerLine_Draw( + (LPCONTAINERLINE)lpLine,hDC,lpRect,lpRectWBounds,fHighlight); + break; +#endif + + default: + return; // unknown line type + } + return; +} + + +/* Line_DrawSelHilight + * ------------------- + * + * Handles selection of list box item + */ +void Line_DrawSelHilight(LPLINE lpLine, HDC hDC, LPRECT lpRect, UINT itemAction, UINT itemState) +{ + switch (lpLine->m_lineType) { + case TEXTLINETYPE: + TextLine_DrawSelHilight((LPTEXTLINE)lpLine, hDC, lpRect, + itemAction, itemState); + break; + +#if defined( OLE_CNTR ) + case CONTAINERLINETYPE: + ContainerLine_DrawSelHilight((LPCONTAINERLINE)lpLine, hDC, lpRect, + itemAction, itemState); + break; +#endif + + default: + return; // unknown line type + } + return; + +} + +/* Line_DrawFocusRect + * ------------------ + * + * Handles focus state of list box item + */ +void Line_DrawFocusRect(LPLINE lpLine, HDC hDC, LPRECT lpRect, UINT itemAction, UINT itemState) +{ + if(lpLine) + DrawFocusRect(hDC, lpRect); +} + +#if defined( USE_DRAGDROP ) + +/* Line_DrawDragFeedback + * --------------------- + * + * Handles focus state of list box item + */ +void Line_DrawDragFeedback(LPLINE lpLine, HDC hDC, LPRECT lpRect, UINT itemState ) +{ + if(lpLine) + DrawFocusRect(hDC, lpRect); +} + +#endif // USE_DRAGDROP + + +/* Line_GetHeightInHimetric + * ------------------------ + * + * Return the height of the item in HIMETRIC units + */ +UINT Line_GetHeightInHimetric(LPLINE lpLine) +{ + if (!lpLine) + return 0; + + return (UINT)lpLine->m_nHeightInHimetric; +} + + +/* Line_SetHeightInHimetric + * ------------------------ + * + * Set the height of the item in HIMETRIC units. + */ +void Line_SetHeightInHimetric(LPLINE lpLine, int nHeight) +{ + if (!lpLine) + return; + + switch (lpLine->m_lineType) { + case TEXTLINETYPE: + TextLine_SetHeightInHimetric((LPTEXTLINE)lpLine, nHeight); + break; + +#if defined( OLE_CNTR ) + case CONTAINERLINETYPE: + ContainerLine_SetHeightInHimetric((LPCONTAINERLINE)lpLine, + nHeight); + break; +#endif + + } +} + + +/* Line_Delete + * ----------- + * + * Delete the Line structure + */ +void Line_Delete(LPLINE lpLine) +{ + switch (lpLine->m_lineType) { + case TEXTLINETYPE: + TextLine_Delete((LPTEXTLINE)lpLine); + break; + +#if defined( OLE_CNTR ) + case CONTAINERLINETYPE: + ContainerLine_Delete((LPCONTAINERLINE)lpLine); + break; +#endif + + default: + break; // unknown line type + } +} + + +/* Line_CopyToDoc + * -------------- + * + * Copy a line to another Document (usually ClipboardDoc) + */ +BOOL Line_CopyToDoc(LPLINE lpSrcLine, LPOUTLINEDOC lpDestDoc, int nIndex) +{ + switch (lpSrcLine->m_lineType) { + case TEXTLINETYPE: + return TextLine_CopyToDoc((LPTEXTLINE)lpSrcLine,lpDestDoc,nIndex); + break; + +#if defined( OLE_CNTR ) + case CONTAINERLINETYPE: + return ContainerLine_CopyToDoc( + (LPCONTAINERLINE)lpSrcLine, + lpDestDoc, + nIndex + ); + break; +#endif + + default: + return FALSE; // unknown line type + } +} + + +/* Line_SaveToStg + * -------------- + * + * Save a single line object to a storage + * + * Return TRUE if successful, FALSE otherwise + */ +BOOL Line_SaveToStg(LPLINE lpLine, UINT uFormat, LPSTORAGE lpSrcStg, LPSTORAGE lpDestStg, LPSTREAM lpLLStm, BOOL fRemember) +{ + LINERECORD_ONDISK lineRecord; + ULONG nWritten; + HRESULT hrErr; + BOOL fStatus; + LARGE_INTEGER dlibSavePos; + LARGE_INTEGER dlibZeroOffset; + LISet32( dlibZeroOffset, 0 ); + + /* save seek position before line record is written in case of error */ + hrErr = lpLLStm->lpVtbl->Seek( + lpLLStm, + dlibZeroOffset, + STREAM_SEEK_CUR, + (ULARGE_INTEGER FAR*)&dlibSavePos + ); + if (hrErr != NOERROR) return FALSE; + +#if defined( OLE_CNTR ) + if (lpLine->m_lineType == CONTAINERLINETYPE) { + /* OLE2NOTE: asking an OLE object to save may cause the + ** object to send an OnViewChange notification if there are any + ** outstanding changes to the object. this is particularly true + ** for objects with coarse update granularity like OLE 1.0 + ** objects. if an OnViewChange notification is received then the + ** object's presentation cache will be updated BEFORE it is + ** saved. It is important that the extents stored as part of + ** the ContainerLine/Line record associated with the OLE object + ** are updated before the Line data is saved to the storage. it + ** is important that this extent information matches the data + ** saved with the OLE object. the Line extent information is + ** updated in the IAdviseSink::OnViewChange method implementation. + */ + // only save the OLE object if format is compatible. + if (uFormat != ((LPCONTAINERAPP)g_lpApp)->m_cfCntrOutl) + goto error; + + fStatus = ContainerLine_SaveOleObjectToStg( + (LPCONTAINERLINE)lpLine, + lpSrcStg, + lpDestStg, + fRemember + ); + if (! fStatus) goto error; + } +#endif + + // Compilers should handle aligment correctly + lineRecord.m_lineType = (USHORT) lpLine->m_lineType; + lineRecord.m_nTabLevel = (USHORT) lpLine->m_nTabLevel; + lineRecord.m_nTabWidthInHimetric = (USHORT) lpLine->m_nTabWidthInHimetric; + lineRecord.m_nWidthInHimetric = (USHORT) lpLine->m_nWidthInHimetric; + lineRecord.m_nHeightInHimetric = (USHORT) lpLine->m_nHeightInHimetric; + lineRecord.m_reserved = 0; + + /* write line record header */ + hrErr = lpLLStm->lpVtbl->Write( + lpLLStm, + (LPVOID)&lineRecord, + sizeof(lineRecord), + &nWritten + ); + + if (hrErr != NOERROR) { + OleDbgOutHResult("Write Line header returned", hrErr); + goto error; + } + + switch (lpLine->m_lineType) { + case TEXTLINETYPE: + fStatus = TextLine_SaveToStm((LPTEXTLINE)lpLine, lpLLStm); + if (! fStatus) goto error; + break; + +#if defined( OLE_CNTR ) + case CONTAINERLINETYPE: + fStatus=ContainerLine_SaveToStm((LPCONTAINERLINE)lpLine,lpLLStm); + if (! fStatus) goto error; + break; +#endif + + default: + goto error; // unknown line type + } + + return TRUE; + +error: + + /* retore seek position prior to writing Line record */ + lpLLStm->lpVtbl->Seek( + lpLLStm, + dlibSavePos, + STREAM_SEEK_SET, + NULL + ); + + return FALSE; +} + + +/* Line_LoadFromStg + * ---------------- + * + * Load a single line object from storage + */ +LPLINE Line_LoadFromStg(LPSTORAGE lpSrcStg, LPSTREAM lpLLStm, LPOUTLINEDOC lpDestDoc) +{ + LINERECORD_ONDISK lineRecord; + LPLINE lpLine = NULL; + ULONG nRead; + HRESULT hrErr; + + /* read line record header */ + hrErr = lpLLStm->lpVtbl->Read( + lpLLStm, + (LPVOID)&lineRecord, + sizeof(lineRecord), + &nRead + ); + + if (hrErr != NOERROR) { + OleDbgOutHResult("Read Line header returned", hrErr); + return NULL; + } + + switch ((LINETYPE) lineRecord.m_lineType) { + case TEXTLINETYPE: + lpLine = TextLine_LoadFromStg(lpSrcStg, lpLLStm, lpDestDoc); + break; + +#if defined( OLE_CNTR ) + case CONTAINERLINETYPE: + lpLine = ContainerLine_LoadFromStg(lpSrcStg, lpLLStm, lpDestDoc); + break; +#endif + + default: + return NULL; // unknown line type + } + + lpLine->m_lineType = (LINETYPE) lineRecord.m_lineType; + lpLine->m_nTabLevel = (UINT) lineRecord.m_nTabLevel; + lpLine->m_nTabWidthInHimetric = (UINT) lineRecord.m_nTabWidthInHimetric; + lpLine->m_nWidthInHimetric = (UINT) lineRecord.m_nWidthInHimetric; + lpLine->m_nHeightInHimetric = (UINT) lineRecord.m_nHeightInHimetric; + + return lpLine; +} + + +/* Line_IsSelected + * --------------- + * + * Return the selection state of the line + */ +BOOL Line_IsSelected(LPLINE lpLine) +{ + if (!lpLine) + return FALSE; + + return lpLine->m_fSelected; +} diff --git a/private/oleutest/letest/outline/outllist.c b/private/oleutest/letest/outline/outllist.c new file mode 100644 index 000000000..b263eebba --- /dev/null +++ b/private/oleutest/letest/outline/outllist.c @@ -0,0 +1,1183 @@ +/************************************************************************* +** +** OLE 2 Sample Code +** +** outldata.c +** +** This file contains LineList and NameTable functions +** and related support functions. +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + + +#include "outline.h" + +OLEDBGDATA + +extern LPOUTLINEAPP g_lpApp; + +char ErrMsgListBox[] = "Can't create ListBox!"; + +static int g_iMapMode; + +/* LineList_Init + * ------------- + * + * Create and Initialize the LineList (owner-drawn listbox) + */ +BOOL LineList_Init(LPLINELIST lpLL, LPOUTLINEDOC lpOutlineDoc) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + +#if defined( INPLACE_CNTR ) + lpLL->m_hWndListBox = CreateWindow( + "listbox", /* Window class name */ + NULL, /* Window's title */ + + /* OLE2NOTE: an in-place contanier MUST use + ** WS_CLIPCHILDREN window style for the window + ** that it uses as the parent for the server's + ** in-place active window so that its + ** painting does NOT interfere with the painting + ** of the server's in-place active child window. + */ + + WS_CLIPCHILDREN | + WS_CHILDWINDOW | + WS_VISIBLE | + WS_VSCROLL | + WS_HSCROLL | + LBS_EXTENDEDSEL | + LBS_NOTIFY | + LBS_OWNERDRAWVARIABLE | + LBS_NOINTEGRALHEIGHT | + LBS_USETABSTOPS, + 0, 0, /* Use default X, Y */ + 0, 0, /* Use default X, Y */ + lpOutlineDoc->m_hWndDoc,/* Parent window's handle */ + (HMENU)IDC_LINELIST, /* Child Window ID */ + lpOutlineApp->m_hInst, /* Instance of window */ + NULL); /* Create struct for WM_CREATE */ +#else + lpLL->m_hWndListBox = CreateWindow( + "listbox", /* Window class name */ + NULL, /* Window's title */ + WS_CHILDWINDOW | + WS_VISIBLE | + WS_VSCROLL | + WS_HSCROLL | + LBS_EXTENDEDSEL | + LBS_NOTIFY | + LBS_OWNERDRAWVARIABLE | + LBS_NOINTEGRALHEIGHT | + LBS_USETABSTOPS, + 0, 0, /* Use default X, Y */ + 0, 0, /* Use default X, Y */ + lpOutlineDoc->m_hWndDoc,/* Parent window's handle */ + (HMENU)IDC_LINELIST, /* Child Window ID */ + lpOutlineApp->m_hInst, /* Instance of window */ + NULL); /* Create struct for WM_CREATE */ + +#endif + + + if(! lpLL->m_hWndListBox) { + OutlineApp_ErrorMessage(g_lpApp, ErrMsgListBox); + return FALSE; + } + + lpOutlineApp->m_ListBoxWndProc = + (FARPROC) GetWindowLong ( lpLL->m_hWndListBox, GWL_WNDPROC ); + SetWindowLong (lpLL->m_hWndListBox, GWL_WNDPROC, (LONG) LineListWndProc); + +#if defined ( USE_DRAGDROP ) + /* m_iDragOverLine saves index of line that has drag/drop target + ** feedback. we currently use our focus rectangle feedback for + ** this. it would be better to have a different visual feedback + ** for potential target of the pending drop. + */ + lpLL->m_iDragOverLine = -1; +#endif + + lpLL->m_nNumLines = 0; + lpLL->m_nMaxLineWidthInHimetric = 0; + lpLL->m_lpDoc = lpOutlineDoc; + _fmemset(&lpLL->m_lrSaveSel, 0, sizeof(LINERANGE)); + + return TRUE; +} + + +/* LineList_Destroy + * ---------------- + * + * Clear (delete) all Line objects from the list and free supporting + * memory (ListBox Window) used by the LineList object itself. + */ +void LineList_Destroy(LPLINELIST lpLL) +{ + int i; + int linesTotal = lpLL->m_nNumLines; + + // Delete all Line objects + for (i = 0; i < linesTotal; i++) + LineList_DeleteLine(lpLL, 0); // NOTE: always delete line 0 + + // Remove all Lines from the ListBox + SendMessage(lpLL->m_hWndListBox,LB_RESETCONTENT,0,0L); + + lpLL->m_nNumLines=0; + DestroyWindow(lpLL->m_hWndListBox); + lpLL->m_hWndListBox = NULL; +} + + +/* LineList_AddLine + * ---------------- + * + * Add one line to the list box. The line is added following the + * line with index "nIndex". If nIndex is larger than the number of lines + * in the ListBox, then the line is appended to the end. The selection + * is set to the newly added line. + */ +void LineList_AddLine(LPLINELIST lpLL, LPLINE lpLine, int nIndex) +{ + int nAddIndex = (lpLL->m_nNumLines == 0 ? + 0 : + (nIndex >= lpLL->m_nNumLines ? lpLL->m_nNumLines : nIndex+1)); + LINERANGE lrSel; + +#if defined( USE_HEADING ) + int nHeight = Line_GetHeightInHimetric(lpLine); + + nHeight = XformHeightInHimetricToPixels(NULL, nHeight); + + // Add a dummy string to the row heading + Heading_RH_SendMessage(OutlineDoc_GetHeading(lpLL->m_lpDoc), + LB_INSERTSTRING, (WPARAM)nAddIndex, MAKELPARAM(nHeight, 0)); +#endif + + + lrSel.m_nStartLine = nAddIndex; + lrSel.m_nEndLine = nAddIndex; + + if (!lpLine) { + OutlineApp_ErrorMessage(g_lpApp, "Could not create line."); + return; + } + + SendMessage(lpLL->m_hWndListBox, LB_INSERTSTRING, (WPARAM)nAddIndex, + (DWORD)lpLine); + + LineList_SetMaxLineWidthInHimetric( + lpLL, + Line_GetTotalWidthInHimetric(lpLine) + ); + + lpLL->m_nNumLines++; + + LineList_SetSel(lpLL, &lrSel); +} + + +/* LineList_DeleteLine + * ------------------- + * + * Delete one line from listbox and memory + */ +void LineList_DeleteLine(LPLINELIST lpLL, int nIndex) +{ + LPLINE lpLine = LineList_GetLine(lpLL, nIndex); + BOOL fResetSel; + + fResetSel = (BOOL)SendMessage(lpLL->m_hWndListBox, LB_GETSEL, (WPARAM)nIndex, 0L); + + if (lpLine) + Line_Delete(lpLine); // free memory of Line + + // Remove the Line from the ListBox + SendMessage(lpLL->m_hWndListBox, LB_DELETESTRING, (WPARAM)nIndex, 0L); + lpLL->m_nNumLines--; + + if (fResetSel) { + if (nIndex > 0) { +#if defined( WIN32 ) + SendMessage( + lpLL->m_hWndListBox, + LB_SETSEL, + (WPARAM)TRUE, + (LPARAM)nIndex-1 + ); +#else + SendMessage( + lpLL->m_hWndListBox, + LB_SETSEL, + (WPARAM)TRUE, + MAKELPARAM(nIndex-1,0) + ); +#endif + } else { + if (lpLL->m_nNumLines > 0) { +#if defined( WIN32 ) + SendMessage( + lpLL->m_hWndListBox, + LB_SETSEL, + (WPARAM)TRUE, + (LPARAM)0 + ); +#else + SendMessage( + lpLL->m_hWndListBox, + LB_SETSEL, + (WPARAM)TRUE, + MAKELPARAM(0,0) + ); +#endif + } + } + } + +#if defined( USE_HEADING ) + // Remove the dummy string from the row heading + Heading_RH_SendMessage(OutlineDoc_GetHeading(lpLL->m_lpDoc), + LB_DELETESTRING, (WPARAM)nIndex, 0L); +#endif + +} + + +/* LineList_ReplaceLine + * -------------------- + * + * Replace the line at a given index in the list box with a new + * line. + */ +void LineList_ReplaceLine(LPLINELIST lpLL, LPLINE lpLine, int nIndex) +{ + LPLINE lpOldLine = LineList_GetLine(lpLL, nIndex); + + if (lpOldLine) + Line_Delete(lpOldLine); // free memory of Line + else + return; // if no previous line then invalid index + + SendMessage( + lpLL->m_hWndListBox, + LB_SETITEMDATA, + (WPARAM)nIndex, + (LPARAM)lpLine + ); +} + + +/* LineList_GetLineIndex + * --------------------- + * + * Return the index of the Line given a pointer to the line. + * Return -1 if the line is not found. + */ +int LineList_GetLineIndex(LPLINELIST lpLL, LPLINE lpLine) +{ + LRESULT lRet; + + if (! lpLine) return -1; + + lRet = SendMessage( + lpLL->m_hWndListBox, + LB_FINDSTRING, + (WPARAM)-1, + (LPARAM)(LPCSTR)lpLine + ); + + return ((lRet == LB_ERR) ? -1 : (int)lRet); +} + + +/* LineList_GetLine + * ---------------- + * + * Retrieve the pointer to the Line given its index in the LineList + */ +LPLINE LineList_GetLine(LPLINELIST lpLL, int nIndex) +{ + DWORD dWord; + LRESULT lRet; + + if (lpLL->m_nNumLines == 0 || nIndex > lpLL->m_nNumLines || nIndex < 0) + return NULL; + + lRet = SendMessage( + lpLL->m_hWndListBox,LB_GETTEXT,nIndex,(LPARAM)(LPCSTR)&dWord); + + return ((lRet == LB_ERR || lRet == 0) ? NULL : (LPLINE)dWord); +} + + +/* LineList_SetFocusLine + * --------------------- + * + */ + +void LineList_SetFocusLine ( LPLINELIST lpLL, WORD wIndex ) +{ + + SendMessage(lpLL->m_hWndListBox, LB_SETCARETINDEX, (WPARAM)wIndex, 0L ); + +} + + +/* LineList_GetLineRect + * -------------------- + * + * Retrieve the rectangle of a Line given its index in the LineList + */ +BOOL LineList_GetLineRect(LPLINELIST lpLL, int nIndex, LPRECT lpRect) +{ + DWORD iReturn = (DWORD)LB_ERR; + + if ( !(lpLL->m_nNumLines == 0 || nIndex > lpLL->m_nNumLines || nIndex < 0) ) + iReturn = SendMessage(lpLL->m_hWndListBox,LB_GETITEMRECT,nIndex,(LPARAM)lpRect); + + return (iReturn == LB_ERR ? FALSE : TRUE ); +} + + +/* LineList_GetFocusLineIndex + * -------------------------- + * + * Get the index of the line that currently has focus (the active line). + */ +int LineList_GetFocusLineIndex(LPLINELIST lpLL) +{ + return (int)SendMessage(lpLL->m_hWndListBox,LB_GETCARETINDEX,0,0L); +} + + +/* LineList_GetCount + * ----------------- + * + * Return number of line objects + */ +int LineList_GetCount(LPLINELIST lpLL) +{ + if (lpLL) + return lpLL->m_nNumLines; + else { + OleDbgAssert(lpLL!=NULL); + return 0; + } +} + + +/* LineList_SetMaxLineWidthInHimetric + * ---------------------------------- + * + * Adjust the maximum line width for the listbox. The max line width is + * used to determine if a horizontal scroll bar is needed. + * + * Parameters: + * nWidthInHimetric - if +ve, width of an additional line + * - if -ve, reset Max to be the value + * + * Returns: + * TRUE is max line width of LineList changed + * FALSE if no change + */ +BOOL LineList_SetMaxLineWidthInHimetric(LPLINELIST lpLL, int nWidthInHimetric) +{ + int nWidthInPix; + BOOL fSizeChanged = FALSE; + LPSCALEFACTOR lpscale; + + if (!lpLL) + return FALSE; + + lpscale = OutlineDoc_GetScaleFactor(lpLL->m_lpDoc); + + if (nWidthInHimetric < 0) { + lpLL->m_nMaxLineWidthInHimetric = -1; + nWidthInHimetric *= -1; + } + + if (nWidthInHimetric > lpLL->m_nMaxLineWidthInHimetric) { + lpLL->m_nMaxLineWidthInHimetric = nWidthInHimetric; + nWidthInPix = XformWidthInHimetricToPixels(NULL, nWidthInHimetric + + LOWORD(OutlineDoc_GetMargin(lpLL->m_lpDoc)) + + HIWORD(OutlineDoc_GetMargin(lpLL->m_lpDoc))); + + nWidthInPix = (int)(nWidthInPix * lpscale->dwSxN / lpscale->dwSxD); + SendMessage( + lpLL->m_hWndListBox, + LB_SETHORIZONTALEXTENT, + nWidthInPix, + 0L + ); + fSizeChanged = TRUE; + +#if defined( USE_HEADING ) + Heading_CH_SetHorizontalExtent( + OutlineDoc_GetHeading(lpLL->m_lpDoc), lpLL->m_hWndListBox); +#endif + + } + return fSizeChanged; +} + + +/* LineList_GetMaxLineWidthInHimetric + * ---------------------------------- + * + * Return the width of the widest line + */ +int LineList_GetMaxLineWidthInHimetric(LPLINELIST lpLL) +{ + return lpLL->m_nMaxLineWidthInHimetric; +} + + +/* LineList_RecalcMaxLineWidthInHimetric + * ------------------------------------- + * + * Recalculate the maximum line width in the entire list. + * + * Parameters: + * nWidthInHimetric should be set to the width of line being removed. + * nWidthInHimetric == 0 forces list to recalculate in all cases. + * nWidthInHimetric == current max width => forces recalc. + * + * Returns: + * TRUE is max line width of LineList changed + * FALSE if no change + */ +BOOL LineList_RecalcMaxLineWidthInHimetric( + LPLINELIST lpLL, + int nWidthInHimetric +) +{ + int i; + LPLINE lpLine; + BOOL fSizeChanged = FALSE; + int nOrgMaxLineWidthInHimetric = lpLL->m_nMaxLineWidthInHimetric; + + if (nWidthInHimetric == 0 || + nWidthInHimetric == lpLL->m_nMaxLineWidthInHimetric) { + + lpLL->m_nMaxLineWidthInHimetric = -1; + + LineList_SetMaxLineWidthInHimetric(lpLL, 0); + + for(i = 0; i < lpLL->m_nNumLines; i++) { + lpLine=LineList_GetLine(lpLL, i); + LineList_SetMaxLineWidthInHimetric( + lpLL, + Line_GetTotalWidthInHimetric(lpLine) + ); + } + } + + if (nOrgMaxLineWidthInHimetric != lpLL->m_nMaxLineWidthInHimetric) + fSizeChanged = TRUE; + + return fSizeChanged; +} + + +/* LineList_CalcSelExtentInHimetric + * -------------------------------- + * + * Calculate the extents (widht and height) of a selection of lines. + * + * if lplrSel == NULL, calculate extent of all lines. + */ +void LineList_CalcSelExtentInHimetric( + LPLINELIST lpLL, + LPLINERANGE lplrSel, + LPSIZEL lpsizel +) +{ + int i; + int nEndLine; + int nStartLine; + LPLINE lpLine; + long lWidth; + + if (lplrSel) { + nEndLine = lplrSel->m_nEndLine; + nStartLine = lplrSel->m_nStartLine; + } else { + nEndLine = LineList_GetCount(lpLL) - 1; + nStartLine = 0; + } + + lpsizel->cx = 0; + lpsizel->cy = 0; + + for(i = nStartLine; i <= nEndLine; i++) { + lpLine=LineList_GetLine(lpLL,i); + if (lpLine) { + lWidth = (long)Line_GetTotalWidthInHimetric(lpLine); + lpsizel->cx = max(lpsizel->cx, lWidth); + lpsizel->cy += lpLine->m_nHeightInHimetric; + } + } +} + + +/* LineList_GetWindow + * ------------------ + * + * Return handle of list box + */ +HWND LineList_GetWindow(LPLINELIST lpLL) +{ + return lpLL->m_hWndListBox; +} + + +/* LineList_GetDC + * -------------- + * + * Return DC handle of list box + */ +HDC LineList_GetDC(LPLINELIST lpLL) +{ + HFONT hfontOld; + HDC hDC = GetDC(lpLL->m_hWndListBox); + int iXppli; //* pixels per logical inch along width + int iYppli; //* pixels per logical inch along height + SIZE size; + + // Setup a mapping mode for the DC which maps physical pixel + // coordinates to HIMETRIC units. The standard MM_HIMETRIC mapping + // mode does not work correctly because it does not take into + // account that a logical inch on the display screen is drawn + // physically larger than 1 inch. We will setup an anisotropic + // mapping mode which will perform the transformation properly. + + g_iMapMode = SetMapMode(hDC, MM_ANISOTROPIC); + iXppli = GetDeviceCaps (hDC, LOGPIXELSX); + iYppli = GetDeviceCaps (hDC, LOGPIXELSY); + SetViewportExtEx(hDC, iXppli, iYppli, &size); + SetWindowExtEx(hDC, HIMETRIC_PER_INCH, HIMETRIC_PER_INCH, &size); + + // Set the default font size, and font face name + hfontOld = SelectObject(hDC, OutlineApp_GetActiveFont(g_lpApp)); + + return hDC; +} + + +/* LineList_ReleaseDC + * ------------------ + * + * Release DC of list box returned from previous LineList_GetDC call. + */ +void LineList_ReleaseDC(LPLINELIST lpLL, HDC hDC) +{ + SetMapMode(hDC, g_iMapMode); + ReleaseDC(lpLL->m_hWndListBox, hDC); +} + + +/* LineList_SetLineHeight + * ---------------------- + * + * Set the height of a line in the LineList list box + */ +void LineList_SetLineHeight(LPLINELIST lpLL,int nIndex,int nHeightInHimetric) +{ + LPARAM lParam; + LPOUTLINEDOC lpDoc; + LPSCALEFACTOR lpscale; + UINT uHeightInPix; + LPHEADING lphead; + + if (!lpLL) + return; + + lpDoc = lpLL->m_lpDoc; + lphead = OutlineDoc_GetHeading(lpDoc); + lpscale = OutlineDoc_GetScaleFactor(lpDoc); + + uHeightInPix = XformHeightInHimetricToPixels(NULL, nHeightInHimetric); + + Heading_RH_SendMessage(lphead, LB_SETITEMDATA, (WPARAM)nIndex, + MAKELPARAM(uHeightInPix, 0)); + + uHeightInPix = (UINT)(uHeightInPix * lpscale->dwSyN / lpscale->dwSyD); + + if (uHeightInPix > LISTBOX_HEIGHT_LIMIT) + uHeightInPix = LISTBOX_HEIGHT_LIMIT; + + + lParam = MAKELPARAM(uHeightInPix, 0); + SendMessage(lpLL->m_hWndListBox,LB_SETITEMHEIGHT,(WPARAM)nIndex, lParam); + Heading_RH_SendMessage(lphead, LB_SETITEMHEIGHT, (WPARAM)nIndex, lParam); + Heading_RH_ForceRedraw(lphead, TRUE); +} + + +/* LineList_ReScale + * ---------------- + * + * Re-scale the LineList list box + */ +void LineList_ReScale(LPLINELIST lpLL, LPSCALEFACTOR lpscale) +{ + int nIndex; + LPLINE lpLine; + UINT uWidthInHim; + + if (!lpLL) + return; + + for (nIndex = 0; nIndex < lpLL->m_nNumLines; nIndex++) { + lpLine = LineList_GetLine(lpLL, nIndex); + if (lpLine) { + LineList_SetLineHeight( + lpLL, + nIndex, + Line_GetHeightInHimetric(lpLine) + ); + } + } + + uWidthInHim = LineList_GetMaxLineWidthInHimetric(lpLL); + LineList_SetMaxLineWidthInHimetric(lpLL, -(int)uWidthInHim); +} + +/* LineList_SetSel + * --------------- + * + * Set the selection in list box + */ +void LineList_SetSel(LPLINELIST lpLL, LPLINERANGE lplrSel) +{ + DWORD dwSel; + + if (lpLL->m_nNumLines <= 0 || lplrSel->m_nStartLine < 0) + return; // no lines in list; can't set a selection + + dwSel = MAKELPARAM(lplrSel->m_nStartLine, lplrSel->m_nEndLine); + + lpLL->m_lrSaveSel = *lplrSel; + + /* remove previous selection */ +#if defined( WIN32 ) + SendMessage( + lpLL->m_hWndListBox, + LB_SETSEL, + (WPARAM)FALSE, + (LPARAM)-1 + ); +#else + SendMessage( + lpLL->m_hWndListBox, + LB_SETSEL, + (WPARAM)FALSE, + MAKELPARAM(-1,0) + ); +#endif + + /* mark selection */ + SendMessage(lpLL->m_hWndListBox,LB_SELITEMRANGE, (WPARAM)TRUE, (LPARAM)dwSel); + /* set focus line (caret) */ + LineList_SetFocusLine ( lpLL, (WORD)lplrSel->m_nStartLine ); + +} + + +/* LineList_GetSel + * --------------- + * + * Get the selection in list box. + * + * Returns the count of items selected + */ +int LineList_GetSel(LPLINELIST lpLL, LPLINERANGE lplrSel) +{ + int nNumSel=(int)SendMessage(lpLL->m_hWndListBox,LB_GETSELCOUNT,0,0L); + + if (nNumSel) { + SendMessage(lpLL->m_hWndListBox,LB_GETSELITEMS, + (WPARAM)1,(LPARAM)(int FAR*)&(lplrSel->m_nStartLine)); + lplrSel->m_nEndLine = lplrSel->m_nStartLine + nNumSel - 1; + } else { + _fmemset(lplrSel, 0, sizeof(LINERANGE)); + } + return nNumSel; +} + + +/* LineList_RemoveSel + * ------------------ + * + * Remove the selection in list box but save the selection state so that + * it can be restored by calling LineList_RestoreSel + * LineList_RemoveSel is called when the LineList window looses focus. + */ +void LineList_RemoveSel(LPLINELIST lpLL) +{ + LINERANGE lrSel; + if (LineList_GetSel(lpLL, &lrSel) > 0) { + lpLL->m_lrSaveSel = lrSel; +#if defined( WIN32 ) + SendMessage( + lpLL->m_hWndListBox, + LB_SETSEL, + (WPARAM)FALSE, + (LPARAM)-1 + ); +#else + SendMessage( + lpLL->m_hWndListBox, + LB_SETSEL, + (WPARAM)FALSE, + MAKELPARAM(-1,0) + ); +#endif + } +} + + +/* LineList_RestoreSel + * ------------------ + * + * Restore the selection in list box that was previously saved by a call to + * LineList_RemoveSel. + * LineList_RestoreSel is called when the LineList window gains focus. + */ +void LineList_RestoreSel(LPLINELIST lpLL) +{ + LineList_SetSel(lpLL, &lpLL->m_lrSaveSel); +} + + +/* LineList_SetRedraw + * ------------------ + * + * Enable/Disable the redraw of the linelist (listbox) on screen + * + * fEnbaleDraw = TRUE - enable redraw + * FALSE - disable redraw + */ +void LineList_SetRedraw(LPLINELIST lpLL, BOOL fEnableDraw) +{ + SendMessage(lpLL->m_hWndListBox,WM_SETREDRAW,(WPARAM)fEnableDraw,0L); +} + + +/* LineList_ForceRedraw + * -------------------- + * + * Force redraw of the linelist (listbox) on screen + */ +void LineList_ForceRedraw(LPLINELIST lpLL, BOOL fErase) +{ + InvalidateRect(lpLL->m_hWndListBox, NULL, fErase); +} + + +/* LineList_ForceLineRedraw + * ------------------------ + * + * Force a particular line of the linelist (listbox) to redraw. + */ +void LineList_ForceLineRedraw(LPLINELIST lpLL, int nIndex, BOOL fErase) +{ + RECT rect; + + LineList_GetLineRect( lpLL, nIndex, (LPRECT)&rect ); + InvalidateRect( lpLL->m_hWndListBox, (LPRECT)&rect, fErase ); +} + + +/* LineList_ScrollLineIntoView + * --------------------------- + * Make sure that the specified line is in view; if necessary scroll + * the listbox. if any portion of the line is visible, then no + * scrolling will occur. + */ +void LineList_ScrollLineIntoView(LPLINELIST lpLL, int nIndex) +{ + RECT rcWindow; + RECT rcLine; + RECT rcInt; + + if ( lpLL->m_nNumLines == 0 ) + return; + + if (! LineList_GetLineRect( lpLL, nIndex, (LPRECT)&rcLine ) ) + return; + + GetClientRect( lpLL->m_hWndListBox, (LPRECT) &rcWindow ); + + if (! IntersectRect((LPRECT)&rcInt, (LPRECT)&rcWindow, (LPRECT)&rcLine)) + SendMessage( + lpLL->m_hWndListBox, + LB_SETTOPINDEX, + (WPARAM)nIndex, + (LPARAM)NULL + ); +} + + +/* LineList_CopySelToDoc + * --------------------- + * + * Copy the selection of the linelist to another document + * + * RETURNS: number of lines copied. + */ +int LineList_CopySelToDoc( + LPLINELIST lpSrcLL, + LPLINERANGE lplrSel, + LPOUTLINEDOC lpDestDoc +) +{ + int nEndLine; + int nStartLine; + LPLINELIST lpDestLL = &lpDestDoc->m_LineList; + signed short nDestIndex = LineList_GetFocusLineIndex(lpDestLL); + LPLINE lpSrcLine; + int nCopied = 0; + int i; + + if (lplrSel) { + nEndLine = lplrSel->m_nEndLine; + nStartLine = lplrSel->m_nStartLine; + } else { + nEndLine = LineList_GetCount(lpSrcLL) - 1; + nStartLine = 0; + } + + for(i = nStartLine; i <= nEndLine; i++) { + lpSrcLine = LineList_GetLine(lpSrcLL, i); + if (lpSrcLine && Line_CopyToDoc(lpSrcLine, lpDestDoc, nDestIndex)) { + nDestIndex++; + nCopied++; + } + } + + return nCopied; +} + + +/* LineList_SaveSelToStg + * --------------------- + * + * Save lines in selection into lpDestStg. + * + * Return TRUE if ok, FALSE if error + */ +BOOL LineList_SaveSelToStg( + LPLINELIST lpLL, + LPLINERANGE lplrSel, + UINT uFormat, + LPSTORAGE lpSrcStg, + LPSTORAGE lpDestStg, + LPSTREAM lpLLStm, + BOOL fRemember +) +{ + int nEndLine; + int nStartLine; + int nNumLinesWritten = 0; + HRESULT hrErr = NOERROR; + ULONG nWritten; + LPLINE lpLine; + LINELISTHEADER_ONDISK llhRecord; + int i; + LARGE_INTEGER dlibSaveHeaderPos; + LARGE_INTEGER dlibZeroOffset; + LISet32( dlibZeroOffset, 0 ); + + if (lplrSel) { + nEndLine = lplrSel->m_nEndLine; + nStartLine = lplrSel->m_nStartLine; + } else { + nEndLine = LineList_GetCount(lpLL) - 1; + nStartLine = 0; + } + + _fmemset(&llhRecord,0,sizeof(llhRecord)); + + /* save seek position for LineList header record */ + hrErr = lpLLStm->lpVtbl->Seek( + lpLLStm, + dlibZeroOffset, + STREAM_SEEK_CUR, + (ULARGE_INTEGER FAR*)&dlibSaveHeaderPos + ); + if (hrErr != NOERROR) goto error; + + /* write LineList header record */ + hrErr = lpLLStm->lpVtbl->Write( + lpLLStm, + (LPVOID)&llhRecord, + sizeof(llhRecord), + &nWritten + ); + if (hrErr != NOERROR) { + OleDbgOutHResult("Write LineList header returned", hrErr); + goto error; + } + + for(i = nStartLine; i <= nEndLine; i++) { + lpLine = LineList_GetLine(lpLL, i); + if(lpLine && + Line_SaveToStg(lpLine, uFormat, lpSrcStg, lpDestStg, lpLLStm, + fRemember)) + llhRecord.m_nNumLines++; + } + + /* retore seek position for LineList header record */ + hrErr = lpLLStm->lpVtbl->Seek( + lpLLStm, + dlibSaveHeaderPos, + STREAM_SEEK_SET, + NULL + ); + if (hrErr != NOERROR) goto error; + + /* write LineList header record */ + hrErr = lpLLStm->lpVtbl->Write( + lpLLStm, + (LPVOID)&llhRecord, + sizeof(llhRecord), + &nWritten + ); + if (hrErr != NOERROR) goto error; + + /* reset seek position to end of stream */ + hrErr = lpLLStm->lpVtbl->Seek( + lpLLStm, + dlibZeroOffset, + STREAM_SEEK_END, + NULL + ); + if (hrErr != NOERROR) goto error; + + return TRUE; + +error: +#if defined( _DEBUG ) + OleDbgAssertSz( + hrErr == NOERROR, + "Could not write LineList header to LineList stream" + ); +#endif + return FALSE; +} + + +/* LineList_LoadFromStg + * -------------------- + * + * Load lines into linelist from storage. + * + * Return TRUE if ok, FALSE if error + */ +BOOL LineList_LoadFromStg( + LPLINELIST lpLL, + LPSTORAGE lpSrcStg, + LPSTREAM lpLLStm +) +{ + HRESULT hrErr; + ULONG nRead; + LPLINE lpLine; + int i; + int nNumLines; + LINELISTHEADER_ONDISK llineRecord; + + /* write LineList header record */ + hrErr = lpLLStm->lpVtbl->Read( + lpLLStm, + (LPVOID)&llineRecord, + sizeof(llineRecord), + &nRead + ); + + if (hrErr != NOERROR) { + OleDbgOutHResult("Read LineList header returned", hrErr); + goto error; + } + + nNumLines = (int) llineRecord.m_nNumLines; + + for(i = 0; i < nNumLines; i++) { + lpLine = Line_LoadFromStg(lpSrcStg, lpLLStm, lpLL->m_lpDoc); + if (! lpLine) + goto error; + + // Directly add lines to LineList without trying to update a NameTbl + LineList_AddLine(lpLL, lpLine, i-1); + } + + return TRUE; + +error: + // Delete any Line objects that were created + if (lpLL->m_nNumLines > 0) { + int nNumLines = lpLL->m_nNumLines; + for (i = 0; i < nNumLines; i++) + LineList_DeleteLine(lpLL, i); + } + + return FALSE; +} + + +#if defined( USE_DRAGDROP ) + + +/* LineList_SetFocusLineFromPointl + * ------------------------------- + * + */ + +void LineList_SetFocusLineFromPointl( LPLINELIST lpLL, POINTL pointl ) +{ + int i = LineList_GetLineIndexFromPointl( lpLL, pointl ); + + if ( i == (int)-1) + return ; + else + LineList_SetFocusLine( lpLL, (WORD)i ); +} + + +/* LineList_SetDragOverLineFromPointl + * ---------------------------------- + * + */ + +void LineList_SetDragOverLineFromPointl ( LPLINELIST lpLL, POINTL pointl ) +{ + int nIndex = LineList_GetLineIndexFromPointl( lpLL, pointl ); + LPLINE lpline = LineList_GetLine( lpLL, nIndex ); + + if (!lpline) + return; + + if (! lpline->m_fDragOverLine) { + /* user has dragged over a new line. force new drop target line + ** to repaint so that drop feedback will be drawn. + */ + lpline->m_fDragOverLine = TRUE; + LineList_ForceLineRedraw( lpLL, nIndex, TRUE /*fErase*/); + + if (lpLL->m_iDragOverLine!= -1 && lpLL->m_iDragOverLine!=nIndex) { + + /* force previous drop target line to repaint so that drop + ** feedback will be undrawn + */ + lpline = LineList_GetLine( lpLL, lpLL->m_iDragOverLine ); + if (lpline) + lpline->m_fDragOverLine = FALSE; + + LineList_ForceLineRedraw( + lpLL,lpLL->m_iDragOverLine,TRUE /*fErase*/); + } + + lpLL->m_iDragOverLine = nIndex; + + // Force repaint immediately + UpdateWindow(lpLL->m_hWndListBox); + } +} + + +/* LineList_Scroll + * --------------- + * + * Scroll the LineList list box in the desired direction by one line. + * + * this function is called during a drag operation. + */ + +void LineList_Scroll(LPLINELIST lpLL, DWORD dwScrollDir) +{ + switch (dwScrollDir) { + case SCROLLDIR_UP: + SendMessage( lpLL->m_hWndListBox, WM_VSCROLL, SB_LINEUP, 0L ); + break; + + case SCROLLDIR_DOWN: + SendMessage( lpLL->m_hWndListBox, WM_VSCROLL, SB_LINEDOWN, 0L ); + break; + } +} + + +/* LineList_GetLineIndexFromPointl + * ------------------------------- + * do hit test to get index of line corresponding to pointl + */ +int LineList_GetLineIndexFromPointl(LPLINELIST lpLL, POINTL pointl) +{ + RECT rect; + POINT point; + DWORD i; + + point.x = (int)pointl.x; + point.y = (int)pointl.y; + + ScreenToClient( lpLL->m_hWndListBox, &point); + + if ( lpLL->m_nNumLines == 0 ) + return -1; + + GetClientRect( lpLL->m_hWndListBox, (LPRECT) &rect ); + + i = SendMessage( lpLL->m_hWndListBox, LB_GETTOPINDEX, (WPARAM)NULL, (LPARAM)NULL ); + + for ( ;; i++){ + + RECT rectItem; + + if (!LineList_GetLineRect( lpLL, (int)i, (LPRECT)&rectItem ) ) + return -1; + + if ( rectItem.top > rect.bottom ) + return -1; + + if ( rectItem.top <= point.y && point.y <= rectItem.bottom) + return (int)i; + + } + +} + + +/* LineList_RestoreDragFeedback + * ---------------------------- + * + * Retore the index of the line that currently has focus (the active line). + */ +void LineList_RestoreDragFeedback(LPLINELIST lpLL) +{ + LPLINE lpLine; + + if (lpLL->m_iDragOverLine < 0 ) + return; + + lpLine = LineList_GetLine( lpLL, lpLL->m_iDragOverLine); + + if (lpLine) { + + lpLine->m_fDragOverLine = FALSE; + LineList_ForceLineRedraw( lpLL,lpLL->m_iDragOverLine,TRUE /*fErase*/); + + // Force repaint immediately + UpdateWindow(lpLL->m_hWndListBox); + } + + lpLL->m_iDragOverLine = -1; + +} + +#endif diff --git a/private/oleutest/letest/outline/outlname.c b/private/oleutest/letest/outline/outlname.c new file mode 100644 index 000000000..640f7f27d --- /dev/null +++ b/private/oleutest/letest/outline/outlname.c @@ -0,0 +1,112 @@ +/************************************************************************* +** +** OLE 2 Sample Code +** +** outlname.c +** +** This file contains OutlineName functions. +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + + +#include "outline.h" + +OLEDBGDATA + + +/* OutlineName_SetName + * ------------------- + * + * Change the string of a name. + */ +void OutlineName_SetName(LPOUTLINENAME lpOutlineName, LPSTR lpszName) +{ + lstrcpy(lpOutlineName->m_szName, lpszName); +} + + +/* OutlineName_SetSel + * ------------------ + * + * Change the line range of a name. + */ +void OutlineName_SetSel(LPOUTLINENAME lpOutlineName, LPLINERANGE lplrSel, BOOL fRangeModified) +{ +#if defined( OLE_SERVER ) + // Call OLE server specific function instead + ServerName_SetSel((LPSERVERNAME)lpOutlineName, lplrSel, fRangeModified); +#else + + lpOutlineName->m_nStartLine = lplrSel->m_nStartLine; + lpOutlineName->m_nEndLine = lplrSel->m_nEndLine; +#endif +} + + +/* OutlineName_GetSel + * ------------------ + * + * Retrieve the line range of a name. + */ +void OutlineName_GetSel(LPOUTLINENAME lpOutlineName, LPLINERANGE lplrSel) +{ + lplrSel->m_nStartLine = lpOutlineName->m_nStartLine; + lplrSel->m_nEndLine = lpOutlineName->m_nEndLine; +} + + +/* OutlineName_SaveToStg + * --------------------- + * + * Save a name into a storage + */ +BOOL OutlineName_SaveToStg(LPOUTLINENAME lpOutlineName, LPLINERANGE lplrSel, UINT uFormat, LPSTREAM lpNTStm, BOOL FAR* lpfNameSaved) +{ + HRESULT hrErr = NOERROR; + ULONG nWritten; + + *lpfNameSaved = FALSE; + + /* if no range given or if the name is completely within the range, + ** write it out. + */ + if (!lplrSel || + ((lplrSel->m_nStartLine <= lpOutlineName->m_nStartLine) && + (lplrSel->m_nEndLine >= lpOutlineName->m_nEndLine))) { + + hrErr = lpNTStm->lpVtbl->Write( + lpNTStm, + lpOutlineName, + sizeof(OUTLINENAME), + &nWritten + ); + *lpfNameSaved = TRUE; + } + return ((hrErr == NOERROR) ? TRUE : FALSE); +} + + +/* OutlineName_LoadFromStg + * ----------------------- + * + * Load names from an open stream of a storage. if the name already + * exits in the OutlineNameTable, it is NOT modified. + * + * Returns TRUE is all ok, else FALSE. + */ +BOOL OutlineName_LoadFromStg(LPOUTLINENAME lpOutlineName, LPSTREAM lpNTStm) +{ + HRESULT hrErr = NOERROR; + ULONG nRead; + + hrErr = lpNTStm->lpVtbl->Read( + lpNTStm, + lpOutlineName, + sizeof(OUTLINENAME), + &nRead + ); + + return ((hrErr == NOERROR) ? TRUE : FALSE); +} diff --git a/private/oleutest/letest/outline/outlntbl.c b/private/oleutest/letest/outline/outlntbl.c new file mode 100644 index 000000000..e4263c9fe --- /dev/null +++ b/private/oleutest/letest/outline/outlntbl.c @@ -0,0 +1,460 @@ +/************************************************************************* +** +** OLE 2 Sample Code +** +** outlntbl.c +** +** This file contains OutlineNameTable functions. +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + + +#include "outline.h" + +OLEDBGDATA + +extern LPOUTLINEAPP g_lpApp; + +char ErrMsgNameTable[] = "Can't create NameTable!"; + + +/* OutlineNameTable_Init + * --------------------- + * + * initialize a name table. + */ +BOOL OutlineNameTable_Init(LPOUTLINENAMETABLE lpOutlineNameTable, LPOUTLINEDOC lpOutlineDoc) +{ + HWND lpParent = OutlineDoc_GetWindow(lpOutlineDoc); + + lpOutlineNameTable->m_nCount = 0; + + /* We will use an OwnerDraw listbox as our data structure to + ** maintain the table of Names. this listbox will never be made + ** visible. the listbox is just a convenient data structure to + ** manage a collection. + */ + lpOutlineNameTable->m_hWndListBox = CreateWindow( + "listbox", /* Window class name */ + NULL, /* Window's title */ + WS_CHILDWINDOW | + LBS_OWNERDRAWFIXED, + 0, 0, /* Use default X, Y */ + 0, 0, /* Use default X, Y */ + lpParent, /* Parent window's handle */ + (HMENU)IDC_NAMETABLE, /* Child Window ID */ + g_lpApp->m_hInst, /* Instance of window */ + NULL); /* Create struct for WM_CREATE */ + + if (! lpOutlineNameTable->m_hWndListBox) { + OutlineApp_ErrorMessage(g_lpApp, ErrMsgNameTable); + return FALSE; + } + + return TRUE; +} + + +/* OutlineNameTable_Destroy + * ------------------------ + * + * Free memory used by the name table. + */ +void OutlineNameTable_Destroy(LPOUTLINENAMETABLE lpOutlineNameTable) +{ + // Delete all names + OutlineNameTable_ClearAll(lpOutlineNameTable); + + DestroyWindow(lpOutlineNameTable->m_hWndListBox); + Delete(lpOutlineNameTable); +} + + +/* OutlineNameTable_AddName + * ------------------------ + * + * Add a name to the table + */ +void OutlineNameTable_AddName(LPOUTLINENAMETABLE lpOutlineNameTable, LPOUTLINENAME lpOutlineName) +{ + SendMessage( + lpOutlineNameTable->m_hWndListBox, + LB_ADDSTRING, + 0, + (DWORD)lpOutlineName + ); + lpOutlineNameTable->m_nCount++; +} + + +/* OutlineNameTable_DeleteName + * --------------------------- + * + * Delete a name from table + */ +void OutlineNameTable_DeleteName(LPOUTLINENAMETABLE lpOutlineNameTable,int nIndex) +{ + LPOUTLINENAME lpOutlineName = OutlineNameTable_GetName(lpOutlineNameTable, nIndex); + +#if defined( OLE_SERVER ) + /* OLE2NOTE: if there is a pseudo object attached to this name, it + ** must first be closed before deleting the Name. this will + ** cause OnClose notification to be sent to all linking clients. + */ + ServerName_ClosePseudoObj((LPSERVERNAME)lpOutlineName); +#endif + + if (lpOutlineName) + Delete(lpOutlineName); // free memory for name + + SendMessage( + lpOutlineNameTable->m_hWndListBox, + LB_DELETESTRING, + (WPARAM)nIndex, + 0L + ); + lpOutlineNameTable->m_nCount--; +} + + +/* OutlineNameTable_GetNameIndex + * ----------------------------- + * + * Return the index of the Name given a pointer to the Name. + * Return -1 if the Name is not found. + */ +int OutlineNameTable_GetNameIndex(LPOUTLINENAMETABLE lpOutlineNameTable, LPOUTLINENAME lpOutlineName) +{ + LRESULT lReturn; + + if (! lpOutlineName) return -1; + + lReturn = SendMessage( + lpOutlineNameTable->m_hWndListBox, + LB_FINDSTRING, + (WPARAM)-1, + (LPARAM)(LPCSTR)lpOutlineName + ); + + return ((lReturn == LB_ERR) ? -1 : (int)lReturn); +} + + +/* OutlineNameTable_GetName + * ------------------------ + * + * Retrieve the pointer to the Name given its index in the NameTable + */ +LPOUTLINENAME OutlineNameTable_GetName(LPOUTLINENAMETABLE lpOutlineNameTable, int nIndex) +{ + LPOUTLINENAME lpOutlineName = NULL; + LRESULT lResult; + + if (lpOutlineNameTable->m_nCount == 0 || + nIndex > lpOutlineNameTable->m_nCount || + nIndex < 0) { + return NULL; + } + + lResult = SendMessage( + lpOutlineNameTable->m_hWndListBox, + LB_GETTEXT, + nIndex, + (LPARAM)(LPCSTR)&lpOutlineName + ); + OleDbgAssert(lResult != LB_ERR); + return lpOutlineName; +} + + +/* OutlineNameTable_FindName + * ------------------------- + * + * Find a name in the name table given a string. + */ +LPOUTLINENAME OutlineNameTable_FindName(LPOUTLINENAMETABLE lpOutlineNameTable, LPSTR lpszName) +{ + LPOUTLINENAME lpOutlineName; + BOOL fFound = FALSE; + int i; + + for (i = 0; i < lpOutlineNameTable->m_nCount; i++) { + lpOutlineName = OutlineNameTable_GetName(lpOutlineNameTable, i); + if (lstrcmp(lpOutlineName->m_szName, lpszName) == 0) { + fFound = TRUE; + break; // FOUND MATCH! + } + } + + return (fFound ? lpOutlineName : NULL); +} + + +/* OutlineNameTable_FindNamedRange + * ------------------------------- + * + * Find a name in the name table which matches a given line range. + */ +LPOUTLINENAME OutlineNameTable_FindNamedRange(LPOUTLINENAMETABLE lpOutlineNameTable, LPLINERANGE lplrSel) +{ + LPOUTLINENAME lpOutlineName; + BOOL fFound = FALSE; + int i; + + for (i = 0; i < lpOutlineNameTable->m_nCount; i++) { + lpOutlineName = OutlineNameTable_GetName(lpOutlineNameTable, i); + if ((lpOutlineName->m_nStartLine == lplrSel->m_nStartLine) && + (lpOutlineName->m_nEndLine == lplrSel->m_nEndLine) ) { + fFound = TRUE; + break; // FOUND MATCH! + } + } + + return (fFound ? lpOutlineName : NULL); +} + + +/* OutlineNameTable_GetCount + * ------------------------- + * + * Return number of names in nametable + */ +int OutlineNameTable_GetCount(LPOUTLINENAMETABLE lpOutlineNameTable) +{ + if (!lpOutlineNameTable) + return 0; + + return lpOutlineNameTable->m_nCount; +} + + +/* OutlineNameTable_ClearAll + * ------------------------- + * + * Remove all names from table + */ +void OutlineNameTable_ClearAll(LPOUTLINENAMETABLE lpOutlineNameTable) +{ + LPOUTLINENAME lpOutlineName; + int i; + int nCount = lpOutlineNameTable->m_nCount; + + for (i = 0; i < nCount; i++) { + lpOutlineName = OutlineNameTable_GetName(lpOutlineNameTable, i); + Delete(lpOutlineName); // free memory for name + } + + lpOutlineNameTable->m_nCount = 0; + SendMessage(lpOutlineNameTable->m_hWndListBox,LB_RESETCONTENT,0,0L); +} + + +/* OutlineNameTable_AddLineUpdate + * ------------------------------ + * + * Update table when a new line is added at nAddIndex + * The line used to be at nAddIndex is pushed down + */ +void OutlineNameTable_AddLineUpdate(LPOUTLINENAMETABLE lpOutlineNameTable, int nAddIndex) +{ + LPOUTLINENAME lpOutlineName; + LINERANGE lrSel; + int i; + BOOL fRangeModified = FALSE; + + for(i = 0; i < lpOutlineNameTable->m_nCount; i++) { + lpOutlineName=OutlineNameTable_GetName(lpOutlineNameTable, i); + OutlineName_GetSel(lpOutlineName, &lrSel); + + if((int)lrSel.m_nStartLine > nAddIndex) { + lrSel.m_nStartLine++; + fRangeModified = !fRangeModified; + } + if((int)lrSel.m_nEndLine > nAddIndex) { + lrSel.m_nEndLine++; + fRangeModified = !fRangeModified; + } + + OutlineName_SetSel(lpOutlineName, &lrSel, fRangeModified); + } +} + + +/* OutlineNameTable_DeleteLineUpdate + * --------------------------------- + * + * Update the table when a line at nDeleteIndex is removed + */ +void OutlineNameTable_DeleteLineUpdate(LPOUTLINENAMETABLE lpOutlineNameTable, int nDeleteIndex) +{ + LPOUTLINENAME lpOutlineName; + LINERANGE lrSel; + int i; + BOOL fRangeModified = FALSE; + + for(i = 0; i < lpOutlineNameTable->m_nCount; i++) { + lpOutlineName=OutlineNameTable_GetName(lpOutlineNameTable, i); + OutlineName_GetSel(lpOutlineName, &lrSel); + + if((int)lrSel.m_nStartLine > nDeleteIndex) { + lrSel.m_nStartLine--; + fRangeModified = !fRangeModified; + } + if((int)lrSel.m_nEndLine >= nDeleteIndex) { + lrSel.m_nEndLine--; + fRangeModified = !fRangeModified; + } + + // delete the name if its entire range is deleted + if(lrSel.m_nStartLine > lrSel.m_nEndLine) { + OutlineNameTable_DeleteName(lpOutlineNameTable, i); + i--; // re-examine this name + } else { + OutlineName_SetSel(lpOutlineName, &lrSel, fRangeModified); + } + } +} + + +/* OutlineNameTable_SaveSelToStg + * ----------------------------- + * + * Save only the names that refer to lines completely contained in the + * specified selection range. + */ +BOOL OutlineNameTable_SaveSelToStg( + LPOUTLINENAMETABLE lpOutlineNameTable, + LPLINERANGE lplrSel, + UINT uFormat, + LPSTREAM lpNTStm +) +{ + HRESULT hrErr; + ULONG nWritten; + LPOUTLINENAME lpOutlineName; + short nNameCount = 0; + BOOL fNameSaved; + BOOL fStatus; + int i; + LARGE_INTEGER dlibZeroOffset; + LISet32( dlibZeroOffset, 0 ); + + /* initially write 0 for count of names. the correct count will be + ** written at the end when we know how many names qualified to + ** be written (within the selection). + */ + hrErr = lpNTStm->lpVtbl->Write( + lpNTStm, + (short FAR*)&nNameCount, + sizeof(nNameCount), + &nWritten + ); + if (hrErr != NOERROR) { + OleDbgOutHResult("Write NameTable header returned", hrErr); + goto error; + } + + for(i = 0; i < lpOutlineNameTable->m_nCount; i++) { + lpOutlineName=OutlineNameTable_GetName(lpOutlineNameTable, i); + fStatus = OutlineName_SaveToStg( + lpOutlineName, + lplrSel, + uFormat, + lpNTStm, + (BOOL FAR*)&fNameSaved + ); + if (! fStatus) goto error; + if (fNameSaved) nNameCount++; + } + + /* write the final count of names written. */ + hrErr = lpNTStm->lpVtbl->Seek( + lpNTStm, + dlibZeroOffset, + STREAM_SEEK_SET, + NULL + ); + if (hrErr != NOERROR) { + OleDbgOutHResult("Seek to NameTable header returned", hrErr); + goto error; + } + + hrErr = lpNTStm->lpVtbl->Write( + lpNTStm, + (short FAR*)&nNameCount, + sizeof(nNameCount), + &nWritten + ); + if (hrErr != NOERROR) { + OleDbgOutHResult("Write NameTable count in header returned", hrErr); + goto error; + } + + OleStdRelease((LPUNKNOWN)lpNTStm); + return TRUE; + +error: + if (lpNTStm) + OleStdRelease((LPUNKNOWN)lpNTStm); + + return FALSE; +} + + +/* OutlineNameTable_LoadFromStg + * ---------------------------- + * + * Load Name Table from file + * + * Return TRUE if ok, FALSE if error + */ +BOOL OutlineNameTable_LoadFromStg(LPOUTLINENAMETABLE lpOutlineNameTable, LPSTORAGE lpSrcStg) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + HRESULT hrErr; + IStream FAR* lpNTStm; + ULONG nRead; + short nCount; + LPOUTLINENAME lpOutlineName; + BOOL fStatus; + short i; + + hrErr = CallIStorageOpenStreamA( + lpSrcStg, + "NameTable", + NULL, + STGM_READ | STGM_SHARE_EXCLUSIVE, + 0, + &lpNTStm + ); + + if (hrErr != NOERROR) { + OleDbgOutHResult("OpenStream NameTable returned", hrErr); + goto error; + } + + hrErr = lpNTStm->lpVtbl->Read(lpNTStm,&nCount,sizeof(nCount),&nRead); + if (hrErr != NOERROR) { + OleDbgOutHResult("Read NameTable header returned", hrErr); + goto error; + } + + for (i = 0; i < nCount; i++) { + lpOutlineName = OutlineApp_CreateName(lpOutlineApp); + if (! lpOutlineName) goto error; + fStatus = OutlineName_LoadFromStg(lpOutlineName, lpNTStm); + if (! fStatus) goto error; + OutlineNameTable_AddName(lpOutlineNameTable, lpOutlineName); + } + + OleStdRelease((LPUNKNOWN)lpNTStm); + return TRUE; + +error: + if (lpNTStm) + OleStdRelease((LPUNKNOWN)lpNTStm); + + return FALSE; +} diff --git a/private/oleutest/letest/outline/outlrc.h b/private/oleutest/letest/outline/outlrc.h new file mode 100644 index 000000000..c8b88e99a --- /dev/null +++ b/private/oleutest/letest/outline/outlrc.h @@ -0,0 +1,164 @@ +/************************************************************************* +** +** OLE 2.0 Sample Code +** +** outlrc.h +** +** This file containes constants used in rc file for Outline.exe +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + +#if !defined( _OUTLRC_H_ ) +#define _OUTLRC_H_ + +#ifndef RC_INVOKED +#pragma message ("INCLUDING OUTLRC.H from " __FILE__) +#endif /* RC_INVOKED */ + +#if defined( OLE_SERVER ) && ! defined( INPLACE_SVR ) +#define APPNAME "SvrOutl" +#define APPMENU "SvrOutlMenu" +#define APPACCEL "SvrOutlAccel" +#define FB_EDIT_ACCEL "SvrOutlAccelFocusEdit" +#define APPICON "SvrOutlIcon" +#define APPWNDCLASS "SvrOutlApp" +#define DOCWNDCLASS "SvrOutlDoc" +#define APPDESC "OLE 2.0 Server Sample Code" +#endif // OLE_SERVER && ! INPLACE_SVR + +#if defined( INPLACE_SVR ) +#define APPNAME "ISvrOtl" +#define APPMENU "SvrOutlMenu" +#define APPACCEL "SvrOutlAccel" +#define FB_EDIT_ACCEL "SvrOutlAccelFocusEdit" +#define APPICON "SvrOutlIcon" +#define APPWNDCLASS "SvrOutlApp" +#define DOCWNDCLASS "SvrOutlDoc" +#define APPDESC "OLE 2.0 In-Place Server Sample Code" +#endif // INPLACE_SVR + +#if defined( OLE_CNTR ) && ! defined( INPLACE_CNTR ) +#define APPNAME "CntrOutl" +#define APPMENU "CntrOutlMenu" +#define APPACCEL "CntrOutlAccel" +#define FB_EDIT_ACCEL "CntrOutlAccelFocusEdit" +#define APPICON "CntrOutlIcon" +#define APPWNDCLASS "CntrOutlApp" +#define DOCWNDCLASS "CntrOutlDoc" +#define APPDESC "OLE 2.0 Container Sample Code" +#endif // OLE_CNTR && ! INPLACE_CNTR + +#if defined( INPLACE_CNTR ) +#define APPNAME "ICntrOtl" +#define APPMENU "CntrOutlMenu" +#define APPACCEL "CntrOutlAccel" +#define FB_EDIT_ACCEL "CntrOutlAccelFocusEdit" +#define APPICON "CntrOutlIcon" +#define APPWNDCLASS "CntrOutlApp" +#define DOCWNDCLASS "CntrOutlDoc" +#define APPDESC "OLE 2.0 In-Place Container Sample Code" +#endif // INPLACE_CNTR + +#if !defined( OLE_VERSION ) +#define APPNAME "Outline" +#define APPMENU "OutlineMenu" +#define APPACCEL "OutlineAccel" +#define FB_EDIT_ACCEL "OutlineAccelFocusEdit" +#define APPICON "OutlineIcon" +#define APPWNDCLASS "OutlineApp" +#define DOCWNDCLASS "OutlineDoc" +#define APPDESC "OLE 2.0 Sample Code" +#endif // OLE_VERSION + +#define IDM_FILE 1000 +#define IDM_F_NEW 1050 +#define IDM_F_OPEN 1100 +#define IDM_F_SAVE 1150 +#define IDM_F_SAVEAS 1200 +#define IDM_F_PRINT 1300 +#define IDM_F_PRINTERSETUP 1350 +#define IDM_F_EXIT 1450 +#define IDM_EDIT 2000 +#define IDM_E_UNDO 2050 +#define IDM_E_CUT 2150 +#define IDM_E_COPY 2200 +#define IDM_E_PASTE 2250 +#define IDM_E_PASTESPECIAL 2255 +#define IDM_E_CLEAR 2300 +#define IDM_E_SELECTALL 2560 +#define IDM_LINE 3000 +#define IDM_L_ADDLINE 3400 +#define IDM_L_EDITLINE 3450 +#define IDM_L_INDENTLINE 3500 +#define IDM_L_UNINDENTLINE 3550 +#define IDM_L_SETLINEHEIGHT 3560 +#define IDM_NAME 4000 +#define IDM_N_DEFINENAME 4050 +#define IDM_N_GOTONAME 4100 +#define IDM_HELP 5000 +#define IDM_H_ABOUT 5050 +#define IDM_DEBUG 6000 +#define IDM_D_DEBUGLEVEL 6050 +#define IDM_D_INSTALLMSGFILTER 6060 +#define IDM_D_REJECTINCOMING 6070 +#define IDM_O_BB_TOP 6100 +#define IDM_O_BB_BOTTOM 6150 +#define IDM_O_BB_POPUP 6200 +#define IDM_O_BB_HIDE 6210 +#define IDM_O_FB_TOP 6250 +#define IDM_O_FB_BOTTOM 6300 +#define IDM_O_FB_POPUP 6350 +#define IDM_O_HEAD_SHOW 6400 +#define IDM_O_HEAD_HIDE 6450 +#define IDM_O_SHOWOBJECT 6460 +#define IDM_V_ZOOM_400 6500 +#define IDM_V_ZOOM_300 6510 +#define IDM_V_ZOOM_200 6520 +#define IDM_V_ZOOM_100 6550 +#define IDM_V_ZOOM_75 6600 +#define IDM_V_ZOOM_50 6650 +#define IDM_V_ZOOM_25 6700 +#define IDM_V_SETMARGIN_0 6750 +#define IDM_V_SETMARGIN_1 6800 +#define IDM_V_SETMARGIN_2 6850 +#define IDM_V_SETMARGIN_3 6860 +#define IDM_V_SETMARGIN_4 6870 +#define IDM_V_ADDTOP_1 6900 +#define IDM_V_ADDTOP_2 6910 +#define IDM_V_ADDTOP_3 6920 +#define IDM_V_ADDTOP_4 6930 + + +#define IDM_FB_EDIT 7000 +#define IDM_FB_CANCEL 7005 +#define IDM_F2 7010 +#define IDM_ESCAPE 7015 + + +#define IDD_LINELISTBOX 101 +#define IDD_EDIT 102 +#define IDD_COMBO 103 +#define IDD_DELETE 104 +#define IDD_CLOSE 105 +#define IDD_APPTEXT 106 +#define IDD_FROM 107 +#define IDD_TO 108 +#define IDD_BITMAPLOCATION 109 +#define IDD_CHECK 110 +#define IDD_TEXT 111 +#define IDD_LIMIT 112 + + +#define IDC_LINELIST 201 +#define IDC_NAMETABLE 202 + + +#define WM_U_INITFRAMETOOLS WM_USER + +#ifdef RC_INVOKED +#include "debug.rc" +#endif /* RC_INVOKED */ + +#endif // _OUTLRC_H_ diff --git a/private/oleutest/letest/outline/outltxtl.c b/private/oleutest/letest/outline/outltxtl.c new file mode 100644 index 000000000..2779e701e --- /dev/null +++ b/private/oleutest/letest/outline/outltxtl.c @@ -0,0 +1,408 @@ +/************************************************************************* +** +** OLE 2 Sample Code +** +** outltxtl.c +** +** This file contains TextLine methods and related support functions. +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + + +#include "outline.h" + +OLEDBGDATA + +extern LPOUTLINEAPP g_lpApp; + + +/* TextLine_Create + * --------------- + * + * Create a text line object and return the pointer + */ +LPTEXTLINE TextLine_Create(HDC hDC, UINT nTab, LPSTR lpszText) +{ + LPTEXTLINE lpTextLine; + + lpTextLine=(LPTEXTLINE) New((DWORD)sizeof(TEXTLINE)); + if (lpTextLine == NULL) { + OleDbgAssertSz(lpTextLine!=NULL,"Error allocating TextLine"); + return NULL; + } + + TextLine_Init(lpTextLine, nTab, hDC); + + if (lpszText) { + lpTextLine->m_nLength = lstrlen(lpszText); + lstrcpy((LPSTR)lpTextLine->m_szText, lpszText); + } else { + lpTextLine->m_nLength = 0; + lpTextLine->m_szText[0] = '\0'; + } + + TextLine_CalcExtents(lpTextLine, hDC); + + return(lpTextLine); +} + + +/* TextLine_Init + * ------------- + * + * Calculate the width/height of a text line object. + */ +void TextLine_Init(LPTEXTLINE lpTextLine, int nTab, HDC hDC) +{ + Line_Init((LPLINE)lpTextLine, nTab, hDC); // init the base class fields + + ((LPLINE)lpTextLine)->m_lineType = TEXTLINETYPE; + lpTextLine->m_nLength = 0; + lpTextLine->m_szText[0] = '\0'; +} + + +/* TextLine_Delete + * --------------- + * + * Delete the TextLine structure + */ +void TextLine_Delete(LPTEXTLINE lpTextLine) +{ + Delete((LPVOID)lpTextLine); +} + + +/* TextLine_Edit + * ------------- + * + * Edit the text line object. + * + * Returns TRUE if line was changed + * FALSE if the line was NOT changed + */ +BOOL TextLine_Edit(LPTEXTLINE lpLine, HWND hWndDoc, HDC hDC) +{ +#if defined( USE_FRAMETOOLS ) + LPFRAMETOOLS lptb = OutlineApp_GetFrameTools(g_lpApp); +#endif + BOOL fStatus = FALSE; + +#if defined( USE_FRAMETOOLS ) + FrameTools_FB_GetEditText(lptb, lpLine->m_szText, sizeof(lpLine->m_szText)); +#else + if (! InputTextDlg(hWndDoc, lpLine->m_szText, "Edit Line")) + return FALSE; +#endif + + lpLine->m_nLength = lstrlen(lpLine->m_szText); + TextLine_CalcExtents(lpLine, hDC); + fStatus = TRUE; + + return fStatus; +} + + +/* TextLine_CalcExtents + * -------------------- + * + * Calculate the width/height of a text line object. + */ +void TextLine_CalcExtents(LPTEXTLINE lpTextLine, HDC hDC) +{ + SIZE size; + LPLINE lpLine = (LPLINE)lpTextLine; + + if (lpTextLine->m_nLength) { + GetTextExtentPoint(hDC, lpTextLine->m_szText, + lpTextLine->m_nLength, &size); + lpLine->m_nWidthInHimetric=size.cx; + lpLine->m_nHeightInHimetric=size.cy; + } else { + // we still need to calculate proper height even for NULL string + TEXTMETRIC tm; + GetTextMetrics(hDC, &tm); + + // required to set height + lpLine->m_nHeightInHimetric = tm.tmHeight; + lpLine->m_nWidthInHimetric = 0; + } + +#if defined( _DEBUG ) + { + RECT rc; + rc.left = 0; + rc.top = 0; + rc.right = XformWidthInHimetricToPixels(hDC, + lpLine->m_nWidthInHimetric); + rc.bottom = XformHeightInHimetricToPixels(hDC, + lpLine->m_nHeightInHimetric); + + OleDbgOutRect3("TextLine_CalcExtents", (LPRECT)&rc); + } +#endif +} + + + +/* TextLine_SetHeightInHimetric + * ---------------------------- + * + * Set the height of a textline object. + */ +void TextLine_SetHeightInHimetric(LPTEXTLINE lpTextLine, int nHeight) +{ + if (!lpTextLine) + return; + + ((LPLINE)lpTextLine)->m_nHeightInHimetric = nHeight; +} + + + +/* TextLine_GetTextLen + * ------------------- + * + * Return length of string of the TextLine (not considering the tab level). + */ +int TextLine_GetTextLen(LPTEXTLINE lpTextLine) +{ + return lstrlen((LPSTR)lpTextLine->m_szText); +} + + +/* TextLine_GetTextData + * -------------------- + * + * Return the string of the TextLine (not considering the tab level). + */ +void TextLine_GetTextData(LPTEXTLINE lpTextLine, LPSTR lpszBuf) +{ + lstrcpy(lpszBuf, (LPSTR)lpTextLine->m_szText); +} + + +/* TextLine_GetOutlineData + * ----------------------- + * + * Return the CF_OUTLINE format data for the TextLine. + */ +BOOL TextLine_GetOutlineData(LPTEXTLINE lpTextLine, LPTEXTLINE lpBuf) +{ + TextLine_Copy((LPTEXTLINE)lpTextLine, lpBuf); + return TRUE; +} + + +/* TextLine_Draw + * ------------- + * + * Draw a text line object on a DC. + * Parameters: + * hDC - DC to which the line will be drawn + * lpRect - the object rectangle in logical coordinates + * lpRectWBounds - bounding rect of the metafile underneath hDC + * (NULL if hDC is not a metafile DC) + * this is used by ContainerLine_Draw to draw the OLE obj + * fHighlight - TRUE use selection highlight text color + */ +void TextLine_Draw( + LPTEXTLINE lpTextLine, + HDC hDC, + LPRECT lpRect, + LPRECT lpRectWBounds, + BOOL fHighlight +) +{ + RECT rc; + int nBkMode; + COLORREF clrefOld; + + if (!lpTextLine) + return; + + rc = *lpRect; + rc.left += ((LPLINE)lpTextLine)->m_nTabWidthInHimetric; + rc.right += ((LPLINE)lpTextLine)->m_nTabWidthInHimetric; + + nBkMode = SetBkMode(hDC, TRANSPARENT); + + if (fHighlight) { + /*Get proper txt colors */ + clrefOld = SetTextColor(hDC,GetSysColor(COLOR_HIGHLIGHTTEXT)); + } + else { + clrefOld = SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT)); + } + + ExtTextOut( + hDC, + rc.left, + rc.top, + ETO_CLIPPED, + (LPRECT)&rc, + lpTextLine->m_szText, + lpTextLine->m_nLength, + (LPINT) NULL /* default char spacing */ + ); + + SetTextColor(hDC, clrefOld); + SetBkMode(hDC, nBkMode); +} + +/* TextLine_DrawSelHilight + * ----------------------- + * + * Handles selection of textline + */ +void TextLine_DrawSelHilight(LPTEXTLINE lpTextLine, HDC hDC, LPRECT lpRect, UINT itemAction, UINT itemState) +{ + if (itemAction & ODA_SELECT) { + // check if there is a selection state change, ==> invert rect + if (itemState & ODS_SELECTED) { + if (!((LPLINE)lpTextLine)->m_fSelected) { + ((LPLINE)lpTextLine)->m_fSelected = TRUE; + InvertRect(hDC, (LPRECT)lpRect); + } + } else { + if (((LPLINE)lpTextLine)->m_fSelected) { + ((LPLINE)lpTextLine)->m_fSelected = FALSE; + InvertRect(hDC, lpRect); + } + } + } else if (itemAction & ODA_DRAWENTIRE) { + ((LPLINE)lpTextLine)->m_fSelected=((itemState & ODS_SELECTED) ? TRUE : FALSE); + InvertRect(hDC, lpRect); + } +} + +/* TextLine_Copy + * ------------- + * + * Duplicate a textline + */ +BOOL TextLine_Copy(LPTEXTLINE lpSrcLine, LPTEXTLINE lpDestLine) +{ + _fmemcpy(lpDestLine, lpSrcLine, sizeof(TEXTLINE)); + return TRUE; +} + + +/* TextLine_CopyToDoc + * ------------------ + * + * Copy a textline to another Document (usually ClipboardDoc) + */ +BOOL TextLine_CopyToDoc(LPTEXTLINE lpSrcLine, LPOUTLINEDOC lpDestDoc, int nIndex) +{ + LPTEXTLINE lpDestLine; + BOOL fStatus = FALSE; + + lpDestLine = (LPTEXTLINE) New((DWORD)sizeof(TEXTLINE)); + if (lpDestLine == NULL) { + OleDbgAssertSz(lpDestLine!=NULL,"Error allocating TextLine"); + return FALSE; + } + + if (TextLine_Copy(lpSrcLine, lpDestLine)) { + OutlineDoc_AddLine(lpDestDoc, (LPLINE)lpDestLine, nIndex); + fStatus = TRUE; + } + + return fStatus; +} + + +/* TextLine_SaveToStg + * ------------------ + * + * Save a textline into a storage + * + * Return TRUE if successful, FALSE otherwise + */ +BOOL TextLine_SaveToStm(LPTEXTLINE lpTextLine, LPSTREAM lpLLStm) +{ + HRESULT hrErr; + ULONG nWritten; + USHORT nLengthOnDisk; + + nLengthOnDisk = (USHORT) lpTextLine->m_nLength; + + hrErr = lpLLStm->lpVtbl->Write( + lpLLStm, + (LPVOID)&nLengthOnDisk, + sizeof(nLengthOnDisk), + &nWritten + ); + if (hrErr != NOERROR) { + OleDbgOutHResult("Write TextLine data (1) returned", hrErr); + return FALSE; + } + + hrErr = lpLLStm->lpVtbl->Write( + lpLLStm, + (LPVOID)lpTextLine->m_szText, + lpTextLine->m_nLength, + &nWritten + ); + if (hrErr != NOERROR) { + OleDbgOutHResult("Write TextLine data (2) returned", hrErr); + return FALSE; + } + + return TRUE; +} + + +/* TextLine_LoadFromStg + * -------------------- + * + * Load a textline from storage + */ +LPLINE TextLine_LoadFromStg(LPSTORAGE lpSrcStg, LPSTREAM lpLLStm, LPOUTLINEDOC lpDestDoc) +{ + HRESULT hrErr; + ULONG nRead; + LPTEXTLINE lpTextLine; + USHORT nLengthOnDisk; + + lpTextLine=(LPTEXTLINE) New((DWORD)sizeof(TEXTLINE)); + if (lpTextLine == NULL) { + OleDbgAssertSz(lpTextLine!=NULL,"Error allocating TextLine"); + return NULL; + } + + TextLine_Init(lpTextLine, 0, NULL); + + hrErr = lpLLStm->lpVtbl->Read( + lpLLStm, + (LPVOID)&nLengthOnDisk, + sizeof(nLengthOnDisk), + &nRead + ); + if (hrErr != NOERROR) { + OleDbgOutHResult("Read TextLine data (1) returned", hrErr); + return NULL; + } + + lpTextLine->m_nLength = (UINT) nLengthOnDisk; + + OleDbgAssert(lpTextLine->m_nLength < sizeof(lpTextLine->m_szText)); + + hrErr = lpLLStm->lpVtbl->Read( + lpLLStm, + (LPVOID)&lpTextLine->m_szText, + lpTextLine->m_nLength, + &nRead + ); + if (hrErr != NOERROR) { + OleDbgOutHResult("Read TextLine data (1) returned", hrErr); + return NULL; + } + + lpTextLine->m_szText[lpTextLine->m_nLength] = '\0'; // add str terminator + + return (LPLINE)lpTextLine; +} diff --git a/private/oleutest/letest/outline/precomp.c b/private/oleutest/letest/outline/precomp.c new file mode 100644 index 000000000..c9053eeeb --- /dev/null +++ b/private/oleutest/letest/outline/precomp.c @@ -0,0 +1,13 @@ +/************************************************************************* +** +** OLE 2.0 Sample Code +** +** precomp.c +** +** This file is used to precompile the OUTLINE.H header file +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + +#include "outline.h" diff --git a/private/oleutest/letest/outline/selcross.cur b/private/oleutest/letest/outline/selcross.cur new file mode 100644 index 000000000..de3d14703 Binary files /dev/null and b/private/oleutest/letest/outline/selcross.cur differ diff --git a/private/oleutest/letest/outline/state.rst b/private/oleutest/letest/outline/state.rst new file mode 100644 index 000000000..8615f7aac --- /dev/null +++ b/private/oleutest/letest/outline/state.rst @@ -0,0 +1,12 @@ +[edit-] +screen=80 50 +toggles=1 1 0 1 0 0 +srch=SaveToFile +src= +rpl= +file=e:\src\ole2samp\outline\svrbase.c 1 1508 1 1508 +[brief] +file=e:\src\ole2samp\outline\svrbase.c 1 1508 1 1508 1 47 78 1 c=0 +[shared-] +pmark=e:\src\ole2samp\outline\svrbase.c 1 1508 + \ No newline at end of file diff --git a/private/oleutest/letest/outline/status.c b/private/oleutest/letest/outline/status.c new file mode 100644 index 000000000..d499bad70 --- /dev/null +++ b/private/oleutest/letest/outline/status.c @@ -0,0 +1,369 @@ +/************************************************************************* +** +** OLE 2.0 Sample Code +** +** status.c +** +** This file contains the window handlers, and various initialization +** and utility functions for an application status bar. +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + +// Application specific include files +#include "outline.h" +#include "message.h" +#include "status.h" + +// Current status message. +static LPSTR lpszStatusMessage = NULL; + +// Window proc for status window. +LRESULT FAR PASCAL StatusWndProc + (HWND hwnd, unsigned message, WPARAM wParam, LPARAM lParam); + +// List of all constant messages. +static STATMESG ControlList[2] = +{ + { STATUS_READY, "Ready." }, + { STATUS_BLANK, " " } +}; + +// List of all system menu messages. +static STATMESG SysMenuList[16] = +{ + { SC_SIZE, "Change the size of the window." }, + { SC_MOVE, "Move the window." }, + { SC_MINIMIZE, "Make the window iconic." }, + { SC_MAXIMIZE, "Make the window the size of the screen." }, + { SC_NEXTWINDOW, "Activate the next window." }, + { SC_PREVWINDOW, "Activate the previous window." }, + { SC_CLOSE, "Close this window." }, + { SC_VSCROLL, "Vertical scroll?" }, + { SC_HSCROLL, "Horizontal scroll?" }, + { SC_MOUSEMENU, "A menu for mice." }, + { SC_KEYMENU, "A menu for keys (I guess)." }, + { SC_ARRANGE, "Arrange something." }, + { SC_RESTORE, "Make the window noramally sized." }, + { SC_TASKLIST, "Put up the task list dialog." }, + { SC_SCREENSAVE, "Save the screen! Run for your life!" }, + { SC_HOTKEY, "Boy, is this key hot!" } +}; + +// Message type for popup messages. +typedef struct { + HMENU hmenu; + char string[MAX_MESSAGE]; +} STATPOPUP; + +// List of all popup messages. +static STATPOPUP PopupList[NUM_POPUP]; + +static UINT nCurrentPopup = 0; + + + +/* RegisterStatusClass + * ------------------- + * + * Creates classes for status window. + * + * HINSTANCE hInstance + * + * RETURNS: TRUE if class successfully registered. + * FALSE otherwise. + * + * CUSTOMIZATION: Change class name. + * + */ +BOOL RegisterStatusClass(HINSTANCE hInstance) +{ + WNDCLASS wc; + + wc.lpszClassName = "ObjStatus"; + wc.lpfnWndProc = StatusWndProc; + wc.style = 0; + wc.hInstance = hInstance; + wc.hIcon = NULL; + wc.cbClsExtra = 4; + wc.cbWndExtra = 0; + wc.lpszMenuName = NULL; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = GetStockObject(LTGRAY_BRUSH); + + if (!RegisterClass(&wc)) + return FALSE; + + return TRUE; +} + + +/* CreateStatusWindow + * ------------------ + * + * Creates status window. + * + * HWND hwndMain + * + * RETURNS: HWND of status window if creation is successful. + * NULL otherwise. + * + * CUSTOMIZATION: Change class name. + * + */ +HWND CreateStatusWindow(HWND hWndApp, HINSTANCE hInst) +{ + RECT rect; + int width, height; + HWND hWndStatusBar; + + lpszStatusMessage = ControlList[0].string; + GetClientRect(hWndApp, &rect); + width = rect.right - rect.left; + height = rect.bottom - rect.top; + + hWndStatusBar = CreateWindow ( + "ObjStatus", + "SvrStatus", + WS_CHILD | + WS_CLIPSIBLINGS | + WS_VISIBLE, + 0, height - STATUS_HEIGHT, + width, + STATUS_HEIGHT, + hWndApp, + NULL, + hInst, + NULL + ); + + return hWndStatusBar; +} + + +/* DestroyStatusWindow + * ------------------- + * + * Destroys status window. + * + * CUSTOMIZATION: None. + * + */ +void DestroyStatusWindow(HWND hWndStatusBar) +{ + DestroyWindow(hWndStatusBar); +} + + +/* AssignPopupMessage + * ------------------ + * + * Associates a string with a popup menu handle. + * + * HMENU hmenuPopup + * char *szMessage + * + * CUSTOMIZATION: None. + * + */ +void AssignPopupMessage(HMENU hmenuPopup, char *szMessage) +{ + if (nCurrentPopup < NUM_POPUP) { + PopupList[nCurrentPopup].hmenu = hmenuPopup; + lstrcpy(PopupList[nCurrentPopup].string, szMessage); + ++nCurrentPopup; + } +} + + +/* SetStatusText + * ------------- + * + * Show the message in the status line. + */ +void SetStatusText(HWND hWndStatusBar, LPSTR lpszMessage) +{ + lpszStatusMessage = lpszMessage; + InvalidateRect (hWndStatusBar, (LPRECT)NULL, TRUE); + UpdateWindow (hWndStatusBar); +} + + +/* GetItemMessage + * -------------- + * + * Retrieve the message associated with the given menu command item number. + * + * UINT wIDItem + * LPVOID lpDoc + * + * CUSTOMIZATION: None. + * + */ +void GetItemMessage(UINT wIDItem, LPSTR FAR* lplpszMessage) +{ + UINT i; + + *lplpszMessage = ControlList[1].string; + for (i = 0; i < NUM_STATS; ++i) { + if (wIDItem == MesgList[i].wIDItem) { + *lplpszMessage = MesgList[i].string; + break; + } + } +} + + +/* GetPopupMessage + * --------------- + * + * Retrieve the message associated with the given popup menu. + * + * HMENU hmenuPopup + * LPVOID lpDoc + * + * CUSTOMIZATION: None. + * + */ +void GetPopupMessage(HMENU hmenuPopup, LPSTR FAR* lplpszMessage) +{ + UINT i; + + *lplpszMessage = ControlList[1].string; + for (i = 0; i < nCurrentPopup; ++i) { + if (hmenuPopup == PopupList[i].hmenu) { + *lplpszMessage = PopupList[i].string; + break; + } + } +} + + +/* GetSysMenuMessage + * ----------------- + * + * Retrieves the messages to correspond to items on the system menu. + * + * + * UINT wIDItem + * LPVOID lpDoc + * + * CUSTOMIZATION: None. + * + */ +void GetSysMenuMessage(UINT wIDItem, LPSTR FAR* lplpszMessage) +{ + UINT i; + + *lplpszMessage = ControlList[1].string; + for (i = 0; i < 16; ++i) { + if (wIDItem == SysMenuList[i].wIDItem) { + *lplpszMessage = SysMenuList[i].string; + break; + } + } +} + + +/* GetControlMessage + * ----------------- + * + * Retrieves the general system messages. + * + * + * STATCONTROL scCommand + * LPVOID lpDoc + * + * CUSTOMIZATION: Add new messages. + * + */ +void GetControlMessage(STATCONTROL scCommand, LPSTR FAR* lplpszMessage) +{ + UINT i; + + *lplpszMessage = ControlList[1].string; + for (i = 0; i < 2; ++i) { + if ((UINT)scCommand == ControlList[i].wIDItem) { + *lplpszMessage = ControlList[i].string; + break; + } + } +} + + + +/* StatusWndProc + * ------------- + * + * Message handler for the statusbar window. + * + * + * CUSTOMIZATION: None + * + */ +LRESULT FAR PASCAL StatusWndProc + (HWND hwnd, unsigned message, WPARAM wParam, LPARAM lParam) +{ + if (message == WM_PAINT) { + RECT rc; + HDC hdc; + PAINTSTRUCT paintstruct; + HPEN hpenOld; + HPEN hpen; + HFONT hfontOld; + HFONT hfont; + HPALETTE hpalOld = NULL; + POINT point; + + BeginPaint (hwnd, &paintstruct); + hdc = GetDC (hwnd); + + GetClientRect (hwnd, (LPRECT) &rc); + + hpenOld = SelectObject (hdc, GetStockObject (BLACK_PEN)); + + MoveToEx (hdc, 0, 0, &point); + LineTo (hdc, rc.right, 0); + + SelectObject (hdc, GetStockObject (WHITE_PEN)); + + MoveToEx (hdc, STATUS_RRIGHT, STATUS_RTOP, &point); + LineTo (hdc, STATUS_RRIGHT, STATUS_RBOTTOM); + LineTo (hdc, STATUS_RLEFT-1, STATUS_RBOTTOM); + + hpen = CreatePen (PS_SOLID, 1, /* DKGRAY */ 0x00808080); + SelectObject (hdc, hpen); + + MoveToEx (hdc, STATUS_RLEFT, STATUS_RBOTTOM-1, &point); + LineTo (hdc, STATUS_RLEFT, STATUS_RTOP); + LineTo (hdc, STATUS_RRIGHT, STATUS_RTOP); + + SetBkMode (hdc, TRANSPARENT); + SetTextAlign (hdc, TA_LEFT | TA_TOP); + hfont = CreateFont (STATUS_THEIGHT, 0, 0, 0, FW_NORMAL, FALSE, FALSE, + FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, + CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, + DEFAULT_PITCH | FF_DONTCARE, "MS Sans Serif"); + + hfontOld = SelectObject(hdc, hfont); + + TextOut (hdc, STATUS_TLEFT, STATUS_TTOP, + lpszStatusMessage, + lstrlen(lpszStatusMessage)); + + // Restore original objects + SelectObject (hdc, hfontOld); + SelectObject (hdc, hpenOld); + DeleteObject (hpen); + DeleteObject (hfont); + + ReleaseDC (hwnd, hdc); + EndPaint (hwnd, &paintstruct); + + return 0; + } + else { + return DefWindowProc(hwnd, message, wParam, lParam); + } +} diff --git a/private/oleutest/letest/outline/status.h b/private/oleutest/letest/outline/status.h new file mode 100644 index 000000000..1a7bcd215 --- /dev/null +++ b/private/oleutest/letest/outline/status.h @@ -0,0 +1,47 @@ +/************************************************************************* +** +** OLE 2.0 Sample Code +** +** status.h +** +** This file contains typedefs, defines, global variable declarations, +** and function prototypes for the status bar window. +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + +// Sizes of statusbar items +#if defined( USE_STATUSBAR ) + #define STATUS_HEIGHT 23 +#else + #define STATUS_HEIGHT 0 +#endif +#define STATUS_RLEFT 8 +#define STATUS_RRIGHT 400 +#define STATUS_RTOP 3 +#define STATUS_RBOTTOM 20 +#define STATUS_TTOP 4 +#define STATUS_TLEFT 11 +#define STATUS_THEIGHT 18 + + +typedef enum { + STATUS_READY, + STATUS_BLANK +} STATCONTROL; + +// Window for status bar. +extern HWND hwndStatusbar; + +BOOL RegisterStatusClass(HINSTANCE hInstance); +HWND CreateStatusWindow(HWND hWndApp, HINSTANCE hInst); +void DestroyStatusWindow(HWND hWndStatusBar); + +void AssignPopupMessage(HMENU hmenuPopup, char *szMessage); + +void SetStatusText(HWND hWndStatusBar, LPSTR lpszMessage); +void GetItemMessage(UINT wIDItem, LPSTR FAR* lplpszMessage); +void GetPopupMessage(HMENU hmenuPopup, LPSTR FAR* lplpszMessage); +void GetSysMenuMessage(UINT wIDItem, LPSTR FAR* lplpszMessage); +void GetControlMessage(STATCONTROL scCommand, LPSTR FAR* lplpszMessage); diff --git a/private/oleutest/letest/outline/svrbase.c b/private/oleutest/letest/outline/svrbase.c new file mode 100644 index 000000000..30a4c4dbc --- /dev/null +++ b/private/oleutest/letest/outline/svrbase.c @@ -0,0 +1,2018 @@ +/************************************************************************* +** +** OLE 2 Server Sample Code +** +** svrbase.c +** +** This file contains all interfaces, methods and related support +** functions for the basic OLE Object (Server) application. The +** basic OLE Object application supports embedding an object and +** linking to a file-based or embedded object as a whole. The basic +** Object application includes the following implementation objects: +** +** ClassFactory (aka. ClassObject) Object (see file classfac.c) +** exposed interfaces: +** IClassFactory interface +** +** ServerDoc Object +** exposed interfaces: +** IUnknown +** IOleObject interface +** IPersistStorage interface +** IDataObject interface +** +** ServerApp Object +** exposed interfaces: +** IUnknown +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + + +#include "outline.h" + +OLEDBGDATA + +extern LPOUTLINEAPP g_lpApp; +extern IOleObjectVtbl g_SvrDoc_OleObjectVtbl; +extern IPersistStorageVtbl g_SvrDoc_PersistStorageVtbl; + +#if defined( INPLACE_SVR ) +extern IOleInPlaceObjectVtbl g_SvrDoc_OleInPlaceObjectVtbl; +extern IOleInPlaceActiveObjectVtbl g_SvrDoc_OleInPlaceActiveObjectVtbl; +#endif // INPLACE_SVR + +#if defined( SVR_TREATAS ) +extern IStdMarshalInfoVtbl g_SvrDoc_StdMarshalInfoVtbl; +#endif // SVR_TREATAS + + +// REVIEW: should use string resource for messages +extern char ErrMsgSaving[]; +extern char ErrMsgFormatNotSupported[]; +static char ErrMsgPSSaveFail[] = "PSSave failed"; +static char ErrMsgLowMemNClose[] = "Warning OUT OF MEMORY! We must close down"; +extern char g_szUpdateCntrDoc[] = "&Update %s"; +extern char g_szExitNReturnToCntrDoc[] = "E&xit && Return to %s"; + + +/************************************************************************* +** ServerDoc::IOleObject interface implementation +*************************************************************************/ + +// IOleObject::QueryInterface method + +STDMETHODIMP SvrDoc_OleObj_QueryInterface( + LPOLEOBJECT lpThis, + REFIID riid, + LPVOID FAR* lplpvObj +) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; + + return OleDoc_QueryInterface((LPOLEDOC)lpServerDoc, riid, lplpvObj); +} + + +// IOleObject::AddRef method + +STDMETHODIMP_(ULONG) SvrDoc_OleObj_AddRef(LPOLEOBJECT lpThis) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; + + OleDbgAddRefMethod(lpThis, "IOleObject"); + + return OleDoc_AddRef((LPOLEDOC)lpServerDoc); +} + + +// IOleObject::Release method + +STDMETHODIMP_(ULONG) SvrDoc_OleObj_Release(LPOLEOBJECT lpThis) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; + + OleDbgReleaseMethod(lpThis, "IOleObject"); + + return OleDoc_Release((LPOLEDOC)lpServerDoc); +} + + +// IOleObject::SetClientSite method + +STDMETHODIMP SvrDoc_OleObj_SetClientSite( + LPOLEOBJECT lpThis, + LPOLECLIENTSITE lpclientSite +) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; + + OLEDBG_BEGIN2("SvrDoc_OleObj_SetClientSite\r\n") + + // SetClientSite is only valid to call on an embedded object + if (lpOutlineDoc->m_docInitType != DOCTYPE_EMBEDDED) { + OleDbgAssert(lpOutlineDoc->m_docInitType == DOCTYPE_EMBEDDED); + OLEDBG_END2 + return ResultFromScode(E_UNEXPECTED); + } + + /* if we currently have a client site ptr, then release it. */ + if (lpServerDoc->m_lpOleClientSite) + OleStdRelease((LPUNKNOWN)lpServerDoc->m_lpOleClientSite); + + lpServerDoc->m_lpOleClientSite = (LPOLECLIENTSITE) lpclientSite; + // OLE2NOTE: to be able to hold onto clientSite pointer, we must AddRef it + if (lpclientSite) + lpclientSite->lpVtbl->AddRef(lpclientSite); + + OLEDBG_END2 + return NOERROR; +} + + +// IOleObject::GetClientSite method + +STDMETHODIMP SvrDoc_OleObj_GetClientSite( + LPOLEOBJECT lpThis, + LPOLECLIENTSITE FAR* lplpClientSite +) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; + OleDbgOut2("SvrDoc_OleObj_GetClientSite\r\n"); + + /* OLE2NOTE: we MUST AddRef this interface pointer to give the + ** caller a personal copy of the pointer + */ + lpServerDoc->m_lpOleClientSite->lpVtbl->AddRef( + lpServerDoc->m_lpOleClientSite + ); + *lplpClientSite = lpServerDoc->m_lpOleClientSite; + + return NOERROR; + +} + + +// IOleObject::SetHostNames method + +STDMETHODIMP SvrDoc_OleObj_SetHostNamesA( + LPOLEOBJECT lpThis, + LPCSTR szContainerApp, + LPCSTR szContainerObj +) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; + OleDbgOut2("SvrDoc_OleObj_SetHostNames\r\n"); + + LSTRCPYN((LPSTR)lpServerDoc->m_szContainerApp, szContainerApp, + sizeof(lpServerDoc->m_szContainerApp)); + LSTRCPYN((LPSTR)lpServerDoc->m_szContainerObj, szContainerObj, + sizeof(lpServerDoc->m_szContainerObj)); + + /* The Window title for an embedded object is constructed as + ** follows: + ** - in + ** + ** here we construct the current document title portion of the + ** name which follows the '-'. OutlineDoc_SetTitle prepends the + ** " - " to the document title. + */ + // REVIEW: this string should be loaded from string resource + wsprintf(lpOutlineDoc->m_szFileName, "%s in %s", + (LPSTR)SHORTUSERTYPENAME, (LPSTR)lpServerDoc->m_szContainerObj); + + lpOutlineDoc->m_lpszDocTitle = lpOutlineDoc->m_szFileName; + OutlineDoc_SetTitle(lpOutlineDoc, FALSE /*fMakeUpperCase*/); + + /* OLE2NOTE: update the application menus correctly for an embedded + ** object. the changes include: + ** 1 Remove File/New and File/Open (SDI ONLY) + ** 2 Change File/Save As.. to File/Save Copy As.. + ** 3 Change File menu so it contains "Update" instead of "Save" + ** 4 Change File/Exit to File/Exit & Return to " + */ + ServerDoc_UpdateMenu(lpServerDoc); + + return NOERROR; +} + +STDMETHODIMP SvrDoc_OleObj_SetHostNames( + LPOLEOBJECT lpThis, + LPCOLESTR szContainerApp, + LPCOLESTR szContainerObj +) +{ + CREATESTR(pstrApp, szContainerApp) + CREATESTR(pstrObj, szContainerObj) + + HRESULT hr = SvrDoc_OleObj_SetHostNamesA(lpThis, pstrApp, pstrObj); + + FREESTR(pstrApp) + FREESTR(pstrObj) + + return hr; +} + + + +// IOleObject::Close method + +STDMETHODIMP SvrDoc_OleObj_Close( + LPOLEOBJECT lpThis, + DWORD dwSaveOption +) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; + BOOL fStatus; + + OLEDBG_BEGIN2("SvrDoc_OleObj_Close\r\n") + + /* OLE2NOTE: the OLE 2.0 user model is that embedded objects should + ** always be saved when closed WITHOUT any prompting to the + ** user. this is the recommendation irregardless of whether the + ** object is activated in-place or open in its own window. + ** this is a CHANGE from the OLE 1.0 user model where it + ** was the guideline that servers always prompt to save changes. + ** thus OLE 2.0 compound document oriented container's should + ** always pass dwSaveOption==OLECLOSE_SAVEIFDIRTY. it is + ** possible that for programmatic uses a container may want to + ** specify a different dwSaveOption. the implementation of + ** various save options can be tricky, particularly considering + ** cases involving in-place activation. the following would be + ** reasonable behavior: + ** + ** (1) OLECLOSE_SAVEIFDIRTY: if dirty, save. close. + ** (2) OLECLOSE_NOSAVE: close. + ** (3) OLECLOSE_PROMPTSAVE: + ** (a) object visible, but not in-place: + ** if not dirty, close. + ** switch(prompt) + ** case IDYES: save. close. + ** case IDNO: close. + ** case IDCANCEL: return OLE_E_PROMPTSAVECANCELLED + ** (b) object invisible (includes UIDeactivated object) + ** if dirty, save. close. + ** NOTE: NO PROMPT. it is not appropriate to prompt + ** if the object is not visible. + ** (c) object is in-place active: + ** if dirty, save. close. + ** NOTE: NO PROMPT. it is not appropriate to prompt + ** if the object is active in-place. + */ + fStatus = OutlineDoc_Close((LPOUTLINEDOC)lpServerDoc, dwSaveOption); + OleDbgAssertSz(fStatus == TRUE, "SvrDoc_OleObj_Close failed\r\n"); + + OLEDBG_END2 + return (fStatus ? NOERROR : ResultFromScode(E_FAIL)); +} + + +// IOleObject::SetMoniker method + +STDMETHODIMP SvrDoc_OleObj_SetMoniker( + LPOLEOBJECT lpThis, + DWORD dwWhichMoniker, + LPMONIKER lpmk +) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; + LPOLEDOC lpOleDoc = (LPOLEDOC)lpServerDoc; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; + LPMONIKER lpmkFull = NULL; + HRESULT hrErr; + SCODE sc; + + OLEDBG_BEGIN2("SvrDoc_OleObj_SetMoniker\r\n") + + /* OLE2NOTE: if our full moniker is passed then we can use it, + ** otherwise we must call back to our ClientSite to get our full + ** moniker. + */ + if (dwWhichMoniker == OLEWHICHMK_OBJFULL) { + + /* Register the document as running with the new moniker and + ** notify any clients that our moniker has changed. + */ + OleDoc_DocRenamedUpdate(lpOleDoc, lpmk); + + if (lpOutlineDoc->m_docInitType != DOCTYPE_EMBEDDED) { + IBindCtx FAR *pbc = NULL; + LPSTR lpszName = NULL; + + /* OLE2NOTE: if this is a FILE-based or untitled document + ** then we should accept this new moniker as our document's + ** moniker. we will remember this moniker instead of the + ** FileMoniker that we have by default. this allows + ** systems that use special monikers to track the + ** location of documents to inform a document that is a + ** link source of its special moniker. this enables the + ** document to use this special moniker when building + ** composite monikers to identify contained objects and + ** pseudo objects (ranges). + ** + ** we should also use the DisplayName form of this + ** moniker as our document name in our window title. + */ + if (lpOleDoc->m_lpFileMoniker) { + lpOleDoc->m_lpFileMoniker->lpVtbl->Release( + lpOleDoc->m_lpFileMoniker); + } + lpOleDoc->m_lpFileMoniker = lpmk; + // we must AddRef the moniker to hold on to it + lpmk->lpVtbl->AddRef(lpmk); + + /* we should also use the DisplayName form of this + ** moniker as our document name in our window title. + */ + CreateBindCtx(0, (LPBC FAR*)&pbc); + CallIMonikerGetDisplayNameA(lpmk,pbc,NULL,&lpszName); + pbc->lpVtbl->Release(pbc); + if (lpszName) { + LSTRCPYN(lpOutlineDoc->m_szFileName, lpszName, + sizeof(lpOutlineDoc->m_szFileName)); + lpOutlineDoc->m_lpszDocTitle = lpOutlineDoc->m_szFileName; + OutlineDoc_SetTitle(lpOutlineDoc, FALSE /*fMakeUpperCase*/); + OleStdFreeString(lpszName, NULL); + } + } + + OLEDBG_END2 + return NOERROR; + } + + /* if the passed moniker was NOT a full moniker then we must call + ** back to our ClientSite to get our full moniker. this is + ** needed in order to register in the RunningObjectTable. if we + ** don't have a ClientSite then this is an error. + */ + if (lpServerDoc->m_lpOleClientSite == NULL) { + sc = E_FAIL; + goto error; + } + + hrErr = lpServerDoc->m_lpOleClientSite->lpVtbl->GetMoniker( + lpServerDoc->m_lpOleClientSite, + OLEGETMONIKER_ONLYIFTHERE, + OLEWHICHMK_OBJFULL, + &lpmkFull + ); + if (hrErr != NOERROR) { + sc = GetScode(hrErr); + goto error; + } + + /* Register the document as running with the new moniker and + ** notify any clients that our moniker has changed. + */ + OleDoc_DocRenamedUpdate(lpOleDoc, lpmkFull); + + if (lpmkFull) + OleStdRelease((LPUNKNOWN)lpmkFull); + + OLEDBG_END2 + return NOERROR; + +error: + OLEDBG_END2 + return ResultFromScode(sc); +} + + +// IOleObject::GetMoniker method + +STDMETHODIMP SvrDoc_OleObj_GetMoniker( + LPOLEOBJECT lpThis, + DWORD dwAssign, + DWORD dwWhichMoniker, + LPMONIKER FAR* lplpmk +) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; + LPOLEDOC lpOleDoc = (LPOLEDOC)lpServerDoc; + SCODE sc; + + OLEDBG_BEGIN2("SvrDoc_OleObj_GetMoniker\r\n") + + /* OLE2NOTE: we must make sure to set all out parameters to NULL. */ + *lplpmk = NULL; + + if (lpServerDoc->m_lpOleClientSite) { + + /* document is an embedded object. retrieve our moniker from + ** our container. + */ + OLEDBG_BEGIN2("IOleClientSite::GetMoniker called\r\n") + sc = GetScode( lpServerDoc->m_lpOleClientSite->lpVtbl->GetMoniker( + lpServerDoc->m_lpOleClientSite, + dwAssign, + dwWhichMoniker, + lplpmk + ) ); + OLEDBG_END2 + + } else if (lpOleDoc->m_lpFileMoniker) { + + /* document is a top-level user document (either + ** file-based or untitled). return the FileMoniker stored + ** with the document; it uniquely identifies the document. + */ + if (dwWhichMoniker == OLEWHICHMK_CONTAINER) + sc = E_INVALIDARG; // file-based object has no CONTAINER moniker + else { + *lplpmk = lpOleDoc->m_lpFileMoniker; + (*lplpmk)->lpVtbl->AddRef(*lplpmk); // must AddRef to pass out ptr + sc = S_OK; + } + + } else { + // document is not yet fully initialized => no moniker + sc = E_FAIL; + } + + OLEDBG_END2 + return ResultFromScode(sc); +} + + +// IOleObject::InitFromData method + +STDMETHODIMP SvrDoc_OleObj_InitFromData( + LPOLEOBJECT lpThis, + LPDATAOBJECT lpDataObject, + BOOL fCreation, + DWORD reserved +) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; + + OLEDBG_BEGIN2("SvrDoc_OleObj_InitFromData\r\n") + + // REVIEW: NOT YET IMPLEMENTED + + OLEDBG_END2 + return ResultFromScode(E_NOTIMPL); +} + + +// IOleObject::GetClipboardData method + +STDMETHODIMP SvrDoc_OleObj_GetClipboardData( + LPOLEOBJECT lpThis, + DWORD reserved, + LPDATAOBJECT FAR* lplpDataObject +) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; + + OLEDBG_BEGIN2("SvrDoc_OleObj_GetClipboardData\r\n") + + // REVIEW: NOT YET IMPLEMENTED + + OLEDBG_END2 + return ResultFromScode(E_NOTIMPL); +} + + +// IOleObject::DoVerb method + +STDMETHODIMP SvrDoc_OleObj_DoVerb( + LPOLEOBJECT lpThis, + LONG lVerb, + LPMSG lpmsg, + LPOLECLIENTSITE lpActiveSite, + LONG lindex, + HWND hwndParent, + LPCRECT lprcPosRect +) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; + SCODE sc = S_OK; + + OLEDBG_BEGIN2("SvrDoc_OleObj_DoVerb\r\n") + + switch (lVerb) { + + default: + /* OLE2NOTE: when an unknown verb number is given, the + ** server must take careful action: + ** 1. if it is one of the specially defined OLEIVERB + ** (negative numbered) verbs, the app should return an + ** error (E_NOTIMPL) and perform no action. + ** + ** 2. if the verb is a application specific verb + ** (positive numbered verb), then the app should + ** return the special scode (OLEOBJ_S_INVALIDVERB). BUT, + ** we should still perform our normal primary verb action. + */ + if (lVerb < 0) { + OLEDBG_END2 + return ResultFromScode(E_NOTIMPL); + } else { + sc = OLEOBJ_S_INVALIDVERB; + } + + // deliberatly fall through to Primary Verb + +#if !defined( INPLACE_SVR ) + case 0: + case OLEIVERB_SHOW: + case OLEIVERB_OPEN: + OutlineDoc_ShowWindow(lpOutlineDoc); + break; + + case OLEIVERB_HIDE: + OleDoc_HideWindow((LPOLEDOC)lpServerDoc, FALSE /*fShutdown*/); + break; +#endif // ! INPLACE_SVR +#if defined( INPLACE_SVR ) + case 0: + case OLEIVERB_SHOW: + + /* OLE2NOTE: if our window is already open (visible) then + ** we should simply surface the open window. if not, + ** then we can do our primary action of in-place + ** activation. + */ + if ( lpServerDoc->m_lpOleClientSite + && ! (IsWindowVisible(lpOutlineDoc->m_hWndDoc) && + ! lpServerDoc->m_fInPlaceActive) ) { + ServerDoc_DoInPlaceActivate( + lpServerDoc, lVerb, lpmsg, lpActiveSite); + } + OutlineDoc_ShowWindow(lpOutlineDoc); + break; + + case 1: + case OLEIVERB_OPEN: + ServerDoc_DoInPlaceDeactivate(lpServerDoc); + OutlineDoc_ShowWindow(lpOutlineDoc); + break; + + + case OLEIVERB_HIDE: + if (lpServerDoc->m_fInPlaceActive) { + + SvrDoc_IPObj_UIDeactivate( + (LPOLEINPLACEOBJECT)&lpServerDoc->m_OleInPlaceObject); + +#if defined( SVR_INSIDEOUT ) + /* OLE2NOTE: an inside-out style in-place server will + ** NOT hide its window in UIDeactive (an outside-in + ** style object will hide its window in + ** UIDeactivate). thus we need to explicitly hide + ** our window now. + */ + ServerDoc_DoInPlaceHide(lpServerDoc); +#endif // INSIEDOUT + + } else { + OleDoc_HideWindow((LPOLEDOC)lpServerDoc, FALSE /*fShutdown*/); + } + break; + + case OLEIVERB_UIACTIVATE: + +#if defined( SVR_INSIDEOUT ) + /* OLE2NOTE: only an inside-out style object supports + ** INPLACEACTIVATE verb + */ + case OLEIVERB_INPLACEACTIVATE: +#endif // SVR_INSIDEOUT + + /* OLE2NOTE: if our window is already open (visible) then + ** we can NOT activate in-place. + */ + if (IsWindowVisible(lpOutlineDoc->m_hWndDoc) && + ! lpServerDoc->m_fInPlaceActive ) { + sc = OLE_E_NOT_INPLACEACTIVE; + } else { + sc = GetScode( ServerDoc_DoInPlaceActivate( + lpServerDoc, lVerb, lpmsg, lpActiveSite) ); + if (SUCCEEDED(sc)) + OutlineDoc_ShowWindow(lpOutlineDoc); + } + break; +#endif // INPLACE_SVR + } + + OLEDBG_END2 + return ResultFromScode(sc); +} + + +// IOleObject::EnumVerbs method + +STDMETHODIMP SvrDoc_OleObj_EnumVerbs( + LPOLEOBJECT lpThis, + LPENUMOLEVERB FAR* lplpenumOleVerb +) +{ + OleDbgOut2("SvrDoc_OleObj_EnumVerbs\r\n"); + + /* OLE2NOTE: we must make sure to set all out parameters to NULL. */ + *lplpenumOleVerb = NULL; + + /* An object implemented as a server EXE (as this sample + ** is) may simply return OLE_S_USEREG to instruct the OLE + ** DefHandler to call the OleReg* helper API which uses info in + ** the registration database. Alternatively, the OleRegEnumVerbs + ** API may be called directly. Objects implemented as a server + ** DLL may NOT return OLE_S_USEREG; they must call the OleReg* + ** API or provide their own implementation. For EXE based + ** objects it is more efficient to return OLE_S_USEREG, because + ** in then the verb enumerator is instantiated in the callers + ** process space and no LRPC remoting is required. + */ + return ResultFromScode(OLE_S_USEREG); +} + + +// IOleObject::Update method + +STDMETHODIMP SvrDoc_OleObj_Update(LPOLEOBJECT lpThis) +{ + OleDbgOut2("SvrDoc_OleObj_Update\r\n"); + + /* OLE2NOTE: a server-only app is always "up-to-date". + ** a container-app which contains links where the link source + ** has changed since the last update of the link would be + ** considered "out-of-date". the "Update" method instructs the + ** object to get an update from any out-of-date links. + */ + + return NOERROR; +} + + +// IOleObject::IsUpToDate method + +STDMETHODIMP SvrDoc_OleObj_IsUpToDate(LPOLEOBJECT lpThis) +{ + OleDbgOut2("SvrDoc_OleObj_IsUpToDate\r\n"); + + /* OLE2NOTE: a server-only app is always "up-to-date". + ** a container-app which contains links where the link source + ** has changed since the last update of the link would be + ** considered "out-of-date". + */ + return NOERROR; +} + + +// IOleObject::GetUserClassID method + +STDMETHODIMP SvrDoc_OleObj_GetUserClassID( + LPOLEOBJECT lpThis, + LPCLSID lpClassID +) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; + OleDbgOut2("SvrDoc_OleObj_GetClassID\r\n"); + + /* OLE2NOTE: we must be carefull to return the correct CLSID here. + ** if we are currently preforming a "TreatAs (aka. ActivateAs)" + ** operation then we need to return the class of the object + ** written in the storage of the object. otherwise we would + ** return our own class id. + */ + return ServerDoc_GetClassID(lpServerDoc, lpClassID); +} + + +// IOleObject::GetUserType method + +STDMETHODIMP SvrDoc_OleObj_GetUserTypeA( + LPOLEOBJECT lpThis, + DWORD dwFormOfType, + LPSTR FAR* lpszUserType +) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; + OleDbgOut2("SvrDoc_OleObj_GetUserType\r\n"); + + /* OLE2NOTE: we must make sure to set all out parameters to NULL. */ + *lpszUserType = NULL; + + /* OLE2NOTE: we must be carefull to return the correct user type here. + ** if we are currently preforming a "TreatAs (aka. ActivateAs)" + ** operation then we need to return the user type name that + ** corresponds to the class of the object we are currently + ** emmulating. otherwise we should return our normal user type + ** name corresponding to our own class. This routine determines + ** the current clsid in effect. + ** + ** An object implemented as a server EXE (as this sample + ** is) may simply return OLE_S_USEREG to instruct the OLE + ** DefHandler to call the OleReg* helper API which uses info in + ** the registration database. Alternatively, the OleRegGetUserType + ** API may be called directly. Objects implemented as a server + ** DLL may NOT return OLE_S_USEREG; they must call the OleReg* + ** API or provide their own implementation. For EXE based + ** objects it is more efficient to return OLE_S_USEREG, because + ** in then the return string is instantiated in the callers + ** process space and no LRPC remoting is required. + */ +#if defined( SVR_TREATAS ) + if (! IsEqualCLSID(&lpServerDoc->m_clsidTreatAs, &CLSID_NULL) ) + return OleRegGetUserTypeA( + &lpServerDoc->m_clsidTreatAs,dwFormOfType,lpszUserType); + else +#endif // SVR_TREATAS + + return ResultFromScode(OLE_S_USEREG); +} + + + +STDMETHODIMP SvrDoc_OleObj_GetUserType( + LPOLEOBJECT lpThis, + DWORD dwFormOfType, + LPOLESTR FAR* lpszUserType +) +{ + LPSTR pstr; + + HRESULT hr = SvrDoc_OleObj_GetUserTypeA(lpThis, dwFormOfType, &pstr); + + CopyAndFreeSTR(pstr, lpszUserType); + + return hr; +} + + + +// IOleObject::SetExtent method + +STDMETHODIMP SvrDoc_OleObj_SetExtent( + LPOLEOBJECT lpThis, + DWORD dwDrawAspect, + LPSIZEL lplgrc +) +{ + OleDbgOut2("SvrDoc_OleObj_SetExtent\r\n"); + + /* SVROUTL does NOT allow the object's size to be set by its + ** container. the size of the ServerDoc object is determined by + ** the data contained within the document. + */ + return ResultFromScode(E_FAIL); +} + + +// IOleObject::GetExtent method + +STDMETHODIMP SvrDoc_OleObj_GetExtent( + LPOLEOBJECT lpThis, + DWORD dwDrawAspect, + LPSIZEL lpsizel +) +{ + LPOLEDOC lpOleDoc = + (LPOLEDOC)((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; + OleDbgOut2("SvrDoc_OleObj_GetExtent\r\n"); + + /* OLE2NOTE: it is VERY important to check which aspect the caller + ** is asking about. an object implemented by a server EXE MAY + ** fail to return extents when asked for DVASPECT_ICON. + */ + if (dwDrawAspect == DVASPECT_CONTENT) { + OleDoc_GetExtent(lpOleDoc, lpsizel); + return NOERROR; + } + +#if defined( LATER ) + + else if (dwDrawAspect == DVASPECT_THUMBNAIL) + { + /* as our thumbnail we will render only the first page of the + ** document. calculate extents of our thumbnail rendering. + ** + ** OLE2NOTE: thumbnails are most often used by applications in + ** FindFile or FileOpen type dialogs to give the user a + ** quick view of the contents of the file or object. + */ + OleDoc_GetThumbnailExtent(lpOleDoc, lpsizel); + return NOERROR; + } +#endif + + else + { + return ResultFromScode(E_FAIL); + } +} + + +// IOleObject::Advise method + +STDMETHODIMP SvrDoc_OleObj_Advise( + LPOLEOBJECT lpThis, + LPADVISESINK lpAdvSink, + LPDWORD lpdwConnection +) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; + HRESULT hrErr; + SCODE sc; + + OLEDBG_BEGIN2("SvrDoc_OleObj_Advise\r\n"); + + if (lpServerDoc->m_OleDoc.m_fObjIsClosing) + { + // We don't accept any more Advise's once we're closing + sc = OLE_E_ADVISENOTSUPPORTED; + goto error; + } + + if (lpServerDoc->m_lpOleAdviseHldr == NULL && + CreateOleAdviseHolder(&lpServerDoc->m_lpOleAdviseHldr) != NOERROR) { + sc = E_OUTOFMEMORY; + goto error; + } + + OLEDBG_BEGIN2("IOleAdviseHolder::Advise called\r\n") + hrErr = lpServerDoc->m_lpOleAdviseHldr->lpVtbl->Advise( + lpServerDoc->m_lpOleAdviseHldr, + lpAdvSink, + lpdwConnection + ); + OLEDBG_END2 + + OLEDBG_END2 + return hrErr; + +error: + OLEDBG_END2 + *lpdwConnection = 0; + return ResultFromScode(sc); +} + + +// IOleObject::Unadvise method + +STDMETHODIMP SvrDoc_OleObj_Unadvise(LPOLEOBJECT lpThis, DWORD dwConnection) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; + HRESULT hrErr; + SCODE sc; + + OLEDBG_BEGIN2("SvrDoc_OleObj_Unadvise\r\n"); + + if (lpServerDoc->m_lpOleAdviseHldr == NULL) { + sc = E_FAIL; + goto error; + } + + OLEDBG_BEGIN2("IOleAdviseHolder::Unadvise called\r\n") + hrErr = lpServerDoc->m_lpOleAdviseHldr->lpVtbl->Unadvise( + lpServerDoc->m_lpOleAdviseHldr, + dwConnection + ); + OLEDBG_END2 + + OLEDBG_END2 + return hrErr; + +error: + OLEDBG_END2 + return ResultFromScode(sc); +} + + +// IOleObject::EnumAdvise method + +STDMETHODIMP SvrDoc_OleObj_EnumAdvise( + LPOLEOBJECT lpThis, + LPENUMSTATDATA FAR* lplpenumAdvise +) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; + HRESULT hrErr; + SCODE sc; + + OLEDBG_BEGIN2("SvrDoc_OleObj_EnumAdvise\r\n"); + + /* OLE2NOTE: we must make sure to set all out parameters to NULL. */ + *lplpenumAdvise = NULL; + + if (lpServerDoc->m_lpOleAdviseHldr == NULL) { + sc = E_FAIL; + goto error; + } + + OLEDBG_BEGIN2("IOleAdviseHolder::EnumAdvise called\r\n") + hrErr = lpServerDoc->m_lpOleAdviseHldr->lpVtbl->EnumAdvise( + lpServerDoc->m_lpOleAdviseHldr, + lplpenumAdvise + ); + OLEDBG_END2 + + OLEDBG_END2 + return hrErr; + +error: + OLEDBG_END2 + return ResultFromScode(sc); +} + + +// IOleObject::GetMiscStatus method + +STDMETHODIMP SvrDoc_OleObj_GetMiscStatus( + LPOLEOBJECT lpThis, + DWORD dwAspect, + DWORD FAR* lpdwStatus +) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; + OleDbgOut2("SvrDoc_OleObj_GetMiscStatus\r\n"); + + /* Get our default MiscStatus for the given Aspect. this + ** information is registered in the RegDB. We query the RegDB + ** here to guarantee that the value returned from this method + ** agrees with the values in RegDB. in this way we only have to + ** maintain the info in one place (in the RegDB). Alternatively + ** we could have the values hard coded here. + */ + OleRegGetMiscStatus((REFCLSID)&CLSID_APP, dwAspect, lpdwStatus); + + /* OLE2NOTE: check if the data copied is compatible to be + ** linked by an OLE 1.0 container. it is compatible if + ** either the data is an untitled document, a file, or a + ** selection of data within a file. if the data is part of + ** an embedded object, then it is NOT compatible to be + ** linked by an OLE 1.0 container. if it is compatible then + ** we must include OLEMISC_CANLINKBYOLE1 as part of the + ** dwStatus flags transfered via CF_OBJECTDESCRIPTOR or + ** CF_LINKSRCDESCRIPTOR. + */ + if (lpOutlineDoc->m_docInitType == DOCTYPE_NEW || + lpOutlineDoc->m_docInitType == DOCTYPE_FROMFILE) + *lpdwStatus |= OLEMISC_CANLINKBYOLE1; + +#if defined( INPLACE_SVR ) + if (dwAspect == DVASPECT_CONTENT) + *lpdwStatus |= (OLEMISC_INSIDEOUT | OLEMISC_ACTIVATEWHENVISIBLE); +#endif // INPLACE_SVR + return NOERROR; +} + + +// IOleObject::SetColorScheme method + +STDMETHODIMP SvrDoc_OleObj_SetColorScheme( + LPOLEOBJECT lpThis, + LPLOGPALETTE lpLogpal +) +{ + OleDbgOut2("SvrDoc_OleObj_SetColorScheme\r\n"); + + // REVIEW: NOT YET IMPLEMENTED + + return ResultFromScode(E_NOTIMPL); +} + + +/************************************************************************* +** ServerDoc::IPersistStorage interface implementation +*************************************************************************/ + +// IPersistStorage::QueryInterface method + +STDMETHODIMP SvrDoc_PStg_QueryInterface( + LPPERSISTSTORAGE lpThis, + REFIID riid, + LPVOID FAR* lplpvObj +) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocPersistStorageImpl FAR*)lpThis)->lpServerDoc; + + return OleDoc_QueryInterface((LPOLEDOC)lpServerDoc, riid, lplpvObj); +} + + +// IPersistStorage::AddRef method + +STDMETHODIMP_(ULONG) SvrDoc_PStg_AddRef(LPPERSISTSTORAGE lpThis) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocPersistStorageImpl FAR*)lpThis)->lpServerDoc; + + OleDbgAddRefMethod(lpThis, "IPersistStorage"); + + return OleDoc_AddRef((LPOLEDOC)lpServerDoc); +} + + +// IPersistStorage::Release method + +STDMETHODIMP_(ULONG) SvrDoc_PStg_Release(LPPERSISTSTORAGE lpThis) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocPersistStorageImpl FAR*)lpThis)->lpServerDoc; + + OleDbgReleaseMethod(lpThis, "IPersistStorage"); + + return OleDoc_Release((LPOLEDOC)lpServerDoc); +} + + +// IPersistStorage::GetClassID method + +STDMETHODIMP SvrDoc_PStg_GetClassID( + LPPERSISTSTORAGE lpThis, + LPCLSID lpClassID +) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocPersistStorageImpl FAR*)lpThis)->lpServerDoc; + OleDbgOut2("SvrDoc_PStg_GetClassID\r\n"); + + /* OLE2NOTE: we must be carefull to return the correct CLSID here. + ** if we are currently preforming a "TreatAs (aka. ActivateAs)" + ** operation then we need to return the class of the object + ** written in the storage of the object. otherwise we would + ** return our own class id. + */ + return ServerDoc_GetClassID(lpServerDoc, lpClassID); +} + + +// IPersistStorage::IsDirty method + +STDMETHODIMP SvrDoc_PStg_IsDirty(LPPERSISTSTORAGE lpThis) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocPersistStorageImpl FAR*)lpThis)->lpServerDoc; + OleDbgOut2("SvrDoc_PStg_IsDirty\r\n"); + + if (OutlineDoc_IsModified((LPOUTLINEDOC)lpServerDoc)) + return NOERROR; + else + return ResultFromScode(S_FALSE); +} + + + +// IPersistStorage::InitNew method + +STDMETHODIMP SvrDoc_PStg_InitNew( + LPPERSISTSTORAGE lpThis, + LPSTORAGE lpStg +) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocPersistStorageImpl FAR*)lpThis)->lpServerDoc; + LPOLEDOC lpOleDoc = (LPOLEDOC)lpServerDoc; + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + LPSTR lpszUserType = (LPSTR)FULLUSERTYPENAME; + HRESULT hrErr; + SCODE sc; + + OLEDBG_BEGIN2("SvrDoc_PStg_InitNew\r\n") + +#if defined( SVR_TREATAS ) + { + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + CLSID clsid; + CLIPFORMAT cfFmt; + LPSTR lpszType; + + /* OLE2NOTE: if the Server is capable of supporting "TreatAs" + ** (aka. ActivateAs), it must read the class that is written + ** into the storage. if this class is NOT the app's own + ** class ID, then this is a TreatAs operation. the server + ** then must faithfully pretend to be the class that is + ** written into the storage. it must also faithfully write + ** the data back to the storage in the SAME format as is + ** written in the storage. + ** + ** SVROUTL and ISVROTL can emulate each other. they have the + ** simplification that they both read/write the identical + ** format. thus for these apps no actual conversion of the + ** native bits is actually required. + */ + lpServerDoc->m_clsidTreatAs = CLSID_NULL; + if (OleStdGetTreatAsFmtUserType(&CLSID_APP, lpStg, &clsid, + (CLIPFORMAT FAR*)&cfFmt, (LPSTR FAR*)&lpszType)) { + + if (cfFmt == lpOutlineApp->m_cfOutline) { + // We should perform TreatAs operation + if (lpServerDoc->m_lpszTreatAsType) + OleStdFreeString(lpServerDoc->m_lpszTreatAsType, NULL); + + lpServerDoc->m_clsidTreatAs = clsid; + ((LPOUTLINEDOC)lpServerDoc)->m_cfSaveFormat = cfFmt; + lpServerDoc->m_lpszTreatAsType = lpszType; + lpszUserType = lpServerDoc->m_lpszTreatAsType; + + OleDbgOut3("SvrDoc_PStg_InitNew: TreateAs ==> '"); + OleDbgOutNoPrefix3(lpServerDoc->m_lpszTreatAsType); + OleDbgOutNoPrefix3("'\r\n"); + } else { + // ERROR: we ONLY support TreatAs for CF_OUTLINE format + OleDbgOut("SvrDoc_PStg_InitNew: INVALID TreatAs Format\r\n"); + OleStdFreeString(lpszType, NULL); + } + } + } +#endif // SVR_TREATAS + + /* OLE2NOTE: a server EXE object should write its format tag to its + ** storage in InitNew so that the DefHandler can know the format + ** of the object. this is particularly important if the objects + ** uses CF_METATFILE or CF_DIB as its format. the DefHandler + ** automatically avoids separately storing presentation cache + ** data when the object's native data is a standard presentation + ** format. + */ + WriteFmtUserTypeStgA(lpStg,lpOutlineApp->m_cfOutline,lpszUserType); + + // set the doc to a new embedded object. + if (! ServerDoc_InitNewEmbed(lpServerDoc)) { + sc = E_FAIL; + goto error; + } + + /* OLE2NOTE: An embedded object must guarantee that it can save + ** even in low memory situations. it must be able to + ** successfully save itself without consuming any additional + ** memory. this means that a server is NOT supposed to open or + ** create any streams or storages when + ** IPersistStorage::Save(fSameAsLoad==TRUE) is called. thus an + ** embedded object should hold onto its storage and pre-open and + ** hold open any streams that it will need later when it is time + ** to save. + */ + hrErr = CallIStorageCreateStreamA( + lpStg, + "LineList", + STGM_WRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE, + 0, + 0, + &lpOleDoc->m_lpLLStm + ); + + if (hrErr != NOERROR) { + OleDbgAssertSz(hrErr==NOERROR,"Could not create LineList stream"); + OleDbgOutHResult("LineList CreateStream returned", hrErr); + sc = GetScode(hrErr); + goto error; + } + + hrErr = CallIStorageCreateStreamA( + lpStg, + "NameTable", + STGM_WRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE, + 0, + 0, + &lpOleDoc->m_lpNTStm + ); + + if (hrErr != NOERROR) { + OleDbgAssertSz(hrErr==NOERROR,"Could not create NameTable stream"); + OleDbgOutHResult("NameTable CreateStream returned", hrErr); + sc = GetScode(hrErr); + goto error; + } + + lpOleDoc->m_lpStg = lpStg; + + // OLE2NOTE: to be able to hold onto IStorage* pointer, we must AddRef it + lpStg->lpVtbl->AddRef(lpStg); + + OLEDBG_END2 + return NOERROR; + +error: + OLEDBG_END2 + return ResultFromScode(sc); +} + + +// IPersistStorage::Load method + +STDMETHODIMP SvrDoc_PStg_Load( + LPPERSISTSTORAGE lpThis, + LPSTORAGE lpStg +) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocPersistStorageImpl FAR*)lpThis)->lpServerDoc; + LPOLEDOC lpOleDoc = (LPOLEDOC)lpServerDoc; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; + SCODE sc; + HRESULT hrErr; + + OLEDBG_BEGIN2("SvrDoc_PStg_Load\r\n") + + if (OutlineDoc_LoadFromStg((LPOUTLINEDOC)lpServerDoc, lpStg)) { + + ((LPOUTLINEDOC)lpServerDoc)->m_docInitType = DOCTYPE_EMBEDDED; + + /* OLE2NOTE: we need to check if the ConvertStg bit is on. if + ** so, we need to clear the ConvertStg bit and mark the + ** document as dirty so as to force a save when the document + ** is closed. the actual conversion of the bits should be + ** performed when the data is loaded from the IStorage*. in + ** our case any conversion of data formats would be done in + ** OutlineDoc_LoadFromStg function. in reality both SVROUTL + ** and ISVROTL read and write the same format so no actual + ** conversion of data bits is necessary. + */ + if (GetConvertStg(lpStg) == NOERROR) { + SetConvertStg(lpStg, FALSE); + + OleDbgOut3("SvrDoc_PStg_Load: ConvertStg==TRUE\r\n"); + OutlineDoc_SetModified(lpOutlineDoc, TRUE, FALSE, FALSE); + } + + } else { + sc = E_FAIL; + goto error; + } + + /* OLE2NOTE: An embedded object must guarantee that it can save + ** even in low memory situations. it must be able to + ** successfully save itself without consuming any additional + ** memory. this means that a server is NOT supposed to open or + ** create any streams or storages when + ** IPersistStorage::Save(fSameAsLoad==TRUE) is called. thus an + ** embedded object should hold onto its storage and pre-open and + ** hold open any streams that it will need later when it is time + ** to save. + */ + if (lpOleDoc->m_lpLLStm) + OleStdRelease((LPUNKNOWN)lpOleDoc->m_lpLLStm); + hrErr = CallIStorageOpenStreamA( + lpStg, + "LineList", + NULL, + STGM_READWRITE | STGM_SHARE_EXCLUSIVE, + 0, + &lpOleDoc->m_lpLLStm + ); + + if (hrErr != NOERROR) { + OleDbgAssertSz(hrErr==NOERROR,"Could not create LineList stream"); + OleDbgOutHResult("LineList CreateStream returned", hrErr); + sc = GetScode(hrErr); + goto error; + } + + if (lpOleDoc->m_lpNTStm) + OleStdRelease((LPUNKNOWN)lpOleDoc->m_lpNTStm); + hrErr = CallIStorageOpenStreamA( + lpStg, + "NameTable", + NULL, + STGM_READWRITE | STGM_SHARE_EXCLUSIVE, + 0, + &lpOleDoc->m_lpNTStm + ); + + if (hrErr != NOERROR) { + OleDbgAssertSz(hrErr==NOERROR,"Could not create NameTable stream"); + OleDbgOutHResult("NameTable CreateStream returned", hrErr); + sc = GetScode(hrErr); + goto error; + } + + lpOleDoc->m_lpStg = lpStg; + + // OLE2NOTE: to be able to hold onto IStorage* pointer, we must AddRef it + lpStg->lpVtbl->AddRef(lpStg); + + OLEDBG_END2 + return NOERROR; + +error: + OLEDBG_END2 + return ResultFromScode(sc); +} + + +// IPersistStorage::Save method + +STDMETHODIMP SvrDoc_PStg_Save( + LPPERSISTSTORAGE lpThis, + LPSTORAGE lpStg, + BOOL fSameAsLoad +) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocPersistStorageImpl FAR*)lpThis)->lpServerDoc; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; + BOOL fStatus; + SCODE sc; + + OLEDBG_BEGIN2("SvrDoc_PStg_Save\r\n") + + fStatus = OutlineDoc_SaveSelToStg( + (LPOUTLINEDOC)lpServerDoc, + NULL, + lpOutlineDoc->m_cfSaveFormat, + lpStg, + fSameAsLoad, + FALSE + ); + + if (! fStatus) { + OutlineApp_ErrorMessage(g_lpApp, ErrMsgPSSaveFail); + sc = E_FAIL; + goto error; + } + + lpServerDoc->m_fSaveWithSameAsLoad = fSameAsLoad; + lpServerDoc->m_fNoScribbleMode = TRUE; + + OLEDBG_END2 + return NOERROR; + +error: + OLEDBG_END2 + return ResultFromScode(sc); +} + + + +// IPersistStorage::SaveCompleted method + +STDMETHODIMP SvrDoc_PStg_SaveCompleted( + LPPERSISTSTORAGE lpThis, + LPSTORAGE lpStgNew +) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocPersistStorageImpl FAR*)lpThis)->lpServerDoc; + LPOLEDOC lpOleDoc = (LPOLEDOC)lpServerDoc; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; + HRESULT hrErr; + + OLEDBG_BEGIN2("SvrDoc_PStg_SaveCompleted\r\n") + + /* OLE2NOTE: this sample application is a pure server application. + ** a container/server application would have to call SaveCompleted + ** for each of its contained compound document objects. if a new + ** storage was given, then the container/server would have to + ** open the corresponding new sub-storage for each compound + ** document object and pass as an argument in the SaveCompleted + ** call. + */ + + /* OLE2NOTE: it is only legal to perform a Save or SaveAs operation + ** on an embedded object. if the document is a file-based document + ** then we can not be changed to a IStorage-base object. + ** + ** fSameAsLoad lpStgNew Type of Save Send OnSave + ** --------------------------------------------------------- + ** TRUE NULL SAVE YES + ** TRUE ! NULL SAVE * YES + ** FALSE ! NULL SAVE AS YES + ** FALSE NULL SAVE COPY AS NO + ** + ** * this is a strange case that is possible. it is inefficient + ** for the caller; it would be better to pass lpStgNew==NULL for + ** the Save operation. + */ + if ( ((lpServerDoc->m_fSaveWithSameAsLoad && lpStgNew==NULL) || lpStgNew) + && (lpOutlineDoc->m_docInitType != DOCTYPE_EMBEDDED) ) { + OLEDBG_END2 + return ResultFromScode(E_INVALIDARG); + } + + /* OLE2NOTE: inform any linking clients that the document has been + ** saved. in addition, any currently active pseudo objects + ** should also inform their clients. we should only broadcast an + ** OnSave notification if a Save or SaveAs operation was + ** performed. we do NOT want to send the notification if a + ** SaveCopyAs operation was performed. + */ + if (lpStgNew || lpServerDoc->m_fSaveWithSameAsLoad) { + + /* OLE2NOTE: if IPersistStorage::Save has been called, then we + ** need to clear the dirty bit and send OnSave notification. + ** if HandsOffStorage is called directly without first + ** calling Save, then we do NOT want to clear the dirty bit + ** and send OnSave when SaveCompleted is called. + */ + if (lpServerDoc->m_fNoScribbleMode) { + OutlineDoc_SetModified(lpOutlineDoc, FALSE, FALSE, FALSE); + + ServerDoc_SendAdvise ( + lpServerDoc, + OLE_ONSAVE, + NULL, /* lpmkDoc -- not relevant here */ + 0 /* advf -- not relevant here */ + ); + } + lpServerDoc->m_fSaveWithSameAsLoad = FALSE; + } + lpServerDoc->m_fNoScribbleMode = FALSE; + + /* OLE2NOTE: An embedded object must guarantee that it can save + ** even in low memory situations. it must be able to + ** successfully save itself without consuming any additional + ** memory. this means that a server is NOT supposed to open or + ** create any streams or storages when + ** IPersistStorage::Save(fSameAsLoad==TRUE) is called. thus an + ** embedded object should hold onto its storage and pre-open and + ** hold open any streams that it will need later when it is time + ** to save. if this is a SaveAs situtation, then we want to + ** pre-open and hold open our streams to guarantee that a + ** subsequent save will be successful in low-memory. if we fail + ** to open these streams then we want to force ourself to close + ** to make sure the can't make editing changes that can't be + ** later saved. + */ + if ( lpStgNew && !lpServerDoc->m_fSaveWithSameAsLoad ) { + + // release previous streams + if (lpOleDoc->m_lpLLStm) { + OleStdRelease((LPUNKNOWN)lpOleDoc->m_lpLLStm); + lpOleDoc->m_lpLLStm = NULL; + } + if (lpOleDoc->m_lpNTStm) { + OleStdRelease((LPUNKNOWN)lpOleDoc->m_lpNTStm); + lpOleDoc->m_lpNTStm = NULL; + } + if (lpOleDoc->m_lpStg) { + OleStdRelease((LPUNKNOWN)lpOleDoc->m_lpStg); + lpOleDoc->m_lpStg = NULL; + } + + hrErr = CallIStorageOpenStreamA( + lpStgNew, + "LineList", + NULL, + STGM_READWRITE | STGM_SHARE_EXCLUSIVE, + 0, + &lpOleDoc->m_lpLLStm + ); + + if (hrErr != NOERROR) { + OleDbgAssertSz(hrErr==NOERROR,"Could not create LineList stream"); + OleDbgOutHResult("LineList CreateStream returned", hrErr); + goto error; + } + + hrErr = CallIStorageOpenStreamA( + lpStgNew, + "NameTable", + NULL, + STGM_READWRITE | STGM_SHARE_EXCLUSIVE, + 0, + &lpOleDoc->m_lpNTStm + ); + + if (hrErr != NOERROR) { + OleDbgAssertSz(hrErr==NOERROR,"Could not create NameTable stream"); + OleDbgOutHResult("NameTable CreateStream returned", hrErr); + goto error; + } + + lpOleDoc->m_lpStg = lpStgNew; + + // OLE2NOTE: to hold onto IStorage* pointer, we must AddRef it + lpStgNew->lpVtbl->AddRef(lpStgNew); + } + + OLEDBG_END2 + return NOERROR; + +error: + OLEDBG_END2 + return ResultFromScode(E_OUTOFMEMORY); +} + + +// IPersistStorage::HandsOffStorage method + +STDMETHODIMP SvrDoc_PStg_HandsOffStorage(LPPERSISTSTORAGE lpThis) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocPersistStorageImpl FAR*)lpThis)->lpServerDoc; + LPOLEDOC lpOleDoc = (LPOLEDOC)lpServerDoc; + + OLEDBG_BEGIN2("SvrDoc_PStg_HandsOffStorage\r\n") + + /* OLE2NOTE: An embedded object must guarantee that it can save + ** even in low memory situations. it must be able to + ** successfully save itself without consuming any additional + ** memory. this means that a server is NOT supposed to open or + ** create any streams or storages when + ** IPersistStorage::Save(fSameAsLoad==TRUE) is called. thus an + ** embedded object should hold onto its storage and pre-open and + ** hold open any streams that it will need later when it is time + ** to save. Now when HandsOffStorage is called the object must + ** release its storage and any streams that is holds open. + ** later when SaveCompleted is called, it will be given back its + ** storage. + */ + if (lpOleDoc->m_lpLLStm) { + OleStdRelease((LPUNKNOWN)lpOleDoc->m_lpLLStm); + lpOleDoc->m_lpLLStm = NULL; + } + if (lpOleDoc->m_lpNTStm) { + OleStdRelease((LPUNKNOWN)lpOleDoc->m_lpNTStm); + lpOleDoc->m_lpNTStm = NULL; + } + if (lpOleDoc->m_lpStg) { + OleStdRelease((LPUNKNOWN)lpOleDoc->m_lpStg); + lpOleDoc->m_lpStg = NULL; + } + + OLEDBG_END2 + return NOERROR; +} + + + +#if defined( SVR_TREATAS ) + +/************************************************************************* +** ServerDoc::IStdMarshalInfo interface implementation +*************************************************************************/ + +// IStdMarshalInfo::QueryInterface method + +STDMETHODIMP SvrDoc_StdMshl_QueryInterface( + LPSTDMARSHALINFO lpThis, + REFIID riid, + LPVOID FAR* lplpvObj +) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocStdMarshalInfoImpl FAR*)lpThis)->lpServerDoc; + + return OleDoc_QueryInterface((LPOLEDOC)lpServerDoc, riid, lplpvObj); +} + + +// IStdMarshalInfo::AddRef method + +STDMETHODIMP_(ULONG) SvrDoc_StdMshl_AddRef(LPSTDMARSHALINFO lpThis) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocStdMarshalInfoImpl FAR*)lpThis)->lpServerDoc; + + OleDbgAddRefMethod(lpThis, "IStdMarshalInfo"); + + return OleDoc_AddRef((LPOLEDOC)lpServerDoc); +} + + +// IStdMarshalInfo::Release method + +STDMETHODIMP_(ULONG) SvrDoc_StdMshl_Release(LPSTDMARSHALINFO lpThis) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocStdMarshalInfoImpl FAR*)lpThis)->lpServerDoc; + + OleDbgReleaseMethod(lpThis, "IStdMarshalInfo"); + + return OleDoc_Release((LPOLEDOC)lpServerDoc); +} + + +// IStdMarshalInfo::GetClassForHandler + +STDMETHODIMP SvrDoc_StdMshl_GetClassForHandler( + LPSTDMARSHALINFO lpThis, + DWORD dwDestContext, + LPVOID pvDestContext, + LPCLSID lpClassID +) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocStdMarshalInfoImpl FAR*)lpThis)->lpServerDoc; + OleDbgOut2("SvrDoc_StdMshl_GetClassForHandler\r\n"); + + // OLE2NOTE: we only handle LOCAL marshal context. + if (dwDestContext != MSHCTX_LOCAL || pvDestContext != NULL) + return ResultFromScode(E_INVALIDARG); + + /* OLE2NOTE: we must return our REAL clsid, NOT the clsid that we + ** are pretending to be if a "TreatAs" is in effect. + */ + *lpClassID = CLSID_APP; + return NOERROR; +} +#endif // SVR_TREATAS + + + +/************************************************************************* +** ServerDoc Support Functions +*************************************************************************/ + + +/* ServerDoc_Init + * -------------- + * + * Initialize the fields of a new ServerDoc object. The object is initially + * not associated with a file or an (Untitled) document. This function sets + * the docInitType to DOCTYPE_UNKNOWN. After calling this function the + * caller should call: + * 1.) OutlineDoc_InitNewFile to set the ServerDoc to (Untitled) + * 2.) OutlineDoc_LoadFromFile to associate the ServerDoc with a file. + * This function creates a new window for the document. + * + * NOTE: the window is initially created with a NIL size. it must be + * sized and positioned by the caller. also the document is initially + * created invisible. the caller must call OutlineDoc_ShowWindow + * after sizing it to make the document window visible. + */ +BOOL ServerDoc_Init(LPSERVERDOC lpServerDoc, BOOL fDataTransferDoc) +{ + lpServerDoc->m_cPseudoObj = 0; + lpServerDoc->m_lpOleClientSite = NULL; + lpServerDoc->m_lpOleAdviseHldr = NULL; + lpServerDoc->m_lpDataAdviseHldr = NULL; + + // initialy doc does not have any storage + lpServerDoc->m_fNoScribbleMode = FALSE; + lpServerDoc->m_fSaveWithSameAsLoad = FALSE; + lpServerDoc->m_szContainerApp[0] = '\0'; + lpServerDoc->m_szContainerObj[0] = '\0'; + lpServerDoc->m_nNextRangeNo = 0L; + lpServerDoc->m_lrSrcSelOfCopy.m_nStartLine = -1; + lpServerDoc->m_lrSrcSelOfCopy.m_nEndLine = -1; + lpServerDoc->m_fDataChanged = FALSE; + lpServerDoc->m_fSizeChanged = FALSE; + lpServerDoc->m_fSendDataOnStop = FALSE; + +#if defined( SVR_TREATAS ) + lpServerDoc->m_clsidTreatAs = CLSID_NULL; + lpServerDoc->m_lpszTreatAsType = NULL; +#endif // SVR_TREATAS + +#if defined( INPLACE_SVR ) + lpServerDoc->m_hWndHatch = + CreateHatchWindow( + OutlineApp_GetWindow(g_lpApp), + OutlineApp_GetInstance(g_lpApp) + ); + if (!lpServerDoc->m_hWndHatch) + return FALSE; + + lpServerDoc->m_fInPlaceActive = FALSE; + lpServerDoc->m_fInPlaceVisible = FALSE; + lpServerDoc->m_fUIActive = FALSE; + lpServerDoc->m_lpIPData = NULL; + lpServerDoc->m_fMenuHelpMode = FALSE; // F1 pressed in menu + + INIT_INTERFACEIMPL( + &lpServerDoc->m_OleInPlaceObject, + &g_SvrDoc_OleInPlaceObjectVtbl, + lpServerDoc + ); + INIT_INTERFACEIMPL( + &lpServerDoc->m_OleInPlaceActiveObject, + &g_SvrDoc_OleInPlaceActiveObjectVtbl, + lpServerDoc + ); +#endif // INPLACE_SVR + + INIT_INTERFACEIMPL( + &lpServerDoc->m_OleObject, + &g_SvrDoc_OleObjectVtbl, + lpServerDoc + ); + + INIT_INTERFACEIMPL( + &lpServerDoc->m_PersistStorage, + &g_SvrDoc_PersistStorageVtbl, + lpServerDoc + ); + +#if defined( SVR_TREATAS ) + + INIT_INTERFACEIMPL( + &lpServerDoc->m_StdMarshalInfo, + &g_SvrDoc_StdMarshalInfoVtbl, + lpServerDoc + ); +#endif // SVR_TREATAS + return TRUE; +} + + +/* ServerDoc_InitNewEmbed + * ---------------------- + * + * Initialize the ServerDoc object to be a new embedded object document. + * This function sets the docInitType to DOCTYPE_EMBED. + */ +BOOL ServerDoc_InitNewEmbed(LPSERVERDOC lpServerDoc) +{ + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; + + OleDbgAssert(lpOutlineDoc->m_docInitType == DOCTYPE_UNKNOWN); + + lpOutlineDoc->m_docInitType = DOCTYPE_EMBEDDED; + + /* The Window title for an embedded object is constructed as + ** follows: + ** - in + ** + ** here we construct the current document title portion of the + ** name which follows the '-'. OutlineDoc_SetTitle prepends the + ** " - " to the document title. + */ + // REVIEW: this string should be loaded from string resource + wsprintf(lpOutlineDoc->m_szFileName, "%s in %s", + (LPSTR)SHORTUSERTYPENAME, + (LPSTR)DEFCONTAINERNAME); + lpOutlineDoc->m_lpszDocTitle = lpOutlineDoc->m_szFileName; + + + /* OLE2NOTE: an embedding should be marked as initially dirty so + ** that on close we always call IOleClientSite::SaveObject. + */ + OutlineDoc_SetModified(lpOutlineDoc, TRUE, FALSE, FALSE); + + OutlineDoc_SetTitle(lpOutlineDoc, FALSE /*fMakeUpperCase*/); + + return TRUE; +} + + +/* ServerDoc_SendAdvise + * -------------------- + * + * This function sends an advise notification on behalf of a specific + * doc object to all its clients. + */ +void ServerDoc_SendAdvise( + LPSERVERDOC lpServerDoc, + WORD wAdvise, + LPMONIKER lpmkDoc, + DWORD dwAdvf +) +{ + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; + LPOLEDOC lpOleDoc = (LPOLEDOC)lpServerDoc; + + switch (wAdvise) { + + case OLE_ONDATACHANGE: + + // inform clients that the data of the object has changed + + if (lpOutlineDoc->m_nDisableDraw == 0) { + /* drawing is currently enabled. inform clients that + ** the data of the object has changed + */ + + lpServerDoc->m_fDataChanged = FALSE; + + /* OLE2NOTE: we must note the time of last change + ** for our object in the RunningObjectTable. + ** this is used as the basis to answer + ** IOleObject::IsUpToDate. we only want to note + ** the change time when an actual change takes + ** place. we do NOT want to set it when we are + ** notifying clients of ADVF_DATAONSTOP + */ + if (dwAdvf == 0) + OleStdNoteObjectChangeTime(lpOleDoc->m_dwRegROT); + + if (lpServerDoc->m_lpDataAdviseHldr) { + OLEDBG_BEGIN2("IDataAdviseHolder::SendOnDataChange called\r\n"); + lpServerDoc->m_lpDataAdviseHldr->lpVtbl->SendOnDataChange( + lpServerDoc->m_lpDataAdviseHldr, + (LPDATAOBJECT)&lpOleDoc->m_DataObject, + 0, + dwAdvf + ); + OLEDBG_END2 + + } + +#if defined( INPLACE_SVR ) + /* OLE2NOTE: if the ServerDoc is currently in-place UI active, + ** then is it important to renegotiate the size for the + ** in-place document window BEFORE sending OnDataChange + ** (which will cause the window to repaint). + */ + if (lpServerDoc->m_fSizeChanged) { + lpServerDoc->m_fSizeChanged = FALSE; + if (lpServerDoc->m_fInPlaceActive) + ServerDoc_UpdateInPlaceWindowOnExtentChange(lpServerDoc); + } +#endif + + /* OLE2NOTE: we do NOT need to tell our pseudo objects to + ** broadcast OnDataChange notification because + ** they will do it automatically when an editing + ** change in the document affects a PseudoObj. + ** (see OutlineNameTable_AddLineUpdate, + ** OutlineNameTable_DeleteLineUpdate, + ** and ServerNameTable_EditLineUpdate) + */ + + } else { + /* drawing is currently disabled. do not send + ** notifications or call + ** IOleInPlaceObject::OnPosRectChange until drawing + ** is re-enabled. + */ + } + break; + + case OLE_ONCLOSE: + + // inform clients that the document is shutting down + + if (lpServerDoc->m_lpOleAdviseHldr) { + OLEDBG_BEGIN2("IOleAdviseHolder::SendOnClose called\r\n"); + lpServerDoc->m_lpOleAdviseHldr->lpVtbl->SendOnClose( + lpServerDoc->m_lpOleAdviseHldr + ); + OLEDBG_END2 + } + + /* OLE2NOTE: we do NOT need to tell our pseudo objects to + ** broadcast OnClose notification because they will do + ** it automatically when the pseudo object is closed. + ** (see PseudoObj_Close) + */ + + break; + + case OLE_ONSAVE: + + // inform clients that the object has been saved + + OLEDBG_BEGIN3("ServerDoc_SendAdvise ONSAVE\r\n"); + + if (lpServerDoc->m_lpOleAdviseHldr) { + OLEDBG_BEGIN2("IOleAdviseHolder::SendOnSave called\r\n"); + lpServerDoc->m_lpOleAdviseHldr->lpVtbl->SendOnSave( + lpServerDoc->m_lpOleAdviseHldr + ); + OLEDBG_END2 + } + + /* OLE2NOTE: inform any clients of pseudo objects + ** within our document, that our document has been + ** saved. + */ + ServerNameTable_InformAllPseudoObjectsDocSaved( + (LPSERVERNAMETABLE)lpOutlineDoc->m_lpNameTable, + lpmkDoc + ); + OLEDBG_END3 + break; + + case OLE_ONRENAME: + + // inform clients that the object's name has changed + + OLEDBG_BEGIN3("ServerDoc_SendAdvise ONRENAME\r\n"); + + if (lpmkDoc && lpServerDoc->m_lpOleAdviseHldr) { + OLEDBG_BEGIN2("IOleAdviseHolder::SendOnRename called\r\n"); + lpServerDoc->m_lpOleAdviseHldr->lpVtbl->SendOnRename( + lpServerDoc->m_lpOleAdviseHldr, + lpmkDoc + ); + OLEDBG_END2 + } + + OLEDBG_END3 + break; + } +} + + +/* ServerDoc_GetClassID +** -------------------- +** Return the class ID corresponding to the bits in the storage. +** normally this will be our application's given CLSID. but if a +** "TreateAs (aka. ActivateAs)" operation is taking place, then our +** application needs to pretend to be the class of the object that +** we are emulating. this is also the class that will be written +** into the storage. +*/ +HRESULT ServerDoc_GetClassID(LPSERVERDOC lpServerDoc, LPCLSID lpclsid) +{ +#if defined( SVR_TREATAS ) + if (! IsEqualCLSID(&lpServerDoc->m_clsidTreatAs, &CLSID_NULL)) + *lpclsid = lpServerDoc->m_clsidTreatAs; + else +#endif // SVR_TREATAS + *lpclsid = CLSID_APP; + + return NOERROR; +} + + + +/* ServerDoc_UpdateMenu + * -------------------- + * + * Update menu for embedding mode. the changes include: + * 1 Remove File/New and File/Open (SDI ONLY) + * 2 Change File/Save As.. to File/Save Copy As.. + * 3 Change File menu so it contains "Update" instead of "Save" + * 4 Change File/Exit to File/Exit & Return to " + */ +void ServerDoc_UpdateMenu(LPSERVERDOC lpServerDoc) +{ + char str[256]; + HWND hWndMain; + HMENU hMenu; + OleDbgOut2("ServerDoc_UpdateMenu\r\n"); + + hWndMain=g_lpApp->m_hWndApp; + hMenu=GetMenu(hWndMain); + +#if defined( SDI_VERSION ) + /* SDI ONLY: Remove File/New and File/Open */ + DeleteMenu(hMenu, IDM_F_NEW, MF_BYCOMMAND); + DeleteMenu(hMenu, IDM_F_OPEN, MF_BYCOMMAND); +#endif + + // Change File.Save As.. to File.Save Copy As.. */ + ModifyMenu(hMenu,IDM_F_SAVEAS, MF_STRING, IDM_F_SAVEAS, "Save Copy As.."); + + // Change File.Save to "&Update " + wsprintf(str, g_szUpdateCntrDoc, lpServerDoc->m_szContainerObj); + ModifyMenu(hMenu, IDM_F_SAVE, MF_STRING, IDM_F_SAVE, str); + + // Change File/Exit to File/Exit & Return to " */ + wsprintf(str, g_szExitNReturnToCntrDoc, lpServerDoc->m_szContainerObj); + ModifyMenu(hMenu, IDM_F_EXIT, MF_STRING, IDM_F_EXIT, str); + + DrawMenuBar(hWndMain); +} + +#if defined( MDI_VERSION ) + +// NOTE: ServerDoc_RestoreMenu is actually redundant because the +// app is dying when the function is called. (In SDI, the +// app will terminate when the ref counter of the server doc +// is zero). However, it is important for MDI. + +/* ServerDoc_RestoreMenu + * --------------------- + * + * Reset the menu to non-embedding mode + */ +void ServerDoc_RestoreMenu(LPSERVERDOC lpServerDoc) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + HWND hWndMain; + HMENU hMenu; + OleDbgOut2("ServerDoc_RestoreMenu\r\n"); + + hWndMain = lpOutlineApp->m_hWndApp; + hMenu = GetMenu(hWndMain); + + /* Add back File/New, File/Open.. and File/Save */ + InsertMenu(hMenu, IDM_F_SAVEAS, MF_BYCOMMAND | MF_ENABLED | MF_STRING, + IDM_F_NEW, "&New"); + InsertMenu(hMenu, IDM_F_SAVEAS, MF_BYCOMMAND | MF_ENABLED | MF_STRING, + IDM_F_OPEN, "&Open..."); + + /* Change File menu so it contains "Save As..." instead of */ + /* "Save Copy As..." */ + ModifyMenu(hMenu, IDM_F_SAVEAS, MF_STRING, IDM_F_SAVEAS, "Save &As.."); + + /* Change File menu so it contains "Save" instead of "Update" */ + ModifyMenu(hMenu, IDM_F_SAVE, MF_STRING, IDM_F_SAVE, "&Save"); + + /* Change File menu so it contains "Exit" */ + /* instead of just "Exit & Return to " */ + ModifyMenu(hMenu, IDM_F_EXIT, MF_STRING, IDM_F_EXIT, "E&xit"); + + DrawMenuBar (hWndMain); +} + +#endif // MDI_VERSION diff --git a/private/oleutest/letest/outline/svrinpl.c b/private/oleutest/letest/outline/svrinpl.c new file mode 100644 index 000000000..fe4219d72 --- /dev/null +++ b/private/oleutest/letest/outline/svrinpl.c @@ -0,0 +1,1451 @@ +/************************************************************************* +** +** OLE 2 Server Sample Code +** +** svrinpl.c +** +** This file contains all interfaces, methods and related support +** functions for an In-Place Object (Server) application (aka. Visual +** Editing). The in-place Object application includes the following +** implementation objects: +** +** ServerDoc Object +** exposed interfaces: +** IOleInPlaceObject +** IOleInPlaceActiveObject +** +** ServerApp Object +** exposed interfaces: +** IUnknown +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + + +#include "outline.h" + +OLEDBGDATA + +extern LPOUTLINEAPP g_lpApp; + + +/* OLE2NOTE: the object should compose a string that is used by +** in-place containers to be used for the window titles. this string +** is passed to the container application via +** IOleInPlaceUIWindow::SetActiveObject. the string should have the +** following form: +** - +** SDI containers can use the string directly to display in the +** frame window title. the container would concatenate the string +** " in ". +** an MDI container with the MDI child window maximized can do the +** same as the SDI container. an MDI container with the MDI child +** windows NOT maximized can look for the " - " in the string from +** the object. the first part of the string (app name) would be put +** as the frame window title; the second part would be composed with +** " in " and used as the MDI child window +** title. +*/ + +// REVIEW: should use string resource for messages +char g_szIPObjectTitle[] = APPNAME " - " SHORTUSERTYPENAME; + +extern RECT g_rectNull; + + + +/************************************************************************* +** ServerDoc::IOleInPlaceObject interface implementation +*************************************************************************/ + +// IOleInPlaceObject::QueryInterface method + +STDMETHODIMP SvrDoc_IPObj_QueryInterface( + LPOLEINPLACEOBJECT lpThis, + REFIID riid, + LPVOID FAR * lplpvObj +) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; + + return OleDoc_QueryInterface((LPOLEDOC)lpServerDoc, riid, lplpvObj); +} + + +// IOleInPlaceObject::AddRef method + +STDMETHODIMP_(ULONG) SvrDoc_IPObj_AddRef(LPOLEINPLACEOBJECT lpThis) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; + + OleDbgAddRefMethod(lpThis, "IOleInPlaceObject"); + + return OleDoc_AddRef((LPOLEDOC)lpServerDoc); +} + + +// IOleInPlaceObject::Release method + +STDMETHODIMP_(ULONG) SvrDoc_IPObj_Release(LPOLEINPLACEOBJECT lpThis) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; + + OleDbgReleaseMethod(lpThis, "IOleInPlaceObject"); + + return OleDoc_Release((LPOLEDOC)lpServerDoc); +} + + +// IOleInPlaceObject::GetWindow method + +STDMETHODIMP SvrDoc_IPObj_GetWindow( + LPOLEINPLACEOBJECT lpThis, + HWND FAR* lphwnd +) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; + + OLEDBG_BEGIN2("SvrDoc_IPObj_GetWindow\r\n") + + *lphwnd = ((LPOUTLINEDOC)lpServerDoc)->m_hWndDoc; + + OLEDBG_END2 + return S_OK; +} + + +// IOleInPlaceObject::ContextSensitiveHelp method + +STDMETHODIMP SvrDoc_IPObj_ContextSensitiveHelp( + LPOLEINPLACEOBJECT lpThis, + BOOL fEnable +) +{ + LPOLEDOC lpOleDoc = + (LPOLEDOC)((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; + OleDbgOut2("SvrDoc_IPObj_ContextSensitiveHelp\r\n"); + + /* OLE2NOTE: see context sensitive help technote (CSHELP.DOC). + ** This method is called when SHIFT-F1 context sensitive help is + ** entered. the cursor should then change to a question mark + ** cursor and the app should enter a modal state where the next + ** mouse click does not perform its normal action but rather + ** gives help corresponding to the location clicked. if the app + ** does not implement a help system, it should at least eat the + ** click and do nothing. + */ + lpOleDoc->m_fCSHelpMode = fEnable; + + return S_OK; +} + + +// IOleInPlaceObject::InPlaceDeactivate method + +STDMETHODIMP SvrDoc_IPObj_InPlaceDeactivate(LPOLEINPLACEOBJECT lpThis) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; + HRESULT hrErr; + + OLEDBG_BEGIN2("SvrDoc_IPObj_InPlaceDeactivate\r\n") + + hrErr = ServerDoc_DoInPlaceDeactivate(lpServerDoc); + + OLEDBG_END2 + return hrErr; +} + + +// IOleInPlaceObject::UIDeactivate method + +STDMETHODIMP SvrDoc_IPObj_UIDeactivate(LPOLEINPLACEOBJECT lpThis) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; + LPSERVERAPP lpServerApp = (LPSERVERAPP)g_lpApp; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; + LPINPLACEDATA lpIPData = lpServerDoc->m_lpIPData; + LPLINELIST lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpServerDoc)->m_LineList; + HWND hWndApp = OutlineApp_GetWindow(g_lpApp); + + OLEDBG_BEGIN2("SvrDoc_IPObj_UIDeactivate\r\n"); + + if (!lpServerDoc->m_fUIActive) { + OLEDBG_END2 + return NOERROR; + } + + lpServerDoc->m_fUIActive = FALSE; + + // Clip the hatch window to the size of pos rect so, that the object + // adornments and hatch border will not be visible. + ServerDoc_ResizeInPlaceWindow(lpServerDoc, + (LPRECT)&(lpServerDoc->m_lpIPData->rcPosRect), + (LPRECT)&(lpServerDoc->m_lpIPData->rcPosRect) + ); + + if (lpIPData->lpDoc) + lpIPData->lpDoc->lpVtbl->SetActiveObject(lpIPData->lpDoc, NULL, NULL); + + if (lpIPData->lpFrame) { + lpIPData->lpFrame->lpVtbl->SetActiveObject( + lpIPData->lpFrame, + NULL, + NULL + ); + } + +#if defined( USE_FRAMETOOLS ) + /* OLE2NOTE: we must hide our frame tools here but NOT call + ** IOleInPlaceFrame::SetBorderSpace(NULL) or SetMenu(NULL). + ** we must hide our tools BEFORE calling + ** IOleInPlaceSite::OnUIDeactivate. the container will put + ** his menus and tools back when OnUIDeactivate is called. + */ + ServerDoc_RemoveFrameLevelTools(lpServerDoc); +#endif + + OLEDBG_BEGIN2("IOleInPlaceSite::OnUIDeactivate called\r\n"); + lpIPData->lpSite->lpVtbl->OnUIDeactivate(lpIPData->lpSite, FALSE); + OLEDBG_END2 + + /* Reset to use our normal app's accelerator table */ + g_lpApp->m_hAccelApp = lpServerApp->m_hAccelBaseApp; + g_lpApp->m_hAccel = lpServerApp->m_hAccelBaseApp; + g_lpApp->m_hWndAccelTarget = hWndApp; + + OLEDBG_END2 + +#if !defined( SVR_INSIDEOUT ) + /* OLE2NOTE: an "outside-in" style in-place server would hide its + ** window here. an "inside-out" style server leaves its window + ** visible when it is UIDeactivated. it would only hide its + ** window when InPlaceDeactivated. this app is an "inside-out" + ** style server. it is recommended for most server to support + ** inside-out behavior if possible. + */ + ServerDoc_DoInPlaceHide(lpServerDoc); +#endif // INSIEDOUT + + return NOERROR; +} + + +// IOleInPlaceObject::SetObjectRects method + +STDMETHODIMP SvrDoc_IPObj_SetObjectRects( + LPOLEINPLACEOBJECT lpThis, + LPCRECT lprcPosRect, + LPCRECT lprcClipRect +) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; + LPINPLACEDATA lpIPData = lpServerDoc->m_lpIPData; + LPLINELIST lpLL = OutlineDoc_GetLineList((LPOUTLINEDOC)lpServerDoc); + OLEDBG_BEGIN2("SvrDoc_IPObj_SetObjectRects\r\n") + +#if defined( _DEBUG ) + OleDbgOutRect3("SvrDoc_IPObj_SetObjectRects (PosRect)", + (LPRECT)lprcPosRect); + OleDbgOutRect3("SvrDoc_IPObj_SetObjectRects (ClipRect)", + (LPRECT)lprcClipRect); +#endif + // save the current PosRect and ClipRect + lpIPData->rcPosRect = *lprcPosRect; + lpIPData->rcClipRect = *lprcClipRect; + + if (! lpServerDoc->m_fUIActive) // hatch and adornaments must not be drawn + lprcClipRect = lprcPosRect; + + ServerDoc_ResizeInPlaceWindow( + lpServerDoc, (LPRECT)lprcPosRect, (LPRECT)lprcClipRect); + + OLEDBG_END2 + return NOERROR; +} + + +// IOleInPlaceObject::ReactivateAndUndo method + +STDMETHODIMP SvrDoc_IPObj_ReactivateAndUndo(LPOLEINPLACEOBJECT lpThis) +{ + OLEDBG_BEGIN2("SvrDoc_IPObj_ReactivateAndUndo\r\n") + + // We do not support support UNDO. + + /* REVIEW: for debugging purposes it would be useful to give a + ** message box indicating that this method has been called. + */ + + OLEDBG_END2 + return NOERROR; +} + + +/************************************************************************* +** ServerDoc::IOleInPlaceActiveObject interface implementation +*************************************************************************/ + +// IOleInPlaceActiveObject::QueryInterface method + +STDMETHODIMP SvrDoc_IPActiveObj_QueryInterface( + LPOLEINPLACEACTIVEOBJECT lpThis, + REFIID riid, + LPVOID FAR * lplpvObj +) +{ + SCODE sc = E_NOINTERFACE; + LPSERVERDOC lpServerDoc = + ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; + + /* The container should not be able to access the other interfaces + ** of our object by doing QI on this interface. + */ + + *lplpvObj = NULL; + if (IsEqualIID(riid, &IID_IUnknown) || + IsEqualIID(riid, &IID_IOleWindow) || + IsEqualIID(riid, &IID_IOleInPlaceActiveObject)) { + OleDbgOut4("OleDoc_QueryInterface: IOleInPlaceActiveObject* RETURNED\r\n"); + + *lplpvObj = lpThis; + OleDoc_AddRef((LPOLEDOC)lpServerDoc); + sc = NOERROR; + } + + OleDbgQueryInterfaceMethod(*lplpvObj); + + return ResultFromScode(sc); +} + + +// IOleInPlaceActiveObject::AddRef method + +STDMETHODIMP_(ULONG) SvrDoc_IPActiveObj_AddRef( + LPOLEINPLACEACTIVEOBJECT lpThis +) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; + + OleDbgAddRefMethod(lpThis, "IOleInPlaceActiveObject"); + + return OleDoc_AddRef((LPOLEDOC)lpServerDoc); +} + + +// IOleInPlaceActiveObject::Release method + +STDMETHODIMP_(ULONG) SvrDoc_IPActiveObj_Release( + LPOLEINPLACEACTIVEOBJECT lpThis +) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; + + OleDbgReleaseMethod(lpThis, "IOleInPlaceActiveObject"); + + return OleDoc_Release((LPOLEDOC)lpServerDoc); +} + + +// IOleInPlaceActiveObject::GetWindow method + +STDMETHODIMP SvrDoc_IPActiveObj_GetWindow( + LPOLEINPLACEACTIVEOBJECT lpThis, + HWND FAR* lphwnd +) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; + + OLEDBG_BEGIN2("SvrDoc_IPActiveObj_GetWindow\r\n") + + *lphwnd = ((LPOUTLINEDOC)lpServerDoc)->m_hWndDoc; + + OLEDBG_END2 + return NOERROR; +} + + +// IOleInPlaceActiveObject::ContextSensitiveHelp method + +STDMETHODIMP SvrDoc_IPActiveObj_ContextSensitiveHelp( + LPOLEINPLACEACTIVEOBJECT lpThis, + BOOL fEnterMode +) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; + OleDbgOut2("SvrDoc_IPActiveObj_ContextSensitiveHelp\r\n"); + + /* OLE2NOTE: see context sensitive help technote (CSHELP.DOC) + ** This method is called when F1 is pressed when a menu item is + ** selected. this tells the in-place server application to give + ** help rather than execute the next menu command. at a minimum, + ** even if the in-place server application does not implement a + ** help system, it should NOT execute the next command when + ** fEnable==TRUE. We set the active object's m_fMenuMode flag here. + ** later, in WM_COMMAND processing in the DocWndProc, if this + ** flag is set then the command is NOT executed (and help could + ** be given if we had a help system....but we don't.) + */ + lpServerDoc->m_fMenuHelpMode = fEnterMode; + +#if !defined( HACK ) + ((LPOLEDOC)lpServerDoc)->m_fCSHelpMode = fEnterMode; +#endif + return NOERROR; +} + + +// IOleInPlaceActiveObject::TranslateAccelerator method + +STDMETHODIMP SvrDoc_IPActiveObj_TranslateAccelerator( + LPOLEINPLACEACTIVEOBJECT lpThis, + LPMSG lpmsg +) +{ + // This will never be called because this server is implemented as an EXE + return NOERROR; +} + + +// IOleInPlaceActiveObject::OnFrameWindowActivate method + +STDMETHODIMP SvrDoc_IPActiveObj_OnFrameWindowActivate( + LPOLEINPLACEACTIVEOBJECT lpThis, + BOOL fActivate +) +{ + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC) + ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; + HWND hWndDoc = OutlineDoc_GetWindow(lpOutlineDoc); +#if defined( _DEBUG ) + if (fActivate) + OleDbgOut2("SvrDoc_IPActiveObj_OnFrameWindowActivate(TRUE)\r\n"); + else + OleDbgOut2("SvrDoc_IPActiveObj_OnFrameWindowActivate(FALSE)\r\n"); +#endif // _DEBUG + + /* OLE2NOTE: this is a notification of the container application's + ** WM_ACTIVATEAPP status. some applications may find this + ** important. we need to update the enable/disable status of our + ** tool bar buttons. + */ + + // OLE2NOTE: We can't call OutlineDoc_UpdateFrameToolButtons + // right away which + // would generate some OLE calls and eventually + // WM_ACTIVATEAPP and a loop was formed. Therefore, we + // should delay the frame tool initialization until + // WM_ACTIVATEAPP is finished by posting a message + // to ourselves. + + /* Update enable/disable state of buttons in toolbar */ + if (fActivate) + PostMessage(hWndDoc, WM_U_INITFRAMETOOLS, 0, 0L); + + return NOERROR; +} + + +// IOleInPlaceActiveObject::OnDocWindowActivate method + +STDMETHODIMP SvrDoc_IPActiveObj_OnDocWindowActivate( + LPOLEINPLACEACTIVEOBJECT lpThis, + BOOL fActivate +) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; + LPINPLACEDATA lpIPData = lpServerDoc->m_lpIPData; +#if defined( _DEBUG ) + if (fActivate) + OleDbgOut2("SvrDoc_IPActiveObj_OnDocWindowActivate(TRUE)\r\n"); + else + OleDbgOut2("SvrDoc_IPActiveObj_OnDocWindowActivate(FALSE)\r\n"); +#endif + + if (fActivate) { + ServerDoc_AddFrameLevelUI(lpServerDoc); + } + else { +#if defined( USE_FRAMETOOLS ) + /* OLE2NOTE: we must NOT call IOleInPlaceFrame::SetBorderSpace(NULL) + ** or SetMenu(NULL) here. we should simply hide our tools. + */ + ServerDoc_RemoveFrameLevelTools(lpServerDoc); +#endif + } + + OLEDBG_END2 + return NOERROR; +} + + +// IOleInPlaceActiveObject::ResizeBorder method + +STDMETHODIMP SvrDoc_IPActiveObj_ResizeBorder( + LPOLEINPLACEACTIVEOBJECT lpThis, + LPCRECT lprectBorder, + LPOLEINPLACEUIWINDOW lpIPUiWnd, + BOOL fFrameWindow +) +{ + LPSERVERDOC lpServerDoc = + ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; + + OLEDBG_BEGIN2("SvrDoc_IPActiveObj_ResizeBorder\r\n") + + +#if defined( USE_FRAMETOOLS ) + + if (fFrameWindow) { + FrameTools_NegotiateForSpaceAndShow( + lpOutlineDoc->m_lpFrameTools, + (LPRECT)lprectBorder, + (LPOLEINPLACEFRAME)lpIPUiWnd + ); + } + +#endif + + OLEDBG_END2 + return NOERROR; +} + + +// IOleInPlaceActiveObject::EnableModeless method + +STDMETHODIMP SvrDoc_IPActiveObj_EnableModeless( + LPOLEINPLACEACTIVEOBJECT lpThis, + BOOL fEnable +) +{ +#if defined( USE_FRAMETOOLS ) + LPSERVERDOC lpServerDoc = + ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; + LPFRAMETOOLS lptb; + + /* OLE2NOTE: we must enable/disable mouse and keyboard input to our + ** floating tool palette + */ + if (lpOutlineDoc) { + lptb = lpOutlineDoc->m_lpFrameTools; + if (lptb) + FrameTools_EnableWindow(lptb, fEnable); + } +#endif // USE_FRAMETOOLS + +#if defined( _DEBUG ) + if (fEnable) + OleDbgOut2("SvrDoc_IPActiveObj_EnableModeless(TRUE)\r\n"); + else + OleDbgOut2("SvrDoc_IPActiveObj_EnableModeless(FALSE)\r\n"); +#endif // _DEBUG + + /* OLE2NOTE: this method is called when the top-level, in-place + ** container puts up a modal dialog. it tells the UIActive + ** object to disable it modeless dialogs for the duration that + ** the container is displaying a modal dialog. + ** + ** ISVROTL does not use any modeless dialogs, thus we can + ** ignore this method. + */ + return NOERROR; +} + + +/************************************************************************* +** Support Functions +*************************************************************************/ + + +HRESULT ServerDoc_DoInPlaceActivate( + LPSERVERDOC lpServerDoc, + LONG lVerb, + LPMSG lpmsg, + LPOLECLIENTSITE lpActiveSite +) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + LPSERVERAPP lpServerApp = (LPSERVERAPP)g_lpApp; + LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; + SCODE sc = E_FAIL; + RECT rcPos; + RECT rcClip; + LPINPLACEDATA lpIPData = lpServerDoc->m_lpIPData; + LPOUTLINEDOC lpOutlineDoc=(LPOUTLINEDOC)lpServerDoc; + HWND hWndDoc = lpOutlineDoc->m_hWndDoc; + HWND hWndHatch = lpServerDoc->m_hWndHatch; + HRESULT hrErr; + LPLINELIST lpLL=(LPLINELIST)&lpOutlineDoc->m_LineList; + LPOLEINPLACESITE lpIPSite = NULL; + + /* OLE2NOTE: lpActiveSite should be used only for InPlace PLAYing. + ** This app does not do inplace PLAYing, so it never uses + ** lpActiveSite. + */ + + /* InPlace activation can only be done if the ClientSite is non-NULL. */ + if (! lpServerDoc->m_lpOleClientSite) + return NOERROR; + + if (! lpServerDoc->m_fInPlaceActive) { + + // if the object is in open mode then we do not want to do inplace + // activation. + if (IsWindowVisible(lpOutlineDoc->m_hWndDoc)) + return NOERROR; + + lpIPSite = (LPOLEINPLACESITE)OleStdQueryInterface( + (LPUNKNOWN)lpServerDoc->m_lpOleClientSite, + &IID_IOleInPlaceSite + ); + + if (! lpIPSite) + goto errActivate; + + OLEDBG_BEGIN2("IOleInPlaceSite::CanInPlaceActivate called\r\n"); + hrErr = lpIPSite->lpVtbl->CanInPlaceActivate(lpIPSite); + OLEDBG_END2 + if (hrErr != NOERROR) + goto errActivate; + + lpServerDoc->m_fInPlaceActive = TRUE; + OLEDBG_BEGIN2("IOleInPlaceSite::OnInPlaceActivate called\r\n"); + hrErr = lpIPSite->lpVtbl->OnInPlaceActivate(lpIPSite); + OLEDBG_END2 + if (hrErr != NOERROR) + goto errActivate; + + if (! ServerDoc_AllocInPlaceData(lpServerDoc)) { + sc = E_OUTOFMEMORY; + OLEDBG_BEGIN2("IOleInPlaceSite::OnInPlaceDeactivate called\r\n"); + lpIPSite->lpVtbl->OnInPlaceDeactivate(lpIPSite); + OLEDBG_END2 + goto errActivate; + } + + (lpIPData = lpServerDoc->m_lpIPData)->lpSite = lpIPSite; + goto InPlaceActive; + + errActivate: + lpServerDoc->m_fInPlaceActive = FALSE; + if (lpIPSite) + OleStdRelease((LPUNKNOWN)lpIPSite); + return ResultFromScode(sc); + } + + +InPlaceActive: + + if (! lpServerDoc->m_fInPlaceVisible) { + lpServerDoc->m_fInPlaceVisible = TRUE; + + OLEDBG_BEGIN2("IOleInPlaceSite::GetWindow called\r\n"); + hrErr = lpIPData->lpSite->lpVtbl->GetWindow( + lpIPData->lpSite, &lpServerDoc->m_hWndParent); + OLEDBG_END2 + if (hrErr != NOERROR) { + sc = GetScode(hrErr); + goto errRtn; + } + + if (! lpServerDoc->m_hWndParent) + goto errRtn; + + /* OLE2NOTE: The server should fill in the "cb" field so that the + ** container can tell what size structure the server is + ** expecting. this enables this structure to be easily extended + ** in future releases of OLE. the container should check this + ** field so that it doesn't try to use fields that do not exist + ** since the server may be using an old structure definition. + */ + _fmemset( + (LPOLEINPLACEFRAMEINFO)&lpIPData->frameInfo, + 0, + sizeof(OLEINPLACEFRAMEINFO) + ); + lpIPData->frameInfo.cb = sizeof(OLEINPLACEFRAMEINFO); + + OLEDBG_BEGIN2("IOleInPlaceSite::GetWindowContext called\r\n"); + hrErr = lpIPData->lpSite->lpVtbl->GetWindowContext(lpIPData->lpSite, + (LPOLEINPLACEFRAME FAR*) &lpIPData->lpFrame, + (LPOLEINPLACEUIWINDOW FAR*)&lpIPData->lpDoc, + (LPRECT)&rcPos, + (LPRECT)&rcClip, + (LPOLEINPLACEFRAMEINFO)&lpIPData->frameInfo); + OLEDBG_END2 + + if (hrErr != NOERROR) { + sc = GetScode(hrErr); + goto errRtn; + } + + lpServerApp->m_lpIPData = lpIPData; + ShowWindow(hWndDoc, SW_HIDE); // make sure we are hidden + + /* OLE2NOTE: reparent in-place server document's window to the + ** special in-place hatch border window. set the in-place site's + ** window as the parent of the hatch window. position the + ** in-place and hatch border windows using the PosRect and + ** ClipRect. + ** it is important to properly parent and position the in-place + ** server window BEFORE calling IOleInPlaceFrame::SetMenu and + ** SetBorderSpace. + */ + ShowWindow(lpServerDoc->m_hWndHatch, SW_SHOW); + // make sure App busy/blocked dialogs are parented to our + // new hWndFrame + OleStdMsgFilter_SetParentWindow( + lpOleApp->m_lpMsgFilter,lpIPData->frameInfo.hwndFrame); + SetParent(lpServerDoc->m_hWndHatch, lpServerDoc->m_hWndParent); + SetParent(hWndDoc, lpServerDoc->m_hWndHatch); + +#if defined( _DEBUG ) + OleDbgOutRect3("IOleInPlaceSite::GetWindowContext (PosRect)", + (LPRECT)&rcPos); + OleDbgOutRect3("IOleInPlaceSite::GetWindowContext (ClipRect)", + (LPRECT)&rcClip); +#endif + // save the current PosRect and ClipRect + lpIPData->rcPosRect = rcPos; + lpIPData->rcClipRect = rcClip; + + /* OLE2NOTE: build the shared menu for the in-place container and + ** the server. + */ + if (ServerDoc_AssembleMenus (lpServerDoc) != NOERROR) + goto errRtn; + +#if defined( SVR_INSIDEOUT ) + if (lVerb == OLEIVERB_INPLACEACTIVATE) { + // Clip the hatch window to the size of pos rect so, that + // hatch and object adornments will not be visible. + ServerDoc_ResizeInPlaceWindow(lpServerDoc, + (LPRECT)&(lpServerDoc->m_lpIPData->rcPosRect), + (LPRECT)&(lpServerDoc->m_lpIPData->rcPosRect) + ); + } +#endif // SVR_INSIDEOUT + } + +#if defined( SVR_INSIDEOUT ) + // OLE2NOTE: if verb is OLEIVERB_INPLACEACTIVATE we do NOT want to + // show our UI + if (lVerb == OLEIVERB_INPLACEACTIVATE) { + return NOERROR; + } +#endif // SVR_INSIDEOUT + + if (! lpServerDoc->m_fUIActive) { + lpServerDoc->m_fUIActive = TRUE; + OLEDBG_BEGIN2("IOleInPlaceSite::OnUIActivate called\r\n"); + hrErr = lpIPData->lpSite->lpVtbl->OnUIActivate(lpIPData->lpSite); + OLEDBG_END2 + if (hrErr != NOERROR) { + lpServerDoc->m_fUIActive = FALSE; + goto errRtn; + } + + SetFocus(hWndDoc); + + // Show the object adornments and hacth border around them. + ServerDoc_ResizeInPlaceWindow(lpServerDoc, + (LPRECT)&lpIPData->rcPosRect, + (LPRECT)&lpIPData->rcClipRect + ); + + /* OLE2NOTE: IOleInPlaceFrame::SetActiveObject must be called BEFORE + ** IOleInPlaceFrame::SetMenu. + */ + OLEDBG_BEGIN2("IOleInPlaceSite::SetActiveObject called\r\n"); + CallIOleInPlaceUIWindowSetActiveObjectA( + (struct IOleInPlaceUIWindow *) lpIPData->lpFrame, + (LPOLEINPLACEACTIVEOBJECT) &lpServerDoc->m_OleInPlaceActiveObject, + (LPSTR)g_szIPObjectTitle + ); + OLEDBG_END2 + + /* OLE2NOTE: If the container wants to give ownership of the + ** palette then he would sendmessage WM_QUEYNEWPALETTE to + ** the object window proc, before returning from + ** IOleInPlaceFrame::SetActiveObject. Those objects which + ** want to be edited inplace only if they have the ownership of + ** the palette, can check at this point in the code whether + ** they got WM_QUERYNEWPALETTE or not. If they didn't get + ** the message, then they can inplace deactivate and do open + ** editing instead. + */ + + + + if (lpIPData->lpDoc) { + CallIOleInPlaceUIWindowSetActiveObjectA( + lpIPData->lpDoc, + (LPOLEINPLACEACTIVEOBJECT)&lpServerDoc->m_OleInPlaceActiveObject, + (LPSTR)g_szIPObjectTitle + ); + } + + /* OLE2NOTE: install the menu and frame-level tools on the in-place + ** frame. + */ + ServerDoc_AddFrameLevelUI(lpServerDoc); + } + + return NOERROR; + +errRtn: + ServerDoc_DoInPlaceDeactivate(lpServerDoc); + return ResultFromScode(sc); +} + + + +HRESULT ServerDoc_DoInPlaceDeactivate(LPSERVERDOC lpServerDoc) +{ + LPINPLACEDATA lpIPData = lpServerDoc->m_lpIPData; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; + + if (!lpServerDoc->m_fInPlaceActive) + return S_OK; + + lpServerDoc->m_fInPlaceActive = FALSE; + + SvrDoc_IPObj_UIDeactivate( + (LPOLEINPLACEOBJECT)&lpServerDoc->m_OleInPlaceObject); + + /* OLE2NOTE: an inside-out style in-place server will + ** NOT hide its window in UIDeactive (an outside-in + ** style object will hide its window in UIDeactivate). + ** thus, an inside-out server must explicitly hide + ** its window in InPlaceDeactivate. it is ALSO important for an + ** outside-in style object to call ServerDoc_DoInPlaceHide here + ** BEFORE freeing the InPlaceData structure. it will be common + ** for in-place containers to call IOleInPlaceObject:: + ** InPlaceDeactivate in their IOleInPlaceSite::OnUIDeactiate + ** implementation. + */ + ServerDoc_DoInPlaceHide(lpServerDoc); + + OLEDBG_BEGIN2("IOleInPlaceSite::OnInPlaceDeactivate called\r\n"); + lpIPData->lpSite->lpVtbl->OnInPlaceDeactivate(lpIPData->lpSite); + OLEDBG_END2 + + OleStdRelease((LPUNKNOWN)lpIPData->lpSite); + lpIPData->lpSite = NULL; + + ServerDoc_FreeInPlaceData(lpServerDoc); + + return NOERROR; +} + + +HRESULT ServerDoc_DoInPlaceHide(LPSERVERDOC lpServerDoc) +{ + LPINPLACEDATA lpIPData = lpServerDoc->m_lpIPData; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; + LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; + HWND hWndApp = OutlineApp_GetWindow(g_lpApp); + + if (! lpServerDoc->m_fInPlaceVisible) + return NOERROR; + + // Set the parent back to server app's window + OleDoc_HideWindow((LPOLEDOC)lpServerDoc, FALSE /* fShutdown */); + + /* we need to enusure that our window is set to normal 100% zoom. + ** if the window is next shown in open mode it should start out + ** at normal zoom factor. our window may have been set to a + ** different zoom factor while it was in-place active. + */ + OutlineDoc_SetCurrentZoomCommand(lpOutlineDoc,IDM_V_ZOOM_100); + + lpServerDoc->m_fInPlaceVisible = FALSE; + + lpServerDoc->m_hWndParent = hWndApp; + SetParent( + lpOutlineDoc->m_hWndDoc, + lpServerDoc->m_hWndParent + ); + + // make sure App busy/blocked dialogs are parented to our own hWndApp + OleStdMsgFilter_SetParentWindow(lpOleApp->m_lpMsgFilter, hWndApp); + + // Hide the in-place hatch border window. + ShowWindow(lpServerDoc->m_hWndHatch, SW_HIDE); + + ServerDoc_DisassembleMenus(lpServerDoc); + + /* we no longer need the IOleInPlaceFrame* or the doc's + ** IOleInPlaceWindow* interface pointers. + */ + if (lpIPData->lpDoc) { + OleStdRelease((LPUNKNOWN)lpIPData->lpDoc); + lpIPData->lpDoc = NULL; + } + + if (lpIPData->lpFrame) { + OleStdRelease((LPUNKNOWN)lpIPData->lpFrame); + lpIPData->lpFrame = NULL; + } + + ((LPSERVERAPP)g_lpApp)->m_lpIPData = NULL; + + return NOERROR; +} + + +BOOL ServerDoc_AllocInPlaceData(LPSERVERDOC lpServerDoc) +{ + LPINPLACEDATA lpIPData; + + if (!(lpIPData = (LPINPLACEDATA) New(sizeof(INPLACEDATA)))) + return FALSE; + + lpIPData->lpFrame = NULL; + lpIPData->lpDoc = NULL; + lpIPData->lpSite = NULL; + lpIPData->hOlemenu = NULL; + lpIPData->hMenuShared = NULL; + + lpServerDoc->m_lpIPData = lpIPData; + return TRUE; +} + + +void ServerDoc_FreeInPlaceData(LPSERVERDOC lpServerDoc) +{ + Delete(lpServerDoc->m_lpIPData); + lpServerDoc->m_lpIPData = NULL; +} + + +HRESULT ServerDoc_AssembleMenus(LPSERVERDOC lpServerDoc) +{ + HMENU hMenuShared; + LONG FAR* lpWidths; + UINT uPosition; + UINT uPositionStart; + LPSERVERAPP lpServerApp = (LPSERVERAPP) g_lpApp; + LPINPLACEDATA lpIPData = lpServerDoc->m_lpIPData; + HRESULT hresult; + BOOL fNoError = TRUE; + + lpWidths = lpIPData->menuGroupWidths.width; + hMenuShared = CreateMenu(); + + if (hMenuShared && + (hresult = lpIPData->lpFrame->lpVtbl->InsertMenus( + lpIPData->lpFrame, hMenuShared, + &lpIPData->menuGroupWidths)) == NOERROR) { + + /* Insert EDIT group menus */ + + uPosition = (UINT)lpWidths[0]; /* # of menus in the FILE group */ + uPositionStart = uPosition; + + fNoError &= InsertMenu( + hMenuShared, + (UINT)uPosition, + (UINT)(MF_BYPOSITION | MF_POPUP), + (UINT)lpServerApp->m_hMenuEdit, + (LPCSTR)"&Edit" + ); + uPosition++; + + lpWidths[1] = uPosition - uPositionStart; + + /* Insert OBJECT group menus */ + + uPosition += (UINT)lpWidths[2]; + uPositionStart = uPosition; + + fNoError &= InsertMenu( + hMenuShared, + (UINT)uPosition, + (UINT)(MF_BYPOSITION | MF_POPUP), + (UINT)lpServerApp->m_hMenuLine, + (LPCSTR)"&Line" + ); + uPosition++; + + fNoError &= InsertMenu( + hMenuShared, + (UINT)uPosition, + (UINT)(MF_BYPOSITION | MF_POPUP), + (UINT)lpServerApp->m_hMenuName, + (LPCSTR)"&Name" + ); + uPosition++; + + fNoError &= InsertMenu( + hMenuShared, + (UINT)uPosition, + (UINT)(MF_BYPOSITION | MF_POPUP), + (UINT)lpServerApp->m_hMenuOptions, + (LPCSTR)"&Options" + ); + uPosition++; + + fNoError &= InsertMenu( + hMenuShared, + (UINT)uPosition, + (UINT)(MF_BYPOSITION | MF_POPUP), + (UINT)lpServerApp->m_hMenuDebug, + (LPCSTR)"DbgI&Svr" + ); + uPosition++; + + lpWidths[3] = uPosition - uPositionStart; + + /* Insert HELP group menus */ + + uPosition += (UINT) lpWidths[4]; /* # of menus in WINDOW group */ + uPositionStart = uPosition; + + fNoError &= InsertMenu( + hMenuShared, + (UINT)uPosition, + (UINT)(MF_BYPOSITION | MF_POPUP), + (UINT)lpServerApp->m_hMenuHelp, + (LPCSTR)"&Help" + ); + uPosition++; + + lpWidths[5] = uPosition - uPositionStart; + + OleDbgAssert(fNoError == TRUE); + + } else { + /* In-place container does not allow us to add menus to the + ** frame. + ** OLE2NOTE: even when the in-place container does NOT allow + ** the building of a merged menu bar, it is CRITICAL that + ** the in-place server still call OleCreateMenuDescriptor + ** passing NULL for hMenuShared. + */ + if (hMenuShared) { + DestroyMenu(hMenuShared); + hMenuShared = NULL; + } + } + + lpIPData->hMenuShared = hMenuShared; + + if (!(lpIPData->hOlemenu = OleCreateMenuDescriptor(hMenuShared, + &lpIPData->menuGroupWidths))) + return ResultFromScode(E_OUTOFMEMORY); + + return NOERROR; +} + + +void ServerDoc_DisassembleMenus(LPSERVERDOC lpServerDoc) +{ + UINT uCount; + UINT uGroup; + UINT uDeleteAt; + LPINPLACEDATA lpIPData = lpServerDoc->m_lpIPData; + LONG FAR* lpWidths = lpIPData->menuGroupWidths.width; + BOOL fNoError = TRUE; + + /* OLE2NOTE: even when hMenuShared is NULL (ie. the server has no + ** Menu), there is still an hOleMenu created that must be destroyed. + */ + if (lpIPData->hOlemenu) { + OleDestroyMenuDescriptor (lpIPData->hOlemenu); + lpIPData->hOlemenu = NULL; + } + + if (! lpIPData->hMenuShared) + return; // no menus to be destroyed + + /* Remove server group menus. */ + uDeleteAt = 0; + for (uGroup = 0; uGroup < 6; uGroup++) { + uDeleteAt += (UINT)lpWidths[uGroup++]; + for (uCount = 0; uCount < (UINT)lpWidths[uGroup]; uCount++) + fNoError &= RemoveMenu(lpIPData->hMenuShared, uDeleteAt, + MF_BYPOSITION); + } + + /* Remove container group menus */ + fNoError &= (lpIPData->lpFrame->lpVtbl->RemoveMenus( + lpIPData->lpFrame, + lpIPData->hMenuShared) == NOERROR); + + OleDbgAssert(fNoError == TRUE); + + DestroyMenu(lpIPData->hMenuShared); + lpIPData->hMenuShared = NULL; +} + + +/* ServerDoc_UpdateInPlaceWindowOnExtentChange +** ------------------------------------------- +** The size of the in-place window needs to be changed. +** calculate the size required in Client coordinates (taking into +** account the current scale factor imposed by the in-place +** container) and ask our in-place container to allow us to resize. +** our container must call us back via +** IOleInPlaceObject::SetObjectRects for the actual sizing to take +** place. +** +** OLE2NOTE: the rectangle that we ask for from our in-place +** container is always the rectangle required for the object display +** itself (in our case the size of the LineList contents). it does +** NOT include the space we require for object frame adornments. +*/ +void ServerDoc_UpdateInPlaceWindowOnExtentChange(LPSERVERDOC lpServerDoc) +{ + SIZEL sizelHim; + SIZEL sizelPix; + RECT rcPosRect; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; + LPLINELIST lpLL=(LPLINELIST)&lpOutlineDoc->m_LineList; + HWND hWndLL = lpLL->m_hWndListBox; + LPSCALEFACTOR lpscale = (LPSCALEFACTOR)&lpOutlineDoc->m_scale; + + if (!lpServerDoc->m_fInPlaceActive) + return; + + OleDoc_GetExtent((LPOLEDOC)lpServerDoc, (LPSIZEL)&sizelHim); + + // apply current scale factor + sizelHim.cx = sizelHim.cx * lpscale->dwSxN / lpscale->dwSxD; + sizelHim.cy = sizelHim.cy * lpscale->dwSxN / lpscale->dwSxD; + XformSizeInHimetricToPixels(NULL, (LPSIZEL)&sizelHim, (LPSIZEL)&sizelPix); + + GetWindowRect(hWndLL, (LPRECT)&rcPosRect); + ScreenToClient(lpServerDoc->m_hWndParent, (POINT FAR *)&rcPosRect); + + rcPosRect.right = rcPosRect.left + (int) sizelPix.cx; + rcPosRect.bottom = rcPosRect.top + (int) sizelPix.cy; + OleDbgOutRect3("ServerDoc_UpdateInPlaceWindowOnExtentChange: (PosRect)", (LPRECT)&rcPosRect); + + OLEDBG_BEGIN2("IOleInPlaceSite::OnPosRectChange called\r\n"); + lpServerDoc->m_lpIPData->lpSite->lpVtbl->OnPosRectChange( + lpServerDoc->m_lpIPData->lpSite, + (LPRECT) &rcPosRect + ); + OLEDBG_END2 +} + + +/* ServerDoc_CalcInPlaceWindowPos + * ------------------------------ + * + * Move (and re-scale) the ServerDoc to the specified rectangle. + * + * Parameters: + * lprcListBox - rect in client coordinate in which the listbox will fit + * lprcDoc - corresponding size of the Doc in client coordinate + * + */ +void ServerDoc_CalcInPlaceWindowPos( + LPSERVERDOC lpServerDoc, + LPRECT lprcListBox, + LPRECT lprcDoc, + LPSCALEFACTOR lpscale +) +{ + SIZEL sizelHim; + SIZEL sizelPix; + LPLINELIST lpLL; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; + LPHEADING lphead; + + if (!lpServerDoc || !lprcListBox || !lprcDoc) + return; + + lphead = (LPHEADING)&lpOutlineDoc->m_heading; + + lpLL = OutlineDoc_GetLineList(lpOutlineDoc); + OleDoc_GetExtent((LPOLEDOC)lpServerDoc, (LPSIZEL)&sizelHim); + XformSizeInHimetricToPixels(NULL, &sizelHim, &sizelPix); + + if (sizelHim.cx == 0 || sizelPix.cx == 0) { + lpscale->dwSxN = 1; + lpscale->dwSxD = 1; + } else { + lpscale->dwSxN = lprcListBox->right - lprcListBox->left; + lpscale->dwSxD = sizelPix.cx; + } + + if (sizelHim.cy == 0 || sizelPix.cy == 0) { + lpscale->dwSyN = 1; + lpscale->dwSyD = 1; + } else { + lpscale->dwSyN = lprcListBox->bottom - lprcListBox->top; + lpscale->dwSyD = sizelPix.cy; + } + + lprcDoc->left = lprcListBox->left - Heading_RH_GetWidth(lphead,lpscale); + lprcDoc->right = lprcListBox->right; + lprcDoc->top = lprcListBox->top - Heading_CH_GetHeight(lphead,lpscale); + lprcDoc->bottom = lprcListBox->bottom; +} + + +/* ServerDoc_ResizeInPlaceWindow +** ----------------------------- +** Actually resize the in-place ServerDoc windows according to the +** PosRect and ClipRect allowed by our in-place container. +** +** OLE2NOTE: the PosRect rectangle that our in-place container tells +** us is always the rectangle required for the object display +** itself (in our case the size of the LineList contents). it does +** NOT include the space we require for object frame adornments. +*/ +void ServerDoc_ResizeInPlaceWindow( + LPSERVERDOC lpServerDoc, + LPCRECT lprcPosRect, + LPCRECT lprcClipRect +) +{ + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; + LPLINELIST lpLL = (LPLINELIST)&lpOutlineDoc->m_LineList; + SCALEFACTOR scale; + RECT rcDoc; + POINT ptOffset; + + /* OLE2NOTE: calculate the space needed for our object frame + ** adornments. our in-place container tells us the size that our + ** object should take in window client coordinates + ** (lprcPosRect). the rectangle cooresponds to the size that our + ** LineList ListBox should be. our Doc window must the correct + ** amount larger to accomodate our row/column headings. + ** then move all windows into position. + */ + ServerDoc_CalcInPlaceWindowPos( + lpServerDoc, + (LPRECT)lprcPosRect, + (LPRECT)&rcDoc, + (LPSCALEFACTOR)&scale + ); + + /* OLE2NOTE: we need to honor the lprcClipRect specified by our + ** in-place container. we must NOT draw outside of the ClipRect. + ** in order to achieve this, we will size the hatch window to be + ** exactly the size that should be visible (rcVisRect). the + ** rcVisRect is defined as the intersection of the full size of + ** the in-place server window and the lprcClipRect. + ** the ClipRect could infact clip the HatchRect on the + ** right/bottom and/or on the top/left. if it is clipped on the + ** right/bottom then it is sufficient to simply resize the hatch + ** window. but if the HatchRect is clipped on the top/left then + ** we must "move" the ServerDoc window (child of HatchWindow) by + ** the delta that was clipped. the window origin of the + ** ServerDoc window will then have negative coordinates relative + ** to its parent HatchWindow. + */ + SetHatchWindowSize( + lpServerDoc->m_hWndHatch, + (LPRECT)&rcDoc, + (LPRECT)lprcClipRect, + (LPPOINT)&ptOffset + ); + + // shift Doc window to account for hatch frame being drawn + OffsetRect((LPRECT)&rcDoc, ptOffset.x, ptOffset.y); + + // move/size/set scale factor of ServerDoc window. + OutlineDoc_SetScaleFactor( + lpOutlineDoc, (LPSCALEFACTOR)&scale, (LPRECT)&rcDoc); + + /* reset the horizontal extent of the listbox. this makes + ** the listbox realize that a scroll bar is not needed. + */ + SendMessage( + lpLL->m_hWndListBox, + LB_SETHORIZONTALEXTENT, + (int) 0, + 0L + ); + SendMessage( + lpLL->m_hWndListBox, + LB_SETHORIZONTALEXTENT, + (int) (lprcPosRect->right - lprcPosRect->left), + 0L + ); +} + + +/* ServerDoc_SetStatusText +** Tell the active in-place frame to display a status message. +*/ +void ServerDoc_SetStatusText(LPSERVERDOC lpServerDoc, LPSTR lpszMessage) +{ + if (lpServerDoc && lpServerDoc->m_fUIActive && + lpServerDoc->m_lpIPData != NULL) { + + OLEDBG_BEGIN2("IOleInPlaceFrame::SetStatusText called\r\n") + CallIOleInPlaceFrameSetStatusTextA + (lpServerDoc->m_lpIPData->lpFrame, lpszMessage); + OLEDBG_END2 + } +} + + +/* ServerDoc_GetTopInPlaceFrame +** ---------------------------- +** returns NON-AddRef'ed pointer to Top In-Place Frame interface +*/ +LPOLEINPLACEFRAME ServerDoc_GetTopInPlaceFrame(LPSERVERDOC lpServerDoc) +{ + if (lpServerDoc->m_lpIPData) + return lpServerDoc->m_lpIPData->lpFrame; + else + return NULL; +} + +void ServerDoc_GetSharedMenuHandles( + LPSERVERDOC lpServerDoc, + HMENU FAR* lphSharedMenu, + HOLEMENU FAR* lphOleMenu +) +{ + if (lpServerDoc->m_lpIPData) { + *lphSharedMenu = lpServerDoc->m_lpIPData->hMenuShared; + *lphOleMenu = lpServerDoc->m_lpIPData->hOlemenu; + } else { + *lphSharedMenu = NULL; + *lphOleMenu = NULL; + } +} + + +void ServerDoc_AddFrameLevelUI(LPSERVERDOC lpServerDoc) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + LPSERVERAPP lpServerApp = (LPSERVERAPP)g_lpApp; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; + LPOLEINPLACEFRAME lpTopIPFrame=ServerDoc_GetTopInPlaceFrame(lpServerDoc); + HMENU hSharedMenu; // combined obj/cntr menu + HOLEMENU hOleMenu; // returned by OleCreateMenuDesc. + + ServerDoc_GetSharedMenuHandles( + lpServerDoc, + &hSharedMenu, + &hOleMenu + ); + + lpTopIPFrame->lpVtbl->SetMenu( + lpTopIPFrame, + hSharedMenu, + hOleMenu, + lpOutlineDoc->m_hWndDoc + ); + + // save normal accelerator table + lpServerApp->m_hAccelBaseApp = lpOutlineApp->m_hAccelApp; + + // install accelerator table for UIActive server (w/ active editor cmds) + lpOutlineApp->m_hAccel = lpServerApp->m_hAccelIPSvr; + lpOutlineApp->m_hAccelApp = lpServerApp->m_hAccelIPSvr; + lpOutlineApp->m_hWndAccelTarget = lpOutlineDoc->m_hWndDoc; + +#if defined( USE_FRAMETOOLS ) + ServerDoc_AddFrameLevelTools(lpServerDoc); + + // update toolbar button enable states + OutlineDoc_UpdateFrameToolButtons(lpOutlineDoc); +#endif +} + + +void ServerDoc_AddFrameLevelTools(LPSERVERDOC lpServerDoc) +{ + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; + LPSERVERAPP lpServerApp = (LPSERVERAPP)g_lpApp; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; + LPOLEINPLACEFRAME lpTopIPFrame=ServerDoc_GetTopInPlaceFrame(lpServerDoc); + +#if defined( USE_FRAMETOOLS ) + HWND hWndFrame; + + FrameTools_Enable(lpOutlineDoc->m_lpFrameTools, TRUE); + + // if not in-place UI active, add our tools to our own frame. + if (! lpServerDoc->m_fUIActive) { + OutlineDoc_AddFrameLevelTools(lpOutlineDoc); + return; + } + + if ((hWndFrame = OutlineApp_GetFrameWindow(lpOutlineApp)) == NULL) { + /* we could NOT get a valid frame window, so POP our tools up. */ + + /* OLE2NOTE: since we are poping up our tools, we MUST inform + ** the top in-place frame window that we need NO tool space + ** BUT that it should NOT put its own tools up. if we were + ** to pass NULL instead of (0,0,0,0), then the container + ** would have the option to leave its own tools up. + */ + lpTopIPFrame->lpVtbl->SetBorderSpace( + lpTopIPFrame, + (LPCBORDERWIDTHS)&g_rectNull + ); + FrameTools_PopupTools(lpOutlineDoc->m_lpFrameTools); + } else { + + /* OLE2NOTE: we need to negotiate for space and attach our frame + ** level tools to the top-level in-place container's frame window. + */ + FrameTools_AttachToFrame(lpOutlineDoc->m_lpFrameTools, hWndFrame); + + FrameTools_NegotiateForSpaceAndShow( + lpOutlineDoc->m_lpFrameTools, + NULL, + lpTopIPFrame + ); + } + +#else // ! USE_FRAMETOOLS + /* OLE2NOTE: if you do NOT use frame tools, you MUST inform the top + ** in-place frame window so that it can put back its own tools. + */ + lpTopIPFrame->lpVtbl->SetBorderSpace(lpIPData->lpFrame, NULL); +#endif // ! USE_FRAMETOOLS +} + + +#if defined( USE_FRAMETOOLS ) + +void ServerDoc_RemoveFrameLevelTools(LPSERVERDOC lpServerDoc) +{ + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; + OleDbgAssert(lpOutlineDoc->m_lpFrameTools != NULL); + + // Reparent our tools back to one of our own windows + FrameTools_AttachToFrame(lpOutlineDoc->m_lpFrameTools,g_lpApp->m_hWndApp); + + FrameTools_Enable(lpOutlineDoc->m_lpFrameTools, FALSE); +} +#endif // USE_FRAMETOOLS + + + +void ServerDoc_UIActivate (LPSERVERDOC lpServerDoc) +{ + if (lpServerDoc->m_fInPlaceActive && !lpServerDoc->m_fUIActive) { + ServerDoc_DoInPlaceActivate(lpServerDoc, + OLEIVERB_UIACTIVATE, + NULL /*lpmsg*/, + lpServerDoc->m_lpOleClientSite + ); + OutlineDoc_ShowWindow((LPOUTLINEDOC)lpServerDoc); + } +} diff --git a/private/oleutest/letest/outline/svroutl.h b/private/oleutest/letest/outline/svroutl.h new file mode 100644 index 000000000..478149eae --- /dev/null +++ b/private/oleutest/letest/outline/svroutl.h @@ -0,0 +1,888 @@ +/************************************************************************* +** +** OLE 2.0 Server Sample Code +** +** svroutl.h +** +** This file contains file contains data structure defintions, +** function prototypes, constants, etc. used by the OLE 2.0 server +** app version of the Outline series of sample applications: +** Outline -- base version of the app (without OLE functionality) +** SvrOutl -- OLE 2.0 Server sample app +** CntrOutl -- OLE 2.0 Containter sample app +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + +#if !defined( _SVROUTL_H_ ) +#define _SVROUTL_H_ + +#ifndef RC_INVOKED +#pragma message ("INCLUDING SVROUTL.H from " __FILE__) +#endif /* RC_INVOKED */ + +#include "oleoutl.h" + +/* Defines */ + +// Enable SVROUTL and ISVROTL to emulate each other (TreatAs aka. ActivateAs) +#define SVR_TREATAS 1 + +// Enable SVROUTL and ISVROTL to convert each other (TreatAs aka. ActivateAs) +#define SVR_CONVERTTO 1 + +// Enable ISVROTL to operate as in inside-out style in-place object +#define SVR_INSIDEOUT 1 + +/* Default name used for container of the embedded object. used if +** container forgets to call IOleObject::SetHostNames +*/ +// REVIEW: should load from string resource +#define DEFCONTAINERNAME "Unknown Document" + +/* Default prefix for auto-generated range names. This is used with +** links to unnamed ranges (pseudo objects). +*/ +// REVIEW: should load from string resource +#define DEFRANGENAMEPREFIX "Range" + +// Maximum length of strings accepted through IOleObject::SetHostNames +// (note: this is rather arbitrary; a better strategy would be to +// dynamically allocated buffers for these strings.) +#define MAXAPPNAME 80 +#define MAXCONTAINERNAME 80 + +// Menu option in embedding mode +#define IDM_F_UPDATE 1151 + +/* Types */ + +/* Codes for CallBack events */ +typedef enum tagOLE_NOTIFICATION { + OLE_ONDATACHANGE, // 0 + OLE_ONSAVE, // 1 + OLE_ONRENAME, // 2 + OLE_ONCLOSE // 3 +} OLE_NOTIFICATION; + +/* Codes to indicate mode of storage for an object. +** Mode of the storage is modified by the IPersistStorage methods: +** Save, HandsOffStorage, and SaveCompleted. +*/ +typedef enum tagSTGMODE { + STGMODE_NORMAL = 0, + STGMODE_NOSCRIBBLE = 1, + STGMODE_HANDSOFF = 2 +} STGMODE; + + +/* Forward type definitions */ +typedef struct tagSERVERAPP FAR* LPSERVERAPP; +typedef struct tagSERVERDOC FAR* LPSERVERDOC; +typedef struct tagPSEUDOOBJ FAR* LPPSEUDOOBJ; + +typedef struct tagINPLACEDATA { + OLEMENUGROUPWIDTHS menuGroupWidths; + HOLEMENU hOlemenu; + HMENU hMenuShared; + LPOLEINPLACESITE lpSite; + LPOLEINPLACEUIWINDOW lpDoc; + LPOLEINPLACEFRAME lpFrame; + OLEINPLACEFRAMEINFO frameInfo; + HWND hWndFrame; + BOOL fBorderOn; + RECT rcPosRect; + RECT rcClipRect; +} INPLACEDATA, FAR* LPINPLACEDATA; + + +/************************************************************************* +** class SERVERDOC : OLEDOC +** SERVERDOC is an extention to the abstract base OLEDOC class. +** The OLEDOC class defines the fields, methods and interfaces that +** are common to both server and client implementations. The +** SERVERDOC class adds the fields, methods and interfaces that are +** specific to OLE 2.0 Server functionality. There is one instance +** of SERVERDOC object created per document open in the app. The SDI +** version of the app supports one SERVERDOC at a time. The MDI +** version of the app can manage multiple documents at one time. +** The SERVERDOC class inherits all fields from the OLEDOC class. +** This inheritance is achieved by including a member variable of +** type OLEDOC as the first field in the SERVERDOC structure. Thus a +** pointer to a SERVERDOC object can be cast to be a pointer to a +** OLEDOC object or an OUTLINEDOC object +*************************************************************************/ + +typedef struct tagSERVERDOC { + OLEDOC m_OleDoc; // ServerDoc inherits from OleDoc + ULONG m_cPseudoObj; // total count of pseudo obj's + LPOLECLIENTSITE m_lpOleClientSite; // Client associated with the obj + LPOLEADVISEHOLDER m_lpOleAdviseHldr; // helper obj to hold ole advises + LPDATAADVISEHOLDER m_lpDataAdviseHldr; // helper obj to hold data advises + BOOL m_fNoScribbleMode; // was IPS::Save called + BOOL m_fSaveWithSameAsLoad; // was IPS::Save called with + // fSameAsLoad==TRUE. + char m_szContainerApp[MAXAPPNAME]; + char m_szContainerObj[MAXCONTAINERNAME]; + ULONG m_nNextRangeNo; // next no. for unnamed range + LINERANGE m_lrSrcSelOfCopy; // src sel if doc created for copy + BOOL m_fDataChanged; // data changed when draw disabled + BOOL m_fSizeChanged; // size changed when draw disabled + BOOL m_fSendDataOnStop; // did data ever change? +#if defined( SVR_TREATAS ) + CLSID m_clsidTreatAs; // clsid to pretend to be + LPSTR m_lpszTreatAsType; // user type name to pretend to be +#endif // SVR_TREATAS + +#if defined( LATER ) + // REVIEW: is it necessary to register a WildCard Moniker + DWORD m_dwWildCardRegROT; // key if wildcard reg'ed in ROT +#endif + +#if defined( INPLACE_SVR ) + BOOL m_fInPlaceActive; + BOOL m_fInPlaceVisible; + BOOL m_fUIActive; + HWND m_hWndParent; + HWND m_hWndHatch; + LPINPLACEDATA m_lpIPData; + BOOL m_fMenuHelpMode;// is F1 pressed in menu, give help + + struct CDocOleInPlaceObjectImpl { + IOleInPlaceObjectVtbl FAR* lpVtbl; + LPSERVERDOC lpServerDoc; + int cRef; // interface specific ref count. + } m_OleInPlaceObject; + + struct CDocOleInPlaceActiveObjectImpl { + IOleInPlaceActiveObjectVtbl FAR* lpVtbl; + LPSERVERDOC lpServerDoc; + int cRef;// interface specific ref count. + } m_OleInPlaceActiveObject; +#endif // INPLACE_SVR + + struct CDocOleObjectImpl { + IOleObjectVtbl FAR* lpVtbl; + LPSERVERDOC lpServerDoc; + int cRef; // interface specific ref count. + } m_OleObject; + + struct CDocPersistStorageImpl { + IPersistStorageVtbl FAR* lpVtbl; + LPSERVERDOC lpServerDoc; + int cRef; // interface specific ref count. + } m_PersistStorage; + +#if defined( SVR_TREATAS ) + struct CDocStdMarshalInfoImpl { + IStdMarshalInfoVtbl FAR* lpVtbl; + LPSERVERDOC lpServerDoc; + int cRef; // interface specific ref count. + } m_StdMarshalInfo; +#endif // SVR_TREATAS + +} SERVERDOC; + +/* ServerDoc methods (functions) */ +BOOL ServerDoc_Init(LPSERVERDOC lpServerDoc, BOOL fDataTransferDoc); +BOOL ServerDoc_InitNewEmbed(LPSERVERDOC lpServerDoc); +void ServerDoc_PseudoObjUnlockDoc( + LPSERVERDOC lpServerDoc, + LPPSEUDOOBJ lpPseudoObj +); +void ServerDoc_PseudoObjLockDoc(LPSERVERDOC lpServerDoc); +BOOL ServerDoc_PasteFormatFromData( + LPSERVERDOC lpServerDoc, + CLIPFORMAT cfFormat, + LPDATAOBJECT lpSrcDataObj, + BOOL fLocalDataObj, + BOOL fLink +); +BOOL ServerDoc_QueryPasteFromData( + LPSERVERDOC lpServerDoc, + LPDATAOBJECT lpSrcDataObj, + BOOL fLink +); +HRESULT ServerDoc_GetClassID(LPSERVERDOC lpServerDoc, LPCLSID lpclsid); +void ServerDoc_UpdateMenu(LPSERVERDOC lpServerDoc); +void ServerDoc_RestoreMenu(LPSERVERDOC lpServerDoc); +HRESULT ServerDoc_GetData ( + LPSERVERDOC lpServerDoc, + LPFORMATETC lpformatetc, + LPSTGMEDIUM lpMedium +); +HRESULT ServerDoc_GetDataHere ( + LPSERVERDOC lpServerDoc, + LPFORMATETC lpformatetc, + LPSTGMEDIUM lpMedium +); +HRESULT ServerDoc_QueryGetData(LPSERVERDOC lpServerDoc,LPFORMATETC lpformatetc); +HRESULT ServerDoc_EnumFormatEtc( + LPSERVERDOC lpServerDoc, + DWORD dwDirection, + LPENUMFORMATETC FAR* lplpenumFormatEtc +); +HANDLE ServerDoc_GetMetafilePictData( + LPSERVERDOC lpServerDoc, + LPLINERANGE lplrSel +); +void ServerDoc_SendAdvise( + LPSERVERDOC lpServerDoc, + WORD wAdvise, + LPMONIKER lpmkDoc, + DWORD dwAdvf +); +HRESULT ServerDoc_GetObject( + LPSERVERDOC lpServerDoc, + LPOLESTR lpszItem, + REFIID riid, + LPVOID FAR* lplpvObject +); +HRESULT ServerDoc_IsRunning(LPSERVERDOC lpServerDoc, LPOLESTR lpszItem); +LPMONIKER ServerDoc_GetSelRelMoniker( + LPSERVERDOC lpServerDoc, + LPLINERANGE lplrSel, + DWORD dwAssign +); +LPMONIKER ServerDoc_GetSelFullMoniker( + LPSERVERDOC lpServerDoc, + LPLINERANGE lplrSel, + DWORD dwAssign +); + + +#if defined( INPLACE_SVR ) +HRESULT ServerDoc_DoInPlaceActivate( + LPSERVERDOC lpServerDoc, + LONG lVerb, + LPMSG lpmsg, + LPOLECLIENTSITE lpActiveSite +); +HRESULT ServerDoc_DoInPlaceDeactivate(LPSERVERDOC lpServerDoc); +HRESULT ServerDoc_DoInPlaceHide(LPSERVERDOC lpServerDoc); +BOOL ServerDoc_AllocInPlaceData(LPSERVERDOC lpServerDoc); +void ServerDoc_FreeInPlaceData(LPSERVERDOC lpServerDoc); + +HRESULT ServerDoc_AssembleMenus(LPSERVERDOC lpServerDoc); +void ServerDoc_DisassembleMenus(LPSERVERDOC lpServerDoc); +void ServerDoc_CalcInPlaceWindowPos( + LPSERVERDOC lpServerDoc, + LPRECT lprcListBox, + LPRECT lprcDoc, + LPSCALEFACTOR lpscale +); +void ServerDoc_UpdateInPlaceWindowOnExtentChange(LPSERVERDOC lpServerDoc); +void ServerDoc_ResizeInPlaceWindow( + LPSERVERDOC lpServerDoc, + LPCRECT lprcPosRect, + LPCRECT lprcClipRect +); +void ServerDoc_ShadeInPlaceBorder(LPSERVERDOC lpServerDoc, BOOL fShadeOn); +void ServerDoc_SetStatusText(LPSERVERDOC lpServerDoc, LPSTR lpszMessage); +LPOLEINPLACEFRAME ServerDoc_GetTopInPlaceFrame(LPSERVERDOC lpServerDoc); +void ServerDoc_GetSharedMenuHandles( + LPSERVERDOC lpServerDoc, + HMENU FAR* lphSharedMenu, + HOLEMENU FAR* lphOleMenu +); +void ServerDoc_AddFrameLevelUI(LPSERVERDOC lpServerDoc); +void ServerDoc_AddFrameLevelTools(LPSERVERDOC lpServerDoc); +void ServerDoc_UIActivate (LPSERVERDOC lpServerDoc); + +#if defined( USE_FRAMETOOLS ) +void ServerDoc_RemoveFrameLevelTools(LPSERVERDOC lpServerDoc); +#endif // USE_FRAMETOOLS + +#endif // INPLACE_SVR + + +/* ServerDoc::IOleObject methods (functions) */ +STDMETHODIMP SvrDoc_OleObj_QueryInterface( + LPOLEOBJECT lpThis, + REFIID riid, + LPVOID FAR* lplpvObj +); +STDMETHODIMP_(ULONG) SvrDoc_OleObj_AddRef(LPOLEOBJECT lpThis); +STDMETHODIMP_(ULONG) SvrDoc_OleObj_Release(LPOLEOBJECT lpThis); +STDMETHODIMP SvrDoc_OleObj_SetClientSite( + LPOLEOBJECT lpThis, + LPOLECLIENTSITE lpclientSite +); +STDMETHODIMP SvrDoc_OleObj_GetClientSite( + LPOLEOBJECT lpThis, + LPOLECLIENTSITE FAR* lplpClientSite +); +STDMETHODIMP SvrDoc_OleObj_SetHostNames( + LPOLEOBJECT lpThis, + LPCOLESTR szContainerApp, + LPCOLESTR szContainerObj +); +STDMETHODIMP SvrDoc_OleObj_Close( + LPOLEOBJECT lpThis, + DWORD dwSaveOption +); +STDMETHODIMP SvrDoc_OleObj_SetMoniker( + LPOLEOBJECT lpThis, + DWORD dwWhichMoniker, + LPMONIKER lpmk +); +STDMETHODIMP SvrDoc_OleObj_GetMoniker( + LPOLEOBJECT lpThis, + DWORD dwAssign, + DWORD dwWhichMoniker, + LPMONIKER FAR* lplpmk +); +STDMETHODIMP SvrDoc_OleObj_InitFromData( + LPOLEOBJECT lpThis, + LPDATAOBJECT lpDataObject, + BOOL fCreation, + DWORD reserved +); +STDMETHODIMP SvrDoc_OleObj_GetClipboardData( + LPOLEOBJECT lpThis, + DWORD reserved, + LPDATAOBJECT FAR* lplpDataObject +); +STDMETHODIMP SvrDoc_OleObj_DoVerb( + LPOLEOBJECT lpThis, + LONG lVerb, + LPMSG lpmsg, + LPOLECLIENTSITE lpActiveSite, + LONG lindex, + HWND hwndParent, + LPCRECT lprcPosRect +); +STDMETHODIMP SvrDoc_OleObj_EnumVerbs( + LPOLEOBJECT lpThis, + LPENUMOLEVERB FAR* lplpenumOleVerb +); +STDMETHODIMP SvrDoc_OleObj_Update(LPOLEOBJECT lpThis); +STDMETHODIMP SvrDoc_OleObj_IsUpToDate(LPOLEOBJECT lpThis); +STDMETHODIMP SvrDoc_OleObj_GetUserClassID( + LPOLEOBJECT lpThis, + LPCLSID lpclsid +); +STDMETHODIMP SvrDoc_OleObj_GetUserType( + LPOLEOBJECT lpThis, + DWORD dwFormOfType, + LPOLESTR FAR* lpszUserType +); +STDMETHODIMP SvrDoc_OleObj_SetExtent( + LPOLEOBJECT lpThis, + DWORD dwDrawAspect, + LPSIZEL lplgrc +); +STDMETHODIMP SvrDoc_OleObj_GetExtent( + LPOLEOBJECT lpThis, + DWORD dwDrawAspect, + LPSIZEL lplgrc +); +STDMETHODIMP SvrDoc_OleObj_Advise( + LPOLEOBJECT lpThis, + LPADVISESINK lpAdvSink, + LPDWORD lpdwConnection +); +STDMETHODIMP SvrDoc_OleObj_Unadvise(LPOLEOBJECT lpThis, DWORD dwConnection); +STDMETHODIMP SvrDoc_OleObj_EnumAdvise( + LPOLEOBJECT lpThis, + LPENUMSTATDATA FAR* lplpenumAdvise +); +STDMETHODIMP SvrDoc_OleObj_GetMiscStatus( + LPOLEOBJECT lpThis, + DWORD dwAspect, + DWORD FAR* lpdwStatus +); +STDMETHODIMP SvrDoc_OleObj_SetColorScheme( + LPOLEOBJECT lpThis, + LPLOGPALETTE lpLogpal +); +STDMETHODIMP SvrDoc_OleObj_LockObject( + LPOLEOBJECT lpThis, + BOOL fLock +); + +/* ServerDoc::IPersistStorage methods (functions) */ +STDMETHODIMP SvrDoc_PStg_QueryInterface( + LPPERSISTSTORAGE lpThis, + REFIID riid, + LPVOID FAR* lplpvObj +); +STDMETHODIMP_(ULONG) SvrDoc_PStg_AddRef(LPPERSISTSTORAGE lpThis); +STDMETHODIMP_(ULONG) SvrDoc_PStg_Release(LPPERSISTSTORAGE lpThis); +STDMETHODIMP SvrDoc_PStg_GetClassID( + LPPERSISTSTORAGE lpThis, + LPCLSID lpClassID +); +STDMETHODIMP SvrDoc_PStg_IsDirty(LPPERSISTSTORAGE lpThis); +STDMETHODIMP SvrDoc_PStg_InitNew( + LPPERSISTSTORAGE lpThis, + LPSTORAGE lpStg +); +STDMETHODIMP SvrDoc_PStg_Load( + LPPERSISTSTORAGE lpThis, + LPSTORAGE lpStg +); +STDMETHODIMP SvrDoc_PStg_Save( + LPPERSISTSTORAGE lpThis, + LPSTORAGE lpStg, + BOOL fSameAsLoad +); +STDMETHODIMP SvrDoc_PStg_SaveCompleted( + LPPERSISTSTORAGE lpThis, + LPSTORAGE lpStgNew +); +STDMETHODIMP SvrDoc_PStg_HandsOffStorage(LPPERSISTSTORAGE lpThis); + + +#if defined( SVR_TREATAS ) + +/* ServerDoc::IStdMarshalInfo methods (functions) */ +STDMETHODIMP SvrDoc_StdMshl_QueryInterface( + LPSTDMARSHALINFO lpThis, + REFIID riid, + LPVOID FAR* lplpvObj +); +STDMETHODIMP_(ULONG) SvrDoc_StdMshl_AddRef(LPSTDMARSHALINFO lpThis); +STDMETHODIMP_(ULONG) SvrDoc_StdMshl_Release(LPSTDMARSHALINFO lpThis); +STDMETHODIMP SvrDoc_StdMshl_GetClassForHandler( + LPSTDMARSHALINFO lpThis, + DWORD dwDestContext, + LPVOID pvDestContext, + LPCLSID lpClassID +); +#endif // SVR_TREATAS + +/************************************************************************* +** class SERVERAPP : OLEAPP +** SERVERAPP is an extention to the abstract base OLEAPP class. +** The OLEAPP class defines the fields, methods and interfaces that +** are common to both server and client implementations. The +** SERVERAPP class adds the fields and methods that are specific to +** OLE 2.0 Server functionality. There is one instance of +** SERVERAPP object created per running application instance. This +** object holds many fields that could otherwise be organized as +** global variables. The SERVERAPP class inherits all fields +** from the OLEAPP class. This inheritance is achieved by including a +** member variable of type OLEAPP as the first field in the SERVERAPP +** structure. OLEAPP inherits from OLEAPP. This inheritance is +** achieved in the same manner. Thus a pointer to a SERVERAPP object +** can be cast to be a pointer to an OLEAPP or an OUTLINEAPP object +*************************************************************************/ + +typedef struct tagSERVERAPP { + OLEAPP m_OleApp; // ServerApp inherits all fields of OleApp + +#if defined( INPLACE_SVR ) + HACCEL m_hAccelIPSvr; // accelerators for server's active object commands + HACCEL m_hAccelBaseApp; // normal accel for non-inplace server mode + HMENU m_hMenuEdit; // handle to Edit menu of the server app + HMENU m_hMenuLine; // handle to Line menu of the server app + HMENU m_hMenuName; // handle to Name menu of the server app + HMENU m_hMenuOptions; // handle to Options menu of the server app + HMENU m_hMenuDebug; // handle to Debug menu of the server app + HMENU m_hMenuHelp; // handle to Help menu of the server app + LPINPLACEDATA m_lpIPData; +#endif + +} SERVERAPP; + +/* ServerApp methods (functions) */ +BOOL ServerApp_InitInstance( + LPSERVERAPP lpServerApp, + HINSTANCE hInst, + int nCmdShow +); +BOOL ServerApp_InitVtbls (LPSERVERAPP lpServerApp); + + + +/************************************************************************* +** class SERVERNAME : OUTLINENAME +** SERVERNAME class is an extension to the OUTLINENAME base class that +** adds functionallity required to support linking to ranges (pseudo +** objects). Pseudo objects are used to allow linking to a range +** (sub-selection) of a SERVERDOC document. The base class OUTLINENAME +** stores a particular named selection in the document. The +** NAMETABLE class holds all of the names defined in a particular +** document. Each OUTLINENAME object has a string as its key and a +** starting line index and an ending line index for the named range. +** The SERVERNAME class, also, stores a pointer to a PSEUDOOBJ if one +** has been allocated that corresponds to the named selection. +** The SERVERNAME class inherits all fields from the OUTLINENAME class. +** This inheritance is achieved by including a member variable of +** type OUTLINENAME as the first field in the SERVERNAME +** structure. Thus a pointer to an SERVERNAME object can be cast to be +** a pointer to a OUTLINENAME object. +*************************************************************************/ + +typedef struct tagSERVERNAME { + OUTLINENAME m_Name; // ServerName inherits all fields of Name + LPPSEUDOOBJ m_lpPseudoObj; // ptr to pseudo object if allocated +} SERVERNAME, FAR* LPSERVERNAME; + +/* ServerName methods (functions) */ +void ServerName_SetSel( + LPSERVERNAME lpServerName, + LPLINERANGE lplrSel, + BOOL fRangeModified +); +void ServerName_SendPendingAdvises(LPSERVERNAME lpServerName); +LPPSEUDOOBJ ServerName_GetPseudoObj( + LPSERVERNAME lpServerName, + LPSERVERDOC lpServerDoc +); +void ServerName_ClosePseudoObj(LPSERVERNAME lpServerName); + + +/************************************************************************* +** class PSEUDOOBJ +** The PSEUDOOBJ (pseudo object) is a concrete class. A pseudo object +** is created when a link is made to a range of lines within an +** SERVERDOC document. A pseudo object is dependent on the existance +** of the SERVERDOC which represents the whole document. +*************************************************************************/ + +typedef struct tagPSEUDOOBJ { + ULONG m_cRef; // total ref count for obj + BOOL m_fObjIsClosing; // flag to guard recursive close + LPSERVERNAME m_lpName; // named range for this pseudo obj + LPSERVERDOC m_lpDoc; // ptr to whole document + LPOLEADVISEHOLDER m_lpOleAdviseHldr; // helper obj to hold ole advises + LPDATAADVISEHOLDER m_lpDataAdviseHldr; // helper obj to hold data advises + BOOL m_fDataChanged; // data changed when draw disabled + + struct CPseudoObjUnknownImpl { + IUnknownVtbl FAR* lpVtbl; + LPPSEUDOOBJ lpPseudoObj; + int cRef; // interface specific ref count. + } m_Unknown; + + struct CPseudoObjOleObjectImpl { + IOleObjectVtbl FAR* lpVtbl; + LPPSEUDOOBJ lpPseudoObj; + int cRef; // interface specific ref count. + } m_OleObject; + + struct CPseudoObjDataObjectImpl { + IDataObjectVtbl FAR* lpVtbl; + LPPSEUDOOBJ lpPseudoObj; + int cRef; // interface specific ref count. + } m_DataObject; + +} PSEUDOOBJ; + +/* PseudoObj methods (functions) */ +void PseudoObj_Init( + LPPSEUDOOBJ lpPseudoObj, + LPSERVERNAME lpServerName, + LPSERVERDOC lpServerDoc +); +ULONG PseudoObj_AddRef(LPPSEUDOOBJ lpPseudoObj); +ULONG PseudoObj_Release(LPPSEUDOOBJ lpPseudoObj); +HRESULT PseudoObj_QueryInterface( + LPPSEUDOOBJ lpPseudoObj, + REFIID riid, + LPVOID FAR* lplpUnk +); +BOOL PseudoObj_Close(LPPSEUDOOBJ lpPseudoObj); +void PseudoObj_Destroy(LPPSEUDOOBJ lpPseudoObj); +void PseudoObj_GetSel(LPPSEUDOOBJ lpPseudoObj, LPLINERANGE lplrSel); +void PseudoObj_GetExtent(LPPSEUDOOBJ lpPseudoObj, LPSIZEL lpsizel); +void PseudoObj_GetExtent(LPPSEUDOOBJ lpPseudoObj, LPSIZEL lpsizel); +void PseudoObj_SendAdvise( + LPPSEUDOOBJ lpPseudoObj, + WORD wAdvise, + LPMONIKER lpmkObj, + DWORD dwAdvf +); +LPMONIKER PseudoObj_GetFullMoniker(LPPSEUDOOBJ lpPseudoObj, LPMONIKER lpmkDoc); + +/* PseudoObj::IUnknown methods (functions) */ +STDMETHODIMP PseudoObj_Unk_QueryInterface( + LPUNKNOWN lpThis, + REFIID riid, + LPVOID FAR* lplpvObj +); +STDMETHODIMP_(ULONG) PseudoObj_Unk_AddRef(LPUNKNOWN lpThis); +STDMETHODIMP_(ULONG) PseudoObj_Unk_Release (LPUNKNOWN lpThis); + +/* PseudoObj::IOleObject methods (functions) */ +STDMETHODIMP PseudoObj_OleObj_QueryInterface( + LPOLEOBJECT lpThis, + REFIID riid, + LPVOID FAR* lplpvObj +); +STDMETHODIMP_(ULONG) PseudoObj_OleObj_AddRef(LPOLEOBJECT lpThis); +STDMETHODIMP_(ULONG) PseudoObj_OleObj_Release(LPOLEOBJECT lpThis); +STDMETHODIMP PseudoObj_OleObj_SetClientSite( + LPOLEOBJECT lpThis, + LPOLECLIENTSITE lpClientSite +); +STDMETHODIMP PseudoObj_OleObj_GetClientSite( + LPOLEOBJECT lpThis, + LPOLECLIENTSITE FAR* lplpClientSite +); +STDMETHODIMP PseudoObj_OleObj_SetHostNames( + LPOLEOBJECT lpThis, + LPCOLESTR szContainerApp, + LPCOLESTR szContainerObj +); +STDMETHODIMP PseudoObj_OleObj_Close( + LPOLEOBJECT lpThis, + DWORD dwSaveOption +); +STDMETHODIMP PseudoObj_OleObj_SetMoniker( + LPOLEOBJECT lpThis, + DWORD dwWhichMoniker, + LPMONIKER lpmk +); +STDMETHODIMP PseudoObj_OleObj_GetMoniker( + LPOLEOBJECT lpThis, + DWORD dwAssign, + DWORD dwWhichMoniker, + LPMONIKER FAR* lplpmk +); +STDMETHODIMP PseudoObj_OleObj_InitFromData( + LPOLEOBJECT lpThis, + LPDATAOBJECT lpDataObject, + BOOL fCreation, + DWORD reserved +); +STDMETHODIMP PseudoObj_OleObj_GetClipboardData( + LPOLEOBJECT lpThis, + DWORD reserved, + LPDATAOBJECT FAR* lplpDataObject +); +STDMETHODIMP PseudoObj_OleObj_DoVerb( + LPOLEOBJECT lpThis, + LONG lVerb, + LPMSG lpmsg, + LPOLECLIENTSITE lpActiveSite, + LONG lindex, + HWND hwndParent, + LPCRECT lprcPosRect +); +STDMETHODIMP PseudoObj_OleObj_EnumVerbs( + LPOLEOBJECT lpThis, + LPENUMOLEVERB FAR* lplpenumOleVerb +); +STDMETHODIMP PseudoObj_OleObj_Update(LPOLEOBJECT lpThis); +STDMETHODIMP PseudoObj_OleObj_IsUpToDate(LPOLEOBJECT lpThis); +STDMETHODIMP PseudoObj_OleObj_GetUserClassID( + LPOLEOBJECT lpThis, + LPCLSID lpclsid +); +STDMETHODIMP PseudoObj_OleObj_GetUserType( + LPOLEOBJECT lpThis, + DWORD dwFormOfType, + LPOLESTR FAR* lpszUserType +); +STDMETHODIMP PseudoObj_OleObj_SetExtent( + LPOLEOBJECT lpThis, + DWORD dwDrawAspect, + LPSIZEL lplgrc +); +STDMETHODIMP PseudoObj_OleObj_GetExtent( + LPOLEOBJECT lpThis, + DWORD dwDrawAspect, + LPSIZEL lplgrc +); +STDMETHODIMP PseudoObj_OleObj_Advise( + LPOLEOBJECT lpThis, + LPADVISESINK lpAdvSink, + LPDWORD lpdwConnection +); +STDMETHODIMP PseudoObj_OleObj_Unadvise(LPOLEOBJECT lpThis,DWORD dwConnection); +STDMETHODIMP PseudoObj_OleObj_EnumAdvise( + LPOLEOBJECT lpThis, + LPENUMSTATDATA FAR* lplpenumAdvise +); +STDMETHODIMP PseudoObj_OleObj_GetMiscStatus( + LPOLEOBJECT lpThis, + DWORD dwAspect, + DWORD FAR* lpdwStatus +); +STDMETHODIMP PseudoObj_OleObj_SetColorScheme( + LPOLEOBJECT lpThis, + LPLOGPALETTE lpLogpal +); +STDMETHODIMP PseudoObj_OleObj_LockObject( + LPOLEOBJECT lpThis, + BOOL fLock +); + +/* PseudoObj::IDataObject methods (functions) */ +STDMETHODIMP PseudoObj_DataObj_QueryInterface ( + LPDATAOBJECT lpThis, + REFIID riid, + LPVOID FAR* lplpvObj +); +STDMETHODIMP_(ULONG) PseudoObj_DataObj_AddRef(LPDATAOBJECT lpThis); +STDMETHODIMP_(ULONG) PseudoObj_DataObj_Release (LPDATAOBJECT lpThis); +STDMETHODIMP PseudoObj_DataObj_GetData ( + LPDATAOBJECT lpThis, + LPFORMATETC lpformatetc, + LPSTGMEDIUM lpMedium +); +STDMETHODIMP PseudoObj_DataObj_GetDataHere ( + LPDATAOBJECT lpThis, + LPFORMATETC lpformatetc, + LPSTGMEDIUM lpMedium +); +STDMETHODIMP PseudoObj_DataObj_QueryGetData ( + LPDATAOBJECT lpThis, + LPFORMATETC lpformatetc +); +STDMETHODIMP PseudoObj_DataObj_GetCanonicalFormatEtc ( + LPDATAOBJECT lpThis, + LPFORMATETC lpformatetc, + LPFORMATETC lpformatetcOut +); +STDMETHODIMP PseudoObj_DataObj_SetData ( + LPDATAOBJECT lpThis, + LPFORMATETC lpformatetc, + LPSTGMEDIUM lpmedium, + BOOL fRelease +); +STDMETHODIMP PseudoObj_DataObj_EnumFormatEtc( + LPDATAOBJECT lpThis, + DWORD dwDirection, + LPENUMFORMATETC FAR* lplpenumFormatEtc +); +STDMETHODIMP PseudoObj_DataObj_DAdvise( + LPDATAOBJECT lpThis, + FORMATETC FAR* lpFormatetc, + DWORD advf, + LPADVISESINK lpAdvSink, + DWORD FAR* lpdwConnection +); +STDMETHODIMP PseudoObj_DataObj_DUnadvise(LPDATAOBJECT lpThis, DWORD dwConnection); +STDMETHODIMP PseudoObj_DataObj_EnumAdvise( + LPDATAOBJECT lpThis, + LPENUMSTATDATA FAR* lplpenumAdvise +); + + +/************************************************************************* +** class SERVERNAMETABLE : OUTLINENAMETABLE +** SERVERNAMETABLE class is an extension to the OUTLINENAMETABLE +** base class that adds functionallity required to support linking +** to ranges (pseudo objects). The name table manages the table of +** named selections in the document. Each name table entry has a +** string as its key and a starting line index and an ending line +** index for the named range. The SERVERNAMETABLE entries, in +** addition, maintain a pointer to a PSEUDOOBJ pseudo object if one +** has been already allocated. There is always one instance of +** SERVERNAMETABLE for each SERVERDOC object created. +** The SERVERNAME class inherits all fields from the NAME class. +** This inheritance is achieved by including a member variable of +** type NAME as the first field in the SERVERNAME +** structure. Thus a pointer to an SERVERNAME object can be cast to be +** a pointer to a NAME object. +*************************************************************************/ + +typedef struct tagSERVERNAMETABLE { + OUTLINENAMETABLE m_NameTable; // we inherit from OUTLINENAMETABLE + + // ServerNameTable does NOT add any fields + +} SERVERNAMETABLE, FAR* LPSERVERNAMETABLE; + +/* ServerNameTable methods (functions) */ +void ServerNameTable_EditLineUpdate( + LPSERVERNAMETABLE lpServerNameTable, + int nEditIndex +); +void ServerNameTable_InformAllPseudoObjectsDocRenamed( + LPSERVERNAMETABLE lpServerNameTable, + LPMONIKER lpmkDoc +); +void ServerNameTable_InformAllPseudoObjectsDocSaved( + LPSERVERNAMETABLE lpServerNameTable, + LPMONIKER lpmkDoc +); +void ServerNameTable_SendPendingAdvises(LPSERVERNAMETABLE lpServerNameTable); +LPPSEUDOOBJ ServerNameTable_GetPseudoObj( + LPSERVERNAMETABLE lpServerNameTable, + LPSTR lpszItem, + LPSERVERDOC lpServerDoc +); +void ServerNameTable_CloseAllPseudoObjs(LPSERVERNAMETABLE lpServerNameTable); + + +#if defined( INPLACE_SVR) + +/* ServerDoc::IOleInPlaceObject methods (functions) */ + +STDMETHODIMP SvrDoc_IPObj_QueryInterface( + LPOLEINPLACEOBJECT lpThis, + REFIID riid, + LPVOID FAR * lplpvObj +); +STDMETHODIMP_(ULONG) SvrDoc_IPObj_AddRef(LPOLEINPLACEOBJECT lpThis); +STDMETHODIMP_(ULONG) SvrDoc_IPObj_Release(LPOLEINPLACEOBJECT lpThis); +STDMETHODIMP SvrDoc_IPObj_GetWindow( + LPOLEINPLACEOBJECT lpThis, + HWND FAR* lphwnd +); +STDMETHODIMP SvrDoc_IPObj_ContextSensitiveHelp( + LPOLEINPLACEOBJECT lpThis, + BOOL fEnable +); +STDMETHODIMP SvrDoc_IPObj_InPlaceDeactivate(LPOLEINPLACEOBJECT lpThis); +STDMETHODIMP SvrDoc_IPObj_UIDeactivate(LPOLEINPLACEOBJECT lpThis); +STDMETHODIMP SvrDoc_IPObj_SetObjectRects( + LPOLEINPLACEOBJECT lpThis, + LPCRECT lprcPosRect, + LPCRECT lprcClipRect +); +STDMETHODIMP SvrDoc_IPObj_ReactivateAndUndo(LPOLEINPLACEOBJECT lpThis); + +/* ServerDoc::IOleInPlaceActiveObject methods (functions) */ + +STDMETHODIMP SvrDoc_IPActiveObj_QueryInterface( + LPOLEINPLACEACTIVEOBJECT lpThis, + REFIID riidReq, + LPVOID FAR * lplpUnk +); +STDMETHODIMP_(ULONG) SvrDoc_IPActiveObj_AddRef( + LPOLEINPLACEACTIVEOBJECT lpThis +); +STDMETHODIMP_(ULONG) SvrDoc_IPActiveObj_Release( + LPOLEINPLACEACTIVEOBJECT lpThis +); +STDMETHODIMP SvrDoc_IPActiveObj_GetWindow( + LPOLEINPLACEACTIVEOBJECT lpThis, + HWND FAR* lphwnd +); +STDMETHODIMP SvrDoc_IPActiveObj_ContextSensitiveHelp( + LPOLEINPLACEACTIVEOBJECT lpThis, + BOOL fEnable +); +STDMETHODIMP SvrDoc_IPActiveObj_TranslateAccelerator( + LPOLEINPLACEACTIVEOBJECT lpThis, + LPMSG lpmsg +); +STDMETHODIMP SvrDoc_IPActiveObj_OnFrameWindowActivate( + LPOLEINPLACEACTIVEOBJECT lpThis, + BOOL fActivate +); +STDMETHODIMP SvrDoc_IPActiveObj_OnDocWindowActivate( + LPOLEINPLACEACTIVEOBJECT lpThis, + BOOL fActivate +); +STDMETHODIMP SvrDoc_IPActiveObj_ResizeBorder( + LPOLEINPLACEACTIVEOBJECT lpThis, + LPCRECT lprectBorder, + LPOLEINPLACEUIWINDOW lpIPUiWnd, + BOOL fFrameWindow +); +STDMETHODIMP SvrDoc_IPActiveObj_EnableModeless( + LPOLEINPLACEACTIVEOBJECT lpThis, + BOOL fEnable +); + +#endif // INPLACE_SVR + +#endif // _SVROUTL_H_ diff --git a/private/oleutest/letest/outline/svroutl.ico b/private/oleutest/letest/outline/svroutl.ico new file mode 100644 index 000000000..b674fc61d Binary files /dev/null and b/private/oleutest/letest/outline/svroutl.ico differ diff --git a/private/oleutest/letest/outline/svroutl/daytona/makefile b/private/oleutest/letest/outline/svroutl/daytona/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/oleutest/letest/outline/svroutl/daytona/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/oleutest/letest/outline/svroutl/daytona/makefile.inc b/private/oleutest/letest/outline/svroutl/daytona/makefile.inc new file mode 100644 index 000000000..462f38133 --- /dev/null +++ b/private/oleutest/letest/outline/svroutl/daytona/makefile.inc @@ -0,0 +1,2 @@ +copyfiles: + xcopy ..\..\*.c . /D diff --git a/private/oleutest/letest/outline/svroutl/daytona/sources b/private/oleutest/letest/outline/svroutl/daytona/sources new file mode 100644 index 000000000..40df009b7 --- /dev/null +++ b/private/oleutest/letest/outline/svroutl/daytona/sources @@ -0,0 +1,106 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + Kenneth MacLeod (Kennethm) 9-Mar-1994 + +!ENDIF + +MAJORCOMP = oleutest +MINORCOMP = letest + +# +# This is the name of the target built from the source files specified +# below. The name should include neither the path nor the file extension. +# + +TARGETNAME= svroutl + +# +# This specifies where the target is to be built. A private target of +# type LIBRARY or DYNLINK should go to obj, whereas a public target of +# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib. +# + +TARGETPATH= obj + +# +# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY, +# etc. +# + +TARGETTYPE= PROGRAM + +INCLUDES= ..\..\..\ole2ui; \ + ..\..\..\bttncur; \ + ..\..\..\gizmobar; \ + ..\..\..\..\inc; \ + ..\.. + +C_DEFINES= \ + $(C_DEFINES) \ + -DFLAT \ + -DWIN32=100 \ + -D_NT1X_=100 \ + -DNOEXCEPTIONS \ + -DOLE_SERVER + +SOURCES= \ + ..\svroutl.rc \ + classfac.c \ + clipbrd.c \ + debug.c \ + debug2.c \ + dialogs.c \ + dragdrop.c \ + frametls.c \ + heading.c \ + linking.c \ + main.c \ + memmgr.c \ + oleapp.c \ + oledoc.c \ + outlapp.c \ + outldoc.c \ + outlline.c \ + outllist.c \ + outlname.c \ + outlntbl.c \ + outltxtl.c \ + svrbase.c \ + svrpsobj.c \ + status.c \ + tests.c + +UMTYPE= windows +UMENTRY= winmain + +USE_CRTDLL=1 +TARGETLIBS= \ + ..\..\..\ole2ui\daytona\obj\*\ole2u32a.lib \ + ..\..\..\gizmobar\daytona\obj\*\gizmobar.lib \ + ..\..\..\bttncur\daytona\obj\*\bttncur.lib \ + $(BASEDIR)\public\sdk\lib\*\ole32.lib \ + $(BASEDIR)\public\sdk\lib\*\shell32.lib \ + $(BASEDIR)\public\sdk\lib\*\gdi32.lib \ + $(BASEDIR)\public\sdk\lib\*\kernel32.lib \ + $(BASEDIR)\public\sdk\lib\*\user32.lib \ + $(BASEDIR)\public\sdk\lib\*\advapi32.lib \ + $(BASEDIR)\public\sdk\lib\*\comdlg32.lib \ + $(BASEDIR)\public\sdk\lib\*\uuid.lib + +NTTARGETFILE0=copyfiles diff --git a/private/oleutest/letest/outline/svroutl/dirs b/private/oleutest/letest/outline/svroutl/dirs new file mode 100644 index 000000000..515c134a8 --- /dev/null +++ b/private/oleutest/letest/outline/svroutl/dirs @@ -0,0 +1,37 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + dirs. + +Abstract: + + This file specifies the subdirectories of the current directory that + contain component makefiles. + + +Author: + + Donna Liu (DonnaLi) 19-Dec-1993 + +!ENDIF + +# +# This is a list of all subdirectories that build required components. +# Each subdirectory name should appear on a line by itself. The build +# follows the order in which the subdirectories are specified. +# + +DIRS= + +# +# This is a list of all subdirectories that build optional components. +# Each subdirectory name should appear on a line by itself. The build +# follows the order in which the subdirectories are specified. +# + +OPTIONAL_DIRS= \ + \ + daytona diff --git a/private/oleutest/letest/outline/svroutl/svroutl.rc b/private/oleutest/letest/outline/svroutl/svroutl.rc new file mode 100644 index 000000000..224009f2b --- /dev/null +++ b/private/oleutest/letest/outline/svroutl/svroutl.rc @@ -0,0 +1,187 @@ +/************************************************************************* +** +** OLE 2.0 Server Sample Code +** +** svroutl.rc +** +** Resource file for svroutl.exe +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + +#include "windows.h" +#include "outlrc.h" + +SelCur CURSOR selcross.cur +DragMoveCur CURSOR dragmove.cur + +#if defined( IF_SPECIAL_DD_CURSORS_NEEDED ) +DragNoneCur CURSOR dragnone.cur +DragCopyCur CURSOR dragcopy.cur +DragLinkCur CURSOR draglink.cur +#endif // IF_SPECIAL_DD_CURSORS_NEEDED + +SvrOutlMenu MENU + BEGIN + POPUP "&File" + BEGIN + MENUITEM "&New", IDM_F_NEW + MENUITEM "&Open...\t Ctrl+F12", IDM_F_OPEN + MENUITEM "&Save\t Shift+F12", IDM_F_SAVE + MENUITEM "Save &As...\t F12", IDM_F_SAVEAS + MENUITEM SEPARATOR + MENUITEM "&Print...\t Ctrl+Shift+F12", IDM_F_PRINT + MENUITEM "Printer Se&tup...", IDM_F_PRINTERSETUP + MENUITEM SEPARATOR + MENUITEM "E&xit\t Alt+F4", IDM_F_EXIT + END + POPUP "&Edit" + BEGIN + MENUITEM "&Undo", IDM_E_UNDO + MENUITEM SEPARATOR + MENUITEM "Cu&t\t Ctrl+X", IDM_E_CUT + MENUITEM "&Copy\t Ctrl+C", IDM_E_COPY + MENUITEM "&Paste\t Ctrl+V", IDM_E_PASTE + MENUITEM "Paste &Special...", IDM_E_PASTESPECIAL + MENUITEM "Cl&ear\t Del", IDM_E_CLEAR + MENUITEM SEPARATOR + MENUITEM "Select A&ll\t Ctrl+A", IDM_E_SELECTALL + END + POPUP "O&utline" + BEGIN + POPUP "&Zoom" + BEGIN + MENUITEM "&400%", IDM_V_ZOOM_400 + MENUITEM "&300%", IDM_V_ZOOM_300 + MENUITEM "&200%", IDM_V_ZOOM_200 + MENUITEM "&100%", IDM_V_ZOOM_100 + MENUITEM "&75%", IDM_V_ZOOM_75 + MENUITEM "&50%", IDM_V_ZOOM_50 + MENUITEM "&25%", IDM_V_ZOOM_25 + END + POPUP "&Left and Right margins" + BEGIN + MENUITEM "&nil", IDM_V_SETMARGIN_0 + MENUITEM "&1 cm", IDM_V_SETMARGIN_1 + MENUITEM "&2 cm", IDM_V_SETMARGIN_2 + MENUITEM "&3 cm", IDM_V_SETMARGIN_3 + MENUITEM "&4 cm", IDM_V_SETMARGIN_4 + END + POPUP "Add &Top Line" + BEGIN + MENUITEM "&1 cm", IDM_V_ADDTOP_1 + MENUITEM "&2 cm", IDM_V_ADDTOP_2 + MENUITEM "&3 cm", IDM_V_ADDTOP_3 + MENUITEM "&4 cm", IDM_V_ADDTOP_4 + END + END + POPUP "&Line" + BEGIN + MENUITEM "&Add Line\t Enter", IDM_L_ADDLINE + MENUITEM "E&dit Line\t Alt+Enter", IDM_L_EDITLINE + MENUITEM SEPARATOR + MENUITEM "&Indent Line\t Tab", IDM_L_INDENTLINE + MENUITEM "U&nindent Line\t Shift+Tab", IDM_L_UNINDENTLINE + MENUITEM SEPARATOR + MENUITEM "&Set Line Height...", IDM_L_SETLINEHEIGHT + END + POPUP "&Name" + BEGIN + MENUITEM "&Define Name...", IDM_N_DEFINENAME + MENUITEM "&Goto Name...", IDM_N_GOTONAME + END + POPUP "&Options" + BEGIN + POPUP "&Button Bar Display" + BEGIN + MENUITEM "At &Top", IDM_O_BB_TOP + MENUITEM "At &Bottom", IDM_O_BB_BOTTOM + MENUITEM "&Popup", IDM_O_BB_POPUP + MENUITEM "&Hide", IDM_O_BB_HIDE + END + POPUP "&Formula Bar Display" + BEGIN + MENUITEM "At &Top", IDM_O_FB_TOP + MENUITEM "At &Bottom", IDM_O_FB_BOTTOM + MENUITEM "&Popup", IDM_O_FB_POPUP + END + POPUP "&Row and Column Heading" + BEGIN + MENUITEM "&Show", IDM_O_HEAD_SHOW + MENUITEM "&Hide", IDM_O_HEAD_HIDE + END + END + POPUP "Dbg&Svr" + BEGIN + MENUITEM "&Debug Level...", IDM_D_DEBUGLEVEL + MENUITEM "Register Message &Filter", IDM_D_INSTALLMSGFILTER + MENUITEM "&Reject Incoming Messages", IDM_D_REJECTINCOMING + END + POPUP "&Help" + BEGIN + MENUITEM "&About...", IDM_H_ABOUT + END + END + +SvrOutlAccel ACCELERATORS + BEGIN + VK_F12, IDM_F_OPEN, VIRTKEY, CONTROL + VK_F12, IDM_F_SAVE, VIRTKEY, SHIFT + VK_F12, IDM_F_SAVEAS, VIRTKEY + VK_F12, IDM_F_PRINT, VIRTKEY, CONTROL, SHIFT + + "x", IDM_E_CUT, VIRTKEY, CONTROL + "c", IDM_E_COPY, VIRTKEY, CONTROL + "v", IDM_E_PASTE, VIRTKEY, CONTROL + VK_DELETE, IDM_E_CLEAR, VIRTKEY + VK_RETURN, IDM_L_ADDLINE, VIRTKEY + VK_RETURN, IDM_L_EDITLINE, VIRTKEY, ALT + VK_TAB, IDM_L_INDENTLINE, VIRTKEY + VK_TAB, IDM_L_UNINDENTLINE, VIRTKEY, SHIFT + "a", IDM_E_SELECTALL, VIRTKEY, CONTROL + + ; old conventions for editing + VK_INSERT, IDM_E_COPY, VIRTKEY, CONTROL + VK_DELETE, IDM_E_CUT, VIRTKEY, SHIFT + VK_INSERT, IDM_E_PASTE, VIRTKEY, SHIFT + + VK_F2, IDM_F2, VIRTKEY + END + +; Same as SvrOutlAccel but without Delete and Backspace +; used when edit control of Formula Bar in focus +; +SvrOutlAccelFocusEdit ACCELERATORS + BEGIN + VK_F12, IDM_F_OPEN, VIRTKEY, CONTROL + VK_F12, IDM_F_SAVE, VIRTKEY, SHIFT + VK_F12, IDM_F_SAVEAS, VIRTKEY + VK_F12, IDM_F_PRINT, VIRTKEY, CONTROL, SHIFT + + "x", IDM_E_CUT, VIRTKEY, CONTROL + "c", IDM_E_COPY, VIRTKEY, CONTROL + "v", IDM_E_PASTE, VIRTKEY, CONTROL + VK_RETURN, IDM_L_ADDLINE, VIRTKEY + VK_RETURN, IDM_L_EDITLINE, VIRTKEY, ALT + VK_TAB, IDM_L_INDENTLINE, VIRTKEY + VK_TAB, IDM_L_UNINDENTLINE, VIRTKEY, SHIFT + "a", IDM_E_SELECTALL, VIRTKEY, CONTROL + + VK_ESCAPE, IDM_FB_CANCEL, VIRTKEY + + ; old conventions for editing + VK_INSERT, IDM_E_COPY, VIRTKEY, CONTROL + VK_DELETE, IDM_E_CUT, VIRTKEY, SHIFT + VK_INSERT, IDM_E_PASTE, VIRTKEY, SHIFT + END + + +SvrOutlIcon ICON svroutl.ico + +Image72 BITMAP image72.bmp +Image96 BITMAP image96.bmp +Image120 BITMAP image120.bmp +LogoBitmap BITMAP ole2.bmp + +#include "DIALOGS.DLG" diff --git a/private/oleutest/letest/outline/svrpsobj.c b/private/oleutest/letest/outline/svrpsobj.c new file mode 100644 index 000000000..c73f16c89 --- /dev/null +++ b/private/oleutest/letest/outline/svrpsobj.c @@ -0,0 +1,1538 @@ +/************************************************************************* +** +** OLE 2 Server Sample Code +** +** svrpsobj.c +** +** This file contains all PseudoObj methods and related support +** functions. +** +** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved +** +*************************************************************************/ + + +#include "outline.h" + +OLEDBGDATA + +extern LPOUTLINEAPP g_lpApp; +extern IUnknownVtbl g_PseudoObj_UnknownVtbl; +extern IOleObjectVtbl g_PseudoObj_OleObjectVtbl; +extern IDataObjectVtbl g_PseudoObj_DataObjectVtbl; + + +/* PseudoObj_Init +** -------------- +** Initialize fields in a newly constructed PseudoObj. +** NOTE: ref cnt of PseudoObj initialized to 0 +*/ +void PseudoObj_Init( + LPPSEUDOOBJ lpPseudoObj, + LPSERVERNAME lpServerName, + LPSERVERDOC lpServerDoc +) +{ + OleDbgOut2("++PseudoObj Created\r\n"); + + lpPseudoObj->m_cRef = 0; + lpPseudoObj->m_lpName = lpServerName; + lpPseudoObj->m_lpDoc = lpServerDoc; + lpPseudoObj->m_lpOleAdviseHldr = NULL; + lpPseudoObj->m_lpDataAdviseHldr = NULL; + lpPseudoObj->m_fObjIsClosing = FALSE; + + INIT_INTERFACEIMPL( + &lpPseudoObj->m_Unknown, + &g_PseudoObj_UnknownVtbl, + lpPseudoObj + ); + + INIT_INTERFACEIMPL( + &lpPseudoObj->m_OleObject, + &g_PseudoObj_OleObjectVtbl, + lpPseudoObj + ); + + INIT_INTERFACEIMPL( + &lpPseudoObj->m_DataObject, + &g_PseudoObj_DataObjectVtbl, + lpPseudoObj + ); + + /* OLE2NOTE: Increment the refcnt of the Doc on behalf of the + ** PseudoObj. the Document should not shut down unless all + ** pseudo objects are closed. when a pseudo object is destroyed, + ** it calls ServerDoc_PseudoObjUnlockDoc to release this hold on + ** the document. + */ + ServerDoc_PseudoObjLockDoc(lpServerDoc); +} + + + +/* PseudoObj_AddRef +** ---------------- +** +** increment the ref count of the PseudoObj object. +** +** Returns the new ref count on the object +*/ +ULONG PseudoObj_AddRef(LPPSEUDOOBJ lpPseudoObj) +{ + ++lpPseudoObj->m_cRef; + +#if defined( _DEBUG ) + OleDbgOutRefCnt4( + "PseudoObj_AddRef: cRef++\r\n", + lpPseudoObj, + lpPseudoObj->m_cRef + ); +#endif + return lpPseudoObj->m_cRef; +} + + +/* PseudoObj_Release +** ----------------- +** +** decrement the ref count of the PseudoObj object. +** if the ref count goes to 0, then the PseudoObj is destroyed. +** +** Returns the remaining ref count on the object +*/ +ULONG PseudoObj_Release(LPPSEUDOOBJ lpPseudoObj) +{ + ULONG cRef; + + /********************************************************************* + ** OLE2NOTE: when the obj refcnt == 0, then destroy the object. ** + ** otherwise the object is still in use. ** + *********************************************************************/ + + cRef = --lpPseudoObj->m_cRef; + +#if defined( _DEBUG ) + OleDbgAssertSz(lpPseudoObj->m_cRef >= 0,"Release called with cRef == 0"); + + OleDbgOutRefCnt4( + "PseudoObj_Release: cRef--\r\n", lpPseudoObj,cRef); +#endif + + if (cRef == 0) + PseudoObj_Destroy(lpPseudoObj); + + return cRef; +} + + +/* PseudoObj_QueryInterface +** ------------------------ +** +** Retrieve a pointer to an interface on the PseudoObj object. +** +** Returns S_OK if interface is successfully retrieved. +** E_NOINTERFACE if the interface is not supported +*/ +HRESULT PseudoObj_QueryInterface( + LPPSEUDOOBJ lpPseudoObj, + REFIID riid, + LPVOID FAR* lplpvObj +) +{ + SCODE sc = E_NOINTERFACE; + + /* OLE2NOTE: we must make sure to set all out ptr parameters to NULL. */ + *lplpvObj = NULL; + + if (IsEqualIID(riid, &IID_IUnknown)) { + OleDbgOut4("PseudoObj_QueryInterface: IUnknown* RETURNED\r\n"); + + *lplpvObj = (LPVOID) &lpPseudoObj->m_Unknown; + PseudoObj_AddRef(lpPseudoObj); + sc = S_OK; + } + else if (IsEqualIID(riid, &IID_IOleObject)) { + OleDbgOut4("PseudoObj_QueryInterface: IOleObject* RETURNED\r\n"); + + *lplpvObj = (LPVOID) &lpPseudoObj->m_OleObject; + PseudoObj_AddRef(lpPseudoObj); + sc = S_OK; + } + else if (IsEqualIID(riid, &IID_IDataObject)) { + OleDbgOut4("PseudoObj_QueryInterface: IDataObject* RETURNED\r\n"); + + *lplpvObj = (LPVOID) &lpPseudoObj->m_DataObject; + PseudoObj_AddRef(lpPseudoObj); + sc = S_OK; + } + + OleDbgQueryInterfaceMethod(*lplpvObj); + + return ResultFromScode(sc); +} + + +/* PseudoObj_Close + * --------------- + * + * Close the pseudo object. Force all external connections to close + * down. This causes link clients to release this PseudoObj. when + * the refcount actually reaches 0, then the PseudoObj will be + * destroyed. + * + * Returns: + * FALSE -- user canceled the closing of the doc. + * TRUE -- the doc was successfully closed + */ + +BOOL PseudoObj_Close(LPPSEUDOOBJ lpPseudoObj) +{ + LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpPseudoObj->m_lpDoc; + LPSERVERNAME lpServerName = (LPSERVERNAME)lpPseudoObj->m_lpName; + LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; + LPOLEDOC lpOleDoc = (LPOLEDOC)lpServerDoc; + BOOL fStatus = TRUE; + + if (lpPseudoObj->m_fObjIsClosing) + return TRUE; // Closing is already in progress + + lpPseudoObj->m_fObjIsClosing = TRUE; // guard against recursive call + + OLEDBG_BEGIN3("PseudoObj_Close\r\n") + + /* OLE2NOTE: in order to have a stable App, Doc, AND pseudo object + ** during the process of closing, we intially AddRef the App, + ** Doc, and PseudoObj ref counts and later Release them. These + ** initial AddRefs are artificial; they are simply done to + ** guarantee that these objects do not get destroyed until the + ** end of this routine. + */ + OleApp_AddRef(lpOleApp); + OleDoc_AddRef(lpOleDoc); + PseudoObj_AddRef(lpPseudoObj); + + if (lpPseudoObj->m_lpDataAdviseHldr) { + /* OLE2NOTE: send last OnDataChange notification to clients + ** that have registered for data notifications when object + ** stops running (ADVF_DATAONSTOP) + */ + PseudoObj_SendAdvise( + lpPseudoObj, + OLE_ONDATACHANGE, + NULL, /* lpmkObj -- not relevant here */ + ADVF_DATAONSTOP + ); + + /* OLE2NOTE: we just sent the last data notification that we + ** need to send; release our DataAdviseHolder. we SHOULD be + ** the only one using it. + */ + OleStdVerifyRelease( + (LPUNKNOWN)lpPseudoObj->m_lpDataAdviseHldr, + "DataAdviseHldr not released properly" + ); + lpPseudoObj->m_lpDataAdviseHldr = NULL; + } + + if (lpPseudoObj->m_lpOleAdviseHldr) { + // OLE2NOTE: inform all of our linking clients that we are closing. + PseudoObj_SendAdvise( + lpPseudoObj, + OLE_ONCLOSE, + NULL, /* lpmkObj -- not relevant here */ + 0 /* advf -- not relevant here */ + ); + + /* OLE2NOTE: OnClose is the last notification that we need to + ** send; release our OleAdviseHolder. we SHOULD be the only + ** one using it. this will make our destructor realize that + ** OnClose notification has already been sent. + */ + OleStdVerifyRelease( + (LPUNKNOWN)lpPseudoObj->m_lpOleAdviseHldr, + "OleAdviseHldr not released properly" + ); + lpPseudoObj->m_lpOleAdviseHldr = NULL; + } + + /* OLE2NOTE: this call forces all external connections to our + ** object to close down and therefore guarantees that we receive + ** all releases associated with those external connections. + */ + OLEDBG_BEGIN2("CoDisconnectObject called\r\n") + CoDisconnectObject((LPUNKNOWN)&lpPseudoObj->m_Unknown, 0); + OLEDBG_END2 + + PseudoObj_Release(lpPseudoObj); // release artificial AddRef above + OleDoc_Release(lpOleDoc); // release artificial AddRef above + OleApp_Release(lpOleApp); // release artificial AddRef above + + OLEDBG_END3 + return fStatus; +} + + +/* PseudoObj_Destroy +** ----------------- +** Destroy (Free) the memory used by a PseudoObj structure. +** This function is called when the ref count of the PseudoObj goes +** to zero. the ref cnt goes to zero after PseudoObj_Delete forces +** the OleObject to unload and release its pointers to the +** PseudoObj IOleClientSite and IAdviseSink interfaces. +*/ + +void PseudoObj_Destroy(LPPSEUDOOBJ lpPseudoObj) +{ + LPSERVERDOC lpServerDoc = lpPseudoObj->m_lpDoc; + LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; + LPOLEDOC lpOleDoc = (LPOLEDOC)lpServerDoc; + + OLEDBG_BEGIN3("PseudoObj_Destroy\r\n") + + /* OLE2NOTE: in order to have a stable App, Doc, AND pseudo object + ** during the process of closing, we intially AddRef the App, + ** Doc ref counts and later Release them. These + ** initial AddRefs are artificial; they are simply done to + ** guarantee that these objects do not get destroyed until the + ** end of this routine. + */ + OleApp_AddRef(lpOleApp); + OleDoc_AddRef(lpOleDoc); + + /****************************************************************** + ** OLE2NOTE: we no longer need the advise and enum holder objects, + ** so release them. + ******************************************************************/ + + if (lpPseudoObj->m_lpDataAdviseHldr) { + /* release DataAdviseHldr; we SHOULD be the only one using it. */ + OleStdVerifyRelease( + (LPUNKNOWN)lpPseudoObj->m_lpDataAdviseHldr, + "DataAdviseHldr not released properly" + ); + lpPseudoObj->m_lpDataAdviseHldr = NULL; + } + + if (lpPseudoObj->m_lpOleAdviseHldr) { + /* release OleAdviseHldr; we SHOULD be the only one using it. */ + OleStdVerifyRelease( + (LPUNKNOWN)lpPseudoObj->m_lpOleAdviseHldr, + "OleAdviseHldr not released properly" + ); + lpPseudoObj->m_lpOleAdviseHldr = NULL; + } + + /* forget the pointer to destroyed PseudoObj in NameTable */ + if (lpPseudoObj->m_lpName) + lpPseudoObj->m_lpName->m_lpPseudoObj = NULL; + + /* OLE2NOTE: release the lock on the Doc held on behalf of the + ** PseudoObj. the Document should not shut down unless all + ** pseudo objects are closed. when a pseudo object is first + ** created, it calls ServerDoc_PseudoObjLockDoc to guarantee + ** that the document stays alive (called from PseudoObj_Init). + */ + ServerDoc_PseudoObjUnlockDoc(lpServerDoc, lpPseudoObj); + + Delete(lpPseudoObj); // Free the memory for the structure itself + + OleDoc_Release(lpOleDoc); // release artificial AddRef above + OleApp_Release(lpOleApp); // release artificial AddRef above + + OLEDBG_END3 +} + + +/* PseudoObj_GetSel +** ---------------- +** Return the line range for the pseudo object +*/ +void PseudoObj_GetSel(LPPSEUDOOBJ lpPseudoObj, LPLINERANGE lplrSel) +{ + LPOUTLINENAME lpOutlineName = (LPOUTLINENAME)lpPseudoObj->m_lpName; + lplrSel->m_nStartLine = lpOutlineName->m_nStartLine; + lplrSel->m_nEndLine = lpOutlineName->m_nEndLine; +} + + +/* PseudoObj_GetExtent + * ------------------- + * + * Get the extent (width, height) of the entire document. + */ +void PseudoObj_GetExtent(LPPSEUDOOBJ lpPseudoObj, LPSIZEL lpsizel) +{ + LPOLEDOC lpOleDoc = (LPOLEDOC)lpPseudoObj->m_lpDoc; + LPLINELIST lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList; + LINERANGE lrSel; + + PseudoObj_GetSel(lpPseudoObj, (LPLINERANGE)&lrSel); + + LineList_CalcSelExtentInHimetric(lpLL, (LPLINERANGE)&lrSel, lpsizel); +} + + +/* PseudoObj_SendAdvise + * -------------------- + * + * This function sends an advise notification on behalf of a specific + * doc object to all its clients. + */ +void PseudoObj_SendAdvise( + LPPSEUDOOBJ lpPseudoObj, + WORD wAdvise, + LPMONIKER lpmkObj, + DWORD dwAdvf +) +{ + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpPseudoObj->m_lpDoc; + + switch (wAdvise) { + + case OLE_ONDATACHANGE: + + // inform clients that the data of the object has changed + + if (lpOutlineDoc->m_nDisableDraw == 0) { + /* drawing is currently enabled. inform clients that + ** the data of the object has changed + */ + + lpPseudoObj->m_fDataChanged = FALSE; + if (lpPseudoObj->m_lpDataAdviseHldr) { + + OLEDBG_BEGIN2("IDataAdviseHolder::SendOnDataChange called\r\n"); + lpPseudoObj->m_lpDataAdviseHldr->lpVtbl->SendOnDataChange( + lpPseudoObj->m_lpDataAdviseHldr, + (LPDATAOBJECT)&lpPseudoObj->m_DataObject, + 0, + dwAdvf + ); + OLEDBG_END2 + } + + } else { + /* drawing is currently disabled. do not send + ** notifications until drawing is re-enabled. + */ + lpPseudoObj->m_fDataChanged = TRUE; + } + break; + + case OLE_ONCLOSE: + + // inform clients that the object is shutting down + + if (lpPseudoObj->m_lpOleAdviseHldr) { + + OLEDBG_BEGIN2("IOleAdviseHolder::SendOnClose called\r\n"); + lpPseudoObj->m_lpOleAdviseHldr->lpVtbl->SendOnClose( + lpPseudoObj->m_lpOleAdviseHldr + ); + OLEDBG_END2 + } + break; + + case OLE_ONSAVE: + + // inform clients that the object has been saved + + if (lpPseudoObj->m_lpOleAdviseHldr) { + + OLEDBG_BEGIN2("IOleAdviseHolder::SendOnClose called\r\n"); + lpPseudoObj->m_lpOleAdviseHldr->lpVtbl->SendOnSave( + lpPseudoObj->m_lpOleAdviseHldr + ); + OLEDBG_END2 + } + break; + + case OLE_ONRENAME: + + // inform clients that the object's name has changed + if (lpmkObj && lpPseudoObj->m_lpOleAdviseHldr) { + + OLEDBG_BEGIN2("IOleAdviseHolder::SendOnRename called\r\n"); + if (lpPseudoObj->m_lpOleAdviseHldr) + lpPseudoObj->m_lpOleAdviseHldr->lpVtbl->SendOnRename( + lpPseudoObj->m_lpOleAdviseHldr, + lpmkObj + ); + OLEDBG_END2 + } + break; + } +} + + +/* PseudoObj_GetFullMoniker + * ------------------------ + * + * Returns the Full, absolute Moniker which identifies this pseudo object. + */ +LPMONIKER PseudoObj_GetFullMoniker(LPPSEUDOOBJ lpPseudoObj, LPMONIKER lpmkDoc) +{ + LPOUTLINENAME lpOutlineName = (LPOUTLINENAME)lpPseudoObj->m_lpName; + LPMONIKER lpmkItem = NULL; + LPMONIKER lpmkPseudoObj = NULL; + + if (lpmkDoc != NULL) { + CreateItemMonikerA(OLESTDDELIM,lpOutlineName->m_szName,&lpmkItem); + + /* OLE2NOTE: create an absolute moniker which identifies the + ** pseudo object. this moniker is created as a composite of + ** the absolute moniker for the entire document appended + ** with an item moniker which identifies the selection of + ** the pseudo object relative to the document. + */ + CreateGenericComposite(lpmkDoc, lpmkItem, &lpmkPseudoObj); + + if (lpmkItem) + OleStdRelease((LPUNKNOWN)lpmkItem); + + return lpmkPseudoObj; + } else { + return NULL; + } +} + + +/************************************************************************* +** PseudoObj::IUnknown interface implementation +*************************************************************************/ + +STDMETHODIMP PseudoObj_Unk_QueryInterface( + LPUNKNOWN lpThis, + REFIID riid, + LPVOID FAR* lplpvObj +) +{ + LPPSEUDOOBJ lpPseudoObj = + ((struct CPseudoObjUnknownImpl FAR*)lpThis)->lpPseudoObj; + + return PseudoObj_QueryInterface(lpPseudoObj, riid, lplpvObj); +} + + +STDMETHODIMP_(ULONG) PseudoObj_Unk_AddRef(LPUNKNOWN lpThis) +{ + LPPSEUDOOBJ lpPseudoObj = + ((struct CPseudoObjUnknownImpl FAR*)lpThis)->lpPseudoObj; + + OleDbgAddRefMethod(lpThis, "IUnknown"); + + return PseudoObj_AddRef(lpPseudoObj); +} + + +STDMETHODIMP_(ULONG) PseudoObj_Unk_Release (LPUNKNOWN lpThis) +{ + LPPSEUDOOBJ lpPseudoObj = + ((struct CPseudoObjUnknownImpl FAR*)lpThis)->lpPseudoObj; + + OleDbgReleaseMethod(lpThis, "IUnknown"); + + return PseudoObj_Release(lpPseudoObj); +} + + +/************************************************************************* +** PseudoObj::IOleObject interface implementation +*************************************************************************/ + +STDMETHODIMP PseudoObj_OleObj_QueryInterface( + LPOLEOBJECT lpThis, + REFIID riid, + LPVOID FAR* lplpvObj +) +{ + LPPSEUDOOBJ lpPseudoObj = + ((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj; + + return PseudoObj_QueryInterface(lpPseudoObj, riid, lplpvObj); +} + + +STDMETHODIMP_(ULONG) PseudoObj_OleObj_AddRef(LPOLEOBJECT lpThis) +{ + LPPSEUDOOBJ lpPseudoObj = + ((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj; + + OleDbgAddRefMethod(lpThis, "IOleObject"); + + return PseudoObj_AddRef((LPPSEUDOOBJ)lpPseudoObj); +} + + +STDMETHODIMP_(ULONG) PseudoObj_OleObj_Release(LPOLEOBJECT lpThis) +{ + LPPSEUDOOBJ lpPseudoObj = + ((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj; + + OleDbgReleaseMethod(lpThis, "IOleObject"); + + return PseudoObj_Release((LPPSEUDOOBJ)lpPseudoObj); +} + + +STDMETHODIMP PseudoObj_OleObj_SetClientSite( + LPOLEOBJECT lpThis, + LPOLECLIENTSITE lpClientSite +) +{ + OleDbgOut2("PseudoObj_OleObj_SetClientSite\r\n"); + + // OLE2NOTE: a pseudo object does NOT support SetExtent + + return ResultFromScode(E_FAIL); +} + + +STDMETHODIMP PseudoObj_OleObj_GetClientSite( + LPOLEOBJECT lpThis, + LPOLECLIENTSITE FAR* lplpClientSite +) +{ + OleDbgOut2("PseudoObj_OleObj_GetClientSite\r\n"); + + *lplpClientSite = NULL; + + // OLE2NOTE: a pseudo object does NOT support SetExtent + + return ResultFromScode(E_FAIL); +} + + + +STDMETHODIMP PseudoObj_OleObj_SetHostNamesA( + LPOLEOBJECT lpThis, + LPCSTR szContainerApp, + LPCSTR szContainerObj +) +{ + OleDbgOut2("PseudoObj_OleObj_SetHostNamesA\r\n"); + + // OLE2NOTE: a pseudo object does NOT support SetExtent + + return ResultFromScode(E_FAIL); +} + + +STDMETHODIMP PseudoObj_OleObj_SetHostNames( + LPOLEOBJECT lpThis, + LPCOLESTR szContainerApp, + LPCOLESTR szContainerObj +) +{ + OleDbgOut2("PseudoObj_OleObj_SetHostNames\r\n"); + + // OLE2NOTE: a pseudo object does NOT support SetExtent + + return ResultFromScode(E_FAIL); +} + + +STDMETHODIMP PseudoObj_OleObj_Close( + LPOLEOBJECT lpThis, + DWORD dwSaveOption +) +{ + LPPSEUDOOBJ lpPseudoObj = + ((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj; + BOOL fStatus; + + OLEDBG_BEGIN2("PseudoObj_OleObj_Close\r\n") + + /* OLE2NOTE: a pseudo object's implementation of IOleObject::Close + ** should ignore the dwSaveOption parameter. it is NOT + ** applicable to pseudo objects. + */ + + fStatus = PseudoObj_Close(lpPseudoObj); + OleDbgAssertSz(fStatus == TRUE, "PseudoObj_OleObj_Close failed\r\n"); + + OLEDBG_END2 + return NOERROR; +} + + +STDMETHODIMP PseudoObj_OleObj_SetMoniker( + LPOLEOBJECT lpThis, + DWORD dwWhichMoniker, + LPMONIKER lpmk +) +{ + OleDbgOut2("PseudoObj_OleObj_SetMoniker\r\n"); + + // OLE2NOTE: a pseudo object does NOT support SetMoniker + + return ResultFromScode(E_FAIL); +} + + +STDMETHODIMP PseudoObj_OleObj_GetMoniker( + LPOLEOBJECT lpThis, + DWORD dwAssign, + DWORD dwWhichMoniker, + LPMONIKER FAR* lplpmk +) +{ + LPPSEUDOOBJ lpPseudoObj = + ((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj; + LPOLEDOC lpOleDoc = (LPOLEDOC)lpPseudoObj->m_lpDoc; + LPMONIKER lpmkDoc; + + OLEDBG_BEGIN2("PseudoObj_OleObj_GetMoniker\r\n") + + lpmkDoc = OleDoc_GetFullMoniker(lpOleDoc, GETMONIKER_ONLYIFTHERE); + *lplpmk = PseudoObj_GetFullMoniker(lpPseudoObj, lpmkDoc); + + OLEDBG_END2 + + if (*lplpmk != NULL) + return NOERROR; + else + return ResultFromScode(E_FAIL); +} + + +STDMETHODIMP PseudoObj_OleObj_InitFromData( + LPOLEOBJECT lpThis, + LPDATAOBJECT lpDataObject, + BOOL fCreation, + DWORD reserved +) +{ + LPPSEUDOOBJ lpPseudoObj = + ((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj; + OleDbgOut2("PseudoObj_OleObj_InitFromData\r\n"); + + // REVIEW: NOT YET IMPLEMENTED + + return ResultFromScode(E_NOTIMPL); +} + + +STDMETHODIMP PseudoObj_OleObj_GetClipboardData( + LPOLEOBJECT lpThis, + DWORD reserved, + LPDATAOBJECT FAR* lplpDataObject +) +{ + LPPSEUDOOBJ lpPseudoObj = + ((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj; + OleDbgOut2("PseudoObj_OleObj_GetClipboardData\r\n"); + + // REVIEW: NOT YET IMPLEMENTED + + return ResultFromScode(E_NOTIMPL); +} + + +STDMETHODIMP PseudoObj_OleObj_DoVerb( + LPOLEOBJECT lpThis, + LONG lVerb, + LPMSG lpmsg, + LPOLECLIENTSITE lpActiveSite, + LONG lindex, + HWND hwndParent, + LPCRECT lprcPosRect +) +{ + LPPSEUDOOBJ lpPseudoObj = + ((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpPseudoObj->m_lpDoc; + LPSERVERDOC lpServerDoc = lpPseudoObj->m_lpDoc; + LINERANGE lrSel; + HRESULT hrErr; + + OLEDBG_BEGIN2("PseudoObj_OleObj_DoVerb\r\n"); + + /* OLE2NOTE: we must first ask our Document to perform the same + ** verb. then if the verb is NOT OLEIVERB_HIDE we should also + ** select the range of our pseudo object. + ** however, we must give our document its own embedding site as + ** its active site. + */ + hrErr = SvrDoc_OleObj_DoVerb( + (LPOLEOBJECT)&lpServerDoc->m_OleObject, + lVerb, + lpmsg, + lpServerDoc->m_lpOleClientSite, + lindex, + NULL, /* we have no hwndParent to give */ + NULL /* we have no lprcPosRect to give */ + ); + if (FAILED(hrErr)) { + OLEDBG_END2 + return hrErr; + } + + if (lVerb != OLEIVERB_HIDE) { + PseudoObj_GetSel(lpPseudoObj, &lrSel); + OutlineDoc_SetSel(lpOutlineDoc, &lrSel); + } + + OLEDBG_END2 + return NOERROR; +} + + + +STDMETHODIMP PseudoObj_OleObj_EnumVerbs( + LPOLEOBJECT lpThis, + LPENUMOLEVERB FAR* lplpenumOleVerb +) +{ + OleDbgOut2("PseudoObj_OleObj_EnumVerbs\r\n"); + + /* OLE2NOTE: we must make sure to set all out parameters to NULL. */ + *lplpenumOleVerb = NULL; + + /* A pseudo object may NOT return OLE_S_USEREG; they must call the + ** OleReg* API or provide their own implementation. Because this + ** pseudo object does NOT implement IPersist, simply a low-level + ** remoting handler (ProxyManager) object as opposed to a + ** DefHandler object is used as the handler for the pseudo + ** object in a clients process space. The ProxyManager does NOT + ** handle the OLE_S_USEREG return values. + */ + return OleRegEnumVerbs((REFCLSID)&CLSID_APP, lplpenumOleVerb); +} + + +STDMETHODIMP PseudoObj_OleObj_Update(LPOLEOBJECT lpThis) +{ + OleDbgOut2("PseudoObj_OleObj_Update\r\n"); + + /* OLE2NOTE: a server-only app is always "up-to-date". + ** a container-app which contains links where the link source + ** has changed since the last update of the link would be + ** considered "out-of-date". the "Update" method instructs the + ** object to get an update from any out-of-date links. + */ + + return NOERROR; +} + + +STDMETHODIMP PseudoObj_OleObj_IsUpToDate(LPOLEOBJECT lpThis) +{ + LPPSEUDOOBJ lpPseudoObj = + ((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj; + OleDbgOut2("PseudoObj_OleObj_IsUpToDate\r\n"); + + /* OLE2NOTE: a server-only app is always "up-to-date". + ** a container-app which contains links where the link source + ** has changed since the last update of the link would be + ** considered "out-of-date". + */ + return NOERROR; +} + + +STDMETHODIMP PseudoObj_OleObj_GetUserClassID( + LPOLEOBJECT lpThis, + LPCLSID lpclsid +) +{ + LPPSEUDOOBJ lpPseudoObj = + ((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj; + LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpPseudoObj->m_lpDoc; + OleDbgOut2("PseudoObj_OleObj_GetUserClassID\r\n"); + + /* OLE2NOTE: we must be carefull to return the correct CLSID here. + ** if we are currently preforming a "TreatAs (aka. ActivateAs)" + ** operation then we need to return the class of the object + ** written in the storage of the object. otherwise we would + ** return our own class id. + */ + return ServerDoc_GetClassID(lpServerDoc, lpclsid); +} + + +STDMETHODIMP PseudoObj_OleObj_GetUserTypeA( + LPOLEOBJECT lpThis, + DWORD dwFormOfType, + LPSTR FAR* lpszUserType +) +{ + LPPSEUDOOBJ lpPseudoObj = + ((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj; + LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpPseudoObj->m_lpDoc; + OleDbgOut2("PseudoObj_OleObj_GetUserType\r\n"); + + /* OLE2NOTE: we must make sure to set all out parameters to NULL. */ + *lpszUserType = NULL; + + /* OLE2NOTE: we must be carefull to return the correct user type here. + ** if we are currently preforming a "TreatAs (aka. ActivateAs)" + ** operation then we need to return the user type name that + ** corresponds to the class of the object we are currently + ** emmulating. otherwise we should return our normal user type + ** name corresponding to our own class. This routine determines + ** the current clsid in effect. + ** + ** A pseudo object may NOT return OLE_S_USEREG; they must call the + ** OleReg* API or provide their own implementation. Because this + ** pseudo object does NOT implement IPersist, simply a low-level + ** remoting handler (ProxyManager) object as opposed to a + ** DefHandler object is used as the handler for the pseudo + ** object in a clients process space. The ProxyManager does NOT + ** handle the OLE_S_USEREG return values. + */ +#if defined( SVR_TREATAS ) + if (! IsEqualCLSID(&lpServerDoc->m_clsidTreatAs, &CLSID_NULL) ) + return OleRegGetUserTypeA( + &lpServerDoc->m_clsidTreatAs,dwFormOfType,lpszUserType); + else +#endif // SVR_TREATAS + + return OleRegGetUserTypeA(&CLSID_APP, dwFormOfType, lpszUserType); +} + +STDMETHODIMP PseudoObj_OleObj_GetUserType( + LPOLEOBJECT lpThis, + DWORD dwFormOfType, + LPOLESTR FAR* lpszUserType +) +{ + LPSTR pstr; + + HRESULT hr = PseudoObj_OleObj_GetUserTypeA(lpThis, dwFormOfType, &pstr); + + CopyAndFreeSTR(pstr, lpszUserType); + + return hr; +} + + + +STDMETHODIMP PseudoObj_OleObj_SetExtent( + LPOLEOBJECT lpThis, + DWORD dwDrawAspect, + LPSIZEL lplgrc +) +{ + OleDbgOut2("PseudoObj_OleObj_SetExtent\r\n"); + + // OLE2NOTE: a pseudo object does NOT support SetExtent + + return ResultFromScode(E_FAIL); +} + + +STDMETHODIMP PseudoObj_OleObj_GetExtent( + LPOLEOBJECT lpThis, + DWORD dwDrawAspect, + LPSIZEL lpsizel +) +{ + LPPSEUDOOBJ lpPseudoObj = + ((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj; + OleDbgOut2("PseudoObj_OleObj_GetExtent\r\n"); + + /* OLE2NOTE: it is VERY important to check which aspect the caller + ** is asking about. an object implemented by a server EXE MAY + ** fail to return extents when asked for DVASPECT_ICON. + */ + if (dwDrawAspect == DVASPECT_CONTENT) { + PseudoObj_GetExtent(lpPseudoObj, lpsizel); + return NOERROR; + } + else + { + return ResultFromScode(E_FAIL); + } +} + + +STDMETHODIMP PseudoObj_OleObj_Advise( + LPOLEOBJECT lpThis, + LPADVISESINK lpAdvSink, + LPDWORD lpdwConnection +) +{ + LPPSEUDOOBJ lpPseudoObj = + ((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj; + HRESULT hrErr; + SCODE sc; + OLEDBG_BEGIN2("PseudoObj_OleObj_Advise\r\n"); + + if (lpPseudoObj->m_lpOleAdviseHldr == NULL && + CreateOleAdviseHolder(&lpPseudoObj->m_lpOleAdviseHldr) != NOERROR) { + sc = E_OUTOFMEMORY; + goto error; + } + + OLEDBG_BEGIN2("IOleAdviseHolder::Advise called\r\n") + hrErr = lpPseudoObj->m_lpOleAdviseHldr->lpVtbl->Advise( + lpPseudoObj->m_lpOleAdviseHldr, + lpAdvSink, + lpdwConnection + ); + OLEDBG_END2 + + OLEDBG_END2 + return hrErr; + +error: + OLEDBG_END2 + return ResultFromScode(sc); +} + + +STDMETHODIMP PseudoObj_OleObj_Unadvise(LPOLEOBJECT lpThis, DWORD dwConnection) +{ + LPPSEUDOOBJ lpPseudoObj = + ((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj; + HRESULT hrErr; + SCODE sc; + + OLEDBG_BEGIN2("PseudoObj_OleObj_Unadvise\r\n"); + + if (lpPseudoObj->m_lpOleAdviseHldr == NULL) { + sc = E_FAIL; + goto error; + } + + OLEDBG_BEGIN2("IOleAdviseHolder::Unadvise called\r\n") + hrErr = lpPseudoObj->m_lpOleAdviseHldr->lpVtbl->Unadvise( + lpPseudoObj->m_lpOleAdviseHldr, + dwConnection + ); + OLEDBG_END2 + + OLEDBG_END2 + return hrErr; + +error: + OLEDBG_END2 + return ResultFromScode(sc); +} + + +STDMETHODIMP PseudoObj_OleObj_EnumAdvise( + LPOLEOBJECT lpThis, + LPENUMSTATDATA FAR* lplpenumAdvise +) +{ + LPPSEUDOOBJ lpPseudoObj = + ((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj; + HRESULT hrErr; + SCODE sc; + + OLEDBG_BEGIN2("PseudoObj_OleObj_EnumAdvise\r\n"); + + /* OLE2NOTE: we must make sure to set all out parameters to NULL. */ + *lplpenumAdvise = NULL; + + if (lpPseudoObj->m_lpOleAdviseHldr == NULL) { + sc = E_FAIL; + goto error; + } + + OLEDBG_BEGIN2("IOleAdviseHolder::EnumAdvise called\r\n") + hrErr = lpPseudoObj->m_lpOleAdviseHldr->lpVtbl->EnumAdvise( + lpPseudoObj->m_lpOleAdviseHldr, + lplpenumAdvise + ); + OLEDBG_END2 + + OLEDBG_END2 + return hrErr; + +error: + OLEDBG_END2 + return ResultFromScode(sc); +} + + +STDMETHODIMP PseudoObj_OleObj_GetMiscStatus( + LPOLEOBJECT lpThis, + DWORD dwAspect, + DWORD FAR* lpdwStatus +) +{ + LPPSEUDOOBJ lpPseudoObj = + ((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpPseudoObj->m_lpDoc; + OleDbgOut2("PseudoObj_OleObj_GetMiscStatus\r\n"); + + /* Get our default MiscStatus for the given Aspect. this + ** information is registered in the RegDB. We query the RegDB + ** here to guarantee that the value returned from this method + ** agrees with the values in RegDB. in this way we only have to + ** maintain the info in one place (in the RegDB). Alternatively + ** we could have the values hard coded here. + ** + ** OLE2NOTE: A pseudo object may NOT return OLE_S_USEREG; they must + ** call the + ** OleReg* API or provide their own implementation. Because this + ** pseudo object does NOT implement IPersist, simply a low-level + ** remoting handler (ProxyManager) object as opposed to a + ** DefHandler object is used as the handler for the pseudo + ** object in a clients process space. The ProxyManager does NOT + ** handle the OLE_S_USEREG return values. + */ + OleRegGetMiscStatus((REFCLSID)&CLSID_APP, dwAspect, lpdwStatus); + + /* OLE2NOTE: check if the pseudo object is compatible to be + ** linked by an OLE 1.0 container. it is compatible if + ** either the pseudo object is an untitled document or a + ** file-based document. if the pseudo object is part of + ** an embedded object, then it is NOT compatible to be + ** linked by an OLE 1.0 container. if it is compatible then + ** we should include OLEMISC_CANLINKBYOLE1 as part of the + ** dwStatus flags. + */ + if (lpOutlineDoc->m_docInitType == DOCTYPE_NEW || + lpOutlineDoc->m_docInitType == DOCTYPE_FROMFILE) + *lpdwStatus |= OLEMISC_CANLINKBYOLE1; + + return NOERROR; +} + + +STDMETHODIMP PseudoObj_OleObj_SetColorScheme( + LPOLEOBJECT lpThis, + LPLOGPALETTE lpLogpal +) +{ + OleDbgOut2("PseudoObj_OleObj_SetColorScheme\r\n"); + + // REVIEW: NOT YET IMPLEMENTED + + return ResultFromScode(E_NOTIMPL); +} + + +/************************************************************************* +** PseudoObj::IDataObject interface implementation +*************************************************************************/ + +STDMETHODIMP PseudoObj_DataObj_QueryInterface ( + LPDATAOBJECT lpThis, + REFIID riid, + LPVOID FAR* lplpvObj +) +{ + LPPSEUDOOBJ lpPseudoObj = + ((struct CPseudoObjDataObjectImpl FAR*)lpThis)->lpPseudoObj; + + return PseudoObj_QueryInterface(lpPseudoObj, riid, lplpvObj); +} + + +STDMETHODIMP_(ULONG) PseudoObj_DataObj_AddRef(LPDATAOBJECT lpThis) +{ + LPPSEUDOOBJ lpPseudoObj = + ((struct CPseudoObjDataObjectImpl FAR*)lpThis)->lpPseudoObj; + + OleDbgAddRefMethod(lpThis, "IDataObject"); + + return PseudoObj_AddRef((LPPSEUDOOBJ)lpPseudoObj); +} + + +STDMETHODIMP_(ULONG) PseudoObj_DataObj_Release (LPDATAOBJECT lpThis) +{ + LPPSEUDOOBJ lpPseudoObj = + ((struct CPseudoObjDataObjectImpl FAR*)lpThis)->lpPseudoObj; + + OleDbgReleaseMethod(lpThis, "IDataObject"); + + return PseudoObj_Release((LPPSEUDOOBJ)lpPseudoObj); +} + + +STDMETHODIMP PseudoObj_DataObj_GetData ( + LPDATAOBJECT lpThis, + LPFORMATETC lpformatetc, + LPSTGMEDIUM lpMedium +) +{ + LPPSEUDOOBJ lpPseudoObj = + ((struct CPseudoObjDataObjectImpl FAR*)lpThis)->lpPseudoObj; + LPSERVERDOC lpServerDoc = lpPseudoObj->m_lpDoc; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; + LPSERVERAPP lpServerApp = (LPSERVERAPP)g_lpApp; + LPOLEAPP lpOleApp = (LPOLEAPP)lpServerApp; + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpServerApp; + LINERANGE lrSel; + SCODE sc = S_OK; + OLEDBG_BEGIN2("PseudoObj_DataObj_GetData\r\n") + + PseudoObj_GetSel(lpPseudoObj, &lrSel); + + /* OLE2NOTE: we must make sure to set all out parameters to NULL. */ + lpMedium->tymed = TYMED_NULL; + lpMedium->pUnkForRelease = NULL; // we transfer ownership to caller + lpMedium->hGlobal = NULL; + + if (lpformatetc->cfFormat == lpOutlineApp->m_cfOutline) { + // Verify caller asked for correct medium + if (!(lpformatetc->tymed & TYMED_HGLOBAL)) { + sc = DATA_E_FORMATETC; + goto error; + } + + lpMedium->hGlobal = OutlineDoc_GetOutlineData (lpOutlineDoc,&lrSel); + if (! lpMedium->hGlobal) return ResultFromScode(E_OUTOFMEMORY); + lpMedium->tymed = TYMED_HGLOBAL; + OleDbgOut3("PseudoObj_DataObj_GetData: rendered CF_OUTLINE\r\n"); + + } else if(lpformatetc->cfFormat == CF_METAFILEPICT && + (lpformatetc->dwAspect & DVASPECT_CONTENT) ) { + // Verify caller asked for correct medium + if (!(lpformatetc->tymed & TYMED_MFPICT)) { + sc = DATA_E_FORMATETC; + goto error; + } + + lpMedium->hGlobal=ServerDoc_GetMetafilePictData(lpServerDoc,&lrSel); + if (! lpMedium->hGlobal) { + sc = E_OUTOFMEMORY; + goto error; + } + lpMedium->tymed = TYMED_MFPICT; + OleDbgOut3("PseudoObj_DataObj_GetData: rendered CF_METAFILEPICT\r\n"); + + } else if (lpformatetc->cfFormat == CF_METAFILEPICT && + (lpformatetc->dwAspect & DVASPECT_ICON) ) { + CLSID clsid; + // Verify caller asked for correct medium + if (!(lpformatetc->tymed & TYMED_MFPICT)) { + sc = DATA_E_FORMATETC; + goto error; + } + + /* OLE2NOTE: we should return the default icon for our class. + ** we must be carefull to use the correct CLSID here. + ** if we are currently preforming a "TreatAs (aka. ActivateAs)" + ** operation then we need to use the class of the object + ** written in the storage of the object. otherwise we would + ** use our own class id. + */ + if (ServerDoc_GetClassID(lpServerDoc, (LPCLSID)&clsid) != NOERROR) { + sc = DATA_E_FORMATETC; + goto error; + } + + lpMedium->hGlobal=GetIconOfClass( + g_lpApp->m_hInst,(REFCLSID)&clsid, NULL, FALSE); + if (! lpMedium->hGlobal) { + sc = E_OUTOFMEMORY; + goto error; + } + + lpMedium->tymed = TYMED_MFPICT; + OleDbgOut3("PseudoObj_DataObj_GetData: rendered CF_METAFILEPICT (icon)\r\n"); + return NOERROR; + + } else if (lpformatetc->cfFormat == CF_TEXT) { + // Verify caller asked for correct medium + if (!(lpformatetc->tymed & TYMED_HGLOBAL)) { + sc = DATA_E_FORMATETC; + goto error; + } + + lpMedium->hGlobal = OutlineDoc_GetTextData (lpOutlineDoc, &lrSel); + if (! lpMedium->hGlobal) { + sc = E_OUTOFMEMORY; + goto error; + } + lpMedium->tymed = TYMED_HGLOBAL; + OleDbgOut3("PseudoObj_DataObj_GetData: rendered CF_TEXT\r\n"); + + } else { + sc = DATA_E_FORMATETC; + goto error; + } + + OLEDBG_END2 + return NOERROR; + +error: + OLEDBG_END2 + return ResultFromScode(sc); +} + + +STDMETHODIMP PseudoObj_DataObj_GetDataHere ( + LPDATAOBJECT lpThis, + LPFORMATETC lpformatetc, + LPSTGMEDIUM lpMedium +) +{ + LPPSEUDOOBJ lpPseudoObj = + ((struct CPseudoObjDataObjectImpl FAR*)lpThis)->lpPseudoObj; + LPSERVERDOC lpServerDoc = lpPseudoObj->m_lpDoc; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; + LPSERVERAPP lpServerApp = (LPSERVERAPP)g_lpApp; + LPOLEAPP lpOleApp = (LPOLEAPP)lpServerApp; + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpServerApp; + OleDbgOut("PseudoObj_DataObj_GetDataHere\r\n"); + + /* Caller is requesting data to be returned in Caller allocated + ** medium, but we do NOT support this. we only support + ** global memory blocks that WE allocate for the caller. + */ + return ResultFromScode(DATA_E_FORMATETC); +} + + +STDMETHODIMP PseudoObj_DataObj_QueryGetData ( + LPDATAOBJECT lpThis, + LPFORMATETC lpformatetc +) +{ + LPPSEUDOOBJ lpPseudoObj = + ((struct CPseudoObjDataObjectImpl FAR*)lpThis)->lpPseudoObj; + LPSERVERDOC lpServerDoc = lpPseudoObj->m_lpDoc; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; + LPSERVERAPP lpServerApp = (LPSERVERAPP)g_lpApp; + LPOLEAPP lpOleApp = (LPOLEAPP)lpServerApp; + LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpServerApp; + OleDbgOut2("PseudoObj_DataObj_QueryGetData\r\n"); + + /* Caller is querying if we support certain format but does not + ** want any data actually returned. + */ + if (lpformatetc->cfFormat == CF_METAFILEPICT && + (lpformatetc->dwAspect & (DVASPECT_CONTENT | DVASPECT_ICON)) ) { + return OleStdQueryFormatMedium(lpformatetc, TYMED_MFPICT); + + } else if (lpformatetc->cfFormat == (lpOutlineApp)->m_cfOutline || + lpformatetc->cfFormat == CF_TEXT) { + return OleStdQueryFormatMedium(lpformatetc, TYMED_HGLOBAL); + } + + return ResultFromScode(DATA_E_FORMATETC); +} + + +STDMETHODIMP PseudoObj_DataObj_GetCanonicalFormatEtc( + LPDATAOBJECT lpThis, + LPFORMATETC lpformatetc, + LPFORMATETC lpformatetcOut +) +{ + HRESULT hrErr; + OleDbgOut2("PseudoObj_DataObj_GetCanonicalFormatEtc\r\n"); + + if (!lpformatetcOut) + return ResultFromScode(E_INVALIDARG); + + /* OLE2NOTE: we must make sure to set all out parameters to NULL. */ + lpformatetcOut->ptd = NULL; + + if (!lpformatetc) + return ResultFromScode(E_INVALIDARG); + + // OLE2NOTE: we must validate that the format requested is supported + if ((hrErr=lpThis->lpVtbl->QueryGetData(lpThis,lpformatetc)) != NOERROR) + return hrErr; + + /* OLE2NOTE: an app that is insensitive to target device (as the + ** Outline Sample is) should fill in the lpformatOut parameter + ** but NULL out the "ptd" field; it should return NOERROR if the + ** input formatetc->ptd what non-NULL. this tells the caller + ** that it is NOT necessary to maintain a separate screen + ** rendering and printer rendering. if should return + ** DATA_S_SAMEFORMATETC if the input and output formatetc's are + ** identical. + */ + + *lpformatetcOut = *lpformatetc; + if (lpformatetc->ptd == NULL) + return ResultFromScode(DATA_S_SAMEFORMATETC); + else { + lpformatetcOut->ptd = NULL; + return NOERROR; + } +} + + +STDMETHODIMP PseudoObj_DataObj_SetData ( + LPDATAOBJECT lpThis, + LPFORMATETC lpformatetc, + LPSTGMEDIUM lpmedium, + BOOL fRelease +) +{ + LPPSEUDOOBJ lpPseudoObj = + ((struct CPseudoObjDataObjectImpl FAR*)lpThis)->lpPseudoObj; + LPSERVERDOC lpServerDoc = lpPseudoObj->m_lpDoc; + LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; + LPSERVERAPP lpServerApp = (LPSERVERAPP)g_lpApp; + + OleDbgOut2("PseudoObj_DataObj_SetData\r\n"); + + // REVIEW: NOT-YET-IMPLEMENTED + return ResultFromScode(E_NOTIMPL); +} + + +STDMETHODIMP PseudoObj_DataObj_EnumFormatEtc( + LPDATAOBJECT lpThis, + DWORD dwDirection, + LPENUMFORMATETC FAR* lplpenumFormatEtc +) +{ + SCODE sc; + OleDbgOut2("PseudoObj_DataObj_EnumFormatEtc\r\n"); + + /* OLE2NOTE: a pseudo object only needs to enumerate the static list + ** of formats that are registered for our app in the + ** registration database. it is NOT + ** required that a pseudo object (ie. non-DataTransferDoc) + ** enumerate the OLE formats: CF_LINKSOURCE, CF_EMBEDSOURCE, or + ** CF_EMBEDDEDOBJECT. we do NOT use pseudo objects for data + ** transfers. + ** + ** A pseudo object may NOT return OLE_S_USEREG; they must call the + ** OleReg* API or provide their own implementation. Because this + ** pseudo object does NOT implement IPersist, simply a low-level + ** remoting handler (ProxyManager) object as opposed to a + ** DefHandler object is used as the handler for the pseudo + ** object in a clients process space. The ProxyManager does NOT + ** handle the OLE_S_USEREG return values. + */ + if (dwDirection == DATADIR_GET) + return OleRegEnumFormatEtc( + (REFCLSID)&CLSID_APP, dwDirection, lplpenumFormatEtc); + else if (dwDirection == DATADIR_SET) + sc = E_NOTIMPL; + else + sc = E_INVALIDARG; + + return ResultFromScode(sc); +} + + +STDMETHODIMP PseudoObj_DataObj_DAdvise( + LPDATAOBJECT lpThis, + FORMATETC FAR* lpFormatetc, + DWORD advf, + LPADVISESINK lpAdvSink, + DWORD FAR* lpdwConnection +) +{ + LPPSEUDOOBJ lpPseudoObj = + ((struct CPseudoObjDataObjectImpl FAR*)lpThis)->lpPseudoObj; + HRESULT hrErr; + SCODE sc; + + OLEDBG_BEGIN2("PseudoObj_DataObj_DAdvise\r\n") + + /* OLE2NOTE: we must make sure to set all out parameters to NULL. */ + *lpdwConnection = 0; + + /* OLE2NOTE: we should validate if the caller is setting up an + ** Advise for a data type that we support. we must + ** explicitly allow an advise for the "wildcard" advise. + */ + if ( !( lpFormatetc->cfFormat == 0 && + lpFormatetc->ptd == NULL && + lpFormatetc->dwAspect == -1L && + lpFormatetc->lindex == -1L && + lpFormatetc->tymed == -1L) && + (hrErr = PseudoObj_DataObj_QueryGetData(lpThis, lpFormatetc)) + != NOERROR) { + sc = GetScode(hrErr); + goto error; + } + + if (lpPseudoObj->m_lpDataAdviseHldr == NULL && + CreateDataAdviseHolder(&lpPseudoObj->m_lpDataAdviseHldr) != NOERROR) { + sc = E_OUTOFMEMORY; + goto error; + } + + OLEDBG_BEGIN2("IOleAdviseHolder::Advise called\r\n") + hrErr = lpPseudoObj->m_lpDataAdviseHldr->lpVtbl->Advise( + lpPseudoObj->m_lpDataAdviseHldr, + (LPDATAOBJECT)&lpPseudoObj->m_DataObject, + lpFormatetc, + advf, + lpAdvSink, + lpdwConnection + ); + OLEDBG_END2 + + OLEDBG_END2 + return hrErr; + +error: + OLEDBG_END2 + return ResultFromScode(sc); +} + + +STDMETHODIMP PseudoObj_DataObj_DUnadvise(LPDATAOBJECT lpThis, DWORD dwConnection) +{ + LPPSEUDOOBJ lpPseudoObj = + ((struct CPseudoObjDataObjectImpl FAR*)lpThis)->lpPseudoObj; + HRESULT hrErr; + SCODE sc; + + OLEDBG_BEGIN2("PseudoObj_DataObj_Unadvise\r\n"); + + // no one registered + if (lpPseudoObj->m_lpDataAdviseHldr == NULL) { + sc = E_FAIL; + goto error; + } + + OLEDBG_BEGIN2("IOleAdviseHolder::DUnadvise called\r\n") + hrErr = lpPseudoObj->m_lpDataAdviseHldr->lpVtbl->Unadvise( + lpPseudoObj->m_lpDataAdviseHldr, + dwConnection + ); + OLEDBG_END2 + + OLEDBG_END2 + return hrErr; + +error: + OLEDBG_END2 + return ResultFromScode(sc); +} + + +STDMETHODIMP PseudoObj_DataObj_EnumAdvise( + LPDATAOBJECT lpThis, + LPENUMSTATDATA FAR* lplpenumAdvise +) +{ + LPPSEUDOOBJ lpPseudoObj = + ((struct CPseudoObjDataObjectImpl FAR*)lpThis)->lpPseudoObj; + HRESULT hrErr; + SCODE sc; + + OLEDBG_BEGIN2("PseudoObj_DataObj_EnumAdvise\r\n"); + + /* OLE2NOTE: we must make sure to set all out parameters to NULL. */ + *lplpenumAdvise = NULL; + + if (lpPseudoObj->m_lpDataAdviseHldr == NULL) { + sc = E_FAIL; + goto error; + } + + OLEDBG_BEGIN2("IOleAdviseHolder::EnumAdvise called\r\n") + hrErr = lpPseudoObj->m_lpDataAdviseHldr->lpVtbl->EnumAdvise( + lpPseudoObj->m_lpDataAdviseHldr, + lplpenumAdvise + ); + OLEDBG_END2 + + OLEDBG_END2 + return hrErr; + +error: + OLEDBG_END2 + return ResultFromScode(sc); +} diff --git a/private/oleutest/letest/outline/tests.c b/private/oleutest/letest/outline/tests.c new file mode 100644 index 000000000..ce8f99a09 --- /dev/null +++ b/private/oleutest/letest/outline/tests.c @@ -0,0 +1,134 @@ +//+------------------------------------------------------------------------- +// +// Microsoft Windows +// Copyright (C) Microsoft Corporation, 1992 - 1993. +// +// File: tests.c +// +// Contents: unit tests for 32bit OLE +// +// Classes: +// +// Functions: StartClipboardTest1 +// +// History: dd-mmm-yy Author Comment +// 16-Jun-94 alexgo author +// +//-------------------------------------------------------------------------- + +#include "outline.h" + +//+------------------------------------------------------------------------- +// +// Function: StartClipboardTest1 +// +// Synopsis: copies the loaded object to the clipboard +// +// Effects: +// +// Arguments: void +// +// Requires: +// +// Returns: void +// +// Signals: +// +// Modifies: +// +// Algorithm: +// +// History: dd-mmm-yy Author Comment +// 16-Jun-94 alexgo author +// +// Notes: +// +//-------------------------------------------------------------------------- + +void StartClipboardTest1( LPOUTLINEAPP lpOutlineApp) +{ + static char FileName[] = "letest12.olc"; + BOOL fStatus; + HRESULT hresult = ResultFromScode(E_FAIL); + + lpOutlineApp->m_lpDoc = OutlineApp_CreateDoc(lpOutlineApp, FALSE); + if (! lpOutlineApp->m_lpDoc) + { + goto errRtn; + } + + fStatus = OutlineDoc_LoadFromFile(lpOutlineApp->m_lpDoc, + FileName); + + if( !fStatus ) + { + hresult = ResultFromScode(STG_E_FILENOTFOUND); + goto errRtn; + } + + + + // position and size the new doc window + OutlineApp_ResizeWindows(lpOutlineApp); + OutlineDoc_ShowWindow(lpOutlineApp->m_lpDoc); + + + // we post a message here to give outline a chance to setup its + // UI before we do the copy. + + UpdateWindow(lpOutlineApp->m_hWndApp); + OutlineDoc_SelectAllCommand(lpOutlineApp->m_lpDoc); + + PostMessage(lpOutlineApp->m_hWndApp, WM_TEST2, 0, 0); + + return; + +errRtn: + + // we should abort if error + PostMessage(g_hwndDriver, WM_TESTEND, TEST_FAILURE, hresult); + PostMessage(lpOutlineApp->m_hWndApp, WM_SYSCOMMAND, SC_CLOSE, 0L); + + +} + +//+------------------------------------------------------------------------- +// +// Function: ContinueClipboardTest1 +// +// Synopsis: finishes up the clipboard test +// +// Effects: +// +// Arguments: +// +// Requires: +// +// Returns: +// +// Signals: +// +// Modifies: +// +// Algorithm: +// +// History: dd-mmm-yy Author Comment +// 16-Jun-94 alexgo author +// Notes: +// +//-------------------------------------------------------------------------- + +void ContinueClipboardTest1( LPOUTLINEAPP lpOutlineApp ) +{ + OutlineDoc_CopyCommand(lpOutlineApp->m_lpDoc); + + OleApp_FlushClipboard((LPOLEAPP)lpOutlineApp); + + //flushing will make the app dirty, just reset that here ;-) + + lpOutlineApp->m_lpDoc->m_fModified = FALSE; + + PostMessage(g_hwndDriver, WM_TEST1, NOERROR, 0); + PostMessage(lpOutlineApp->m_hWndApp, WM_SYSCOMMAND, SC_CLOSE, 0L); +} + diff --git a/private/oleutest/letest/readme.txt b/private/oleutest/letest/readme.txt new file mode 100644 index 000000000..a273023d7 --- /dev/null +++ b/private/oleutest/letest/readme.txt @@ -0,0 +1,11 @@ +Author: Kennethm +Date: 3-10-94 + +There are four applications made from this directory. These four apps +are made from one common source base. The master files are found in the +cntroutl subdirectory. If you make any of the apps their source code +will be copied into the proper subdirectory. + +Do not modify any source files other than those in the cntroutl directory! + + \ No newline at end of file -- cgit v1.2.3