957 lines
26 KiB
C
957 lines
26 KiB
C
/************************************************************/
|
||
/* Windows Write, Copyright 1985-1992 Microsoft Corporation */
|
||
/************************************************************/
|
||
|
||
/* clipbord.c -- Cut/Paste to clipboard */
|
||
|
||
#define NOVIRTUALKEYCODES
|
||
#define NOWINSTYLES
|
||
#define NOGDICAPMASKS
|
||
#define NOSYSMETRICS
|
||
#define NOMENUS
|
||
#define NOCTLMGR
|
||
#define NOFONT
|
||
#define NOPEN
|
||
#define NOBRUSH
|
||
#define NOSCROLL
|
||
#define NOCOMM
|
||
#define NOWNDCLASS
|
||
#include <windows.h>
|
||
|
||
#include "mw.h"
|
||
#include "docdefs.h"
|
||
#include "cmddefs.h"
|
||
#include "str.h"
|
||
#include "propdefs.h"
|
||
#include "editdefs.h"
|
||
#include "winddefs.h"
|
||
#include "filedefs.h"
|
||
#include "wwdefs.h"
|
||
#include "prmdefs.h"
|
||
#if defined(OLE)
|
||
#include "obj.h"
|
||
#endif
|
||
|
||
#ifdef JAPAN //T-HIROYN Win3.1
|
||
#include "kanji.h"
|
||
#endif
|
||
|
||
#include "debug.h"
|
||
|
||
extern struct SEL selCur; /* Current selection (i.e., sel in current ww */
|
||
extern int docCur; /* Document in current ww */
|
||
|
||
extern int docUndo;
|
||
extern int docScrap;
|
||
extern int vfSeeSel;
|
||
extern struct DOD (**hpdocdod)[];
|
||
extern struct PAP vpapAbs;
|
||
extern typeCP vcpLimParaCache;
|
||
extern typeCP vcpFirstParaCache;
|
||
extern int vfPictSel;
|
||
extern HCURSOR vhcIBeam;
|
||
extern int vfScrapIsPic;
|
||
extern struct UAB vuab;
|
||
extern int ferror;
|
||
extern struct FCB (**hpfnfcb)[];
|
||
extern struct WWD rgwwd[];
|
||
|
||
/* THESE ARE LOCAL TO THIS MODULE */
|
||
#if defined(OLE)
|
||
int NEAR PASCAL CopyScrapToTmp(void);
|
||
#endif
|
||
|
||
/* fn we created during the last non-local cut of MEMO rich text */
|
||
int fnLastCut=fnNil;
|
||
/* Local communication between ChangeClipboard() and MdocDestroyClip() */
|
||
int fDontDestroyClip=FALSE;
|
||
|
||
|
||
FMdocClipboardMsg( message, wParam, lParam )
|
||
unsigned message;
|
||
WORD wParam;
|
||
LONG lParam;
|
||
{ /* Process WRITE clipboard messages sent to MdocWndproc.
|
||
return TRUE if a message was processed, FALSE otherwise */
|
||
|
||
switch (message)
|
||
{
|
||
default:
|
||
return FALSE;
|
||
|
||
/*-------DATA INTERCHANGE COMMANDS-----------*/
|
||
case WM_CUT:
|
||
fnCutEdit();
|
||
break;
|
||
|
||
case WM_COPY:
|
||
fnCopyEdit();
|
||
break;
|
||
|
||
case WM_PASTE:
|
||
#if defined(OLE)
|
||
vbObjLinkOnly = FALSE;
|
||
#endif
|
||
fnPasteEdit();
|
||
break;
|
||
|
||
case WM_CLEAR:
|
||
fnClearEdit(OBJ_DELETING);
|
||
break;
|
||
|
||
case WM_UNDO:
|
||
fnUndoEdit();
|
||
break;
|
||
|
||
/*---------------CLIPBOARD INTERACTION-------------*/
|
||
|
||
case WM_DESTROYCLIPBOARD:
|
||
/* A notification that we are about to lose the ownership
|
||
of the clipboard. We should free any resources that are
|
||
holding the contents of the clipboard */
|
||
MdocDestroyClip();
|
||
break;
|
||
|
||
case WM_RENDERFORMAT:
|
||
/* A request to render the contents of the clipboard
|
||
in the data format specified. Reception of this message
|
||
implies that the receiver is the current owner of the
|
||
clipboard. See clipbord.c */
|
||
MdocRenderFormat( wParam );
|
||
break;
|
||
|
||
/*-------CLIPBOARD DISPLAY---------------------*/
|
||
|
||
case WM_PAINTCLIPBOARD:
|
||
/* A request to paint the clipboard contents.
|
||
wParam is a handle to the clipboard window
|
||
LOWORD( lParam ) is a handle to a PAINTSTRUCT giving
|
||
a DC and RECT for the area to repaint */
|
||
|
||
MdocPaintClipboard( wParam, LOWORD(lParam) );
|
||
break;
|
||
|
||
case WM_VSCROLLCLIPBOARD:
|
||
/* A request to vertically scroll the clipboard contents.
|
||
wParam is a handle to the clipboard window
|
||
LOWORD( lParam ) is the scroll type (SB_)
|
||
HIWORD( lParam ) is the new thumb position (if needed) */
|
||
|
||
MdocVscrollClipboard( wParam, LOWORD(lParam), HIWORD(lParam) );
|
||
break;
|
||
|
||
case WM_HSCROLLCLIPBOARD:
|
||
/* A request to horizontally scroll the clipboard contents.
|
||
wParam is a handle to the clipboard window
|
||
LOWORD( lParam ) is the scroll type (SB_)
|
||
HIWORD( lParam ) is the new thumb position (if needed) */
|
||
|
||
MdocHscrollClipboard( wParam, LOWORD(lParam), HIWORD(lParam) );
|
||
break;
|
||
|
||
case WM_SIZECLIPBOARD:
|
||
/* A notification that the clipboard window is being re-sized.
|
||
wParam is a handle to the clipboard window
|
||
LOWORD(lParam) is a handle to a RECT giving the new size */
|
||
|
||
MdocSizeClipboard( wParam, LOWORD(lParam) );
|
||
break;
|
||
|
||
case WM_ASKCBFORMATNAME:
|
||
/* A request for the name of the CF_OWNERDISPLAY clip format.
|
||
wParam is the max. # of chars to store (including terminator)
|
||
lParam is a long pointer to a buffer in which to store the name */
|
||
|
||
MdocAskCBFormatName( (LPCH) lParam, wParam );
|
||
break;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
|
||
|
||
fnCopyEdit()
|
||
{ /* COPY command: copy selection to clipboard */
|
||
extern int vfOwnClipboard;
|
||
typeCP cpFirst;
|
||
typeCP dcp;
|
||
|
||
StartLongOp();
|
||
|
||
cpFirst = selCur.cpFirst;
|
||
SetUndo( uacReplScrap, docCur, cpFirst, dcp = selCur.cpLim - cpFirst,
|
||
docNil, cpNil, cp0, 0);
|
||
SetUndoMenuStr(IDSTRUndoEdit);
|
||
|
||
ClobberDoc(docScrap, docCur, cpFirst, dcp);
|
||
|
||
#ifdef DCLIP
|
||
{
|
||
char rgch[100];
|
||
wsprintf(rgch,"fnCopyEdit: cpFirst %lu, dcp %lu \n\r", cpFirst, dcp);
|
||
CommSz(rgch);
|
||
}
|
||
#endif
|
||
|
||
if (ferror)
|
||
NoUndo();
|
||
else
|
||
{
|
||
if (wwdCurrentDoc.fEditHeader || wwdCurrentDoc.fEditFooter)
|
||
MakeScrapUnRunning();
|
||
vfScrapIsPic = vfPictSel;
|
||
}
|
||
|
||
#ifdef STYLES
|
||
(**hpdocdod)[docScrap].docSsht = (**hpdocdod)[docCur].docSsht;
|
||
#endif
|
||
|
||
|
||
#if defined(OLE)
|
||
ObjEnumInDoc(docScrap,ObjCloneObjectInDoc);
|
||
#endif
|
||
|
||
ChangeClipboard(); /* Force repaint of clipboard display & Set ownership */
|
||
|
||
EndLongOp(vhcIBeam);
|
||
}
|
||
|
||
|
||
MakeScrapUnRunning()
|
||
{ /* If the 1st para of docScrap is a running head,
|
||
apply a sprm to the whole of docScrap that gives it an rhc code of 0.
|
||
This is to avoid pasting running head stuff into the main part of a doc */
|
||
|
||
CHAR rgb [2];
|
||
typeCP cpMacScrap = (**hpdocdod) [docScrap].cpMac;
|
||
|
||
if (cpMacScrap != cp0 )
|
||
{
|
||
CachePara( docScrap, cp0 );
|
||
if (vpapAbs.rhc != 0)
|
||
{
|
||
rgb [0] = sprmPRhc;
|
||
rgb [1] = 0;
|
||
AddSprmCps( rgb, docScrap, cp0, cpMacScrap );
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
fnCutEdit()
|
||
{ /* CUT command: copy selection to clipboard & delete it */
|
||
extern int vfOwnClipboard;
|
||
typeCP cpFirst, cpLim, dcp;
|
||
|
||
ClearInsertLine(); /* Since we will be affecting cp's */
|
||
|
||
if (!FWriteOk( fwcDelete ))
|
||
/* Not OK to write on this doc */
|
||
return;
|
||
|
||
cpFirst = selCur.cpFirst;
|
||
cpLim = selCur.cpLim;
|
||
|
||
if (!ObjDeletionOK(OBJ_CUTTING))
|
||
return;
|
||
|
||
StartLongOp();
|
||
|
||
SetUndo( uacDelScrap, docCur, cpFirst, dcp = cpLim - cpFirst, docNil,
|
||
cpNil, cp0, 0);
|
||
ClobberDoc(docScrap, docCur, cpFirst, dcp);
|
||
if (wwdCurrentDoc.fEditHeader || wwdCurrentDoc.fEditFooter)
|
||
MakeScrapUnRunning();
|
||
|
||
|
||
if (!ferror) /* Don't stomp document if Clobber Doc failed */
|
||
{
|
||
if (wwdCurrentDoc.fEditHeader || wwdCurrentDoc.fEditFooter)
|
||
MakeScrapUnRunning();
|
||
Replace(docCur, cpFirst, dcp, fnNil, fc0, fc0);
|
||
}
|
||
else
|
||
NoUndo(); /* undo would be invalid */
|
||
|
||
#ifdef STYLES
|
||
(**hpdocdod)[docScrap].docSsht = (**hpdocdod)[docCur].docSsht;
|
||
#endif
|
||
|
||
vfScrapIsPic = vfPictSel;
|
||
vfPictSel = false;
|
||
|
||
ChangeClipboard(); /* Force repaint of clipboard display, get ownership */
|
||
|
||
#if 0
|
||
#if defined(OLE)
|
||
ObjEnumInDoc(docScrap,ObjCloneObjectInDoc);
|
||
#endif
|
||
#endif
|
||
|
||
EndLongOp(vhcIBeam);
|
||
}
|
||
|
||
|
||
fnPasteEdit()
|
||
{
|
||
/* PASTE command: replace selection with clipboard contents */
|
||
extern CHAR szDocClass[];
|
||
extern int vfScrapIsPic;
|
||
extern HWND vhWnd;
|
||
HWND hWndClipOwner;
|
||
int fUnFormattedText = FALSE;
|
||
typeCP cpFirst = selCur.cpFirst;
|
||
BOOL bClearScrap=FALSE;
|
||
|
||
StartLongOp();
|
||
|
||
if ( (hWndClipOwner = GetClipboardOwner()) != vhWnd )
|
||
{ /* Clipboard owner is not this instance of memo */
|
||
if ( (hWndClipOwner == NULL) ||
|
||
!FSameClassHwndSz( hWndClipOwner, szDocClass ))
|
||
{ /* Clipboard owner is not MEMO -- process standard CF_ formats */
|
||
if ( !FReadExtScrap() )
|
||
goto PasteErr;
|
||
|
||
bClearScrap = TRUE;
|
||
fUnFormattedText = !vfScrapIsPic;
|
||
}
|
||
else
|
||
{ /* Clipboard owner is another instance of MEMO */
|
||
if (!FGrabExtMemoScrap())
|
||
goto PasteErr;
|
||
}
|
||
}
|
||
|
||
/* Replace the selection with the scrap document */
|
||
CmdInsScrap( fUnFormattedText );
|
||
|
||
if (ferror)
|
||
goto PasteErr;
|
||
|
||
#if defined(OLE)
|
||
if (!bClearScrap) // then we're keeping scrap, need to clone
|
||
{
|
||
if (ObjEnumInDoc(docScrap,ObjCloneObjectInDoc) < 0)
|
||
goto PasteErr;
|
||
}
|
||
|
||
else // then we're not keeping scrap (came from clipboard)
|
||
{
|
||
/*
|
||
We don't need contents anymore, and if it contains an object,
|
||
then its got to go because its been inserted into the doc and not cloned
|
||
and we don't want a duplicate around.
|
||
|
||
Also gotta mark the object in docCur as no longer reusable (if
|
||
it gets copied later we will need to clone it).
|
||
*/
|
||
typeCP cpLim = cpFirst+CpMacText(docScrap);
|
||
ClobberDoc(docScrap,docNil,cp0,cp0);
|
||
ObjEnumInRange(docCur,cpFirst,cpLim,ObjFromCloneInDoc);
|
||
}
|
||
#endif
|
||
|
||
EndLongOp(vhcIBeam);
|
||
return;
|
||
|
||
PasteErr:
|
||
NoUndo();
|
||
EndLongOp(vhcIBeam);
|
||
_beep();
|
||
}
|
||
|
||
|
||
|
||
MdocRenderFormat( wCf )
|
||
int wCf;
|
||
{ /* Render clipboard data in format specified by wCf */
|
||
typeCP cpMac=CpMacText( docScrap );
|
||
struct PICINFOX picInfo;
|
||
|
||
#if defined(OLE)
|
||
if (vfScrapIsPic)
|
||
{
|
||
GetPicInfo( cp0, cpMac, docScrap, &picInfo );
|
||
|
||
if ((picInfo.mfp.mm == MM_OLE) && (wCf != CF_OWNERDISPLAY))
|
||
goto Render;
|
||
}
|
||
#endif
|
||
|
||
switch (wCf) {
|
||
|
||
case CF_OWNERDISPLAY:
|
||
/* Render rich text to another MEMO instance */
|
||
FPutExtMemoScrap();
|
||
break;
|
||
|
||
case CF_TEXT:
|
||
/* Remove formatting from scrap; put bare text out to clipboard */
|
||
goto Render;
|
||
|
||
case CF_BITMAP:
|
||
if (picInfo.mfp.mm == MM_BITMAP)
|
||
{
|
||
goto Render;
|
||
}
|
||
break;
|
||
|
||
case CF_METAFILEPICT:
|
||
/* We can supply this if the scrap is a metafile picture */
|
||
if (picInfo.mfp.mm != MM_BITMAP)
|
||
{
|
||
Render:
|
||
if (!FWriteExtScrap())
|
||
Error( IDPMTClipLarge );
|
||
}
|
||
break;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
MdocDestroyClip()
|
||
{ /* Handles WM_DESTROYCLIPBOARD message. We are being notified that
|
||
the clipboard is being emptied & we don't need to keep its
|
||
contents around anymore. */
|
||
|
||
extern int vfOwnClipboard;
|
||
extern HWND vhWnd;
|
||
|
||
if (fDontDestroyClip)
|
||
return;
|
||
|
||
vfOwnClipboard = FALSE;
|
||
|
||
/* Clear out the scrap document */
|
||
ClobberDoc( docScrap, docNil, cp0, cp0 );
|
||
|
||
/* Disable UNDO operations that require the clipboard */
|
||
switch (vuab.uac) {
|
||
case uacDelScrap:
|
||
case uacUDelScrap:
|
||
case uacReplScrap:
|
||
case uacUReplScrap:
|
||
NoUndo();
|
||
break;
|
||
}
|
||
|
||
/* Remove all records of the file we generated in FPutExtMemoScrap
|
||
from the hpfnfcb array. Note that we assume that no document
|
||
in this instance has pieces of fn. */
|
||
|
||
if ( fnLastCut != fnNil )
|
||
{
|
||
FreeFn( fnLastCut );
|
||
fnLastCut = fnNil;
|
||
}
|
||
|
||
/* If we made a wwd entry for the display of the clipboard,
|
||
remove it now. We test here to avoid bringing in the
|
||
CLIPDISP module if we never did any display. */
|
||
{
|
||
if (wwClipboard != wwNil)
|
||
FreeWw( wwClipboard );
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
int FPutExtMemoScrap()
|
||
{ /* Write docScrap to a new file; send the normalized name
|
||
of the file to the clipboard as data handle for rich text type.
|
||
Assumes clipboard is open for SetClipboardData call. On exit,
|
||
the file written has an fn, but no document (including docScrap)
|
||
has pieces that point to it. This allows us to relinquish
|
||
ownership of the fn to the pasting instance.
|
||
RETURN: TRUE == OK, FALSE == ERROR
|
||
*/
|
||
int fn;
|
||
CHAR szT[ cchMaxFile ];
|
||
HANDLE hMem;
|
||
LPCH lpch;
|
||
int cch;
|
||
#if defined(OLE)
|
||
int docTemp;
|
||
#endif
|
||
|
||
/* Create a new, formatted file with a unique name */
|
||
szT [0] = '\0'; /* Create it on a temp drive in the root */
|
||
if ((fn = FnCreateSz( szT, cp0, dtyNetwork ))== fnNil )
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
fnLastCut = fn; /* Save in a static so we can relinquish it later */
|
||
|
||
/* Save scrap document to file. Note that FWriteFn does NOT modify
|
||
the piece table of docScrap, so no document has pieces pointing
|
||
to fn. This is important because we don't want local pastes
|
||
to generate pieces pointing to this fn; we want to be able to cleanly
|
||
transfer ownership of the fn to another instance */
|
||
|
||
#if defined(OLE)
|
||
if ((docTemp = CopyScrapToTmp()) == docNil)
|
||
{
|
||
FDeleteFn( fn ); /* This will free the fn even if deleting the file
|
||
fails */
|
||
return FALSE;
|
||
}
|
||
#endif
|
||
|
||
if (!FWriteFn( fn, docTemp, TRUE ))
|
||
{
|
||
FDeleteFn( fn ); /* This will free the fn even if deleting the file
|
||
fails */
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
#if defined(OLE)
|
||
if (docTemp != docScrap)
|
||
KillDoc (docTemp);
|
||
#endif
|
||
|
||
/* Make a global handle containing the name of the file; send it to the
|
||
clipboard as the rendering of the rich text format */
|
||
|
||
if ( ((hMem = GlobalAlloc( GMEM_MOVEABLE, (LONG)(cch=CchSz( szT ))))== NULL ) ||
|
||
((lpch = GlobalLock( hMem )) == NULL) )
|
||
{
|
||
return FALSE;
|
||
}
|
||
bltbx( (LPCH)szT, lpch, cch );
|
||
GlobalUnlock( hMem );
|
||
|
||
SetClipboardData( CF_OWNERDISPLAY, hMem );
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
|
||
|
||
int FGrabExtMemoScrap()
|
||
{
|
||
/* We get here on a PASTE if the clipboard contains rich text from a
|
||
MEMO instance other than this one. This routine requests the contents of
|
||
the clipboard from the other instance, and places the contents into docScrap.
|
||
The contents of the clipboard are passed in a MEMO formatted file, whose
|
||
filename is contained in the clipboard's handle. The instance that owns
|
||
the clipboard does not keep any references to the fn for the clipboard
|
||
file (once we EmptyClipboard). After pasting, this routine arrogates
|
||
the ownership of the clipboard to this instance.
|
||
returns FALSE=error, true=OK */
|
||
|
||
extern int vfOwnClipboard;
|
||
extern HWND vhWnd;
|
||
|
||
LPCH lpch;
|
||
CHAR szT [cchMaxFile];
|
||
int fn;
|
||
typeFC dfc;
|
||
HANDLE hData;
|
||
int fOK=false;
|
||
|
||
/* Open Clipboard to lock out contenders */
|
||
|
||
if ( !OpenClipboard( vhWnd ))
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
/* Grab clipboard data handle contents: it is a normalized
|
||
filename string referring to a formatted file containing
|
||
the rich text. The GetClipboardData call actually initiates
|
||
a WM_RENDERFORMAT message to which MdocRenderFormat responds */
|
||
|
||
if ( ((hData = GetClipboardData( CF_OWNERDISPLAY )) == NULL ) ||
|
||
((lpch = GlobalLock( hData )) == NULL ) )
|
||
{
|
||
goto GrabErr;
|
||
}
|
||
|
||
bltszx( lpch, (LPCH)szT );
|
||
GlobalUnlock( hData ); /* handle will be freed in EmptyClipboard sequence */
|
||
|
||
/* Open the file; replace the contents of the scrap document
|
||
with the contents of the file */
|
||
|
||
if ((fn = FnOpenSz( szT, dtyNormal, FALSE )) == fnNil)
|
||
{ /* Unfortunately, if this fails, the file that the other
|
||
instance created will "float", with noone holding an fn
|
||
for it, and it will not get deleted at the end of the session.
|
||
On the bright side, if the reason for the failure was that
|
||
the file never got created anyway, we have done exactly right */
|
||
goto GrabErr;
|
||
}
|
||
|
||
{ /* Opened file OK */
|
||
struct FCB *pfcb = &(**hpfnfcb)[fn];
|
||
struct FFNTB **hffntb;
|
||
struct FFNTB **HffntbCreateForFn();
|
||
int wUnused;
|
||
|
||
pfcb->fDelete = TRUE;
|
||
dfc = pfcb->fFormatted ? cfcPage : fc0;
|
||
Replace( docScrap,
|
||
cp0,
|
||
(**hpdocdod)[docScrap].cpMac,
|
||
fn,
|
||
dfc,
|
||
pfcb->fcMac - dfc );
|
||
|
||
/* give the scrap the correct font table */
|
||
FreeFfntb((**hpdocdod)[docScrap].hffntb);
|
||
if (FNoHeap(hffntb = HffntbCreateForFn(fn, &wUnused)))
|
||
hffntb = 0;
|
||
(**hpdocdod)[docScrap].hffntb = hffntb;
|
||
}
|
||
|
||
#if defined(OLE)
|
||
/* if there are any objects in there, Load 'em */
|
||
if (ObjEnumInDoc(docScrap,ObjLoadObjectInDoc) < 0)
|
||
fOK = FALSE;
|
||
else
|
||
#endif
|
||
fOK = !ferror; /* All is well if we didn't run out of memory */
|
||
|
||
/* Take over ownership of the clipboard. This results in a
|
||
WM_DESTROYCLIPBOARD message being sent to the other instance,
|
||
which will delete its fn entry for the file so we are the
|
||
exclusive owners */
|
||
|
||
GrabErr:
|
||
CloseClipboard();
|
||
ChangeClipboard();
|
||
return fOK;
|
||
}
|
||
|
||
|
||
|
||
|
||
ChangeClipboard()
|
||
{ /* Mark clipboard as changed. If we are not the owner of the clipboard, */
|
||
/* make us the owner (via EmptyClipboard). The EmptyClipboard call */
|
||
/* will result in a WM_DESTROYCLIPBOARD message being sent to the */
|
||
/* owning instance. The CloseClipboard call will result in a */
|
||
/* WM_DRAWCLIPBOARD message being sent to the clipboard viewer. */
|
||
/* If the clipboard viewer is CLIP.EXE, we will get a WM_PAINTCLIPBOARD */
|
||
/* message */
|
||
/* Added 10/8/85 by BL: If docScrap is empty, relinquish ownership */
|
||
/* of the clipboard */
|
||
|
||
extern int vfOwnClipboard;
|
||
extern HWND vhWnd;
|
||
int cf;
|
||
struct PICINFOX picInfo;
|
||
typeCP cpMacScrap = (**hpdocdod) [docScrap].cpMac;
|
||
|
||
if (!OpenClipboard( vhWnd ))
|
||
{ /* Couldn't open the clipboard, wipe out contents & disable UNDO */
|
||
MdocDestroyClip();
|
||
return;
|
||
}
|
||
|
||
/* We want to clear out previous data formats in the clipboard.
|
||
Unfortunately, the only way to do this is to call EmptyClipboard(),
|
||
which has the side effect of calling us with a WM_MDOCDESTROYCLIP
|
||
message. We use this primitive global comunication to prevent
|
||
docScrap from being wiped out in MdocDestroyClip() */
|
||
|
||
fDontDestroyClip = TRUE;
|
||
EmptyClipboard();
|
||
fDontDestroyClip = FALSE;
|
||
|
||
/* Re-validate vfScrapIsPic (in case a docScrap edit changed what it should be */
|
||
|
||
CachePara( docScrap, cp0 );
|
||
vfScrapIsPic = (vpapAbs.fGraphics && vcpLimParaCache == cpMacScrap);
|
||
|
||
if (!vfScrapIsPic)
|
||
cf = CF_TEXT;
|
||
else
|
||
{
|
||
GetPicInfo( cp0, cpMacScrap, docScrap, &picInfo );
|
||
switch(picInfo.mfp.mm)
|
||
{
|
||
case MM_BITMAP:
|
||
cf = CF_BITMAP;
|
||
break;
|
||
|
||
case MM_OLE:
|
||
cf = 0;
|
||
break;
|
||
|
||
default:
|
||
cf = CF_METAFILEPICT;
|
||
break;
|
||
}
|
||
}
|
||
|
||
vfOwnClipboard = (cpMacScrap != cp0);
|
||
if (vfOwnClipboard)
|
||
{ /* only set handles if we really have something in docScrap */
|
||
SetClipboardData( CF_OWNERDISPLAY, NULL );
|
||
if ((cf != CF_TEXT) && (picInfo.mfp.mm == MM_OLE))
|
||
{
|
||
while (cf = OleEnumFormats(lpOBJ_QUERY_OBJECT(&picInfo),cf))
|
||
{
|
||
if (cf == vcfLink)
|
||
SetClipboardData( vcfOwnerLink, NULL );
|
||
else
|
||
SetClipboardData( cf, NULL );
|
||
//if (cf == vcfNative)
|
||
//SetClipboardData( vcfOwnerLink, NULL );
|
||
}
|
||
}
|
||
else
|
||
SetClipboardData( cf, NULL );
|
||
}
|
||
|
||
CloseClipboard();
|
||
}
|
||
|
||
#ifdef JAPAN //T-HIROYN Win3.1
|
||
extern typeCP vcpFetch;
|
||
extern int vcchFetch;
|
||
extern CHAR *vpchFetch;
|
||
#endif
|
||
|
||
CmdInsScrap( fUnFormattedText )
|
||
int fUnFormattedText;
|
||
{ /* Insert the scrap into the document at the current point (PASTE) */
|
||
/* If fUnFormattedText is TRUE, the scrap is treated as unformatted */
|
||
/* text; that is, the characters are put into the document with the */
|
||
/* formatting that is active at the selection */
|
||
extern struct CHP vchpSel;
|
||
typeCP cp, dcp;
|
||
int cchAddedEol=0;
|
||
struct CHP chpT;
|
||
|
||
if (!FWriteOk( fwcInsert ))
|
||
return;
|
||
|
||
if ((dcp = CpMacText(docScrap)) == cp0)
|
||
return;
|
||
|
||
ClearInsertLine();
|
||
|
||
if (fnClearEdit(OBJ_INSERTING))
|
||
return;
|
||
|
||
chpT = vchpSel;
|
||
cp = selCur.cpFirst;
|
||
|
||
CachePara( docScrap, cp0 );
|
||
if (vpapAbs.fGraphics && cp > cp0)
|
||
{ /* Special case for inserting a picture paragraph */
|
||
/* Must put an Eol in front of the picture unless we're
|
||
inserting it at the start of the document or one is there already */
|
||
|
||
Assert( !fUnFormattedText );
|
||
(**hpdocdod)[docCur].fFormatted = fTrue;
|
||
CachePara(docCur, cp - 1);
|
||
if (vcpLimParaCache != cp)
|
||
{
|
||
cchAddedEol = ccpEol;
|
||
|
||
InsertEolPap(docCur, cp, &vpapAbs);
|
||
dcp += (typeCP)ccpEol;
|
||
}
|
||
}
|
||
|
||
SetUndo( uacInsert, docCur, cp, dcp, docNil, cpNil, cp0, 0 );
|
||
|
||
SetUndoMenuStr(IDSTRUndoEdit);
|
||
ReplaceCps(docCur, cp + (typeCP)cchAddedEol, cp0, docScrap, cp0,
|
||
dcp - (typeCP)cchAddedEol);
|
||
if (ferror) /* Not enough memory to do replace operation */
|
||
NoUndo(); /* should not be able to undo what never took place */
|
||
else
|
||
{
|
||
typeCP cpSel=CpFirstSty( cp + dcp, styChar );
|
||
|
||
if (vfScrapIsPic && vuab.uac == uacReplNS)
|
||
/* Special UNDO code for picture paste */
|
||
vuab.uac = uacReplPic;
|
||
|
||
if (fUnFormattedText)
|
||
{ /* If pasting unformatted text, give it the props at the selection */
|
||
CHAR rgch[ cchCHP + 1 ];
|
||
|
||
rgch [0] = sprmCSame;
|
||
#ifdef JAPAN //T-HIROYN Win3.1
|
||
{
|
||
struct CHP savechpT;
|
||
typeCP cpF, cpFirst, cpLim, kcpF, kcpL;
|
||
int cchF;
|
||
int kanjiftc, alphaftc;
|
||
CHAR *rp;
|
||
CHAR ch;
|
||
int cch, cblen;
|
||
|
||
if(NATIVE_CHARSET != GetCharSetFromChp(&chpT)) {
|
||
kanjiftc = GetKanjiFtc(&chpT);
|
||
alphaftc = GetFtcFromPchp(&chpT);
|
||
savechpT = chpT;
|
||
cpFirst = cp;
|
||
|
||
do {
|
||
FetchCp(docCur, cpFirst, 0, fcmChars);
|
||
cpF = vcpFetch;
|
||
cchF = vcchFetch;
|
||
kcpF = cpF;
|
||
|
||
if ((cpF+cchF) < cp + dcp)
|
||
cpLim = (cpF+cchF);
|
||
else
|
||
cpLim = cp + dcp;
|
||
|
||
cch = 0;
|
||
rp = vpchFetch;
|
||
|
||
while ( kcpF < cpLim ) {
|
||
ch = *rp;
|
||
|
||
if( FKana(ch) || IsDBCSLeadByte(ch) ) {
|
||
cblen = GetKanjiStringLen(cch, cchF, rp);
|
||
chpT.ftc = kanjiftc;
|
||
} else {
|
||
cblen = GetAlphaStringLen(cch, cchF, rp);
|
||
chpT.ftc = alphaftc;
|
||
}
|
||
|
||
kcpL = kcpF + cblen;
|
||
cch += cblen;
|
||
rp += cblen;
|
||
|
||
bltbyte( &chpT, &rgch [1], cchCHP );
|
||
AddSprmCps(rgch, docCur, kcpF, kcpL);
|
||
|
||
kcpF = kcpL;
|
||
}
|
||
cpFirst = kcpF;
|
||
} while ((cpF + cchF) < cp + dcp );
|
||
chpT = savechpT;
|
||
} else {
|
||
bltbyte( &chpT, &rgch [1], cchCHP );
|
||
AddSprmCps( rgch, docCur, cp, cp + dcp );
|
||
} //END IF ELSE
|
||
} // END JAPAN
|
||
#else
|
||
bltbyte( &chpT, &rgch [1], cchCHP );
|
||
AddSprmCps( rgch, docCur, cp, cp + dcp );
|
||
#endif
|
||
}
|
||
Select( cpSel, cpSel );
|
||
vchpSel = chpT; /* Preserve insert point props across this operation */
|
||
if (wwdCurrentDoc.fEditHeader || wwdCurrentDoc.fEditFooter)
|
||
{ /* If running head/foot, remove chSects & set para props */
|
||
MakeRunningCps( docCur, cp, dcp );
|
||
}
|
||
if (ferror)
|
||
NoUndo();
|
||
}
|
||
|
||
vfSeeSel = true; /* Tell Idle() to scroll the selection into view */
|
||
}
|
||
|
||
|
||
#if defined(OLE)
|
||
int NEAR PASCAL CopyScrapToTmp(void)
|
||
/*
|
||
If scrap doesn't contain OLE objects, return docScrap. Else
|
||
create docTemp and copy docScrap into it. Make sure objects
|
||
all have their data and have their lpObjInfos NULL'd out.
|
||
*/
|
||
{
|
||
extern typeCP cpMinCur, cpMacCur, cpMinDocument;
|
||
typeCP cpMinCurT = cpMinCur,
|
||
cpMacCurT = cpMacCur,
|
||
cpMinDocumentT = cpMinDocument;
|
||
int docTemp = docNil,
|
||
docReturn = docNil;
|
||
|
||
/* are there any objects? */
|
||
switch (ObjEnumInDoc(docScrap,NULL))
|
||
{
|
||
case -1: // error
|
||
return docNil;
|
||
case 0: // no objects in scrap
|
||
return docScrap;
|
||
}
|
||
|
||
/* Create copy of document */
|
||
if ((docTemp = DocCreate(fnNil, HszCreate(""), dtyNormal)) == docNil)
|
||
return docNil;
|
||
|
||
/* copy scrap to docTemp */
|
||
ClobberDoc(docTemp, docScrap, cp0, CpMacText(docScrap));
|
||
|
||
if (ferror)
|
||
goto error;
|
||
|
||
/* now save objects to make sure their data is present */
|
||
{
|
||
OBJPICINFO picInfo;
|
||
typeCP cpPicInfo;
|
||
|
||
for (cpPicInfo = cpNil;
|
||
ObjPicEnumInRange(&picInfo,docTemp,cp0,CpMacText(docTemp),&cpPicInfo);
|
||
)
|
||
{
|
||
OBJINFO ObjInfoSave;
|
||
typeCP cpRetval;
|
||
|
||
if (picInfo.lpObjInfo == NULL)
|
||
continue;
|
||
|
||
ObjInfoSave = *picInfo.lpObjInfo;
|
||
|
||
cpRetval = ObjSaveObjectToDoc(&picInfo,docTemp,cpPicInfo);
|
||
|
||
/*
|
||
Do this just in case saving the object to docTemp changes the
|
||
object's state. We don't want the object to appear clean
|
||
or saved when in fact it isn't or hasn't been except in docTemp,
|
||
which will be deleted by the calling routine.
|
||
*/
|
||
*picInfo.lpObjInfo = ObjInfoSave;
|
||
|
||
if (cpRetval == cp0) // save failed
|
||
goto error;
|
||
|
||
/* so pasting instance will reload object */
|
||
picInfo.lpObjInfo = NULL;
|
||
ObjSetPicInfo(&picInfo,docTemp,cpPicInfo);
|
||
}
|
||
}
|
||
|
||
/* success */
|
||
docReturn = docTemp;
|
||
|
||
error:
|
||
|
||
if ((docReturn == docNil) && (docTemp != docNil))
|
||
KillDoc(docTemp);
|
||
|
||
/* Restore cpMinCur, cpMacCur */
|
||
cpMinCur = cpMinCurT;
|
||
cpMacCur = cpMacCurT;
|
||
cpMinDocument = cpMinDocumentT; /* destroyed possibly by DocCreate */
|
||
|
||
return docReturn;
|
||
}
|
||
#endif
|
||
|