1 /************************************************************************/
2 /*									*/
3 /*  Get/Move/Set Selections.						*/
4 /*									*/
5 /************************************************************************/
6 
7 #   include	"docBufConfig.h"
8 
9 #   include	<appDebugon.h>
10 
11 #   include	"docBuf.h"
12 #   include	"docNodeTree.h"
13 #   include	"docDebug.h"
14 #   include	"docParaString.h"
15 #   include	"docParaParticules.h"
16 
17 /************************************************************************/
18 /*									*/
19 /*  Move to the first/last position.					*/
20 /*									*/
21 /************************************************************************/
22 
docGotoFirstPosition(DocumentPosition * dp,BufferItem * node)23 int docGotoFirstPosition(	DocumentPosition *	dp,
24 				BufferItem *		node )
25     {
26     while( node )
27 	{
28 	if  ( node->biLevel == DOClevPARA )
29 	    {
30 	    docSetDocumentPosition( dp, node, docParaFirstStroff( node ) );
31 	    return 0;
32 	    }
33 
34 	if  ( node->biChildCount == 0 )
35 	    { /*LDEB(node->biChildCount);*/ return -1;	}
36 
37 	node= node->biChildren[0];
38 	}
39 
40     /*XDEB(node);*/ return -1;
41     }
42 
docHeadPosition(DocumentPosition * dp,BufferItem * node)43 int docHeadPosition(	DocumentPosition *	dp,
44 			BufferItem *		node )
45     {
46     while( node )
47 	{
48 	if  ( node->biLevel == DOClevPARA )
49 	    {
50 	    docSetDocumentPosition( dp, node, 0 );
51 	    return 0;
52 	    }
53 
54 	if  ( node->biChildCount == 0 )
55 	    { /*LDEB(node->biChildCount);*/ return -1;	}
56 
57 	node= node->biChildren[0];
58 	}
59 
60     /*XDEB(node);*/ return -1;
61     }
62 
docGotoLastPosition(DocumentPosition * dp,BufferItem * node)63 int docGotoLastPosition(	DocumentPosition *	dp,
64 				BufferItem *		node )
65     {
66     while( node )
67 	{
68 	if  ( node->biLevel == DOClevPARA )
69 	    {
70 	    docSetDocumentPosition( dp, node, docParaLastStroff( node ) );
71 	    return 0;
72 	    }
73 
74 	if  ( node->biChildCount == 0 )
75 	    { /*LDEB(node->biChildCount);*/ return -1;	}
76 
77 	node= node->biChildren[node->biChildCount- 1];
78 	}
79 
80     /*XDEB(node);*/ return -1;
81     }
82 
docTailPosition(DocumentPosition * dp,BufferItem * node)83 int docTailPosition(	DocumentPosition *	dp,
84 			BufferItem *		node )
85     {
86     while( node )
87 	{
88 	if  ( node->biLevel == DOClevPARA )
89 	    {
90 	    docSetDocumentPosition( dp, node, docParaStrlen( node ) );
91 	    return 0;
92 	    }
93 
94 	if  ( node->biChildCount == 0 )
95 	    { /*LDEB(node->biChildCount);*/ return -1;	}
96 
97 	node= node->biChildren[node->biChildCount- 1];
98 	}
99 
100     /*XDEB(node);*/ return -1;
101     }
102 
docDocumentHead(DocumentPosition * dp,BufferDocument * bd)103 int docDocumentHead(	DocumentPosition *	dp,
104 			BufferDocument *	bd )
105     {
106     if  ( docHeadPosition( dp, bd->bdBody.dtRoot ) )
107 	{ return -1;	}
108 
109     return 0;
110     }
111 
docDocumentTail(DocumentPosition * dp,BufferDocument * bd)112 int docDocumentTail(	DocumentPosition *	dp,
113 				BufferDocument *	bd )
114     {
115     if  ( docTailPosition( dp, bd->bdBody.dtRoot ) )
116 	{ return -1;	}
117 
118     return 0;
119     }
120 
121 /************************************************************************/
122 /*									*/
123 /*  Keep out the read-only field at the Head of certain kinds of	*/
124 /*  paragraphs.								*/
125 /*									*/
126 /************************************************************************/
127 
docAvoidParaHeadField(DocumentPosition * dp,int * pPart,const BufferDocument * bd)128 void docAvoidParaHeadField(	DocumentPosition *	dp,
129 				int *			pPart,
130 				const BufferDocument *	bd )
131     {
132     DocumentField *	dfHead= (DocumentField *)0;
133     DocumentSelection	dsInsideHead;
134     DocumentSelection	dsAroundHead;
135     int			partBegin= -1;
136     int			partEnd= -1;
137 
138     int	fieldKind= docParaHeadFieldKind( dp->dpNode, bd );
139     if  ( fieldKind < 0 )
140 	{ return;	}
141 
142     if  ( docDelimitParaHeadField( &dfHead, &dsInsideHead, &dsAroundHead,
143 					&partBegin, &partEnd, dp->dpNode, bd ) )
144 	{ LDEB(1);	}
145     else{
146 	if  ( dp->dpStroff < dsAroundHead.dsTail.dpStroff )
147 	    { dp->dpStroff=  dsAroundHead.dsTail.dpStroff;	}
148 
149 	if  ( pPart && *pPart <= partBegin )
150 	    { *pPart= partBegin+ 1;	}
151 	}
152 
153     return;
154     }
155 
156 /************************************************************************/
157 /*									*/
158 /*  Move to the next/previous position.					*/
159 /*									*/
160 /************************************************************************/
161 
162 # define docIsMergedCell( node ) ( \
163     (node)->biParent && \
164     docIsRowNode( (node)->biParent ) && \
165     (node)->biNumberInParent < (node)->biParent->biRowCellCount && \
166     CELL_MERGED( &( (node)->biParent->biRowCells[(node)->biNumberInParent] ) ) )
167 
docNextNode(BufferItem * node,int level)168 static BufferItem * docNextNode(	BufferItem *	node,
169 					int		level )
170     {
171     for (;;)
172 	{
173 	if  ( ! node->biParent )
174 	    { return (BufferItem *)0;	}
175 
176 	if  ( node->biNumberInParent < node->biParent->biChildCount- 1 )
177 	    {
178 	    node= node->biParent->biChildren[node->biNumberInParent+ 1];
179 
180 	    if  ( docIsMergedCell( node ) )
181 		{ continue;	}
182 
183 	    while( node->biLevel < level	&&
184 		   node->biChildCount > 0	)
185 		{
186 		node= node->biChildren[0];
187 
188 		if  ( docIsMergedCell( node ) )
189 		    { break; }
190 		}
191 
192 	    if  ( docIsMergedCell( node ) )
193 		{ continue; }
194 
195 	    if  ( node->biLevel == level )
196 		{ return node;	}
197 	    }
198 	else{ node= node->biParent;	}
199 	}
200     }
201 
docNextParagraph(BufferItem * node)202 BufferItem *	docNextParagraph(	BufferItem *	node )
203     { return docNextNode( node, DOClevPARA );	}
204 
docNextSection(BufferItem * node)205 BufferItem *	docNextSection(	BufferItem *	node )
206     { return docNextNode( node, DOClevSECT );	}
207 
docPrevNode(BufferItem * node,int level)208 static BufferItem * docPrevNode(	BufferItem *	node,
209 					int		level )
210     {
211     for (;;)
212 	{
213 	if  ( ! node->biParent )
214 	    { return (BufferItem *)0;	}
215 
216 	if  ( node->biNumberInParent > 0 )
217 	    {
218 	    node= node->biParent->biChildren[node->biNumberInParent- 1];
219 
220 	    if  ( docIsMergedCell( node ) )
221 		{ continue;	}
222 
223 	    while( node->biLevel < level	&&
224 		   node->biChildCount > 0	)
225 		{
226 		node= node->biChildren[node->biChildCount- 1];
227 
228 		if  ( docIsMergedCell( node ) )
229 		    { break; }
230 		}
231 
232 	    if  ( docIsMergedCell( node ) )
233 		{ continue; }
234 
235 	    if  ( node->biLevel == level )
236 		{ return node;	}
237 	    }
238 	else{ node= node->biParent;	}
239 	}
240     }
241 
docPrevParagraph(BufferItem * node)242 BufferItem *	docPrevParagraph(	BufferItem *	node )
243     { return docPrevNode( node, DOClevPARA );	}
244 
docPrevSection(BufferItem * node)245 BufferItem *	docPrevSection(		BufferItem *	node )
246     { return docPrevNode( node, DOClevSECT );	}
247 
248 /************************************************************************/
249 /*									*/
250 /*  Move to the Next/Previous word.					*/
251 /*									*/
252 /*  1)  Words start after a particule ending in a space or at the	*/
253 /*	beginning of a paragraph.					*/
254 /*									*/
255 /************************************************************************/
256 
docNextWord(DocumentPosition * dp)257 int docNextWord(	DocumentPosition *	dp )
258     {
259     BufferItem *		paraBi= dp->dpNode;
260     int				stroff= dp->dpStroff;
261 
262     if  ( stroff == docParaStrlen( paraBi ) )
263 	{
264 	paraBi= docNextParagraph( paraBi );
265 	if  ( ! paraBi )
266 	    { return 1;	}
267 
268 	stroff= 0;
269 	}
270 
271     stroff= docParaNextWord( paraBi, stroff );
272     docSetDocumentPosition( dp, paraBi, stroff );
273 
274     return 0;
275     }
276 
docPrevWord(DocumentPosition * dp)277 int docPrevWord(	DocumentPosition *	dp )
278     {
279     BufferItem *		paraBi= dp->dpNode;
280     int				stroff= dp->dpStroff;
281 
282     if  ( stroff == 0 )
283 	{
284 	paraBi= docPrevParagraph( paraBi );
285 	if  ( ! paraBi )
286 	    { return 1;	}
287 
288 	stroff= docParaStrlen( paraBi );
289 	}
290 
291     stroff= docParaPrevWord( paraBi, stroff );
292     docSetDocumentPosition( dp, paraBi, stroff );
293 
294     return 0;
295     }
296 
297 /************************************************************************/
298 /*									*/
299 /*  Move one line up.							*/
300 /*									*/
301 /*  1)  Go to previous line of the paragraph or to the last line of the	*/
302 /*	last paragraph before this one that has any lines.		*/
303 /*  2)  In a clumsy attempt to implement vertical movement in tables,	*/
304 /*	try to stay in the same column of a table.			*/
305 /*									*/
306 /************************************************************************/
307 
docLineUp(int * pLine,DocumentPosition * dp,int line)308 int docLineUp(		int *			pLine,
309 			DocumentPosition *	dp,
310 			int			line )
311     {
312     TextLine *		tl;
313     BufferItem *	node= dp->dpNode;
314 
315     line--;
316 
317     /*  1  */
318     while( node )
319 	{
320 	if  ( node->biParaLineCount == 0 )
321 	    { LLDEB(docNumberOfParagraph(node),node->biParaLineCount);	}
322 
323 	if  ( node->biLevel == DOClevPARA		&&
324 	      line < node->biParaLineCount	&& /* against crashes */
325 	      line >= 0				)
326 	    {
327 	    tl= node->biParaLines+ line;
328 
329 	    dp->dpNode= node;
330 	    dp->dpStroff= tl->tlStroff;
331 
332 	    if  ( pLine )
333 		{ *pLine= line;	}
334 	    return 0;
335 	    }
336 
337 	/*  2  */
338 	if  ( node->biLevel == DOClevPARA		&&
339 	      node->biParaTableNesting > 0	&&
340 	      node->biNumberInParent == 0		)
341 	    {
342 	    int			col;
343 	    int			row0;
344 	    int			row;
345 	    int			row1;
346 
347 	    BufferItem *	parentNode;
348 
349 	    if  ( docDelimitTable( node, &parentNode, &col, &row0, &row, &row1 ) )
350 		{ LDEB(1); return -1;	}
351 
352 	    if  ( row > row0 )
353 		{
354 		BufferItem *	rowNode= parentNode->biChildren[row-1];
355 
356 		if  ( col < rowNode->biChildCount )
357 		    {
358 		    BufferItem *	cellNode= rowNode->biChildren[col];
359 
360 		    node= cellNode->biChildren[cellNode->biChildCount-1];
361 		    line= node->biParaLineCount- 1;
362 		    continue;
363 		    }
364 		}
365 	    }
366 
367 	node= docPrevParagraph( node );
368 	if  ( ! node )
369 	    { break;	}
370 	line= node->biParaLineCount- 1;
371 	}
372 
373     return -1;
374     }
375 
376 /************************************************************************/
377 /*									*/
378 /*  Move one line down.							*/
379 /*									*/
380 /*  1)  Go to the next line of the paragraph or to the first line of	*/
381 /*	the first paragraph after this one that has any lines.		*/
382 /*  2)  In a clumsy attempt to implement vertical movement in tables,	*/
383 /*	try to stay in the same column of a table.			*/
384 /*									*/
385 /************************************************************************/
386 
docLineDown(int * pLine,DocumentPosition * dp,int line)387 int docLineDown(	int *			pLine,
388 			DocumentPosition *	dp,
389 			int			line )
390     {
391     TextLine *		tl;
392     BufferItem *	node= dp->dpNode;
393 
394     line++;
395 
396     /*  1  */
397     while( node )
398 	{
399 	if  ( node->biLevel == DOClevPARA		&&
400 	      line < node->biParaLineCount	&&
401 	      line >= 0				)   /*  against crashes  */
402 	    {
403 	    tl= node->biParaLines+ line;
404 
405 	    dp->dpNode= node;
406 	    dp->dpStroff= tl->tlStroff;
407 
408 	    if  ( pLine )
409 		{ *pLine= line;	}
410 	    return 0;
411 	    }
412 
413 	/*  2  */
414 	if  ( node->biLevel == DOClevPARA					&&
415 	      node->biParaTableNesting > 0				&&
416 	      node->biNumberInParent == node->biParent->biChildCount- 1	)
417 	    {
418 	    int			col;
419 	    int			row0;
420 	    int			row;
421 	    int			row1;
422 
423 	    BufferItem *	parentNode;
424 
425 	    if  ( docDelimitTable( node, &parentNode, &col, &row0, &row, &row1 ) )
426 		{ LDEB(1); return -1;	}
427 
428 	    if  ( row < row1 )
429 		{
430 		BufferItem *	rowNode= parentNode->biChildren[row+1];
431 
432 		if  ( col < rowNode->biChildCount )
433 		    {
434 		    BufferItem *	cellNode= rowNode->biChildren[col];
435 
436 		    node= cellNode->biChildren[0];
437 		    line= 0;
438 		    continue;
439 		    }
440 		}
441 	    }
442 
443 	node= docNextParagraph( node );
444 	line= 0;
445 	}
446 
447     return -1;
448     }
449 
450 /************************************************************************/
451 /*									*/
452 /*  Move to the beginning/end of a line					*/
453 /*									*/
454 /************************************************************************/
455 
docLineHead(DocumentPosition * dp,int positionFlags)456 int docLineHead(	DocumentPosition *	dp,
457 			int			positionFlags )
458     {
459     int			line;
460     int			flags= 0;
461     const int		lastOne= PARAfindFIRST;
462 
463     if  ( positionFlags & POSflagLINE_HEAD )
464 	{ return 0;	}
465 
466     if  ( docFindLineOfPosition( &line, &flags, dp, lastOne ) )
467 	{ LDEB(dp->dpStroff); return -1;	}
468 
469     dp->dpStroff= dp->dpNode->biParaLines[line].tlStroff;
470 
471     return 0;
472     }
473 
docLineTail(DocumentPosition * dp,int positionFlags)474 int docLineTail(	DocumentPosition *	dp,
475 			int			positionFlags )
476     {
477     int			line;
478     int			flags= 0;
479     const int		lastOne= PARAfindLAST;
480     const TextLine *	tl;
481 
482     if  ( positionFlags & POSflagLINE_TAIL )
483 	{ return 0;	}
484 
485     if  ( docFindLineOfPosition( &line, &flags, dp, lastOne ) )
486 	{ LDEB(dp->dpStroff); return -1;	}
487 
488     tl= &(dp->dpNode->biParaLines[line]);
489     dp->dpStroff= tl->tlStroff+ tl->tlStrlen;
490 
491     return 0;
492     }
493 
494 /************************************************************************/
495 /*									*/
496 /*  Get buffer positions for a text line.				*/
497 /*									*/
498 /************************************************************************/
499 
docLineSelection(DocumentSelection * dsLine,int * pPartLineBegin,int * pPartLineEnd,const BufferItem * node,int line)500 void docLineSelection(	DocumentSelection *	dsLine,
501 			int *			pPartLineBegin,
502 			int *			pPartLineEnd,
503 			const BufferItem *	node,
504 			int			line )
505     {
506     const TextLine *	tl= node->biParaLines+ line;
507 
508     if  ( node->biLevel != DOClevPARA )
509 	{ LLDEB(node->biLevel,DOClevPARA); return;	}
510     if  ( line < 0 || line >= node->biParaLineCount )
511 	{ LLDEB(line,node->biParaLineCount); return;	}
512 
513     docInitDocumentSelection( dsLine );
514 
515     dsLine->dsHead.dpNode= (BufferItem *)node;
516     dsLine->dsHead.dpStroff= tl->tlStroff;
517 
518     dsLine->dsTail.dpNode= (BufferItem *)node;
519     dsLine->dsTail.dpStroff= tl->tlStroff+ tl->tlStrlen;
520 
521     dsLine->dsAnchor= dsLine->dsHead;
522     dsLine->dsDirection= 1;
523 
524     dsLine->dsCol0= dsLine->dsCol1= -1;
525 
526     docSetSelectionScope( dsLine );
527 
528     *pPartLineBegin= tl->tlFirstParticule;
529     *pPartLineEnd= tl->tlFirstParticule+ tl->tlParticuleCount- 1;
530 
531     return;
532     }
533 
534 /************************************************************************/
535 /*									*/
536 /*  Delimit a 'Word' in the document.					*/
537 /*									*/
538 /*  A 'Word' is one of the following:					*/
539 /*  1)	A continguous stretch of text. It is not interrupted by either	*/
540 /*	white space or control particules. Any white space after the	*/
541 /*	word is included in the word.					*/
542 /*  2)	An object or an image.						*/
543 /*									*/
544 /************************************************************************/
545 
docWordSelection(DocumentSelection * dsWord,int * pIsObject,const DocumentPosition * dpAround)546 void docWordSelection(	DocumentSelection *		dsWord,
547 			int *				pIsObject,
548 			const DocumentPosition *	dpAround )
549     {
550     TextParticule *	tp;
551 
552     BufferItem *	paraBi= dpAround->dpNode;
553     int			part;
554 
555     if  ( paraBi->biLevel != DOClevPARA )
556 	{ LLDEB(paraBi->biLevel,DOClevPARA); return;	}
557 
558     if  ( docFindParticuleOfPosition( &part, (int *)0,
559 						dpAround, PARAfindLAST ) )
560 	{ LDEB(dpAround->dpStroff); return;	}
561 
562     tp= paraBi->biParaParticules+ part;
563     while( part < paraBi->biParaParticuleCount- 1		&&
564 	   tp->tpStroff+ tp->tpStrlen <= dpAround->dpStroff	)
565 	{ tp++; part++;	}
566 
567     if  ( tp->tpStroff == dpAround->dpStroff	&&
568 	  part > 0				&&
569 	  tp[-1].tpKind == DOCkindOBJECT	)
570 	{
571 	docSetParaSelection( dsWord, paraBi, 1,
572 					tp[-1].tpStroff, tp[-1].tpStrlen );
573 	*pIsObject= 1;
574 	return;
575 	}
576 
577     if  ( tp->tpKind == DOCkindOBJECT )
578 	{
579 	docSetParaSelection( dsWord, paraBi, 1, tp->tpStroff, tp->tpStrlen );
580 	*pIsObject= 1;
581 	return;
582 	}
583     else{
584 	int	stroffHead;
585 	int	stroffTail;
586 
587 	docParaHeadOfWord( &stroffHead, paraBi, part );
588 	docParaTailOfWord( &stroffTail, paraBi, part );
589 
590 	docSetParaSelection( dsWord, paraBi, 1,
591 					stroffHead, stroffTail- stroffHead );
592 	}
593 
594     return;
595     }
596 
597 /************************************************************************/
598 /*									*/
599 /*  Translate a TableRectangle to a DocumentSelection.			*/
600 /*									*/
601 /************************************************************************/
602 
docTableRectangleSelection(DocumentSelection * ds,BufferItem ** pSelParentBi,BufferDocument * bd,const TableRectangle * tr)603 int docTableRectangleSelection(	DocumentSelection *	ds,
604 				BufferItem **		pSelParentBi,
605 				BufferDocument *	bd,
606 				const TableRectangle *	tr )
607     {
608     DocumentSelection	dsNew;
609 
610     BufferItem *	selSectBi;
611     BufferItem *	selParentBi;
612     BufferItem *	rowNode;
613     BufferItem *	cellNode;
614 
615     docInitDocumentSelection( &dsNew );
616 
617     /*******/
618 
619     selParentBi= docGetSelectionRoot( (DocumentTree **)0, (BufferItem **)0,
620 								    bd, ds );
621     if  ( ! selParentBi )
622 	{ XDEB(selParentBi); return -1;	}
623 
624     if  ( selParentBi->biLevel == DOClevPARA )
625 	{ selParentBi= selParentBi->biParent;	}
626     if  ( selParentBi->biLevel == DOClevCELL )
627 	{ selParentBi= selParentBi->biParent;	}
628     if  ( selParentBi->biLevel == DOClevROW )
629 	{ selParentBi= selParentBi->biParent;	}
630 
631     selSectBi= docGetSectNode( selParentBi );
632     if  ( ! selSectBi )
633 	{ XDEB(selSectBi); return -1;	}
634 
635     /*******/
636 
637     if  ( tr->trRow0 < 0					||
638 	  tr->trRow0 >= selParentBi->biChildCount		)
639 	{ LLDEB(tr->trRow0,selParentBi->biChildCount); return -1;	}
640     rowNode= selParentBi->biChildren[tr->trRow0];
641 
642     if  ( tr->trCol0 < 0			||
643 	  tr->trCol0 >= rowNode->biChildCount	)
644 	{ LLDEB(tr->trCol0,rowNode->biChildCount); return -1;	}
645     cellNode= rowNode->biChildren[tr->trCol0];
646 
647     if  ( docHeadPosition( &dsNew.dsHead, cellNode ) )
648 	{ LDEB(0); return -1;	}
649 
650     /*******/
651 
652     if  ( tr->trRow1 < 0				||
653 	  tr->trRow1 >= selParentBi->biChildCount	)
654 	{ LLDEB(tr->trRow0,selParentBi->biChildCount); return -1;	}
655     rowNode= selParentBi->biChildren[tr->trRow1];
656 
657     if  ( tr->trCol1 < 0			||
658 	  tr->trCol1 >= rowNode->biChildCount	)
659 	{ LLDEB(tr->trCol1,rowNode->biChildCount); return -1;	}
660     cellNode= rowNode->biChildren[tr->trCol1];
661 
662     if  ( docTailPosition( &dsNew.dsTail, cellNode ) )
663 	{ LDEB(0); return -1;	}
664 
665     /*******/
666 
667     dsNew.dsCol0= tr->trCol0;
668     dsNew.dsCol1= tr->trCol1;
669     dsNew.dsDirection= 1;
670     dsNew.dsAnchor= dsNew.dsHead;
671 
672     if  ( tr->trRow1 < tr->trRow0					||
673 	  ( tr->trRow1 == tr->trRow0 && tr->trCol1 < tr->trCol0 )	)
674 	{
675 	dsNew.dsDirection= -1;
676 	dsNew.dsAnchor= dsNew.dsTail;
677 	}
678 
679     docSetSelectionScope( &dsNew );
680 
681     *ds= dsNew;
682     *pSelParentBi= selParentBi;
683 
684     return 0;
685     }
686 
687 /************************************************************************/
688 /*									*/
689 /*  Is the selection exactly an object?					*/
690 /*									*/
691 /************************************************************************/
692 
docGetObjectSelection(const DocumentSelection * ds,const BufferDocument * bd,int * pPart,DocumentPosition * dpObject,InsertedObject ** pIo)693 int docGetObjectSelection(	const DocumentSelection *	ds,
694 				const BufferDocument *		bd,
695 				int *				pPart,
696 				DocumentPosition *		dpObject,
697 				InsertedObject **		pIo )
698     {
699     if  ( ds->dsHead.dpNode				&&
700 	  ds->dsTail.dpNode == ds->dsHead.dpNode	)
701 	{
702 	BufferItem *		paraBi= ds->dsHead.dpNode;
703 	int			part;
704 	TextParticule *		tp;
705 
706 	if  ( docFindParticuleOfPosition( &part, (int *)0,
707 						&(ds->dsHead), PARAfindLAST ) )
708 	    { LDEB(ds->dsHead.dpStroff); return -1;	}
709 
710 	tp= paraBi->biParaParticules+ part;
711 
712 	if  ( tp->tpKind == DOCkindOBJECT			&&
713 	      ds->dsHead.dpStroff == tp->tpStroff		&&
714 	      ds->dsTail.dpStroff == tp->tpStroff+ tp->tpStrlen	)
715 	    {
716 	    *pPart= part;
717 	    *dpObject= ds->dsHead;
718 	    *pIo= docGetObject( bd, tp->tpObjectNumber );
719 
720 	    return 0;
721 	    }
722 	}
723 
724     return 1;
725     }
726 
727 /************************************************************************/
728 /*									*/
729 /*  Select the whole frame around a position. Make no difficulties if	*/
730 /*  the position is not in a frame: simply select the neghbourhood that	*/
731 /*  is not a frame. (Usually the whole cell.)				*/
732 /*									*/
733 /************************************************************************/
734 
docSelectFrameOfPosition(DocumentSelection * ds,const DocumentPosition * dp)735 int docSelectFrameOfPosition(	DocumentSelection *		ds,
736 				const DocumentPosition *	dp )
737     {
738     BufferItem *	cellNode;
739     int			para0;
740     int			para1;
741     int			frameNumber;
742 
743     DocumentPosition	dpHead;
744     DocumentPosition	dpTail;
745 
746     const int		direction= 1;
747 
748     docInitDocumentPosition( &dpHead );
749     docInitDocumentPosition( &dpTail );
750 
751     if  ( ! dp->dpNode )
752 	{ XDEB(dp->dpNode); return 1;	}
753 
754     frameNumber= dp->dpNode->biParaFrameNumber;
755     cellNode= dp->dpNode->biParent;
756     para0= para1= dp->dpNode->biNumberInParent;
757 
758     while( para0 > 0 )
759 	{
760 	if  ( cellNode->biChildren[para0- 1]->biParaFrameNumber != frameNumber )
761 	    { break;	}
762 	para0--;
763 	}
764 
765     while( para1 < cellNode->biChildCount- 1 )
766 	{
767 	if  ( cellNode->biChildren[para1+ 1]->biParaFrameNumber != frameNumber )
768 	    { break;	}
769 	para1++;
770 	}
771 
772     if  ( docHeadPosition( &dpHead, cellNode->biChildren[para0] ) )
773 	{ LDEB(1); return 1;	}
774     if  ( docTailPosition( &dpTail, cellNode->biChildren[para1] ) )
775 	{ LDEB(1); return 1;	}
776 
777     docSetRangeSelection( ds, &dpHead, &dpTail, direction );
778 
779     return 0;
780     }
781 
782