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.

422 lines
11 KiB

  1. /*++
  2. *
  3. * WOW v1.0
  4. *
  5. * Copyright (c) 1991, Microsoft Corporation
  6. *
  7. * EDMLRARE.C
  8. * Win16 edit control code
  9. *
  10. * History:
  11. *
  12. * Created 28-May-1991 by Jeff Parsons (jeffpar)
  13. * Copied from WIN31 and edited (as little as possible) for WOW16.
  14. --*/
  15. /****************************************************************************/
  16. /* edmlRare.c - Edit controls Routines Called rarely are to be */
  17. /* put in a seperate segment _EDMLRare. This file contains */
  18. /* these routines. */
  19. /****************************************************************************/
  20. #define NO_LOCALOBJ_TAGS
  21. #include "user.h"
  22. #include "edit.h"
  23. /****************************************************************************/
  24. /* Multi-Line Support Routines called Rarely */
  25. /****************************************************************************/
  26. BOOL FAR PASCAL MLInsertCrCrLf(ped)
  27. register PED ped;
  28. /* effects: Inserts CR CR LF characters into the text at soft (word-wrap) line
  29. * breaks. CR LF (hard) line breaks are unaffected. Assumes that the text
  30. * has already been formatted ie. ped->chLines is where we want the line
  31. * breaks to occur. Note that ped->chLines is not updated to reflect the
  32. * movement of text by the addition of CR CR LFs. Returns TRUE if successful
  33. * else notify parent and return FALSE if the memory couldn't be allocated.
  34. */
  35. {
  36. ICH dch;
  37. ICH li;
  38. ICH lineSize;
  39. /*register*/ unsigned char *pchText;
  40. unsigned char *pchTextNew;
  41. if (!ped->fWrap || !ped->cch)
  42. /* There are no soft line breaks if word-wrapping is off or if no chars
  43. */
  44. return(TRUE);
  45. /* Calc an upper bound on the number of additional characters we will be
  46. * adding to the text when we insert CR CR LFs.
  47. */
  48. dch = 3 * sizeof(char) * ped->cLines;
  49. if (!LocalReAlloc(ped->hText, ped->cch + dch, 0))
  50. {
  51. ECNotifyParent(ped, EN_ERRSPACE);
  52. return (FALSE);
  53. }
  54. ped->cchAlloc = ped->cch + dch;
  55. /* Move the text up dch bytes and then copy it back down, inserting the CR
  56. * CR LF's as necessary.
  57. */
  58. pchTextNew = pchText = LocalLock(ped->hText);
  59. pchText += dch;
  60. dch = 0; /* Now we will use this to keep track of how many chars we add
  61. to the text */
  62. /* Copy the text up dch bytes to pchText. This will shift all indices in
  63. * ped->chLines up by dch bytes.
  64. */
  65. LCopyStruct((LPSTR)pchTextNew, (LPSTR)pchText, ped->cch);
  66. /* Now copy chars from pchText down to pchTextNew and insert CRCRLF at soft
  67. * line breaks.
  68. */
  69. for (li = 0; li < ped->cLines-1; li++)
  70. {
  71. lineSize = ped->chLines[li+1]-ped->chLines[li];
  72. LCopyStruct((LPSTR)pchText, (LPSTR)pchTextNew, lineSize);
  73. pchTextNew += lineSize;
  74. pchText += lineSize;
  75. /* If last character in newly copied line is not a line feed, then we
  76. * need to add the CR CR LF triple to the end
  77. */
  78. if (*(PSTR)(pchTextNew-1) != 0x0A)
  79. {
  80. *pchTextNew++ = 0x0D;
  81. *pchTextNew++ = 0x0D;
  82. *pchTextNew++ = 0x0A;
  83. dch += 3;
  84. }
  85. }
  86. /* Now move the last line up. It won't have any line breaks in it... */
  87. LCopyStruct((LPSTR)pchText, (LPSTR)pchTextNew,
  88. ped->cch-ped->chLines[ped->cLines-1]);
  89. LocalUnlock(ped->hText);
  90. /* Update number of characters in text handle */
  91. ped->cch += dch;
  92. if (dch)
  93. /*
  94. * So that the next time we do anything with the text, we can strip the
  95. * CRCRLFs
  96. */
  97. ped->fStripCRCRLF = TRUE;
  98. return((dch != 0));
  99. }
  100. void FAR PASCAL MLStripCrCrLf(ped)
  101. register PED ped;
  102. /* effects: Strips the CR CR LF character combination from the text. This
  103. * shows the soft (word wrapped) line breaks. CR LF (hard) line breaks are
  104. * unaffected.
  105. */
  106. {
  107. register unsigned char *pchSrc;
  108. unsigned char *pchDst;
  109. unsigned char *pchLast;
  110. if (ped->cch)
  111. {
  112. pchSrc = pchDst = LocalLock(ped->hText);
  113. pchLast = pchSrc + ped->cch;
  114. while (pchSrc < pchLast)
  115. {
  116. if (*(int *)pchSrc != 0x0D0D)
  117. *pchDst++ = *pchSrc++;
  118. else
  119. {
  120. pchSrc += 3;
  121. ped->cch = ped->cch - 3;
  122. }
  123. }
  124. LocalUnlock(ped->hText);
  125. }
  126. }
  127. void FAR PASCAL MLSetHandleHandler(ped, hNewText)
  128. register PED ped;
  129. HANDLE hNewText;
  130. /* effects: Sets the ped to contain the given handle.
  131. */
  132. {
  133. ICH newCch;
  134. ped->cch = ped->cchAlloc = LocalSize(ped->hText = hNewText);
  135. if (ped->cch)
  136. {
  137. /* We have to do it this way in case the app gives us a zero size
  138. handle */
  139. ped->cch = lstrlen((LPSTR)LocalLock(ped->hText));
  140. LocalUnlock(ped->hText);
  141. }
  142. /* Empty the undo buffer since the text will be in an inconsistant state.
  143. */
  144. ECEmptyUndo(ped);
  145. newCch = (ICH)(ped->cch + CCHALLOCEXTRA);
  146. /* We do this LocalReAlloc in case the app changed the size of the handle */
  147. if (LocalReAlloc(ped->hText, newCch, 0))
  148. ped->cchAlloc = newCch;
  149. ped->fDirty = FALSE;
  150. MLStripCrCrLf(ped);
  151. MLBuildchLines(ped,0,0,FALSE);
  152. /* Reset caret and selections since the text could have changed causing
  153. * these to be out of range.
  154. */
  155. ped->xOffset = ped->screenStart = ped->ichMinSel = ped->ichMaxSel = 0;
  156. ped->iCaretLine = ped->ichCaret = 0;
  157. SetScrollPos(ped->hwnd, SB_VERT, 0, TRUE);
  158. SetScrollPos(ped->hwnd, SB_HORZ, 0, TRUE);
  159. /* We will always redraw the text whether or not the insert was successful
  160. * since we may set to null text. Also, since PaintHandler checks the redraw
  161. * flag, we won't bother to check it here.
  162. */
  163. InvalidateRect(ped->hwnd, (LPRECT)NULL, TRUE);
  164. UpdateWindow(ped->hwnd);
  165. }
  166. LONG FAR PASCAL MLGetLineHandler(ped, lineNumber, maxCchToCopy, lpBuffer)
  167. register PED ped;
  168. WORD lineNumber;
  169. ICH maxCchToCopy;
  170. LPSTR lpBuffer;
  171. /* effects: Copies maxCchToCopy bytes of line lineNumber to the buffer
  172. * lpBuffer. The string is not zero terminated.
  173. */
  174. {
  175. PSTR pText;
  176. if (lineNumber > ped->cLines-1)
  177. return(0L);
  178. maxCchToCopy = umin(MLLineLength(ped, lineNumber), maxCchToCopy);
  179. if (maxCchToCopy)
  180. {
  181. pText = (PSTR)(LocalLock(ped->hText) + ped->chLines[lineNumber]);
  182. LCopyStruct((LPSTR)pText, (LPSTR)lpBuffer, maxCchToCopy);
  183. LocalUnlock(ped->hText);
  184. }
  185. return(maxCchToCopy);
  186. }
  187. ICH FAR PASCAL MLLineIndexHandler(ped, iLine)
  188. register PED ped;
  189. register int iLine;
  190. /* effects: This function returns the number of character positions that occur
  191. * preceeding the first char in a given line.
  192. */
  193. {
  194. if (iLine == -1)
  195. iLine = ped->iCaretLine;
  196. return(iLine < ped->cLines ? ped->chLines[iLine] : -1);
  197. }
  198. ICH FAR PASCAL MLLineLengthHandler(ped, ich)
  199. register PED ped;
  200. ICH ich;
  201. /* effects: if ich = -1, return the length of the lines containing the current
  202. * selection but not including the selection. Otherwise, return the length of
  203. * the line containing ich.
  204. */
  205. {
  206. ICH il1, il2;
  207. if (ich != 0xFFFF)
  208. return(MLLineLength(ped, MLIchToLineHandler(ped, ich)));
  209. /* Find length of lines corresponding to current selection */
  210. il1 = MLIchToLineHandler(ped, ped->ichMinSel);
  211. il2 = MLIchToLineHandler(ped, ped->ichMaxSel);
  212. if (il1 == il2)
  213. return(MLLineLength(ped, il1) - (ped->ichMaxSel - ped->ichMinSel));
  214. return(ped->ichMinSel - ped->chLines[il1] +
  215. MLLineLength(ped, il2) - (ped->ichMaxSel - ped->chLines[il2]));
  216. }
  217. void FAR PASCAL MLSetSelectionHandler(ped, ichMinSel, ichMaxSel)
  218. register PED ped;
  219. ICH ichMinSel;
  220. ICH ichMaxSel;
  221. /*
  222. * effects: Sets the selection to the points given and puts the cursor at
  223. * ichMaxSel.
  224. */
  225. {
  226. register HDC hdc;
  227. if (ichMinSel == 0xFFFF)
  228. /* Set no selection if we specify -1
  229. */
  230. ichMinSel = ichMaxSel = ped->ichCaret;
  231. /* Since these are unsigned, we don't check if they are greater than 0.
  232. */
  233. ichMinSel = umin(ped->cch,ichMinSel);
  234. ichMaxSel = umin(ped->cch,ichMaxSel);
  235. /* Set the caret's position to be at ichMaxSel.
  236. */
  237. ped->ichCaret = ichMaxSel;
  238. ped->iCaretLine = MLIchToLineHandler(ped, ped->ichCaret);
  239. hdc = ECGetEditDC(ped,FALSE);
  240. MLChangeSelection(ped, hdc, ichMinSel, ichMaxSel);
  241. MLSetCaretPosition(ped,hdc);
  242. ECReleaseEditDC(ped,hdc,FALSE);
  243. MLEnsureCaretVisible(ped);
  244. }
  245. /**
  246. ** MLSetTabStops(ped, nTabPos, lpTabStops)
  247. **
  248. ** This sets the tab stop positions set by the App by sending
  249. ** a EM_SETTABSTOPS message.
  250. **
  251. ** nTabPos : Number of tab stops set by the caller
  252. ** lpTabStops: array of tab stop positions in Dialog units.
  253. **
  254. ** Returns:
  255. ** TRUE if successful
  256. ** FALSE if memory allocation error.
  257. **/
  258. BOOL FAR PASCAL MLSetTabStops(ped, nTabPos, lpTabStops)
  259. PED ped;
  260. int nTabPos;
  261. LPINT lpTabStops;
  262. {
  263. int * pTabStops;
  264. /* Check if tab positions already exist */
  265. if (!ped -> pTabStops)
  266. {
  267. /* Check if the caller wants the new tab positions */
  268. if (nTabPos)
  269. {
  270. /* Allocate the array of tab stops */
  271. if(!(pTabStops = (int *)LocalAlloc(LPTR, (nTabPos + 1)*sizeof(int))))
  272. return(FALSE);
  273. }
  274. else
  275. return(TRUE); /* No stops then and no stops now! */
  276. }
  277. else
  278. {
  279. /* Check if the caller wants the new tab positions */
  280. if(nTabPos)
  281. {
  282. /* Check if the number of tab positions is different */
  283. if (ped->pTabStops[0] != nTabPos)
  284. {
  285. /* Yes! So ReAlloc to new size */
  286. if(!(pTabStops = (int *)LocalReAlloc((HANDLE)ped->pTabStops,
  287. (nTabPos + 1) * sizeof(int), LPTR)))
  288. return(FALSE);
  289. }
  290. else
  291. pTabStops = ped->pTabStops;
  292. }
  293. else
  294. {
  295. /* Caller wants to remove all the tab stops; So, release */
  296. if (LocalFree((HANDLE)ped->pTabStops))
  297. return(FALSE); /* Failure */
  298. ped->pTabStops = NULL;
  299. return(TRUE);
  300. }
  301. }
  302. /* Copy the new tab stops onto the tab stop array after converting the
  303. * dialog co-ordinates into the pixel co-ordinates
  304. */
  305. ped -> pTabStops = pTabStops;
  306. *pTabStops++ = nTabPos; /* First element contains the count */
  307. while(nTabPos--)
  308. {
  309. /* aveCharWidth must be used instead of cxSysCharWidth.
  310. * Fix for Bug #3871 --SANKAR-- 03/14/91
  311. */
  312. *pTabStops++ = MultDiv(*lpTabStops++, ped->aveCharWidth, 4);
  313. }
  314. return(TRUE);
  315. }
  316. BOOL FAR PASCAL MLUndoHandler(ped)
  317. register PED ped;
  318. /* effects: Handles Undo for multiline edit controls. */
  319. {
  320. HANDLE hDeletedText = ped->hDeletedText;
  321. BOOL fDelete = (BOOL)(ped->undoType & UNDO_DELETE);
  322. WORD cchDeleted = ped->cchDeleted;
  323. WORD ichDeleted = ped->ichDeleted;
  324. if (ped->undoType == UNDO_NONE)
  325. /* No undo... */
  326. return(FALSE);
  327. ped->hDeletedText = NULL;
  328. ped->cchDeleted = 0;
  329. ped->ichDeleted = -1;
  330. ped->undoType &= ~UNDO_DELETE;
  331. if (ped->undoType == UNDO_INSERT)
  332. {
  333. ped->undoType = UNDO_NONE;
  334. /* Set the selection to the inserted text */
  335. MLSetSelectionHandler(ped, ped->ichInsStart, ped->ichInsEnd);
  336. ped->ichInsStart = ped->ichInsEnd = -1;
  337. /* Now send a backspace to delete and save it in the undo buffer...
  338. */
  339. MLCharHandler(ped, VK_BACK, NOMODIFY);
  340. }
  341. if (fDelete)
  342. {
  343. /* Insert deleted chars */
  344. /* Set the selection to the inserted text */
  345. MLSetSelectionHandler(ped, ichDeleted, ichDeleted);
  346. MLInsertText(ped, GlobalLock(hDeletedText), cchDeleted, FALSE);
  347. GlobalUnlock(hDeletedText);
  348. GlobalFree(hDeletedText);
  349. MLSetSelectionHandler(ped, ichDeleted, ichDeleted+cchDeleted);
  350. }
  351. return(TRUE);
  352. }
  353.