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.

806 lines
22 KiB

  1. /************************************************************/
  2. /* Windows Write, Copyright 1985-1992 Microsoft Corporation */
  3. /************************************************************/
  4. /* select.c -- MW selection routines */
  5. #define NOCLIPBOARD
  6. #define NOGDICAPMASKS
  7. #define NOCTLMGR
  8. #define NOVIRTUALKEYCODES
  9. #define NOWINMESSAGES
  10. #define NOWINSTYLES
  11. #define NOSYSMETRICS
  12. #define NOMENUS
  13. #define NOSOUND
  14. #define NOCOMM
  15. #define NOPEN
  16. #define NOWNDCLASS
  17. #define NOICON
  18. #define NORASTEROPS
  19. #define NOSHOWWINDOW
  20. #define NOATOM
  21. #define NOKEYSTATE
  22. #define NOSYSCOMMANDS
  23. #define NOBITMAP
  24. #define NOBRUSH
  25. #define NOCOLOR
  26. #define NODRAWTEXT
  27. #define NOMB
  28. #define NOPOINT
  29. #define NOMSG
  30. #include <windows.h>
  31. #include "mw.h"
  32. #include "toolbox.h"
  33. #include "docdefs.h"
  34. #include "editdefs.h"
  35. #include "dispdefs.h"
  36. #include "cmddefs.h"
  37. #include "wwdefs.h"
  38. #include "ch.h"
  39. #include "fmtdefs.h"
  40. #include "propdefs.h"
  41. #ifdef DBCS
  42. #include "DBCS.h"
  43. #endif
  44. extern int vfSeeSel;
  45. extern typeCP vcpFirstParaCache;
  46. extern typeCP vcpLimParaCache;
  47. extern typeCP vcpFetch;
  48. extern CHAR *vpchFetch;
  49. extern int vccpFetch;
  50. extern typeCP cpMinCur;
  51. extern typeCP cpMacCur;
  52. extern struct SEL selCur;
  53. extern int docCur;
  54. extern struct FLI vfli;
  55. extern struct WWD rgwwd[];
  56. extern int vfSelHidden;
  57. extern int wwCur;
  58. extern struct CHP vchpFetch;
  59. extern struct PAP vpapAbs;
  60. extern struct WWD *pwwdCur;
  61. extern int vfInsEnd;
  62. extern typeCP CpBeginLine();
  63. extern int vfPictSel;
  64. extern int vfSizeMode;
  65. extern struct CHP vchpNormal;
  66. extern int vfInsertOn;
  67. extern struct CHP vchpSel; /* Holds the props when the selection
  68. is an insert point */
  69. extern int vfMakeInsEnd;
  70. extern typeCP vcpSelect;
  71. extern int vfSelAtPara;
  72. /* true iff the last selection was made by an Up/Down cursor key */
  73. extern int vfLastCursor;
  74. extern int vfDidSearch;
  75. extern typeCP cpWall;
  76. /* C P L I M S T Y */
  77. typeCP CpLimSty(cp, sty)
  78. typeCP cp;
  79. int sty;
  80. { /* Return the first cp which is not part of the same sty unit */
  81. typeCP CpLastStyChar(), CpLimStySpecial();
  82. int wb, ch, ich;
  83. struct EDL *pedl;
  84. if (cp >= cpMacCur)
  85. { /* Endmark is own unit */
  86. return cpMacCur;
  87. }
  88. if (cp < cpMinCur)
  89. cp = cpMinCur;
  90. switch (sty)
  91. {
  92. int dl;
  93. default:
  94. Assert( FALSE );
  95. case styNil:
  96. return cp;
  97. case styPara:
  98. CachePara(docCur, cp);
  99. if (vcpLimParaCache > cpMacCur)
  100. { /* No EOL at end of doc */
  101. return cpMacCur;
  102. }
  103. return vcpLimParaCache;
  104. case styChar:
  105. /* Because CpLastStyChar() could be returning cpMacCur already. */
  106. cp = CpLastStyChar( cp ) + 1;
  107. return ((cp <= cpMacCur) ? cp : cpMacCur);
  108. #ifdef BOGUS
  109. /* This portion never gets executed... Why is it in here! */
  110. CachePara(docCur, cp);
  111. if (vpapAbs.fGraphics /* && cp > vcpFirstParaCache */)
  112. return vcpLimParaCache;
  113. #ifdef CRLF
  114. FetchCp(docCur, cp, 0, fcmChars + fcmNoExpand);
  115. return *vpchFetch == chReturn ? cp + 2 : cp + 1;
  116. #else /* not CRLF */
  117. return cp + 1;
  118. #endif
  119. #endif
  120. case styLine:
  121. CpBeginLine(&dl, cp); /* Scrolls cp vertically into view */
  122. pedl = &(**wwdCurrentDoc.hdndl) [dl];
  123. return CpMin(pedl->cpMin + pedl->dcpMac, cpMacCur);
  124. case styDoc:
  125. return cpMacCur;
  126. case styWord:
  127. case stySent:
  128. #ifdef DBCS
  129. return CpLimStySpecial( CpFirstSty(cp, styChar), sty );
  130. #else
  131. return CpLimStySpecial( cp, sty );
  132. #endif /* DBCS */
  133. }
  134. Assert( FALSE );
  135. }
  136. typeCP CpLastStyChar( cp )
  137. typeCP cp;
  138. { /* Return the last cp of the styChar containing cp */
  139. /* This will be == cp except for pictures & CR-LF */
  140. /* And the second byte of DBCS char's. */
  141. #ifdef DBCS
  142. typeCP CpFirstSty();
  143. CHAR chRetained;
  144. #endif
  145. if (cp >= cpMacCur)
  146. /* Endmark is own unit */
  147. return cpMacCur;
  148. if (cp < cpMinCur)
  149. cp = cpMinCur;
  150. /* Check for picture */
  151. CachePara(docCur, cp);
  152. if (vpapAbs.fGraphics)
  153. return vcpLimParaCache-1;
  154. /* Check for CR-LF */
  155. /* This checking for CR-LF first based on the carriage return */
  156. /* works only becasue the chReturn is outside of the DBCS */
  157. /* range. */
  158. #ifdef CRLF
  159. FetchCp(docCur, cp, 0, fcmChars + fcmNoExpand);
  160. #ifdef DBCS
  161. if ((chRetained = *vpchFetch) == chReturn) {
  162. return cp + 1;
  163. }
  164. else {
  165. if (CpFirstSty(cp, styChar) != cp) {
  166. return cp; /* cp is pointing to the second byte of DBCS. */
  167. }
  168. else {
  169. /* First byte of DBCS or a regular ASCII char. */
  170. return (IsDBCSLeadByte(chRetained) ? cp + 1 : cp);
  171. }
  172. }
  173. #else
  174. return *vpchFetch == chReturn ? cp + 1 : cp;
  175. #endif /* DBCS */
  176. #else
  177. return cp;
  178. #endif
  179. }
  180. /* C P F I R S T S T Y */
  181. typeCP CpFirstSty(cp, sty)
  182. typeCP cp;
  183. int sty;
  184. { /* Return the first cp of this sty unit. */
  185. typeCP CpFirstStySpecial();
  186. typeCP cpBegin;
  187. int wb, ch, dcpChunk;
  188. typeCP cpSent;
  189. CHAR rgch[dcpAvgSent];
  190. int ich;
  191. typeCP cpT;
  192. if (cp <= cpMinCur)
  193. return cpMinCur;
  194. else if (cp >= cpMacCur)
  195. switch(sty)
  196. {
  197. case styNil:
  198. case styChar:
  199. return cpMacCur; /* Endmark is own unit */
  200. default:
  201. break;
  202. }
  203. CachePara( docCur, cp );
  204. switch (sty)
  205. {
  206. default:
  207. Assert( FALSE );
  208. case styNil:
  209. return cp;
  210. case styPara:
  211. return vcpFirstParaCache;
  212. case styChar:
  213. if (vpapAbs.fGraphics)
  214. return vcpFirstParaCache;
  215. #ifdef CRLF
  216. {
  217. typeCP cpCheckReturn;
  218. typeCP cpMinScan;
  219. cpCheckReturn = CpMax( cp, (typeCP) 1) - 1;
  220. #ifdef DBCS
  221. /* Save vcpFirstParaCache, because it could be changed
  222. by FetchCp() */
  223. cpMinScan = vcpFirstParaCache;
  224. #endif /* DBCS */
  225. FetchCp( docCur, cpCheckReturn, 0, fcmChars + fcmNoExpand );
  226. #ifdef DBCS
  227. /* This works because chReturn is outside of DBCS range. */
  228. if (*vpchFetch == chReturn) {
  229. return cpCheckReturn;
  230. }
  231. else {
  232. typeCP cpT;
  233. typeCP cpRgMin;
  234. int ichMacRgch;
  235. BOOL fBreakFound;
  236. int fkCur;
  237. cpT = cp;
  238. do {
  239. cpRgMin = CpMax( cpT - dcpAvgSent, cpMinScan);
  240. FetchRgch(&ichMacRgch, rgch, docCur, cpRgMin, cpT,
  241. dcpAvgSent);
  242. ich = ichMacRgch - 1;
  243. fBreakFound = FALSE;
  244. while (ich >= 0 && !fBreakFound) {
  245. if (!IsDBCSLeadByte(rgch[ich])) {
  246. fBreakFound = TRUE;
  247. }
  248. else {
  249. ich--;
  250. }
  251. }
  252. cpT = cpRgMin;
  253. } while (!fBreakFound && cpRgMin > cpMinScan);
  254. if (fBreakFound) {
  255. ich++;
  256. }
  257. else {
  258. ich = 0;
  259. }
  260. fkCur = fkNonDBCS;
  261. cpT = cpRgMin + ichMacRgch;
  262. do {
  263. while (ich < ichMacRgch) {
  264. if (fkCur == fkDBCS1) {
  265. /* Last rgch[] ended with the first byte
  266. of a DBCS character. */
  267. fkCur = fkNonDBCS;
  268. }
  269. else if (IsDBCSLeadByte(rgch[ich])) {
  270. if (ich + 1 < ichMacRgch) {
  271. fkCur = fkNonDBCS;
  272. ich++;
  273. }
  274. else {
  275. fkCur = fkDBCS1;
  276. }
  277. }
  278. else {
  279. fkCur = fkNonDBCS;
  280. }
  281. ich++;
  282. }
  283. cpRgMin = cpT;
  284. cpT += dcpAvgSent;
  285. if (cpT <= cp) { /* Saves some time. */
  286. FetchRgch(&ichMacRgch, rgch, docCur, cpRgMin, cpT,
  287. dcpAvgSent);
  288. ich = 0;
  289. }
  290. } while (cpT <= cp);
  291. if (fkCur == fkDBCS1) {
  292. Assert(cp - 1 <= cpMacCur);
  293. return (cp - 1);
  294. }
  295. else {
  296. Assert(cp <= cpMacCur);
  297. return (cp);
  298. }
  299. }
  300. #else
  301. return *vpchFetch == chReturn ? cpCheckReturn : cp;
  302. #endif /* DBCS */
  303. }
  304. #else
  305. return cp;
  306. #endif
  307. case styDoc:
  308. return cpMinCur;
  309. case styLine:
  310. {
  311. int dlJunk;
  312. return CpBeginLine( &dlJunk, cp );
  313. }
  314. case styWord:
  315. case stySent:
  316. #ifdef DBCS
  317. return CpFirstStySpecial( CpFirstSty(cp, styChar), sty );
  318. #else
  319. return CpFirstStySpecial( cp, sty );
  320. #endif /* DBCS */
  321. }
  322. Assert( FALSE );
  323. }
  324. /* S E L E C T */
  325. /* used to make a selection from a cp-interval, for example after a find. */
  326. Select(cpFirst, cpLim)
  327. typeCP cpFirst, cpLim;
  328. { /* Make a selection */
  329. typeCP cpFirstOld = selCur.cpFirst;
  330. typeCP cpLimOld = selCur.cpLim;
  331. int fOldCursorLine;
  332. if (cpFirst > cpLim)
  333. /* The only time this condition should be true is when we have
  334. run out of memory. The following is a senario where
  335. such is the case (and actually, the reason for this code change).
  336. Let us suppose that we have cut, pasted to the end of the
  337. document, and are now executing a "command a" (repeat last
  338. operation). The procedure CmdAgain is invoked. CmdAgain first
  339. calls replace in order to add the text to the document. Now it
  340. must position the cursor properly by calling select.
  341. A SetUndo operation called by the prior paste gave us the
  342. number of bytes that were added to the document. In its call
  343. to Select, CmdAgain assumes that where it wants to position the
  344. cursor is at the old last char position plus the SetUndo quantity
  345. mentioned above. But, if the replace operation failed (due to
  346. lack of memory), CmdAgain may be trying to place the cursor beyond
  347. the physical end of the document.
  348. Other fixes of this problem, at the caller level (CmdAgain)
  349. instead of within Select, are probably "better" in the sense of
  350. programming clarity. The chosen solution has the one advantage
  351. of programming expediency. */
  352. cpFirst = cpLim;
  353. /* This statement replaces "Assert(cpFirst <= cpLim);" */
  354. vfInsEnd = fFalse;
  355. /* notation: + add highlight
  356. - remove highlight
  357. .. leave alone
  358. 00 common portion
  359. */
  360. if (!vfSelHidden)
  361. {
  362. if (cpFirst < cpFirstOld)
  363. { /* +++... */
  364. if (cpLim <= cpFirstOld)
  365. { /* +++ --- */
  366. goto SeparateSels;
  367. }
  368. else
  369. { /* +++000... */
  370. ToggleSel(cpFirst, cpFirstOld, true);
  371. if (cpLim < cpLimOld)
  372. { /* +++000--- */
  373. ToggleSel(cpLim, cpLimOld, false);
  374. }
  375. else if (cpLim > cpLimOld)
  376. { /* +++000+++ */
  377. ToggleSel(cpLimOld, cpLim, true);
  378. }
  379. /* Handle the case when old selection was an insert bar */
  380. if (cpFirstOld == cpLimOld)
  381. ToggleSel(cpFirstOld, cpLimOld, false);
  382. }
  383. }
  384. else
  385. { /* ---... */
  386. if (cpLimOld <= cpFirst)
  387. { /* --- +++ */
  388. SeparateSels:
  389. fOldCursorLine = cpFirstOld == cpLimOld;
  390. /* prevent flashing if insert point which is ON is repeatedly selected */
  391. /* conditions are: not repeated, not insert point, not ON, not at desired end of line */
  392. vfInsEnd = vfMakeInsEnd;
  393. if ( cpFirst != cpFirstOld || cpLim != cpLimOld ||
  394. !fOldCursorLine || !vfInsertOn ||
  395. selCur.fEndOfLine != vfMakeInsEnd)
  396. {
  397. selCur.fEndOfLine = vfMakeInsEnd;
  398. if (fOldCursorLine)
  399. ClearInsertLine();
  400. /* old selection is off if it was a cursor line */
  401. ToggleSel(cpFirst, cpLim, fTrue);
  402. /* otherwise the old selection is turned off AFTER the new one is made to
  403. make it look faster */
  404. if (!fOldCursorLine)
  405. ToggleSel(cpFirstOld, cpLimOld, fFalse);
  406. }
  407. }
  408. else
  409. { /* ---000... */
  410. if (cpLimOld < cpLim)
  411. { /* ---000+++ */
  412. ToggleSel(cpLimOld, cpLim, true);
  413. }
  414. else if (cpLimOld > cpLim)
  415. { /* ---000--- */
  416. ToggleSel(cpLim, cpLimOld, false);
  417. }
  418. ToggleSel(cpFirstOld, cpFirst, false);
  419. }
  420. }
  421. }
  422. selCur.cpFirst = cpFirst;
  423. selCur.cpLim = cpLim;
  424. selCur.fForward = cpFirst != cpMacCur;
  425. if (cpFirst == cpLim)
  426. {
  427. GetInsPtProps(cpFirst);
  428. vfDidSearch = FALSE; /* reestablish for searching */
  429. cpWall = cpLim;
  430. }
  431. vfLastCursor = vfSizeMode = vfPictSel = vfMakeInsEnd = false;
  432. /* Set vfPictSel iff the selection is exactly one picture */
  433. CachePara( docCur, selCur.cpFirst );
  434. if (vpapAbs.fGraphics && selCur.cpLim == vcpLimParaCache)
  435. vfPictSel = TRUE;
  436. }
  437. /* G E T I N S P T P R O P S */
  438. GetInsPtProps(cp)
  439. typeCP cp;
  440. { /* determine properties of the insertion point */
  441. if (cpMacCur != cpMinCur)
  442. {
  443. CachePara(docCur, cp);
  444. if (vcpFirstParaCache == cpMacCur)
  445. {
  446. /* cp is in the last para--use preceding para props */
  447. CachePara(docCur, vcpFirstParaCache - 1);
  448. if (vpapAbs.fGraphics)
  449. { /* Yet another 10 point kludge -- get default props
  450. when typing after a picture at doc end */
  451. goto Default;
  452. }
  453. }
  454. if (vpapAbs.fGraphics)
  455. /* 10 point kludge: make typing before picture non-vchpNormal */
  456. goto Default;
  457. FetchCp(docCur, CpMax(vcpFirstParaCache, cp - 1), 0, fcmProps);
  458. blt(&vchpFetch, &vchpSel, cwCHP);
  459. if (vchpFetch.fSpecial && vchpFetch.hpsPos != 0)
  460. { /* if this char is a footnote or page marker, then ignore */
  461. vchpSel.hpsPos = 0; /* super/subscript stuff. */
  462. vchpSel.hps = HpsAlter(vchpSel.hps, 1);
  463. }
  464. vchpSel.fSpecial = FALSE;
  465. }
  466. else
  467. {
  468. Default:
  469. /* force default character properties, font size to be 10 point */
  470. blt(&vchpNormal, &vchpSel, cwCHP);
  471. vchpSel.hps = hpsDefault;
  472. }
  473. }
  474. /* C H A N G E S E L */
  475. ChangeSel(cp, sty)
  476. typeCP cp;
  477. int sty;
  478. { /* Make selCur move, expand or contract to cp */
  479. /* sty is unit to keep in case of movement or flipped selection */
  480. /* styChar is not supported; it is munged to styNil */
  481. /* This is because the Write/Word user interface never asks us to */
  482. /* pivot the selection around a single character, we pivot around */
  483. /* an insertion point ("styNil") instead */
  484. int fNullSelection = (selCur.cpFirst == selCur.cpLim);
  485. typeCP cpFirst = selCur.cpFirst;
  486. typeCP cpLim = selCur.cpLim;
  487. int fForward = selCur.fForward;
  488. typeCP cpOffFirst, cpOffLim, cpOnFirst, cpOnLim;
  489. if (sty == styChar)
  490. sty = styNil;
  491. if (cp == cpMinCur - 1 || cp > cpMacCur)
  492. { /* Trying to flip off the beginning or end */
  493. _beep();
  494. return;
  495. }
  496. cpOffFirst = cpOffLim = cpOnFirst = cpOnLim = cpNil;
  497. if (cp <= cpFirst)
  498. { /* Extend backwards */
  499. if (cp == cpLim)
  500. return;
  501. if (fForward && !fNullSelection)
  502. { /* Selection flipped */
  503. if (vfPictSel)
  504. /* stuck this in to 'correct' behaviour when select pict and
  505. drag up. Don't want to unselect first pict (4.22.91) v-dougk */
  506. {
  507. cpOnFirst = CpFirstSty( cp, sty);
  508. cpOffFirst = cpOffLim = cpLim;
  509. }
  510. else
  511. {
  512. cpOffFirst = selCur.cpLim = CpMin(cpLim, CpLimSty(cpFirst, sty));
  513. cpOnFirst = CpFirstSty( cp, sty);
  514. cpOffLim = cpLim;
  515. }
  516. }
  517. else
  518. {
  519. if ( fNullSelection )
  520. cpOffLim = cpOffFirst = selCur.cpFirst;
  521. cpOnFirst = CpFirstSty( cp, styChar );
  522. if (cpFirst == cpOnFirst)
  523. return;
  524. }
  525. selCur.fForward = false;
  526. cpOnLim = cpFirst;
  527. selCur.cpFirst = cpOnFirst;
  528. }
  529. else if (cp >= cpLim)
  530. { /* Extend forwards */
  531. if (cp == cpFirst)
  532. return;
  533. if (!fForward && !fNullSelection)
  534. { /* Selection flipped */
  535. cpOffLim = selCur.cpFirst =
  536. CpMax( cpFirst, CpFirstSty( (sty ==styNil) ? cpLim : cpLim-1,
  537. sty ));
  538. cpOnLim = CpLimSty(cp, sty);
  539. cpOffFirst = cpFirst;
  540. }
  541. else
  542. {
  543. if ( fNullSelection )
  544. cpOffLim = cpOffFirst = selCur.cpFirst;
  545. cpOnLim = cp;
  546. if (cpLim == cpOnLim)
  547. return;
  548. }
  549. selCur.fForward = true;
  550. cpOnFirst = cpLim;
  551. selCur.cpLim = cpOnLim;
  552. if (cpOnLim == cpLim && cpOffLim != cpLim)
  553. cpOnLim = cpNil;
  554. }
  555. else if (fForward)
  556. { /* Shrink a forward selection */
  557. cpOffFirst = cp;
  558. if (selCur.cpLim == cpOffFirst)
  559. return;
  560. selCur.cpLim = cpOffFirst;
  561. cpOffLim = cpLim;
  562. }
  563. else
  564. { /* Shrink a backward selection */
  565. cpOffLim = cp;
  566. if (selCur.cpFirst == cpOffLim)
  567. return;
  568. selCur.cpFirst = cpOffLim;
  569. cpOffFirst = cpFirst;
  570. }
  571. ToggleSel(cpOnFirst, cpOnLim, true);
  572. ToggleSel(cpOffFirst, cpOffLim, false);
  573. /* Check for a stray insert point */
  574. if (selCur.cpFirst != selCur.cpLim)
  575. ClearInsertLine();
  576. /* Set vfPictSel iff the selection is exactly one picture */
  577. CachePara( docCur, selCur.cpFirst );
  578. vfPictSel = vpapAbs.fGraphics && (selCur.cpLim == vcpLimParaCache);
  579. }
  580. /* S E L E C T D L X P */
  581. SelectDlXp(dl, xp, sty, fDrag)
  582. int dl, xp, sty;
  583. int fDrag;
  584. { /* Move cursor to the nearest valid CP and select unit */
  585. typeCP cp;
  586. typeCP cpFirst;
  587. typeCP cpLim;
  588. register struct EDL *pedl;
  589. int xpStart = xpSelBar - wwdCurrentDoc.xpMin;
  590. int itcMin, itcLim;
  591. int xpLeft;
  592. int xpPos;
  593. int fPictInsertPoint=FALSE; /* Setting an insert point before a pict */
  594. UpdateWw(wwCur, false); /* Synchronize cursor & text */
  595. xp = max(0, xp - xpStart);
  596. dl = min( wwdCurrentDoc.dlMax - 1, dl );
  597. pedl = &(**wwdCurrentDoc.hdndl) [dl];
  598. cp = pedl->cpMin;
  599. /* At or Below EMark */
  600. if (cp >= cpMacCur)
  601. {
  602. cp = cpMacCur;
  603. goto FoundCp;
  604. }
  605. if (pedl->fGraphics)
  606. { /*
  607. Special kludge for selecting a picture:
  608. Select the whole picture (if the hit is inside or to the
  609. right of the picture)
  610. Select an insert point just before the picture if the hit
  611. is to the left of the picture OR in the selection bar
  612. when the picture is left-justified) */
  613. if ( (xp < pedl->xpLeft) || (sty == styLine && xp == 0) )
  614. fPictInsertPoint = TRUE;
  615. goto FoundCp;
  616. }
  617. if (sty >= styPara)
  618. { /* Selecting a paragraph, line, doc */
  619. goto FoundCp;
  620. }
  621. /* Must Format to figure out the right cp */
  622. FormatLine(docCur, cp, pedl->ichCpMin, cpMacCur, flmSandMode); /*HM*/
  623. CachePara(docCur, cp);
  624. pedl = &(**wwdCurrentDoc.hdndl) [dl];
  625. if (vfli.fSplat) /* Selecting in division/page break */
  626. {
  627. cp = vfli.cpMin;
  628. goto FoundCp;
  629. }
  630. xpLeft = pedl->xpLeft;
  631. if (vfli.xpLeft != xpLeft)
  632. /* This indicates that we are in lo memory conditions; in trouble */
  633. return;
  634. /* Assert (vfli.xpLeft == xpLeft); May not be true in lo memory */
  635. if (xp <= xpLeft)
  636. {
  637. itcMin = 0;
  638. goto FoundCp;
  639. }
  640. /* Out of bounds right */
  641. if (xp >= pedl->xpMac)
  642. {
  643. itcMin = vfli.cpMac - cp - 1;
  644. cp = vfli.cpMac - 1;
  645. goto CheckPastPara;
  646. }
  647. /* Search through the line for the cp at position xp */
  648. xpPos = xpLeft;
  649. itcMin = 0;
  650. itcLim = vfli.cpMac - cp;
  651. while (itcMin < itcLim && xpPos < xp)
  652. xpPos += vfli.rgdxp[itcMin++];
  653. if (itcMin >= 1)
  654. /* This may not be true if we are so low on memory that
  655. FormatLine could not do its job */
  656. itcMin--;
  657. cp += itcMin;
  658. CachePara(docCur, cp);
  659. if ((xpPos < xp + vfli.rgdxp[itcMin] / 2) &&
  660. (sty == styChar /* || !fDrag */) )
  661. { /* Actually selecting next character */
  662. CheckPastPara:
  663. if (cp + 1 == vcpLimParaCache && !vpapAbs.fGraphics &&
  664. (vfSelAtPara || vcpSelect == cpNil))
  665. /* Return insert point before paragraph mark */
  666. {
  667. if (vcpSelect == cpNil)
  668. vfSelAtPara = true;
  669. goto FoundCp;
  670. }
  671. itcMin++;
  672. cp++;
  673. }
  674. //T-HIROYN sync win3.0
  675. #ifdef DBCS
  676. /* if itcMin point the second char of kanji, increment itcMin */
  677. if (itcMin < itcLim && vfli.rgdxp[itcMin]==0)
  678. goto CheckPastPara; /* Select next character */
  679. #endif /* DBCS */
  680. FoundCp:
  681. /* Set up selection limits */
  682. cpFirst = CpFirstSty( cp, sty );
  683. cpLim = CpLimSty( cp, sty );
  684. if (sty == styChar)
  685. {
  686. if ( !pedl->fGraphics || fPictInsertPoint )
  687. /* In text or before a pic: don't extend to end of styChar */
  688. cpLim = cpFirst;
  689. if ( vcpSelect == cpNil )
  690. { /* First time through, remember where we started */
  691. /* Set if we want to kludge the insert point at the end of *pedl */
  692. vfMakeInsEnd = (cp == pedl->cpMin + pedl->dcpMac &&
  693. cp <= cpMacCur &&
  694. !pedl->fGraphics &&
  695. !pedl->fSplat);
  696. vcpSelect = cpFirst;
  697. }
  698. }
  699. if (fDrag)
  700. ChangeSel( selCur.fForward ? cpLim : cpFirst, sty );
  701. else
  702. Select( cpFirst, cpLim );
  703. }
  704. typeCP CpEdge()
  705. { /* Return edge of selection */
  706. return selCur.fForward ?
  707. CpMax( CpFirstSty( selCur.cpLim - 1, styChar ), selCur.cpFirst ) :
  708. selCur.cpFirst;
  709. }
  710.