Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1278 lines
38 KiB

  1. /************************************************************/
  2. /* Windows Write, Copyright 1985-1992 Microsoft Corporation */
  3. /************************************************************/
  4. /* edit.c -- MW editing routines */
  5. #define NOVIRTUALKEYCODES
  6. #define NOCTLMGR
  7. #define NOWINMESSAGES
  8. #define NOWINSTYLES
  9. #define NOCLIPBOARD
  10. #define NOGDICAPMASKS
  11. #define NOSYSMETRICS
  12. #define NOMENUS
  13. #define NOKEYSTATE
  14. #define NORASTEROPS
  15. #define NOSYSCOMMANDS
  16. #define NOSHOWWINDOW
  17. #define NOCOLOR
  18. //#define NOATOM
  19. #define NOBITMAP
  20. #define NOICON
  21. #define NOBRUSH
  22. #define NOCREATESTRUCT
  23. #define NOMB
  24. #define NOMSG
  25. #define NOOPENFILE
  26. #define NOPEN
  27. #define NOPOINT
  28. #define NOREGION
  29. #define NOSCROLL
  30. #define NOSOUND
  31. #define NOWH
  32. #define NOWINOFFSETS
  33. #define NOWNDCLASS
  34. #define NOCOMM
  35. #include <windows.h>
  36. #include "mw.h"
  37. #include "cmddefs.h"
  38. #include "docdefs.h"
  39. #include "filedefs.h"
  40. #include "propdefs.h"
  41. #include "fkpdefs.h"
  42. #include "debug.h"
  43. #include "wwdefs.h"
  44. #include "dispdefs.h"
  45. #include "editdefs.h"
  46. #include "str.h"
  47. #include "prmdefs.h"
  48. #include "printdef.h"
  49. #include "fontdefs.h"
  50. #if defined(OLE)
  51. #include "obj.h"
  52. #endif
  53. /* E X T E R N A L S */
  54. extern int vfOutOfMemory;
  55. extern struct DOD (**hpdocdod)[];
  56. extern typeCP vcpFirstSectCache;
  57. extern struct UAB vuab;
  58. extern typeCP cpMinCur;
  59. extern typeCP cpMacCur;
  60. extern struct SEL selCur;
  61. extern int docCur;
  62. extern struct WWD rgwwd[];
  63. extern int wwMac;
  64. extern int wwCur;
  65. extern typeCP vcpLimSectCache;
  66. /*extern int idstrUndoBase;*/
  67. extern int docScrap;
  68. extern int docUndo;
  69. extern int vfSeeSel;
  70. extern struct PAP vpapAbs;
  71. extern int vfPictSel;
  72. extern int ferror;
  73. /* the following used to be defined here */
  74. extern typeCP vcpFirstParaCache;
  75. extern typeCP vcpLimParaCache;
  76. /* this is a global parameter to AdjustCp; if false, no invalidation will
  77. take place */
  78. extern BOOL vfInvalid;
  79. #ifdef ENABLE
  80. extern struct SEL selRulerSprm;
  81. #endif
  82. extern int docRulerSprm;
  83. extern struct EDL *vpedlAdjustCp;
  84. struct PCD *PpcdOpen();
  85. /* R E P L A C E */
  86. Replace(doc, cp, dcp, fn, fc, dfc)
  87. int doc, fn;
  88. typeCP cp, dcp;
  89. typeFC fc, dfc;
  90. { /* Replace cp through (cp+dcp-1) in doc by fc through (fc+dfc-1) in fn */
  91. if (ferror) return;
  92. #ifdef ENABLE
  93. if (docRulerSprm != docNil) ClearRulerSprm();
  94. #endif
  95. /* if (fn == fnNil) we are infact deleting text by replacing text
  96. with nil. Thus, the memory space check is unnecessary.*/
  97. #ifdef BOGUS /* No longer have cwHeapFree available */
  98. if ((fn != fnNil) && (cwHeapFree < 3 * cpcdMaxIncr * cwPCD))
  99. {
  100. #ifdef DEBUG
  101. ErrorWithMsg(IDPMTNoMemory, " edit#1");
  102. #else
  103. Error(IDPMTNoMemory);
  104. #endif
  105. return;
  106. }
  107. #else
  108. if (vfOutOfMemory)
  109. {
  110. ferror = 1;
  111. return;
  112. }
  113. #endif
  114. if (dcp != cp0)
  115. {
  116. AdjParas(doc, cp, doc, cp, dcp, fTrue); /* Check for del EOL */
  117. DelFtns(doc, cp, cp + dcp); /* Delete any footnotes */
  118. }
  119. Repl1(doc, cp, dcp, fn, fc, dfc);
  120. if (ferror)
  121. return;
  122. AdjustCp(doc, cp, dcp, dfc);
  123. /* Special kludge for graphics paragraphs */
  124. if (dfc != dcp)
  125. CheckGraphic(doc, cp + dfc);
  126. }
  127. /* C H E C K G R A P H I C */
  128. CheckGraphic(doc, cp)
  129. int doc; typeCP cp;
  130. {
  131. #if defined(OLE)
  132. extern BOOL bNoEol;
  133. #endif
  134. #ifdef CASHMERE /* No docBuffer in MEMO */
  135. extern int docBuffer; /* Don't need extra paragraph mark in txb document */
  136. if (cp == ((**hpdocdod)[doc]).cpMac || doc == docBuffer)
  137. return;
  138. #else
  139. if (cp == ((**hpdocdod)[doc]).cpMac)
  140. return;
  141. CachePara(doc, cp);
  142. /* !!! this has a bug. There are cases when you don't want to insert
  143. EOL. Ex1: place cursor in front of bitmap and press
  144. backspace. Ex2: OleSaveObjectToDoc deletes an object and
  145. insert new one (Eol gets inserted too). (4.10.91) v-dougk
  146. */
  147. if (vpapAbs.fGraphics && vcpFirstParaCache != cp)
  148. #if defined(OLE)
  149. if (!bNoEol)
  150. #endif
  151. InsertEolInsert(doc, cp);
  152. #endif
  153. }
  154. int IpcdSplit(hpctb, cp)
  155. struct PCTB **hpctb;
  156. typeCP cp;
  157. { /* Ensure cp is the beginning of a piece. Return index of that piece.
  158. return ipcdNil on error (extern int ferror will be set in that case) */
  159. register struct PCD *ppcd = &(**hpctb).rgpcd[IpcdFromCp(*hpctb, cp)];
  160. typeCP dcp = cp - ppcd->cpMin;
  161. if (dcp != cp0)
  162. {
  163. ppcd = PpcdOpen(hpctb, ppcd + 1, 1); /* Insert a new piece */
  164. if (ppcd == NULL)
  165. return ipcdNil;
  166. ppcd->cpMin = cp;
  167. ppcd->fn = (ppcd - 1)->fn;
  168. ppcd->fc = (ppcd - 1)->fc + dcp;
  169. ppcd->prm = (ppcd - 1)->prm;
  170. ppcd->fNoParaLast = (ppcd - 1)->fNoParaLast;
  171. }
  172. /* NOTE CASTS: For piece tables with rgpcd > 32Kbytes */
  173. /* return ppcd - (*hpctb)->rgpcd; */
  174. return ((unsigned)ppcd - (unsigned)((*hpctb)->rgpcd)) / sizeof (struct PCD);
  175. }
  176. /* P P C D O P E N */
  177. struct PCD *PpcdOpen(hpctb, ppcd, cpcd)
  178. struct PCTB **hpctb;
  179. struct PCD *ppcd;
  180. int cpcd;
  181. { /* Insert or delete cpcd pieces */
  182. register struct PCTB *ppctb = *hpctb;
  183. /* NOTE CASTS: For piece tables with rgpcd > 32Kbytes */
  184. /* int ipcd = ppcd - ppctb->rgpcd; */
  185. int ipcd = ((unsigned)ppcd - (unsigned)(ppctb->rgpcd)) / sizeof (struct PCD);
  186. int ipcdMac, ipcdMax;
  187. ipcdMac = ppctb->ipcdMac + cpcd;
  188. ipcdMax = ppctb->ipcdMax;
  189. if (cpcd > 0)
  190. { /* Inserting pieces; check for pctb too small */
  191. if (ipcdMac > ipcdMax)
  192. { /* Enlarge piece table */
  193. int cpcdIncr = umin(cpcdMaxIncr, ipcdMac / cpcdChunk);
  194. if (!FChngSizeH((int **) hpctb, (int) (cwPCTBInit + cwPCD *
  195. ((ipcdMax = ipcdMac + cpcdIncr) - cpcdInit)), false))
  196. {
  197. #ifdef DEBUG
  198. ErrorWithMsg(IDPMTNoMemory, " edit#3");
  199. #else
  200. Error(IDPMTNoMemory);
  201. #endif
  202. return (struct PCD *)NULL;
  203. }
  204. /* Successfully expanded piece table */
  205. ppctb = *hpctb;
  206. ppcd = &ppctb->rgpcd [ipcd];
  207. ppctb->ipcdMax = ipcdMax;
  208. }
  209. ppctb->ipcdMac = ipcdMac;
  210. blt(ppcd, ppcd + cpcd, cwPCD * (ipcdMac - (ipcd + cpcd)));
  211. }
  212. else if (cpcd < 0)
  213. { /* Deleting pieces; check for pctb obscenely large */
  214. ppctb->ipcdMac = ipcdMac;
  215. blt(ppcd - cpcd, ppcd, cwPCD * (ipcdMac - ipcd));
  216. if (ipcdMax > cpcdInit && ipcdMac * 2 < ipcdMax)
  217. { /* Shrink piece table */
  218. #ifdef DEBUG
  219. int f =
  220. #endif
  221. FChngSizeH((int **) hpctb, (int) (cwPCTBInit + cwPCD *
  222. ((ppctb->ipcdMax = umax(cpcdInit,
  223. ipcdMac + ipcdMac / cpcdChunk)) - cpcdInit)), true);
  224. Assert( f );
  225. return &(**hpctb).rgpcd[ipcd];
  226. }
  227. }
  228. return ppcd;
  229. }
  230. /* R E P L 1 */
  231. /* core of replace except for checking and Adjust */
  232. Repl1(doc, cp, dcp, fn, fc, dfc)
  233. int doc, fn;
  234. typeCP cp, dcp;
  235. typeFC fc, dfc;
  236. { /* Replace pieces with an optional new piece */
  237. struct PCTB **hpctb;
  238. int ipcdFirst;
  239. int cpcd;
  240. typeCP dcpAdj = dfc - dcp;
  241. register struct PCD *ppcd;
  242. struct PCD *ppcdMac;
  243. struct PCTB *ppctb;
  244. struct PCD *ppcdPrev;
  245. struct PCD *ppcdLim=NULL;
  246. hpctb = (**hpdocdod)[doc].hpctb;
  247. ipcdFirst = IpcdSplit(hpctb, cp);
  248. if (dcp == cp0)
  249. cpcd = 0;
  250. else
  251. cpcd = IpcdSplit( hpctb, cp + dcp ) - ipcdFirst;
  252. if (ferror)
  253. return;
  254. ppctb = *hpctb;
  255. ppcdPrev = &ppctb->rgpcd[ipcdFirst - 1];
  256. if ( dfc == fc0 ||
  257. (ipcdFirst > 0 && ppcdPrev->fn == fn && bPRMNIL(ppcdPrev->prm) &&
  258. ppcdPrev->fc + (cp - ppcdPrev->cpMin) == fc) ||
  259. ((ppcdLim=ppcdPrev + (cpcd + 1))->fn == fn &&
  260. bPRMNIL(ppcdLim->prm) && (ppcdLim->fc == fc + dfc)))
  261. { /* Cases: (1) No insertion,
  262. (2) Insertion is appended to previous piece
  263. (3) Insertion is prepended to this piece */
  264. ppcd = PpcdOpen( hpctb, ppcdPrev + 1, -cpcd );
  265. if (ppcd == NULL)
  266. return;
  267. if (dfc != fc0)
  268. { /* Cases 2 & 3 */
  269. if (ppcdLim != NULL)
  270. /* Case 3 */
  271. (ppcd++)->fc = fc;
  272. /* If extending, say we might have inserted EOL */
  273. (ppcd - 1)->fNoParaLast = false;
  274. }
  275. }
  276. else
  277. { /* Insertion */
  278. ppcd = PpcdOpen( hpctb, ppcdPrev + 1, 1 - cpcd );
  279. if (ppcd == NULL)
  280. return;
  281. ppcd->cpMin = cp;
  282. ppcd->fn = fn;
  283. ppcd->fc = fc;
  284. SETPRMNIL(ppcd->prm);
  285. ppcd->fNoParaLast = false; /* Don't know yet */
  286. ++ppcd;
  287. }
  288. ppcdMac = &(*hpctb)->rgpcd[(*hpctb)->ipcdMac];
  289. if (dcpAdj !=0)
  290. while (ppcd < ppcdMac)
  291. (ppcd++)->cpMin += dcpAdj;
  292. }
  293. /* A D J U S T C P */
  294. /* note global parameter vfInvalid */
  295. /* sets global vpedlAdjustCp to pedl of line containing cpFirst, if any */
  296. AdjustCp(doc, cpFirst, dcpDel, dcpIns)
  297. int doc;
  298. typeCP cpFirst, dcpDel, dcpIns;
  299. {
  300. /* Adjust all cp references in doc to conform to the deletion of
  301. dcpDel chars and the insertion of dcpIns chars at cpFirst.
  302. Mark display lines (dl's) dirty for all lines in all windows
  303. displaying doc that are affected by the insertion & deletion
  304. */
  305. extern int vdocBitmapCache;
  306. extern typeCP vcpBitmapCache;
  307. int ww;
  308. typeCP cpLim = cpFirst + dcpDel;
  309. typeCP dcpAdj = dcpIns - dcpDel;
  310. #ifdef DEBUG
  311. Scribble(2,'A');
  312. #endif
  313. { /* Range in which pdod belongs in a register */
  314. register struct DOD *pdod = &(**hpdocdod)[doc];
  315. #ifdef STYLES
  316. /* If inserting or deleting in style sheet, invalidates rest of doc */
  317. if (pdod->dty == dtySsht && dcpAdj != cp0)
  318. cpLim = pdod->cpMac;
  319. #endif
  320. pdod->cpMac += dcpAdj;
  321. /* Change for sand to support separate footnote windows: Make sure that edit
  322. was within the current cpMacCur */
  323. /* note <= (CS) */
  324. if (doc == docCur && cpFirst <= cpMacCur)
  325. cpMacCur += dcpAdj;
  326. #ifdef STYLES
  327. if (dcpAdj != cp0 && pdod->dty != dtySsht)
  328. #else
  329. if (dcpAdj != cp0)
  330. #endif
  331. {
  332. #ifdef FOOTNOTES
  333. if (pdod->hfntb != 0)
  334. { /* Adjust footnotes */
  335. struct FNTB *pfntb = *pdod->hfntb;
  336. int cfnd = pfntb->cfnd;
  337. struct FND *pfnd = &pfntb->rgfnd[cfnd];
  338. AdjRg(pfnd, cchFND, bcpRefFND, cfnd, cpFirst, dcpAdj);
  339. AdjRg(pfnd, cchFND, bcpFtnFND, cfnd, cpFirst + 1, dcpAdj);
  340. }
  341. #endif
  342. #ifdef CASHMERE
  343. if (pdod->hsetb != 0)
  344. { /* Adjust sections */
  345. struct SETB *psetb = *pdod->hsetb;
  346. int csed = psetb->csed;
  347. AdjRg(&psetb->rgsed[csed], cchSED, bcpSED, csed, cpFirst + 1,
  348. dcpAdj);
  349. }
  350. #endif
  351. if (pdod->dty == dtyNormal && pdod->hpgtb != 0)
  352. { /* Adjust page table */
  353. struct PGTB *ppgtb = *pdod->hpgtb;
  354. int cpgd = ppgtb->cpgd;
  355. AdjRg(&ppgtb->rgpgd[cpgd], cchPGD, bcpPGD, cpgd, cpFirst + 1,
  356. dcpAdj);
  357. }
  358. }
  359. #ifdef ENABLE
  360. /* invalidate selection which contains the sprm Ruler1. When AdjustCp is
  361. called in behalf of DragTabs, this invalidation will be undone by the caller
  362. */
  363. if (doc == docRulerSprm && cpFirst >= selRulerSprm.cpFirst)
  364. docRulerSprm = docNil;
  365. #endif
  366. } /* End of pdod belongs in a register */
  367. /* Adjust or invalidate bitmap cache as appropriate */
  368. if (doc == vdocBitmapCache)
  369. {
  370. if (vcpBitmapCache >= cpFirst)
  371. {
  372. if (vcpBitmapCache < cpFirst + dcpDel)
  373. FreeBitmapCache();
  374. else
  375. vcpBitmapCache += dcpAdj;
  376. }
  377. }
  378. for (ww = 0; ww < wwMac; ww++)
  379. {
  380. register struct WWD *pwwd;
  381. if ((pwwd = &rgwwd[ww])->doc == doc)
  382. { /* This window may be affected */
  383. int dlFirst = 0;
  384. int dlLim = pwwd->dlMac;
  385. struct EDL *pedlFirst;
  386. struct EDL *pedlLast;
  387. register struct EDL *pedl;
  388. typeCP cpFirstWw = pwwd->cpFirst;
  389. struct SEL *psel = (ww == wwCur) ? &selCur : &pwwd->sel;
  390. if (pwwd->cpMac >= cpLim)
  391. {
  392. pwwd->cpMac += dcpAdj;
  393. if (pwwd->cpMin > cpLim || pwwd->cpMac < pwwd->cpMin)
  394. {
  395. pwwd->cpMin += dcpAdj;
  396. if (ww == wwCur)
  397. cpMinCur = pwwd->cpMin;
  398. }
  399. }
  400. #ifndef BOGUSCS
  401. if (dcpAdj != cp0 && psel->cpLim >= cpFirst)
  402. #else
  403. if (dcpAdj != cp0 && psel->cpLim > cpFirst)
  404. #endif
  405. { /* Adjust selection */
  406. if (psel->cpFirst >= cpLim)
  407. { /* Whole sel is after edit */
  408. psel->cpFirst += dcpAdj;
  409. psel->cpLim += dcpAdj;
  410. }
  411. else
  412. { /* Part of sel is in edit */
  413. typeCP cpLimNew = (dcpIns == 0) ?
  414. CpFirstSty( cpFirst, styChar ) :
  415. cpFirst + dcpIns;
  416. #ifdef BOGUSCS
  417. if (ww == wwCur)
  418. TurnOffSel();
  419. #endif
  420. psel->cpFirst = cpFirst;
  421. psel->cpLim = cpLimNew;
  422. }
  423. }
  424. pedlFirst = &(**(pwwd->hdndl))[0];
  425. pedl = pedlLast = &pedlFirst[ dlLim - 1];
  426. while (pedl >= pedlFirst && (pedl->cpMin > cpLim
  427. /* || (dcpAdj < 0 && pedl->cpMin == cpLim) */))
  428. { /* Adjust dl's after edit */
  429. pedl->cpMin += dcpAdj;
  430. pedl--;
  431. }
  432. /* Invalidate dl's containing edit */
  433. while (pedl >= pedlFirst && (pedl->cpMin + pedl->dcpMac > cpFirst ||
  434. (pedl->cpMin + pedl->dcpMac == cpFirst && pedl->fIchCpIncr)))
  435. {
  436. if (vfInvalid)
  437. pedl->fValid = false;
  438. if (ww == wwCur) vpedlAdjustCp = pedl;
  439. pedl--;
  440. }
  441. if (pedl == pedlLast)
  442. continue; /* Entire edit below ww */
  443. if (vfInvalid)
  444. pwwd->fDirty = fTrue; /* Say ww needs updating */
  445. if (pedl < pedlFirst)
  446. { /* Check for possible cpFirstWw change */
  447. if (cpFirstWw > cpLim) /* Edit above ww */
  448. pwwd->cpFirst = cpFirstWw + dcpAdj;
  449. else if (cpFirstWw + pwwd->dcpDepend > cpFirst)
  450. /* Edit includes hot spot at top of ww */
  451. {
  452. if (cpFirst + dcpIns < cpFirstWw)
  453. {
  454. pwwd->cpFirst = cpFirst;
  455. pwwd->ichCpFirst = 0;
  456. }
  457. }
  458. else /* Edit doesn't affect cpFirstWw */
  459. continue;
  460. pwwd->fCpBad = true; /* Say cpFirst inaccurate */
  461. DirtyCache(cpFirst); /* Say cache inaccurate */
  462. }
  463. else do
  464. { /* Invalidate previous line if necessary */
  465. if (pedl->cpMin + pedl->dcpMac + pedl->dcpDepend > cpFirst)
  466. {
  467. pedl->fValid = fFalse;
  468. pwwd->fDirty = fTrue;
  469. }
  470. else
  471. break;
  472. } while (pedl-- > pedlFirst);
  473. }
  474. } /* end for */
  475. #if defined(OLE)
  476. ObjAdjustCps(doc,cpLim,dcpAdj);
  477. #endif
  478. InvalidateCaches(doc);
  479. Scribble(2,' ');
  480. }
  481. ReplaceCps(docDest, cpDel, dcpDel, docSrc, cpIns, dcpIns)
  482. int docDest, docSrc;
  483. typeCP cpDel, dcpDel, cpIns, dcpIns;
  484. { /* General replace routine */
  485. /* Replace dcpDel cp's starting at cpDel in docDest with
  486. dcpIns cp's starting at cpIns in docSrc. */
  487. register struct PCTB **hpctbDest;
  488. struct PCTB **hpctbSrc;
  489. int ipcdFirst, ipcdLim, ipcdInsFirst, ipcdInsLast;
  490. register struct PCD *ppcdDest;
  491. struct PCD *ppcdIns, *ppcdMac;
  492. typeCP dcpFile, dcpAdj;
  493. int cpcd;
  494. if (ferror) return;
  495. #ifdef ENABLE
  496. if (docRulerSprm != docNil) ClearRulerSprm();
  497. #endif
  498. if (dcpIns == cp0) /* This is just too easy . . . */
  499. {
  500. Replace(docDest, cpDel, dcpDel, fnNil, fc0, fc0);
  501. return;
  502. }
  503. #ifdef DEBUG
  504. Assert(docDest != docSrc);
  505. #endif /* DEBUG */
  506. /* Keep the heap handles, because IpcdSplit & PpcdOpen move heap */
  507. hpctbDest = (**hpdocdod)[docDest].hpctb;
  508. hpctbSrc = (**hpdocdod)[docSrc].hpctb;
  509. /* Get the first and last pieces for insertion */
  510. ipcdInsFirst = IpcdFromCp(*hpctbSrc, cpIns);
  511. ipcdInsLast = IpcdFromCp(*hpctbSrc, cpIns + dcpIns - 1);
  512. #ifdef BOGUS /* No longer have cwHeapFree */
  513. if (cwHeapFree < (ipcdInsLast - ipcdInsFirst + cpcdMaxIncr + 1) * cwPCD + 10)
  514. {
  515. #ifdef DEBUG
  516. ErrorWithMsg(IDPMTNoMemory, " edit#2");
  517. #else
  518. Error(IDPMTNoMemory);
  519. #endif
  520. return;
  521. }
  522. #else
  523. if (vfOutOfMemory)
  524. {
  525. ferror = TRUE;
  526. return;
  527. }
  528. #endif
  529. if (docDest == docCur)
  530. HideSel(); /* Take down sel before we mess with cp's */
  531. if (dcpDel != cp0)
  532. { /* Check for deleting EOL */
  533. AdjParas(docDest, cpDel, docDest, cpDel, dcpDel, fTrue);
  534. DelFtns(docDest, cpDel, cpDel + dcpDel); /* Remove footnotes */
  535. }
  536. if (dcpIns != cp0)
  537. AdjParas(docDest, cpDel, docSrc, cpIns, dcpIns, fFalse);
  538. /* Get the limiting pieces for deletion (indices because hp moves ) */
  539. ipcdFirst = IpcdSplit(hpctbDest, cpDel);
  540. ipcdLim = (dcpDel == cp0) ? ipcdFirst : IpcdSplit(hpctbDest, cpDel + dcpDel);
  541. if (ferror)
  542. return;
  543. /* Adjust pctb size; get pointer to the first new piece, ppcdDest, and to the
  544. first piece we are inserting. No more heap movement! */
  545. ppcdDest = PpcdOpen(hpctbDest, &(**hpctbDest).rgpcd[ipcdFirst],
  546. ipcdFirst - ipcdLim + ipcdInsLast - ipcdInsFirst + 1);
  547. ppcdIns = &(**hpctbSrc).rgpcd[ipcdInsFirst];
  548. if (ferror)
  549. /* Ran out of memory expanding piece table */
  550. return;
  551. /* Fill first new piece */
  552. blt(ppcdIns, ppcdDest, cwPCD);
  553. ppcdDest->cpMin = cpDel;
  554. ppcdDest->fc += (cpIns - ppcdIns->cpMin);
  555. dcpFile = cpDel - cpIns;
  556. dcpAdj = dcpIns - dcpDel;
  557. /* Fill in rest of inserted pieces */
  558. if ((cpcd = ipcdInsLast - ipcdInsFirst) != 0)
  559. {
  560. blt((ppcdIns + 1), (ppcdDest + 1), cwPCD * cpcd);
  561. while (cpcd--)
  562. (++ppcdDest)->cpMin += dcpFile;
  563. }
  564. /* Adjust rest of pieces in destination doc */
  565. ppcdMac = &(**hpctbDest).rgpcd[(**hpctbDest).ipcdMac];
  566. while (++ppcdDest < ppcdMac)
  567. ppcdDest->cpMin += dcpAdj;
  568. #ifdef DEBUG
  569. /* ShowDocPcd("From ReplaceCps: ", docDest); */
  570. #endif
  571. /* And inform anyone else who cares */
  572. AdjustCp(docDest, cpDel, dcpDel, dcpIns);
  573. /* Copy any footnotes along with their reference marks */
  574. #ifdef FOOTNOTES
  575. {
  576. /* If there are any footnotes call AddFtns */
  577. struct FNTB **hfntbSrc;
  578. if ((hfntbSrc = HfntbGet(docSrc)) != 0)
  579. AddFtns(docDest, cpDel, docSrc, cpIns, cpIns + dcpIns, hfntbSrc);
  580. }
  581. #endif /* FOOTNOTES */
  582. #ifdef CASHMERE
  583. {
  584. /* If there are any sections call AddSects */
  585. struct SETB **hsetbSrc;
  586. if ((hsetbSrc = HsetbGet(docSrc)) != 0)
  587. AddSects(docDest, cpDel, docSrc, cpIns, cpIns + dcpIns, hsetbSrc);
  588. }
  589. #endif
  590. /* Special kludge for graphics paragraphs */
  591. if (dcpIns != dcpDel)
  592. CheckGraphic(docDest, cpDel + dcpIns);
  593. if (dcpIns != cp0)
  594. {
  595. /* may have to merge in font tables */
  596. MergeFfntb(docSrc, docDest, cpDel, cpDel + dcpIns);
  597. }
  598. #ifdef DEBUG
  599. /* ShowDocPcd("From ReplaceCps End: ", docDest); */
  600. #endif
  601. }
  602. /* A D J P A R A S */
  603. AdjParas(docDest, cpDest, docSrc, cpFirstSrc, dcpLimSrc, fDel)
  604. int docDest, docSrc, fDel;
  605. typeCP cpDest, cpFirstSrc, dcpLimSrc;
  606. { /* Mark display lines showing the section/paragraph containing cpDest
  607. in docDest as invalid if the range cpFirstSrc through cpLimSrc-1
  608. in docSrc contains end-of-section/end-of-paragraph marks */
  609. typeCP cpFirstPara, cpFirstSect;
  610. typeCP cpLimSrc = cpFirstSrc + dcpLimSrc;
  611. #ifdef CASHMERE /* In WRITE, the document is one big section */
  612. CacheSect(docSrc, cpFirstSrc);
  613. if (cpLimSrc >= vcpLimSectCache)
  614. { /* Sel includes sect mark */
  615. typeCP dcp;
  616. CacheSect(docDest, cpDest);
  617. dcp = cpDest - vcpFirstSectCache;
  618. AdjustCp(docDest, vcpFirstSectCache, dcp, dcp);
  619. }
  620. #endif
  621. CachePara(docSrc, cpFirstSrc);
  622. if (cpLimSrc >= vcpLimParaCache)
  623. { /* Diddling with a para return */
  624. typeCP dcp, cpLim;
  625. typeCP cpMacT = (**hpdocdod)[docDest].cpMac;
  626. typeCP cpFirst;
  627. if ((cpDest == cpMacT) && (cpMacT != cp0))
  628. {
  629. CachePara(docDest, cpDest-1);
  630. cpLim = cpMacT + 1;
  631. }
  632. else
  633. {
  634. CachePara(docDest, cpLim = cpDest);
  635. }
  636. cpFirst = vcpFirstParaCache;
  637. /* invalidate at least from cpFirst to cpLim */
  638. /* cpFirst is start of disturbed para in destination doc */
  639. /* next few lines check for effect of the edit on the semi-paragraph after
  640. the last paragraph mark in the document.
  641. Note: cpLimSrc is redefined as the point of insertion if !fDel.
  642. If fDel, Src and Dest documents are the same.
  643. */
  644. if (!fDel)
  645. cpLimSrc = cpFirstSrc;
  646. if (cpLimSrc <= cpMacT)
  647. {
  648. /* if a paragraph exists at the end of the disturbance, is it the last
  649. semi-paragraph? */
  650. CachePara(docDest, cpLimSrc);
  651. if (vcpLimParaCache > cpMacT)
  652. /* yes, extend invalidation over the semi-para */
  653. cpLim = cpMacT + 1;
  654. }
  655. else
  656. cpLim = cpMacT + 1;
  657. dcp = cpLim - cpFirst;
  658. AdjustCp(docDest, cpFirst, dcp, dcp);
  659. }
  660. }
  661. int IcpSearch(cp, rgfoo, cchFoo, bcp, ifooLim)
  662. typeCP cp;
  663. CHAR rgfoo[];
  664. unsigned cchFoo;
  665. unsigned bcp;
  666. unsigned ifooLim;
  667. { /* Binary search a table for cp; return index of 1st >= cp */
  668. unsigned ifooMin = 0;
  669. while (ifooMin + 1 < ifooLim)
  670. {
  671. int ifooGuess = (ifooMin + ifooLim - 1) >> 1;
  672. typeCP cpGuess;
  673. if ((cpGuess = *(typeCP *) &rgfoo[cchFoo * ifooGuess + bcp]) < cp)
  674. ifooMin = ifooGuess + 1;
  675. else if (cpGuess > cp)
  676. ifooLim = ifooGuess + 1;
  677. else
  678. return ifooGuess;
  679. }
  680. return ifooMin;
  681. } /* end of I c p S e a r c h */
  682. DelFtns(doc, cpFirst, cpLim)
  683. typeCP cpFirst, cpLim;
  684. int doc;
  685. { /* Delete all footnote text corresponding to refs in [cpFirst:cpLim) */
  686. /* Also delete SED's for section marks. */
  687. struct FNTB **hfntb;
  688. struct SETB **hsetb;
  689. struct PGTB **hpgtb;
  690. struct DOD *pdod;
  691. #ifdef FOOTNOTES
  692. if ((hfntb = HfntbGet(doc)) != 0)
  693. RemoveDelFtnText(doc, cpFirst, cpLim, hfntb);
  694. #endif /* FOOTNOTES */
  695. #ifdef CASHMERE
  696. if ((hsetb = HsetbGet(doc)) != 0)
  697. RemoveDelSeds(doc, cpFirst, cpLim, hsetb);
  698. #endif
  699. pdod = &(**hpdocdod)[doc];
  700. if (pdod->dty == dtyNormal && (hpgtb = pdod->hpgtb) != 0)
  701. RemoveDelPgd(doc, cpFirst, cpLim, hpgtb);
  702. }
  703. AdjRg(pfoo, cchFoo, bcp, ccp, cp, dcpAdj)
  704. register CHAR *pfoo;
  705. int cchFoo, bcp, ccp;
  706. typeCP cp, dcpAdj;
  707. { /* Adjust cp's in an array */
  708. pfoo += bcp;
  709. while (ccp-- && *(typeCP *)((pfoo -= cchFoo)) >= cp)
  710. *(typeCP *)(pfoo) += dcpAdj;
  711. }
  712. DeleteSel()
  713. { /* Delete a selection */
  714. typeCP cpFirst;
  715. typeCP cpLim;
  716. typeCP dcp;
  717. cpFirst = selCur.cpFirst;
  718. cpLim = selCur.cpLim;
  719. NoUndo(); /* We don't want any combining of adjacents for this operation */
  720. SetUndo(uacDelNS, docCur, cpFirst, dcp = cpLim - cpFirst,
  721. docNil, cpNil, cp0, 0);
  722. Replace(docCur, cpFirst, dcp, fnNil, fc0, fc0);
  723. vfSeeSel = true;
  724. vfPictSel = false;
  725. return ferror;
  726. }
  727. FWriteOk( fwc )
  728. int fwc;
  729. { /* Test whether the edit operation specified by fwc is acceptable.
  730. Assume the operation is to be performed on selCur in docCur.
  731. Return TRUE if the operation is acceptable; FALSE otherwise */
  732. extern int vfOutOfMemory;
  733. return !vfOutOfMemory;
  734. }
  735. /* S E T U N D O */
  736. SetUndo(uac, doc, cp, dcp, doc2, cp2, dcp2, itxb)
  737. int uac, doc, doc2;
  738. typeCP cp, dcp, cp2, dcp2;
  739. short itxb;
  740. {/* Set up the UNDO structure, vuab, in response to an editing operation */
  741. struct DOD *pdod, *pdodUndo;
  742. /* Group delete operations together with adjacent deletes or replaces */
  743. /* WRITE needs the replace case since AlphaMode is treated as a big */
  744. /* replace operation */
  745. if (uac == uacDelNS && doc == vuab.doc)
  746. {
  747. if ((vuab.uac == uacDelNS) || (vuab.uac == uacReplNS))
  748. {
  749. typeCP cpUndoAdd;
  750. if (cp == vuab.cp)
  751. {
  752. cpUndoAdd = CpMacText( docUndo );
  753. goto UndoAdd;
  754. }
  755. else if (cp + dcp == vuab.cp)
  756. {
  757. cpUndoAdd = cp0;
  758. UndoAdd: ReplaceCps( docUndo, cpUndoAdd, cp0, doc, cp, dcp );
  759. if (vuab.uac == uacDelNS)
  760. vuab.dcp += dcp;
  761. else
  762. vuab.dcp2 += dcp;
  763. goto SURet;
  764. }
  765. else if (vuab.uac == uacReplNS && cp == vuab.cp + vuab.dcp)
  766. { /* Special case for combining insertions --
  767. do not start a new undo operation if a null
  768. deletion is done at the end of an existing replace */
  769. if (dcp == cp0)
  770. return;
  771. }
  772. }
  773. }
  774. /* Group insertions together with adjacent ins's and replaces */
  775. if (uac == uacInsert && doc == vuab.doc)
  776. {/* check for adjacent inserts */
  777. /* Because we can be popped out of Alpha Mode so easily
  778. in WRITE, we try to be smarter about combining adjacent
  779. insert operations */
  780. if (vuab.uac == uacInsert || vuab.uac == uacReplNS)
  781. {
  782. if (cp == vuab.cp + vuab.dcp)
  783. {
  784. vuab.dcp += dcp;
  785. goto SURet;
  786. }
  787. }
  788. else if (cp == vuab.cp)
  789. switch(vuab.uac)
  790. {
  791. default:
  792. break;
  793. case uacDelNS:
  794. vuab.dcp2 = vuab.dcp;
  795. vuab.uac = uacReplNS;
  796. goto repl;
  797. case uacDelBuf:
  798. vuab.uac = uacReplBuf;
  799. goto repl;
  800. case uacDelScrap:
  801. vuab.uac = uacReplScrap;
  802. repl:
  803. vuab.dcp = dcp;
  804. SetUndoMenuStr(IDSTRUndoEdit);
  805. goto SURet;
  806. }
  807. }
  808. #ifndef CASHMERE
  809. /* The use of vuab.itxb is a kludge to determine if the undo block is
  810. for a ruler change or an undone ruler change. */
  811. if (uac == uacRulerChange && vuab.uac == uacRulerChange && doc ==
  812. vuab.doc && cp == vuab.cp && vuab.itxb == 0)
  813. {
  814. /* The undo action block for the ruler change is already set. */
  815. vuab.dcp = CpMax(dcp, vuab.dcp);
  816. goto SURet;
  817. }
  818. #endif /* not CASHMERE */
  819. vuab.doc = doc;
  820. vuab.cp = cp;
  821. vuab.dcp = dcp;
  822. vuab.doc2 = doc2;
  823. vuab.cp2 = cp2;
  824. vuab.dcp2 = dcp2;
  825. vuab.itxb = itxb;
  826. /*idstrUndoBase = IDSTRUndoBase;*/
  827. switch (vuab.uac = uac)
  828. { /* Save deleted text if necessary */
  829. default:
  830. SetUndoMenuStr(IDSTRUndoEdit);
  831. break;
  832. case uacDelScrap:
  833. case uacReplScrap:
  834. /* Two-level edit; save scrap */
  835. {
  836. extern int vfOwnClipboard;
  837. if ( vfOwnClipboard )
  838. {
  839. ClobberDoc( docUndo, docScrap, cp0,
  840. CpMacText( docScrap ) );
  841. }
  842. else
  843. ClobberDoc(docUndo, docNil, cp0, cp0);
  844. SetUndoMenuStr(IDSTRUndoEdit);
  845. /* SetUndoMenuStr(uac == uacDelScrap ? IDSTRUndoCut :*/
  846. /* IDSTRUndoPaste);*/
  847. break;
  848. }
  849. case uacDelNS:
  850. /* One-level edit; save deleted text */
  851. ClobberDoc(docUndo, doc, cp, dcp);
  852. SetUndoMenuStr(IDSTRUndoEdit);
  853. /* SetUndoMenuStr(IDSTRUndoCut);*/
  854. break;
  855. case uacReplNS:
  856. /* One-level edit; save deleted text */
  857. ClobberDoc(docUndo, doc, cp, dcp2);
  858. SetUndoMenuStr(IDSTRUndoEdit);
  859. /* SetUndoMenuStr(IDSTRUndoPaste);*/
  860. break;
  861. case uacPictSel:
  862. ClobberDoc(docUndo, doc, cp, dcp);
  863. SetUndoMenuStr(IDSTRUndoEdit);
  864. /* SetUndoMenuStr(IDSTRUndoPict);*/
  865. break;
  866. case uacChLook:
  867. case uacChLookSect:
  868. SetUndoMenuStr(IDSTRUndoLook);
  869. break;
  870. #ifndef CASHMERE
  871. case uacFormatTabs:
  872. ClobberDoc(docUndo, doc, cp, dcp);
  873. SetUndoMenuStr(IDSTRUndoBase);
  874. break;
  875. case uacRepaginate:
  876. case uacFormatSection:
  877. ClobberDoc(docUndo, doc, cp, dcp);
  878. if ((**hpdocdod)[doc].hpgtb)
  879. { /* copy page table over if there is one */
  880. int cw = cwPgtbBase + (**(**hpdocdod)[doc].hpgtb).cpgdMax * cwPGD;
  881. CopyHeapTableHandle(hpdocdod,
  882. (sizeof(struct DOD) * doc) + BStructMember(DOD, hpgtb),
  883. (sizeof(struct DOD) * docUndo) + BStructMember(DOD, hpgtb),
  884. cw);
  885. }
  886. SetUndoMenuStr(IDSTRUndoBase);
  887. break;
  888. case uacRulerChange:
  889. ClobberDoc(docUndo, doc, cp, dcp2);
  890. SetUndoMenuStr(IDSTRUndoLook);
  891. /* SetUndoMenuStr(IDSTRUndoRuler);*/
  892. break;
  893. #endif /* not CASHMERE */
  894. #ifdef UPDATE_UNDO
  895. #if defined(OLE)
  896. case uacObjUpdate:
  897. ClobberDoc(docUndo, docNil, cp0, cp0);
  898. SetUndoMenuStr(IDSTRObjUndo);
  899. break;
  900. #endif
  901. #endif
  902. }
  903. if (doc != docNil)
  904. {
  905. pdod = &(**hpdocdod)[doc];
  906. pdodUndo = &(**hpdocdod)[docUndo];
  907. pdodUndo->fDirty = pdod->fDirty;
  908. pdodUndo->fFormatted = pdod->fFormatted;
  909. if (uac != uacReplScrap)
  910. /* If SetUndo is called with uacReplScrap, = COPY SCRAP */
  911. pdod->fDirty = true;
  912. }
  913. #ifdef BOGUSCS
  914. if (uac == uacMove)
  915. CheckMove();
  916. #endif
  917. SURet:
  918. if (ferror) NoUndo();
  919. return;
  920. }
  921. /* C L O B B E R D O C */
  922. ClobberDoc(docDest, docSrc, cp, dcp)
  923. int docDest, docSrc;
  924. typeCP cp, dcp;
  925. { /* Replace contents of docDest with docSrc[cp:dcp] */
  926. extern int docScrap;
  927. extern int vfOwnClipboard;
  928. struct FFNTB **hffntb;
  929. struct SEP **hsep;
  930. struct TBD (**hgtbd)[];
  931. register int bdodDest=sizeof(struct DOD)*docDest;
  932. register int bdodSrc=sizeof(struct DOD)*docSrc;
  933. #define dodDest (*((struct DOD *)(((CHAR *)(*hpdocdod))+bdodDest)))
  934. #define dodSrc (*((struct DOD *)(((CHAR *)(*hpdocdod))+bdodSrc)))
  935. /* clear out dest doc's font table - it will get a copy of source's */
  936. hffntb = HffntbGet(docDest);
  937. dodDest.hffntb = 0;
  938. /* this does nothing if hffntb is NULL (5.15.91) v-dougk */
  939. FreeFfntb(hffntb);
  940. SmashDocFce(docDest); /* font cache entries can't refer to it by doc
  941. any more */
  942. /* this does nothing (code stubbed out) (5.15.91) v-dougk */
  943. ZeroFtns(docDest); /* So ReplaceCps doesn't worry about them */
  944. ReplaceCps(docDest, cp0, dodDest.cpMac, docSrc, cp, dcp);
  945. /* Copy section properties and tab table, both of which are
  946. document properties in MEMO */
  947. CopyHeapTableHandle( hpdocdod,
  948. ((docSrc == docNil) ? -1 :
  949. bdodSrc + BStructMember( DOD, hsep )),
  950. bdodDest + BStructMember( DOD, hsep ),
  951. cwSEP );
  952. CopyHeapTableHandle( hpdocdod,
  953. ((docSrc == docNil) ? -1 :
  954. bdodSrc + BStructMember( DOD, hgtbd )),
  955. bdodDest + BStructMember( DOD, hgtbd ),
  956. cwTBD * itbdMax );
  957. }
  958. CopyHeapTableHandle( hBase, bhSrc, bhDest, cwHandle )
  959. CHAR **hBase;
  960. register int bhSrc;
  961. register int bhDest;
  962. int cwHandle;
  963. { /* Copy cwHandle words of contents from a handle located at
  964. offset (in bytes) bhSrc from the beginning of heap object
  965. hBase to a handle located at bhDest from the same base. If the
  966. destination handle is non-NULL, free it first.
  967. If bhSrc is negative, free the destination, but do not copy */
  968. int **hT;
  969. #define hSrc (*((int ***) ((*hBase)+bhSrc)))
  970. #define hDest (*((int ***) ((*hBase)+bhDest)))
  971. if (hDest != NULL)
  972. {
  973. FreeH( hDest );
  974. hDest = NULL;
  975. }
  976. if ( (bhSrc >= 0) && (hSrc != NULL) &&
  977. !FNoHeap( hT = (int **)HAllocate( cwHandle )))
  978. {
  979. blt( *hSrc, *hT, cwHandle );
  980. hDest = hT;
  981. }
  982. #undef hSrc
  983. #undef hDest
  984. }
  985. ZeroFtns(doc)
  986. { /* Remove all footnote & section references from doc */
  987. struct FNTB **hfntb;
  988. struct SETB **hsetb;
  989. #ifdef FOOTNOTES
  990. if ((hfntb = HfntbGet(doc)) != 0)
  991. {
  992. FreeH(hfntb);
  993. (**hpdocdod)[doc].hfntb = 0;
  994. }
  995. #endif /* FOOTNOTES */
  996. #ifdef CASHMERE
  997. if ((hsetb = HsetbGet(doc)) != 0)
  998. {
  999. FreeH(hsetb);
  1000. (**hpdocdod)[doc].hsetb = 0;
  1001. }
  1002. #endif
  1003. }
  1004. fnClearEdit(int nInsertingOver)
  1005. { /* CLEAR command entry point: Delete the current selection */
  1006. /**
  1007. NOTE: as of this comment, this is used:
  1008. 1) when typing over a selection (AlphaMode() in insert.c)
  1009. 2) when Pasting over a selection (fnPasteEdit in clipboard.c)
  1010. 3) when pressing the delete key
  1011. 4) for InsertObject (obj3.c)
  1012. 5) for DragDrop (obj3.c)
  1013. 6) Clear header/footer (running.c)
  1014. A similar sequence occurs when cutting to the clipboard
  1015. (fnCutEdit in clipbord.c).
  1016. Also see copying to clipboard (fnCopyEdit in clipbord.c).
  1017. (8.29.91) v-dougk
  1018. **/
  1019. if (!FWriteOk( fwcDelete ))
  1020. return TRUE;
  1021. if (selCur.cpFirst < selCur.cpLim)
  1022. {
  1023. #if defined(OLE)
  1024. /* this'll prevent us from deleting open embeds */
  1025. if (!ObjDeletionOK(nInsertingOver))
  1026. return TRUE;
  1027. /* close open links */
  1028. ObjEnumInRange(docCur,selCur.cpFirst,selCur.cpLim,ObjCloseObjectInDoc);
  1029. #endif
  1030. return DeleteSel();
  1031. }
  1032. return FALSE;
  1033. }
  1034. MergeFfntb(docSrc, docDest, cpMin, cpLim)
  1035. /* determines if the two docs font tables differ to the extent that we need
  1036. to apply a mapping sprm to the specified cp's */
  1037. int docSrc, docDest;
  1038. typeCP cpMin, cpLim;
  1039. {
  1040. struct FFNTB **hffntb;
  1041. int cftcDiffer, ftc, iffn;
  1042. struct FFN *pffn;
  1043. CHAR rgbSprm[2 + 256];
  1044. CHAR rgbFfn[ibFfnMax];
  1045. hffntb = HffntbGet(docSrc);
  1046. if (hffntb != 0)
  1047. {
  1048. cftcDiffer = 0;
  1049. for (iffn = 0; iffn < (*hffntb)->iffnMac; iffn++)
  1050. {
  1051. pffn = *(*hffntb)->mpftchffn[iffn];
  1052. bltbyte(pffn, rgbFfn, CbFromPffn(pffn));
  1053. ftc = FtcChkDocFfn(docDest, rgbFfn);
  1054. if (ftc != iffn)
  1055. cftcDiffer++;
  1056. rgbSprm[2+iffn] = ftc;
  1057. if (ftc == ftcNil)
  1058. /* we're stuck! */
  1059. return;
  1060. }
  1061. if (cftcDiffer == 0)
  1062. /* new font table is a superset, & all the old font table's
  1063. ftc's matched exactly - no need to do anything */
  1064. return;
  1065. rgbSprm[0] = sprmCMapFtc;
  1066. rgbSprm[1] = (*hffntb)->iffnMac;
  1067. /* here goes - apply the mapping */
  1068. AddSprmCps(rgbSprm, docDest, cpMin, cpLim);
  1069. }
  1070. }
  1071. 
  1072.