OLD | NEW |
| (Empty) |
1 // Copyright 2014 PDFium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | |
6 | |
7 #include "xfa/src/fee/fde_txtedtengine.h" | |
8 | |
9 #include <algorithm> | |
10 | |
11 #include "xfa/src/fde/tto/fde_textout.h" | |
12 #include "xfa/src/fee/fde_txtedtbuf.h" | |
13 #include "xfa/src/fee/fde_txtedtparag.h" | |
14 #include "xfa/src/fee/ifde_txtedtbuf.h" | |
15 #include "xfa/src/fee/ifde_txtedtengine.h" | |
16 #include "xfa/src/fee/ifde_txtedtpage.h" | |
17 | |
18 #define FDE_PAGEWIDTH_MAX 0xFFFF | |
19 #define FDE_TXTPLATESIZE (1024 * 12) | |
20 #define FDE_UNICODE_PARAGRAPH_SPERATOR (0x2029) | |
21 #define FDE_TXTEDT_DORECORD_INS 0 | |
22 #define FDE_TXTEDT_DORECORD_DEL 1 | |
23 | |
24 IFDE_TxtEdtEngine* IFDE_TxtEdtEngine::Create() { | |
25 return new CFDE_TxtEdtEngine(); | |
26 } | |
27 CFDE_TxtEdtEngine::CFDE_TxtEdtEngine() | |
28 : m_pTextBreak(nullptr), | |
29 m_nPageLineCount(20), | |
30 m_nLineCount(0), | |
31 m_nAnchorPos(-1), | |
32 m_nLayoutPos(0), | |
33 m_fCaretPosReserve(0.0), | |
34 m_nCaret(0), | |
35 m_bBefore(TRUE), | |
36 m_nCaretPage(0), | |
37 m_dwFindFlags(0), | |
38 m_bLock(FALSE), | |
39 m_nLimit(0), | |
40 m_wcAliasChar(L'*'), | |
41 m_nFirstLineEnd(FDE_TXTEDIT_LINEEND_Auto), | |
42 m_bAutoLineEnd(TRUE), | |
43 m_wLineEnd(FDE_UNICODE_PARAGRAPH_SPERATOR) { | |
44 FXSYS_memset(&m_rtCaret, 0, sizeof(CFX_RectF)); | |
45 m_pTxtBuf = new CFDE_TxtEdtBuf(); | |
46 m_bAutoLineEnd = (m_Param.nLineEnd == FDE_TXTEDIT_LINEEND_Auto); | |
47 } | |
48 CFDE_TxtEdtEngine::~CFDE_TxtEdtEngine() { | |
49 if (m_pTxtBuf) { | |
50 m_pTxtBuf->Release(); | |
51 m_pTxtBuf = NULL; | |
52 } | |
53 if (m_pTextBreak) { | |
54 m_pTextBreak->Release(); | |
55 m_pTextBreak = NULL; | |
56 } | |
57 RemoveAllParags(); | |
58 RemoveAllPages(); | |
59 m_Param.pEventSink = NULL; | |
60 ClearSelection(); | |
61 } | |
62 void CFDE_TxtEdtEngine::Release() { | |
63 delete this; | |
64 } | |
65 void CFDE_TxtEdtEngine::SetEditParams(const FDE_TXTEDTPARAMS& params) { | |
66 if (m_pTextBreak == NULL) { | |
67 m_pTextBreak = IFX_TxtBreak::Create(FX_TXTBREAKPOLICY_None); | |
68 } | |
69 FXSYS_memcpy(&m_Param, ¶ms, sizeof(FDE_TXTEDTPARAMS)); | |
70 m_wLineEnd = params.wLineBreakChar; | |
71 m_bAutoLineEnd = (m_Param.nLineEnd == FDE_TXTEDIT_LINEEND_Auto); | |
72 UpdateTxtBreak(); | |
73 } | |
74 const FDE_TXTEDTPARAMS* CFDE_TxtEdtEngine::GetEditParams() const { | |
75 return &m_Param; | |
76 } | |
77 int32_t CFDE_TxtEdtEngine::CountPages() const { | |
78 if (m_nLineCount == 0) { | |
79 return 0; | |
80 } | |
81 return ((m_nLineCount - 1) / m_nPageLineCount) + 1; | |
82 } | |
83 IFDE_TxtEdtPage* CFDE_TxtEdtEngine::GetPage(int32_t nIndex) { | |
84 if (m_PagePtrArray.GetSize() <= nIndex) { | |
85 return NULL; | |
86 } | |
87 return (IFDE_TxtEdtPage*)m_PagePtrArray[nIndex]; | |
88 } | |
89 FX_BOOL CFDE_TxtEdtEngine::SetBufChunkSize(int32_t nChunkSize) { | |
90 return m_pTxtBuf->SetChunkSize(nChunkSize); | |
91 } | |
92 void CFDE_TxtEdtEngine::SetTextByStream(IFX_Stream* pStream) { | |
93 ResetEngine(); | |
94 int32_t nIndex = 0; | |
95 if (pStream != NULL && pStream->GetLength()) { | |
96 int32_t nStreamLength = pStream->GetLength(); | |
97 FX_BOOL bValid = TRUE; | |
98 if (m_nLimit > 0 && nStreamLength > m_nLimit) { | |
99 bValid = FALSE; | |
100 } | |
101 FX_BOOL bPreIsCR = FALSE; | |
102 if (bValid) { | |
103 uint8_t bom[4]; | |
104 int32_t nPos = pStream->GetBOM(bom); | |
105 pStream->Seek(FX_STREAMSEEK_Begin, nPos); | |
106 int32_t nPlateSize = std::min(nStreamLength, m_pTxtBuf->GetChunkSize()); | |
107 FX_WCHAR* lpwstr = FX_Alloc(FX_WCHAR, nPlateSize); | |
108 FX_BOOL bEos = false; | |
109 while (!bEos) { | |
110 int32_t nRead = pStream->ReadString(lpwstr, nPlateSize, bEos); | |
111 bPreIsCR = ReplaceParagEnd(lpwstr, nRead, bPreIsCR); | |
112 m_pTxtBuf->Insert(nIndex, lpwstr, nRead); | |
113 nIndex += nRead; | |
114 } | |
115 FX_Free(lpwstr); | |
116 } | |
117 } | |
118 m_pTxtBuf->Insert(nIndex, &m_wLineEnd, 1); | |
119 RebuildParagraphs(); | |
120 } | |
121 void CFDE_TxtEdtEngine::SetText(const CFX_WideString& wsText) { | |
122 ResetEngine(); | |
123 int32_t nLength = wsText.GetLength(); | |
124 if (nLength > 0) { | |
125 CFX_WideString wsTemp; | |
126 FX_WCHAR* lpBuffer = wsTemp.GetBuffer(nLength); | |
127 FXSYS_memcpy(lpBuffer, wsText.c_str(), nLength * sizeof(FX_WCHAR)); | |
128 ReplaceParagEnd(lpBuffer, nLength, FALSE); | |
129 wsTemp.ReleaseBuffer(nLength); | |
130 if (m_nLimit > 0 && nLength > m_nLimit) { | |
131 wsTemp.Delete(m_nLimit, nLength - m_nLimit); | |
132 nLength = m_nLimit; | |
133 } | |
134 m_pTxtBuf->SetText(wsTemp); | |
135 } | |
136 m_pTxtBuf->Insert(nLength, &m_wLineEnd, 1); | |
137 RebuildParagraphs(); | |
138 } | |
139 int32_t CFDE_TxtEdtEngine::GetTextLength() const { | |
140 return GetTextBufLength(); | |
141 } | |
142 void CFDE_TxtEdtEngine::GetText(CFX_WideString& wsText, | |
143 int32_t nStart, | |
144 int32_t nCount) { | |
145 int32_t nTextBufLength = GetTextBufLength(); | |
146 if (nCount == -1) { | |
147 nCount = nTextBufLength - nStart; | |
148 } | |
149 m_pTxtBuf->GetRange(wsText, nStart, nCount); | |
150 RecoverParagEnd(wsText); | |
151 } | |
152 | |
153 void CFDE_TxtEdtEngine::ClearText() { | |
154 DeleteRange(0, -1); | |
155 } | |
156 int32_t CFDE_TxtEdtEngine::GetCaretRect(CFX_RectF& rtCaret) const { | |
157 rtCaret = m_rtCaret; | |
158 return m_nCaret; | |
159 } | |
160 int32_t CFDE_TxtEdtEngine::GetCaretPos() const { | |
161 if (IsLocked()) { | |
162 return 0; | |
163 } | |
164 return m_nCaret + (m_bBefore ? 0 : 1); | |
165 } | |
166 int32_t CFDE_TxtEdtEngine::SetCaretPos(int32_t nIndex, FX_BOOL bBefore) { | |
167 if (IsLocked()) { | |
168 return 0; | |
169 } | |
170 FXSYS_assert(nIndex >= 0 && nIndex <= GetTextBufLength()); | |
171 if (m_PagePtrArray.GetSize() <= m_nCaretPage) { | |
172 return 0; | |
173 } | |
174 m_bBefore = bBefore; | |
175 m_nCaret = nIndex; | |
176 MovePage2Char(m_nCaret); | |
177 GetCaretRect(m_rtCaret, m_nCaretPage, m_nCaret, m_bBefore); | |
178 if (!m_bBefore) { | |
179 m_nCaret++; | |
180 m_bBefore = TRUE; | |
181 } | |
182 m_fCaretPosReserve = (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_DocVertical) | |
183 ? m_rtCaret.top | |
184 : m_rtCaret.left; | |
185 m_Param.pEventSink->On_CaretChanged(this, m_nCaretPage, 0); | |
186 m_nAnchorPos = -1; | |
187 return m_nCaret; | |
188 } | |
189 int32_t CFDE_TxtEdtEngine::MoveCaretPos(FDE_TXTEDTMOVECARET eMoveCaret, | |
190 FX_BOOL bShift, | |
191 FX_BOOL bCtrl) { | |
192 if (IsLocked()) { | |
193 return 0; | |
194 } | |
195 if (m_PagePtrArray.GetSize() <= m_nCaretPage) { | |
196 return 0; | |
197 } | |
198 FX_BOOL bSelChange = FALSE; | |
199 if (IsSelect()) { | |
200 ClearSelection(); | |
201 bSelChange = TRUE; | |
202 } | |
203 if (bShift) { | |
204 if (m_nAnchorPos == -1) { | |
205 m_nAnchorPos = m_nCaret; | |
206 } | |
207 } else { | |
208 m_nAnchorPos = -1; | |
209 } | |
210 FX_BOOL bVertical = m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_DocVertical; | |
211 switch (eMoveCaret) { | |
212 case MC_Left: { | |
213 if (bVertical) { | |
214 CFX_PointF ptCaret; | |
215 if (MoveUp(ptCaret)) { | |
216 UpdateCaretIndex(ptCaret); | |
217 } | |
218 } else { | |
219 FX_BOOL bBefore = TRUE; | |
220 int32_t nIndex = MoveBackward(bBefore); | |
221 if (nIndex >= 0) { | |
222 UpdateCaretRect(nIndex, bBefore); | |
223 } | |
224 } | |
225 } break; | |
226 case MC_Right: { | |
227 if (bVertical) { | |
228 CFX_PointF ptCaret; | |
229 if (MoveDown(ptCaret)) { | |
230 UpdateCaretIndex(ptCaret); | |
231 } | |
232 } else { | |
233 FX_BOOL bBefore = TRUE; | |
234 int32_t nIndex = MoveForward(bBefore); | |
235 if (nIndex >= 0) { | |
236 UpdateCaretRect(nIndex, bBefore); | |
237 } | |
238 } | |
239 } break; | |
240 case MC_Up: { | |
241 if (bVertical) { | |
242 FX_BOOL bBefore = TRUE; | |
243 int32_t nIndex = MoveBackward(bBefore); | |
244 if (nIndex >= 0) { | |
245 UpdateCaretRect(nIndex, bBefore); | |
246 } | |
247 } else { | |
248 CFX_PointF ptCaret; | |
249 if (MoveUp(ptCaret)) { | |
250 UpdateCaretIndex(ptCaret); | |
251 } | |
252 } | |
253 } break; | |
254 case MC_Down: { | |
255 if (bVertical) { | |
256 FX_BOOL bBefore = TRUE; | |
257 int32_t nIndex = MoveForward(bBefore); | |
258 if (nIndex >= 0) { | |
259 UpdateCaretRect(nIndex, bBefore); | |
260 } | |
261 } else { | |
262 CFX_PointF ptCaret; | |
263 if (MoveDown(ptCaret)) { | |
264 UpdateCaretIndex(ptCaret); | |
265 } | |
266 } | |
267 } break; | |
268 case MC_WordBackward: | |
269 break; | |
270 case MC_WordForward: | |
271 break; | |
272 case MC_LineStart: | |
273 MoveLineStart(); | |
274 break; | |
275 case MC_LineEnd: | |
276 MoveLineEnd(); | |
277 break; | |
278 case MC_ParagStart: | |
279 MoveParagStart(); | |
280 break; | |
281 case MC_ParagEnd: | |
282 MoveParagEnd(); | |
283 break; | |
284 case MC_PageDown: | |
285 break; | |
286 case MC_PageUp: | |
287 break; | |
288 case MC_Home: | |
289 MoveHome(); | |
290 break; | |
291 case MC_End: | |
292 MoveEnd(); | |
293 break; | |
294 default: | |
295 break; | |
296 } | |
297 if (bShift && m_nAnchorPos != -1 && (m_nAnchorPos != m_nCaret)) { | |
298 AddSelRange(std::min(m_nAnchorPos, m_nCaret), | |
299 FXSYS_abs(m_nAnchorPos - m_nCaret)); | |
300 m_Param.pEventSink->On_SelChanged(this); | |
301 } | |
302 if (bSelChange) { | |
303 m_Param.pEventSink->On_SelChanged(this); | |
304 } | |
305 return m_nCaret; | |
306 } | |
307 void CFDE_TxtEdtEngine::Lock() { | |
308 m_bLock = TRUE; | |
309 } | |
310 void CFDE_TxtEdtEngine::Unlock() { | |
311 m_bLock = FALSE; | |
312 } | |
313 FX_BOOL CFDE_TxtEdtEngine::IsLocked() const { | |
314 return m_bLock; | |
315 } | |
316 int32_t CFDE_TxtEdtEngine::Insert(int32_t nStart, | |
317 const FX_WCHAR* lpText, | |
318 int32_t nLength) { | |
319 if (IsLocked()) { | |
320 return FDE_TXTEDT_MODIFY_RET_F_Locked; | |
321 } | |
322 CFX_WideString wsTemp; | |
323 FX_WCHAR* lpBuffer = wsTemp.GetBuffer(nLength); | |
324 FXSYS_memcpy(lpBuffer, lpText, nLength * sizeof(FX_WCHAR)); | |
325 ReplaceParagEnd(lpBuffer, nLength, FALSE); | |
326 wsTemp.ReleaseBuffer(nLength); | |
327 FX_BOOL bPart = FALSE; | |
328 if (m_nLimit > 0) { | |
329 int32_t nTotalLength = GetTextBufLength(); | |
330 int32_t nCount = m_SelRangePtrArr.GetSize(); | |
331 for (int32_t i = 0; i < nCount; i++) { | |
332 FDE_LPTXTEDTSELRANGE lpSelRange = m_SelRangePtrArr.GetAt(i); | |
333 nTotalLength -= lpSelRange->nCount; | |
334 } | |
335 int32_t nExpectLength = nTotalLength + nLength; | |
336 if (nTotalLength == m_nLimit) { | |
337 return FDE_TXTEDT_MODIFY_RET_F_Full; | |
338 } | |
339 if (nExpectLength > m_nLimit) { | |
340 nLength -= (nExpectLength - m_nLimit); | |
341 bPart = TRUE; | |
342 } | |
343 } | |
344 if ((m_Param.dwMode & FDE_TEXTEDITMODE_LimitArea_Vert) || | |
345 (m_Param.dwMode & FDE_TEXTEDITMODE_LimitArea_Horz)) { | |
346 int32_t nTemp = nLength; | |
347 if (m_Param.dwMode & FDE_TEXTEDITMODE_Password) { | |
348 CFX_WideString wsText; | |
349 while (nLength > 0) { | |
350 GetPreInsertText(wsText, m_nCaret, lpBuffer, nLength); | |
351 int32_t nTotal = wsText.GetLength(); | |
352 FX_WCHAR* lpBuf = wsText.GetBuffer(nTotal); | |
353 for (int32_t i = 0; i < nTotal; i++) { | |
354 lpBuf[i] = m_wcAliasChar; | |
355 } | |
356 wsText.ReleaseBuffer(nTotal); | |
357 if (IsFitArea(wsText)) { | |
358 break; | |
359 } | |
360 nLength--; | |
361 } | |
362 } else { | |
363 CFX_WideString wsText; | |
364 while (nLength > 0) { | |
365 GetPreInsertText(wsText, m_nCaret, lpBuffer, nLength); | |
366 if (IsFitArea(wsText)) { | |
367 break; | |
368 } | |
369 nLength--; | |
370 } | |
371 } | |
372 if (nLength == 0) { | |
373 return FDE_TXTEDT_MODIFY_RET_F_Full; | |
374 } | |
375 if (nLength < nTemp) { | |
376 bPart = TRUE; | |
377 } | |
378 } | |
379 if (m_Param.dwMode & FDE_TEXTEDITMODE_Validate) { | |
380 CFX_WideString wsText; | |
381 GetPreInsertText(wsText, m_nCaret, lpBuffer, nLength); | |
382 if (!m_Param.pEventSink->On_Validate(this, wsText)) { | |
383 return FDE_TXTEDT_MODIFY_RET_F_Invalidate; | |
384 } | |
385 } | |
386 if (IsSelect()) { | |
387 DeleteSelect(); | |
388 } | |
389 if (!(m_Param.dwMode & FDE_TEXTEDITMODE_NoRedoUndo)) { | |
390 IFDE_TxtEdtDoRecord* pRecord = | |
391 new CFDE_TxtEdtDoRecord_Insert(this, m_nCaret, lpBuffer, nLength); | |
392 CFX_ByteString bsDoRecord; | |
393 pRecord->Serialize(bsDoRecord); | |
394 m_Param.pEventSink->On_AddDoRecord(this, bsDoRecord); | |
395 pRecord->Release(); | |
396 } | |
397 GetText(m_ChangeInfo.wsPrevText, 0); | |
398 Inner_Insert(m_nCaret, lpBuffer, nLength); | |
399 m_ChangeInfo.nChangeType = FDE_TXTEDT_TEXTCHANGE_TYPE_Insert; | |
400 m_ChangeInfo.wsInsert = CFX_WideString(lpBuffer, nLength); | |
401 nStart = m_nCaret; | |
402 nStart += nLength; | |
403 FX_WCHAR wChar = m_pTxtBuf->GetCharByIndex(nStart - 1); | |
404 FX_BOOL bBefore = TRUE; | |
405 if (wChar != L'\n' && wChar != L'\r') { | |
406 nStart--; | |
407 bBefore = FALSE; | |
408 } | |
409 SetCaretPos(nStart, bBefore); | |
410 m_Param.pEventSink->On_TextChanged(this, m_ChangeInfo); | |
411 return bPart ? FDE_TXTEDT_MODIFY_RET_S_Part : FDE_TXTEDT_MODIFY_RET_S_Normal; | |
412 } | |
413 int32_t CFDE_TxtEdtEngine::Delete(int32_t nStart, FX_BOOL bBackspace) { | |
414 if (IsLocked()) { | |
415 return FDE_TXTEDT_MODIFY_RET_F_Locked; | |
416 } | |
417 if (IsSelect()) { | |
418 DeleteSelect(); | |
419 return FDE_TXTEDT_MODIFY_RET_S_Normal; | |
420 } | |
421 | |
422 int32_t nCount = 1; | |
423 if (bBackspace) { | |
424 if (nStart == 0) { | |
425 return FDE_TXTEDT_MODIFY_RET_F_Boundary; | |
426 } | |
427 if (nStart > 2 && m_pTxtBuf->GetCharByIndex(nStart - 1) == L'\n' && | |
428 m_pTxtBuf->GetCharByIndex(nStart - 2) == L'\r') { | |
429 nStart--; | |
430 nCount++; | |
431 } | |
432 nStart--; | |
433 } else { | |
434 if (nStart == GetTextBufLength()) { | |
435 return FDE_TXTEDT_MODIFY_RET_F_Full; | |
436 } | |
437 if ((nStart + 1 < GetTextBufLength()) && | |
438 (m_pTxtBuf->GetCharByIndex(nStart) == L'\r') && | |
439 (m_pTxtBuf->GetCharByIndex(nStart + 1) == L'\n')) { | |
440 nCount++; | |
441 } | |
442 } | |
443 if (m_Param.dwMode & FDE_TEXTEDITMODE_Validate) { | |
444 CFX_WideString wsText; | |
445 GetPreDeleteText(wsText, nStart, nCount); | |
446 if (!m_Param.pEventSink->On_Validate(this, wsText)) { | |
447 return FDE_TXTEDT_MODIFY_RET_F_Invalidate; | |
448 } | |
449 } | |
450 if (!(m_Param.dwMode & FDE_TEXTEDITMODE_NoRedoUndo)) { | |
451 CFX_WideString wsRange; | |
452 m_pTxtBuf->GetRange(wsRange, nStart, nCount); | |
453 IFDE_TxtEdtDoRecord* pRecord = | |
454 new CFDE_TxtEdtDoRecord_DeleteRange(this, nStart, m_nCaret, wsRange); | |
455 CFX_ByteString bsDoRecord; | |
456 pRecord->Serialize(bsDoRecord); | |
457 m_Param.pEventSink->On_AddDoRecord(this, bsDoRecord); | |
458 pRecord->Release(); | |
459 } | |
460 m_ChangeInfo.nChangeType = FDE_TXTEDT_TEXTCHANGE_TYPE_Delete; | |
461 GetText(m_ChangeInfo.wsDelete, nStart, nCount); | |
462 Inner_DeleteRange(nStart, nCount); | |
463 SetCaretPos(nStart + ((!bBackspace && nStart > 0) ? -1 : 0), | |
464 (bBackspace || nStart == 0)); | |
465 m_Param.pEventSink->On_TextChanged(this, m_ChangeInfo); | |
466 return FDE_TXTEDT_MODIFY_RET_S_Normal; | |
467 } | |
468 int32_t CFDE_TxtEdtEngine::DeleteRange(int32_t nStart, int32_t nCount) { | |
469 if (IsLocked()) { | |
470 return FDE_TXTEDT_MODIFY_RET_F_Locked; | |
471 } | |
472 if (nCount == -1) { | |
473 nCount = GetTextBufLength(); | |
474 } | |
475 if (nCount == 0) { | |
476 return FDE_TXTEDT_MODIFY_RET_S_Normal; | |
477 } | |
478 if (m_Param.dwMode & FDE_TEXTEDITMODE_Validate) { | |
479 CFX_WideString wsText; | |
480 GetPreDeleteText(wsText, nStart, nCount); | |
481 if (!m_Param.pEventSink->On_Validate(this, wsText)) { | |
482 return FDE_TXTEDT_MODIFY_RET_F_Invalidate; | |
483 } | |
484 } | |
485 DeleteRange_DoRecord(nStart, nCount); | |
486 m_Param.pEventSink->On_TextChanged(this, m_ChangeInfo); | |
487 SetCaretPos(nStart, TRUE); | |
488 return FDE_TXTEDT_MODIFY_RET_S_Normal; | |
489 } | |
490 int32_t CFDE_TxtEdtEngine::Replace(int32_t nStart, | |
491 int32_t nLength, | |
492 const CFX_WideString& wsReplace) { | |
493 if (IsLocked()) { | |
494 return FDE_TXTEDT_MODIFY_RET_F_Locked; | |
495 } | |
496 if (nStart < 0 || (nStart + nLength > GetTextBufLength())) { | |
497 return FDE_TXTEDT_MODIFY_RET_F_Boundary; | |
498 } | |
499 if (m_Param.dwMode & FDE_TEXTEDITMODE_Validate) { | |
500 CFX_WideString wsText; | |
501 GetPreReplaceText(wsText, nStart, nLength, wsReplace.c_str(), | |
502 wsReplace.GetLength()); | |
503 if (!m_Param.pEventSink->On_Validate(this, wsText)) { | |
504 return FDE_TXTEDT_MODIFY_RET_F_Invalidate; | |
505 } | |
506 } | |
507 if (IsSelect()) { | |
508 ClearSelection(); | |
509 } | |
510 m_ChangeInfo.nChangeType = FDE_TXTEDT_TEXTCHANGE_TYPE_Replace; | |
511 GetText(m_ChangeInfo.wsDelete, nStart, nLength); | |
512 if (nLength > 0) { | |
513 Inner_DeleteRange(nStart, nLength); | |
514 } | |
515 int32_t nTextLength = wsReplace.GetLength(); | |
516 if (nTextLength > 0) { | |
517 Inner_Insert(nStart, wsReplace.c_str(), nTextLength); | |
518 } | |
519 m_ChangeInfo.wsInsert = CFX_WideString(wsReplace.c_str(), nTextLength); | |
520 nStart += nTextLength; | |
521 FX_WCHAR wChar = m_pTxtBuf->GetCharByIndex(nStart - 1); | |
522 FX_BOOL bBefore = TRUE; | |
523 if (wChar != L'\n' && wChar != L'\r') { | |
524 nStart--; | |
525 bBefore = FALSE; | |
526 } | |
527 SetCaretPos(nStart, bBefore); | |
528 m_Param.pEventSink->On_PageUnload(this, m_nCaretPage, 0); | |
529 m_Param.pEventSink->On_PageLoad(this, m_nCaretPage, 0); | |
530 m_Param.pEventSink->On_TextChanged(this, m_ChangeInfo); | |
531 return FDE_TXTEDT_MODIFY_RET_S_Normal; | |
532 } | |
533 void CFDE_TxtEdtEngine::SetLimit(int32_t nLimit) { | |
534 m_nLimit = nLimit; | |
535 } | |
536 void CFDE_TxtEdtEngine::SetAliasChar(FX_WCHAR wcAlias) { | |
537 m_wcAliasChar = wcAlias; | |
538 } | |
539 | |
540 void CFDE_TxtEdtEngine::RemoveSelRange(int32_t nStart, int32_t nCount) { | |
541 FDE_LPTXTEDTSELRANGE lpTemp = NULL; | |
542 int32_t nRangeCount = m_SelRangePtrArr.GetSize(); | |
543 int32_t i = 0; | |
544 for (i = 0; i < nRangeCount; i++) { | |
545 lpTemp = m_SelRangePtrArr[i]; | |
546 if (lpTemp->nStart == nStart && lpTemp->nCount == nCount) { | |
547 delete lpTemp; | |
548 m_SelRangePtrArr.RemoveAt(i); | |
549 return; | |
550 } | |
551 } | |
552 } | |
553 | |
554 void CFDE_TxtEdtEngine::AddSelRange(int32_t nStart, int32_t nCount) { | |
555 if (nCount == -1) { | |
556 nCount = GetTextLength() - nStart; | |
557 } | |
558 int32_t nSize = m_SelRangePtrArr.GetSize(); | |
559 if (nSize <= 0) { | |
560 FDE_LPTXTEDTSELRANGE lpSelRange = new FDE_TXTEDTSELRANGE; | |
561 lpSelRange->nStart = nStart; | |
562 lpSelRange->nCount = nCount; | |
563 m_SelRangePtrArr.Add(lpSelRange); | |
564 m_Param.pEventSink->On_SelChanged(this); | |
565 return; | |
566 } | |
567 FDE_LPTXTEDTSELRANGE lpTemp = NULL; | |
568 lpTemp = m_SelRangePtrArr[nSize - 1]; | |
569 if (nStart >= lpTemp->nStart + lpTemp->nCount) { | |
570 FDE_LPTXTEDTSELRANGE lpSelRange = new FDE_TXTEDTSELRANGE; | |
571 lpSelRange->nStart = nStart; | |
572 lpSelRange->nCount = nCount; | |
573 m_SelRangePtrArr.Add(lpSelRange); | |
574 m_Param.pEventSink->On_SelChanged(this); | |
575 return; | |
576 } | |
577 int32_t nEnd = nStart + nCount - 1; | |
578 FX_BOOL bBegin = FALSE; | |
579 int32_t nRangeBgn = 0; | |
580 int32_t nRangeCnt = 0; | |
581 for (int32_t i = 0; i < nSize; i++) { | |
582 lpTemp = m_SelRangePtrArr[i]; | |
583 int32_t nTempBgn = lpTemp->nStart; | |
584 int32_t nTempEnd = nTempBgn + lpTemp->nCount - 1; | |
585 if (bBegin) { | |
586 if (nEnd < nTempBgn) { | |
587 break; | |
588 } else if (nStart >= nTempBgn && nStart <= nTempEnd) { | |
589 nRangeCnt++; | |
590 break; | |
591 } | |
592 nRangeCnt++; | |
593 } else { | |
594 if (nStart <= nTempEnd) { | |
595 nRangeBgn = i; | |
596 if (nEnd < nTempBgn) { | |
597 break; | |
598 } | |
599 nRangeCnt = 1; | |
600 bBegin = TRUE; | |
601 } | |
602 } | |
603 } | |
604 if (nRangeCnt == 0) { | |
605 FDE_LPTXTEDTSELRANGE lpSelRange = new FDE_TXTEDTSELRANGE; | |
606 lpSelRange->nStart = nStart; | |
607 lpSelRange->nCount = nCount; | |
608 m_SelRangePtrArr.InsertAt(nRangeBgn, lpSelRange); | |
609 } else { | |
610 lpTemp = m_SelRangePtrArr[nRangeBgn]; | |
611 lpTemp->nStart = nStart; | |
612 lpTemp->nCount = nCount; | |
613 nRangeCnt--; | |
614 nRangeBgn++; | |
615 while (nRangeCnt--) { | |
616 delete m_SelRangePtrArr[nRangeBgn]; | |
617 m_SelRangePtrArr.RemoveAt(nRangeBgn); | |
618 } | |
619 } | |
620 m_Param.pEventSink->On_SelChanged(this); | |
621 } | |
622 | |
623 int32_t CFDE_TxtEdtEngine::CountSelRanges() { | |
624 return m_SelRangePtrArr.GetSize(); | |
625 } | |
626 int32_t CFDE_TxtEdtEngine::GetSelRange(int32_t nIndex, int32_t& nStart) { | |
627 nStart = m_SelRangePtrArr[nIndex]->nStart; | |
628 return m_SelRangePtrArr[nIndex]->nCount; | |
629 } | |
630 void CFDE_TxtEdtEngine::ClearSelection() { | |
631 int32_t nCount = m_SelRangePtrArr.GetSize(); | |
632 FDE_LPTXTEDTSELRANGE lpRange = NULL; | |
633 int32_t i = 0; | |
634 for (i = 0; i < nCount; i++) { | |
635 lpRange = m_SelRangePtrArr[i]; | |
636 if (lpRange != NULL) { | |
637 delete lpRange; | |
638 lpRange = NULL; | |
639 } | |
640 } | |
641 m_SelRangePtrArr.RemoveAll(); | |
642 if (nCount && m_Param.pEventSink) { | |
643 m_Param.pEventSink->On_SelChanged(this); | |
644 } | |
645 } | |
646 FX_BOOL CFDE_TxtEdtEngine::Redo(const CFX_ByteStringC& bsRedo) { | |
647 if (IsLocked()) { | |
648 return FALSE; | |
649 } | |
650 if (m_Param.dwMode & FDE_TEXTEDITMODE_NoRedoUndo) { | |
651 return FALSE; | |
652 } | |
653 IFDE_TxtEdtDoRecord* pDoRecord = IFDE_TxtEdtDoRecord::Create(bsRedo); | |
654 FXSYS_assert(pDoRecord); | |
655 if (pDoRecord == NULL) { | |
656 return FALSE; | |
657 } | |
658 FX_BOOL bOK = pDoRecord->Redo(); | |
659 pDoRecord->Release(); | |
660 return bOK; | |
661 } | |
662 FX_BOOL CFDE_TxtEdtEngine::Undo(const CFX_ByteStringC& bsUndo) { | |
663 if (IsLocked()) { | |
664 return FALSE; | |
665 } | |
666 if (m_Param.dwMode & FDE_TEXTEDITMODE_NoRedoUndo) { | |
667 return FALSE; | |
668 } | |
669 IFDE_TxtEdtDoRecord* pDoRecord = IFDE_TxtEdtDoRecord::Create(bsUndo); | |
670 FXSYS_assert(pDoRecord); | |
671 if (pDoRecord == NULL) { | |
672 return FALSE; | |
673 } | |
674 FX_BOOL bOK = pDoRecord->Undo(); | |
675 pDoRecord->Release(); | |
676 return bOK; | |
677 } | |
678 int32_t CFDE_TxtEdtEngine::StartLayout() { | |
679 Lock(); | |
680 RemoveAllPages(); | |
681 m_nLayoutPos = 0; | |
682 m_nLineCount = 0; | |
683 return 0; | |
684 } | |
685 int32_t CFDE_TxtEdtEngine::DoLayout(IFX_Pause* pPause) { | |
686 int32_t nCount = m_ParagPtrArray.GetSize(); | |
687 CFDE_TxtEdtParag* pParag = NULL; | |
688 int32_t nLineCount = 0; | |
689 for (; m_nLayoutPos < nCount; m_nLayoutPos++) { | |
690 pParag = m_ParagPtrArray[m_nLayoutPos]; | |
691 pParag->CalcLines(); | |
692 nLineCount += pParag->m_nLineCount; | |
693 if ((pPause != NULL) && (nLineCount > m_nPageLineCount) && | |
694 pPause->NeedToPauseNow()) { | |
695 m_nLineCount += nLineCount; | |
696 return (++m_nLayoutPos * 100) / nCount; | |
697 } | |
698 } | |
699 m_nLineCount += nLineCount; | |
700 return 100; | |
701 } | |
702 void CFDE_TxtEdtEngine::EndLayout() { | |
703 UpdatePages(); | |
704 int32_t nLength = GetTextLength(); | |
705 if (m_nCaret > nLength) { | |
706 m_nCaret = nLength; | |
707 } | |
708 int32_t nIndex = m_nCaret; | |
709 if (!m_bBefore) { | |
710 nIndex--; | |
711 } | |
712 m_rtCaret.Set(0, 0, 1, m_Param.fFontSize); | |
713 Unlock(); | |
714 } | |
715 FX_BOOL CFDE_TxtEdtEngine::Optimize(IFX_Pause* pPause) { | |
716 return m_pTxtBuf->Optimize(pPause); | |
717 } | |
718 IFDE_TxtEdtBuf* CFDE_TxtEdtEngine::GetTextBuf() const { | |
719 return (IFDE_TxtEdtBuf*)m_pTxtBuf; | |
720 } | |
721 int32_t CFDE_TxtEdtEngine::GetTextBufLength() const { | |
722 return m_pTxtBuf->GetTextLength() - 1; | |
723 } | |
724 IFX_TxtBreak* CFDE_TxtEdtEngine::GetTextBreak() const { | |
725 return m_pTextBreak; | |
726 } | |
727 int32_t CFDE_TxtEdtEngine::GetLineCount() const { | |
728 return m_nLineCount; | |
729 } | |
730 int32_t CFDE_TxtEdtEngine::GetPageLineCount() const { | |
731 return m_nPageLineCount; | |
732 } | |
733 int32_t CFDE_TxtEdtEngine::CountParags() const { | |
734 return m_ParagPtrArray.GetSize(); | |
735 } | |
736 IFDE_TxtEdtParag* CFDE_TxtEdtEngine::GetParag(int32_t nParagIndex) const { | |
737 return m_ParagPtrArray[nParagIndex]; | |
738 } | |
739 IFX_CharIter* CFDE_TxtEdtEngine::CreateCharIter() { | |
740 if (!m_pTxtBuf) { | |
741 return NULL; | |
742 } | |
743 return new CFDE_TxtEdtBufIter((CFDE_TxtEdtBuf*)m_pTxtBuf); | |
744 } | |
745 int32_t CFDE_TxtEdtEngine::Line2Parag(int32_t nStartParag, | |
746 int32_t nStartLineofParag, | |
747 int32_t nLineIndex, | |
748 int32_t& nStartLine) const { | |
749 int32_t nLineTotal = nStartLineofParag; | |
750 int32_t nCount = m_ParagPtrArray.GetSize(); | |
751 CFDE_TxtEdtParag* pParag = NULL; | |
752 int32_t i = nStartParag; | |
753 for (; i < nCount; i++) { | |
754 pParag = m_ParagPtrArray[i]; | |
755 nLineTotal += pParag->m_nLineCount; | |
756 if (nLineTotal > nLineIndex) { | |
757 break; | |
758 } | |
759 } | |
760 nStartLine = nLineTotal - pParag->m_nLineCount; | |
761 return i; | |
762 } | |
763 void CFDE_TxtEdtEngine::GetPreDeleteText(CFX_WideString& wsText, | |
764 int32_t nIndex, | |
765 int32_t nLength) { | |
766 GetText(wsText, 0, GetTextBufLength()); | |
767 wsText.Delete(nIndex, nLength); | |
768 } | |
769 void CFDE_TxtEdtEngine::GetPreInsertText(CFX_WideString& wsText, | |
770 int32_t nIndex, | |
771 const FX_WCHAR* lpText, | |
772 int32_t nLength) { | |
773 GetText(wsText, 0, GetTextBufLength()); | |
774 int32_t nSelIndex = 0; | |
775 int32_t nSelLength = 0; | |
776 int32_t nSelCount = CountSelRanges(); | |
777 while (nSelCount--) { | |
778 nSelLength = GetSelRange(nSelCount, nSelIndex); | |
779 wsText.Delete(nSelIndex, nSelLength); | |
780 nIndex = nSelIndex; | |
781 } | |
782 CFX_WideString wsTemp; | |
783 int32_t nOldLength = wsText.GetLength(); | |
784 const FX_WCHAR* pOldBuffer = wsText.c_str(); | |
785 FX_WCHAR* lpBuffer = wsTemp.GetBuffer(nOldLength + nLength); | |
786 FXSYS_memcpy(lpBuffer, pOldBuffer, (nIndex) * sizeof(FX_WCHAR)); | |
787 FXSYS_memcpy(lpBuffer + nIndex, lpText, nLength * sizeof(FX_WCHAR)); | |
788 FXSYS_memcpy(lpBuffer + nIndex + nLength, pOldBuffer + nIndex, | |
789 (nOldLength - nIndex) * sizeof(FX_WCHAR)); | |
790 wsTemp.ReleaseBuffer(nOldLength + nLength); | |
791 wsText = wsTemp; | |
792 } | |
793 void CFDE_TxtEdtEngine::GetPreReplaceText(CFX_WideString& wsText, | |
794 int32_t nIndex, | |
795 int32_t nOriginLength, | |
796 const FX_WCHAR* lpText, | |
797 int32_t nLength) { | |
798 GetText(wsText, 0, GetTextBufLength()); | |
799 int32_t nSelIndex = 0; | |
800 int32_t nSelLength = 0; | |
801 int32_t nSelCount = CountSelRanges(); | |
802 while (nSelCount--) { | |
803 nSelLength = GetSelRange(nSelCount, nSelIndex); | |
804 wsText.Delete(nSelIndex, nSelLength); | |
805 } | |
806 wsText.Delete(nIndex, nOriginLength); | |
807 int32_t i = 0; | |
808 for (i = 0; i < nLength; i++) { | |
809 wsText.Insert(nIndex++, lpText[i]); | |
810 } | |
811 } | |
812 void CFDE_TxtEdtEngine::Inner_Insert(int32_t nStart, | |
813 const FX_WCHAR* lpText, | |
814 int32_t nLength) { | |
815 FXSYS_assert(nLength > 0); | |
816 FDE_TXTEDTPARAGPOS ParagPos; | |
817 TextPos2ParagPos(nStart, ParagPos); | |
818 m_Param.pEventSink->On_PageUnload(this, m_nCaretPage, 0); | |
819 int32_t nParagCount = m_ParagPtrArray.GetSize(); | |
820 int32_t i = 0; | |
821 for (i = ParagPos.nParagIndex + 1; i < nParagCount; i++) { | |
822 m_ParagPtrArray[i]->m_nCharStart += nLength; | |
823 } | |
824 CFDE_TxtEdtParag* pParag = m_ParagPtrArray[ParagPos.nParagIndex]; | |
825 int32_t nReserveLineCount = pParag->m_nLineCount; | |
826 int32_t nReserveCharStart = pParag->m_nCharStart; | |
827 int32_t nLeavePart = ParagPos.nCharIndex; | |
828 int32_t nCutPart = pParag->m_nCharCount - ParagPos.nCharIndex; | |
829 int32_t nTextStart = 0; | |
830 FX_WCHAR wCurChar = L' '; | |
831 const FX_WCHAR* lpPos = lpText; | |
832 FX_BOOL bFirst = TRUE; | |
833 int32_t nParagIndex = ParagPos.nParagIndex; | |
834 for (i = 0; i < nLength; i++, lpPos++) { | |
835 wCurChar = *lpPos; | |
836 if (wCurChar == m_wLineEnd) { | |
837 if (bFirst) { | |
838 pParag->m_nCharCount = nLeavePart + (i - nTextStart + 1); | |
839 pParag->m_nLineCount = -1; | |
840 nReserveCharStart += pParag->m_nCharCount; | |
841 bFirst = FALSE; | |
842 } else { | |
843 pParag = new CFDE_TxtEdtParag(this); | |
844 pParag->m_nLineCount = -1; | |
845 pParag->m_nCharCount = i - nTextStart + 1; | |
846 pParag->m_nCharStart = nReserveCharStart; | |
847 m_ParagPtrArray.InsertAt(++nParagIndex, pParag); | |
848 nReserveCharStart += pParag->m_nCharCount; | |
849 } | |
850 nTextStart = i + 1; | |
851 } | |
852 } | |
853 if (bFirst) { | |
854 pParag->m_nCharCount += nLength; | |
855 pParag->m_nLineCount = -1; | |
856 bFirst = FALSE; | |
857 } else { | |
858 pParag = new CFDE_TxtEdtParag(this); | |
859 pParag->m_nLineCount = -1; | |
860 pParag->m_nCharCount = nLength - nTextStart + nCutPart; | |
861 pParag->m_nCharStart = nReserveCharStart; | |
862 m_ParagPtrArray.InsertAt(++nParagIndex, pParag); | |
863 } | |
864 m_pTxtBuf->Insert(nStart, lpText, nLength); | |
865 int32_t nTotalLineCount = 0; | |
866 for (i = ParagPos.nParagIndex; i <= nParagIndex; i++) { | |
867 pParag = m_ParagPtrArray[i]; | |
868 pParag->CalcLines(); | |
869 nTotalLineCount += pParag->m_nLineCount; | |
870 } | |
871 m_nLineCount += nTotalLineCount - nReserveLineCount; | |
872 m_Param.pEventSink->On_PageLoad(this, m_nCaretPage, 0); | |
873 UpdatePages(); | |
874 } | |
875 | |
876 void CFDE_TxtEdtEngine::Inner_DeleteRange(int32_t nStart, int32_t nCount) { | |
877 if (nCount == -1) { | |
878 nCount = m_pTxtBuf->GetTextLength() - nStart; | |
879 } | |
880 int32_t nEnd = nStart + nCount - 1; | |
881 FXSYS_assert(nStart >= 0 && nEnd < m_pTxtBuf->GetTextLength()); | |
882 m_Param.pEventSink->On_PageUnload(this, m_nCaretPage, 0); | |
883 FDE_TXTEDTPARAGPOS ParagPosBgn, ParagPosEnd; | |
884 TextPos2ParagPos(nStart, ParagPosBgn); | |
885 TextPos2ParagPos(nEnd, ParagPosEnd); | |
886 CFDE_TxtEdtParag* pParag = m_ParagPtrArray[ParagPosEnd.nParagIndex]; | |
887 FX_BOOL bLastParag = FALSE; | |
888 if (ParagPosEnd.nCharIndex == pParag->m_nCharCount - 1) { | |
889 if (ParagPosEnd.nParagIndex < m_ParagPtrArray.GetSize() - 1) { | |
890 ParagPosEnd.nParagIndex++; | |
891 } else { | |
892 bLastParag = TRUE; | |
893 } | |
894 } | |
895 int32_t nTotalLineCount = 0; | |
896 int32_t nTotalCharCount = 0; | |
897 int32_t i = 0; | |
898 for (i = ParagPosBgn.nParagIndex; i <= ParagPosEnd.nParagIndex; i++) { | |
899 CFDE_TxtEdtParag* pParag = m_ParagPtrArray[i]; | |
900 pParag->CalcLines(); | |
901 nTotalLineCount += pParag->m_nLineCount; | |
902 nTotalCharCount += pParag->m_nCharCount; | |
903 } | |
904 m_pTxtBuf->Delete(nStart, nCount); | |
905 int32_t nNextParagIndex = (ParagPosBgn.nCharIndex == 0 && bLastParag) | |
906 ? ParagPosBgn.nParagIndex | |
907 : (ParagPosBgn.nParagIndex + 1); | |
908 for (i = nNextParagIndex; i <= ParagPosEnd.nParagIndex; i++) { | |
909 CFDE_TxtEdtParag* pParag = m_ParagPtrArray[nNextParagIndex]; | |
910 delete pParag; | |
911 m_ParagPtrArray.RemoveAt(nNextParagIndex); | |
912 } | |
913 if (!(bLastParag && ParagPosBgn.nCharIndex == 0)) { | |
914 pParag = m_ParagPtrArray[ParagPosBgn.nParagIndex]; | |
915 pParag->m_nCharCount = nTotalCharCount - nCount; | |
916 pParag->CalcLines(); | |
917 nTotalLineCount -= pParag->m_nLineCount; | |
918 } | |
919 int32_t nParagCount = m_ParagPtrArray.GetSize(); | |
920 for (i = nNextParagIndex; i < nParagCount; i++) { | |
921 m_ParagPtrArray[i]->m_nCharStart -= nCount; | |
922 } | |
923 m_nLineCount -= nTotalLineCount; | |
924 UpdatePages(); | |
925 int32_t nPageCount = CountPages(); | |
926 if (m_nCaretPage >= nPageCount) { | |
927 m_nCaretPage = nPageCount - 1; | |
928 } | |
929 m_Param.pEventSink->On_PageLoad(this, m_nCaretPage, 0); | |
930 } | |
931 void CFDE_TxtEdtEngine::DeleteRange_DoRecord(int32_t nStart, | |
932 int32_t nCount, | |
933 FX_BOOL bSel) { | |
934 FXSYS_assert(nStart >= 0); | |
935 if (nCount == -1) { | |
936 nCount = GetTextLength() - nStart; | |
937 } | |
938 FXSYS_assert((nStart + nCount) <= m_pTxtBuf->GetTextLength()); | |
939 | |
940 if (!(m_Param.dwMode & FDE_TEXTEDITMODE_NoRedoUndo)) { | |
941 CFX_WideString wsRange; | |
942 m_pTxtBuf->GetRange(wsRange, nStart, nCount); | |
943 IFDE_TxtEdtDoRecord* pRecord = new CFDE_TxtEdtDoRecord_DeleteRange( | |
944 this, nStart, m_nCaret, wsRange, bSel); | |
945 CFX_ByteString bsDoRecord; | |
946 pRecord->Serialize(bsDoRecord); | |
947 m_Param.pEventSink->On_AddDoRecord(this, bsDoRecord); | |
948 pRecord->Release(); | |
949 } | |
950 m_ChangeInfo.nChangeType = FDE_TXTEDT_TEXTCHANGE_TYPE_Delete; | |
951 GetText(m_ChangeInfo.wsDelete, nStart, nCount); | |
952 Inner_DeleteRange(nStart, nCount); | |
953 } | |
954 void CFDE_TxtEdtEngine::ResetEngine() { | |
955 RemoveAllPages(); | |
956 RemoveAllParags(); | |
957 ClearSelection(); | |
958 m_nCaret = 0; | |
959 m_pTxtBuf->Clear(FALSE); | |
960 m_nCaret = 0; | |
961 } | |
962 void CFDE_TxtEdtEngine::RebuildParagraphs() { | |
963 RemoveAllParags(); | |
964 FX_WCHAR wChar = L' '; | |
965 int32_t nParagStart = 0; | |
966 int32_t nIndex = 0; | |
967 IFX_CharIter* pIter = new CFDE_TxtEdtBufIter((CFDE_TxtEdtBuf*)m_pTxtBuf); | |
968 pIter->SetAt(0); | |
969 do { | |
970 wChar = pIter->GetChar(); | |
971 nIndex = pIter->GetAt(); | |
972 if (wChar == m_wLineEnd) { | |
973 CFDE_TxtEdtParag* pParag = new CFDE_TxtEdtParag(this); | |
974 pParag->m_nCharStart = nParagStart; | |
975 pParag->m_nCharCount = nIndex - nParagStart + 1; | |
976 pParag->m_nLineCount = -1; | |
977 m_ParagPtrArray.Add(pParag); | |
978 nParagStart = nIndex + 1; | |
979 } | |
980 } while (pIter->Next()); | |
981 pIter->Release(); | |
982 } | |
983 void CFDE_TxtEdtEngine::RemoveAllParags() { | |
984 int32_t nCount = m_ParagPtrArray.GetSize(); | |
985 int32_t i = 0; | |
986 for (i = 0; i < nCount; i++) { | |
987 CFDE_TxtEdtParag* pParag = m_ParagPtrArray[i]; | |
988 if (pParag) { | |
989 delete pParag; | |
990 } | |
991 } | |
992 m_ParagPtrArray.RemoveAll(); | |
993 } | |
994 void CFDE_TxtEdtEngine::RemoveAllPages() { | |
995 int32_t nCount = m_PagePtrArray.GetSize(); | |
996 int32_t i = 0; | |
997 for (i = 0; i < nCount; i++) { | |
998 IFDE_TxtEdtPage* pPage = m_PagePtrArray[i]; | |
999 if (pPage) { | |
1000 pPage->Release(); | |
1001 } | |
1002 } | |
1003 m_PagePtrArray.RemoveAll(); | |
1004 } | |
1005 void CFDE_TxtEdtEngine::UpdateParags() { | |
1006 int32_t nCount = m_ParagPtrArray.GetSize(); | |
1007 if (nCount == 0) { | |
1008 return; | |
1009 } | |
1010 CFDE_TxtEdtParag* pParag = NULL; | |
1011 int32_t nLineCount = 0; | |
1012 int32_t i = 0; | |
1013 for (i = 0; i < nCount; i++) { | |
1014 pParag = m_ParagPtrArray[i]; | |
1015 if (pParag->m_nLineCount == -1) { | |
1016 pParag->CalcLines(); | |
1017 } | |
1018 nLineCount += pParag->m_nLineCount; | |
1019 } | |
1020 m_nLineCount = nLineCount; | |
1021 } | |
1022 void CFDE_TxtEdtEngine::UpdatePages() { | |
1023 if (m_nLineCount == 0) { | |
1024 return; | |
1025 } | |
1026 int32_t nPageCount = (m_nLineCount - 1) / (m_nPageLineCount) + 1; | |
1027 int32_t nSize = m_PagePtrArray.GetSize(); | |
1028 if (nSize == nPageCount) { | |
1029 return; | |
1030 } | |
1031 if (nSize > nPageCount) { | |
1032 IFDE_TxtEdtPage* pPage = NULL; | |
1033 int32_t i = 0; | |
1034 for (i = nSize - 1; i >= nPageCount; i--) { | |
1035 pPage = m_PagePtrArray[i]; | |
1036 if (pPage) { | |
1037 pPage->Release(); | |
1038 } | |
1039 m_PagePtrArray.RemoveAt(i); | |
1040 } | |
1041 m_Param.pEventSink->On_PageCountChanged(this); | |
1042 return; | |
1043 } | |
1044 if (nSize < nPageCount) { | |
1045 IFDE_TxtEdtPage* pPage = NULL; | |
1046 int32_t i = 0; | |
1047 for (i = nSize; i < nPageCount; i++) { | |
1048 pPage = IFDE_TxtEdtPage::Create(this, i); | |
1049 m_PagePtrArray.Add(pPage); | |
1050 } | |
1051 m_Param.pEventSink->On_PageCountChanged(this); | |
1052 return; | |
1053 } | |
1054 } | |
1055 void CFDE_TxtEdtEngine::UpdateTxtBreak() { | |
1056 FX_DWORD dwStyle = m_pTextBreak->GetLayoutStyles(); | |
1057 if (m_Param.dwMode & FDE_TEXTEDITMODE_MultiLines) { | |
1058 dwStyle &= ~FX_TXTLAYOUTSTYLE_SingleLine; | |
1059 } else { | |
1060 dwStyle |= FX_TXTLAYOUTSTYLE_SingleLine; | |
1061 } | |
1062 if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_DocVertical) { | |
1063 dwStyle |= FX_TXTLAYOUTSTYLE_VerticalLayout; | |
1064 } else { | |
1065 dwStyle &= ~FX_TXTLAYOUTSTYLE_VerticalLayout; | |
1066 } | |
1067 if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_LineReserve) { | |
1068 dwStyle |= FX_TXTLAYOUTSTYLE_ReverseLine; | |
1069 } else { | |
1070 dwStyle &= ~FX_TXTLAYOUTSTYLE_ReverseLine; | |
1071 } | |
1072 if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_RTL) { | |
1073 dwStyle |= FX_TXTLAYOUTSTYLE_RTLReadingOrder; | |
1074 } else { | |
1075 dwStyle &= ~FX_TXTLAYOUTSTYLE_RTLReadingOrder; | |
1076 } | |
1077 if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_CombText) { | |
1078 dwStyle |= FX_TXTLAYOUTSTYLE_CombText; | |
1079 } else { | |
1080 dwStyle &= ~FX_TXTLAYOUTSTYLE_CombText; | |
1081 } | |
1082 if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_CharVertial) { | |
1083 dwStyle |= FX_TXTLAYOUTSTYLE_VerticalChars; | |
1084 } else { | |
1085 dwStyle &= ~FX_TXTLAYOUTSTYLE_VerticalChars; | |
1086 } | |
1087 if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_ExpandTab) { | |
1088 dwStyle |= FX_TXTLAYOUTSTYLE_ExpandTab; | |
1089 } else { | |
1090 dwStyle &= ~FX_TXTLAYOUTSTYLE_ExpandTab; | |
1091 } | |
1092 if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_ArabicContext) { | |
1093 dwStyle |= FX_TXTLAYOUTSTYLE_ArabicContext; | |
1094 } else { | |
1095 dwStyle &= ~FX_TXTLAYOUTSTYLE_ArabicContext; | |
1096 } | |
1097 if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_ArabicShapes) { | |
1098 dwStyle |= FX_TXTLAYOUTSTYLE_ArabicShapes; | |
1099 } else { | |
1100 dwStyle &= ~FX_TXTLAYOUTSTYLE_ArabicShapes; | |
1101 } | |
1102 m_pTextBreak->SetLayoutStyles(dwStyle); | |
1103 FX_DWORD dwAligment = 0; | |
1104 if (m_Param.dwAlignment & FDE_TEXTEDITALIGN_Justified) { | |
1105 dwAligment |= FX_TXTLINEALIGNMENT_Justified; | |
1106 } else if (m_Param.dwAlignment & FDE_TEXTEDITALIGN_Distributed) { | |
1107 dwAligment |= FX_TXTLINEALIGNMENT_Distributed; | |
1108 } | |
1109 if (m_Param.dwAlignment & FDE_TEXTEDITALIGN_Center) { | |
1110 dwAligment |= FX_TXTLINEALIGNMENT_Center; | |
1111 } else if (m_Param.dwAlignment & FDE_TEXTEDITALIGN_Right) { | |
1112 dwAligment |= FX_TXTLINEALIGNMENT_Right; | |
1113 } | |
1114 m_pTextBreak->SetAlignment(dwAligment); | |
1115 if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_DocVertical) { | |
1116 if (m_Param.dwMode & FDE_TEXTEDITMODE_AutoLineWrap) { | |
1117 m_pTextBreak->SetLineWidth(m_Param.fPlateHeight); | |
1118 } else { | |
1119 m_pTextBreak->SetLineWidth(FDE_PAGEWIDTH_MAX); | |
1120 } | |
1121 } else { | |
1122 if (m_Param.dwMode & FDE_TEXTEDITMODE_AutoLineWrap) { | |
1123 m_pTextBreak->SetLineWidth(m_Param.fPlateWidth); | |
1124 } else { | |
1125 m_pTextBreak->SetLineWidth(FDE_PAGEWIDTH_MAX); | |
1126 } | |
1127 } | |
1128 m_nPageLineCount = m_Param.nLineCount; | |
1129 if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_CombText) { | |
1130 FX_FLOAT fCombWidth = | |
1131 m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_DocVertical | |
1132 ? m_Param.fPlateHeight | |
1133 : m_Param.fPlateWidth; | |
1134 if (m_nLimit > 0) { | |
1135 fCombWidth /= m_nLimit; | |
1136 } | |
1137 m_pTextBreak->SetCombWidth(fCombWidth); | |
1138 } | |
1139 m_pTextBreak->SetFont(m_Param.pFont); | |
1140 m_pTextBreak->SetFontSize(m_Param.fFontSize); | |
1141 m_pTextBreak->SetTabWidth(m_Param.fTabWidth, m_Param.bTabEquidistant); | |
1142 m_pTextBreak->SetDefaultChar(m_Param.wDefChar); | |
1143 m_pTextBreak->SetParagraphBreakChar(m_Param.wLineBreakChar); | |
1144 m_pTextBreak->SetCharRotation(m_Param.nCharRotation); | |
1145 m_pTextBreak->SetLineBreakTolerance(m_Param.fFontSize * 0.2f); | |
1146 m_pTextBreak->SetHorizontalScale(m_Param.nHorzScale); | |
1147 m_pTextBreak->SetCharSpace(m_Param.fCharSpace); | |
1148 } | |
1149 FX_BOOL CFDE_TxtEdtEngine::ReplaceParagEnd(FX_WCHAR*& lpText, | |
1150 int32_t& nLength, | |
1151 FX_BOOL bPreIsCR) { | |
1152 for (int32_t i = 0; i < nLength; i++) { | |
1153 FX_WCHAR wc = lpText[i]; | |
1154 switch (wc) { | |
1155 case L'\r': { | |
1156 lpText[i] = m_wLineEnd; | |
1157 bPreIsCR = TRUE; | |
1158 } break; | |
1159 case L'\n': { | |
1160 if (bPreIsCR == TRUE) { | |
1161 int32_t nNext = i + 1; | |
1162 if (nNext < nLength) { | |
1163 FXSYS_memmove(lpText + i, lpText + nNext, | |
1164 (nLength - nNext) * sizeof(FX_WCHAR)); | |
1165 } | |
1166 i--; | |
1167 nLength--; | |
1168 bPreIsCR = FALSE; | |
1169 if (m_bAutoLineEnd) { | |
1170 m_nFirstLineEnd = FDE_TXTEDIT_LINEEND_CRLF; | |
1171 m_bAutoLineEnd = FALSE; | |
1172 } | |
1173 } else { | |
1174 lpText[i] = m_wLineEnd; | |
1175 if (m_bAutoLineEnd) { | |
1176 m_nFirstLineEnd = FDE_TXTEDIT_LINEEND_LF; | |
1177 m_bAutoLineEnd = FALSE; | |
1178 } | |
1179 } | |
1180 } break; | |
1181 default: { | |
1182 if (bPreIsCR && m_bAutoLineEnd) { | |
1183 m_nFirstLineEnd = FDE_TXTEDIT_LINEEND_CR; | |
1184 m_bAutoLineEnd = FALSE; | |
1185 } | |
1186 bPreIsCR = FALSE; | |
1187 } break; | |
1188 } | |
1189 } | |
1190 return bPreIsCR; | |
1191 } | |
1192 void CFDE_TxtEdtEngine::RecoverParagEnd(CFX_WideString& wsText) { | |
1193 FX_WCHAR wc = (m_nFirstLineEnd == FDE_TXTEDIT_LINEEND_CR) ? L'\n' : L'\r'; | |
1194 if (m_nFirstLineEnd == FDE_TXTEDIT_LINEEND_CRLF) { | |
1195 CFX_ArrayTemplate<int32_t> PosArr; | |
1196 int32_t nLength = wsText.GetLength(); | |
1197 int32_t i = 0; | |
1198 FX_WCHAR* lpPos = (FX_WCHAR*)(const FX_WCHAR*)wsText; | |
1199 for (i = 0; i < nLength; i++, lpPos++) { | |
1200 if (*lpPos == m_wLineEnd) { | |
1201 *lpPos = wc; | |
1202 PosArr.Add(i); | |
1203 } | |
1204 } | |
1205 const FX_WCHAR* lpSrcBuf = wsText.c_str(); | |
1206 CFX_WideString wsTemp; | |
1207 int32_t nCount = PosArr.GetSize(); | |
1208 FX_WCHAR* lpDstBuf = wsTemp.GetBuffer(nLength + nCount); | |
1209 int32_t nDstPos = 0; | |
1210 int32_t nSrcPos = 0; | |
1211 for (i = 0; i < nCount; i++) { | |
1212 int32_t nPos = PosArr[i]; | |
1213 int32_t nCopyLen = nPos - nSrcPos + 1; | |
1214 FXSYS_memcpy(lpDstBuf + nDstPos, lpSrcBuf + nSrcPos, | |
1215 nCopyLen * sizeof(FX_WCHAR)); | |
1216 nDstPos += nCopyLen; | |
1217 nSrcPos += nCopyLen; | |
1218 lpDstBuf[nDstPos] = L'\n'; | |
1219 nDstPos++; | |
1220 } | |
1221 if (nSrcPos < nLength) { | |
1222 FXSYS_memcpy(lpDstBuf + nDstPos, lpSrcBuf + nSrcPos, | |
1223 (nLength - nSrcPos) * sizeof(FX_WCHAR)); | |
1224 } | |
1225 wsTemp.ReleaseBuffer(nLength + nCount); | |
1226 wsText = wsTemp; | |
1227 } else { | |
1228 int32_t nLength = wsText.GetLength(); | |
1229 FX_WCHAR* lpBuf = (FX_WCHAR*)(const FX_WCHAR*)wsText; | |
1230 for (int32_t i = 0; i < nLength; i++, lpBuf++) { | |
1231 if (*lpBuf == m_wLineEnd) { | |
1232 *lpBuf = wc; | |
1233 } | |
1234 } | |
1235 } | |
1236 } | |
1237 int32_t CFDE_TxtEdtEngine::MovePage2Char(int32_t nIndex) { | |
1238 FXSYS_assert(nIndex >= 0); | |
1239 FXSYS_assert(nIndex <= m_pTxtBuf->GetTextLength()); | |
1240 if (m_nCaretPage >= 0) { | |
1241 IFDE_TxtEdtPage* pPage = m_PagePtrArray[m_nCaretPage]; | |
1242 m_Param.pEventSink->On_PageLoad(this, m_nCaretPage, 0); | |
1243 int32_t nPageCharStart = pPage->GetCharStart(); | |
1244 int32_t nPageCharCount = pPage->GetCharCount(); | |
1245 if (nIndex >= nPageCharStart && nIndex < nPageCharStart + nPageCharCount) { | |
1246 m_Param.pEventSink->On_PageUnload(this, m_nCaretPage, 0); | |
1247 return m_nCaretPage; | |
1248 } | |
1249 m_Param.pEventSink->On_PageUnload(this, m_nCaretPage, 0); | |
1250 } | |
1251 CFDE_TxtEdtParag* pParag = NULL; | |
1252 int32_t nLineCount = 0; | |
1253 int32_t nParagCount = m_ParagPtrArray.GetSize(); | |
1254 int32_t i = 0; | |
1255 for (i = 0; i < nParagCount; i++) { | |
1256 pParag = m_ParagPtrArray[i]; | |
1257 if (pParag->m_nCharStart <= nIndex && | |
1258 nIndex < (pParag->m_nCharStart + pParag->m_nCharCount)) { | |
1259 break; | |
1260 } | |
1261 nLineCount += pParag->m_nLineCount; | |
1262 } | |
1263 pParag->LoadParag(); | |
1264 int32_t nLineStart = -1; | |
1265 int32_t nLineCharCount = -1; | |
1266 for (i = 0; i < pParag->m_nLineCount; i++) { | |
1267 pParag->GetLineRange(i, nLineStart, nLineCharCount); | |
1268 if (nLineStart <= nIndex && nIndex < (nLineStart + nLineCharCount)) { | |
1269 break; | |
1270 } | |
1271 } | |
1272 FXSYS_assert(i < pParag->m_nLineCount); | |
1273 nLineCount += (i + 1); | |
1274 m_nCaretPage = (nLineCount - 1) / m_nPageLineCount + 1 - 1; | |
1275 m_Param.pEventSink->On_PageChange(this, m_nCaretPage); | |
1276 pParag->UnloadParag(); | |
1277 return m_nCaretPage; | |
1278 } | |
1279 void CFDE_TxtEdtEngine::TextPos2ParagPos(int32_t nIndex, | |
1280 FDE_TXTEDTPARAGPOS& ParagPos) const { | |
1281 FXSYS_assert(nIndex >= 0 && nIndex < m_pTxtBuf->GetTextLength()); | |
1282 int32_t nCount = m_ParagPtrArray.GetSize(); | |
1283 int32_t nBgn = 0; | |
1284 int32_t nMid = 0; | |
1285 int32_t nEnd = nCount - 1; | |
1286 while (nEnd > nBgn) { | |
1287 nMid = (nBgn + nEnd) / 2; | |
1288 CFDE_TxtEdtParag* pParag = m_ParagPtrArray[nMid]; | |
1289 if (nIndex < pParag->m_nCharStart) { | |
1290 nEnd = nMid - 1; | |
1291 } else if (nIndex >= (pParag->m_nCharStart + pParag->m_nCharCount)) { | |
1292 nBgn = nMid + 1; | |
1293 } else { | |
1294 break; | |
1295 } | |
1296 } | |
1297 if (nBgn == nEnd) { | |
1298 nMid = nBgn; | |
1299 } | |
1300 FXSYS_assert(nIndex >= m_ParagPtrArray[nMid]->m_nCharStart && | |
1301 (nIndex < m_ParagPtrArray[nMid]->m_nCharStart + | |
1302 m_ParagPtrArray[nMid]->m_nCharCount)); | |
1303 ParagPos.nParagIndex = nMid; | |
1304 ParagPos.nCharIndex = nIndex - m_ParagPtrArray[nMid]->m_nCharStart; | |
1305 } | |
1306 int32_t CFDE_TxtEdtEngine::MoveForward(FX_BOOL& bBefore) { | |
1307 if (m_nCaret == m_pTxtBuf->GetTextLength() - 1) { | |
1308 return -1; | |
1309 } | |
1310 int32_t nCaret = m_nCaret; | |
1311 if ((nCaret + 1 < m_pTxtBuf->GetTextLength()) && | |
1312 (m_pTxtBuf->GetCharByIndex(nCaret) == L'\r') && | |
1313 (m_pTxtBuf->GetCharByIndex(nCaret + 1) == L'\n')) { | |
1314 nCaret++; | |
1315 } | |
1316 nCaret++; | |
1317 bBefore = TRUE; | |
1318 return nCaret; | |
1319 } | |
1320 int32_t CFDE_TxtEdtEngine::MoveBackward(FX_BOOL& bBefore) { | |
1321 if (m_nCaret == 0) { | |
1322 return FALSE; | |
1323 } | |
1324 int32_t nCaret = m_nCaret; | |
1325 if (nCaret > 2 && m_pTxtBuf->GetCharByIndex(nCaret - 1) == L'\n' && | |
1326 m_pTxtBuf->GetCharByIndex(nCaret - 2) == L'\r') { | |
1327 nCaret--; | |
1328 } | |
1329 nCaret--; | |
1330 bBefore = TRUE; | |
1331 return nCaret; | |
1332 } | |
1333 FX_BOOL CFDE_TxtEdtEngine::MoveUp(CFX_PointF& ptCaret) { | |
1334 IFDE_TxtEdtPage* pPage = GetPage(m_nCaretPage); | |
1335 const CFX_RectF& rtContent = pPage->GetContentsBox(); | |
1336 if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_DocVertical) { | |
1337 ptCaret.x = m_rtCaret.left + m_rtCaret.width / 2 - m_Param.fLineSpace; | |
1338 ptCaret.y = m_fCaretPosReserve; | |
1339 FX_BOOL bLineReserve = | |
1340 m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_LineReserve; | |
1341 if (ptCaret.x < rtContent.left) { | |
1342 if (bLineReserve) { | |
1343 if (m_nCaretPage == CountPages() - 1) { | |
1344 return FALSE; | |
1345 } | |
1346 } else { | |
1347 if (m_nCaretPage == 0) { | |
1348 return FALSE; | |
1349 } | |
1350 } | |
1351 if (bLineReserve) { | |
1352 m_nCaretPage++; | |
1353 } else { | |
1354 m_nCaretPage--; | |
1355 } | |
1356 m_Param.pEventSink->On_PageChange(this, m_nCaretPage); | |
1357 ptCaret.x -= rtContent.left; | |
1358 IFDE_TxtEdtPage* pCurPage = GetPage(m_nCaretPage); | |
1359 ptCaret.x += pCurPage->GetContentsBox().right(); | |
1360 } | |
1361 } else { | |
1362 ptCaret.x = m_fCaretPosReserve; | |
1363 ptCaret.y = m_rtCaret.top + m_rtCaret.height / 2 - m_Param.fLineSpace; | |
1364 if (ptCaret.y < rtContent.top) { | |
1365 if (m_nCaretPage == 0) { | |
1366 return FALSE; | |
1367 } | |
1368 ptCaret.y -= rtContent.top; | |
1369 m_nCaretPage--; | |
1370 m_Param.pEventSink->On_PageChange(this, m_nCaretPage); | |
1371 IFDE_TxtEdtPage* pCurPage = GetPage(m_nCaretPage); | |
1372 ptCaret.y += pCurPage->GetContentsBox().bottom(); | |
1373 } | |
1374 } | |
1375 return TRUE; | |
1376 } | |
1377 FX_BOOL CFDE_TxtEdtEngine::MoveDown(CFX_PointF& ptCaret) { | |
1378 IFDE_TxtEdtPage* pPage = GetPage(m_nCaretPage); | |
1379 const CFX_RectF& rtContent = pPage->GetContentsBox(); | |
1380 if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_DocVertical) { | |
1381 ptCaret.x = m_rtCaret.left + m_rtCaret.width / 2 + m_Param.fLineSpace; | |
1382 ptCaret.y = m_fCaretPosReserve; | |
1383 if (ptCaret.x >= rtContent.right()) { | |
1384 FX_BOOL bLineReserve = | |
1385 m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_LineReserve; | |
1386 if (bLineReserve) { | |
1387 if (m_nCaretPage == 0) { | |
1388 return FALSE; | |
1389 } | |
1390 } else { | |
1391 if (m_nCaretPage == CountPages() - 1) { | |
1392 return FALSE; | |
1393 } | |
1394 } | |
1395 if (bLineReserve) { | |
1396 m_nCaretPage--; | |
1397 } else { | |
1398 m_nCaretPage++; | |
1399 } | |
1400 m_Param.pEventSink->On_PageChange(this, m_nCaretPage); | |
1401 ptCaret.x -= rtContent.right(); | |
1402 IFDE_TxtEdtPage* pCurPage = GetPage(m_nCaretPage); | |
1403 ptCaret.x += pCurPage->GetContentsBox().left; | |
1404 } | |
1405 } else { | |
1406 ptCaret.x = m_fCaretPosReserve; | |
1407 ptCaret.y = m_rtCaret.top + m_rtCaret.height / 2 + m_Param.fLineSpace; | |
1408 if (ptCaret.y >= rtContent.bottom()) { | |
1409 if (m_nCaretPage == CountPages() - 1) { | |
1410 return FALSE; | |
1411 } | |
1412 ptCaret.y -= rtContent.bottom(); | |
1413 m_nCaretPage++; | |
1414 m_Param.pEventSink->On_PageChange(this, m_nCaretPage); | |
1415 IFDE_TxtEdtPage* pCurPage = GetPage(m_nCaretPage); | |
1416 ptCaret.y += pCurPage->GetContentsBox().top; | |
1417 } | |
1418 } | |
1419 return TRUE; | |
1420 } | |
1421 FX_BOOL CFDE_TxtEdtEngine::MoveLineStart() { | |
1422 int32_t nIndex = m_bBefore ? m_nCaret : m_nCaret - 1; | |
1423 FDE_TXTEDTPARAGPOS ParagPos; | |
1424 TextPos2ParagPos(nIndex, ParagPos); | |
1425 CFDE_TxtEdtParag* pParag = m_ParagPtrArray[ParagPos.nParagIndex]; | |
1426 pParag->LoadParag(); | |
1427 int32_t nLineCount = pParag->m_nLineCount; | |
1428 int32_t i = 0; | |
1429 int32_t nStart = 0; | |
1430 int32_t nCount = 0; | |
1431 for (; i < nLineCount; i++) { | |
1432 pParag->GetLineRange(i, nStart, nCount); | |
1433 if (nIndex >= nStart && nIndex < nStart + nCount) { | |
1434 break; | |
1435 } | |
1436 } | |
1437 UpdateCaretRect(nStart, TRUE); | |
1438 pParag->UnloadParag(); | |
1439 return TRUE; | |
1440 } | |
1441 FX_BOOL CFDE_TxtEdtEngine::MoveLineEnd() { | |
1442 int32_t nIndex = m_bBefore ? m_nCaret : m_nCaret - 1; | |
1443 FDE_TXTEDTPARAGPOS ParagPos; | |
1444 TextPos2ParagPos(nIndex, ParagPos); | |
1445 CFDE_TxtEdtParag* pParag = m_ParagPtrArray[ParagPos.nParagIndex]; | |
1446 pParag->LoadParag(); | |
1447 int32_t nLineCount = pParag->m_nLineCount; | |
1448 int32_t i = 0; | |
1449 int32_t nStart = 0; | |
1450 int32_t nCount = 0; | |
1451 for (; i < nLineCount; i++) { | |
1452 pParag->GetLineRange(i, nStart, nCount); | |
1453 if (nIndex >= nStart && nIndex < nStart + nCount) { | |
1454 break; | |
1455 } | |
1456 } | |
1457 nIndex = nStart + nCount - 1; | |
1458 FXSYS_assert(nIndex <= GetTextBufLength()); | |
1459 FX_WCHAR wChar = m_pTxtBuf->GetCharByIndex(nIndex); | |
1460 FX_BOOL bBefore = FALSE; | |
1461 if (nIndex <= GetTextBufLength()) { | |
1462 if (wChar == L'\r') { | |
1463 bBefore = TRUE; | |
1464 } else if (wChar == L'\n' && nIndex > nStart) { | |
1465 bBefore = TRUE; | |
1466 nIndex--; | |
1467 wChar = m_pTxtBuf->GetCharByIndex(nIndex); | |
1468 if (wChar != L'\r') { | |
1469 nIndex++; | |
1470 } | |
1471 } | |
1472 } | |
1473 UpdateCaretRect(nIndex, bBefore); | |
1474 pParag->UnloadParag(); | |
1475 return TRUE; | |
1476 } | |
1477 FX_BOOL CFDE_TxtEdtEngine::MoveParagStart() { | |
1478 int32_t nIndex = m_bBefore ? m_nCaret : m_nCaret - 1; | |
1479 FDE_TXTEDTPARAGPOS ParagPos; | |
1480 TextPos2ParagPos(nIndex, ParagPos); | |
1481 CFDE_TxtEdtParag* pParag = m_ParagPtrArray[ParagPos.nParagIndex]; | |
1482 UpdateCaretRect(pParag->m_nCharStart, TRUE); | |
1483 return TRUE; | |
1484 } | |
1485 FX_BOOL CFDE_TxtEdtEngine::MoveParagEnd() { | |
1486 int32_t nIndex = m_bBefore ? m_nCaret : m_nCaret - 1; | |
1487 FDE_TXTEDTPARAGPOS ParagPos; | |
1488 TextPos2ParagPos(nIndex, ParagPos); | |
1489 CFDE_TxtEdtParag* pParag = m_ParagPtrArray[ParagPos.nParagIndex]; | |
1490 nIndex = pParag->m_nCharStart + pParag->m_nCharCount - 1; | |
1491 FX_WCHAR wChar = m_pTxtBuf->GetCharByIndex(nIndex); | |
1492 if (wChar == L'\n' && nIndex > 0) { | |
1493 nIndex--; | |
1494 wChar = m_pTxtBuf->GetCharByIndex(nIndex); | |
1495 if (wChar != L'\r') { | |
1496 nIndex++; | |
1497 } | |
1498 } | |
1499 UpdateCaretRect(nIndex, TRUE); | |
1500 return TRUE; | |
1501 } | |
1502 FX_BOOL CFDE_TxtEdtEngine::MoveHome() { | |
1503 UpdateCaretRect(0, TRUE); | |
1504 return TRUE; | |
1505 } | |
1506 FX_BOOL CFDE_TxtEdtEngine::MoveEnd() { | |
1507 UpdateCaretRect(GetTextBufLength(), TRUE); | |
1508 return TRUE; | |
1509 } | |
1510 | |
1511 FX_BOOL CFDE_TxtEdtEngine::IsFitArea(CFX_WideString& wsText) { | |
1512 IFDE_TextOut* pTextOut = IFDE_TextOut::Create(); | |
1513 pTextOut->SetLineSpace(m_Param.fLineSpace); | |
1514 pTextOut->SetFont(m_Param.pFont); | |
1515 pTextOut->SetFontSize(m_Param.fFontSize); | |
1516 CFX_RectF rcText; | |
1517 FXSYS_memset(&rcText, 0, sizeof(rcText)); | |
1518 FX_DWORD dwStyle = 0; | |
1519 if (!(m_Param.dwMode & FDE_TEXTEDITMODE_MultiLines)) { | |
1520 dwStyle |= FDE_TTOSTYLE_SingleLine; | |
1521 } | |
1522 if (m_Param.dwMode & FDE_TEXTEDITMODE_AutoLineWrap) { | |
1523 dwStyle |= FDE_TTOSTYLE_LineWrap; | |
1524 rcText.width = m_Param.fPlateWidth; | |
1525 } else { | |
1526 rcText.width = 65535; | |
1527 } | |
1528 pTextOut->SetStyles(dwStyle); | |
1529 wsText += L"\n"; | |
1530 pTextOut->CalcLogicSize(wsText, wsText.GetLength(), rcText); | |
1531 pTextOut->Release(); | |
1532 wsText.Delete(wsText.GetLength() - 1); | |
1533 if ((m_Param.dwMode & FDE_TEXTEDITMODE_LimitArea_Horz) && | |
1534 (rcText.width > m_Param.fPlateWidth)) { | |
1535 return FALSE; | |
1536 } | |
1537 if ((m_Param.dwMode & FDE_TEXTEDITMODE_LimitArea_Vert) && | |
1538 (rcText.height > m_Param.fLineSpace * m_Param.nLineCount)) { | |
1539 return FALSE; | |
1540 } | |
1541 return TRUE; | |
1542 } | |
1543 void CFDE_TxtEdtEngine::UpdateCaretRect(int32_t nIndex, FX_BOOL bBefore) { | |
1544 MovePage2Char(nIndex); | |
1545 GetCaretRect(m_rtCaret, m_nCaretPage, nIndex, bBefore); | |
1546 m_nCaret = nIndex; | |
1547 m_bBefore = bBefore; | |
1548 if (!m_bBefore) { | |
1549 m_nCaret++; | |
1550 m_bBefore = TRUE; | |
1551 } | |
1552 m_fCaretPosReserve = (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_DocVertical) | |
1553 ? m_rtCaret.top | |
1554 : m_rtCaret.left; | |
1555 m_Param.pEventSink->On_CaretChanged(this, m_nCaretPage, 0); | |
1556 } | |
1557 void CFDE_TxtEdtEngine::GetCaretRect(CFX_RectF& rtCaret, | |
1558 int32_t nPageIndex, | |
1559 int32_t nCaret, | |
1560 FX_BOOL bBefore) { | |
1561 IFDE_TxtEdtPage* pPage = m_PagePtrArray[m_nCaretPage]; | |
1562 m_Param.pEventSink->On_PageLoad(this, m_nCaretPage, 0); | |
1563 FX_BOOL bCombText = m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_CombText; | |
1564 int32_t nIndexInpage = nCaret - pPage->GetCharStart(); | |
1565 if (bBefore && bCombText && nIndexInpage > 0) { | |
1566 nIndexInpage--; | |
1567 bBefore = FALSE; | |
1568 } | |
1569 int32_t nBIDILevel = pPage->GetCharRect(nIndexInpage, rtCaret, bCombText); | |
1570 if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_DocVertical) { | |
1571 if ((!FX_IsOdd(nBIDILevel) && !bBefore) || | |
1572 (FX_IsOdd(nBIDILevel) && bBefore)) { | |
1573 rtCaret.Offset(0, rtCaret.height - 1.0f); | |
1574 } | |
1575 if (rtCaret.height == 0 && rtCaret.top > 1.0f) { | |
1576 rtCaret.top -= 1.0f; | |
1577 } | |
1578 rtCaret.height = 1.0f; | |
1579 } else { | |
1580 if ((!FX_IsOdd(nBIDILevel) && !bBefore) || | |
1581 (FX_IsOdd(nBIDILevel) && bBefore)) { | |
1582 rtCaret.Offset(rtCaret.width - 1.0f, 0); | |
1583 } | |
1584 if (rtCaret.width == 0 && rtCaret.left > 1.0f) { | |
1585 rtCaret.left -= 1.0f; | |
1586 } | |
1587 rtCaret.width = 1.0f; | |
1588 } | |
1589 m_Param.pEventSink->On_PageUnload(this, m_nCaretPage, 0); | |
1590 } | |
1591 void CFDE_TxtEdtEngine::UpdateCaretIndex(const CFX_PointF& ptCaret) { | |
1592 IFDE_TxtEdtPage* pPage = m_PagePtrArray[m_nCaretPage]; | |
1593 m_Param.pEventSink->On_PageLoad(this, m_nCaretPage, 0); | |
1594 m_nCaret = pPage->GetCharIndex(ptCaret, m_bBefore); | |
1595 GetCaretRect(m_rtCaret, m_nCaretPage, m_nCaret, m_bBefore); | |
1596 if (!m_bBefore) { | |
1597 m_nCaret++; | |
1598 m_bBefore = TRUE; | |
1599 } | |
1600 m_Param.pEventSink->On_CaretChanged(this, m_nCaretPage); | |
1601 m_Param.pEventSink->On_PageUnload(this, m_nCaretPage, 0); | |
1602 } | |
1603 FX_BOOL CFDE_TxtEdtEngine::IsSelect() { | |
1604 return m_SelRangePtrArr.GetSize() > 0; | |
1605 } | |
1606 void CFDE_TxtEdtEngine::DeleteSelect() { | |
1607 int32_t nCountRange = CountSelRanges(); | |
1608 if (nCountRange > 0) { | |
1609 int32_t nSelStart; | |
1610 int32_t nSelCount; | |
1611 while (nCountRange > 0) { | |
1612 nSelCount = GetSelRange(--nCountRange, nSelStart); | |
1613 FDE_LPTXTEDTSELRANGE lpTemp = m_SelRangePtrArr[nCountRange]; | |
1614 delete lpTemp; | |
1615 m_SelRangePtrArr.RemoveAt(nCountRange); | |
1616 DeleteRange_DoRecord(nSelStart, nSelCount, TRUE); | |
1617 } | |
1618 ClearSelection(); | |
1619 m_Param.pEventSink->On_TextChanged(this, m_ChangeInfo); | |
1620 m_Param.pEventSink->On_SelChanged(this); | |
1621 SetCaretPos(nSelStart, TRUE); | |
1622 return; | |
1623 } | |
1624 } | |
1625 IFDE_TxtEdtDoRecord* IFDE_TxtEdtDoRecord::Create( | |
1626 const CFX_ByteStringC& bsDoRecord) { | |
1627 const FX_CHAR* lpBuf = bsDoRecord.GetCStr(); | |
1628 int32_t nType = *((int32_t*)lpBuf); | |
1629 switch (nType) { | |
1630 case FDE_TXTEDT_DORECORD_INS: | |
1631 return new CFDE_TxtEdtDoRecord_Insert(bsDoRecord); | |
1632 case FDE_TXTEDT_DORECORD_DEL: | |
1633 return new CFDE_TxtEdtDoRecord_DeleteRange(bsDoRecord); | |
1634 default: | |
1635 break; | |
1636 } | |
1637 return NULL; | |
1638 } | |
1639 CFDE_TxtEdtDoRecord_Insert::CFDE_TxtEdtDoRecord_Insert( | |
1640 const CFX_ByteStringC& bsDoRecord) { | |
1641 Deserialize(bsDoRecord); | |
1642 } | |
1643 CFDE_TxtEdtDoRecord_Insert::CFDE_TxtEdtDoRecord_Insert( | |
1644 CFDE_TxtEdtEngine* pEngine, | |
1645 int32_t nCaret, | |
1646 const FX_WCHAR* lpText, | |
1647 int32_t nLength) | |
1648 : m_pEngine(pEngine), m_nCaret(nCaret) { | |
1649 FXSYS_assert(pEngine); | |
1650 FX_WCHAR* lpBuffer = m_wsInsert.GetBuffer(nLength); | |
1651 FXSYS_memcpy(lpBuffer, lpText, nLength * sizeof(FX_WCHAR)); | |
1652 m_wsInsert.ReleaseBuffer(); | |
1653 } | |
1654 CFDE_TxtEdtDoRecord_Insert::~CFDE_TxtEdtDoRecord_Insert() {} | |
1655 void CFDE_TxtEdtDoRecord_Insert::Release() { | |
1656 delete this; | |
1657 } | |
1658 FX_BOOL CFDE_TxtEdtDoRecord_Insert::Undo() { | |
1659 if (m_pEngine->IsSelect()) { | |
1660 m_pEngine->ClearSelection(); | |
1661 } | |
1662 m_pEngine->Inner_DeleteRange(m_nCaret, m_wsInsert.GetLength()); | |
1663 FDE_TXTEDTPARAMS& Param = m_pEngine->m_Param; | |
1664 m_pEngine->m_ChangeInfo.nChangeType = FDE_TXTEDT_TEXTCHANGE_TYPE_Delete; | |
1665 m_pEngine->m_ChangeInfo.wsDelete = m_wsInsert; | |
1666 Param.pEventSink->On_TextChanged(m_pEngine, m_pEngine->m_ChangeInfo); | |
1667 m_pEngine->SetCaretPos(m_nCaret, TRUE); | |
1668 return TRUE; | |
1669 } | |
1670 FX_BOOL CFDE_TxtEdtDoRecord_Insert::Redo() { | |
1671 m_pEngine->Inner_Insert(m_nCaret, m_wsInsert.c_str(), m_wsInsert.GetLength()); | |
1672 FDE_TXTEDTPARAMS& Param = m_pEngine->m_Param; | |
1673 m_pEngine->m_ChangeInfo.nChangeType = FDE_TXTEDT_TEXTCHANGE_TYPE_Insert; | |
1674 m_pEngine->m_ChangeInfo.wsDelete = m_wsInsert; | |
1675 Param.pEventSink->On_TextChanged(m_pEngine, m_pEngine->m_ChangeInfo); | |
1676 m_pEngine->SetCaretPos(m_nCaret, FALSE); | |
1677 return TRUE; | |
1678 } | |
1679 void CFDE_TxtEdtDoRecord_Insert::Serialize(CFX_ByteString& bsDoRecord) const { | |
1680 CFX_ArchiveSaver ArchiveSaver; | |
1681 ArchiveSaver << int32_t(FDE_TXTEDT_DORECORD_INS); | |
1682 ArchiveSaver << (int32_t)(uintptr_t)m_pEngine; | |
1683 ArchiveSaver << m_nCaret; | |
1684 ArchiveSaver << m_wsInsert; | |
1685 int32_t nLength = ArchiveSaver.GetLength(); | |
1686 const uint8_t* lpSrcBuf = ArchiveSaver.GetBuffer(); | |
1687 FX_CHAR* lpDstBuf = bsDoRecord.GetBuffer(nLength); | |
1688 FXSYS_memcpy(lpDstBuf, lpSrcBuf, nLength); | |
1689 bsDoRecord.ReleaseBuffer(nLength); | |
1690 } | |
1691 void CFDE_TxtEdtDoRecord_Insert::Deserialize( | |
1692 const CFX_ByteStringC& bsDoRecord) { | |
1693 CFX_ArchiveLoader ArchiveLoader((const uint8_t*)bsDoRecord.GetCStr(), | |
1694 bsDoRecord.GetLength()); | |
1695 int32_t nType = 0; | |
1696 ArchiveLoader >> nType; | |
1697 FXSYS_assert(nType == FDE_TXTEDT_DORECORD_INS); | |
1698 int32_t nEngine = 0; | |
1699 ArchiveLoader >> nEngine; | |
1700 m_pEngine = (CFDE_TxtEdtEngine*)(uintptr_t)nEngine; | |
1701 ArchiveLoader >> m_nCaret; | |
1702 ArchiveLoader >> m_wsInsert; | |
1703 } | |
1704 CFDE_TxtEdtDoRecord_DeleteRange::CFDE_TxtEdtDoRecord_DeleteRange( | |
1705 const CFX_ByteStringC& bsDoRecord) { | |
1706 Deserialize(bsDoRecord); | |
1707 } | |
1708 CFDE_TxtEdtDoRecord_DeleteRange::CFDE_TxtEdtDoRecord_DeleteRange( | |
1709 CFDE_TxtEdtEngine* pEngine, | |
1710 int32_t nIndex, | |
1711 int32_t nCaret, | |
1712 const CFX_WideString& wsRange, | |
1713 FX_BOOL bSel) | |
1714 : m_pEngine(pEngine), | |
1715 m_bSel(bSel), | |
1716 m_nIndex(nIndex), | |
1717 m_nCaret(nCaret), | |
1718 m_wsRange(wsRange) { | |
1719 FXSYS_assert(pEngine); | |
1720 } | |
1721 CFDE_TxtEdtDoRecord_DeleteRange::~CFDE_TxtEdtDoRecord_DeleteRange() {} | |
1722 void CFDE_TxtEdtDoRecord_DeleteRange::Release() { | |
1723 delete this; | |
1724 } | |
1725 FX_BOOL CFDE_TxtEdtDoRecord_DeleteRange::Undo() { | |
1726 if (m_pEngine->IsSelect()) { | |
1727 m_pEngine->ClearSelection(); | |
1728 } | |
1729 m_pEngine->Inner_Insert(m_nIndex, m_wsRange.c_str(), m_wsRange.GetLength()); | |
1730 if (m_bSel) { | |
1731 m_pEngine->AddSelRange(m_nIndex, m_wsRange.GetLength()); | |
1732 } | |
1733 FDE_TXTEDTPARAMS& Param = m_pEngine->m_Param; | |
1734 m_pEngine->m_ChangeInfo.nChangeType = FDE_TXTEDT_TEXTCHANGE_TYPE_Insert; | |
1735 m_pEngine->m_ChangeInfo.wsDelete = m_wsRange; | |
1736 Param.pEventSink->On_TextChanged(m_pEngine, m_pEngine->m_ChangeInfo); | |
1737 m_pEngine->SetCaretPos(m_nCaret, TRUE); | |
1738 return TRUE; | |
1739 } | |
1740 FX_BOOL CFDE_TxtEdtDoRecord_DeleteRange::Redo() { | |
1741 m_pEngine->Inner_DeleteRange(m_nIndex, m_wsRange.GetLength()); | |
1742 if (m_bSel) { | |
1743 m_pEngine->RemoveSelRange(m_nIndex, m_wsRange.GetLength()); | |
1744 } | |
1745 FDE_TXTEDTPARAMS& Param = m_pEngine->m_Param; | |
1746 m_pEngine->m_ChangeInfo.nChangeType = FDE_TXTEDT_TEXTCHANGE_TYPE_Insert; | |
1747 m_pEngine->m_ChangeInfo.wsDelete = m_wsRange; | |
1748 Param.pEventSink->On_TextChanged(m_pEngine, m_pEngine->m_ChangeInfo); | |
1749 m_pEngine->SetCaretPos(m_nIndex, TRUE); | |
1750 return TRUE; | |
1751 } | |
1752 void CFDE_TxtEdtDoRecord_DeleteRange::Serialize( | |
1753 CFX_ByteString& bsDoRecord) const { | |
1754 CFX_ArchiveSaver ArchiveSaver; | |
1755 ArchiveSaver << int32_t(FDE_TXTEDT_DORECORD_DEL); | |
1756 ArchiveSaver << (int32_t)(uintptr_t)m_pEngine; | |
1757 ArchiveSaver << (int32_t)m_bSel; | |
1758 ArchiveSaver << m_nIndex; | |
1759 ArchiveSaver << m_nCaret; | |
1760 ArchiveSaver << m_wsRange; | |
1761 int32_t nLength = ArchiveSaver.GetLength(); | |
1762 const uint8_t* lpSrcBuf = ArchiveSaver.GetBuffer(); | |
1763 FX_CHAR* lpDstBuf = bsDoRecord.GetBuffer(nLength); | |
1764 FXSYS_memcpy(lpDstBuf, lpSrcBuf, nLength); | |
1765 bsDoRecord.ReleaseBuffer(nLength); | |
1766 } | |
1767 void CFDE_TxtEdtDoRecord_DeleteRange::Deserialize( | |
1768 const CFX_ByteStringC& bsDoRecord) { | |
1769 CFX_ArchiveLoader ArchiveLoader((const uint8_t*)bsDoRecord.GetCStr(), | |
1770 bsDoRecord.GetLength()); | |
1771 int32_t nType = 0; | |
1772 ArchiveLoader >> nType; | |
1773 FXSYS_assert(nType == FDE_TXTEDT_DORECORD_DEL); | |
1774 int32_t nEngine = 0; | |
1775 ArchiveLoader >> nEngine; | |
1776 m_pEngine = (CFDE_TxtEdtEngine*)(uintptr_t)nEngine; | |
1777 int32_t iSel = 0; | |
1778 ArchiveLoader >> iSel; | |
1779 m_bSel = !!iSel; | |
1780 ArchiveLoader >> m_nIndex; | |
1781 ArchiveLoader >> m_nCaret; | |
1782 ArchiveLoader >> m_wsRange; | |
1783 } | |
OLD | NEW |