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.

526 lines
14 KiB

  1. /************************************************************/
  2. /* Windows Write, Copyright 1985-1992 Microsoft Corporation */
  3. /************************************************************/
  4. /* curskeys.c-- cursor key movement subroutines */
  5. /* Oct 4, 1984, KJS */
  6. #define NOGDICAPMASKS
  7. #define NOWINMESSAGES
  8. #define NOWINSTYLES
  9. #define NOCLIPBOARD
  10. #define NOCTLMGR
  11. #define NOSYSMETRICS
  12. #define NOATOM
  13. #define NOSYSCOMMANDS
  14. #define NOCOMM
  15. #define NOSOUND
  16. #define NOMENUS
  17. #define NOGDI
  18. #define NOPEN
  19. #define NOBRUSH
  20. #define NOFONT
  21. #define NOWNDCLASS
  22. #include <windows.h>
  23. #include "mw.h"
  24. #define NOUAC
  25. #include "cmddefs.h"
  26. #include "dispdefs.h"
  27. #include "wwdefs.h"
  28. #include "ch.h"
  29. #include "docdefs.h"
  30. #include "editdefs.h"
  31. #include "propdefs.h"
  32. #include "debug.h"
  33. #include "fmtdefs.h"
  34. #include "printdef.h"
  35. struct DOD (**hpdocdod)[];
  36. extern typeCP cpMinCur;
  37. extern typeCP cpMacCur;
  38. extern struct PAP vpapAbs;
  39. extern int vfSeeSel;
  40. extern int vfShiftKey;
  41. extern struct FLI vfli;
  42. extern struct SEL selCur;
  43. extern int wwCur;
  44. extern struct WWD rgwwd[];
  45. extern struct WWD *pwwdCur; /* Current window descriptor */
  46. extern int docCur;
  47. extern typeCP vcpSelect;
  48. extern int vfSelAtPara;
  49. extern int vfLastCursor;
  50. extern int vfMakeInsEnd;
  51. extern CHAR *vpchFetch;
  52. int vfSeeEdgeSel=FALSE; /* Whether Idle() should show edge of selection
  53. even if selection is partially visible */
  54. /* Absolute x-position to try to achieve on up-down motions;
  55. used in this module only */
  56. int vxpCursor;
  57. MoveLeftRight( kc )
  58. int kc;
  59. { /* Move or drag selection in left or right directions */
  60. extern int vfInsEnd;
  61. typeCP CpEdge();
  62. extern int vfGotoKeyMode;
  63. extern int xpRightLim;
  64. int fDrag = vfShiftKey ;
  65. int fFwdKey = FALSE;
  66. int fForward = selCur.fForward;
  67. int sty;
  68. typeCP cp;
  69. MSG msg;
  70. PeekMessage(&msg, (HWND)NULL, NULL, NULL, PM_NOREMOVE);
  71. vfGotoKeyMode |= (GetKeyState( kcGoto & ~wKcCommandMask) < 0);
  72. switch( kc ) {
  73. int dl;
  74. int xp;
  75. int xpJunk;
  76. default:
  77. Assert( FALSE );
  78. return;
  79. case kcNextPara:
  80. fFwdKey = TRUE;
  81. case kcPrevPara:
  82. sty = styPara;
  83. break;
  84. case kcWordRight:
  85. fFwdKey = TRUE;
  86. case kcWordLeft:
  87. sty = styWord;
  88. break;
  89. case kcEndLine:
  90. if (vfGotoKeyMode)
  91. {
  92. MoveUpDown( kcEndDoc );
  93. return;
  94. }
  95. xp = xpRightLim;
  96. goto GoDlXp;
  97. case kcBeginLine:
  98. if (vfGotoKeyMode)
  99. {
  100. MoveUpDown( kcTopDoc );
  101. return;
  102. }
  103. xp = xpSelBar - wwdCurrentDoc.xpMin;
  104. GoDlXp:
  105. if (CpBeginLine( &dl, CpEdge() ) == selCur.cpFirst &&
  106. selCur.cpFirst > cpMinCur && vfInsEnd )
  107. {
  108. CpBeginLine( &dl, selCur.cpFirst - 1);
  109. }
  110. vcpSelect = cpNil;
  111. vfSelAtPara = false;
  112. SelectDlXp( dl, xp, styChar, fDrag );
  113. goto SeeSel;
  114. case kcRight:
  115. fFwdKey = TRUE;
  116. case kcLeft:
  117. sty = (vfGotoKeyMode) ? stySent : styChar;
  118. break;
  119. }
  120. /* Find cp to start extension from */
  121. if (selCur.cpLim == selCur.cpFirst || fDrag)
  122. cp = fForward ? selCur.cpLim : selCur.cpFirst;
  123. else
  124. cp = fFwdKey ? selCur.cpLim - 1 : selCur.cpFirst + 1;
  125. /* Catch attempts to run off the document start or end */
  126. if (fFwdKey)
  127. {
  128. if (cp == cpMacCur)
  129. {
  130. _beep();
  131. return;
  132. }
  133. }
  134. else if (cp == cpMinCur)
  135. {
  136. _beep();
  137. return;
  138. }
  139. if (fFwdKey)
  140. {
  141. if (cp >= cpMacCur)
  142. /* If at end, stay at end. */
  143. cp = cpMacCur;
  144. else
  145. {
  146. cp = CpLimSty( cp, sty );
  147. }
  148. }
  149. else
  150. {
  151. if (cp > cpMinCur)
  152. /* So we go back to the PREVIOUS sty unit */
  153. cp--;
  154. cp = CpFirstSty( cp, sty );
  155. }
  156. if (fDrag)
  157. { /* Drag selection edge to new bound. */
  158. /* If selection flips, keep one sty unit selected EXCEPT if it's styChar;
  159. when dragging by char, the selection can become an insertion point */
  160. ChangeSel( cp, sty == styChar ? styNil : sty );
  161. }
  162. else
  163. {
  164. Select(cp, cp);
  165. if (!fFwdKey)
  166. selCur.fForward = false;
  167. }
  168. SeeSel:
  169. vfSeeSel = true; /* Tell Idle to scroll the selection into view */
  170. vfSeeEdgeSel = true; /* And the edge of it even if it's already partly visible */
  171. return;
  172. }
  173. /* M O V E U P D O W N */
  174. MoveUpDown(kc)
  175. int kc;
  176. { /* Move the selection in direction of kc, in up or down directions */
  177. /* Our goal with up-and-down motions is to keep (if applicable) an */
  178. /* absolute x-position to which the cursor tends to go if there is */
  179. /* text on the line at that position. We set this position (vxpCursor) */
  180. /* when we process the first up/down key, and hang onto it thereafter */
  181. /* A global flag, vfLastCursor, tells us whether we should use the */
  182. /* last calculated setting of vxpCursor or generate a new one. vxpCursor */
  183. /* is set below and cleared in Select() and AlphaMode() */
  184. extern int vfGotoKeyMode;
  185. int fDrag = vfShiftKey;
  186. int dl;
  187. typeCP cpT;
  188. struct EDL (**hdndl)[] = wwdCurrentDoc.hdndl;
  189. register struct EDL *pedl;
  190. int dipgd;
  191. int xpNow;
  192. MSG msg;
  193. PeekMessage(&msg, (HWND)NULL, NULL, NULL, PM_NOREMOVE);
  194. vfGotoKeyMode |= (GetKeyState( kcGoto & ~wKcCommandMask) < 0);
  195. /* Compute dl, vxpCursor for selection starting point */
  196. switch (kc)
  197. {
  198. default:
  199. Assert( FALSE );
  200. break;
  201. case kcUp:
  202. if (vfGotoKeyMode)
  203. { /* GOTO-UP is Prev Para */
  204. MoveLeftRight( kcPrevPara );
  205. return;
  206. }
  207. case kcPageUp:
  208. case kcUpScrollLock:
  209. case kcTopScreen:
  210. case kcTopDoc:
  211. cpT = selCur.fForward && fDrag ? selCur.cpLim : selCur.cpFirst;
  212. break;
  213. case kcDown:
  214. if (vfGotoKeyMode)
  215. { /* GOTO-DOWN is Next Para */
  216. MoveLeftRight( kcNextPara );
  217. return;
  218. }
  219. case kcPageDown:
  220. case kcDownScrollLock:
  221. case kcEndScreen:
  222. case kcEndDoc:
  223. cpT = selCur.fForward || !fDrag ? selCur.cpLim : selCur.cpFirst;
  224. break;
  225. }
  226. CpToDlXp( cpT, &dl, (vfLastCursor) ? &xpNow : &vxpCursor );
  227. /* HACK: If the guy is dragging up/down and is on the first/last line of
  228. the doc but not right at the start/end of the doc, extend him to
  229. the start/end of the doc */
  230. if (fDrag && !vfGotoKeyMode)
  231. {
  232. switch (kc) {
  233. case kcUp:
  234. /* Special fix for dragging upward: if we are seeking up to a position
  235. that is equivalent in cp space to where we are now, force a decrement
  236. of the source dl so we really go up a line */
  237. if (vfLastCursor && xpNow <= xpSelBar && vxpCursor > xpSelBar &&
  238. cpT > cpMinCur)
  239. {
  240. CpToDlXp( CpFirstSty( cpT - 1, styChar), &dl, &xpNow );
  241. }
  242. case kcPageUp:
  243. case kcUpScrollLock:
  244. if (wwdCurrentDoc.cpFirst == cpMinCur && cpT > cpMinCur)
  245. if (dl == 0 || kc == kcPageUp)
  246. {
  247. MoveUpDown( kcTopDoc );
  248. return;
  249. }
  250. break;
  251. case kcPageDown:
  252. case kcDown:
  253. case kcDownScrollLock:
  254. {
  255. typeCP cpLimDl;
  256. pedl = &(**hdndl) [dl];
  257. cpLimDl = pedl->cpMin + pedl->dcpMac;
  258. if (cpLimDl >= cpMacCur && cpT >= pedl->cpMin && cpT < cpMacCur)
  259. {
  260. MoveUpDown( kcEndDoc );
  261. return;
  262. }
  263. break;
  264. }
  265. }
  266. }
  267. /* Do the cursor movement, scrolling if necessary */
  268. switch (kc)
  269. {
  270. case kcPageUp:
  271. if (vfGotoKeyMode)
  272. { /* Go to previous printed page */
  273. extern int vipgd;
  274. extern int rgval[];
  275. struct PGTB **hpgtb;
  276. int ipgd;
  277. dipgd = -1;
  278. CachePage( docCur, selCur.cpFirst );
  279. if (vipgd != iNil)
  280. {
  281. hpgtb = (**hpdocdod) [docCur].hpgtb;
  282. if ((**hpgtb).rgpgd [vipgd].cpMin != selCur.cpFirst)
  283. /* Not at page start; go there first */
  284. dipgd++;
  285. }
  286. GoPage: CachePage( docCur, selCur.cpFirst ); /*validate vipgd*/
  287. hpgtb = (**hpdocdod)[docCur].hpgtb;
  288. if ((vipgd == iNil) ||
  289. ((ipgd = vipgd + dipgd) < 0) ||
  290. (ipgd >= (**hpgtb).cpgd))
  291. { /*Whole doc on one page || run off either end*/
  292. _beep();
  293. }
  294. else
  295. {
  296. rgval [0] = (**hpgtb).rgpgd[ipgd].pgn;
  297. CmdJumpPage(); /* rgval [0] is a parm to CmdJumpPage */
  298. }
  299. return;
  300. }
  301. ScrollUpDypWw();
  302. break;
  303. case kcPageDown:
  304. if (vfGotoKeyMode)
  305. { /* Go to next printed page */
  306. dipgd = 1;
  307. goto GoPage;
  308. }
  309. /* Special case for extending selection one page down from the
  310. top line of the ww -- extend to the NEXT line so we don't
  311. end up without any part of the selection on the screen */
  312. ScrollDownCtr( 100 ); /* 100 > tr's in a page */
  313. vcpSelect = cpNil;
  314. vfSelAtPara = false;
  315. SelectDlXp( dl, (**hdndl)[dl].fGraphics ? 0 : vxpCursor, styChar, fDrag );
  316. if (fDrag && (dl == 0) && selCur.cpLim == wwdCurrentDoc.cpFirst)
  317. {
  318. MoveUpDown( kcDown );
  319. }
  320. goto DontSelect;
  321. case kcUpScrollLock:
  322. case kcUp:
  323. UpdateWw(wwCur, false);
  324. pedl = &(**hdndl) [dl];
  325. if ( fDrag && (selCur.fForward ? selCur.cpLim : selCur.cpFirst) ==
  326. pedl->cpMin && pedl->cpMin > cpMinCur)
  327. { /* Up into picture == left */
  328. CachePara( docCur, pedl->cpMin - 1 );
  329. if (vpapAbs.fGraphics)
  330. {
  331. MoveLeftRight( kcLeft );
  332. return;
  333. }
  334. }
  335. if ((pedl->cpMin == cpMinCur) && (pedl->ichCpMin == 0))
  336. { /* At beginning of doc or area */
  337. int xpT;
  338. _beep();
  339. CpToDlXp(cpMinCur, &dl, &xpT);
  340. goto DoSelect;
  341. }
  342. else if ( (dl == 0) || (kc == kcUpScrollLock) )
  343. { /* At top of screen OR keep posn */
  344. ScrollUpCtr( 1 );
  345. UpdateWw(wwCur, false);
  346. }
  347. else
  348. {
  349. --dl;
  350. }
  351. break;
  352. case kcDownScrollLock:
  353. case kcDown:
  354. UpdateWw(wwCur, false);
  355. pedl = &(**hdndl)[dl];
  356. {
  357. int xpT;
  358. typeCP cp;
  359. cp = pedl->cpMin + pedl->dcpMac;
  360. if (selCur.cpFirst < selCur.cpLim && selCur.fForward &&
  361. pedl->cpMin == selCur.cpLim &&
  362. cp < cpMacCur &&
  363. (!fDrag ||
  364. ((vxpCursor > pedl->xpLeft + xpSelBar) &&
  365. (pedl->dcpMac > ccpEol))))
  366. { /* In this case, it thinks we are at the start of the
  367. next line; incrementing/scrolling is unnecessary */
  368. goto DoSelect;
  369. }
  370. if (pedl->fGraphics)
  371. { /* Special for pictures */
  372. MoveLeftRight( kcRight );
  373. if (!fDrag)
  374. {
  375. extern struct PAP vpapAbs;
  376. CachePara( docCur, selCur.cpFirst );
  377. if (vpapAbs.fGraphics)
  378. {
  379. vfShiftKey = TRUE;
  380. MoveLeftRight( kcRight );
  381. SetShiftFlags();
  382. }
  383. }
  384. goto DontSelect;
  385. }
  386. if (cp > cpMacCur)
  387. {
  388. if (selCur.cpLim == selCur.cpFirst || selCur.cpLim == cpMacCur)
  389. /* test is because CpToDlXp cannot account for
  390. selection extending to end of next-to-last line */
  391. _beep();
  392. CpToDlXp(cpMacCur, &dl, &xpT);
  393. goto DoSelect;
  394. }
  395. if ( (dl >= wwdCurrentDoc.dlMac - 2) || (kc == kcDownScrollLock) )
  396. { /* within one line of window end */
  397. ScrollDownCtr( 1 );
  398. UpdateWw(wwCur, false);
  399. }
  400. else
  401. dl++;
  402. }
  403. break;
  404. case kcTopScreen:
  405. dl = 0;
  406. break;
  407. case kcEndScreen:
  408. dl = wwdCurrentDoc.dlMac - 1;
  409. if ( dl > 0 && (**wwdCurrentDoc.hdndl) [dl].yp >= wwdCurrentDoc.ypMac)
  410. { /* Back up if last (and not only) dl is partially clipped */
  411. dl--;
  412. }
  413. break;
  414. case kcTopDoc:
  415. CpToDlXp(cpMinCur, &dl, &vxpCursor);
  416. break;
  417. case kcEndDoc:
  418. CpToDlXp(cpMacCur, &dl, &vxpCursor);
  419. break;
  420. default:
  421. return;
  422. }
  423. DoSelect: /* select at/to position vxpCursor on line dl */
  424. vcpSelect = cpNil;
  425. vfSelAtPara = false;
  426. SelectDlXp( dl, (**hdndl)[dl].fGraphics ? 0 : vxpCursor, styChar, fDrag );
  427. DontSelect:
  428. vfLastCursor = true; /* don't recalc vxpCursor next time */
  429. }
  430. /* C P T O D L X P */
  431. CpToDlXp(cp, pdl, pxp)
  432. typeCP cp;
  433. int *pdl, *pxp;
  434. { /* Transform cp into cursor coordinates */
  435. extern int vfInsEnd;
  436. typeCP cpBegin;
  437. int dcp;
  438. int xp;
  439. if (!vfInsEnd)
  440. PutCpInWwHz(cp);
  441. cpBegin = CpBeginLine(pdl, cp);
  442. ClearInsertLine();
  443. if ( (cp == selCur.cpFirst) && (cp == selCur.cpLim) && vfInsEnd &&
  444. cp > cpMinCur)
  445. { /* cp indicates we are at line beginning, but we are really
  446. kludged at the end of the previous line */
  447. CpToDlXp( cp - 1, pdl, pxp );
  448. PutCpInWwHz( cp - 1 );
  449. return;
  450. }
  451. dcp = (int) (cp - cpBegin);
  452. FormatLine(docCur, cpBegin, 0, cpMacCur, flmSandMode);
  453. xp = DxpDiff(0, dcp, &xp) + vfli.xpLeft;
  454. *pxp = xp + (xpSelBar - wwdCurrentDoc.xpMin);
  455. }