1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_i18npool.hxx"
26
27 #include <com/sun/star/i18n/CharacterIteratorMode.hpp>
28 #include <breakiterator_ctl.hxx>
29
30 #include <string.h> // for memset
31
32 using namespace ::com::sun::star::uno;
33 using namespace ::com::sun::star::lang;
34 using namespace ::rtl;
35
36 namespace com { namespace sun { namespace star { namespace i18n {
37
38 /**
39 * Constructor.
40 */
BreakIterator_CTL()41 BreakIterator_CTL::BreakIterator_CTL() :
42 cachedText(),
43 nextCellIndex( NULL ),
44 previousCellIndex( NULL ),
45 cellIndexSize( 512 )
46 {
47 cBreakIterator = "com.sun.star.i18n.BreakIterator_CTL";
48 // to improve performance, alloc big enough memory in construct.
49 nextCellIndex = (sal_Int32*) calloc(cellIndexSize, sizeof(sal_Int32));
50 previousCellIndex = (sal_Int32*) calloc(cellIndexSize, sizeof(sal_Int32));
51 memset(nextCellIndex, 0, cellIndexSize * sizeof(sal_Int32));
52 }
53
54 /**
55 * Deconstructor.
56 */
~BreakIterator_CTL()57 BreakIterator_CTL::~BreakIterator_CTL()
58 {
59 free(nextCellIndex);
60 free(previousCellIndex);
61 }
62
previousCharacters(const OUString & Text,sal_Int32 nStartPos,const lang::Locale & rLocale,sal_Int16 nCharacterIteratorMode,sal_Int32 nCount,sal_Int32 & nDone)63 sal_Int32 SAL_CALL BreakIterator_CTL::previousCharacters( const OUString& Text,
64 sal_Int32 nStartPos, const lang::Locale& rLocale,
65 sal_Int16 nCharacterIteratorMode, sal_Int32 nCount, sal_Int32& nDone )
66 throw(RuntimeException)
67 {
68 if (nCharacterIteratorMode == CharacterIteratorMode::SKIPCELL ) {
69 nDone = 0;
70 if (nStartPos > 0) { // for others to skip cell.
71 makeIndex(Text, nStartPos);
72
73 if (nextCellIndex[nStartPos-1] == 0) // not a CTL character
74 return BreakIterator_Unicode::previousCharacters(Text, nStartPos, rLocale,
75 nCharacterIteratorMode, nCount, nDone);
76 else while (nCount > 0 && nextCellIndex[nStartPos - 1] > 0) {
77 nCount--; nDone++;
78 nStartPos = previousCellIndex[nStartPos - 1];
79 }
80 } else
81 nStartPos = 0;
82 } else { // for BS to delete one char.
83 nDone = (nStartPos > nCount) ? nCount : nStartPos;
84 nStartPos -= nDone;
85 }
86
87 return nStartPos;
88 }
89
nextCharacters(const OUString & Text,sal_Int32 nStartPos,const lang::Locale & rLocale,sal_Int16 nCharacterIteratorMode,sal_Int32 nCount,sal_Int32 & nDone)90 sal_Int32 SAL_CALL BreakIterator_CTL::nextCharacters(const OUString& Text,
91 sal_Int32 nStartPos, const lang::Locale& rLocale,
92 sal_Int16 nCharacterIteratorMode, sal_Int32 nCount, sal_Int32& nDone)
93 throw(RuntimeException)
94 {
95 sal_Int32 len = Text.getLength();
96 if (nCharacterIteratorMode == CharacterIteratorMode::SKIPCELL ) {
97 nDone = 0;
98 if (nStartPos < len) {
99 makeIndex(Text, nStartPos);
100
101 if (nextCellIndex[nStartPos] == 0) // not a CTL character
102 return BreakIterator_Unicode::nextCharacters(Text, nStartPos, rLocale,
103 nCharacterIteratorMode, nCount, nDone);
104 else while (nCount > 0 && nextCellIndex[nStartPos] > 0) {
105 nCount--; nDone++;
106 nStartPos = nextCellIndex[nStartPos];
107 }
108 } else
109 nStartPos = len;
110 } else {
111 nDone = (len - nStartPos > nCount) ? nCount : len - nStartPos;
112 nStartPos += nDone;
113 }
114
115 return nStartPos;
116 }
117
118 // This method should be overwritten by derived language specific class.
makeIndex(const OUString &,sal_Int32)119 void SAL_CALL BreakIterator_CTL::makeIndex(const OUString& /*text*/, sal_Int32 /*pos*/)
120 throw(RuntimeException)
121 {
122 throw RuntimeException();
123 }
124
125 // Make sure line is broken on cell boundary if we implement cell iterator.
getLineBreak(const OUString & Text,sal_Int32 nStartPos,const lang::Locale & rLocale,sal_Int32 nMinBreakPos,const LineBreakHyphenationOptions & hOptions,const LineBreakUserOptions & bOptions)126 LineBreakResults SAL_CALL BreakIterator_CTL::getLineBreak(
127 const OUString& Text, sal_Int32 nStartPos,
128 const lang::Locale& rLocale, sal_Int32 nMinBreakPos,
129 const LineBreakHyphenationOptions& hOptions,
130 const LineBreakUserOptions& bOptions ) throw(RuntimeException)
131 {
132 LineBreakResults lbr = BreakIterator_Unicode::getLineBreak(Text, nStartPos,
133 rLocale, nMinBreakPos, hOptions, bOptions );
134 if (lbr.breakIndex < Text.getLength()) {
135 makeIndex(Text, lbr.breakIndex);
136 lbr.breakIndex = previousCellIndex[ lbr.breakIndex ];
137 }
138 return lbr;
139 }
140
141 } } } }
142