Merge XFA to PDFium master at 4dc95e7 on 10/28/2014
[pdfium.git] / xfa / src / fee / src / fee / fde_txtedtengine.cpp
1 // Copyright 2014 PDFium Authors. All rights reserved.\r
2 // Use of this source code is governed by a BSD-style license that can be\r
3 // found in the LICENSE file.\r
4 \r
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com\r
6 \r
7 #include "../../../foxitlib.h"\r
8 #include "../../include/ifde_txtedtengine.h"\r
9 #include "../../include/ifde_txtedtbuf.h"\r
10 #include "../../include/ifde_txtedtpage.h"\r
11 #include "fde_txtedtengine.h"\r
12 #include "fde_txtedtparag.h"\r
13 #include "fde_txtedtkmpmatch.h"\r
14 #include "fde_txtedtbuf.h"\r
15 #ifdef FDE_USEFORMATBLOCK\r
16 #include "fde_txtedtblock.h"\r
17 #endif\r
18 #define FDE_PAGEWIDTH_MAX                               0xFFFF\r
19 #define FDE_TXTPLATESIZE                                (1024 * 12)\r
20 #define FDE_UNICODE_PARAGRAPH_SPERATOR  (0x2029)\r
21 #define FDE_TXTEDT_DORECORD_INS                 0\r
22 #define FDE_TXTEDT_DORECORD_DEL                 1\r
23 #ifdef FDE_USEFORMATBLOCK\r
24 #define FDE_TXTEDT_DORECORD_FORMATINS   3\r
25 #define FDE_TXTEDT_DORECORD_FORMATDEL   4\r
26 #define FDE_TXTEDT_DORECORD_FORMATREP   5\r
27 #define FDE_TXTEDT_FORMATBLOCK_BGN              0xFFF9\r
28 #define FDE_TXTEDT_FORMATBLOCK_END              0xFFFB\r
29 #endif\r
30 IFDE_TxtEdtEngine * IFDE_TxtEdtEngine::Create()\r
31 {\r
32     return FX_NEW CFDE_TxtEdtEngine();\r
33 }\r
34 CFDE_TxtEdtEngine::CFDE_TxtEdtEngine()\r
35     : m_nPageLineCount(20)\r
36     , m_nLineCount(0)\r
37     , m_nAnchorPos(-1)\r
38     , m_nLayoutPos(0)\r
39     , m_fCaretPosReserve(0.0)\r
40     , m_nCaret(0)\r
41     , m_bBefore(TRUE)\r
42     , m_nCaretPage(0)\r
43     , m_bLock(FALSE)\r
44     , m_nLimit(0)\r
45     , m_wcAliasChar(L'*')\r
46     , m_pTextBreak(NULL)\r
47 #ifdef FDE_USEFORMATBLOCK\r
48     , m_nFixLength(-1)\r
49 #endif\r
50     , m_dwFindFlags(0)\r
51     , m_nFirstLineEnd(FDE_TXTEDIT_LINEEND_Auto)\r
52     , m_wLineEnd(FDE_UNICODE_PARAGRAPH_SPERATOR)\r
53     , m_bAutoLineEnd(TRUE)\r
54 {\r
55     FXSYS_memset(&m_rtCaret, 0, sizeof(CFX_RectF));\r
56     m_pTxtBuf = FX_NEW CFDE_TxtEdtBuf();\r
57     m_bAutoLineEnd      = (m_Param.nLineEnd == FDE_TXTEDIT_LINEEND_Auto);\r
58 }\r
59 CFDE_TxtEdtEngine::~CFDE_TxtEdtEngine()\r
60 {\r
61     if (m_pTxtBuf) {\r
62         m_pTxtBuf->Release();\r
63         m_pTxtBuf = NULL;\r
64     }\r
65     if (m_pTextBreak) {\r
66         m_pTextBreak->Release();\r
67         m_pTextBreak = NULL;\r
68     }\r
69 #ifdef FDE_USEFORMATBLOCK\r
70     FX_INT32 nBlockCount = m_BlockArray.GetSize();\r
71     if (nBlockCount > 0) {\r
72         FX_INT32 i = 0;\r
73         for (; i < nBlockCount; i ++) {\r
74             CFDE_TxtEdtBlock * pBlock = m_BlockArray[i];\r
75             delete pBlock;\r
76         }\r
77         m_BlockArray.RemoveAll();\r
78     }\r
79 #endif\r
80     RemoveAllParags();\r
81     RemoveAllPages();\r
82     m_Param.pEventSink = NULL;\r
83     ClearSelection();\r
84 }\r
85 void CFDE_TxtEdtEngine::Release()\r
86 {\r
87     delete this;\r
88 }\r
89 void CFDE_TxtEdtEngine::SetEditParams(const FDE_TXTEDTPARAMS &params)\r
90 {\r
91     if (m_pTextBreak == NULL) {\r
92         m_pTextBreak    = IFX_TxtBreak::Create(FX_TXTBREAKPOLICY_None);\r
93     }\r
94     FXSYS_memcpy(&m_Param, &params, sizeof(FDE_TXTEDTPARAMS));\r
95     m_wLineEnd          = params.wLineBreakChar;\r
96     m_bAutoLineEnd      = (m_Param.nLineEnd == FDE_TXTEDIT_LINEEND_Auto);\r
97     UpdateTxtBreak();\r
98 }\r
99 const FDE_TXTEDTPARAMS * CFDE_TxtEdtEngine::GetEditParams() const\r
100 {\r
101     return &m_Param;\r
102 }\r
103 FX_INT32 CFDE_TxtEdtEngine::CountPages() const\r
104 {\r
105     if (m_nLineCount == 0) {\r
106         return 0;\r
107     }\r
108     return ((m_nLineCount - 1) / m_nPageLineCount) + 1;\r
109 }\r
110 IFDE_TxtEdtPage * CFDE_TxtEdtEngine::GetPage(FX_INT32 nIndex)\r
111 {\r
112     if (m_PagePtrArray.GetSize() <= nIndex) {\r
113         return NULL;\r
114     }\r
115     return (IFDE_TxtEdtPage*)m_PagePtrArray[nIndex];\r
116 }\r
117 FX_BOOL CFDE_TxtEdtEngine::SetBufChunkSize(FX_INT32 nChunkSize)\r
118 {\r
119     return m_pTxtBuf->SetChunkSize(nChunkSize);\r
120 }\r
121 void CFDE_TxtEdtEngine::SetTextByStream(IFX_Stream *pStream)\r
122 {\r
123     ResetEngine();\r
124     FX_INT32    nIndex  = 0;\r
125     if (pStream != NULL && pStream->GetLength()) {\r
126         FX_INT32        nStreamLength   = pStream->GetLength();\r
127         FX_BOOL         bValid                  = TRUE;\r
128         if (m_nLimit > 0 && nStreamLength > m_nLimit) {\r
129             bValid = FALSE;\r
130         }\r
131         FX_BOOL bPreIsCR = FALSE;\r
132         if (bValid) {\r
133             FX_BYTE bom[4];\r
134             FX_INT32 nPos  = pStream->GetBOM(bom);\r
135             pStream->Seek(FX_STREAMSEEK_Begin, nPos);\r
136             FX_INT32    bEos            = FALSE;\r
137             FX_INT32    nPlateSize      = FX_MIN(nStreamLength, m_pTxtBuf->GetChunkSize());\r
138             FX_LPWSTR   lpwstr          = (FX_LPWSTR)FDE_Alloc(nPlateSize * sizeof(FX_WCHAR));\r
139             FXSYS_assert(lpwstr);\r
140             FX_INT32    nRead = 0;\r
141             while (!bEos) {\r
142                 nRead = pStream->ReadString(lpwstr, nPlateSize, bEos);\r
143                 bPreIsCR = ReplaceParagEnd(lpwstr, nRead, bPreIsCR);\r
144                 m_pTxtBuf->Insert(nIndex, lpwstr, nRead);\r
145                 nIndex += nRead;\r
146             }\r
147             FDE_Free(lpwstr);\r
148         }\r
149     }\r
150     m_pTxtBuf->Insert(nIndex, &m_wLineEnd, 1);\r
151     RebuildParagraphs();\r
152 }\r
153 void CFDE_TxtEdtEngine::SetText(const CFX_WideString &wsText)\r
154 {\r
155     ResetEngine();\r
156     FX_INT32 nLength = wsText.GetLength();\r
157     if (nLength > 0) {\r
158         CFX_WideString wsTemp;\r
159         FX_LPWSTR lpBuffer = wsTemp.GetBuffer(nLength);\r
160         FXSYS_memcpy(lpBuffer, FX_LPCWSTR(wsText), nLength * sizeof(FX_WCHAR));\r
161         ReplaceParagEnd(lpBuffer, nLength, FALSE);\r
162         wsTemp.ReleaseBuffer(nLength);\r
163         if (m_nLimit > 0 && nLength > m_nLimit) {\r
164             wsTemp.Delete(m_nLimit, nLength - m_nLimit);\r
165             nLength = m_nLimit;\r
166         }\r
167         m_pTxtBuf->SetText(wsTemp);\r
168     }\r
169     m_pTxtBuf->Insert(nLength, &m_wLineEnd, 1);\r
170     RebuildParagraphs();\r
171 }\r
172 FX_INT32 CFDE_TxtEdtEngine::GetTextLength() const\r
173 {\r
174     return GetTextBufLength();\r
175 }\r
176 void CFDE_TxtEdtEngine::GetText(CFX_WideString &wsText, FX_INT32 nStart, FX_INT32 nCount )\r
177 {\r
178     FX_INT32 nTextBufLength = GetTextBufLength();\r
179     if (nCount == -1) {\r
180         nCount = nTextBufLength - nStart;\r
181     }\r
182 #ifdef FDE_USEFORMATBLOCK\r
183     FX_INT32 nBlockCount = m_BlockArray.GetSize();\r
184     if (nBlockCount == 0 || m_wsFixText.IsEmpty()) {\r
185         m_pTxtBuf->GetRange(wsText, nStart, nCount);\r
186         return;\r
187     }\r
188     CFX_WideString wsTemp;\r
189     FX_LPCWSTR  lpFixBuffer     = FX_LPCWSTR(m_wsFixText);\r
190     FX_LPWSTR   lpBuffer        = wsTemp.GetBuffer(nTextBufLength);\r
191     FX_INT32 nRealLength        = 0;\r
192     FX_INT32 nPrePos            = 0;\r
193     for (FX_INT32 i = 0; i < nBlockCount; i ++) {\r
194         CFDE_TxtEdtBlock *pBlock = m_BlockArray[i];\r
195         FX_INT32 nPos = pBlock->GetPos();\r
196         FX_INT32 nCopyLength = nPos - nPrePos;\r
197         FXSYS_memcpy(lpBuffer + nRealLength, lpFixBuffer + nPrePos, nCopyLength * sizeof(FX_WCHAR));\r
198         nRealLength += nCopyLength;\r
199         nPrePos         =  nPos;\r
200         CFX_WideString wsBlock;\r
201         pBlock->GetRealText(wsBlock);\r
202         nCopyLength = wsBlock.GetLength();\r
203         FXSYS_memcpy(lpBuffer + nRealLength, FX_LPCWSTR(wsBlock), nCopyLength * sizeof(FX_WCHAR));\r
204         nRealLength += nCopyLength;\r
205     }\r
206     FX_INT32 nLeftLength = m_wsFixText.GetLength() - nPrePos;\r
207     if (nLeftLength > 0) {\r
208         FXSYS_memcpy(lpBuffer + nRealLength, lpFixBuffer + nPrePos, nLeftLength * sizeof(FX_WCHAR));\r
209         nRealLength += nLeftLength;\r
210     }\r
211     wsTemp.ReleaseBuffer(nRealLength);\r
212     FX_INT32 nRealBgn   = GetRealIndex(nStart);\r
213     FX_INT32 nRealEnd   = GetRealIndex(nStart + nCount - 1);\r
214     FX_INT32 nRealCount = nRealEnd - nRealBgn;\r
215     FX_LPWSTR lpDestBuf = wsText.GetBuffer(nRealCount);\r
216     FXSYS_memcpy(lpDestBuf, FX_LPCWSTR(wsTemp) + nRealBgn, nRealCount * sizeof(FX_WCHAR));\r
217     wsText.ReleaseBuffer();\r
218 #else\r
219     m_pTxtBuf->GetRange(wsText, nStart, nCount);\r
220     RecoverParagEnd(wsText);\r
221     return;\r
222 #endif\r
223 }\r
224 void CFDE_TxtEdtEngine::ClearText()\r
225 {\r
226     DeleteRange(0, -1);\r
227 }\r
228 FX_INT32 CFDE_TxtEdtEngine::GetCaretRect(CFX_RectF &rtCaret) const\r
229 {\r
230     rtCaret = m_rtCaret;\r
231     return m_nCaret;\r
232 }\r
233 FX_INT32 CFDE_TxtEdtEngine::GetCaretPos() const\r
234 {\r
235     if (IsLocked()) {\r
236         return 0;\r
237     }\r
238     return m_nCaret + (m_bBefore ? 0 : 1);\r
239 }\r
240 FX_INT32 CFDE_TxtEdtEngine::SetCaretPos(FX_INT32 nIndex, FX_BOOL bBefore)\r
241 {\r
242     if (IsLocked()) {\r
243         return 0;\r
244     }\r
245     FXSYS_assert(nIndex >= 0 && nIndex <= GetTextBufLength());\r
246     if (m_PagePtrArray.GetSize() <= m_nCaretPage) {\r
247         return 0;\r
248     }\r
249 #ifdef FDE_USEFORMATBLOCK\r
250     if (m_BlockArray.GetSize() > 0) {\r
251         nIndex = NormalizeCaretPos(nIndex, FDE_FORMAT_CARET_MIDDLE, bBefore);\r
252     }\r
253 #endif\r
254     m_bBefore   = bBefore;\r
255     m_nCaret    = nIndex;\r
256     MovePage2Char(m_nCaret);\r
257     GetCaretRect(m_rtCaret, m_nCaretPage, m_nCaret, m_bBefore);\r
258     if (!m_bBefore) {\r
259         m_nCaret ++;\r
260         m_bBefore = TRUE;\r
261     }\r
262     m_fCaretPosReserve = (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_DocVertical) ? \\r
263                          m_rtCaret.top : m_rtCaret.left;\r
264     m_Param.pEventSink->On_CaretChanged(this, m_nCaretPage, 0);\r
265     m_nAnchorPos = -1;\r
266     return m_nCaret;\r
267 }\r
268 FX_INT32 CFDE_TxtEdtEngine::MoveCaretPos(FDE_TXTEDTMOVECARET eMoveCaret,\r
269         FX_BOOL bShift ,\r
270         FX_BOOL bCtrl )\r
271 {\r
272     if (IsLocked()) {\r
273         return 0;\r
274     }\r
275     if (m_PagePtrArray.GetSize() <= m_nCaretPage) {\r
276         return 0;\r
277     }\r
278     FX_BOOL bSelChange = FALSE;\r
279     if (IsSelect()) {\r
280         ClearSelection();\r
281         bSelChange = TRUE;\r
282     }\r
283     if (bShift) {\r
284         if (m_nAnchorPos == -1) {\r
285             m_nAnchorPos = m_nCaret;\r
286         }\r
287     } else {\r
288         m_nAnchorPos = -1;\r
289     }\r
290     FX_BOOL             bVertical       = m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_DocVertical;\r
291     FX_INT32    nCaret          = m_nCaret;\r
292     FX_INT32    nCaretPage      = m_nCaretPage;\r
293     switch (eMoveCaret) {\r
294         case MC_Left: {\r
295                 if (bVertical) {\r
296                     CFX_PointF ptCaret;\r
297                     if (MoveUp(ptCaret)) {\r
298                         UpdateCaretIndex(ptCaret);\r
299                     }\r
300                 } else {\r
301                     FX_BOOL bBefore = TRUE;\r
302                     FX_INT32 nIndex = MoveBackward(bBefore);\r
303 #ifdef FDE_USEFORMATBLOCK\r
304                     if (m_BlockArray.GetSize()) {\r
305                         nIndex = NormalizeCaretPos(nIndex, FDE_FORMAT_CARET_BACKWARD, bBefore);\r
306                         if (nIndex < 0) {\r
307                             return m_nCaret;\r
308                         }\r
309                     }\r
310 #endif\r
311                     if (nIndex >= 0) {\r
312                         UpdateCaretRect(nIndex, bBefore);\r
313                     }\r
314                 }\r
315             }\r
316             break;\r
317         case MC_Right: {\r
318                 if (bVertical) {\r
319                     CFX_PointF ptCaret;\r
320                     if (MoveDown(ptCaret))      {\r
321                         UpdateCaretIndex(ptCaret);\r
322                     }\r
323                 } else {\r
324                     FX_BOOL bBefore = TRUE;\r
325                     FX_INT32 nIndex = MoveForward(bBefore);\r
326 #ifdef FDE_USEFORMATBLOCK\r
327                     if (m_BlockArray.GetSize()) {\r
328                         if (nIndex == -1) {\r
329                             nIndex = GetTextBufLength();\r
330                         }\r
331                         nIndex = NormalizeCaretPos(nIndex, FDE_FORMAT_CARET_FORWARD, bBefore);\r
332                     }\r
333 #endif\r
334                     if (nIndex >= 0) {\r
335                         UpdateCaretRect(nIndex, bBefore);\r
336                     }\r
337                 }\r
338             }\r
339             break;\r
340         case MC_Up: {\r
341                 if (bVertical) {\r
342                     FX_BOOL bBefore = TRUE;\r
343                     FX_INT32 nIndex = MoveBackward(bBefore);\r
344 #ifdef FDE_USEFORMATBLOCK\r
345                     if (m_BlockArray.GetSize()) {\r
346                         nIndex = NormalizeCaretPos(nIndex, FDE_FORMAT_CARET_BACKWARD, bBefore);\r
347                     }\r
348 #endif\r
349                     if (nIndex >= 0) {\r
350                         UpdateCaretRect(nIndex, bBefore);\r
351                     }\r
352                 } else {\r
353                     CFX_PointF ptCaret;\r
354                     if (MoveUp(ptCaret)) {\r
355                         UpdateCaretIndex(ptCaret);\r
356                     }\r
357                 }\r
358             }\r
359             break;\r
360         case MC_Down: {\r
361                 if (bVertical) {\r
362                     FX_BOOL bBefore = TRUE;\r
363                     FX_INT32 nIndex = MoveForward(bBefore);\r
364 #ifdef FDE_USEFORMATBLOCK\r
365                     if (m_BlockArray.GetSize()) {\r
366                         nIndex = NormalizeCaretPos(nIndex, FDE_FORMAT_CARET_FORWARD, bBefore);\r
367                     }\r
368 #endif\r
369                     if (nIndex >= 0) {\r
370                         UpdateCaretRect(nIndex, bBefore);\r
371                     }\r
372                 } else {\r
373                     CFX_PointF ptCaret;\r
374                     if (MoveDown(ptCaret)) {\r
375                         UpdateCaretIndex(ptCaret);\r
376                     }\r
377                 }\r
378             }\r
379             break;\r
380         case MC_WordBackward:\r
381             break;\r
382         case MC_WordForward:\r
383             break;\r
384         case MC_LineStart:\r
385             MoveLineStart();\r
386             break;\r
387         case MC_LineEnd:\r
388             MoveLineEnd();\r
389             break;\r
390         case MC_ParagStart:\r
391             MoveParagStart();\r
392             break;\r
393         case MC_ParagEnd:\r
394             MoveParagEnd();\r
395             break;\r
396         case MC_PageDown:\r
397             break;\r
398         case MC_PageUp:\r
399             break;\r
400         case MC_Home:\r
401             MoveHome();\r
402             break;\r
403         case MC_End:\r
404             MoveEnd();\r
405             break;\r
406         default:\r
407             break;\r
408     }\r
409     if (bShift && m_nAnchorPos != -1 && (m_nAnchorPos != m_nCaret)) {\r
410         AddSelRange(FX_MIN(m_nAnchorPos, m_nCaret), FXSYS_abs(m_nAnchorPos - m_nCaret));\r
411         m_Param.pEventSink->On_SelChanged(this);\r
412     }\r
413     if (bSelChange) {\r
414         m_Param.pEventSink->On_SelChanged(this);\r
415     }\r
416     return m_nCaret;\r
417 }\r
418 void CFDE_TxtEdtEngine::Lock()\r
419 {\r
420     m_bLock = TRUE;\r
421 }\r
422 void CFDE_TxtEdtEngine::Unlock()\r
423 {\r
424     m_bLock = FALSE;\r
425 }\r
426 FX_BOOL CFDE_TxtEdtEngine::IsLocked() const\r
427 {\r
428     return m_bLock;\r
429 }\r
430 FX_INT32 CFDE_TxtEdtEngine::Insert(FX_INT32 nStart, FX_LPCWSTR lpText, FX_INT32 nLength)\r
431 {\r
432     if (IsLocked()) {\r
433         return FDE_TXTEDT_MODIFY_RET_F_Locked;\r
434     }\r
435 #ifdef FDE_USEFORMATBLOCK\r
436     FX_INT32 nBlockCount = m_BlockArray.GetSize();\r
437     if (nBlockCount) {\r
438         if (m_Param.dwMode & FDE_TEXTEDITMODE_FIELD_TAB && nLength == 1 && lpText[0] == L'\t') {\r
439             return Move2NextEditableField(nStart) ? FDE_TXTEDT_MODIFY_RET_T_Tab : \\r
440                    FDE_TXTEDT_MODIFY_RET_F_Tab;\r
441         }\r
442         FX_INT32 nSelRangeCount = CountSelRanges();\r
443         if (nSelRangeCount > 0) {\r
444             if (nSelRangeCount > 1) {\r
445                 return FDE_TXTEDT_MODIFY_RET_F_Boundary;\r
446             }\r
447             FX_INT32 nSelStart;\r
448             FX_INT32 nSelCount;\r
449             nSelCount = GetSelRange(0, nSelStart);\r
450             FX_INT32 nSelEnd = nSelStart + nSelCount;\r
451             FX_INT32 nBgn = 0;\r
452             FX_INT32 nEnd = 0;\r
453             CFDE_TxtEdtField * pField = NULL;\r
454             FX_BOOL bInField = GetFieldBoundary(nSelStart, nBgn, nEnd, pField);\r
455             if (nSelEnd > nEnd) {\r
456                 return FDE_TXTEDT_MODIFY_RET_F_Boundary;\r
457             }\r
458             if (bInField) {\r
459                 pField->Backup();\r
460                 FX_BOOL bBefore = FALSE;\r
461                 CFX_WideString wsDel;\r
462                 FX_INT32 nCaret;\r
463                 FX_INT32 nIndexInField = nSelStart - nBgn;\r
464                 FX_INT32 nRet = pField->Replace(nSelStart - nBgn, nSelCount, CFX_WideStringC(lpText, nLength), wsDel, nCaret, bBefore);\r
465                 switch(nRet) {\r
466                     case FDE_FORMAT_FIELD_INSERT_RET_F_FULL:\r
467                         pField->Restore();\r
468                         return FDE_TXTEDT_MODIFY_RET_F_Full;\r
469                     case FDE_FORMAT_FIELD_INSERT_RET_F_INVALIDATE:\r
470                         pField->Restore();\r
471                         return FDE_TXTEDT_MODIFY_RET_F_Invalidate;\r
472                     default:\r
473                         break;\r
474                 }\r
475                 CFX_WideString wsField;\r
476                 pField->GetFieldText(wsField);\r
477                 if (!m_Param.pEventSink->On_ValidateField(this, pField->GetBlockIndex(), pField->GetIndex(), wsField, 0)) {\r
478                     pField->Restore();\r
479                     return FDE_TXTEDT_MODIFY_RET_F_Invalidate;\r
480                 }\r
481                 CFX_WideString wsDisplay;\r
482                 pField->GetDisplayText(wsDisplay);\r
483                 if ((m_Param.dwMode & FDE_TEXTEDITMODE_LimitArea_Vert) || (m_Param.dwMode & FDE_TEXTEDITMODE_LimitArea_Horz)) {\r
484                     CFX_WideString wsText;\r
485                     GetPreReplaceText(wsText, nBgn, nEnd - nBgn + 1, FX_LPCWSTR(wsDisplay), wsDisplay.GetLength());\r
486                     if (!IsFitArea(wsText)) {\r
487                         pField->Restore();\r
488                         return FDE_TXTEDT_MODIFY_RET_F_Full;\r
489                     }\r
490                 }\r
491                 Replace(nBgn, nEnd - nBgn + 1, wsDisplay);\r
492                 FX_INT32 nNewCaret = nBgn + nCaret;\r
493                 if (!(m_Param.dwMode & FDE_TEXTEDITMODE_NoRedoUndo)) {\r
494                     IFDE_TxtEdtDoRecord * pRecord = FX_NEW CFDE_TxtEdtDoRecord_FieldReplace(this, \\r
495                                                     m_nCaret, nNewCaret, pField, nIndexInField, nBgn, wsDisplay.GetLength(), \\r
496                                                     wsDel, CFX_WideStringC(lpText, nLength), TRUE);\r
497                     CFX_ByteString bsDoRecord;\r
498                     pRecord->Serialize(bsDoRecord);\r
499                     m_Param.pEventSink->On_AddDoRecord(this, bsDoRecord);\r
500                     pRecord->Release();\r
501                 }\r
502                 SetCaretPos(nBgn + nCaret, bBefore);\r
503                 return FDE_TXTEDT_MODIFY_RET_S_Normal;\r
504             }\r
505         }\r
506         FX_INT32 nBgn = 0;\r
507         FX_INT32 nEnd = 0;\r
508         CFDE_TxtEdtField * pField = NULL;\r
509         FX_BOOL bInField = GetFieldBoundary(m_nCaret, nBgn, nEnd, pField);\r
510         FX_INT32        nCaretInField   = m_nCaret - nBgn;\r
511         FX_BOOL         bBefore                 = FALSE;\r
512         if (bInField) {\r
513             pField->Backup();\r
514             CFX_WideStringC  wsIns(lpText, nLength);\r
515             FX_INT32 nRet = pField->Insert(nCaretInField, wsIns, nCaretInField, bBefore);\r
516             FX_BOOL bFull = FALSE;\r
517             switch (nRet) {\r
518                 case FDE_FORMAT_FIELD_INSERT_RET_S_NORMAL:\r
519                     break;\r
520                 case FDE_FORMAT_FIELD_INSERT_RET_S_FULL:\r
521                     bFull = TRUE;\r
522                     break;\r
523                 case FDE_FORMAT_FIELD_INSERT_RET_F_FULL:\r
524                     return FDE_TXTEDT_MODIFY_RET_F_Full;\r
525                 case FDE_FORMAT_FIELD_INSERT_RET_F_INVALIDATE:\r
526                     return FDE_TXTEDT_MODIFY_RET_F_Invalidate;\r
527                 default:\r
528                     return FDE_TXTEDT_MODIFY_RET_F_Normal;\r
529             }\r
530             CFX_WideString wsField;\r
531             pField->GetFieldText(wsField);\r
532             if (!m_Param.pEventSink->On_ValidateField(this, pField->GetBlockIndex(), pField->GetIndex(), wsField, 0)) {\r
533                 pField->Restore();\r
534                 return FDE_TXTEDT_MODIFY_RET_F_Invalidate;\r
535             }\r
536             CFX_WideString wsDisplay;\r
537             pField->GetDisplayText(wsDisplay);\r
538             if ((m_Param.dwMode & FDE_TEXTEDITMODE_LimitArea_Vert) || (m_Param.dwMode & FDE_TEXTEDITMODE_LimitArea_Horz)) {\r
539                 CFX_WideString wsText;\r
540                 GetPreReplaceText(wsText, nBgn, nEnd - nBgn + 1, FX_LPCWSTR(wsDisplay), wsDisplay.GetLength());\r
541                 if (!IsFitArea(wsText)) {\r
542                     pField->Restore();\r
543                     return FDE_TXTEDT_MODIFY_RET_F_Full;\r
544                 }\r
545             }\r
546             Replace(nBgn, nEnd - nBgn + 1, wsDisplay);\r
547             if (!(m_Param.dwMode & FDE_TEXTEDITMODE_NoRedoUndo)) {\r
548                 IFDE_TxtEdtDoRecord * pRecord = FX_NEW CFDE_TxtEdtDoRecord_FieldInsert(this, \\r
549                                                 m_nCaret, pField, m_nCaret - nBgn, nBgn, \\r
550                                                 nEnd - nBgn + 1, wsDisplay.GetLength(), \\r
551                                                 CFX_WideStringC(lpText, nLength), FALSE);\r
552                 CFX_ByteString bsDoRecord;\r
553                 pRecord->Serialize(bsDoRecord);\r
554                 m_Param.pEventSink->On_AddDoRecord(this, bsDoRecord);\r
555                 pRecord->Release();\r
556             }\r
557             FX_INT32 nCaretPos = nBgn + nCaretInField;\r
558             if (m_Param.dwMode & FDE_TEXTEDITMODE_FIELD_AUTO && bFull && nCaretPos == nEnd) {\r
559                 if (Move2NextEditableField(nEnd, TRUE, FALSE)) {\r
560                     return TRUE;\r
561                 }\r
562             }\r
563             SetCaretPos(nCaretPos, bBefore);\r
564             return bFull ? FDE_TXTEDT_MODIFY_RET_S_Full : FDE_TXTEDT_MODIFY_RET_S_Normal;\r
565         }\r
566         FXSYS_assert(0);\r
567         return FDE_TXTEDT_MODIFY_RET_F_Normal;\r
568     }\r
569 #endif\r
570     CFX_WideString wsTemp;\r
571     FX_LPWSTR lpBuffer = wsTemp.GetBuffer(nLength);\r
572     FXSYS_memcpy(lpBuffer, lpText, nLength * sizeof(FX_WCHAR));\r
573     ReplaceParagEnd(lpBuffer, nLength, FALSE);\r
574     wsTemp.ReleaseBuffer(nLength);\r
575     FX_BOOL bPart = FALSE;\r
576     if (m_nLimit > 0) {\r
577         FX_INT32 nTotalLength   = GetTextBufLength();\r
578         FX_INT32 nDelLength             = 0;\r
579         FX_INT32 nCount = m_SelRangePtrArr.GetSize();\r
580         for (FX_INT32 i = 0; i < nCount; i ++) {\r
581             FDE_LPTXTEDTSELRANGE lpSelRange = m_SelRangePtrArr.GetAt(i);\r
582             nTotalLength -= lpSelRange->nCount;\r
583         }\r
584         FX_INT32 nExpectLength  = nTotalLength + nLength;\r
585         if (nTotalLength == m_nLimit) {\r
586             return FDE_TXTEDT_MODIFY_RET_F_Full;\r
587         }\r
588         if (nExpectLength > m_nLimit) {\r
589             nLength -= (nExpectLength - m_nLimit);\r
590             bPart = TRUE;\r
591         }\r
592     }\r
593     if ((m_Param.dwMode & FDE_TEXTEDITMODE_LimitArea_Vert) || (m_Param.dwMode & FDE_TEXTEDITMODE_LimitArea_Horz)) {\r
594         FX_INT32 nTemp = nLength;\r
595         if (m_Param.dwMode & FDE_TEXTEDITMODE_Password) {\r
596             CFX_WideString wsText;\r
597             while (nLength > 0) {\r
598                 GetPreInsertText(wsText, m_nCaret, lpBuffer, nLength);\r
599                 FX_INT32 nTotal = wsText.GetLength();\r
600                 FX_LPWSTR lpBuf = wsText.GetBuffer(nTotal);\r
601                 for (FX_INT32 i = 0; i < nTotal; i ++) {\r
602                     lpBuf[i] = m_wcAliasChar;\r
603                 }\r
604                 wsText.ReleaseBuffer(nTotal);\r
605                 if (IsFitArea(wsText)) {\r
606                     break;\r
607                 }\r
608                 nLength --;\r
609             }\r
610         } else {\r
611             CFX_WideString wsText;\r
612             while (nLength > 0) {\r
613                 GetPreInsertText(wsText, m_nCaret, lpBuffer, nLength);\r
614                 if (IsFitArea(wsText)) {\r
615                     break;\r
616                 }\r
617                 nLength --;\r
618             }\r
619         }\r
620         if (nLength == 0) {\r
621             return FDE_TXTEDT_MODIFY_RET_F_Full;\r
622         }\r
623         if (nLength < nTemp) {\r
624             bPart = TRUE;\r
625         }\r
626     }\r
627     if (m_Param.dwMode & FDE_TEXTEDITMODE_Validate) {\r
628         CFX_WideString wsText;\r
629         GetPreInsertText(wsText, m_nCaret, lpBuffer, nLength);\r
630         if (!m_Param.pEventSink->On_Validate(this, wsText)) {\r
631             return FDE_TXTEDT_MODIFY_RET_F_Invalidate;\r
632         }\r
633     }\r
634     if (IsSelect()) {\r
635         DeleteSelect();\r
636     }\r
637     if (!(m_Param.dwMode & FDE_TEXTEDITMODE_NoRedoUndo)) {\r
638         IFDE_TxtEdtDoRecord * pRecord = FX_NEW CFDE_TxtEdtDoRecord_Insert(this, m_nCaret, lpBuffer, nLength);\r
639         CFX_ByteString bsDoRecord;\r
640         pRecord->Serialize(bsDoRecord);\r
641         m_Param.pEventSink->On_AddDoRecord(this, bsDoRecord);\r
642         pRecord->Release();\r
643     }\r
644     GetText(m_ChangeInfo.wsPrevText, 0);\r
645     Inner_Insert(m_nCaret, lpBuffer, nLength);\r
646     m_ChangeInfo.nChangeType    = FDE_TXTEDT_TEXTCHANGE_TYPE_Insert;\r
647     m_ChangeInfo.wsInsert               = CFX_WideString(lpBuffer, nLength);\r
648     nStart =    m_nCaret;\r
649     nStart +=   nLength;\r
650     FX_WCHAR wChar = m_pTxtBuf->GetCharByIndex(nStart - 1);\r
651     FX_BOOL bBefore = TRUE;\r
652     if (wChar != L'\n' && wChar != L'\r') {\r
653         nStart --;\r
654         bBefore = FALSE;\r
655     }\r
656     SetCaretPos(nStart, bBefore);\r
657     m_Param.pEventSink->On_TextChanged(this, m_ChangeInfo);\r
658     return bPart ? FDE_TXTEDT_MODIFY_RET_S_Part : FDE_TXTEDT_MODIFY_RET_S_Normal;\r
659 }\r
660 FX_INT32 CFDE_TxtEdtEngine::Delete(FX_INT32 nStart, FX_BOOL bBackspace )\r
661 {\r
662     if (IsLocked()) {\r
663         return FDE_TXTEDT_MODIFY_RET_F_Locked;\r
664     }\r
665     if (IsSelect()) {\r
666         DeleteSelect();\r
667         return FDE_TXTEDT_MODIFY_RET_S_Normal;\r
668     }\r
669 #ifdef FDE_USEFORMATBLOCK\r
670     FX_INT32 nBlockCount = m_BlockArray.GetSize();\r
671     if (nBlockCount > 0) {\r
672         if (bBackspace) {\r
673             nStart --;\r
674         }\r
675         FX_INT32 nCount = 1;\r
676         FX_INT32 nBgn = 0;\r
677         FX_INT32 nEnd = 0;\r
678         CFDE_TxtEdtField * pField = NULL;\r
679         FX_BOOL bInField = GetFieldBoundary(nStart, nBgn, nEnd, pField);\r
680         FX_INT32        nCaretInField   = nStart - nBgn;\r
681         FX_BOOL         bBefore                 = FALSE;\r
682         if (bInField && !pField->IsFix()) {\r
683             pField->Backup();\r
684             CFX_WideString wsDel;\r
685             FX_INT32 nCaret = 0;\r
686             FX_INT32 nRet = pField->Delete(nCaretInField, nCount, wsDel, nCaret, bBefore);\r
687             nCaret += nBgn;\r
688             switch (nRet) {\r
689                 case FDE_FORMAT_FIELD_DELETE_RET_S:\r
690                     break;\r
691                 case FDE_FORMAT_FIELD_DELETE_RET_F_INVALIDATE:\r
692                     return FDE_TXTEDT_MODIFY_RET_F_Invalidate;\r
693                 case FDE_FORMAT_FIELD_DELETE_RET_F_BOUNDARY:\r
694                     return FDE_TXTEDT_MODIFY_RET_F_Boundary;\r
695                 default:\r
696                     FXSYS_assert(0);\r
697                     break;\r
698             }\r
699             CFX_WideString wsField;\r
700             pField->GetFieldText(wsField);\r
701             if (!m_Param.pEventSink->On_ValidateField(this, pField->GetBlockIndex(), pField->GetIndex(), wsField, 0)) {\r
702                 pField->Restore();\r
703                 return FDE_TXTEDT_MODIFY_RET_F_Invalidate;\r
704             }\r
705             CFX_WideString wsDisplay;\r
706             pField->GetDisplayText(wsDisplay);\r
707             Replace(nBgn, nEnd - nBgn + 1, wsDisplay);\r
708             if (!(m_Param.dwMode & FDE_TEXTEDITMODE_NoRedoUndo)) {\r
709                 IFDE_TxtEdtDoRecord * pRecord = FX_NEW CFDE_TxtEdtDoRecord_FieldDelete(this, nStart, pField, nCaretInField,\r
710                                                 nBgn, nEnd - nBgn + 1, wsDisplay.GetLength(), wsDel, FALSE);\r
711                 CFX_ByteString bsDoRecord;\r
712                 pRecord->Serialize(bsDoRecord);\r
713                 m_Param.pEventSink->On_AddDoRecord(this, bsDoRecord);\r
714                 pRecord->Release();\r
715             }\r
716             SetCaretPos(nStart, bBefore);\r
717             return FDE_TXTEDT_MODIFY_RET_S_Normal;\r
718         }\r
719         return FDE_TXTEDT_MODIFY_RET_F_Boundary;\r
720     }\r
721 #endif\r
722     FX_INT32 nCount = 1;\r
723     if (bBackspace) {\r
724         if (nStart == 0) {\r
725             return FDE_TXTEDT_MODIFY_RET_F_Boundary;\r
726         }\r
727         if (nStart > 2 && m_pTxtBuf->GetCharByIndex(nStart - 1) == L'\n' && \\r
728                 m_pTxtBuf->GetCharByIndex(nStart - 2) == L'\r') {\r
729             nStart --;\r
730             nCount ++;\r
731         }\r
732         nStart --;\r
733     } else {\r
734         if (nStart == GetTextBufLength()) {\r
735             return FDE_TXTEDT_MODIFY_RET_F_Full;\r
736         }\r
737         if ((nStart + 1 < GetTextBufLength()) && (m_pTxtBuf->GetCharByIndex(nStart) == L'\r') && \\r
738                 (m_pTxtBuf->GetCharByIndex(nStart + 1) == L'\n')) {\r
739             nCount ++;\r
740         }\r
741     }\r
742     if (m_Param.dwMode & FDE_TEXTEDITMODE_Validate) {\r
743         CFX_WideString wsText;\r
744         GetPreDeleteText(wsText, nStart, nCount);\r
745         if (!m_Param.pEventSink->On_Validate(this, wsText)) {\r
746             return FDE_TXTEDT_MODIFY_RET_F_Invalidate;\r
747         }\r
748     }\r
749     if (!(m_Param.dwMode & FDE_TEXTEDITMODE_NoRedoUndo)) {\r
750         CFX_WideString wsRange;\r
751         m_pTxtBuf->GetRange(wsRange, nStart, nCount);\r
752         IFDE_TxtEdtDoRecord * pRecord = FX_NEW CFDE_TxtEdtDoRecord_DeleteRange(this, nStart, m_nCaret, wsRange);\r
753         CFX_ByteString bsDoRecord;\r
754         pRecord->Serialize(bsDoRecord);\r
755         m_Param.pEventSink->On_AddDoRecord(this, bsDoRecord);\r
756         pRecord->Release();\r
757     }\r
758     m_ChangeInfo.nChangeType    = FDE_TXTEDT_TEXTCHANGE_TYPE_Delete;\r
759     GetText(m_ChangeInfo.wsDelete, nStart, nCount);\r
760     Inner_DeleteRange(nStart, nCount);\r
761     SetCaretPos(nStart + ((!bBackspace && nStart > 0) ? -1 : 0), (bBackspace || nStart == 0));\r
762     m_Param.pEventSink->On_TextChanged(this, m_ChangeInfo);\r
763     return FDE_TXTEDT_MODIFY_RET_S_Normal;\r
764 }\r
765 FX_INT32 CFDE_TxtEdtEngine::DeleteRange(FX_INT32 nStart, FX_INT32 nCount )\r
766 {\r
767     if (IsLocked()) {\r
768         return FDE_TXTEDT_MODIFY_RET_F_Locked;\r
769     }\r
770     if (nCount == -1) {\r
771         nCount = GetTextBufLength();\r
772     }\r
773     if (nCount == 0) {\r
774         return FDE_TXTEDT_MODIFY_RET_S_Normal;\r
775     }\r
776     if (m_Param.dwMode & FDE_TEXTEDITMODE_Validate) {\r
777         CFX_WideString wsText;\r
778         GetPreDeleteText(wsText, nStart, nCount);\r
779         if (!m_Param.pEventSink->On_Validate(this, wsText)) {\r
780             return FDE_TXTEDT_MODIFY_RET_F_Invalidate;\r
781         }\r
782     }\r
783     DeleteRange_DoRecord(nStart, nCount);\r
784     m_Param.pEventSink->On_TextChanged(this, m_ChangeInfo);\r
785     SetCaretPos(nStart, TRUE);\r
786     return FDE_TXTEDT_MODIFY_RET_S_Normal;\r
787 }\r
788 FX_INT32 CFDE_TxtEdtEngine::Replace(FX_INT32 nStart, FX_INT32 nLength, const CFX_WideString &wsReplace)\r
789 {\r
790     if (IsLocked()) {\r
791         return FDE_TXTEDT_MODIFY_RET_F_Locked;\r
792     }\r
793     if (nStart < 0 || (nStart + nLength > GetTextBufLength())) {\r
794         return FDE_TXTEDT_MODIFY_RET_F_Boundary;\r
795     }\r
796     if (m_Param.dwMode & FDE_TEXTEDITMODE_Validate) {\r
797         CFX_WideString wsText;\r
798         GetPreReplaceText(wsText, nStart, nLength, FX_LPCWSTR(wsReplace), wsReplace.GetLength());\r
799         if (!m_Param.pEventSink->On_Validate(this, wsText)) {\r
800             return FDE_TXTEDT_MODIFY_RET_F_Invalidate;\r
801         }\r
802     }\r
803     if (IsSelect()) {\r
804         ClearSelection();\r
805     }\r
806     m_ChangeInfo.nChangeType    = FDE_TXTEDT_TEXTCHANGE_TYPE_Replace;\r
807     GetText(m_ChangeInfo.wsDelete, nStart, nLength);\r
808     if (nLength > 0) {\r
809         Inner_DeleteRange(nStart, nLength);\r
810     }\r
811     FX_INT32 nTextLength = wsReplace.GetLength();\r
812     if (nTextLength > 0) {\r
813         Inner_Insert(nStart, FX_LPCWSTR(wsReplace), nTextLength);\r
814     }\r
815     m_ChangeInfo.wsInsert = CFX_WideString(FX_LPCWSTR(wsReplace), nTextLength);\r
816     nStart +=   nTextLength;\r
817     FX_WCHAR wChar = m_pTxtBuf->GetCharByIndex(nStart - 1);\r
818     FX_BOOL bBefore = TRUE;\r
819     if (wChar != L'\n' && wChar != L'\r') {\r
820         nStart --;\r
821         bBefore = FALSE;\r
822     }\r
823     SetCaretPos(nStart, bBefore);\r
824     m_Param.pEventSink->On_PageUnload(this, m_nCaretPage, 0);\r
825     m_Param.pEventSink->On_PageLoad(this, m_nCaretPage, 0);\r
826     m_Param.pEventSink->On_TextChanged(this, m_ChangeInfo);\r
827     return FDE_TXTEDT_MODIFY_RET_S_Normal;\r
828 }\r
829 void CFDE_TxtEdtEngine::SetLimit(FX_INT32 nLimit)\r
830 {\r
831     m_nLimit = nLimit;\r
832 }\r
833 void CFDE_TxtEdtEngine::SetAliasChar(FX_WCHAR wcAlias)\r
834 {\r
835     m_wcAliasChar = wcAlias;\r
836 }\r
837 void CFDE_TxtEdtEngine::SetFormatBlock(FX_INT32 nIndex, const CFX_WideString &wsBlockFormat)\r
838 {\r
839 #ifdef FDE_USEFORMATBLOCK\r
840     if (m_nFixLength == -1) {\r
841         m_nFixLength = GetTextLength();\r
842         FXSYS_assert(m_wsFixText.IsEmpty());\r
843         GetText(m_wsFixText, 0, -1);\r
844     }\r
845     FX_BOOL             bInBlock        = FALSE;\r
846     FX_INT32    nCharIndex      = 0;\r
847     FX_INT32    nBlockIndex     = 0;\r
848     FX_INT32    nBlockPos       = -1;\r
849     FX_WCHAR    wc;\r
850     CFDE_TxtEdtBufIter * pIter = FX_NEW CFDE_TxtEdtBufIter((CFDE_TxtEdtBuf*)m_pTxtBuf, FALSE);\r
851     pIter->SetAt(0);\r
852     do {\r
853         wc = pIter->GetChar();\r
854         if (bInBlock) {\r
855             if (wc == FDE_TXTEDT_FORMATBLOCK_END) {\r
856                 nBlockIndex ++;\r
857                 bInBlock = FALSE;\r
858             }\r
859         } else {\r
860             if (wc == FDE_TXTEDT_FORMATBLOCK_BGN) {\r
861                 bInBlock = TRUE;\r
862             } else {\r
863                 if (nCharIndex ++ == nIndex) {\r
864                     nBlockPos = pIter->GetAt();\r
865                     break;\r
866                 }\r
867             }\r
868         }\r
869     } while (pIter->Next());\r
870     pIter->Release();\r
871     if (nBlockPos == -1) {\r
872         nBlockPos = GetTextBufLength();\r
873     }\r
874     CFDE_TxtEdtBlock * pEditBlock = FX_NEW CFDE_TxtEdtBlock(this, wsBlockFormat, nIndex);\r
875     m_BlockArray.InsertAt(m_BlockArray.GetSize(), pEditBlock);\r
876     CFX_WideString wsDisplay;\r
877     pEditBlock->GetDisplayText(wsDisplay);\r
878     m_nCaret = nBlockPos;\r
879     if (wsDisplay.GetLength() > 0) {\r
880         RawInsert(nBlockPos, FX_LPCWSTR(wsDisplay), wsDisplay.GetLength());\r
881     }\r
882 #endif\r
883 }\r
884 FX_INT32 CFDE_TxtEdtEngine::CountEditBlocks() const\r
885 {\r
886 #ifdef FDE_USEFORMATBLOCK\r
887     return m_BlockArray.GetSize();\r
888 #else\r
889     return 0;\r
890 #endif\r
891 }\r
892 void CFDE_TxtEdtEngine::GetEditBlockText(FX_INT32 nIndex, CFX_WideString &wsBlockText) const\r
893 {\r
894 #ifdef FDE_USEFORMATBLOCK\r
895     CFDE_TxtEdtBlock * pBlock = m_BlockArray[nIndex];\r
896     pBlock->GetBlockText(wsBlockText);\r
897 #endif\r
898 }\r
899 FX_INT32 CFDE_TxtEdtEngine::CountEditFields(FX_INT32 nBlockIndex) const\r
900 {\r
901 #ifdef FDE_USEFORMATBLOCK\r
902     CFDE_TxtEdtBlock * pBlock = m_BlockArray[nBlockIndex];\r
903     return pBlock->CountField();\r
904 #else\r
905     return 0;\r
906 #endif\r
907 }\r
908 void CFDE_TxtEdtEngine::GetEditFieldText(FX_INT32 nBlockIndex, FX_INT32 nFieldIndex, CFX_WideString &wsFieldText) const\r
909 {\r
910 #ifdef FDE_USEFORMATBLOCK\r
911     CFDE_TxtEdtBlock * pBlock = m_BlockArray[nBlockIndex];\r
912     pBlock->GetFieldText(nFieldIndex, wsFieldText);\r
913 #endif\r
914 }\r
915 void CFDE_TxtEdtEngine::StartEdit()\r
916 {\r
917 #ifdef FDE_USEFORMATBLOCK\r
918 #endif\r
919 }\r
920 void CFDE_TxtEdtEngine::EndEdit()\r
921 {\r
922 #ifdef FDE_USEFORMATBLOCK\r
923 #endif\r
924 }\r
925 void CFDE_TxtEdtEngine::RemoveSelRange(FX_INT32 nStart, FX_INT32 nCount )\r
926 {\r
927     FDE_LPTXTEDTSELRANGE lpTemp = NULL;\r
928     FX_INT32 nRangeCount = m_SelRangePtrArr.GetSize();\r
929     FX_INT32 i = 0;\r
930     for (i = 0; i < nRangeCount; i ++) {\r
931         lpTemp = m_SelRangePtrArr[i];\r
932         if (lpTemp->nStart == nStart && lpTemp->nCount == nCount) {\r
933             delete lpTemp;\r
934             m_SelRangePtrArr.RemoveAt(i);\r
935             return;\r
936         }\r
937     }\r
938     return;\r
939 }\r
940 void CFDE_TxtEdtEngine::AddSelRange(FX_INT32 nStart, FX_INT32 nCount )\r
941 {\r
942     if (nCount == -1) {\r
943         nCount = GetTextLength() - nStart;\r
944     }\r
945     FX_INT32 nSize      = m_SelRangePtrArr.GetSize();\r
946     if (nSize <= 0) {\r
947         FDE_LPTXTEDTSELRANGE lpSelRange = FX_NEW FDE_TXTEDTSELRANGE;\r
948         lpSelRange->nStart      = nStart;\r
949         lpSelRange->nCount      = nCount;\r
950         m_SelRangePtrArr.Add(lpSelRange);\r
951         m_Param.pEventSink->On_SelChanged(this);\r
952         return;\r
953     }\r
954     FDE_LPTXTEDTSELRANGE lpTemp = NULL;\r
955     lpTemp = m_SelRangePtrArr[nSize - 1];\r
956     if (nStart >= lpTemp->nStart + lpTemp->nCount) {\r
957         FDE_LPTXTEDTSELRANGE lpSelRange = FX_NEW FDE_TXTEDTSELRANGE;\r
958         lpSelRange->nStart      = nStart;\r
959         lpSelRange->nCount      = nCount;\r
960         m_SelRangePtrArr.Add(lpSelRange);\r
961         m_Param.pEventSink->On_SelChanged(this);\r
962         return;\r
963     }\r
964     FX_INT32    nEnd            = nStart + nCount - 1;\r
965     FX_BOOL             bBegin          = FALSE;\r
966     FX_INT32    nRangeBgn       = 0;\r
967     FX_INT32    nRangeCnt       = 0;\r
968     for (FX_INT32 i = 0; i < nSize; i ++) {\r
969         lpTemp          = m_SelRangePtrArr[i];\r
970         FX_INT32 nTempBgn       = lpTemp->nStart;\r
971         FX_INT32 nTempEnd       = nTempBgn + lpTemp->nCount - 1;\r
972         if (bBegin) {\r
973             if (nEnd < nTempBgn) {\r
974                 break;\r
975             } else if (nStart >= nTempBgn && nStart <= nTempEnd) {\r
976                 nRangeCnt ++;\r
977                 break;\r
978             }\r
979             nRangeCnt ++;\r
980         } else {\r
981             if (nStart <= nTempEnd) {\r
982                 nRangeBgn = i;\r
983                 if (nEnd < nTempBgn) {\r
984                     break;\r
985                 }\r
986                 nRangeCnt = 1;\r
987                 bBegin = TRUE;\r
988             }\r
989         }\r
990     }\r
991     if (nRangeCnt == 0) {\r
992         FDE_LPTXTEDTSELRANGE lpSelRange = FX_NEW FDE_TXTEDTSELRANGE;\r
993         lpSelRange->nStart      = nStart;\r
994         lpSelRange->nCount      = nCount;\r
995         m_SelRangePtrArr.InsertAt(nRangeBgn, lpSelRange);\r
996     } else {\r
997         lpTemp = m_SelRangePtrArr[nRangeBgn];\r
998         lpTemp->nStart = nStart;\r
999         lpTemp->nCount = nCount;\r
1000         nRangeCnt --;\r
1001         nRangeBgn ++;\r
1002         while (nRangeCnt--) {\r
1003             delete m_SelRangePtrArr[nRangeBgn];\r
1004             m_SelRangePtrArr.RemoveAt(nRangeBgn);\r
1005         }\r
1006     }\r
1007     m_Param.pEventSink->On_SelChanged(this);\r
1008     return;\r
1009 }\r
1010 FX_INT32 CFDE_TxtEdtEngine::CountSelRanges()\r
1011 {\r
1012     return m_SelRangePtrArr.GetSize();\r
1013 }\r
1014 FX_INT32 CFDE_TxtEdtEngine::GetSelRange(FX_INT32 nIndex, FX_INT32 &nStart)\r
1015 {\r
1016     nStart = m_SelRangePtrArr[nIndex]->nStart;\r
1017     return m_SelRangePtrArr[nIndex]->nCount;\r
1018 }\r
1019 void CFDE_TxtEdtEngine::ClearSelection()\r
1020 {\r
1021     FX_INT32 nCount = m_SelRangePtrArr.GetSize();\r
1022     FDE_LPTXTEDTSELRANGE lpRange = NULL;\r
1023     FX_INT32 i = 0;\r
1024     for (i = 0; i < nCount; i ++) {\r
1025         lpRange = m_SelRangePtrArr[i];\r
1026         if (lpRange != NULL) {\r
1027             delete lpRange;\r
1028             lpRange = NULL;\r
1029         }\r
1030     }\r
1031     m_SelRangePtrArr.RemoveAll();\r
1032     if (nCount && m_Param.pEventSink) {\r
1033         m_Param.pEventSink->On_SelChanged(this);\r
1034     }\r
1035 }\r
1036 FX_BOOL CFDE_TxtEdtEngine::Redo(FX_BSTR bsRedo)\r
1037 {\r
1038     if (IsLocked()) {\r
1039         return FALSE;\r
1040     }\r
1041     if (m_Param.dwMode & FDE_TEXTEDITMODE_NoRedoUndo) {\r
1042         return FALSE;\r
1043     }\r
1044     IFDE_TxtEdtDoRecord * pDoRecord = IFDE_TxtEdtDoRecord::Create(bsRedo);\r
1045     FXSYS_assert(pDoRecord);\r
1046     if (pDoRecord == NULL) {\r
1047         return FALSE;\r
1048     }\r
1049     FX_BOOL bOK = pDoRecord->Redo();\r
1050     pDoRecord->Release();\r
1051     return bOK;\r
1052 }\r
1053 FX_BOOL CFDE_TxtEdtEngine::Undo(FX_BSTR bsUndo)\r
1054 {\r
1055     if (IsLocked()) {\r
1056         return FALSE;\r
1057     }\r
1058     if (m_Param.dwMode & FDE_TEXTEDITMODE_NoRedoUndo) {\r
1059         return FALSE;\r
1060     }\r
1061     IFDE_TxtEdtDoRecord * pDoRecord = IFDE_TxtEdtDoRecord::Create(bsUndo);\r
1062     FXSYS_assert(pDoRecord);\r
1063     if (pDoRecord == NULL) {\r
1064         return FALSE;\r
1065     }\r
1066     FX_BOOL bOK = pDoRecord->Undo();\r
1067     pDoRecord->Release();\r
1068     return bOK;\r
1069 }\r
1070 FX_INT32 CFDE_TxtEdtEngine::StartLayout()\r
1071 {\r
1072     Lock();\r
1073     RemoveAllPages();\r
1074     m_nLayoutPos = 0;\r
1075     m_nLineCount = 0;\r
1076     return 0;\r
1077 }\r
1078 FX_INT32 CFDE_TxtEdtEngine::DoLayout(IFX_Pause * pPause)\r
1079 {\r
1080     FX_INT32 nCount = m_ParagPtrArray.GetSize();\r
1081     CFDE_TxtEdtParag * pParag = NULL;\r
1082     FX_INT32 nLineCount = 0;\r
1083     for (; m_nLayoutPos < nCount; m_nLayoutPos ++) {\r
1084         pParag = m_ParagPtrArray[m_nLayoutPos];\r
1085         pParag->CalcLines();\r
1086         nLineCount += pParag->m_nLineCount;\r
1087         if ((pPause != NULL) && (nLineCount > m_nPageLineCount) && pPause->NeedToPauseNow()) {\r
1088             m_nLineCount += nLineCount;\r
1089             return (++m_nLayoutPos  * 100) / nCount;\r
1090         }\r
1091     }\r
1092     m_nLineCount += nLineCount;\r
1093     return 100;\r
1094 }\r
1095 void CFDE_TxtEdtEngine::EndLayout()\r
1096 {\r
1097     UpdatePages();\r
1098     FX_INT32 nLength = GetTextLength();\r
1099     if (m_nCaret > nLength) {\r
1100         m_nCaret = nLength;\r
1101     }\r
1102     FX_INT32 nIndex = m_nCaret;\r
1103     if (!m_bBefore) {\r
1104         nIndex --;\r
1105     }\r
1106     m_rtCaret.Set(0, 0, 1, m_Param.fFontSize);\r
1107     Unlock();\r
1108 }\r
1109 FX_BOOL CFDE_TxtEdtEngine::Optimize(IFX_Pause * pPause )\r
1110 {\r
1111     return m_pTxtBuf->Optimize(pPause);\r
1112 }\r
1113 IFDE_TxtEdtBuf * CFDE_TxtEdtEngine::GetTextBuf() const\r
1114 {\r
1115     return (IFDE_TxtEdtBuf*)m_pTxtBuf;\r
1116 }\r
1117 FX_INT32 CFDE_TxtEdtEngine::GetTextBufLength() const\r
1118 {\r
1119     return m_pTxtBuf->GetTextLength() - 1;\r
1120 }\r
1121 IFX_TxtBreak * CFDE_TxtEdtEngine::GetTextBreak() const\r
1122 {\r
1123     return m_pTextBreak;\r
1124 }\r
1125 FX_INT32 CFDE_TxtEdtEngine::GetLineCount() const\r
1126 {\r
1127     return m_nLineCount;\r
1128 }\r
1129 FX_INT32 CFDE_TxtEdtEngine::GetPageLineCount() const\r
1130 {\r
1131     return m_nPageLineCount;\r
1132 }\r
1133 FX_INT32 CFDE_TxtEdtEngine::CountParags() const\r
1134 {\r
1135     return m_ParagPtrArray.GetSize();\r
1136 }\r
1137 IFDE_TxtEdtParag* CFDE_TxtEdtEngine::GetParag(FX_INT32 nParagIndex) const\r
1138 {\r
1139     return m_ParagPtrArray[nParagIndex];\r
1140 }\r
1141 IFX_CharIter* CFDE_TxtEdtEngine::CreateCharIter()\r
1142 {\r
1143     if (!m_pTxtBuf) {\r
1144         return NULL;\r
1145     }\r
1146     return FX_NEW CFDE_TxtEdtBufIter((CFDE_TxtEdtBuf*)m_pTxtBuf);\r
1147 }\r
1148 FX_INT32 CFDE_TxtEdtEngine::Line2Parag(FX_INT32 nStartParag, FX_INT32 nStartLineofParag, \\r
1149                                        FX_INT32 nLineIndex, FX_INT32 &nStartLine) const\r
1150 {\r
1151     FX_INT32 nLineTotal = nStartLineofParag;\r
1152     FX_INT32 nCount = m_ParagPtrArray.GetSize();\r
1153     CFDE_TxtEdtParag * pParag = NULL;\r
1154     FX_INT32 i = nStartParag;\r
1155     for (; i < nCount; i ++) {\r
1156         pParag = m_ParagPtrArray[i];\r
1157         nLineTotal += pParag->m_nLineCount;\r
1158         if (nLineTotal > nLineIndex) {\r
1159             break;\r
1160         }\r
1161     }\r
1162     nStartLine = nLineTotal - pParag->m_nLineCount;\r
1163     return i;\r
1164 }\r
1165 void CFDE_TxtEdtEngine::GetPreDeleteText(CFX_WideString &wsText, FX_INT32 nIndex, FX_INT32 nLength)\r
1166 {\r
1167     GetText(wsText, 0, GetTextBufLength());\r
1168     wsText.Delete(nIndex, nLength);\r
1169 }\r
1170 void CFDE_TxtEdtEngine::GetPreInsertText(CFX_WideString &wsText, FX_INT32 nIndex, FX_LPCWSTR lpText, FX_INT32 nLength)\r
1171 {\r
1172     GetText(wsText, 0, GetTextBufLength());\r
1173     FX_INT32 nSelIndex  = 0;\r
1174     FX_INT32 nSelLength = 0;\r
1175     FX_INT32 nSelCount  = CountSelRanges();\r
1176     while (nSelCount --) {\r
1177         nSelLength = GetSelRange(nSelCount, nSelIndex);\r
1178         wsText.Delete(nSelIndex, nSelLength);\r
1179         nIndex = nSelIndex;\r
1180     }\r
1181     CFX_WideString wsTemp;\r
1182     FX_INT32    nOldLength = wsText.GetLength();\r
1183     FX_LPCWSTR  pOldBuffer = FX_LPCWSTR(wsText);\r
1184     FX_LPWSTR lpBuffer = wsTemp.GetBuffer(nOldLength + nLength);\r
1185     FXSYS_memcpy(lpBuffer, pOldBuffer, (nIndex) * sizeof(FX_WCHAR));\r
1186     FXSYS_memcpy(lpBuffer + nIndex, lpText, nLength * sizeof(FX_WCHAR));\r
1187     FXSYS_memcpy(lpBuffer + nIndex + nLength, pOldBuffer + nIndex, (nOldLength - nIndex) * sizeof(FX_WCHAR));\r
1188     wsTemp.ReleaseBuffer(nOldLength + nLength);\r
1189     wsText = wsTemp;\r
1190 }\r
1191 void CFDE_TxtEdtEngine::GetPreReplaceText(CFX_WideString &wsText, FX_INT32 nIndex, FX_INT32 nOriginLength, FX_LPCWSTR lpText, FX_INT32 nLength)\r
1192 {\r
1193     GetText(wsText, 0, GetTextBufLength());\r
1194     FX_INT32 nSelIndex  = 0;\r
1195     FX_INT32 nSelLength = 0;\r
1196     FX_INT32 nSelCount  = CountSelRanges();\r
1197     while (nSelCount --) {\r
1198         nSelLength = GetSelRange(nSelCount, nSelIndex);\r
1199         wsText.Delete(nSelIndex, nSelLength);\r
1200     }\r
1201     wsText.Delete(nIndex, nOriginLength);\r
1202     FX_INT32 i = 0;\r
1203     for (i = 0; i < nLength; i ++) {\r
1204         wsText.Insert(nIndex ++, lpText[i]);\r
1205     }\r
1206 }\r
1207 void CFDE_TxtEdtEngine::Inner_Insert(FX_INT32 nStart, FX_LPCWSTR lpText, FX_INT32 nLength)\r
1208 {\r
1209     FXSYS_assert(nLength > 0);\r
1210     FDE_TXTEDTPARAGPOS ParagPos;\r
1211     TextPos2ParagPos(nStart, ParagPos);\r
1212     m_Param.pEventSink->On_PageUnload(this, m_nCaretPage, 0);\r
1213     FX_INT32 nParagCount = m_ParagPtrArray.GetSize();\r
1214     FX_INT32 i = 0;\r
1215     for (i = ParagPos.nParagIndex + 1; i < nParagCount; i ++) {\r
1216         m_ParagPtrArray[i]->m_nCharStart += nLength;\r
1217     }\r
1218     CFDE_TxtEdtParag * pParag   = m_ParagPtrArray[ParagPos.nParagIndex];\r
1219     FX_INT32 nReserveLineCount  = pParag->m_nLineCount;\r
1220     FX_INT32 nReserveCharStart  = pParag->m_nCharStart;\r
1221     FX_INT32 nLeavePart                 = ParagPos.nCharIndex;\r
1222     FX_INT32 nCutPart                   = pParag->m_nCharCount - ParagPos.nCharIndex;\r
1223     FX_INT32 nTextStart                 = 0;\r
1224     FX_WCHAR wCurChar   = L' ';\r
1225     FX_LPCWSTR lpPos    = lpText;\r
1226     FX_BOOL bFirst              = TRUE;\r
1227     FX_INT32 nParagIndex = ParagPos.nParagIndex;\r
1228     for (i = 0; i < nLength; i ++, lpPos ++) {\r
1229         wCurChar = *lpPos;\r
1230         if (wCurChar == m_wLineEnd) {\r
1231             if (bFirst) {\r
1232                 pParag->m_nCharCount = nLeavePart + (i - nTextStart + 1);\r
1233                 pParag->m_nLineCount = -1;\r
1234                 nReserveCharStart += pParag->m_nCharCount;\r
1235                 bFirst = FALSE;\r
1236             } else {\r
1237                 pParag = FX_NEW CFDE_TxtEdtParag(this);\r
1238                 pParag->m_nLineCount = -1;\r
1239                 pParag->m_nCharCount = i - nTextStart + 1;\r
1240                 pParag->m_nCharStart = nReserveCharStart;\r
1241                 m_ParagPtrArray.InsertAt(++nParagIndex, pParag);\r
1242                 nReserveCharStart += pParag->m_nCharCount;\r
1243             }\r
1244             nTextStart = i + 1;\r
1245         }\r
1246     }\r
1247     if (bFirst) {\r
1248         pParag->m_nCharCount += nLength;\r
1249         pParag->m_nLineCount = -1;\r
1250         bFirst = FALSE;\r
1251     } else {\r
1252         pParag = FX_NEW CFDE_TxtEdtParag(this);\r
1253         pParag->m_nLineCount = -1;\r
1254         pParag->m_nCharCount = nLength - nTextStart + nCutPart;\r
1255         pParag->m_nCharStart = nReserveCharStart;\r
1256         m_ParagPtrArray.InsertAt(++nParagIndex, pParag);\r
1257     }\r
1258     m_pTxtBuf->Insert(nStart, lpText, nLength);\r
1259     FX_INT32 nTotalLineCount = 0;\r
1260     for (i = ParagPos.nParagIndex; i <= nParagIndex; i ++) {\r
1261         pParag = m_ParagPtrArray[i];\r
1262         pParag->CalcLines();\r
1263         nTotalLineCount += pParag->m_nLineCount;\r
1264     }\r
1265     m_nLineCount +=  nTotalLineCount - nReserveLineCount;\r
1266     m_Param.pEventSink->On_PageLoad(this, m_nCaretPage, 0);\r
1267     UpdatePages();\r
1268 }\r
1269 #ifdef FDE_USEFORMATBLOCK\r
1270 void CFDE_TxtEdtEngine::RawInsert(FX_INT32 nStart, FX_LPCWSTR lpText, FX_INT32 nLength)\r
1271 {\r
1272     FXSYS_assert(nLength > 0);\r
1273     FDE_TXTEDTPARAGPOS ParagPos;\r
1274     TextPos2ParagPos(nStart, ParagPos);\r
1275     FX_INT32 nParagCount = m_ParagPtrArray.GetSize();\r
1276     FX_INT32 i = 0;\r
1277     for (i = ParagPos.nParagIndex + 1; i < nParagCount; i ++) {\r
1278         m_ParagPtrArray[i]->m_nCharStart += nLength;\r
1279     }\r
1280     CFDE_TxtEdtParag * pParag   = m_ParagPtrArray[ParagPos.nParagIndex];\r
1281     FX_INT32 nReserveLineCount  = pParag->m_nLineCount;\r
1282     FX_INT32 nReserveCharStart  = pParag->m_nCharStart;\r
1283     FX_INT32 nLeavePart                 = ParagPos.nCharIndex;\r
1284     FX_INT32 nCutPart                   = pParag->m_nCharCount - ParagPos.nCharIndex;\r
1285     FX_INT32 nTextStart                 = 0;\r
1286     FX_WCHAR wCurChar   = L' ';\r
1287     FX_LPCWSTR lpPos    = lpText;\r
1288     FX_BOOL bFirst              = TRUE;\r
1289     FX_INT32 nParagIndex = ParagPos.nParagIndex;\r
1290     for (i = 0; i < nLength; i ++, lpPos ++) {\r
1291         wCurChar = *lpPos;\r
1292         if (wCurChar == m_wLineEnd) {\r
1293             if (bFirst) {\r
1294                 pParag->m_nCharCount = nLeavePart + (i - nTextStart + 1);\r
1295                 pParag->m_nLineCount = -1;\r
1296                 nReserveCharStart += pParag->m_nCharCount;\r
1297                 bFirst = FALSE;\r
1298             } else {\r
1299                 pParag = FX_NEW CFDE_TxtEdtParag(this);\r
1300                 pParag->m_nLineCount = -1;\r
1301                 pParag->m_nCharCount = i - nTextStart + 1;\r
1302                 pParag->m_nCharStart = nReserveCharStart;\r
1303                 m_ParagPtrArray.InsertAt(++nParagIndex, pParag);\r
1304                 nReserveCharStart += pParag->m_nCharCount;\r
1305             }\r
1306             nTextStart = i + 1;\r
1307         }\r
1308     }\r
1309     if (bFirst) {\r
1310         pParag->m_nCharCount += nLength;\r
1311         pParag->m_nLineCount = -1;\r
1312         bFirst = FALSE;\r
1313     } else {\r
1314         pParag = FX_NEW CFDE_TxtEdtParag(this);\r
1315         pParag->m_nLineCount = -1;\r
1316         pParag->m_nCharCount = nLength - nTextStart + nCutPart;\r
1317         pParag->m_nCharStart = nReserveCharStart;\r
1318         m_ParagPtrArray.InsertAt(++nParagIndex, pParag);\r
1319     }\r
1320     m_pTxtBuf->Insert(nStart, lpText, nLength);\r
1321 }\r
1322 #endif\r
1323 void CFDE_TxtEdtEngine::Inner_DeleteRange(FX_INT32 nStart, FX_INT32 nCount )\r
1324 {\r
1325     if (nCount == -1) {\r
1326         nCount = m_pTxtBuf->GetTextLength() - nStart;\r
1327     }\r
1328     FX_INT32 nEnd = nStart + nCount - 1;\r
1329     FXSYS_assert(nStart >= 0 && nEnd < m_pTxtBuf->GetTextLength());\r
1330     m_Param.pEventSink->On_PageUnload(this, m_nCaretPage, 0);\r
1331     FDE_TXTEDTPARAGPOS ParagPosBgn, ParagPosEnd;\r
1332     TextPos2ParagPos(nStart, ParagPosBgn);\r
1333     TextPos2ParagPos(nEnd, ParagPosEnd);\r
1334     CFDE_TxtEdtParag * pParag = m_ParagPtrArray[ParagPosEnd.nParagIndex];\r
1335     FX_BOOL bLastParag = FALSE;\r
1336     if (ParagPosEnd.nCharIndex == pParag->m_nCharCount - 1) {\r
1337         if (ParagPosEnd.nParagIndex < m_ParagPtrArray.GetSize() - 1) {\r
1338             ParagPosEnd.nParagIndex ++;\r
1339         } else {\r
1340             bLastParag = TRUE;\r
1341         }\r
1342     }\r
1343     FX_INT32 nTotalLineCount    = 0;\r
1344     FX_INT32 nTotalCharCount    = 0;\r
1345     FX_INT32 i = 0;\r
1346     for (i = ParagPosBgn.nParagIndex; i <= ParagPosEnd.nParagIndex; i ++) {\r
1347         CFDE_TxtEdtParag * pParag = m_ParagPtrArray[i];\r
1348         pParag->CalcLines();\r
1349         nTotalLineCount += pParag->m_nLineCount;\r
1350         nTotalCharCount += pParag->m_nCharCount;\r
1351     }\r
1352     m_pTxtBuf->Delete(nStart, nCount);\r
1353     CFDE_TxtEdtParag * pEndParag = m_ParagPtrArray[ParagPosEnd.nParagIndex];\r
1354     FX_INT32 nNextParagIndex = (ParagPosBgn.nCharIndex == 0 && bLastParag) ? ParagPosBgn.nParagIndex : \\r
1355                                (ParagPosBgn.nParagIndex + 1);\r
1356     for (i = nNextParagIndex; i <= ParagPosEnd.nParagIndex; i ++) {\r
1357         CFDE_TxtEdtParag * pParag = m_ParagPtrArray[nNextParagIndex];\r
1358         delete pParag;\r
1359         m_ParagPtrArray.RemoveAt(nNextParagIndex);\r
1360     }\r
1361     if (!(bLastParag && ParagPosBgn.nCharIndex == 0)) {\r
1362         pParag = m_ParagPtrArray[ParagPosBgn.nParagIndex];\r
1363         pParag->m_nCharCount = nTotalCharCount - nCount;\r
1364         pParag->CalcLines();\r
1365         nTotalLineCount -= pParag->m_nLineCount;\r
1366     }\r
1367     FX_INT32 nParagCount = m_ParagPtrArray.GetSize();\r
1368     for (i = nNextParagIndex; i < nParagCount; i ++) {\r
1369         m_ParagPtrArray[i]->m_nCharStart -= nCount;\r
1370     }\r
1371     m_nLineCount -= nTotalLineCount;\r
1372     UpdatePages();\r
1373     FX_INT32 nPageCount = CountPages();\r
1374     if (m_nCaretPage >= nPageCount) {\r
1375         m_nCaretPage = nPageCount - 1;\r
1376     }\r
1377     m_Param.pEventSink->On_PageLoad(this, m_nCaretPage, 0);\r
1378 }\r
1379 void CFDE_TxtEdtEngine::DeleteRange_DoRecord(FX_INT32 nStart, FX_INT32 nCount, FX_BOOL bSel )\r
1380 {\r
1381     FXSYS_assert(nStart >= 0);\r
1382     if (nCount == -1) {\r
1383         nCount = GetTextLength() - nStart;\r
1384     }\r
1385     FXSYS_assert((nStart + nCount) <= m_pTxtBuf->GetTextLength());\r
1386 #ifdef FDE_USEFORMATBLOCK\r
1387     FX_INT32 nBlockCount = m_BlockArray.GetSize();\r
1388     if (nBlockCount > 0) {\r
1389     }\r
1390 #endif\r
1391     if (!(m_Param.dwMode & FDE_TEXTEDITMODE_NoRedoUndo)) {\r
1392         CFX_WideString wsRange;\r
1393         m_pTxtBuf->GetRange(wsRange, nStart, nCount);\r
1394         IFDE_TxtEdtDoRecord * pRecord = FX_NEW CFDE_TxtEdtDoRecord_DeleteRange(this, nStart, m_nCaret, \\r
1395                                         wsRange, bSel);\r
1396         CFX_ByteString bsDoRecord;\r
1397         pRecord->Serialize(bsDoRecord);\r
1398         m_Param.pEventSink->On_AddDoRecord(this, bsDoRecord);\r
1399         pRecord->Release();\r
1400     }\r
1401     m_ChangeInfo.nChangeType    = FDE_TXTEDT_TEXTCHANGE_TYPE_Delete;\r
1402     GetText(m_ChangeInfo.wsDelete, nStart, nCount);\r
1403     Inner_DeleteRange(nStart, nCount);\r
1404 }\r
1405 void CFDE_TxtEdtEngine::ResetEngine()\r
1406 {\r
1407     RemoveAllPages();\r
1408     RemoveAllParags();\r
1409     ClearSelection();\r
1410     m_nCaret = 0;\r
1411     m_pTxtBuf->Clear(FALSE);\r
1412     m_nCaret = 0;\r
1413 }\r
1414 void CFDE_TxtEdtEngine::RebuildParagraphs()\r
1415 {\r
1416     RemoveAllParags();\r
1417     FX_WCHAR wChar                      = L' ';\r
1418     FX_WCHAR wCharPre           = L' ';\r
1419     FX_INT32 nParagStart        = 0;\r
1420     FX_INT32 nCount                     = m_pTxtBuf->GetTextLength();\r
1421     FX_INT32 nIndex                             = 0;\r
1422     CFDE_TxtEdtParag * pParag   = NULL;\r
1423     IFX_CharIter * pIter        = FX_NEW CFDE_TxtEdtBufIter((CFDE_TxtEdtBuf*)m_pTxtBuf);\r
1424     pIter->SetAt(0);\r
1425     do {\r
1426         wChar   = pIter->GetChar();\r
1427         nIndex  = pIter->GetAt();\r
1428         if (wChar == m_wLineEnd) {\r
1429             CFDE_TxtEdtParag * pParag = FX_NEW CFDE_TxtEdtParag(this);\r
1430             pParag->m_nCharStart = nParagStart;\r
1431             pParag->m_nCharCount = nIndex - nParagStart + 1;\r
1432             pParag->m_nLineCount = -1;\r
1433             m_ParagPtrArray.Add(pParag);\r
1434             nParagStart = nIndex + 1;\r
1435         }\r
1436     } while (pIter->Next());\r
1437     pIter->Release();\r
1438 }\r
1439 void CFDE_TxtEdtEngine::RemoveAllParags()\r
1440 {\r
1441     FX_INT32 nCount = m_ParagPtrArray.GetSize();\r
1442     FX_INT32 i = 0;\r
1443     for (i = 0; i < nCount; i ++) {\r
1444         CFDE_TxtEdtParag * pParag = m_ParagPtrArray[i];\r
1445         if (pParag) {\r
1446             delete pParag;\r
1447         }\r
1448     }\r
1449     m_ParagPtrArray.RemoveAll();\r
1450 }\r
1451 void CFDE_TxtEdtEngine::RemoveAllPages()\r
1452 {\r
1453     FX_INT32 nCount = m_PagePtrArray.GetSize();\r
1454     FX_INT32 i = 0;\r
1455     for (i = 0; i < nCount; i ++) {\r
1456         IFDE_TxtEdtPage * pPage = m_PagePtrArray[i];\r
1457         if (pPage) {\r
1458             pPage->Release();\r
1459         }\r
1460     }\r
1461     m_PagePtrArray.RemoveAll();\r
1462 }\r
1463 void CFDE_TxtEdtEngine::UpdateParags()\r
1464 {\r
1465     FX_INT32 nCount = m_ParagPtrArray.GetSize();\r
1466     if (nCount == 0) {\r
1467         return;\r
1468     }\r
1469     CFDE_TxtEdtParag * pParag = NULL;\r
1470     FX_INT32 nLineCount = 0;\r
1471     FX_INT32 i = 0;\r
1472     for (i = 0; i < nCount; i ++) {\r
1473         pParag = m_ParagPtrArray[i];\r
1474         if (pParag->m_nLineCount == -1) {\r
1475             pParag->CalcLines();\r
1476         }\r
1477         nLineCount += pParag->m_nLineCount;\r
1478     }\r
1479     m_nLineCount = nLineCount;\r
1480 }\r
1481 void CFDE_TxtEdtEngine::UpdatePages()\r
1482 {\r
1483     if (m_nLineCount == 0) {\r
1484         return;\r
1485     }\r
1486     FX_INT32 nPageCount = (m_nLineCount - 1) / (m_nPageLineCount) + 1;\r
1487     FX_INT32 nSize              = m_PagePtrArray.GetSize();\r
1488     if (nSize == nPageCount) {\r
1489         return;\r
1490     }\r
1491     if (nSize > nPageCount) {\r
1492         IFDE_TxtEdtPage * pPage = NULL;\r
1493         FX_INT32 i = 0;\r
1494         for (i = nSize - 1; i >= nPageCount; i --) {\r
1495             pPage = m_PagePtrArray[i];\r
1496             if (pPage) {\r
1497                 pPage->Release();\r
1498             }\r
1499             m_PagePtrArray.RemoveAt(i);\r
1500         }\r
1501         m_Param.pEventSink->On_PageCountChanged(this);\r
1502         return;\r
1503     }\r
1504     if (nSize < nPageCount) {\r
1505         IFDE_TxtEdtPage * pPage = NULL;\r
1506         FX_INT32 i = 0;\r
1507         for (i = nSize; i < nPageCount; i ++) {\r
1508             pPage = IFDE_TxtEdtPage::Create(this, i);\r
1509             m_PagePtrArray.Add(pPage);\r
1510         }\r
1511         m_Param.pEventSink->On_PageCountChanged(this);\r
1512         return;\r
1513     }\r
1514 }\r
1515 void CFDE_TxtEdtEngine::UpdateTxtBreak()\r
1516 {\r
1517     FX_DWORD dwStyle = m_pTextBreak->GetLayoutStyles();\r
1518     if (m_Param.dwMode & FDE_TEXTEDITMODE_MultiLines) {\r
1519         dwStyle &= ~FX_TXTLAYOUTSTYLE_SingleLine;\r
1520     } else {\r
1521         dwStyle |= FX_TXTLAYOUTSTYLE_SingleLine;\r
1522     }\r
1523     if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_DocVertical) {\r
1524         dwStyle |= FX_TXTLAYOUTSTYLE_VerticalLayout;\r
1525     } else {\r
1526         dwStyle &= ~FX_TXTLAYOUTSTYLE_VerticalLayout;\r
1527     }\r
1528     if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_LineReserve) {\r
1529         dwStyle |= FX_TXTLAYOUTSTYLE_ReverseLine;\r
1530     } else {\r
1531         dwStyle &= ~FX_TXTLAYOUTSTYLE_ReverseLine;\r
1532     }\r
1533     if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_RTL) {\r
1534         dwStyle |= FX_TXTLAYOUTSTYLE_RTLReadingOrder;\r
1535     } else {\r
1536         dwStyle &= ~FX_TXTLAYOUTSTYLE_RTLReadingOrder;\r
1537     }\r
1538     if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_CombText) {\r
1539         dwStyle |= FX_TXTLAYOUTSTYLE_CombText;\r
1540     } else {\r
1541         dwStyle &= ~FX_TXTLAYOUTSTYLE_CombText;\r
1542     }\r
1543     if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_CharVertial) {\r
1544         dwStyle |= FX_TXTLAYOUTSTYLE_VerticalChars;\r
1545     } else {\r
1546         dwStyle &= ~FX_TXTLAYOUTSTYLE_VerticalChars;\r
1547     }\r
1548     if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_ExpandTab) {\r
1549         dwStyle |= FX_TXTLAYOUTSTYLE_ExpandTab;\r
1550     } else {\r
1551         dwStyle &= ~ FX_TXTLAYOUTSTYLE_ExpandTab;\r
1552     }\r
1553     if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_ArabicContext) {\r
1554         dwStyle |= FX_TXTLAYOUTSTYLE_ArabicContext;\r
1555     } else {\r
1556         dwStyle &= ~FX_TXTLAYOUTSTYLE_ArabicContext;\r
1557     }\r
1558     if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_ArabicShapes) {\r
1559         dwStyle |= FX_TXTLAYOUTSTYLE_ArabicShapes;\r
1560     } else {\r
1561         dwStyle &= ~FX_TXTLAYOUTSTYLE_ArabicShapes;\r
1562     }\r
1563     m_pTextBreak->SetLayoutStyles(dwStyle);\r
1564     FX_DWORD dwAligment = 0;\r
1565     if (m_Param.dwAlignment & FDE_TEXTEDITALIGN_Justified) {\r
1566         dwAligment |= FX_TXTLINEALIGNMENT_Justified;\r
1567     } else if (m_Param.dwAlignment & FDE_TEXTEDITALIGN_Distributed) {\r
1568         dwAligment |= FX_TXTLINEALIGNMENT_Distributed;\r
1569     }\r
1570     if (m_Param.dwAlignment & FDE_TEXTEDITALIGN_Center) {\r
1571         dwAligment |= FX_TXTLINEALIGNMENT_Center;\r
1572     } else if(m_Param.dwAlignment & FDE_TEXTEDITALIGN_Right) {\r
1573         dwAligment |= FX_TXTLINEALIGNMENT_Right;\r
1574     }\r
1575     m_pTextBreak->SetAlignment(dwAligment);\r
1576     if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_DocVertical) {\r
1577         if (m_Param.dwMode & FDE_TEXTEDITMODE_AutoLineWrap) {\r
1578             m_pTextBreak->SetLineWidth(m_Param.fPlateHeight);\r
1579         } else {\r
1580             m_pTextBreak->SetLineWidth(FDE_PAGEWIDTH_MAX);\r
1581         }\r
1582     } else {\r
1583         if (m_Param.dwMode & FDE_TEXTEDITMODE_AutoLineWrap) {\r
1584             m_pTextBreak->SetLineWidth(m_Param.fPlateWidth);\r
1585         } else {\r
1586             m_pTextBreak->SetLineWidth(FDE_PAGEWIDTH_MAX);\r
1587         }\r
1588     }\r
1589     m_nPageLineCount = m_Param.nLineCount;\r
1590     if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_CombText) {\r
1591         FX_FLOAT fCombWidth = m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_DocVertical ?\r
1592                               m_Param.fPlateHeight : m_Param.fPlateWidth;\r
1593         if (m_nLimit > 0) {\r
1594             fCombWidth /= m_nLimit;\r
1595         }\r
1596         m_pTextBreak->SetCombWidth(fCombWidth);\r
1597     }\r
1598     m_pTextBreak->SetFont(m_Param.pFont);\r
1599     m_pTextBreak->SetFontSize(m_Param.fFontSize);\r
1600     m_pTextBreak->SetTabWidth(m_Param.fTabWidth, m_Param.bTabEquidistant);\r
1601     m_pTextBreak->SetDefaultChar(m_Param.wDefChar);\r
1602     m_pTextBreak->SetParagraphBreakChar(m_Param.wLineBreakChar);\r
1603     m_pTextBreak->SetCharRotation(m_Param.nCharRotation);\r
1604     m_pTextBreak->SetLineBreakTolerance(m_Param.fFontSize * 0.2f);\r
1605     m_pTextBreak->SetHorizontalScale(m_Param.nHorzScale);\r
1606     m_pTextBreak->SetCharSpace(m_Param.fCharSpace);\r
1607 }\r
1608 FX_BOOL CFDE_TxtEdtEngine::ReplaceParagEnd(FX_LPWSTR &lpText, FX_INT32 &nLength, FX_BOOL bPreIsCR )\r
1609 {\r
1610     for (FX_INT32 i = 0; i < nLength; i ++) {\r
1611         FX_WCHAR wc = lpText[i];\r
1612         switch(wc) {\r
1613             case L'\r': {\r
1614                     lpText[i]   = m_wLineEnd;\r
1615                     bPreIsCR    = TRUE;\r
1616                 }\r
1617                 break;\r
1618             case L'\n': {\r
1619                     if (bPreIsCR == TRUE) {\r
1620                         FX_INT32 nNext = i + 1;\r
1621                         if (nNext < nLength) {\r
1622                             FXSYS_memmove(lpText + i, lpText + nNext, (nLength - nNext) * sizeof(FX_WCHAR));\r
1623                         }\r
1624                         i --;\r
1625                         nLength --;\r
1626                         bPreIsCR = FALSE;\r
1627                         if (m_bAutoLineEnd) {\r
1628                             m_nFirstLineEnd = FDE_TXTEDIT_LINEEND_CRLF;\r
1629                             m_bAutoLineEnd      = FALSE;\r
1630                         }\r
1631                     } else {\r
1632                         lpText[i] = m_wLineEnd;\r
1633                         if (m_bAutoLineEnd) {\r
1634                             m_nFirstLineEnd = FDE_TXTEDIT_LINEEND_LF;\r
1635                             m_bAutoLineEnd      = FALSE;\r
1636                         }\r
1637                     }\r
1638                 }\r
1639                 break;\r
1640             default: {\r
1641                     if (bPreIsCR && m_bAutoLineEnd) {\r
1642                         m_nFirstLineEnd = FDE_TXTEDIT_LINEEND_CR;\r
1643                         m_bAutoLineEnd  = FALSE;\r
1644                     }\r
1645                     bPreIsCR = FALSE;\r
1646                 }\r
1647                 break;\r
1648         }\r
1649     }\r
1650     return bPreIsCR;\r
1651 }\r
1652 void CFDE_TxtEdtEngine::RecoverParagEnd(CFX_WideString &wsText)\r
1653 {\r
1654     FX_WCHAR wc = (m_nFirstLineEnd == FDE_TXTEDIT_LINEEND_CR) ? L'\n' : L'\r';\r
1655     if (m_nFirstLineEnd == FDE_TXTEDIT_LINEEND_CRLF) {\r
1656         CFX_ArrayTemplate<FX_INT32> PosArr;\r
1657         FX_INT32 nLength = wsText.GetLength();\r
1658         FX_INT32 i = 0;\r
1659         FX_LPWSTR lpPos = (FX_LPWSTR)(FX_LPCWSTR)wsText;\r
1660         for (i = 0; i < nLength; i ++, lpPos ++) {\r
1661             if (*lpPos == m_wLineEnd) {\r
1662                 *lpPos = wc;\r
1663                 PosArr.Add(i);\r
1664             }\r
1665         }\r
1666         FX_LPCWSTR lpSrcBuf = FX_LPCWSTR(wsText);\r
1667         CFX_WideString wsTemp;\r
1668         FX_INT32 nCount = PosArr.GetSize();\r
1669         FX_LPWSTR lpDstBuf = wsTemp.GetBuffer(nLength + nCount);\r
1670         FX_INT32 nDstPos = 0;\r
1671         FX_INT32 nSrcPos = 0;\r
1672         for (i = 0; i < nCount; i ++) {\r
1673             FX_INT32 nPos = PosArr[i];\r
1674             FX_INT32 nCopyLen = nPos - nSrcPos + 1;\r
1675             FXSYS_memcpy(lpDstBuf + nDstPos, lpSrcBuf + nSrcPos, nCopyLen * sizeof(FX_WCHAR));\r
1676             nDstPos += nCopyLen;\r
1677             nSrcPos += nCopyLen;\r
1678             lpDstBuf[nDstPos] = L'\n';\r
1679             nDstPos ++;\r
1680         }\r
1681         if (nSrcPos < nLength) {\r
1682             FXSYS_memcpy(lpDstBuf + nDstPos, lpSrcBuf + nSrcPos, (nLength - nSrcPos) * sizeof(FX_WCHAR));\r
1683         }\r
1684         wsTemp.ReleaseBuffer(nLength + nCount);\r
1685         wsText = wsTemp;\r
1686     } else {\r
1687         FX_INT32 nLength = wsText.GetLength();\r
1688         FX_LPWSTR lpBuf = (FX_LPWSTR)(FX_LPCWSTR)wsText;\r
1689         for (FX_INT32 i = 0; i < nLength; i ++, lpBuf++) {\r
1690             if (*lpBuf == m_wLineEnd) {\r
1691                 *lpBuf = wc;\r
1692             }\r
1693         }\r
1694     }\r
1695 }\r
1696 FX_INT32 CFDE_TxtEdtEngine::MovePage2Char(FX_INT32 nIndex)\r
1697 {\r
1698     FXSYS_assert(nIndex >= 0);\r
1699     FXSYS_assert(nIndex <= m_pTxtBuf->GetTextLength());\r
1700     if (m_nCaretPage >= 0) {\r
1701         IFDE_TxtEdtPage* pPage = m_PagePtrArray[m_nCaretPage];\r
1702         m_Param.pEventSink->On_PageLoad(this, m_nCaretPage, 0);\r
1703         FX_INT32 nPageCharStart = pPage->GetCharStart();\r
1704         FX_INT32 nPageCharCount = pPage->GetCharCount();\r
1705         if (nIndex >= nPageCharStart && nIndex < nPageCharStart + nPageCharCount) {\r
1706             m_Param.pEventSink->On_PageUnload(this, m_nCaretPage, 0);\r
1707             return m_nCaretPage;\r
1708         }\r
1709         m_Param.pEventSink->On_PageUnload(this, m_nCaretPage, 0);\r
1710     }\r
1711     CFDE_TxtEdtParag * pParag = NULL;\r
1712     FX_INT32 nLineCount         = 0;\r
1713     FX_INT32 nParagCount        = m_ParagPtrArray.GetSize();\r
1714     FX_INT32 i = 0;\r
1715     for (i = 0; i < nParagCount; i ++) {\r
1716         pParag = m_ParagPtrArray[i];\r
1717         if (pParag->m_nCharStart <= nIndex && nIndex < (pParag->m_nCharStart + pParag->m_nCharCount)) {\r
1718             break;\r
1719         }\r
1720         nLineCount += pParag->m_nLineCount;\r
1721     }\r
1722     pParag->LoadParag();\r
1723     FX_INT32 nLineStart         = -1;\r
1724     FX_INT32 nLineCharCount = -1;\r
1725     for (i = 0; i < pParag->m_nLineCount; i ++) {\r
1726         pParag->GetLineRange(i, nLineStart, nLineCharCount);\r
1727         if (nLineStart <= nIndex && nIndex < (nLineStart + nLineCharCount)) {\r
1728             break;\r
1729         }\r
1730     }\r
1731     FXSYS_assert(i < pParag->m_nLineCount);\r
1732     nLineCount += (i + 1);\r
1733     m_nCaretPage = (nLineCount - 1) / m_nPageLineCount + 1 - 1;\r
1734     m_Param.pEventSink->On_PageChange(this, m_nCaretPage);\r
1735     pParag->UnloadParag();\r
1736     return m_nCaretPage;\r
1737 }\r
1738 void CFDE_TxtEdtEngine::TextPos2ParagPos(FX_INT32 nIndex, FDE_TXTEDTPARAGPOS &ParagPos) const\r
1739 {\r
1740     FXSYS_assert(nIndex >= 0 && nIndex < m_pTxtBuf->GetTextLength());\r
1741     FX_INT32 nCount = m_ParagPtrArray.GetSize();\r
1742     FX_INT32 nBgn = 0;\r
1743     FX_INT32 nMid = 0;\r
1744     FX_INT32 nEnd = nCount - 1;\r
1745     while (nEnd > nBgn) {\r
1746         nMid = (nBgn + nEnd) / 2;\r
1747         CFDE_TxtEdtParag * pParag = m_ParagPtrArray[nMid];\r
1748         if (nIndex < pParag->m_nCharStart) {\r
1749             nEnd = nMid - 1;\r
1750         } else if (nIndex >= (pParag->m_nCharStart + pParag->m_nCharCount)) {\r
1751             nBgn = nMid + 1;\r
1752         } else {\r
1753             break;\r
1754         }\r
1755     }\r
1756     if (nBgn == nEnd) {\r
1757         nMid = nBgn;\r
1758     }\r
1759     FXSYS_assert(nIndex >= m_ParagPtrArray[nMid]->m_nCharStart && \\r
1760                  (nIndex < m_ParagPtrArray[nMid]->m_nCharStart + m_ParagPtrArray[nMid]->m_nCharCount));\r
1761     ParagPos.nParagIndex        = nMid;\r
1762     ParagPos.nCharIndex         = nIndex - m_ParagPtrArray[nMid]->m_nCharStart;\r
1763 }\r
1764 FX_INT32 CFDE_TxtEdtEngine::MoveForward(FX_BOOL &bBefore)\r
1765 {\r
1766     if (m_nCaret == m_pTxtBuf->GetTextLength() - 1) {\r
1767         return -1;\r
1768     }\r
1769     FX_INT32 nCaret = m_nCaret;\r
1770     if ((nCaret + 1 < m_pTxtBuf->GetTextLength()) && (m_pTxtBuf->GetCharByIndex(nCaret) == L'\r') && \\r
1771             (m_pTxtBuf->GetCharByIndex(nCaret + 1) == L'\n')) {\r
1772         nCaret ++;\r
1773     }\r
1774     nCaret ++;\r
1775     bBefore = TRUE;\r
1776     return nCaret;\r
1777 }\r
1778 FX_INT32 CFDE_TxtEdtEngine::MoveBackward(FX_BOOL &bBefore)\r
1779 {\r
1780     if (m_nCaret == 0) {\r
1781         return FALSE;\r
1782     }\r
1783     FX_INT32 nCaret = m_nCaret;\r
1784     if (nCaret > 2 && m_pTxtBuf->GetCharByIndex(nCaret - 1) == L'\n' && \\r
1785             m_pTxtBuf->GetCharByIndex(nCaret - 2) == L'\r') {\r
1786         nCaret --;\r
1787     }\r
1788     nCaret --;\r
1789     bBefore = TRUE;\r
1790     return nCaret;\r
1791 }\r
1792 FX_BOOL CFDE_TxtEdtEngine::MoveUp(CFX_PointF &ptCaret)\r
1793 {\r
1794     IFDE_TxtEdtPage * pPage             = GetPage(m_nCaretPage);\r
1795     const CFX_RectF& rtContent  = pPage->GetContentsBox();\r
1796     if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_DocVertical) {\r
1797         ptCaret.x = m_rtCaret.left + m_rtCaret.width / 2 - m_Param.fLineSpace;\r
1798         ptCaret.y = m_fCaretPosReserve;\r
1799         FX_BOOL bLineReserve = m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_LineReserve;\r
1800         if (ptCaret.x < rtContent.left) {\r
1801             if (bLineReserve) {\r
1802                 if (m_nCaretPage == CountPages() - 1) {\r
1803                     return FALSE;\r
1804                 }\r
1805             } else {\r
1806                 if (m_nCaretPage == 0) {\r
1807                     return FALSE;\r
1808                 }\r
1809             }\r
1810             if (bLineReserve) {\r
1811                 m_nCaretPage ++;\r
1812             } else {\r
1813                 m_nCaretPage --;\r
1814             }\r
1815             m_Param.pEventSink->On_PageChange(this, m_nCaretPage);\r
1816             ptCaret.x -= rtContent.left;\r
1817             IFDE_TxtEdtPage * pCurPage = GetPage(m_nCaretPage);\r
1818             ptCaret.x += pCurPage->GetContentsBox().right();\r
1819         }\r
1820     } else {\r
1821         ptCaret.x = m_fCaretPosReserve;\r
1822         ptCaret.y = m_rtCaret.top + m_rtCaret.height / 2 - m_Param.fLineSpace;\r
1823         if (ptCaret.y < rtContent.top) {\r
1824             if (m_nCaretPage == 0) {\r
1825                 return FALSE;\r
1826             }\r
1827             ptCaret.y -= rtContent.top;\r
1828             m_nCaretPage --;\r
1829             m_Param.pEventSink->On_PageChange(this, m_nCaretPage);\r
1830             IFDE_TxtEdtPage * pCurPage = GetPage(m_nCaretPage);\r
1831             ptCaret.y += pCurPage->GetContentsBox().bottom();\r
1832         }\r
1833     }\r
1834     return TRUE;\r
1835 }\r
1836 FX_BOOL CFDE_TxtEdtEngine::MoveDown(CFX_PointF &ptCaret)\r
1837 {\r
1838     IFDE_TxtEdtPage * pPage = GetPage(m_nCaretPage);\r
1839     const CFX_RectF& rtContent = pPage->GetContentsBox();\r
1840     if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_DocVertical) {\r
1841         ptCaret.x = m_rtCaret.left + m_rtCaret.width / 2 + m_Param.fLineSpace;\r
1842         ptCaret.y = m_fCaretPosReserve;\r
1843         if (ptCaret.x >= rtContent.right()) {\r
1844             FX_BOOL bLineReserve = m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_LineReserve;\r
1845             if (bLineReserve) {\r
1846                 if (m_nCaretPage == 0) {\r
1847                     return FALSE;\r
1848                 }\r
1849             } else {\r
1850                 if (m_nCaretPage == CountPages() - 1) {\r
1851                     return FALSE;\r
1852                 }\r
1853             }\r
1854             if (bLineReserve) {\r
1855                 m_nCaretPage --;\r
1856             } else {\r
1857                 m_nCaretPage ++;\r
1858             }\r
1859             m_Param.pEventSink->On_PageChange(this, m_nCaretPage);\r
1860             ptCaret.x -= rtContent.right();\r
1861             IFDE_TxtEdtPage * pCurPage = GetPage(m_nCaretPage);\r
1862             ptCaret.x += pCurPage->GetContentsBox().left;\r
1863         }\r
1864     } else {\r
1865         ptCaret.x = m_fCaretPosReserve;\r
1866         ptCaret.y = m_rtCaret.top + m_rtCaret.height / 2 + m_Param.fLineSpace;\r
1867         if (ptCaret.y >= rtContent.bottom()) {\r
1868             if (m_nCaretPage == CountPages() - 1) {\r
1869                 return FALSE;\r
1870             }\r
1871             ptCaret.y -= rtContent.bottom();\r
1872             m_nCaretPage ++;\r
1873             m_Param.pEventSink->On_PageChange(this, m_nCaretPage);\r
1874             IFDE_TxtEdtPage * pCurPage = GetPage(m_nCaretPage);\r
1875             ptCaret.y += pCurPage->GetContentsBox().top;\r
1876         }\r
1877     }\r
1878     return TRUE;\r
1879 }\r
1880 FX_BOOL CFDE_TxtEdtEngine::MoveLineStart()\r
1881 {\r
1882     FX_INT32 nIndex = m_bBefore ? m_nCaret : m_nCaret - 1;\r
1883     FDE_TXTEDTPARAGPOS ParagPos;\r
1884     TextPos2ParagPos(nIndex, ParagPos);\r
1885     CFDE_TxtEdtParag * pParag = m_ParagPtrArray[ParagPos.nParagIndex];\r
1886     pParag->LoadParag();\r
1887     FX_INT32 nLineCount = pParag->m_nLineCount;\r
1888     FX_INT32 i = 0;\r
1889     FX_INT32 nStart = 0;\r
1890     FX_INT32 nCount = 0;\r
1891     for (; i < nLineCount; i ++) {\r
1892         pParag->GetLineRange(i, nStart, nCount);\r
1893         if (nIndex >= nStart && nIndex < nStart + nCount) {\r
1894             break;\r
1895         }\r
1896     }\r
1897     UpdateCaretRect(nStart, TRUE);\r
1898     pParag->UnloadParag();\r
1899     return TRUE;\r
1900 }\r
1901 FX_BOOL CFDE_TxtEdtEngine::MoveLineEnd()\r
1902 {\r
1903     FX_INT32 nIndex = m_bBefore ? m_nCaret : m_nCaret - 1;\r
1904     FDE_TXTEDTPARAGPOS ParagPos;\r
1905     TextPos2ParagPos(nIndex, ParagPos);\r
1906     CFDE_TxtEdtParag * pParag = m_ParagPtrArray[ParagPos.nParagIndex];\r
1907     pParag->LoadParag();\r
1908     FX_INT32 nLineCount = pParag->m_nLineCount;\r
1909     FX_INT32 i = 0;\r
1910     FX_INT32 nStart = 0;\r
1911     FX_INT32 nCount = 0;\r
1912     for (; i < nLineCount; i ++) {\r
1913         pParag->GetLineRange(i, nStart, nCount);\r
1914         if (nIndex >= nStart && nIndex < nStart + nCount) {\r
1915             break;\r
1916         }\r
1917     }\r
1918     nIndex      = nStart + nCount - 1;\r
1919     FXSYS_assert(nIndex <= GetTextBufLength());\r
1920     FX_WCHAR wChar      = m_pTxtBuf->GetCharByIndex(nIndex);\r
1921     FX_BOOL bBefore = FALSE;\r
1922     if (nIndex <= GetTextBufLength()) {\r
1923         if (wChar == L'\r') {\r
1924             bBefore = TRUE;\r
1925         } else if (wChar == L'\n' && nIndex > nStart) {\r
1926             bBefore = TRUE;\r
1927             nIndex --;\r
1928             wChar = m_pTxtBuf->GetCharByIndex(nIndex);\r
1929             if (wChar != L'\r') {\r
1930                 nIndex ++;\r
1931             }\r
1932         }\r
1933     }\r
1934     UpdateCaretRect(nIndex, bBefore);\r
1935     pParag->UnloadParag();\r
1936     return TRUE;\r
1937 }\r
1938 FX_BOOL CFDE_TxtEdtEngine::MoveParagStart()\r
1939 {\r
1940     FX_INT32 nIndex = m_bBefore ? m_nCaret : m_nCaret - 1;\r
1941     FDE_TXTEDTPARAGPOS ParagPos;\r
1942     TextPos2ParagPos(nIndex, ParagPos);\r
1943     CFDE_TxtEdtParag * pParag = m_ParagPtrArray[ParagPos.nParagIndex];\r
1944     UpdateCaretRect(pParag->m_nCharStart, TRUE);\r
1945     return TRUE;\r
1946 }\r
1947 FX_BOOL CFDE_TxtEdtEngine::MoveParagEnd()\r
1948 {\r
1949     FX_INT32 nIndex = m_bBefore ? m_nCaret : m_nCaret - 1;\r
1950     FDE_TXTEDTPARAGPOS ParagPos;\r
1951     TextPos2ParagPos(nIndex, ParagPos);\r
1952     CFDE_TxtEdtParag * pParag = m_ParagPtrArray[ParagPos.nParagIndex];\r
1953     nIndex      = pParag->m_nCharStart + pParag->m_nCharCount - 1;\r
1954     FX_WCHAR wChar      = m_pTxtBuf->GetCharByIndex(nIndex);\r
1955     if (wChar == L'\n' && nIndex > 0) {\r
1956         nIndex --;\r
1957         wChar = m_pTxtBuf->GetCharByIndex(nIndex);\r
1958         if (wChar != L'\r') {\r
1959             nIndex ++;\r
1960         }\r
1961     }\r
1962     UpdateCaretRect(nIndex, TRUE);\r
1963     return TRUE;\r
1964 }\r
1965 FX_BOOL CFDE_TxtEdtEngine::MoveHome()\r
1966 {\r
1967     UpdateCaretRect(0, TRUE);\r
1968     return TRUE;\r
1969 }\r
1970 FX_BOOL CFDE_TxtEdtEngine::MoveEnd()\r
1971 {\r
1972     UpdateCaretRect(GetTextBufLength(), TRUE);\r
1973     return TRUE;\r
1974 }\r
1975 #ifdef FDE_USEFORMATBLOCK\r
1976 FX_INT32 CFDE_TxtEdtEngine::NormalizeCaretPos(FX_INT32 nIndex, FX_INT32 nFlags, FX_BOOL &bBefore)\r
1977 {\r
1978     bBefore = TRUE;\r
1979     FX_INT32 nBgn = 0, nEnd = 0;\r
1980     FX_INT32 nRecord = -1;\r
1981     CFDE_TxtEdtField * pField = NULL;\r
1982     FX_BOOL bRet = GetFieldBoundary(nIndex, nBgn, nEnd, pField);\r
1983     FX_INT32 nDelta = 0;\r
1984     if (bRet && !pField->IsFix()) {\r
1985         if (nIndex - nBgn < FDE_FORMAT_EDIT_FIELD_HADERSIZE) {\r
1986             if (nFlags == FDE_FORMAT_CARET_BACKWARD) {\r
1987                 CFDE_TxtEdtField * pEditableField = NULL;\r
1988                 if (FindEditableField(nIndex, nBgn, nEnd, pEditableField, FALSE)) {\r
1989                     return pEditableField->NormalizeCaretPos(nEnd - nBgn, FDE_FORMAT_CARET_BACKWARD) + nBgn;\r
1990                 }\r
1991             }\r
1992             nIndex = nBgn + FDE_FORMAT_EDIT_FIELD_HADERSIZE;\r
1993         }\r
1994         FX_INT32 nRet = pField->NormalizeCaretPos(nIndex - nBgn, (FDE_FORMAT_CARET_DIRECTION)nFlags);\r
1995         if (nRet >= 0) {\r
1996             return nRet + nBgn;\r
1997         }\r
1998         if (nRet == -2) {\r
1999             FX_INT32 nEditablePosBgn = 0, nEditablePosEnd = 0;\r
2000             pField->GetEditableRange(nEditablePosBgn, nEditablePosEnd);\r
2001             nRecord = nBgn + nEditablePosBgn;\r
2002             nFlags = FDE_FORMAT_CARET_BACKWARD;\r
2003         } else {\r
2004             FXSYS_assert(nRet == -1);\r
2005             FX_INT32 nEditablePosBgn = 0, nEditablePosEnd = 0;\r
2006             pField->GetEditableRange(nEditablePosBgn, nEditablePosEnd);\r
2007             nRecord = nBgn + nEditablePosEnd;\r
2008             nFlags = FDE_FORMAT_CARET_FORWARD;\r
2009         }\r
2010     } else if (!bRet) {\r
2011         nDelta = FDE_FORMAT_EDIT_FIELD_HADERSIZE - FDE_FORMAT_EDIT_FIELD_TAILSIZE;\r
2012     }\r
2013     switch (nFlags) {\r
2014         case FDE_FORMAT_CARET_FORWARD: {\r
2015                 if (FindEditableField(nIndex, nBgn, nEnd, pField)) {\r
2016                     return pField->NormalizeCaretPos(FDE_FORMAT_EDIT_FIELD_HADERSIZE, FDE_FORMAT_CARET_FORWARD) +  nBgn;\r
2017                 } else {\r
2018                     if (nRecord != -1) {\r
2019                         return nRecord;\r
2020                     }\r
2021                     bRet = FindEditableField(nIndex, nBgn, nEnd, pField, FALSE);\r
2022                     FXSYS_assert(bRet);\r
2023                     return pField->NormalizeCaretPos(nEnd - nBgn, FDE_FORMAT_CARET_BACKWARD) + nBgn;\r
2024                 }\r
2025             }\r
2026             break;\r
2027         case FDE_FORMAT_CARET_MIDDLE: {\r
2028                 FX_INT32 nBgn1 = 0, nEnd1 = 0, nBgn2 = 0, nEnd2 = 0;\r
2029                 CFDE_TxtEdtField * pEditableField1 = NULL;\r
2030                 CFDE_TxtEdtField * pEditableField2 = NULL;\r
2031                 FX_BOOL bRet1 = FindEditableField(nIndex, nBgn1, nEnd1, pEditableField1, FALSE);\r
2032                 FX_BOOL bRet2 = FindEditableField(nIndex, nBgn2, nEnd2, pEditableField2);\r
2033                 if (bRet1 == FALSE) {\r
2034                     FXSYS_assert(bRet2);\r
2035                     return pEditableField2->NormalizeCaretPos(FDE_FORMAT_EDIT_FIELD_HADERSIZE, FDE_FORMAT_CARET_FORWARD) + nBgn2;\r
2036                 } else if (bRet2 == FALSE) {\r
2037                     FXSYS_assert(bRet1);\r
2038                     return pEditableField1->NormalizeCaretPos(nEnd1 - nBgn1, FDE_FORMAT_CARET_BACKWARD) + nBgn1;\r
2039                 } else {\r
2040                     FX_INT32 nEditablePosBgn = 0, nEditablePosEnd = 0;\r
2041                     if (nIndex - nEnd1 < nBgn2 + nDelta - nIndex) {\r
2042                         pEditableField1->GetEditableRange(nEditablePosBgn, nEditablePosEnd);\r
2043                         return nEditablePosEnd + nBgn1;\r
2044                     } else {\r
2045                         pEditableField2->GetEditableRange(nEditablePosBgn, nEditablePosEnd);\r
2046                         return nEditablePosBgn + nBgn2;\r
2047                     }\r
2048                 }\r
2049             }\r
2050             break;\r
2051         case FDE_FORMAT_CARET_BACKWARD: {\r
2052                 if (FindEditableField(nIndex, nBgn, nEnd, pField, FALSE)) {\r
2053                     return pField->NormalizeCaretPos(nEnd - nBgn, FDE_FORMAT_CARET_BACKWARD) + nBgn;\r
2054                 } else {\r
2055                     if (nRecord != -1) {\r
2056                         return nRecord;\r
2057                     }\r
2058                     bRet = FindEditableField(nIndex, nBgn, nEnd, pField);\r
2059                     FXSYS_assert(bRet);\r
2060                     return pField->NormalizeCaretPos(FDE_FORMAT_EDIT_FIELD_HADERSIZE, FDE_FORMAT_CARET_FORWARD) + nBgn;\r
2061                 }\r
2062             }\r
2063             break;\r
2064         default:\r
2065             FXSYS_assert(0);\r
2066             return nIndex;\r
2067     }\r
2068 }\r
2069 FX_BOOL CFDE_TxtEdtEngine::GetFieldBoundary(FX_INT32 nIndex, FX_INT32 &nBgn, FX_INT32 &nEnd, CFDE_TxtEdtField * &pField)\r
2070 {\r
2071     CFDE_TxtEdtBufIter * pIter = FX_NEW CFDE_TxtEdtBufIter((CFDE_TxtEdtBuf*)m_pTxtBuf, FALSE);\r
2072     pIter->SetAt(nIndex);\r
2073     FX_BOOL bFind = FALSE;\r
2074     do {\r
2075         FX_WCHAR wc = pIter->GetChar();\r
2076         if (wc == FDE_TXTEDT_FORMATBLOCK_END) {\r
2077             nEnd        = pIter->GetAt();\r
2078             bFind       = TRUE;\r
2079             nIndex --;\r
2080             break;\r
2081         }\r
2082         if (wc == FDE_TXTEDT_FORMATBLOCK_BGN) {\r
2083             pIter->Release();\r
2084             return FALSE;\r
2085         }\r
2086     } while (pIter->Next());\r
2087     if (!bFind) {\r
2088         pIter->Release();\r
2089         return FALSE;\r
2090     }\r
2091     pIter->SetAt(nIndex);\r
2092     do {\r
2093         FX_WCHAR wc = pIter->GetChar();\r
2094         if (wc == FDE_TXTEDT_FORMATBLOCK_BGN) {\r
2095             nBgn = pIter->GetAt();\r
2096             pIter->Next();\r
2097             FX_DWORD dwPre = (FX_DWORD)pIter->GetChar();\r
2098             pIter->Next();\r
2099             FX_DWORD dwCur = (FX_DWORD)pIter->GetChar();\r
2100             pField = (CFDE_TxtEdtField *)((dwCur << 16) | dwPre);\r
2101             pIter->Release();\r
2102             return TRUE;\r
2103         }\r
2104         if (wc == FDE_TXTEDT_FORMATBLOCK_END) {\r
2105             pIter->Release();\r
2106             return FALSE;\r
2107         }\r
2108     } while (pIter->Next(TRUE));\r
2109     pIter->Release();\r
2110     return FALSE;\r
2111 }\r
2112 FX_BOOL CFDE_TxtEdtEngine::FindEditableField(FX_INT32 nIndex, FX_INT32 &nBgn, FX_INT32 &nEnd, CFDE_TxtEdtField * &pField, FX_BOOL bForward )\r
2113 {\r
2114     FX_WCHAR wcFirst    = FDE_TXTEDT_FORMATBLOCK_BGN;\r
2115     FX_WCHAR wcSecond   = FDE_TXTEDT_FORMATBLOCK_END;\r
2116     if (!bForward) {\r
2117         wcFirst         = FDE_TXTEDT_FORMATBLOCK_END;\r
2118         wcSecond        = FDE_TXTEDT_FORMATBLOCK_BGN;\r
2119     }\r
2120     CFDE_TxtEdtBufIter * pIter = FX_NEW CFDE_TxtEdtBufIter((CFDE_TxtEdtBuf*)m_pTxtBuf, FALSE);\r
2121     pIter->SetAt(nIndex);\r
2122     FX_INT32 bFind = FALSE;\r
2123     do {\r
2124         FX_WCHAR wc = pIter->GetChar();\r
2125         if (wc == wcFirst) {\r
2126             nBgn        = pIter->GetAt();\r
2127             bFind       = TRUE;\r
2128             break;\r
2129         }\r
2130     } while (pIter->Next(!bForward));\r
2131     if (!bFind) {\r
2132         pIter->Release();\r
2133         return FALSE;\r
2134     }\r
2135     bFind = FALSE;\r
2136     do {\r
2137         FX_WCHAR wc = pIter->GetChar();\r
2138         if (wc == wcSecond) {\r
2139             nEnd = pIter->GetAt();\r
2140             bFind = TRUE;\r
2141             break;\r
2142         }\r
2143     } while (pIter->Next(!bForward));\r
2144     FXSYS_assert(bFind);\r
2145     if (!bForward) {\r
2146         FX_INT32 nTemp = nBgn;\r
2147         nBgn = nEnd;\r
2148         nEnd = nTemp;\r
2149     }\r
2150     pIter->SetAt(nBgn + 1);\r
2151     FX_DWORD dwPre = (FX_DWORD)pIter->GetChar();\r
2152     pIter->Next();\r
2153     FX_DWORD dwCur = (FX_DWORD)pIter->GetChar();\r
2154     pField = (CFDE_TxtEdtField *)((dwCur << 16) | dwPre);\r
2155     pIter->Release();\r
2156     if (!pField->IsFix()) {\r
2157         return TRUE;\r
2158     }\r
2159     return FindEditableField((bForward ? nEnd : nBgn), nBgn, nEnd, pField, bForward);\r
2160 }\r
2161 FX_BOOL CFDE_TxtEdtEngine::Move2NextEditableField(FX_INT32 nIndex, FX_BOOL bForward , FX_BOOL bSelect  )\r
2162 {\r
2163     if (m_SelRangePtrArr.GetSize() > 0) {\r
2164         ClearSelection();\r
2165         m_Param.pEventSink->On_SelChanged(this);\r
2166     }\r
2167     FX_INT32 nBgn = 0, nEnd = 0;\r
2168     CFDE_TxtEdtField * pField = NULL;\r
2169     FX_BOOL bRet = FindEditableField(nIndex, nBgn, nEnd, pField, bForward);\r
2170     if (!bRet) {\r
2171         return FALSE;\r
2172     }\r
2173     FX_INT32 nEditableBgn = 0, nEditableEnd = 0;\r
2174     pField->GetEditableRange(nEditableBgn, nEditableEnd);\r
2175     nEditableBgn += nBgn;\r
2176     nEditableEnd += nBgn;\r
2177     if (bSelect) {\r
2178         FX_INT32 nRangeCount = nEditableEnd - nEditableBgn;\r
2179         if (nRangeCount > 0) {\r
2180             AddSelRange(nEditableBgn, nEditableEnd - nEditableBgn);\r
2181         }\r
2182     }\r
2183     SetCaretPos(nEditableEnd, TRUE);\r
2184     return TRUE;\r
2185 }\r
2186 FX_INT32 CFDE_TxtEdtEngine::GetRealIndex(FX_INT32 nIndex) const\r
2187 {\r
2188     CFDE_TxtEdtBufIter * pIter = FX_NEW CFDE_TxtEdtBufIter((CFDE_TxtEdtBuf*)m_pTxtBuf, FALSE);\r
2189     pIter->SetAt(0);\r
2190     FX_BOOL             bInField        = FALSE;\r
2191     FX_INT32    nFieldBgn       = 0;\r
2192     FX_INT32    nRealIndex      = 0;\r
2193     for (FX_INT32 i = 0; i <= nIndex; i ++) {\r
2194         FX_WCHAR wc = pIter->GetChar();\r
2195         if (bInField) {\r
2196             if (wc == FDE_TXTEDT_FORMATBLOCK_END) {\r
2197                 FX_DWORD dwPre = (FX_DWORD)m_pTxtBuf->GetCharByIndex(nFieldBgn + 1);\r
2198                 FX_DWORD dwCur = (FX_DWORD)m_pTxtBuf->GetCharByIndex(nFieldBgn + 2);\r
2199                 CFDE_TxtEdtField * pField = (CFDE_TxtEdtField *)((dwCur << 16) | dwPre);\r
2200                 nRealIndex += pField->GetFieldTextLength();\r
2201                 bInField = FALSE;\r
2202             }\r
2203         } else {\r
2204             if (wc == FDE_TXTEDT_FORMATBLOCK_BGN) {\r
2205                 bInField        = TRUE;\r
2206                 nFieldBgn       = pIter->GetAt();\r
2207             } else {\r
2208                 nRealIndex ++;\r
2209             }\r
2210         }\r
2211         pIter->Next();\r
2212     }\r
2213     if (!bInField) {\r
2214         pIter->Release();\r
2215         return nRealIndex;\r
2216     }\r
2217     pIter->SetAt(nFieldBgn + 1);\r
2218     FX_DWORD dwPre = (FX_DWORD)pIter->GetChar();\r
2219     pIter->Next();\r
2220     FX_DWORD dwCur = (FX_DWORD)pIter->GetChar();\r
2221     CFDE_TxtEdtField * pField = (CFDE_TxtEdtField *)((dwCur << 16) | dwPre);\r
2222     pIter->Release();\r
2223     if (pField->IsFix()) {\r
2224         FX_INT32 nDelta = nIndex - nFieldBgn - FDE_FORMAT_EDIT_FIELD_HADERSIZE + 1;\r
2225         return nRealIndex + (nDelta > 0 ? nDelta : 0);\r
2226     } else {\r
2227         return nRealIndex + pField->GetRealIndex(nIndex - nFieldBgn);\r
2228     }\r
2229 }\r
2230 #endif\r
2231 FX_BOOL CFDE_TxtEdtEngine::IsFitArea(CFX_WideString &wsText)\r
2232 {\r
2233     IFDE_TextOut * pTextOut = IFDE_TextOut::Create();\r
2234     pTextOut->SetLineSpace(m_Param.fLineSpace);\r
2235     pTextOut->SetFont(m_Param.pFont);\r
2236     pTextOut->SetFontSize(m_Param.fFontSize);\r
2237     CFX_RectF rcText;\r
2238     FXSYS_memset(&rcText, 0, sizeof(rcText));\r
2239     FX_DWORD dwStyle = 0;\r
2240     if (!(m_Param.dwMode & FDE_TEXTEDITMODE_MultiLines)) {\r
2241         dwStyle |= FDE_TTOSTYLE_SingleLine;\r
2242     }\r
2243     if (m_Param.dwMode & FDE_TEXTEDITMODE_AutoLineWrap) {\r
2244         dwStyle |= FDE_TTOSTYLE_LineWrap;\r
2245         rcText.width = m_Param.fPlateWidth;\r
2246     } else {\r
2247         rcText.width = 65535;\r
2248     }\r
2249     pTextOut->SetStyles(dwStyle);\r
2250     wsText += L"\n";\r
2251     pTextOut->CalcLogicSize(wsText, wsText.GetLength(), rcText);\r
2252     pTextOut->Release();\r
2253     wsText.Delete(wsText.GetLength() - 1);\r
2254     if ((m_Param.dwMode & FDE_TEXTEDITMODE_LimitArea_Horz) && (rcText.width > m_Param.fPlateWidth)) {\r
2255         return FALSE;\r
2256     }\r
2257     if ((m_Param.dwMode & FDE_TEXTEDITMODE_LimitArea_Vert) && \\r
2258             (rcText.height > m_Param.fLineSpace * m_Param.nLineCount)) {\r
2259         return FALSE;\r
2260     }\r
2261     return TRUE;\r
2262 }\r
2263 void CFDE_TxtEdtEngine::UpdateCaretRect(FX_INT32 nIndex, FX_BOOL bBefore)\r
2264 {\r
2265     MovePage2Char(nIndex);\r
2266     GetCaretRect(m_rtCaret, m_nCaretPage, nIndex, bBefore);\r
2267     m_nCaret    = nIndex;\r
2268     m_bBefore   = bBefore;\r
2269     if (!m_bBefore) {\r
2270         m_nCaret ++;\r
2271         m_bBefore = TRUE;\r
2272     }\r
2273     m_fCaretPosReserve = (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_DocVertical) ? \\r
2274                          m_rtCaret.top : m_rtCaret.left;\r
2275     m_Param.pEventSink->On_CaretChanged(this, m_nCaretPage, 0);\r
2276 }\r
2277 void CFDE_TxtEdtEngine::GetCaretRect(CFX_RectF &rtCaret, FX_INT32 nPageIndex, FX_INT32 nCaret, FX_BOOL bBefore )\r
2278 {\r
2279     IFDE_TxtEdtPage * pPage = m_PagePtrArray[m_nCaretPage];\r
2280     m_Param.pEventSink->On_PageLoad(this, m_nCaretPage, 0);\r
2281     FX_BOOL             bCombText               = m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_CombText;\r
2282     FX_INT32    nIndexInpage    = nCaret - pPage->GetCharStart();\r
2283     if (bBefore && bCombText && nIndexInpage > 0) {\r
2284         nIndexInpage--;\r
2285         bBefore = FALSE;\r
2286     }\r
2287     FX_INT32 nBIDILevel = pPage->GetCharRect(nIndexInpage, rtCaret, bCombText);\r
2288     if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_DocVertical) {\r
2289         if ((!FX_IsOdd(nBIDILevel) && !bBefore) || (FX_IsOdd(nBIDILevel) && bBefore)) {\r
2290             rtCaret.Offset(0, rtCaret.height - 1.0f);\r
2291         }\r
2292         if (rtCaret.height == 0 && rtCaret.top > 1.0f) {\r
2293             rtCaret.top -= 1.0f;\r
2294         }\r
2295         rtCaret.height = 1.0f;\r
2296     } else {\r
2297         if ((!FX_IsOdd(nBIDILevel) && !bBefore) || (FX_IsOdd(nBIDILevel) && bBefore)) {\r
2298             rtCaret.Offset(rtCaret.width - 1.0f, 0);\r
2299         }\r
2300         if (rtCaret.width == 0 && rtCaret.left > 1.0f) {\r
2301             rtCaret.left -= 1.0f;\r
2302         }\r
2303         rtCaret.width = 1.0f;\r
2304     }\r
2305     m_Param.pEventSink->On_PageUnload(this, m_nCaretPage, 0);\r
2306 }\r
2307 void CFDE_TxtEdtEngine::UpdateCaretIndex(const CFX_PointF & ptCaret)\r
2308 {\r
2309     IFDE_TxtEdtPage * pPage = m_PagePtrArray[m_nCaretPage];\r
2310     m_Param.pEventSink->On_PageLoad(this, m_nCaretPage, 0);\r
2311     m_nCaret = pPage->GetCharIndex(ptCaret, m_bBefore);\r
2312     GetCaretRect(m_rtCaret, m_nCaretPage, m_nCaret, m_bBefore);\r
2313     if (!m_bBefore) {\r
2314         m_nCaret ++;\r
2315         m_bBefore = TRUE;\r
2316     }\r
2317     m_Param.pEventSink->On_CaretChanged(this, m_nCaretPage);\r
2318     m_Param.pEventSink->On_PageUnload(this, m_nCaretPage, 0);\r
2319 }\r
2320 FX_BOOL CFDE_TxtEdtEngine::IsSelect()\r
2321 {\r
2322     return m_SelRangePtrArr.GetSize() > 0;\r
2323 }\r
2324 void CFDE_TxtEdtEngine::DeleteSelect()\r
2325 {\r
2326     FX_INT32 nCountRange = CountSelRanges();\r
2327     if (nCountRange > 0) {\r
2328 #ifdef FDE_USEFORMATBLOCK\r
2329         FX_INT32 nBlockCount = m_BlockArray.GetSize();\r
2330         if (nBlockCount > 0) {\r
2331             if (nCountRange > 1) {\r
2332                 return;\r
2333             }\r
2334             FX_INT32 nSelStart;\r
2335             FX_INT32 nSelCount;\r
2336             nSelCount = GetSelRange(0, nSelStart);\r
2337             FX_INT32 nSelEnd = nSelStart + nSelCount;\r
2338             FX_INT32 nBgn = 0;\r
2339             FX_INT32 nEnd = 0;\r
2340             CFDE_TxtEdtField * pField = NULL;\r
2341             FX_BOOL bInField = GetFieldBoundary(nSelStart, nBgn, nEnd, pField);\r
2342             FX_INT32    nCaretInField   = nSelStart - nBgn;\r
2343             FX_BOOL             bBefore                 = FALSE;\r
2344             if (!bInField || pField->IsFix() || nSelEnd > nEnd) {\r
2345                 return;\r
2346             }\r
2347             pField->Backup();\r
2348             CFX_WideString wsDel;\r
2349             FX_INT32 nCaret = 0;\r
2350             FX_INT32 nRet = pField->Delete(nCaretInField, nSelCount, wsDel, nCaret, bBefore);\r
2351             nCaret += nBgn;\r
2352             switch (nRet) {\r
2353                 case FDE_FORMAT_FIELD_DELETE_RET_S:\r
2354                     break;\r
2355                 case FDE_FORMAT_FIELD_DELETE_RET_F_INVALIDATE:\r
2356                 case FDE_FORMAT_FIELD_DELETE_RET_F_BOUNDARY:\r
2357                     return;\r
2358                 default:\r
2359                     FXSYS_assert(0);\r
2360                     break;\r
2361             }\r
2362             CFX_WideString wsField;\r
2363             pField->GetFieldText(wsField);\r
2364             if (!m_Param.pEventSink->On_ValidateField(this, pField->GetBlockIndex(), pField->GetIndex(), wsField, 0)) {\r
2365                 pField->Restore();\r
2366                 return;\r
2367             }\r
2368             CFX_WideString wsDisplay;\r
2369             pField->GetDisplayText(wsDisplay);\r
2370             Replace(nBgn, nEnd - nBgn + 1, wsDisplay);\r
2371             if (!(m_Param.dwMode & FDE_TEXTEDITMODE_NoRedoUndo)) {\r
2372                 IFDE_TxtEdtDoRecord * pRecord = FX_NEW CFDE_TxtEdtDoRecord_FieldDelete(this, nSelStart, pField, nCaretInField,\r
2373                                                 nBgn, nEnd - nBgn + 1, wsDisplay.GetLength(), wsDel, FALSE);\r
2374                 CFX_ByteString bsDoRecord;\r
2375                 pRecord->Serialize(bsDoRecord);\r
2376                 m_Param.pEventSink->On_AddDoRecord(this, bsDoRecord);\r
2377                 pRecord->Release();\r
2378             }\r
2379             SetCaretPos(nSelStart, bBefore);\r
2380             return;\r
2381         }\r
2382 #endif\r
2383         FX_INT32 nSelStart;\r
2384         FX_INT32 nSelCount;\r
2385         while (nCountRange > 0) {\r
2386             nSelCount = GetSelRange(--nCountRange, nSelStart);\r
2387             FDE_LPTXTEDTSELRANGE lpTemp = m_SelRangePtrArr[nCountRange];\r
2388             delete lpTemp;\r
2389             m_SelRangePtrArr.RemoveAt(nCountRange);\r
2390             DeleteRange_DoRecord(nSelStart, nSelCount, TRUE);\r
2391         }\r
2392         ClearSelection();\r
2393         m_Param.pEventSink->On_TextChanged(this, m_ChangeInfo);\r
2394         m_Param.pEventSink->On_SelChanged(this);\r
2395         SetCaretPos(nSelStart, TRUE);\r
2396         return;\r
2397     }\r
2398 }\r
2399 IFDE_TxtEdtDoRecord * IFDE_TxtEdtDoRecord::Create(FX_BSTR bsDoRecord)\r
2400 {\r
2401     FX_LPCSTR   lpBuf   =       bsDoRecord.GetCStr();\r
2402     FX_INT32    nType   =       *((FX_INT32*)lpBuf);\r
2403     switch(nType) {\r
2404         case FDE_TXTEDT_DORECORD_INS:\r
2405             return FX_NEW CFDE_TxtEdtDoRecord_Insert(bsDoRecord);\r
2406         case FDE_TXTEDT_DORECORD_DEL:\r
2407             return FX_NEW CFDE_TxtEdtDoRecord_DeleteRange(bsDoRecord);\r
2408 #ifdef FDE_USEFORMATBLOCK\r
2409         case FDE_TXTEDT_DORECORD_FORMATINS:\r
2410             return FX_NEW CFDE_TxtEdtDoRecord_FieldInsert(bsDoRecord);\r
2411         case FDE_TXTEDT_DORECORD_FORMATDEL:\r
2412             return FX_NEW CFDE_TxtEdtDoRecord_FieldDelete(bsDoRecord);\r
2413         case FDE_TXTEDT_DORECORD_FORMATREP:\r
2414             return FX_NEW CFDE_TxtEdtDoRecord_FieldReplace(bsDoRecord);\r
2415 #endif\r
2416         default:\r
2417             break;\r
2418     }\r
2419     return NULL;\r
2420 }\r
2421 CFDE_TxtEdtDoRecord_Insert::CFDE_TxtEdtDoRecord_Insert(FX_BSTR bsDoRecord)\r
2422 {\r
2423     Deserialize(bsDoRecord);\r
2424 }\r
2425 CFDE_TxtEdtDoRecord_Insert::CFDE_TxtEdtDoRecord_Insert(CFDE_TxtEdtEngine * pEngine,\r
2426         FX_INT32 nCaret,\r
2427         FX_LPCWSTR lpText,\r
2428         FX_INT32 nLength)\r
2429     : m_pEngine(pEngine)\r
2430     , m_nCaret(nCaret)\r
2431 {\r
2432     FXSYS_assert(pEngine);\r
2433     FX_LPWSTR lpBuffer = m_wsInsert.GetBuffer(nLength);\r
2434     FXSYS_memcpy(lpBuffer, lpText, nLength * sizeof(FX_WCHAR));\r
2435     m_wsInsert.ReleaseBuffer();\r
2436 }\r
2437 CFDE_TxtEdtDoRecord_Insert::~CFDE_TxtEdtDoRecord_Insert()\r
2438 {\r
2439 }\r
2440 void CFDE_TxtEdtDoRecord_Insert::Release()\r
2441 {\r
2442     delete this;\r
2443 }\r
2444 FX_BOOL CFDE_TxtEdtDoRecord_Insert::Undo()\r
2445 {\r
2446     if (m_pEngine->IsSelect()) {\r
2447         m_pEngine->ClearSelection();\r
2448     }\r
2449     m_pEngine->Inner_DeleteRange(m_nCaret, m_wsInsert.GetLength());\r
2450     FDE_TXTEDTPARAMS& Param = m_pEngine->m_Param;\r
2451     m_pEngine->m_ChangeInfo.nChangeType = FDE_TXTEDT_TEXTCHANGE_TYPE_Delete;\r
2452     m_pEngine->m_ChangeInfo.wsDelete    = m_wsInsert;\r
2453     Param.pEventSink->On_TextChanged(m_pEngine, m_pEngine->m_ChangeInfo);\r
2454     m_pEngine->SetCaretPos(m_nCaret, TRUE);\r
2455     return TRUE;\r
2456 }\r
2457 FX_BOOL CFDE_TxtEdtDoRecord_Insert::Redo()\r
2458 {\r
2459     m_pEngine->Inner_Insert(m_nCaret, FX_LPCWSTR(m_wsInsert), m_wsInsert.GetLength());\r
2460     FDE_TXTEDTPARAMS& Param = m_pEngine->m_Param;\r
2461     m_pEngine->m_ChangeInfo.nChangeType = FDE_TXTEDT_TEXTCHANGE_TYPE_Insert;\r
2462     m_pEngine->m_ChangeInfo.wsDelete    = m_wsInsert;\r
2463     Param.pEventSink->On_TextChanged(m_pEngine, m_pEngine->m_ChangeInfo);\r
2464     m_pEngine->SetCaretPos(m_nCaret, FALSE);\r
2465     return TRUE;\r
2466 }\r
2467 void CFDE_TxtEdtDoRecord_Insert::Serialize(CFX_ByteString &bsDoRecord) const\r
2468 {\r
2469     CFX_ArchiveSaver ArchiveSaver;\r
2470     ArchiveSaver << FX_INT32(FDE_TXTEDT_DORECORD_INS);\r
2471     ArchiveSaver << (FX_INT32)(FX_UINTPTR)m_pEngine;\r
2472     ArchiveSaver << m_nCaret;\r
2473     ArchiveSaver << m_wsInsert;\r
2474     FX_INT32    nLength         = ArchiveSaver.GetLength();\r
2475     FX_LPCBYTE  lpSrcBuf        = ArchiveSaver.GetBuffer();\r
2476     FX_LPSTR    lpDstBuf        = bsDoRecord.GetBuffer(nLength);\r
2477     FXSYS_memcpy(lpDstBuf, lpSrcBuf, nLength);\r
2478     bsDoRecord.ReleaseBuffer(nLength);\r
2479 }\r
2480 void CFDE_TxtEdtDoRecord_Insert::Deserialize(FX_BSTR bsDoRecord)\r
2481 {\r
2482     CFX_ArchiveLoader ArchiveLoader((FX_LPCBYTE)bsDoRecord.GetCStr(), bsDoRecord.GetLength());\r
2483     FX_INT32 nType = 0;\r
2484     ArchiveLoader >> nType;\r
2485     FXSYS_assert(nType == FDE_TXTEDT_DORECORD_INS);\r
2486     FX_INT32 nEngine = 0;\r
2487     ArchiveLoader >> nEngine;\r
2488     m_pEngine = (CFDE_TxtEdtEngine*)(FX_UINTPTR)nEngine;\r
2489     ArchiveLoader >> m_nCaret;\r
2490     ArchiveLoader >> m_wsInsert;\r
2491 }\r
2492 CFDE_TxtEdtDoRecord_DeleteRange::CFDE_TxtEdtDoRecord_DeleteRange(FX_BSTR bsDoRecord)\r
2493 {\r
2494     Deserialize(bsDoRecord);\r
2495 }\r
2496 CFDE_TxtEdtDoRecord_DeleteRange::CFDE_TxtEdtDoRecord_DeleteRange(CFDE_TxtEdtEngine * pEngine,\r
2497         FX_INT32 nIndex,\r
2498         FX_INT32 nCaret,\r
2499         const CFX_WideString &wsRange,\r
2500         FX_BOOL bSel)\r
2501     : m_pEngine(pEngine)\r
2502     , m_nIndex(nIndex)\r
2503     , m_nCaret(nCaret)\r
2504     , m_wsRange(wsRange)\r
2505     , m_bSel(bSel)\r
2506 {\r
2507     FXSYS_assert(pEngine);\r
2508 }\r
2509 CFDE_TxtEdtDoRecord_DeleteRange::~CFDE_TxtEdtDoRecord_DeleteRange()\r
2510 {\r
2511 }\r
2512 void CFDE_TxtEdtDoRecord_DeleteRange::Release()\r
2513 {\r
2514     delete this;\r
2515 }\r
2516 FX_BOOL CFDE_TxtEdtDoRecord_DeleteRange::Undo()\r
2517 {\r
2518     if (m_pEngine->IsSelect()) {\r
2519         m_pEngine->ClearSelection();\r
2520     }\r
2521     m_pEngine->Inner_Insert(m_nIndex, FX_LPCWSTR(m_wsRange), m_wsRange.GetLength());\r
2522     if (m_bSel) {\r
2523         m_pEngine->AddSelRange(m_nIndex, m_wsRange.GetLength());\r
2524     }\r
2525     FDE_TXTEDTPARAMS& Param = m_pEngine->m_Param;\r
2526     m_pEngine->m_ChangeInfo.nChangeType = FDE_TXTEDT_TEXTCHANGE_TYPE_Insert;\r
2527     m_pEngine->m_ChangeInfo.wsDelete    = m_wsRange;\r
2528     Param.pEventSink->On_TextChanged(m_pEngine, m_pEngine->m_ChangeInfo);\r
2529     m_pEngine->SetCaretPos(m_nCaret, TRUE);\r
2530     return TRUE;\r
2531 }\r
2532 FX_BOOL CFDE_TxtEdtDoRecord_DeleteRange::Redo()\r
2533 {\r
2534     m_pEngine->Inner_DeleteRange(m_nIndex, m_wsRange.GetLength());\r
2535     if (m_bSel) {\r
2536         m_pEngine->RemoveSelRange(m_nIndex, m_wsRange.GetLength());\r
2537     }\r
2538     FDE_TXTEDTPARAMS& Param = m_pEngine->m_Param;\r
2539     m_pEngine->m_ChangeInfo.nChangeType = FDE_TXTEDT_TEXTCHANGE_TYPE_Insert;\r
2540     m_pEngine->m_ChangeInfo.wsDelete    = m_wsRange;\r
2541     Param.pEventSink->On_TextChanged(m_pEngine, m_pEngine->m_ChangeInfo);\r
2542     m_pEngine->SetCaretPos(m_nIndex, TRUE);\r
2543     return TRUE;\r
2544 }\r
2545 void CFDE_TxtEdtDoRecord_DeleteRange::Serialize(CFX_ByteString &bsDoRecord) const\r
2546 {\r
2547     CFX_ArchiveSaver ArchiveSaver;\r
2548     ArchiveSaver << FX_INT32(FDE_TXTEDT_DORECORD_DEL);\r
2549     ArchiveSaver << (FX_INT32)(FX_UINTPTR)m_pEngine;\r
2550     ArchiveSaver << m_bSel;\r
2551     ArchiveSaver << m_nIndex;\r
2552     ArchiveSaver << m_nCaret;\r
2553     ArchiveSaver << m_wsRange;\r
2554     FX_INT32    nLength         = ArchiveSaver.GetLength();\r
2555     FX_LPCBYTE  lpSrcBuf        = ArchiveSaver.GetBuffer();\r
2556     FX_LPSTR    lpDstBuf        = bsDoRecord.GetBuffer(nLength);\r
2557     FXSYS_memcpy(lpDstBuf, lpSrcBuf, nLength);\r
2558     bsDoRecord.ReleaseBuffer(nLength);\r
2559 }\r
2560 void CFDE_TxtEdtDoRecord_DeleteRange::Deserialize(FX_BSTR bsDoRecord)\r
2561 {\r
2562     CFX_ArchiveLoader ArchiveLoader((FX_LPCBYTE)bsDoRecord.GetCStr(), bsDoRecord.GetLength());\r
2563     FX_INT32 nType = 0;\r
2564     ArchiveLoader >> nType;\r
2565     FXSYS_assert(nType == FDE_TXTEDT_DORECORD_DEL);\r
2566     FX_INT32 nEngine = 0;\r
2567     ArchiveLoader >> nEngine;\r
2568     m_pEngine = (CFDE_TxtEdtEngine*)(FX_UINTPTR)nEngine;\r
2569     ArchiveLoader >> m_bSel;\r
2570     ArchiveLoader >> m_nIndex;\r
2571     ArchiveLoader >> m_nCaret;\r
2572     ArchiveLoader >> m_wsRange;\r
2573 }\r
2574 #ifdef FDE_USEFORMATBLOCK\r
2575 CFDE_TxtEdtDoRecord_FieldInsert::CFDE_TxtEdtDoRecord_FieldInsert(FX_BSTR bsDoRecord)\r
2576 {\r
2577     Deserialize(bsDoRecord);\r
2578 }\r
2579 CFDE_TxtEdtDoRecord_FieldInsert::CFDE_TxtEdtDoRecord_FieldInsert(CFDE_TxtEdtEngine * pEngine,\r
2580         FX_INT32 nCaret,\r
2581         CFDE_TxtEdtField * pField,\r
2582         FX_INT32 nIndexInField,\r
2583         FX_INT32 nFieldBgn,\r
2584         FX_INT32 nOldFieldLength,\r
2585         FX_INT32 nNewFieldLength,\r
2586         const CFX_WideString &wsIns,\r
2587         FX_BOOL bSel )\r
2588     : m_pEngine(pEngine)\r
2589     , m_nCaret(nCaret)\r
2590     , m_pField(pField)\r
2591     , m_nIndexInField(nIndexInField)\r
2592     , m_nFieldBgn(nFieldBgn)\r
2593     , m_nOldFieldLength(nOldFieldLength)\r
2594     , m_nNewFieldLength(nNewFieldLength)\r
2595     , m_wsIns(wsIns)\r
2596     , m_bSel(bSel)\r
2597 {\r
2598     FXSYS_assert(pEngine);\r
2599     FXSYS_assert(pField);\r
2600 }\r
2601 CFDE_TxtEdtDoRecord_FieldInsert::~CFDE_TxtEdtDoRecord_FieldInsert()\r
2602 {\r
2603 }\r
2604 void CFDE_TxtEdtDoRecord_FieldInsert::Release()\r
2605 {\r
2606     delete this;\r
2607 }\r
2608 FX_BOOL CFDE_TxtEdtDoRecord_FieldInsert::Undo()\r
2609 {\r
2610     CFX_WideString wsDel;\r
2611     FX_INT32    nCaret          = 0;\r
2612     FX_BOOL             bBefore = FALSE;\r
2613     FX_INT32 nRet = m_pField->Delete(m_nIndexInField, m_wsIns.GetLength(), wsDel, nCaret, bBefore);\r
2614     FXSYS_assert(nRet != FDE_FORMAT_FIELD_DELETE_RET_F_INVALIDATE && nRet != FDE_FORMAT_FIELD_DELETE_RET_F_BOUNDARY);\r
2615     CFX_WideString wsDisplay;\r
2616     m_pField->GetDisplayText(wsDisplay);\r
2617     m_pEngine->Replace(m_nFieldBgn, m_nNewFieldLength, wsDisplay);\r
2618     m_pEngine->SetCaretPos(m_nCaret, TRUE);\r
2619     return TRUE;\r
2620 }\r
2621 FX_BOOL CFDE_TxtEdtDoRecord_FieldInsert::Redo()\r
2622 {\r
2623     FX_INT32    nCaret  = 0;\r
2624     FX_BOOL             bBefore = FALSE;\r
2625     FX_INT32 nRet = m_pField->Insert(m_nIndexInField, m_wsIns, nCaret, bBefore);\r
2626     FXSYS_assert(nRet != FDE_FORMAT_FIELD_INSERT_RET_F_FULL && nRet != FDE_FORMAT_FIELD_INSERT_RET_F_INVALIDATE);\r
2627     CFX_WideString wsDisplay;\r
2628     m_pField->GetDisplayText(wsDisplay);\r
2629     m_pEngine->Replace(m_nFieldBgn, m_nOldFieldLength, wsDisplay);\r
2630     m_pEngine->SetCaretPos(m_nCaret + m_wsIns.GetLength(), TRUE);\r
2631     return TRUE;\r
2632 }\r
2633 void CFDE_TxtEdtDoRecord_FieldInsert::Serialize(CFX_ByteString &bsDoRecord) const\r
2634 {\r
2635     CFX_ArchiveSaver ArchiveSaver;\r
2636     ArchiveSaver << FX_INT32(FDE_TXTEDT_DORECORD_FORMATINS);\r
2637     ArchiveSaver << FX_INT32(m_pEngine);\r
2638     ArchiveSaver << m_nCaret;\r
2639     ArchiveSaver << FX_INT32(m_pField);\r
2640     ArchiveSaver << m_nIndexInField;\r
2641     ArchiveSaver << m_nFieldBgn;\r
2642     ArchiveSaver << m_nOldFieldLength;\r
2643     ArchiveSaver << m_nNewFieldLength;\r
2644     ArchiveSaver << m_wsIns;\r
2645     ArchiveSaver << m_bSel;\r
2646     FX_INT32    nLength         = ArchiveSaver.GetLength();\r
2647     FX_LPCBYTE  lpSrcBuf        = ArchiveSaver.GetBuffer();\r
2648     FX_LPSTR    lpDstBuf        = bsDoRecord.GetBuffer(nLength);\r
2649     FXSYS_memcpy(lpDstBuf, lpSrcBuf, nLength);\r
2650     bsDoRecord.ReleaseBuffer(nLength);\r
2651 }\r
2652 void CFDE_TxtEdtDoRecord_FieldInsert::Deserialize(FX_BSTR bsDoRecord)\r
2653 {\r
2654     CFX_ArchiveLoader ArchiveLoader((FX_LPCBYTE)bsDoRecord.GetCStr(), bsDoRecord.GetLength());\r
2655     FX_INT32 nType = 0;\r
2656     ArchiveLoader >> nType;\r
2657     FXSYS_assert(nType == FDE_TXTEDT_DORECORD_FORMATINS);\r
2658     FX_INT32 nEngine = 0;\r
2659     ArchiveLoader >> nEngine;\r
2660     m_pEngine = (CFDE_TxtEdtEngine*)(FX_UINTPTR)nEngine;\r
2661     ArchiveLoader >> m_nCaret;\r
2662     FX_INT32 nField = 0;\r
2663     ArchiveLoader >> nField;\r
2664     m_pField = (CFDE_TxtEdtField*)nField;\r
2665     ArchiveLoader >> m_nIndexInField;\r
2666     ArchiveLoader >> m_nFieldBgn;\r
2667     ArchiveLoader >> m_nOldFieldLength;\r
2668     ArchiveLoader >> m_nNewFieldLength;\r
2669     ArchiveLoader >> m_wsIns;\r
2670     ArchiveLoader >> m_bSel;\r
2671 }\r
2672 CFDE_TxtEdtDoRecord_FieldDelete::CFDE_TxtEdtDoRecord_FieldDelete(FX_BSTR bsDoRecord)\r
2673 {\r
2674     Deserialize(bsDoRecord);\r
2675 }\r
2676 CFDE_TxtEdtDoRecord_FieldDelete::CFDE_TxtEdtDoRecord_FieldDelete(CFDE_TxtEdtEngine * pEngine,\r
2677         FX_INT32 nCaret,\r
2678         CFDE_TxtEdtField * pField,\r
2679         FX_INT32 nIndexInField,\r
2680         FX_INT32 nFieldBgn,\r
2681         FX_INT32 nOldLength,\r
2682         FX_INT32 nNewLength,\r
2683         const CFX_WideString &wsDel,\r
2684         FX_BOOL bSel )\r
2685     : m_pEngine(pEngine)\r
2686     , m_nCaret(nCaret)\r
2687     , m_pField(pField)\r
2688     , m_nIndexInField(nIndexInField)\r
2689     , m_nFieldBgn(nFieldBgn)\r
2690     , m_nOldFieldLength(nOldLength)\r
2691     , m_nNewFieldLength(nNewLength)\r
2692     , m_wsDel(wsDel)\r
2693     , m_bSel(bSel)\r
2694 {\r
2695     FXSYS_assert(m_pEngine);\r
2696     FXSYS_assert(m_pField);\r
2697 }\r
2698 CFDE_TxtEdtDoRecord_FieldDelete::~CFDE_TxtEdtDoRecord_FieldDelete()\r
2699 {\r
2700 }\r
2701 void CFDE_TxtEdtDoRecord_FieldDelete::Release()\r
2702 {\r
2703     delete this;\r
2704 }\r
2705 FX_BOOL CFDE_TxtEdtDoRecord_FieldDelete::Undo()\r
2706 {\r
2707     FX_INT32    nCaret  = 0;\r
2708     FX_BOOL             bBefore = FALSE;\r
2709     FX_INT32  nRet = m_pField->Insert(m_nIndexInField, m_wsDel, nCaret, bBefore);\r
2710     FXSYS_assert(nRet != FDE_FORMAT_FIELD_INSERT_RET_F_FULL && nRet != FDE_FORMAT_FIELD_INSERT_RET_F_INVALIDATE);\r
2711     CFX_WideString wsDisplay;\r
2712     m_pField->GetDisplayText(wsDisplay);\r
2713     m_pEngine->Replace(m_nFieldBgn, m_nNewFieldLength, wsDisplay);\r
2714     m_pEngine->SetCaretPos(m_nCaret, TRUE);\r
2715     return TRUE;\r
2716 }\r
2717 FX_BOOL CFDE_TxtEdtDoRecord_FieldDelete::Redo()\r
2718 {\r
2719     FX_INT32    nCaret  = 0;\r
2720     FX_BOOL             bBefore = 0;\r
2721     CFX_WideString wsDel;\r
2722     FX_INT32 nRet = m_pField->Delete(m_nIndexInField, m_wsDel.GetLength(), wsDel, nCaret, bBefore);\r
2723     FXSYS_assert(nRet != FDE_FORMAT_FIELD_DELETE_RET_F_INVALIDATE && nRet != FDE_FORMAT_FIELD_DELETE_RET_F_BOUNDARY);\r
2724     CFX_WideString wsDisplay;\r
2725     m_pField->GetDisplayText(wsDisplay);\r
2726     m_pEngine->Replace(m_nFieldBgn, m_nOldFieldLength, wsDisplay);\r
2727     m_pEngine->SetCaretPos(m_nCaret - m_wsDel.GetLength(), TRUE);\r
2728     return TRUE;\r
2729 }\r
2730 void CFDE_TxtEdtDoRecord_FieldDelete::Serialize(CFX_ByteString &bsDoRecord) const\r
2731 {\r
2732     CFX_ArchiveSaver ArchiveSaver;\r
2733     ArchiveSaver << FX_INT32(FDE_TXTEDT_DORECORD_FORMATDEL);\r
2734     ArchiveSaver << FX_INT32(m_pEngine);\r
2735     ArchiveSaver << m_nCaret;\r
2736     ArchiveSaver << FX_INT32(m_pField);\r
2737     ArchiveSaver << m_nIndexInField;\r
2738     ArchiveSaver << m_nFieldBgn;\r
2739     ArchiveSaver << m_nOldFieldLength;\r
2740     ArchiveSaver << m_nNewFieldLength;\r
2741     ArchiveSaver << m_wsDel;\r
2742     ArchiveSaver << m_bSel;\r
2743     FX_INT32    nLength         = ArchiveSaver.GetLength();\r
2744     FX_LPCBYTE  lpSrcBuf        = ArchiveSaver.GetBuffer();\r
2745     FX_LPSTR    lpDstBuf        = bsDoRecord.GetBuffer(nLength);\r
2746     FXSYS_memcpy(lpDstBuf, lpSrcBuf, nLength);\r
2747     bsDoRecord.ReleaseBuffer(nLength);\r
2748 }\r
2749 void CFDE_TxtEdtDoRecord_FieldDelete::Deserialize(FX_BSTR bsDoRecord)\r
2750 {\r
2751     CFX_ArchiveLoader ArchiveLoader((FX_LPCBYTE)bsDoRecord.GetCStr(), bsDoRecord.GetLength());\r
2752     FX_INT32 nType = 0;\r
2753     ArchiveLoader >> nType;\r
2754     FXSYS_assert(nType == FDE_TXTEDT_DORECORD_FORMATDEL);\r
2755     FX_INT32 nEngine = 0;\r
2756     ArchiveLoader >> nEngine;\r
2757     m_pEngine = (CFDE_TxtEdtEngine*)(FX_UINTPTR)nEngine;\r
2758     ArchiveLoader >> m_nCaret;\r
2759     FX_INT32 nField = 0;\r
2760     ArchiveLoader >> nField;\r
2761     m_pField = (CFDE_TxtEdtField*)nField;\r
2762     ArchiveLoader >> m_nIndexInField;\r
2763     ArchiveLoader >> m_nFieldBgn;\r
2764     ArchiveLoader >> m_nOldFieldLength;\r
2765     ArchiveLoader >> m_nNewFieldLength;\r
2766     ArchiveLoader >> m_wsDel;\r
2767     ArchiveLoader >> m_bSel;\r
2768 }\r
2769 CFDE_TxtEdtDoRecord_FieldReplace::CFDE_TxtEdtDoRecord_FieldReplace(FX_BSTR bsDoRecord)\r
2770 {\r
2771     Deserialize(bsDoRecord);\r
2772 }\r
2773 CFDE_TxtEdtDoRecord_FieldReplace::CFDE_TxtEdtDoRecord_FieldReplace(     CFDE_TxtEdtEngine * pEngine,\r
2774         FX_INT32 nCaret,\r
2775         FX_INT32 nNewCaret,\r
2776         CFDE_TxtEdtField * pField,\r
2777         FX_INT32        nIndexInField,\r
2778         FX_INT32        nFieldBgn,\r
2779         FX_INT32        nFieldNewLength,\r
2780         const CFX_WideString &wsDel,\r
2781         const CFX_WideString &wsIns,\r
2782         FX_BOOL bSel)\r
2783     : m_pEngine(pEngine)\r
2784     , m_nCaret(nCaret)\r
2785     , m_nNewCaret(nNewCaret)\r
2786     , m_pField(pField)\r
2787     , m_nIndexInField(nIndexInField)\r
2788     , m_nFieldBgn(nFieldBgn)\r
2789     , m_nFieldNewLength(nFieldNewLength)\r
2790     , m_wsDel(wsDel)\r
2791     , m_wsIns(wsIns)\r
2792     , m_bSel(bSel)\r
2793 {\r
2794     FXSYS_assert(m_pEngine);\r
2795     FXSYS_assert(m_pField);\r
2796 }\r
2797 CFDE_TxtEdtDoRecord_FieldReplace::~CFDE_TxtEdtDoRecord_FieldReplace()\r
2798 {\r
2799 }\r
2800 void CFDE_TxtEdtDoRecord_FieldReplace::Release()\r
2801 {\r
2802     delete this;\r
2803 }\r
2804 FX_BOOL CFDE_TxtEdtDoRecord_FieldReplace::Undo()\r
2805 {\r
2806     CFX_WideString wsDel;\r
2807     FX_INT32    nCaret  = 0;\r
2808     FX_BOOL             bBefore = FALSE;\r
2809     FX_INT32    nRet    = m_pField->Replace(m_nIndexInField, m_wsIns.GetLength(), m_wsDel, wsDel, nCaret, bBefore);\r
2810     FXSYS_assert(nRet != FDE_FORMAT_FIELD_DELETE_RET_F_INVALIDATE && nRet != FDE_FORMAT_FIELD_DELETE_RET_F_BOUNDARY);\r
2811     CFX_WideString wsDisplay;\r
2812     m_pField->GetDisplayText(wsDisplay);\r
2813     m_pEngine->Replace(m_nFieldBgn, m_nFieldNewLength, wsDisplay);\r
2814     m_pEngine->SetCaretPos(m_nCaret, TRUE);\r
2815     return TRUE;\r
2816 }\r
2817 FX_BOOL CFDE_TxtEdtDoRecord_FieldReplace::Redo()\r
2818 {\r
2819     CFX_WideString wsDel;\r
2820     FX_INT32    nCaret  = 0;\r
2821     FX_BOOL             bBefore = FALSE;\r
2822     FX_INT32    nRet    = m_pField->Replace(m_nIndexInField, m_wsDel.GetLength(), m_wsIns, wsDel, nCaret, bBefore);\r
2823     FXSYS_assert(nRet != FDE_FORMAT_FIELD_DELETE_RET_F_INVALIDATE && nRet != FDE_FORMAT_FIELD_DELETE_RET_F_BOUNDARY);\r
2824     CFX_WideString wsDisplay;\r
2825     m_pField->GetDisplayText(wsDisplay);\r
2826     m_pEngine->Replace(m_nFieldBgn, m_nFieldNewLength, wsDisplay);\r
2827     m_pEngine->SetCaretPos(m_nNewCaret, TRUE);\r
2828     return TRUE;\r
2829 }\r
2830 void CFDE_TxtEdtDoRecord_FieldReplace::Serialize(CFX_ByteString &bsDoRecord) const\r
2831 {\r
2832     CFX_ArchiveSaver ArchiveSaver;\r
2833     ArchiveSaver << FX_INT32(FDE_TXTEDT_DORECORD_FORMATREP);\r
2834     ArchiveSaver << FX_INT32(m_pEngine);\r
2835     ArchiveSaver << m_nCaret;\r
2836     ArchiveSaver << m_nNewCaret;\r
2837     ArchiveSaver << FX_INT32(m_pField);\r
2838     ArchiveSaver << m_nIndexInField;\r
2839     ArchiveSaver << m_nFieldBgn;\r
2840     ArchiveSaver << m_nFieldNewLength;\r
2841     ArchiveSaver << m_wsDel;\r
2842     ArchiveSaver << m_wsIns;\r
2843     ArchiveSaver << m_bSel;\r
2844     FX_INT32    nLength         = ArchiveSaver.GetLength();\r
2845     FX_LPCBYTE  lpSrcBuf        = ArchiveSaver.GetBuffer();\r
2846     FX_LPSTR    lpDstBuf        = bsDoRecord.GetBuffer(nLength);\r
2847     FXSYS_memcpy(lpDstBuf, lpSrcBuf, nLength);\r
2848     bsDoRecord.ReleaseBuffer(nLength);\r
2849 }\r
2850 void CFDE_TxtEdtDoRecord_FieldReplace::Deserialize(FX_BSTR bsDoRecord)\r
2851 {\r
2852     CFX_ArchiveLoader ArchiveLoader((FX_LPCBYTE)bsDoRecord.GetCStr(), bsDoRecord.GetLength());\r
2853     FX_INT32 nType = 0;\r
2854     ArchiveLoader >> nType;\r
2855     FXSYS_assert(nType == FDE_TXTEDT_DORECORD_FORMATREP);\r
2856     FX_INT32 nEngine = 0;\r
2857     ArchiveLoader >> nEngine;\r
2858     m_pEngine = (CFDE_TxtEdtEngine*)(FX_UINTPTR)nEngine;\r
2859     ArchiveLoader >> m_nCaret;\r
2860     ArchiveLoader >> m_nNewCaret;\r
2861     FX_INT32 nField = 0;\r
2862     ArchiveLoader >> nField;\r
2863     m_pField = (CFDE_TxtEdtField*)nField;\r
2864     ArchiveLoader >> m_nIndexInField;\r
2865     ArchiveLoader >> m_nFieldBgn;\r
2866     ArchiveLoader >> m_nFieldNewLength;\r
2867     ArchiveLoader >> m_wsDel;\r
2868     ArchiveLoader >> m_wsIns;\r
2869     ArchiveLoader >> m_bSel;\r
2870 }\r
2871 #endif\r