1279 lines
38 KiB
C
1279 lines
38 KiB
C
|
/************************************************************/
|
|||
|
/* Windows Write, Copyright 1985-1992 Microsoft Corporation */
|
|||
|
/************************************************************/
|
|||
|
|
|||
|
/* edit.c -- MW editing routines */
|
|||
|
|
|||
|
#define NOVIRTUALKEYCODES
|
|||
|
#define NOCTLMGR
|
|||
|
#define NOWINMESSAGES
|
|||
|
#define NOWINSTYLES
|
|||
|
#define NOCLIPBOARD
|
|||
|
#define NOGDICAPMASKS
|
|||
|
#define NOSYSMETRICS
|
|||
|
#define NOMENUS
|
|||
|
#define NOKEYSTATE
|
|||
|
#define NORASTEROPS
|
|||
|
#define NOSYSCOMMANDS
|
|||
|
#define NOSHOWWINDOW
|
|||
|
#define NOCOLOR
|
|||
|
//#define NOATOM
|
|||
|
#define NOBITMAP
|
|||
|
#define NOICON
|
|||
|
#define NOBRUSH
|
|||
|
#define NOCREATESTRUCT
|
|||
|
#define NOMB
|
|||
|
#define NOMSG
|
|||
|
#define NOOPENFILE
|
|||
|
#define NOPEN
|
|||
|
#define NOPOINT
|
|||
|
#define NOREGION
|
|||
|
#define NOSCROLL
|
|||
|
#define NOSOUND
|
|||
|
#define NOWH
|
|||
|
#define NOWINOFFSETS
|
|||
|
#define NOWNDCLASS
|
|||
|
#define NOCOMM
|
|||
|
#include <windows.h>
|
|||
|
|
|||
|
#include "mw.h"
|
|||
|
#include "cmddefs.h"
|
|||
|
#include "docdefs.h"
|
|||
|
#include "filedefs.h"
|
|||
|
#include "propdefs.h"
|
|||
|
#include "fkpdefs.h"
|
|||
|
#include "debug.h"
|
|||
|
#include "wwdefs.h"
|
|||
|
#include "dispdefs.h"
|
|||
|
#include "editdefs.h"
|
|||
|
#include "str.h"
|
|||
|
#include "prmdefs.h"
|
|||
|
#include "printdef.h"
|
|||
|
#include "fontdefs.h"
|
|||
|
#if defined(OLE)
|
|||
|
#include "obj.h"
|
|||
|
#endif
|
|||
|
|
|||
|
/* E X T E R N A L S */
|
|||
|
extern int vfOutOfMemory;
|
|||
|
extern struct DOD (**hpdocdod)[];
|
|||
|
extern typeCP vcpFirstSectCache;
|
|||
|
extern struct UAB vuab;
|
|||
|
extern typeCP cpMinCur;
|
|||
|
extern typeCP cpMacCur;
|
|||
|
extern struct SEL selCur;
|
|||
|
extern int docCur;
|
|||
|
extern struct WWD rgwwd[];
|
|||
|
extern int wwMac;
|
|||
|
extern int wwCur;
|
|||
|
extern typeCP vcpLimSectCache;
|
|||
|
/*extern int idstrUndoBase;*/
|
|||
|
extern int docScrap;
|
|||
|
extern int docUndo;
|
|||
|
extern int vfSeeSel;
|
|||
|
extern struct PAP vpapAbs;
|
|||
|
extern int vfPictSel;
|
|||
|
extern int ferror;
|
|||
|
|
|||
|
/* the following used to be defined here */
|
|||
|
extern typeCP vcpFirstParaCache;
|
|||
|
extern typeCP vcpLimParaCache;
|
|||
|
/* this is a global parameter to AdjustCp; if false, no invalidation will
|
|||
|
take place */
|
|||
|
extern BOOL vfInvalid;
|
|||
|
|
|||
|
#ifdef ENABLE
|
|||
|
extern struct SEL selRulerSprm;
|
|||
|
#endif
|
|||
|
|
|||
|
extern int docRulerSprm;
|
|||
|
extern struct EDL *vpedlAdjustCp;
|
|||
|
|
|||
|
struct PCD *PpcdOpen();
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/* R E P L A C E */
|
|||
|
Replace(doc, cp, dcp, fn, fc, dfc)
|
|||
|
int doc, fn;
|
|||
|
typeCP cp, dcp;
|
|||
|
typeFC fc, dfc;
|
|||
|
{ /* Replace cp through (cp+dcp-1) in doc by fc through (fc+dfc-1) in fn */
|
|||
|
|
|||
|
if (ferror) return;
|
|||
|
#ifdef ENABLE
|
|||
|
if (docRulerSprm != docNil) ClearRulerSprm();
|
|||
|
#endif
|
|||
|
/* if (fn == fnNil) we are infact deleting text by replacing text
|
|||
|
with nil. Thus, the memory space check is unnecessary.*/
|
|||
|
#ifdef BOGUS /* No longer have cwHeapFree available */
|
|||
|
if ((fn != fnNil) && (cwHeapFree < 3 * cpcdMaxIncr * cwPCD))
|
|||
|
{
|
|||
|
#ifdef DEBUG
|
|||
|
ErrorWithMsg(IDPMTNoMemory, " edit#1");
|
|||
|
#else
|
|||
|
Error(IDPMTNoMemory);
|
|||
|
#endif
|
|||
|
return;
|
|||
|
}
|
|||
|
#else
|
|||
|
if (vfOutOfMemory)
|
|||
|
{
|
|||
|
ferror = 1;
|
|||
|
return;
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
if (dcp != cp0)
|
|||
|
{
|
|||
|
AdjParas(doc, cp, doc, cp, dcp, fTrue); /* Check for del EOL */
|
|||
|
DelFtns(doc, cp, cp + dcp); /* Delete any footnotes */
|
|||
|
}
|
|||
|
|
|||
|
Repl1(doc, cp, dcp, fn, fc, dfc);
|
|||
|
if (ferror)
|
|||
|
return;
|
|||
|
AdjustCp(doc, cp, dcp, dfc);
|
|||
|
|
|||
|
/* Special kludge for graphics paragraphs */
|
|||
|
if (dfc != dcp)
|
|||
|
CheckGraphic(doc, cp + dfc);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/* C H E C K G R A P H I C */
|
|||
|
CheckGraphic(doc, cp)
|
|||
|
int doc; typeCP cp;
|
|||
|
{
|
|||
|
#if defined(OLE)
|
|||
|
extern BOOL bNoEol;
|
|||
|
#endif
|
|||
|
|
|||
|
#ifdef CASHMERE /* No docBuffer in MEMO */
|
|||
|
extern int docBuffer; /* Don't need extra paragraph mark in txb document */
|
|||
|
if (cp == ((**hpdocdod)[doc]).cpMac || doc == docBuffer)
|
|||
|
return;
|
|||
|
#else
|
|||
|
if (cp == ((**hpdocdod)[doc]).cpMac)
|
|||
|
return;
|
|||
|
CachePara(doc, cp);
|
|||
|
/* !!! this has a bug. There are cases when you don't want to insert
|
|||
|
EOL. Ex1: place cursor in front of bitmap and press
|
|||
|
backspace. Ex2: OleSaveObjectToDoc deletes an object and
|
|||
|
insert new one (Eol gets inserted too). (4.10.91) v-dougk
|
|||
|
*/
|
|||
|
if (vpapAbs.fGraphics && vcpFirstParaCache != cp)
|
|||
|
#if defined(OLE)
|
|||
|
if (!bNoEol)
|
|||
|
#endif
|
|||
|
InsertEolInsert(doc, cp);
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
int IpcdSplit(hpctb, cp)
|
|||
|
struct PCTB **hpctb;
|
|||
|
typeCP cp;
|
|||
|
{ /* Ensure cp is the beginning of a piece. Return index of that piece.
|
|||
|
return ipcdNil on error (extern int ferror will be set in that case) */
|
|||
|
register struct PCD *ppcd = &(**hpctb).rgpcd[IpcdFromCp(*hpctb, cp)];
|
|||
|
typeCP dcp = cp - ppcd->cpMin;
|
|||
|
|
|||
|
if (dcp != cp0)
|
|||
|
{
|
|||
|
ppcd = PpcdOpen(hpctb, ppcd + 1, 1); /* Insert a new piece */
|
|||
|
if (ppcd == NULL)
|
|||
|
return ipcdNil;
|
|||
|
ppcd->cpMin = cp;
|
|||
|
ppcd->fn = (ppcd - 1)->fn;
|
|||
|
ppcd->fc = (ppcd - 1)->fc + dcp;
|
|||
|
ppcd->prm = (ppcd - 1)->prm;
|
|||
|
ppcd->fNoParaLast = (ppcd - 1)->fNoParaLast;
|
|||
|
}
|
|||
|
/* NOTE CASTS: For piece tables with rgpcd > 32Kbytes */
|
|||
|
/* return ppcd - (*hpctb)->rgpcd; */
|
|||
|
|
|||
|
return ((unsigned)ppcd - (unsigned)((*hpctb)->rgpcd)) / sizeof (struct PCD);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/* P P C D O P E N */
|
|||
|
struct PCD *PpcdOpen(hpctb, ppcd, cpcd)
|
|||
|
struct PCTB **hpctb;
|
|||
|
struct PCD *ppcd;
|
|||
|
int cpcd;
|
|||
|
{ /* Insert or delete cpcd pieces */
|
|||
|
register struct PCTB *ppctb = *hpctb;
|
|||
|
|
|||
|
/* NOTE CASTS: For piece tables with rgpcd > 32Kbytes */
|
|||
|
/* int ipcd = ppcd - ppctb->rgpcd; */
|
|||
|
int ipcd = ((unsigned)ppcd - (unsigned)(ppctb->rgpcd)) / sizeof (struct PCD);
|
|||
|
int ipcdMac, ipcdMax;
|
|||
|
|
|||
|
ipcdMac = ppctb->ipcdMac + cpcd;
|
|||
|
ipcdMax = ppctb->ipcdMax;
|
|||
|
|
|||
|
if (cpcd > 0)
|
|||
|
{ /* Inserting pieces; check for pctb too small */
|
|||
|
if (ipcdMac > ipcdMax)
|
|||
|
{ /* Enlarge piece table */
|
|||
|
int cpcdIncr = umin(cpcdMaxIncr, ipcdMac / cpcdChunk);
|
|||
|
|
|||
|
if (!FChngSizeH((int **) hpctb, (int) (cwPCTBInit + cwPCD *
|
|||
|
((ipcdMax = ipcdMac + cpcdIncr) - cpcdInit)), false))
|
|||
|
{
|
|||
|
#ifdef DEBUG
|
|||
|
ErrorWithMsg(IDPMTNoMemory, " edit#3");
|
|||
|
#else
|
|||
|
Error(IDPMTNoMemory);
|
|||
|
#endif
|
|||
|
return (struct PCD *)NULL;
|
|||
|
}
|
|||
|
|
|||
|
/* Successfully expanded piece table */
|
|||
|
|
|||
|
ppctb = *hpctb;
|
|||
|
ppcd = &ppctb->rgpcd [ipcd];
|
|||
|
ppctb->ipcdMax = ipcdMax;
|
|||
|
}
|
|||
|
ppctb->ipcdMac = ipcdMac;
|
|||
|
blt(ppcd, ppcd + cpcd, cwPCD * (ipcdMac - (ipcd + cpcd)));
|
|||
|
}
|
|||
|
else if (cpcd < 0)
|
|||
|
{ /* Deleting pieces; check for pctb obscenely large */
|
|||
|
ppctb->ipcdMac = ipcdMac;
|
|||
|
blt(ppcd - cpcd, ppcd, cwPCD * (ipcdMac - ipcd));
|
|||
|
if (ipcdMax > cpcdInit && ipcdMac * 2 < ipcdMax)
|
|||
|
{ /* Shrink piece table */
|
|||
|
#ifdef DEBUG
|
|||
|
int f =
|
|||
|
#endif
|
|||
|
FChngSizeH((int **) hpctb, (int) (cwPCTBInit + cwPCD *
|
|||
|
((ppctb->ipcdMax = umax(cpcdInit,
|
|||
|
ipcdMac + ipcdMac / cpcdChunk)) - cpcdInit)), true);
|
|||
|
|
|||
|
Assert( f );
|
|||
|
|
|||
|
return &(**hpctb).rgpcd[ipcd];
|
|||
|
}
|
|||
|
}
|
|||
|
return ppcd;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/* R E P L 1 */
|
|||
|
/* core of replace except for checking and Adjust */
|
|||
|
Repl1(doc, cp, dcp, fn, fc, dfc)
|
|||
|
int doc, fn;
|
|||
|
typeCP cp, dcp;
|
|||
|
typeFC fc, dfc;
|
|||
|
{ /* Replace pieces with an optional new piece */
|
|||
|
struct PCTB **hpctb;
|
|||
|
int ipcdFirst;
|
|||
|
int cpcd;
|
|||
|
typeCP dcpAdj = dfc - dcp;
|
|||
|
register struct PCD *ppcd;
|
|||
|
struct PCD *ppcdMac;
|
|||
|
struct PCTB *ppctb;
|
|||
|
struct PCD *ppcdPrev;
|
|||
|
struct PCD *ppcdLim=NULL;
|
|||
|
|
|||
|
hpctb = (**hpdocdod)[doc].hpctb;
|
|||
|
ipcdFirst = IpcdSplit(hpctb, cp);
|
|||
|
|
|||
|
if (dcp == cp0)
|
|||
|
cpcd = 0;
|
|||
|
else
|
|||
|
cpcd = IpcdSplit( hpctb, cp + dcp ) - ipcdFirst;
|
|||
|
|
|||
|
if (ferror)
|
|||
|
return;
|
|||
|
|
|||
|
ppctb = *hpctb;
|
|||
|
ppcdPrev = &ppctb->rgpcd[ipcdFirst - 1];
|
|||
|
|
|||
|
if ( dfc == fc0 ||
|
|||
|
(ipcdFirst > 0 && ppcdPrev->fn == fn && bPRMNIL(ppcdPrev->prm) &&
|
|||
|
ppcdPrev->fc + (cp - ppcdPrev->cpMin) == fc) ||
|
|||
|
((ppcdLim=ppcdPrev + (cpcd + 1))->fn == fn &&
|
|||
|
bPRMNIL(ppcdLim->prm) && (ppcdLim->fc == fc + dfc)))
|
|||
|
{ /* Cases: (1) No insertion,
|
|||
|
(2) Insertion is appended to previous piece
|
|||
|
(3) Insertion is prepended to this piece */
|
|||
|
|
|||
|
ppcd = PpcdOpen( hpctb, ppcdPrev + 1, -cpcd );
|
|||
|
if (ppcd == NULL)
|
|||
|
return;
|
|||
|
|
|||
|
if (dfc != fc0)
|
|||
|
{ /* Cases 2 & 3 */
|
|||
|
if (ppcdLim != NULL)
|
|||
|
/* Case 3 */
|
|||
|
(ppcd++)->fc = fc;
|
|||
|
|
|||
|
/* If extending, say we might have inserted EOL */
|
|||
|
(ppcd - 1)->fNoParaLast = false;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{ /* Insertion */
|
|||
|
ppcd = PpcdOpen( hpctb, ppcdPrev + 1, 1 - cpcd );
|
|||
|
if (ppcd == NULL)
|
|||
|
return;
|
|||
|
ppcd->cpMin = cp;
|
|||
|
ppcd->fn = fn;
|
|||
|
ppcd->fc = fc;
|
|||
|
SETPRMNIL(ppcd->prm);
|
|||
|
ppcd->fNoParaLast = false; /* Don't know yet */
|
|||
|
++ppcd;
|
|||
|
}
|
|||
|
ppcdMac = &(*hpctb)->rgpcd[(*hpctb)->ipcdMac];
|
|||
|
if (dcpAdj !=0)
|
|||
|
while (ppcd < ppcdMac)
|
|||
|
(ppcd++)->cpMin += dcpAdj;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/* A D J U S T C P */
|
|||
|
/* note global parameter vfInvalid */
|
|||
|
/* sets global vpedlAdjustCp to pedl of line containing cpFirst, if any */
|
|||
|
AdjustCp(doc, cpFirst, dcpDel, dcpIns)
|
|||
|
int doc;
|
|||
|
typeCP cpFirst, dcpDel, dcpIns;
|
|||
|
{
|
|||
|
/* Adjust all cp references in doc to conform to the deletion of
|
|||
|
dcpDel chars and the insertion of dcpIns chars at cpFirst.
|
|||
|
Mark display lines (dl's) dirty for all lines in all windows
|
|||
|
displaying doc that are affected by the insertion & deletion
|
|||
|
*/
|
|||
|
extern int vdocBitmapCache;
|
|||
|
extern typeCP vcpBitmapCache;
|
|||
|
int ww;
|
|||
|
typeCP cpLim = cpFirst + dcpDel;
|
|||
|
typeCP dcpAdj = dcpIns - dcpDel;
|
|||
|
#ifdef DEBUG
|
|||
|
Scribble(2,'A');
|
|||
|
#endif
|
|||
|
|
|||
|
{ /* Range in which pdod belongs in a register */
|
|||
|
register struct DOD *pdod = &(**hpdocdod)[doc];
|
|||
|
|
|||
|
#ifdef STYLES
|
|||
|
/* If inserting or deleting in style sheet, invalidates rest of doc */
|
|||
|
if (pdod->dty == dtySsht && dcpAdj != cp0)
|
|||
|
cpLim = pdod->cpMac;
|
|||
|
#endif
|
|||
|
pdod->cpMac += dcpAdj;
|
|||
|
/* Change for sand to support separate footnote windows: Make sure that edit
|
|||
|
was within the current cpMacCur */
|
|||
|
/* note <= (CS) */
|
|||
|
if (doc == docCur && cpFirst <= cpMacCur)
|
|||
|
cpMacCur += dcpAdj;
|
|||
|
|
|||
|
#ifdef STYLES
|
|||
|
if (dcpAdj != cp0 && pdod->dty != dtySsht)
|
|||
|
#else
|
|||
|
if (dcpAdj != cp0)
|
|||
|
#endif
|
|||
|
{
|
|||
|
#ifdef FOOTNOTES
|
|||
|
if (pdod->hfntb != 0)
|
|||
|
{ /* Adjust footnotes */
|
|||
|
struct FNTB *pfntb = *pdod->hfntb;
|
|||
|
int cfnd = pfntb->cfnd;
|
|||
|
struct FND *pfnd = &pfntb->rgfnd[cfnd];
|
|||
|
AdjRg(pfnd, cchFND, bcpRefFND, cfnd, cpFirst, dcpAdj);
|
|||
|
AdjRg(pfnd, cchFND, bcpFtnFND, cfnd, cpFirst + 1, dcpAdj);
|
|||
|
}
|
|||
|
#endif
|
|||
|
#ifdef CASHMERE
|
|||
|
if (pdod->hsetb != 0)
|
|||
|
{ /* Adjust sections */
|
|||
|
struct SETB *psetb = *pdod->hsetb;
|
|||
|
int csed = psetb->csed;
|
|||
|
AdjRg(&psetb->rgsed[csed], cchSED, bcpSED, csed, cpFirst + 1,
|
|||
|
dcpAdj);
|
|||
|
}
|
|||
|
#endif
|
|||
|
if (pdod->dty == dtyNormal && pdod->hpgtb != 0)
|
|||
|
{ /* Adjust page table */
|
|||
|
struct PGTB *ppgtb = *pdod->hpgtb;
|
|||
|
int cpgd = ppgtb->cpgd;
|
|||
|
AdjRg(&ppgtb->rgpgd[cpgd], cchPGD, bcpPGD, cpgd, cpFirst + 1,
|
|||
|
dcpAdj);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#ifdef ENABLE
|
|||
|
/* invalidate selection which contains the sprm Ruler1. When AdjustCp is
|
|||
|
called in behalf of DragTabs, this invalidation will be undone by the caller
|
|||
|
*/
|
|||
|
if (doc == docRulerSprm && cpFirst >= selRulerSprm.cpFirst)
|
|||
|
docRulerSprm = docNil;
|
|||
|
#endif
|
|||
|
} /* End of pdod belongs in a register */
|
|||
|
|
|||
|
/* Adjust or invalidate bitmap cache as appropriate */
|
|||
|
|
|||
|
if (doc == vdocBitmapCache)
|
|||
|
{
|
|||
|
if (vcpBitmapCache >= cpFirst)
|
|||
|
{
|
|||
|
if (vcpBitmapCache < cpFirst + dcpDel)
|
|||
|
FreeBitmapCache();
|
|||
|
else
|
|||
|
vcpBitmapCache += dcpAdj;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
for (ww = 0; ww < wwMac; ww++)
|
|||
|
{
|
|||
|
register struct WWD *pwwd;
|
|||
|
if ((pwwd = &rgwwd[ww])->doc == doc)
|
|||
|
{ /* This window may be affected */
|
|||
|
int dlFirst = 0;
|
|||
|
int dlLim = pwwd->dlMac;
|
|||
|
struct EDL *pedlFirst;
|
|||
|
struct EDL *pedlLast;
|
|||
|
register struct EDL *pedl;
|
|||
|
typeCP cpFirstWw = pwwd->cpFirst;
|
|||
|
struct SEL *psel = (ww == wwCur) ? &selCur : &pwwd->sel;
|
|||
|
|
|||
|
if (pwwd->cpMac >= cpLim)
|
|||
|
{
|
|||
|
pwwd->cpMac += dcpAdj;
|
|||
|
if (pwwd->cpMin > cpLim || pwwd->cpMac < pwwd->cpMin)
|
|||
|
{
|
|||
|
pwwd->cpMin += dcpAdj;
|
|||
|
if (ww == wwCur)
|
|||
|
cpMinCur = pwwd->cpMin;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#ifndef BOGUSCS
|
|||
|
if (dcpAdj != cp0 && psel->cpLim >= cpFirst)
|
|||
|
#else
|
|||
|
if (dcpAdj != cp0 && psel->cpLim > cpFirst)
|
|||
|
#endif
|
|||
|
{ /* Adjust selection */
|
|||
|
if (psel->cpFirst >= cpLim)
|
|||
|
{ /* Whole sel is after edit */
|
|||
|
psel->cpFirst += dcpAdj;
|
|||
|
psel->cpLim += dcpAdj;
|
|||
|
}
|
|||
|
else
|
|||
|
{ /* Part of sel is in edit */
|
|||
|
typeCP cpLimNew = (dcpIns == 0) ?
|
|||
|
CpFirstSty( cpFirst, styChar ) :
|
|||
|
cpFirst + dcpIns;
|
|||
|
#ifdef BOGUSCS
|
|||
|
if (ww == wwCur)
|
|||
|
TurnOffSel();
|
|||
|
#endif
|
|||
|
psel->cpFirst = cpFirst;
|
|||
|
psel->cpLim = cpLimNew;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
pedlFirst = &(**(pwwd->hdndl))[0];
|
|||
|
pedl = pedlLast = &pedlFirst[ dlLim - 1];
|
|||
|
|
|||
|
while (pedl >= pedlFirst && (pedl->cpMin > cpLim
|
|||
|
/* || (dcpAdj < 0 && pedl->cpMin == cpLim) */))
|
|||
|
{ /* Adjust dl's after edit */
|
|||
|
pedl->cpMin += dcpAdj;
|
|||
|
pedl--;
|
|||
|
}
|
|||
|
|
|||
|
/* Invalidate dl's containing edit */
|
|||
|
while (pedl >= pedlFirst && (pedl->cpMin + pedl->dcpMac > cpFirst ||
|
|||
|
(pedl->cpMin + pedl->dcpMac == cpFirst && pedl->fIchCpIncr)))
|
|||
|
{
|
|||
|
if (vfInvalid)
|
|||
|
pedl->fValid = false;
|
|||
|
if (ww == wwCur) vpedlAdjustCp = pedl;
|
|||
|
pedl--;
|
|||
|
}
|
|||
|
|
|||
|
if (pedl == pedlLast)
|
|||
|
continue; /* Entire edit below ww */
|
|||
|
|
|||
|
if (vfInvalid)
|
|||
|
pwwd->fDirty = fTrue; /* Say ww needs updating */
|
|||
|
|
|||
|
if (pedl < pedlFirst)
|
|||
|
{ /* Check for possible cpFirstWw change */
|
|||
|
if (cpFirstWw > cpLim) /* Edit above ww */
|
|||
|
pwwd->cpFirst = cpFirstWw + dcpAdj;
|
|||
|
else if (cpFirstWw + pwwd->dcpDepend > cpFirst)
|
|||
|
/* Edit includes hot spot at top of ww */
|
|||
|
{
|
|||
|
if (cpFirst + dcpIns < cpFirstWw)
|
|||
|
{
|
|||
|
pwwd->cpFirst = cpFirst;
|
|||
|
pwwd->ichCpFirst = 0;
|
|||
|
}
|
|||
|
}
|
|||
|
else /* Edit doesn't affect cpFirstWw */
|
|||
|
continue;
|
|||
|
|
|||
|
pwwd->fCpBad = true; /* Say cpFirst inaccurate */
|
|||
|
DirtyCache(cpFirst); /* Say cache inaccurate */
|
|||
|
}
|
|||
|
else do
|
|||
|
{ /* Invalidate previous line if necessary */
|
|||
|
if (pedl->cpMin + pedl->dcpMac + pedl->dcpDepend > cpFirst)
|
|||
|
{
|
|||
|
pedl->fValid = fFalse;
|
|||
|
pwwd->fDirty = fTrue;
|
|||
|
}
|
|||
|
else
|
|||
|
break;
|
|||
|
} while (pedl-- > pedlFirst);
|
|||
|
}
|
|||
|
} /* end for */
|
|||
|
|
|||
|
#if defined(OLE)
|
|||
|
ObjAdjustCps(doc,cpLim,dcpAdj);
|
|||
|
#endif
|
|||
|
|
|||
|
InvalidateCaches(doc);
|
|||
|
Scribble(2,' ');
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
ReplaceCps(docDest, cpDel, dcpDel, docSrc, cpIns, dcpIns)
|
|||
|
int docDest, docSrc;
|
|||
|
typeCP cpDel, dcpDel, cpIns, dcpIns;
|
|||
|
{ /* General replace routine */
|
|||
|
/* Replace dcpDel cp's starting at cpDel in docDest with
|
|||
|
dcpIns cp's starting at cpIns in docSrc. */
|
|||
|
register struct PCTB **hpctbDest;
|
|||
|
struct PCTB **hpctbSrc;
|
|||
|
int ipcdFirst, ipcdLim, ipcdInsFirst, ipcdInsLast;
|
|||
|
register struct PCD *ppcdDest;
|
|||
|
struct PCD *ppcdIns, *ppcdMac;
|
|||
|
typeCP dcpFile, dcpAdj;
|
|||
|
int cpcd;
|
|||
|
|
|||
|
if (ferror) return;
|
|||
|
#ifdef ENABLE
|
|||
|
if (docRulerSprm != docNil) ClearRulerSprm();
|
|||
|
#endif
|
|||
|
|
|||
|
if (dcpIns == cp0) /* This is just too easy . . . */
|
|||
|
{
|
|||
|
Replace(docDest, cpDel, dcpDel, fnNil, fc0, fc0);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
#ifdef DEBUG
|
|||
|
Assert(docDest != docSrc);
|
|||
|
#endif /* DEBUG */
|
|||
|
|
|||
|
/* Keep the heap handles, because IpcdSplit & PpcdOpen move heap */
|
|||
|
hpctbDest = (**hpdocdod)[docDest].hpctb;
|
|||
|
hpctbSrc = (**hpdocdod)[docSrc].hpctb;
|
|||
|
|
|||
|
/* Get the first and last pieces for insertion */
|
|||
|
ipcdInsFirst = IpcdFromCp(*hpctbSrc, cpIns);
|
|||
|
ipcdInsLast = IpcdFromCp(*hpctbSrc, cpIns + dcpIns - 1);
|
|||
|
|
|||
|
#ifdef BOGUS /* No longer have cwHeapFree */
|
|||
|
if (cwHeapFree < (ipcdInsLast - ipcdInsFirst + cpcdMaxIncr + 1) * cwPCD + 10)
|
|||
|
{
|
|||
|
#ifdef DEBUG
|
|||
|
ErrorWithMsg(IDPMTNoMemory, " edit#2");
|
|||
|
#else
|
|||
|
Error(IDPMTNoMemory);
|
|||
|
#endif
|
|||
|
return;
|
|||
|
}
|
|||
|
#else
|
|||
|
if (vfOutOfMemory)
|
|||
|
{
|
|||
|
ferror = TRUE;
|
|||
|
return;
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
if (docDest == docCur)
|
|||
|
HideSel(); /* Take down sel before we mess with cp's */
|
|||
|
|
|||
|
if (dcpDel != cp0)
|
|||
|
{ /* Check for deleting EOL */
|
|||
|
AdjParas(docDest, cpDel, docDest, cpDel, dcpDel, fTrue);
|
|||
|
DelFtns(docDest, cpDel, cpDel + dcpDel); /* Remove footnotes */
|
|||
|
}
|
|||
|
|
|||
|
if (dcpIns != cp0)
|
|||
|
AdjParas(docDest, cpDel, docSrc, cpIns, dcpIns, fFalse);
|
|||
|
|
|||
|
/* Get the limiting pieces for deletion (indices because hp moves ) */
|
|||
|
ipcdFirst = IpcdSplit(hpctbDest, cpDel);
|
|||
|
ipcdLim = (dcpDel == cp0) ? ipcdFirst : IpcdSplit(hpctbDest, cpDel + dcpDel);
|
|||
|
if (ferror)
|
|||
|
return;
|
|||
|
|
|||
|
/* Adjust pctb size; get pointer to the first new piece, ppcdDest, and to the
|
|||
|
first piece we are inserting. No more heap movement! */
|
|||
|
ppcdDest = PpcdOpen(hpctbDest, &(**hpctbDest).rgpcd[ipcdFirst],
|
|||
|
ipcdFirst - ipcdLim + ipcdInsLast - ipcdInsFirst + 1);
|
|||
|
ppcdIns = &(**hpctbSrc).rgpcd[ipcdInsFirst];
|
|||
|
|
|||
|
if (ferror)
|
|||
|
/* Ran out of memory expanding piece table */
|
|||
|
return;
|
|||
|
|
|||
|
/* Fill first new piece */
|
|||
|
blt(ppcdIns, ppcdDest, cwPCD);
|
|||
|
ppcdDest->cpMin = cpDel;
|
|||
|
ppcdDest->fc += (cpIns - ppcdIns->cpMin);
|
|||
|
|
|||
|
dcpFile = cpDel - cpIns;
|
|||
|
dcpAdj = dcpIns - dcpDel;
|
|||
|
|
|||
|
/* Fill in rest of inserted pieces */
|
|||
|
if ((cpcd = ipcdInsLast - ipcdInsFirst) != 0)
|
|||
|
{
|
|||
|
blt((ppcdIns + 1), (ppcdDest + 1), cwPCD * cpcd);
|
|||
|
while (cpcd--)
|
|||
|
(++ppcdDest)->cpMin += dcpFile;
|
|||
|
}
|
|||
|
|
|||
|
/* Adjust rest of pieces in destination doc */
|
|||
|
ppcdMac = &(**hpctbDest).rgpcd[(**hpctbDest).ipcdMac];
|
|||
|
while (++ppcdDest < ppcdMac)
|
|||
|
ppcdDest->cpMin += dcpAdj;
|
|||
|
#ifdef DEBUG
|
|||
|
/* ShowDocPcd("From ReplaceCps: ", docDest); */
|
|||
|
#endif
|
|||
|
|
|||
|
/* And inform anyone else who cares */
|
|||
|
AdjustCp(docDest, cpDel, dcpDel, dcpIns);
|
|||
|
/* Copy any footnotes along with their reference marks */
|
|||
|
|
|||
|
#ifdef FOOTNOTES
|
|||
|
{
|
|||
|
/* If there are any footnotes call AddFtns */
|
|||
|
struct FNTB **hfntbSrc;
|
|||
|
if ((hfntbSrc = HfntbGet(docSrc)) != 0)
|
|||
|
AddFtns(docDest, cpDel, docSrc, cpIns, cpIns + dcpIns, hfntbSrc);
|
|||
|
}
|
|||
|
#endif /* FOOTNOTES */
|
|||
|
|
|||
|
#ifdef CASHMERE
|
|||
|
{
|
|||
|
/* If there are any sections call AddSects */
|
|||
|
struct SETB **hsetbSrc;
|
|||
|
if ((hsetbSrc = HsetbGet(docSrc)) != 0)
|
|||
|
AddSects(docDest, cpDel, docSrc, cpIns, cpIns + dcpIns, hsetbSrc);
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
/* Special kludge for graphics paragraphs */
|
|||
|
if (dcpIns != dcpDel)
|
|||
|
CheckGraphic(docDest, cpDel + dcpIns);
|
|||
|
|
|||
|
if (dcpIns != cp0)
|
|||
|
{
|
|||
|
/* may have to merge in font tables */
|
|||
|
MergeFfntb(docSrc, docDest, cpDel, cpDel + dcpIns);
|
|||
|
}
|
|||
|
|
|||
|
#ifdef DEBUG
|
|||
|
/* ShowDocPcd("From ReplaceCps End: ", docDest); */
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/* A D J P A R A S */
|
|||
|
AdjParas(docDest, cpDest, docSrc, cpFirstSrc, dcpLimSrc, fDel)
|
|||
|
int docDest, docSrc, fDel;
|
|||
|
typeCP cpDest, cpFirstSrc, dcpLimSrc;
|
|||
|
{ /* Mark display lines showing the section/paragraph containing cpDest
|
|||
|
in docDest as invalid if the range cpFirstSrc through cpLimSrc-1
|
|||
|
in docSrc contains end-of-section/end-of-paragraph marks */
|
|||
|
|
|||
|
|
|||
|
typeCP cpFirstPara, cpFirstSect;
|
|||
|
typeCP cpLimSrc = cpFirstSrc + dcpLimSrc;
|
|||
|
|
|||
|
#ifdef CASHMERE /* In WRITE, the document is one big section */
|
|||
|
CacheSect(docSrc, cpFirstSrc);
|
|||
|
if (cpLimSrc >= vcpLimSectCache)
|
|||
|
{ /* Sel includes sect mark */
|
|||
|
typeCP dcp;
|
|||
|
CacheSect(docDest, cpDest);
|
|||
|
dcp = cpDest - vcpFirstSectCache;
|
|||
|
AdjustCp(docDest, vcpFirstSectCache, dcp, dcp);
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
CachePara(docSrc, cpFirstSrc);
|
|||
|
if (cpLimSrc >= vcpLimParaCache)
|
|||
|
{ /* Diddling with a para return */
|
|||
|
typeCP dcp, cpLim;
|
|||
|
typeCP cpMacT = (**hpdocdod)[docDest].cpMac;
|
|||
|
typeCP cpFirst;
|
|||
|
|
|||
|
if ((cpDest == cpMacT) && (cpMacT != cp0))
|
|||
|
{
|
|||
|
CachePara(docDest, cpDest-1);
|
|||
|
cpLim = cpMacT + 1;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
CachePara(docDest, cpLim = cpDest);
|
|||
|
}
|
|||
|
cpFirst = vcpFirstParaCache;
|
|||
|
/* invalidate at least from cpFirst to cpLim */
|
|||
|
|
|||
|
/* cpFirst is start of disturbed para in destination doc */
|
|||
|
/* next few lines check for effect of the edit on the semi-paragraph after
|
|||
|
the last paragraph mark in the document.
|
|||
|
Note: cpLimSrc is redefined as the point of insertion if !fDel.
|
|||
|
If fDel, Src and Dest documents are the same.
|
|||
|
*/
|
|||
|
if (!fDel)
|
|||
|
cpLimSrc = cpFirstSrc;
|
|||
|
if (cpLimSrc <= cpMacT)
|
|||
|
{
|
|||
|
/* if a paragraph exists at the end of the disturbance, is it the last
|
|||
|
semi-paragraph? */
|
|||
|
CachePara(docDest, cpLimSrc);
|
|||
|
if (vcpLimParaCache > cpMacT)
|
|||
|
/* yes, extend invalidation over the semi-para */
|
|||
|
cpLim = cpMacT + 1;
|
|||
|
}
|
|||
|
else
|
|||
|
cpLim = cpMacT + 1;
|
|||
|
dcp = cpLim - cpFirst;
|
|||
|
AdjustCp(docDest, cpFirst, dcp, dcp);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
int IcpSearch(cp, rgfoo, cchFoo, bcp, ifooLim)
|
|||
|
typeCP cp;
|
|||
|
CHAR rgfoo[];
|
|||
|
unsigned cchFoo;
|
|||
|
unsigned bcp;
|
|||
|
unsigned ifooLim;
|
|||
|
{ /* Binary search a table for cp; return index of 1st >= cp */
|
|||
|
unsigned ifooMin = 0;
|
|||
|
|
|||
|
while (ifooMin + 1 < ifooLim)
|
|||
|
{
|
|||
|
int ifooGuess = (ifooMin + ifooLim - 1) >> 1;
|
|||
|
typeCP cpGuess;
|
|||
|
if ((cpGuess = *(typeCP *) &rgfoo[cchFoo * ifooGuess + bcp]) < cp)
|
|||
|
ifooMin = ifooGuess + 1;
|
|||
|
else if (cpGuess > cp)
|
|||
|
ifooLim = ifooGuess + 1;
|
|||
|
else
|
|||
|
return ifooGuess;
|
|||
|
}
|
|||
|
return ifooMin;
|
|||
|
} /* end of I c p S e a r c h */
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
DelFtns(doc, cpFirst, cpLim)
|
|||
|
typeCP cpFirst, cpLim;
|
|||
|
int doc;
|
|||
|
{ /* Delete all footnote text corresponding to refs in [cpFirst:cpLim) */
|
|||
|
/* Also delete SED's for section marks. */
|
|||
|
struct FNTB **hfntb;
|
|||
|
|
|||
|
struct SETB **hsetb;
|
|||
|
|
|||
|
struct PGTB **hpgtb;
|
|||
|
|
|||
|
struct DOD *pdod;
|
|||
|
|
|||
|
#ifdef FOOTNOTES
|
|||
|
if ((hfntb = HfntbGet(doc)) != 0)
|
|||
|
RemoveDelFtnText(doc, cpFirst, cpLim, hfntb);
|
|||
|
#endif /* FOOTNOTES */
|
|||
|
|
|||
|
#ifdef CASHMERE
|
|||
|
if ((hsetb = HsetbGet(doc)) != 0)
|
|||
|
RemoveDelSeds(doc, cpFirst, cpLim, hsetb);
|
|||
|
#endif
|
|||
|
|
|||
|
pdod = &(**hpdocdod)[doc];
|
|||
|
if (pdod->dty == dtyNormal && (hpgtb = pdod->hpgtb) != 0)
|
|||
|
RemoveDelPgd(doc, cpFirst, cpLim, hpgtb);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
AdjRg(pfoo, cchFoo, bcp, ccp, cp, dcpAdj)
|
|||
|
register CHAR *pfoo;
|
|||
|
int cchFoo, bcp, ccp;
|
|||
|
typeCP cp, dcpAdj;
|
|||
|
{ /* Adjust cp's in an array */
|
|||
|
pfoo += bcp;
|
|||
|
while (ccp-- && *(typeCP *)((pfoo -= cchFoo)) >= cp)
|
|||
|
*(typeCP *)(pfoo) += dcpAdj;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
DeleteSel()
|
|||
|
{ /* Delete a selection */
|
|||
|
typeCP cpFirst;
|
|||
|
typeCP cpLim;
|
|||
|
typeCP dcp;
|
|||
|
|
|||
|
cpFirst = selCur.cpFirst;
|
|||
|
cpLim = selCur.cpLim;
|
|||
|
|
|||
|
NoUndo(); /* We don't want any combining of adjacents for this operation */
|
|||
|
SetUndo(uacDelNS, docCur, cpFirst, dcp = cpLim - cpFirst,
|
|||
|
docNil, cpNil, cp0, 0);
|
|||
|
Replace(docCur, cpFirst, dcp, fnNil, fc0, fc0);
|
|||
|
vfSeeSel = true;
|
|||
|
vfPictSel = false;
|
|||
|
return ferror;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
FWriteOk( fwc )
|
|||
|
int fwc;
|
|||
|
{ /* Test whether the edit operation specified by fwc is acceptable.
|
|||
|
Assume the operation is to be performed on selCur in docCur.
|
|||
|
Return TRUE if the operation is acceptable; FALSE otherwise */
|
|||
|
extern int vfOutOfMemory;
|
|||
|
|
|||
|
return !vfOutOfMemory;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/* S E T U N D O */
|
|||
|
SetUndo(uac, doc, cp, dcp, doc2, cp2, dcp2, itxb)
|
|||
|
int uac, doc, doc2;
|
|||
|
typeCP cp, dcp, cp2, dcp2;
|
|||
|
short itxb;
|
|||
|
{/* Set up the UNDO structure, vuab, in response to an editing operation */
|
|||
|
struct DOD *pdod, *pdodUndo;
|
|||
|
|
|||
|
/* Group delete operations together with adjacent deletes or replaces */
|
|||
|
/* WRITE needs the replace case since AlphaMode is treated as a big */
|
|||
|
/* replace operation */
|
|||
|
|
|||
|
if (uac == uacDelNS && doc == vuab.doc)
|
|||
|
{
|
|||
|
if ((vuab.uac == uacDelNS) || (vuab.uac == uacReplNS))
|
|||
|
{
|
|||
|
typeCP cpUndoAdd;
|
|||
|
|
|||
|
if (cp == vuab.cp)
|
|||
|
{
|
|||
|
cpUndoAdd = CpMacText( docUndo );
|
|||
|
goto UndoAdd;
|
|||
|
}
|
|||
|
else if (cp + dcp == vuab.cp)
|
|||
|
{
|
|||
|
cpUndoAdd = cp0;
|
|||
|
UndoAdd: ReplaceCps( docUndo, cpUndoAdd, cp0, doc, cp, dcp );
|
|||
|
if (vuab.uac == uacDelNS)
|
|||
|
vuab.dcp += dcp;
|
|||
|
else
|
|||
|
vuab.dcp2 += dcp;
|
|||
|
goto SURet;
|
|||
|
}
|
|||
|
else if (vuab.uac == uacReplNS && cp == vuab.cp + vuab.dcp)
|
|||
|
{ /* Special case for combining insertions --
|
|||
|
do not start a new undo operation if a null
|
|||
|
deletion is done at the end of an existing replace */
|
|||
|
if (dcp == cp0)
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/* Group insertions together with adjacent ins's and replaces */
|
|||
|
|
|||
|
if (uac == uacInsert && doc == vuab.doc)
|
|||
|
{/* check for adjacent inserts */
|
|||
|
/* Because we can be popped out of Alpha Mode so easily
|
|||
|
in WRITE, we try to be smarter about combining adjacent
|
|||
|
insert operations */
|
|||
|
if (vuab.uac == uacInsert || vuab.uac == uacReplNS)
|
|||
|
{
|
|||
|
if (cp == vuab.cp + vuab.dcp)
|
|||
|
{
|
|||
|
vuab.dcp += dcp;
|
|||
|
goto SURet;
|
|||
|
}
|
|||
|
}
|
|||
|
else if (cp == vuab.cp)
|
|||
|
switch(vuab.uac)
|
|||
|
{
|
|||
|
default:
|
|||
|
break;
|
|||
|
case uacDelNS:
|
|||
|
vuab.dcp2 = vuab.dcp;
|
|||
|
vuab.uac = uacReplNS;
|
|||
|
goto repl;
|
|||
|
case uacDelBuf:
|
|||
|
vuab.uac = uacReplBuf;
|
|||
|
goto repl;
|
|||
|
case uacDelScrap:
|
|||
|
vuab.uac = uacReplScrap;
|
|||
|
repl:
|
|||
|
vuab.dcp = dcp;
|
|||
|
SetUndoMenuStr(IDSTRUndoEdit);
|
|||
|
goto SURet;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#ifndef CASHMERE
|
|||
|
/* The use of vuab.itxb is a kludge to determine if the undo block is
|
|||
|
for a ruler change or an undone ruler change. */
|
|||
|
if (uac == uacRulerChange && vuab.uac == uacRulerChange && doc ==
|
|||
|
vuab.doc && cp == vuab.cp && vuab.itxb == 0)
|
|||
|
{
|
|||
|
/* The undo action block for the ruler change is already set. */
|
|||
|
vuab.dcp = CpMax(dcp, vuab.dcp);
|
|||
|
goto SURet;
|
|||
|
}
|
|||
|
#endif /* not CASHMERE */
|
|||
|
|
|||
|
vuab.doc = doc;
|
|||
|
vuab.cp = cp;
|
|||
|
vuab.dcp = dcp;
|
|||
|
vuab.doc2 = doc2;
|
|||
|
vuab.cp2 = cp2;
|
|||
|
vuab.dcp2 = dcp2;
|
|||
|
vuab.itxb = itxb;
|
|||
|
/*idstrUndoBase = IDSTRUndoBase;*/
|
|||
|
switch (vuab.uac = uac)
|
|||
|
{ /* Save deleted text if necessary */
|
|||
|
default:
|
|||
|
SetUndoMenuStr(IDSTRUndoEdit);
|
|||
|
break;
|
|||
|
case uacDelScrap:
|
|||
|
case uacReplScrap:
|
|||
|
/* Two-level edit; save scrap */
|
|||
|
{
|
|||
|
extern int vfOwnClipboard;
|
|||
|
|
|||
|
if ( vfOwnClipboard )
|
|||
|
{
|
|||
|
ClobberDoc( docUndo, docScrap, cp0,
|
|||
|
CpMacText( docScrap ) );
|
|||
|
}
|
|||
|
else
|
|||
|
ClobberDoc(docUndo, docNil, cp0, cp0);
|
|||
|
|
|||
|
SetUndoMenuStr(IDSTRUndoEdit);
|
|||
|
/* SetUndoMenuStr(uac == uacDelScrap ? IDSTRUndoCut :*/
|
|||
|
/* IDSTRUndoPaste);*/
|
|||
|
break;
|
|||
|
}
|
|||
|
case uacDelNS:
|
|||
|
/* One-level edit; save deleted text */
|
|||
|
ClobberDoc(docUndo, doc, cp, dcp);
|
|||
|
SetUndoMenuStr(IDSTRUndoEdit);
|
|||
|
/* SetUndoMenuStr(IDSTRUndoCut);*/
|
|||
|
break;
|
|||
|
case uacReplNS:
|
|||
|
/* One-level edit; save deleted text */
|
|||
|
ClobberDoc(docUndo, doc, cp, dcp2);
|
|||
|
SetUndoMenuStr(IDSTRUndoEdit);
|
|||
|
/* SetUndoMenuStr(IDSTRUndoPaste);*/
|
|||
|
break;
|
|||
|
case uacPictSel:
|
|||
|
ClobberDoc(docUndo, doc, cp, dcp);
|
|||
|
SetUndoMenuStr(IDSTRUndoEdit);
|
|||
|
/* SetUndoMenuStr(IDSTRUndoPict);*/
|
|||
|
break;
|
|||
|
case uacChLook:
|
|||
|
case uacChLookSect:
|
|||
|
SetUndoMenuStr(IDSTRUndoLook);
|
|||
|
break;
|
|||
|
|
|||
|
#ifndef CASHMERE
|
|||
|
case uacFormatTabs:
|
|||
|
ClobberDoc(docUndo, doc, cp, dcp);
|
|||
|
SetUndoMenuStr(IDSTRUndoBase);
|
|||
|
break;
|
|||
|
case uacRepaginate:
|
|||
|
case uacFormatSection:
|
|||
|
ClobberDoc(docUndo, doc, cp, dcp);
|
|||
|
if ((**hpdocdod)[doc].hpgtb)
|
|||
|
{ /* copy page table over if there is one */
|
|||
|
int cw = cwPgtbBase + (**(**hpdocdod)[doc].hpgtb).cpgdMax * cwPGD;
|
|||
|
CopyHeapTableHandle(hpdocdod,
|
|||
|
(sizeof(struct DOD) * doc) + BStructMember(DOD, hpgtb),
|
|||
|
(sizeof(struct DOD) * docUndo) + BStructMember(DOD, hpgtb),
|
|||
|
cw);
|
|||
|
}
|
|||
|
SetUndoMenuStr(IDSTRUndoBase);
|
|||
|
break;
|
|||
|
case uacRulerChange:
|
|||
|
ClobberDoc(docUndo, doc, cp, dcp2);
|
|||
|
SetUndoMenuStr(IDSTRUndoLook);
|
|||
|
/* SetUndoMenuStr(IDSTRUndoRuler);*/
|
|||
|
break;
|
|||
|
#endif /* not CASHMERE */
|
|||
|
|
|||
|
#ifdef UPDATE_UNDO
|
|||
|
#if defined(OLE)
|
|||
|
case uacObjUpdate:
|
|||
|
ClobberDoc(docUndo, docNil, cp0, cp0);
|
|||
|
SetUndoMenuStr(IDSTRObjUndo);
|
|||
|
break;
|
|||
|
#endif
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
if (doc != docNil)
|
|||
|
{
|
|||
|
pdod = &(**hpdocdod)[doc];
|
|||
|
pdodUndo = &(**hpdocdod)[docUndo];
|
|||
|
pdodUndo->fDirty = pdod->fDirty;
|
|||
|
pdodUndo->fFormatted = pdod->fFormatted;
|
|||
|
if (uac != uacReplScrap)
|
|||
|
/* If SetUndo is called with uacReplScrap, = COPY SCRAP */
|
|||
|
pdod->fDirty = true;
|
|||
|
}
|
|||
|
#ifdef BOGUSCS
|
|||
|
if (uac == uacMove)
|
|||
|
CheckMove();
|
|||
|
#endif
|
|||
|
SURet:
|
|||
|
if (ferror) NoUndo();
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/* C L O B B E R D O C */
|
|||
|
ClobberDoc(docDest, docSrc, cp, dcp)
|
|||
|
int docDest, docSrc;
|
|||
|
typeCP cp, dcp;
|
|||
|
{ /* Replace contents of docDest with docSrc[cp:dcp] */
|
|||
|
|
|||
|
extern int docScrap;
|
|||
|
extern int vfOwnClipboard;
|
|||
|
struct FFNTB **hffntb;
|
|||
|
struct SEP **hsep;
|
|||
|
struct TBD (**hgtbd)[];
|
|||
|
|
|||
|
register int bdodDest=sizeof(struct DOD)*docDest;
|
|||
|
register int bdodSrc=sizeof(struct DOD)*docSrc;
|
|||
|
|
|||
|
#define dodDest (*((struct DOD *)(((CHAR *)(*hpdocdod))+bdodDest)))
|
|||
|
#define dodSrc (*((struct DOD *)(((CHAR *)(*hpdocdod))+bdodSrc)))
|
|||
|
|
|||
|
/* clear out dest doc's font table - it will get a copy of source's */
|
|||
|
hffntb = HffntbGet(docDest);
|
|||
|
dodDest.hffntb = 0;
|
|||
|
|
|||
|
/* this does nothing if hffntb is NULL (5.15.91) v-dougk */
|
|||
|
FreeFfntb(hffntb);
|
|||
|
|
|||
|
SmashDocFce(docDest); /* font cache entries can't refer to it by doc
|
|||
|
any more */
|
|||
|
|
|||
|
/* this does nothing (code stubbed out) (5.15.91) v-dougk */
|
|||
|
ZeroFtns(docDest); /* So ReplaceCps doesn't worry about them */
|
|||
|
|
|||
|
ReplaceCps(docDest, cp0, dodDest.cpMac, docSrc, cp, dcp);
|
|||
|
|
|||
|
/* Copy section properties and tab table, both of which are
|
|||
|
document properties in MEMO */
|
|||
|
CopyHeapTableHandle( hpdocdod,
|
|||
|
((docSrc == docNil) ? -1 :
|
|||
|
bdodSrc + BStructMember( DOD, hsep )),
|
|||
|
bdodDest + BStructMember( DOD, hsep ),
|
|||
|
cwSEP );
|
|||
|
CopyHeapTableHandle( hpdocdod,
|
|||
|
((docSrc == docNil) ? -1 :
|
|||
|
bdodSrc + BStructMember( DOD, hgtbd )),
|
|||
|
bdodDest + BStructMember( DOD, hgtbd ),
|
|||
|
cwTBD * itbdMax );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CopyHeapTableHandle( hBase, bhSrc, bhDest, cwHandle )
|
|||
|
CHAR **hBase;
|
|||
|
register int bhSrc;
|
|||
|
register int bhDest;
|
|||
|
int cwHandle;
|
|||
|
{ /* Copy cwHandle words of contents from a handle located at
|
|||
|
offset (in bytes) bhSrc from the beginning of heap object
|
|||
|
hBase to a handle located at bhDest from the same base. If the
|
|||
|
destination handle is non-NULL, free it first.
|
|||
|
If bhSrc is negative, free the destination, but do not copy */
|
|||
|
|
|||
|
int **hT;
|
|||
|
|
|||
|
#define hSrc (*((int ***) ((*hBase)+bhSrc)))
|
|||
|
#define hDest (*((int ***) ((*hBase)+bhDest)))
|
|||
|
|
|||
|
if (hDest != NULL)
|
|||
|
{
|
|||
|
FreeH( hDest );
|
|||
|
hDest = NULL;
|
|||
|
}
|
|||
|
|
|||
|
if ( (bhSrc >= 0) && (hSrc != NULL) &&
|
|||
|
!FNoHeap( hT = (int **)HAllocate( cwHandle )))
|
|||
|
{
|
|||
|
blt( *hSrc, *hT, cwHandle );
|
|||
|
hDest = hT;
|
|||
|
}
|
|||
|
|
|||
|
#undef hSrc
|
|||
|
#undef hDest
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
ZeroFtns(doc)
|
|||
|
{ /* Remove all footnote & section references from doc */
|
|||
|
struct FNTB **hfntb;
|
|||
|
struct SETB **hsetb;
|
|||
|
|
|||
|
#ifdef FOOTNOTES
|
|||
|
if ((hfntb = HfntbGet(doc)) != 0)
|
|||
|
{
|
|||
|
FreeH(hfntb);
|
|||
|
(**hpdocdod)[doc].hfntb = 0;
|
|||
|
}
|
|||
|
#endif /* FOOTNOTES */
|
|||
|
#ifdef CASHMERE
|
|||
|
if ((hsetb = HsetbGet(doc)) != 0)
|
|||
|
{
|
|||
|
FreeH(hsetb);
|
|||
|
(**hpdocdod)[doc].hsetb = 0;
|
|||
|
}
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
fnClearEdit(int nInsertingOver)
|
|||
|
|
|||
|
{ /* CLEAR command entry point: Delete the current selection */
|
|||
|
|
|||
|
/**
|
|||
|
NOTE: as of this comment, this is used:
|
|||
|
1) when typing over a selection (AlphaMode() in insert.c)
|
|||
|
2) when Pasting over a selection (fnPasteEdit in clipboard.c)
|
|||
|
3) when pressing the delete key
|
|||
|
4) for InsertObject (obj3.c)
|
|||
|
5) for DragDrop (obj3.c)
|
|||
|
6) Clear header/footer (running.c)
|
|||
|
|
|||
|
A similar sequence occurs when cutting to the clipboard
|
|||
|
(fnCutEdit in clipbord.c).
|
|||
|
|
|||
|
Also see copying to clipboard (fnCopyEdit in clipbord.c).
|
|||
|
|
|||
|
(8.29.91) v-dougk
|
|||
|
**/
|
|||
|
|
|||
|
if (!FWriteOk( fwcDelete ))
|
|||
|
return TRUE;
|
|||
|
|
|||
|
if (selCur.cpFirst < selCur.cpLim)
|
|||
|
{
|
|||
|
#if defined(OLE)
|
|||
|
|
|||
|
/* this'll prevent us from deleting open embeds */
|
|||
|
if (!ObjDeletionOK(nInsertingOver))
|
|||
|
return TRUE;
|
|||
|
|
|||
|
/* close open links */
|
|||
|
ObjEnumInRange(docCur,selCur.cpFirst,selCur.cpLim,ObjCloseObjectInDoc);
|
|||
|
#endif
|
|||
|
|
|||
|
return DeleteSel();
|
|||
|
}
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
MergeFfntb(docSrc, docDest, cpMin, cpLim)
|
|||
|
/* determines if the two docs font tables differ to the extent that we need
|
|||
|
to apply a mapping sprm to the specified cp's */
|
|||
|
|
|||
|
int docSrc, docDest;
|
|||
|
typeCP cpMin, cpLim;
|
|||
|
{
|
|||
|
struct FFNTB **hffntb;
|
|||
|
int cftcDiffer, ftc, iffn;
|
|||
|
struct FFN *pffn;
|
|||
|
CHAR rgbSprm[2 + 256];
|
|||
|
CHAR rgbFfn[ibFfnMax];
|
|||
|
|
|||
|
hffntb = HffntbGet(docSrc);
|
|||
|
if (hffntb != 0)
|
|||
|
{
|
|||
|
cftcDiffer = 0;
|
|||
|
for (iffn = 0; iffn < (*hffntb)->iffnMac; iffn++)
|
|||
|
{
|
|||
|
pffn = *(*hffntb)->mpftchffn[iffn];
|
|||
|
bltbyte(pffn, rgbFfn, CbFromPffn(pffn));
|
|||
|
ftc = FtcChkDocFfn(docDest, rgbFfn);
|
|||
|
if (ftc != iffn)
|
|||
|
cftcDiffer++;
|
|||
|
rgbSprm[2+iffn] = ftc;
|
|||
|
if (ftc == ftcNil)
|
|||
|
/* we're stuck! */
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if (cftcDiffer == 0)
|
|||
|
/* new font table is a superset, & all the old font table's
|
|||
|
ftc's matched exactly - no need to do anything */
|
|||
|
return;
|
|||
|
|
|||
|
rgbSprm[0] = sprmCMapFtc;
|
|||
|
rgbSprm[1] = (*hffntb)->iffnMac;
|
|||
|
|
|||
|
/* here goes - apply the mapping */
|
|||
|
AddSprmCps(rgbSprm, docDest, cpMin, cpLim);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|