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.

709 lines
14 KiB

  1. /************************************************************/
  2. /* Windows Write, Copyright 1985-1992 Microsoft Corporation */
  3. /************************************************************/
  4. /* Select2.c -- Less-frequently-used 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 "kanji.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. #ifndef DBCS /* US version */
  75. /* C P L I M S T Y S P E C I A L */
  76. typeCP CpLimStySpecial(cp, sty)
  77. typeCP cp;
  78. int sty;
  79. { /* Return the first cp which is not part of the same sty unit */
  80. int wb, ch, ich;
  81. struct EDL *pedl;
  82. /* Other cases covered in CpLimSty, our only caller */
  83. Assert( cp < cpMacCur );
  84. Assert( cp >= cpMinCur );
  85. Assert( sty == styWord || sty == stySent );
  86. /* Special kludge for picture paragraphs */
  87. CachePara(docCur, cp);
  88. if (vpapAbs.fGraphics)
  89. return vcpLimParaCache;
  90. FetchCp(docCur, cp, 0, fcmChars + fcmNoExpand);
  91. Assert(vccpFetch != 0);
  92. /* Must be word or sentence */
  93. wb = WbFromCh(ch = vpchFetch[ich = 0]);
  94. #ifdef CRLF
  95. if (ch == chReturn)
  96. return vcpFetch + 2;
  97. #endif
  98. if (ch == chEol || ch == chSect || ch == chNewLine || ch == chTab)
  99. /* EOL is its own unit */
  100. return vcpFetch + 1;
  101. if (wb == wbWhite && sty == stySent)
  102. { /* Might be between sentences; go back to text */
  103. FetchCp(docCur, CpFirstSty(cp, styWord), 0, fcmChars + fcmNoExpand);
  104. wb = WbFromCh(ch = vpchFetch[ich = 0]);
  105. }
  106. for (;;)
  107. {
  108. if (++ich >= vccpFetch)
  109. { /* Get next line and set up */
  110. FetchCp(docNil, cpNil, 0, fcmChars);
  111. if (vcpFetch == cpMacCur)
  112. return cpMacCur; /* End of doc */
  113. ich = 0;
  114. }
  115. if (sty == stySent)
  116. switch (ch)
  117. {
  118. case chDot:
  119. case chBang:
  120. case chQMark:
  121. sty = styWord;
  122. wb = wbPunct;
  123. }
  124. switch (ch = vpchFetch[ich])
  125. {
  126. case chTab:
  127. case chEol:
  128. case chSect:
  129. case chNewLine:
  130. #ifdef CRLF
  131. case chReturn:
  132. #endif
  133. goto BreakFor;
  134. }
  135. if (sty == styWord)
  136. { /* Word ends after white space or on text/punct break */
  137. int wbT = WbFromCh(ch);
  138. if (wb != wbT && (wb = wbT) != wbWhite)
  139. break;
  140. }
  141. }
  142. BreakFor:
  143. return vcpFetch + ich;
  144. }
  145. /* C P F I R S T S T Y S P E C I A L */
  146. typeCP CpFirstStySpecial(cp, sty)
  147. typeCP cp;
  148. int sty;
  149. { /* Return the first cp of this sty unit. */
  150. typeCP cpBegin;
  151. int wb, ch, dcpChunk;
  152. typeCP cpSent;
  153. CHAR rgch[dcpAvgSent];
  154. int ich;
  155. typeCP cpT;
  156. /* Other cases were covered by CpFirstSty, our only caller */
  157. Assert( cp > cpMinCur );
  158. Assert( sty == stySent || sty == styWord );
  159. if (cp >= cpMacCur)
  160. cpT = cp = cpMacCur;
  161. else
  162. cpT = cp++;
  163. CachePara(docCur, cpT );
  164. if ((vcpFirstParaCache == cpT) || vpapAbs.fGraphics)
  165. return vcpFirstParaCache;
  166. dcpChunk = (sty == styWord) ? dcpAvgWord : dcpAvgSent;
  167. cpBegin = (cp > dcpChunk) ? cp - dcpChunk : cp0;
  168. FetchRgch(&ich, rgch, docCur, cpBegin, cp, dcpChunk);
  169. wb = WbFromCh(ch = rgch[--ich]);
  170. #ifdef CRLF
  171. if(cpBegin + ich == 0)
  172. return cp0;
  173. if (ch == chEol && rgch[ich-1] == chReturn) /* EOL is its own unit */
  174. return cpBegin + ich - 1;
  175. if (ch == chEol || ch == chReturn || ch == chSect || ch == chNewLine || ch == chTab)
  176. return cpBegin + ich;
  177. #else /* not CRLF */
  178. if (ch == chEol || ch == chSect || ch == chNewLine || ch == chTab) /* EOL is its own unit */
  179. return cpBegin + ich;
  180. #endif /* CRLF */
  181. if (wb == wbText)
  182. cpSent = cpBegin + ich;
  183. else
  184. cpSent = cpNil;
  185. for (;;)
  186. {
  187. if (ich == 0)
  188. {
  189. if (cpBegin == cpMinCur)
  190. return cpMinCur; /* beginning of doc */
  191. cpBegin = (cpBegin > dcpChunk) ? cpBegin - dcpChunk : cp0;
  192. FetchRgch(&ich, rgch, docCur, cpBegin, cp, dcpChunk);
  193. }
  194. ch = rgch[--ich];
  195. CachePara( docCur, cpBegin + ich ); /* Needed for pictures */
  196. if (ch == chEol || ch == chSect || ch == chNewLine ||
  197. ch == chTab || vpapAbs.fGraphics )
  198. break; /* EOL Always ends a unit */
  199. if (sty == styWord)
  200. {
  201. if (wb != wbWhite)
  202. {
  203. if (WbFromCh(ch) != wb)
  204. break;
  205. }
  206. else
  207. wb = WbFromCh(ch);
  208. }
  209. else
  210. { /* Test for sentence. */
  211. switch (ch)
  212. {
  213. case chDot:
  214. case chBang:
  215. case chQMark:
  216. if (cpSent != cpNil)
  217. return cpSent;
  218. }
  219. switch (WbFromCh(ch))
  220. {
  221. case wbText:
  222. cpSent = cpBegin + ich;
  223. wb = wbText;
  224. break;
  225. case wbPunct:
  226. switch (wb)
  227. {
  228. case wbWhite:
  229. wb = wbPunct;
  230. break;
  231. case wbText:
  232. cpSent = cpBegin + ich;
  233. }
  234. break;
  235. case wbWhite:
  236. if (wb == wbPunct)
  237. cpSent = cpBegin + ich + 1;
  238. wb = wbWhite;
  239. break;
  240. }
  241. }
  242. }
  243. return cpBegin + ich + 1;
  244. }
  245. #else /* DBCS version */
  246. typeCP CpLimStySpecial(cp, sty)
  247. typeCP cp;
  248. int sty;
  249. {
  250. CHAR rgch[cchKanji];
  251. int ch, ch2;
  252. int ich, wb;
  253. typeCP cpLim, cpT;
  254. /* Other cases covered in CpLimSty, our only caller */
  255. Assert(cp < cpMacCur);
  256. Assert(cp >= cpMinCur);
  257. Assert(sty == styWord || sty == stySent);
  258. /* Picture paragraph? */
  259. CachePara(docCur, cp);
  260. if (vpapAbs.fGraphics) {
  261. return vcpLimParaCache;
  262. }
  263. cpLim = vcpLimParaCache;
  264. if (vcpLimParaCache > cpMacCur) {
  265. /* No EOL at end of doc */
  266. cpLim = cpMacCur;
  267. }
  268. FetchRgch(&ich, rgch, docCur, cp,
  269. ((cpT = cp + cchKanji) < cpLim) ? cpT : cpLim, cchKanji);
  270. ch = rgch[0];
  271. #ifdef CRLF
  272. if (ch == chReturn) {
  273. return (cp + 2);
  274. }
  275. #endif /* CRLF */
  276. if (ch == chEol || ch == chSect || ch == chNewLine || ch == chTab) {
  277. /* EOL is its own unit. */
  278. return (cp + 1);
  279. }
  280. #ifdef KOREA
  281. wb=WbFromCh(ch);
  282. #else
  283. if (FKanji1(ch)) {
  284. wb = WbFromKanjiChCh(ch, (int) rgch[1]);
  285. if (sty == styWord && wb == wbKanjiText) {
  286. return (CpLimSty(cp, styChar));
  287. }
  288. else {
  289. if (wb == wbKanjiText) {
  290. wb = wbKanjiTextFirst;
  291. }
  292. }
  293. }
  294. else {
  295. if (sty == styWord && FKanaText(ch)) {
  296. return (CpLimSty(cp, styChar));
  297. }
  298. wb = WbFromCh(ch);
  299. }
  300. #endif
  301. for (; cp < cpLim;) {
  302. int wbT;
  303. if (sty == stySent) {
  304. if (FKanji1(ch)) {
  305. CHAR ch2;
  306. ch2 = rgch[1];
  307. if (FKanjiKuten(ch, ch2) ||
  308. FKanjiQMark(ch, ch2) ||
  309. FKanjiBang(ch, ch2) ||
  310. FKanjiPeriod(ch, ch2)) {
  311. sty = styWord;
  312. wb = wbPunct;
  313. goto lblNextFetch;
  314. }
  315. }
  316. else {
  317. switch (ch) {
  318. #ifndef KOREA
  319. case bKanjiKuten:
  320. #endif
  321. case chDot:
  322. case chBang:
  323. case chQMark:
  324. sty = styWord;
  325. wb = wbPunct;
  326. goto lblNextFetch;
  327. }
  328. }
  329. }
  330. switch (ch) {
  331. case chTab:
  332. case chEol:
  333. case chSect:
  334. case chNewLine:
  335. #ifdef CRLF
  336. case chReturn:
  337. #endif /* CRLF */
  338. return cp;
  339. }
  340. if (sty == styWord) {
  341. #ifdef KOREA
  342. wbT = WbFromCh(ch);
  343. #else
  344. if (FKanji1(ch)) {
  345. wbT = WbFromKanjiChCh(ch, (int) rgch[1]);
  346. }
  347. else {
  348. wbT = WbFromCh(ch);
  349. }
  350. #endif
  351. if (wb != wbT && (wb = wbT) != wbWhite) {
  352. return (cp);
  353. }
  354. }
  355. lblNextFetch:
  356. cp = CpLimSty(cp, styChar);
  357. if (cp < cpLim) {
  358. /* Save some time and an untimely demise.... */
  359. FetchRgch(&ich, rgch, docCur, cp,
  360. ((cpT = cp + cchKanji) < cpLim) ? cpT : cpLim, cchKanji);
  361. ch = rgch[0];
  362. }
  363. }
  364. return (cpLim);
  365. }
  366. typeCP CpFirstStySpecial(cp, sty)
  367. typeCP cp;
  368. int sty;
  369. { /* Return the first cp of this sty unit. */
  370. typeCP cpT, cpLim, cpFirstPara,
  371. cpFirstLastSent; /* cpFirst of the last possible sentence boundary */
  372. CHAR rgch[cchKanji];
  373. int ch;
  374. int wb;
  375. int ich;
  376. /* Other cases were covered by CpFirstSty, our only caller */
  377. Assert( cp > cpMinCur );
  378. Assert(CpFirstSty(cp, styChar) == cp); /* cp is on a char boundary */
  379. Assert( sty == stySent || sty == styWord );
  380. cpT = cp;
  381. if (cp >= cpMacCur) {
  382. cpT = cp = cpMacCur;
  383. }
  384. CachePara(docCur, cpT );
  385. cpFirstPara = vcpFirstParaCache;
  386. if ((vcpFirstParaCache == cpT) || vpapAbs.fGraphics) {
  387. return vcpFirstParaCache;
  388. }
  389. #ifdef CRLF
  390. /* CR-LF is assumed. */
  391. Assert(TRUE);
  392. #else
  393. Assert(FALSE);
  394. #endif /* CRLF */
  395. FetchRgch(&ich, rgch, docCur, cp,
  396. ((cpT = cp + cchKanji) < cpMacCur) ? cpT : cpMacCur, cchKanji);
  397. ch = rgch[0];
  398. if (ich == cchKanji && ch == chReturn && rgch[1] == chEol) {
  399. /* EOL is its own unit */
  400. return cp;
  401. }
  402. if (ch == chEol || ch == chReturn || ch == chSect ||
  403. ch == chNewLine || ch == chTab) {
  404. return cp;
  405. }
  406. cpFirstLastSent = cpNil;
  407. #ifdef KOREA
  408. wb = WbFromCh(ch);
  409. #else
  410. if (FKanji1(ch)) {
  411. wb = WbFromKanjiChCh(ch, (int) rgch[1]);
  412. if (sty == styWord && wb == wbKanjiText) {
  413. return (CpFirstSty(cp, styChar));
  414. }
  415. else {
  416. if (wb == wbKanjiText) {
  417. wb = wbKanjiTextFirst;
  418. }
  419. }
  420. }
  421. else {
  422. if (sty == styWord && FKanaText(ch)) {
  423. return (CpFirstSty(cp, styChar));
  424. }
  425. wb = WbFromCh(ch);
  426. }
  427. #endif
  428. for (; cpFirstPara < cp; ) {
  429. typeCP cpTemp;
  430. int wbT;
  431. cpTemp = CpFirstSty(cp - 1, styChar);
  432. FetchRgch(&ich, rgch, docCur, cpTemp,
  433. ((cpT = cpTemp + cchKanji) < cpMacCur) ? cpT : cpMacCur, cchKanji);
  434. ch = rgch[0];
  435. #ifdef KOREA
  436. wbT = WbFromCh(ch);
  437. #else
  438. if (FKanji1(ch)) {
  439. wbT = WbFromKanjiChCh(ch, (int) rgch[1]);
  440. }
  441. else {
  442. wbT = WbFromCh(ch);
  443. }
  444. #endif
  445. if (wb == wbWhite) {
  446. #ifdef KOREA
  447. wb=wbT;
  448. #else
  449. wb = (wbT == wbKanjiText) ? wbKanjiTextFirst : wbT;
  450. #endif
  451. }
  452. else if (wb != wbT) {
  453. if (sty == styWord) {
  454. return (cp);
  455. }
  456. else /* sty == stySent */ {
  457. /* wb != wbWhite */
  458. /* wb != wbT */
  459. if (wbT == wbWhite || wbT == wbPunct) {
  460. cpFirstLastSent = cp;
  461. wb = wbWhite;
  462. }
  463. }
  464. }
  465. if (sty == stySent) { /* for the sentence */
  466. if (FKanji1(ch)) {
  467. int ch2;
  468. ch2 = rgch[1];
  469. if (FKanjiKuten(ch, ch2) ||
  470. FKanjiQMark(ch, ch2) ||
  471. FKanjiBang(ch, ch2) ||
  472. FKanjiPeriod(ch, ch2)) {
  473. if (cpFirstLastSent != cpNil) {
  474. return (cpFirstLastSent);
  475. }
  476. else {
  477. cpFirstLastSent = cp;
  478. }
  479. }
  480. }
  481. else {
  482. switch(ch) {
  483. #ifndef KOREA
  484. case bKanjiKuten:
  485. #endif
  486. case chDot:
  487. case chBang:
  488. case chQMark:
  489. if (cpFirstLastSent != cpNil) {
  490. return (cpFirstLastSent);
  491. }
  492. else {
  493. cpFirstLastSent = cp;
  494. }
  495. }
  496. }
  497. }
  498. cp = cpTemp;
  499. }
  500. return (cpFirstPara);
  501. }
  502. #endif /* DBCS */
  503. /* W B F R O M C H */
  504. int WbFromCh(ch)
  505. int ch;
  506. { /* Return word-breakness of ch */
  507. #if defined(DBCS) & !defined(KOREA) /* was in JAPAN; KenjiK '90-10-29 */
  508. /* Brought from WIN2 source. */
  509. if (FKanaPunct(ch)) {
  510. return wbPunct;
  511. }
  512. else if (FKanaText(ch)) {
  513. return wbKanjiText;
  514. }
  515. #endif
  516. switch (ch)
  517. {
  518. case chSpace:
  519. case chEol:
  520. #ifdef CRLF
  521. case chReturn:
  522. #endif
  523. case chSect:
  524. case chTab:
  525. case chNewLine:
  526. case chNBSFile:
  527. return wbWhite;
  528. case chNRHFile:
  529. return wbText;
  530. default: /* we are using the ANSI char set that windows used */
  531. #ifdef KOREA
  532. return ((isalpha(ch) || isdigit(ch) || ((ch>0x81)&&(ch<0xfe)))? wbText : wbPunct);
  533. #else
  534. return ((isalpha(ch) || isdigit(ch))? wbText : wbPunct);
  535. #endif
  536. }
  537. }
  538. #ifdef DBCS /* was in JAPAN; KenjiK '90-10-29 */
  539. /* Brought from WIN2 source. */
  540. int WbFromKanjiChCh(ch1, ch2)
  541. int ch1, ch2;
  542. {
  543. if (ch1 == chReturn && ch2 == chEol) {
  544. return wbWhite;
  545. }
  546. else if (FKanjiSpace(ch1, ch2)) {
  547. return wbWhite;
  548. }
  549. else
  550. #ifdef JAPAN
  551. {
  552. switch (ch1) {
  553. case 0x81:
  554. if (0x57 <= ch2 && ch2 <= 0x59) {
  555. return wbKanjiText;
  556. }
  557. else {
  558. return wbPunct;
  559. }
  560. case 0x85:
  561. if ((0x40 <= ch2 && ch2 <= 0x4E) ||
  562. (0x59 <= ch2 && ch2 <= 0x5F) ||
  563. (0x7A <= ch2 && ch2 <= 0x7E) ||
  564. (0x9B <= ch2 && ch2 <= 0xA3) ||
  565. (0xDC <= ch2 && ch2 <= 0xDD)) {
  566. return wbPunct;
  567. }
  568. else {
  569. return wbKanjiText;
  570. }
  571. case 0x86:
  572. return wbPunct;
  573. case 0x87:
  574. return ((ch2 >= 0x90) ? wbPunct : wbKanjiText);
  575. default:
  576. return wbKanjiText;
  577. }
  578. }
  579. #endif
  580. #ifdef KOREA
  581. {
  582. switch (ch1) {
  583. case 0xa2:
  584. if (0xde <= ch2 && ch2 <= 0xe5) {
  585. return wbText; // wbKanjiText; MSCH bklee 01/26/95
  586. }
  587. else {
  588. return wbPunct;
  589. }
  590. case 0xa3:
  591. if ((0xa1 <= ch2 && ch2 <= 0xaf) ||
  592. (0xba <= ch2 && ch2 <= 0xc0) ||
  593. (0xdb <= ch2 && ch2 <= 0xe0) ||
  594. (0xfb <= ch2 && ch2 <= 0xfe)) {
  595. return wbPunct;
  596. }
  597. else {
  598. return wbText; //wbKanjiText; MSCH bklee 01/26/95
  599. }
  600. default:
  601. return wbText; //wbKanjiText; MSCH bklee 01/26/95
  602. }
  603. }
  604. #endif
  605. #ifdef PRC // brucere 11/16/95
  606. {
  607. switch (ch1) {
  608. case 0xA1:
  609. return wbPunct;
  610. case 0xA3:
  611. if ((0xA1 <= ch2 && ch2 <= 0xAF) ||
  612. (0xBA <= ch2 && ch2 <= 0xC0) ||
  613. (0xDB <= ch2 && ch2 <= 0xE0) ||
  614. (0xFB <= ch2 && ch2 <= 0xFE))
  615. return wbPunct;
  616. else
  617. return wbKanjiText;
  618. case 0xA4:
  619. if (ch2 == 0x92)
  620. return wbPunct;
  621. else
  622. return wbKanjiText;
  623. default:
  624. return wbKanjiText;
  625. }
  626. }
  627. #elif TAIWAN
  628. {
  629. switch (ch1) {
  630. case 0xA1:
  631. if (0x41 <= ch2 && ch2 <= 0xAC)
  632. return wbPunct;
  633. else
  634. return wbKanjiText;
  635. default:
  636. return wbKanjiText;
  637. }
  638. }
  639. #endif
  640. }
  641. #endif
  642.