1 /************************************************************************/
2 /* */
3 /* Manage lines in a paragraph. */
4 /* */
5 /************************************************************************/
6
7 # include "docBufConfig.h"
8
9 # include <stdlib.h>
10
11 # include <appDebugon.h>
12
13 # include "docBuf.h"
14 # include "docParaParticules.h"
15 # include "docDebug.h"
16
17 /************************************************************************/
18 /* */
19 /* Remember about a line in a Text Item. */
20 /* */
21 /************************************************************************/
22
docInsertTextLine(BufferItem * bi,int line)23 TextLine * docInsertTextLine( BufferItem * bi,
24 int line )
25 {
26 TextLine * tl;
27 int newSize;
28
29 if ( bi->biParaLineCount % 10 )
30 { newSize= bi->biParaLineCount+ 1; }
31 else{ newSize= bi->biParaLineCount+ 11; }
32
33 newSize *= sizeof(TextLine);
34
35 tl= (TextLine *)realloc( bi->biParaLines, newSize );
36 if ( ! tl )
37 { LXDEB(bi->biParaLineCount,tl); return (TextLine *)0; }
38 bi->biParaLines= tl;
39
40 if ( line == -1 )
41 { line= bi->biParaLineCount; }
42 else{
43 int i;
44
45 for ( i= bi->biParaLineCount; i > line; i-- )
46 { tl[i]= tl[i-1]; }
47 }
48
49 tl += line;
50
51 docInitTextLine( tl );
52
53 bi->biParaLineCount++;
54 return tl;
55 }
56
57 /************************************************************************/
58 /* */
59 /* Find the line number for a certain string offset in the paragraph. */
60 /* */
61 /* NOTE: This does not expect the paragraph to be formatted. We just */
62 /* fail because there are no lines. We do not crash however. */
63 /* */
64 /************************************************************************/
65
docFindLineOfPosition(int * pLine,int * pFlags,const DocumentPosition * dp,int lastOne)66 int docFindLineOfPosition( int * pLine,
67 int * pFlags,
68 const DocumentPosition * dp,
69 int lastOne )
70 {
71 const BufferItem * paraNode= dp->dpNode;
72 const int stroff= dp->dpStroff;
73
74 int l= 0;
75 int r= paraNode->biParaLineCount;
76 int m= ( l+ r )/ 2;
77
78 const TextLine * tl= paraNode->biParaLines+ m;
79 const int paraStrlen= docParaStrlen( paraNode );
80
81 if ( r <= 0 )
82 { LSDEB(r,docTreeTypeStr(paraNode->biTreeType)); return -1; }
83 if ( stroff < 0 || stroff > paraStrlen )
84 { LDEB(stroff); return -1; }
85
86 switch( lastOne )
87 {
88 case PARAfindPAST:
89 if ( stroff == paraStrlen )
90 {
91 *pLine= paraNode->biParaLineCount;
92 if ( pFlags )
93 {
94 *pFlags= POSflagPARA_TAIL;
95
96 if ( stroff == 0 )
97 { *pFlags |= POSflagPARA_HEAD; }
98 }
99 return 0;
100 }
101
102 /*FALLTHROUGH*/
103 case PARAfindLAST:
104 /* Binary search for last: tl->tlStroff <= stroff */
105 while( l < m )
106 {
107 if ( tl->tlStroff <= stroff )
108 { l= m; }
109 else{ r= m; }
110
111 m= ( l+ r )/ 2; tl= paraNode->biParaLines+ m;
112 }
113
114 if ( stroff < tl->tlStroff )
115 { m--; }
116 break;
117
118 case PARAfindFIRST:
119 /* Binary search for first: tl->tlStroff+ tl->tlStrlen >= stroff */
120 while( l < m )
121 {
122 if ( tl->tlStroff+ tl->tlStrlen < stroff )
123 { l= m; }
124 else{ r= m; }
125
126 m= ( l+ r )/ 2; tl= paraNode->biParaLines+ m;
127 }
128
129 if ( stroff > tl->tlStroff+ tl->tlStrlen )
130 { m++; }
131 break;
132
133 default:
134 LDEB(lastOne); return -1;
135 }
136
137 if ( m < 0 || m >= paraNode->biParaLineCount )
138 {
139 const int checkGeometry= 0;
140
141 LLLLDEB(stroff,m,lastOne,paraNode->biParaLineCount);
142 docListNode( 0, paraNode, checkGeometry );
143 return -1;
144 }
145
146 *pLine= m;
147
148 if ( pFlags )
149 {
150 const TextLine * tl= paraNode->biParaLines+ m;
151
152 *pFlags= 0;
153
154 if ( stroff == tl->tlStroff )
155 { *pFlags |= POSflagLINE_HEAD; }
156 if ( stroff == tl->tlStroff+ tl->tlStrlen )
157 { *pFlags |= POSflagLINE_TAIL; }
158
159 if ( stroff == 0 )
160 { *pFlags |= POSflagPARA_HEAD; }
161 if ( stroff == paraStrlen )
162 { *pFlags |= POSflagPARA_TAIL; }
163 }
164
165 return 0;
166 }
167
168