1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_i18npool.hxx"
30 
31 #include <com/sun/star/i18n/CharacterIteratorMode.hpp>
32 #include <breakiterator_ctl.hxx>
33 
34 #include <string.h>	// for memset
35 
36 using namespace ::com::sun::star::uno;
37 using namespace ::com::sun::star::lang;
38 using namespace ::rtl;
39 
40 namespace com { namespace sun { namespace star { namespace i18n {
41 
42 /**
43  * Constructor.
44  */
45 BreakIterator_CTL::BreakIterator_CTL() :
46     cachedText(),
47     nextCellIndex( NULL ),
48     previousCellIndex( NULL ),
49     cellIndexSize( 512 )
50 {
51 	cBreakIterator = "com.sun.star.i18n.BreakIterator_CTL";
52 	// to improve performance, alloc big enough memory in construct.
53 	nextCellIndex = (sal_Int32*) calloc(cellIndexSize, sizeof(sal_Int32));
54 	previousCellIndex = (sal_Int32*) calloc(cellIndexSize, sizeof(sal_Int32));
55 	memset(nextCellIndex, 0, cellIndexSize * sizeof(sal_Int32));
56 }
57 
58 /**
59  * Deconstructor.
60  */
61 BreakIterator_CTL::~BreakIterator_CTL()
62 {
63 	free(nextCellIndex);
64 	free(previousCellIndex);
65 }
66 
67 sal_Int32 SAL_CALL BreakIterator_CTL::previousCharacters( const OUString& Text,
68 	sal_Int32 nStartPos, const lang::Locale& rLocale,
69 	sal_Int16 nCharacterIteratorMode, sal_Int32 nCount, sal_Int32& nDone )
70 	throw(RuntimeException)
71 {
72 	if (nCharacterIteratorMode == CharacterIteratorMode::SKIPCELL ) {
73 	    nDone = 0;
74 	    if (nStartPos > 0) { 	// for others to skip cell.
75 		makeIndex(Text, nStartPos);
76 
77 		if (nextCellIndex[nStartPos-1] == 0) // not a CTL character
78 		    return BreakIterator_Unicode::previousCharacters(Text, nStartPos, rLocale,
79 				nCharacterIteratorMode, nCount, nDone);
80 		else while (nCount > 0 && nextCellIndex[nStartPos - 1] > 0) {
81 		    nCount--; nDone++;
82 		    nStartPos = previousCellIndex[nStartPos - 1];
83 		}
84 	    } else
85 		nStartPos = 0;
86 	} else { // for BS to delete one char.
87 	    nDone = (nStartPos > nCount) ? nCount : nStartPos;
88 	    nStartPos -= nDone;
89 	}
90 
91 	return nStartPos;
92 }
93 
94 sal_Int32 SAL_CALL BreakIterator_CTL::nextCharacters(const OUString& Text,
95 	sal_Int32 nStartPos, const lang::Locale& rLocale,
96 	sal_Int16 nCharacterIteratorMode, sal_Int32 nCount, sal_Int32& nDone)
97 	throw(RuntimeException)
98 {
99 	sal_Int32 len = Text.getLength();
100 	if (nCharacterIteratorMode == CharacterIteratorMode::SKIPCELL ) {
101 	    nDone = 0;
102 	    if (nStartPos < len) {
103 		makeIndex(Text, nStartPos);
104 
105 		if (nextCellIndex[nStartPos] == 0) // not a CTL character
106 		    return BreakIterator_Unicode::nextCharacters(Text, nStartPos, rLocale,
107 				nCharacterIteratorMode, nCount, nDone);
108 		else while (nCount > 0 && nextCellIndex[nStartPos] > 0) {
109 		    nCount--; nDone++;
110 		    nStartPos = nextCellIndex[nStartPos];
111 		}
112 	    } else
113 		nStartPos = len;
114 	} else {
115 	    nDone = (len - nStartPos > nCount) ? nCount : len - nStartPos;
116 	    nStartPos += nDone;
117 	}
118 
119 	return nStartPos;
120 }
121 
122 // This method should be overwritten by derived language specific class.
123 void SAL_CALL BreakIterator_CTL::makeIndex(const OUString& /*text*/, sal_Int32 /*pos*/)
124 	throw(RuntimeException)
125 {
126 	throw RuntimeException();
127 }
128 
129 // Make sure line is broken on cell boundary if we implement cell iterator.
130 LineBreakResults SAL_CALL BreakIterator_CTL::getLineBreak(
131 	const OUString& Text, sal_Int32 nStartPos,
132 	const lang::Locale& rLocale, sal_Int32 nMinBreakPos,
133 	const LineBreakHyphenationOptions& hOptions,
134 	const LineBreakUserOptions& bOptions ) throw(RuntimeException)
135 {
136 	LineBreakResults lbr = BreakIterator_Unicode::getLineBreak(Text, nStartPos,
137 					rLocale, nMinBreakPos, hOptions, bOptions );
138     if (lbr.breakIndex < Text.getLength()) {
139         makeIndex(Text, lbr.breakIndex);
140         lbr.breakIndex = previousCellIndex[ lbr.breakIndex ];
141     }
142 	return lbr;
143 }
144 
145 } } } }
146