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