1 /************************************************************************/
2 /*									*/
3 /*  Management of the list table of a document.				*/
4 /*  Individual list levels.						*/
5 /*									*/
6 /*  O)	Word 7.0 == Word 95 compatibility				*/
7 /*									*/
8 /************************************************************************/
9 
10 #   include	"docBaseConfig.h"
11 
12 #   include	<stdlib.h>
13 #   include	<string.h>
14 #   include	<stdio.h>
15 
16 #   include	<utilBase26.h>
17 #   include	<utilRoman.h>
18 #   include	<uniUtf8.h>
19 
20 #   include	<appDebugon.h>
21 
22 #   include	"docListLevel.h"
23 #   include	"docParaNumber.h"
24 
docInitDocumentListLevel(ListLevel * ll)25 void docInitDocumentListLevel(	ListLevel *	ll )
26     {
27     ll->llStartAt= 1;
28     ll->llNumberStyle= 0;
29     ll->llJustification= DOCllaLEFT;
30     ll->llFollow= DOCllfTAB;
31     ll->llPrevToDigits= 0;
32     ll->llNoRestart= 0;
33     ll->llPictureNumber= -1;
34     ll->llFontBias= 0;
35 
36     utilInitMemoryBuffer( &(ll->llFormatString) );
37     ll->llLevelNumbers= (LevelNumber *)0;
38     ll->llLevelNumberCount= 0;
39     ll->llTemplateID= -1;
40 
41     ll->llFromOld= 0;			/*  O  */
42     ll->llUsePrevText= 0;		/*  O  */
43     ll->llUsePrevSpace= 0;		/*  O  */
44     ll->llIndent= 0;			/*  O  */
45     ll->llSpace= 0;			/*  O  */
46 
47     ll->llTabStopListNumber= 0;
48     ll->llLeftIndentTwips= 0;
49     ll->llFirstIndentTwips= 0;
50     utilPropMaskClear( &(ll->llParaPropertyMask) );
51 
52     utilInitTextAttribute( &(ll->llTextAttribute) );
53     utilPropMaskClear( &(ll->llTextAttributeMask) );
54     }
55 
docCleanDocumentListLevel(ListLevel * ll)56 void docCleanDocumentListLevel(	ListLevel *	ll )
57     {
58     utilCleanMemoryBuffer( &(ll->llFormatString) );
59 
60     if  ( ll->llLevelNumbers )
61 	{ free( ll->llLevelNumbers ); }
62     }
63 
docListLevelApplyTextAttribute(ListLevel * ll,const PropertyMask * taSetMask,const TextAttribute * taSet)64 int docListLevelApplyTextAttribute(	ListLevel *		ll,
65 					const PropertyMask *	taSetMask,
66 					const TextAttribute *	taSet )
67     {
68     utilUpdateTextAttribute( (PropertyMask *)0, &(ll->llTextAttribute),
69 							taSetMask, taSet );
70     utilPropMaskOr( &(ll->llTextAttributeMask),
71 				    &(ll->llTextAttributeMask), taSetMask );
72     return 0;
73     }
74 
docCopyDocumentListLevel(ListLevel * to,const ListLevel * from,int copyIds,const int * fontMap,const int * colorMap,const int * rulerMap)75 int docCopyDocumentListLevel(	ListLevel *		to,
76 				const ListLevel *	from,
77 				int			copyIds,
78 				const int *		fontMap,
79 				const int *		colorMap,
80 				const int *		rulerMap )
81     {
82     int			rval= 0;
83 
84     LevelNumber *	levelNumbers= (LevelNumber *)0;
85 
86     if  ( utilCopyMemoryBuffer( &(to->llFormatString),
87 						&(from->llFormatString) ) )
88 	{ LDEB(1); return -1;	}
89 
90     if  ( from->llLevelNumbers )
91 	{
92 	int		i;
93 	int		count= from->llLevelNumberCount+ 1; /* NOTE +1 */
94 
95 	levelNumbers= (LevelNumber *)malloc( count* sizeof(LevelNumber) );
96 	if  ( ! levelNumbers )
97 	    { LPDEB(count,levelNumbers); rval= -1; goto ready;	}
98 
99 	for ( i= 0; i < count; i++ )
100 	    { levelNumbers[i]= from->llLevelNumbers[i];	}
101 	}
102 
103     if  ( to->llLevelNumbers )
104 	{ free( to->llLevelNumbers ); }
105 
106     to->llStartAt= from->llStartAt;
107     to->llNumberStyle= from->llNumberStyle;
108     to->llJustification= from->llJustification;
109     to->llFollow= from->llFollow;
110     to->llPrevToDigits= from->llPrevToDigits;
111     to->llNoRestart= from->llNoRestart;
112     to->llFontBias= from->llFontBias;
113     to->llPictureNumber= from->llPictureNumber;
114 
115     if  ( copyIds )
116 	{ to->llTemplateID= from->llTemplateID;	}
117 
118     to->llFromOld= from->llFromOld;
119     to->llUsePrevText= from->llUsePrevText;
120     to->llUsePrevSpace= from->llUsePrevSpace;
121     to->llIndent= from->llIndent;
122     to->llSpace= from->llSpace;
123     to->llTabStopListNumber= from->llTabStopListNumber;
124     to->llLeftIndentTwips= from->llLeftIndentTwips;
125     to->llFirstIndentTwips= from->llFirstIndentTwips;
126     to->llParaPropertyMask= from->llParaPropertyMask;
127     to->llTextAttribute= from->llTextAttribute;
128     to->llTextAttributeMask= from->llTextAttributeMask;
129 
130     if  ( fontMap							&&
131 	  PROPmaskISSET( &(to->llTextAttributeMask), TApropFONT_NUMBER ) )
132 	{
133 	to->llTextAttribute.taFontNumber=
134 				fontMap[from->llTextAttribute.taFontNumber];
135 	}
136     if  ( colorMap							&&
137 	  PROPmaskISSET( &(to->llTextAttributeMask), TApropFONT_NUMBER ) &&
138 	  from->llTextAttribute.taTextColorNumber > 0			)
139 	{
140 	to->llTextAttribute.taTextColorNumber=
141 			    colorMap[from->llTextAttribute.taTextColorNumber];
142 	}
143     if  ( rulerMap							&&
144 	  PROPmaskISSET( &(to->llParaPropertyMask), PPpropTAB_STOPS )	&&
145 	  from->llTabStopListNumber > 0			)
146 	{
147 	to->llTabStopListNumber= rulerMap[from->llTabStopListNumber];
148 	}
149 
150     /* steal */
151     to->llLevelNumbers= levelNumbers; levelNumbers= (LevelNumber *)0;
152     to->llLevelNumberCount= from->llLevelNumberCount;
153 
154   ready:
155 
156     if  ( levelNumbers )
157 	{ free( levelNumbers );	}
158 
159     return rval;
160     }
161 
162 /************************************************************************/
163 /*									*/
164 /*  Set the relevant style attributes in a list level.			*/
165 /*									*/
166 /*  1)  Paragraph Properties.						*/
167 /*  2)  Text Attributes.						*/
168 /*									*/
169 /************************************************************************/
170 
docListLevelSetStyle(ListLevel * ll,const PropertyMask * paraMask,const ParagraphProperties * pp,const PropertyMask * taSetMask,const TextAttribute * taSet)171 int docListLevelSetStyle(	ListLevel *			ll,
172 				const PropertyMask *		paraMask,
173 				const ParagraphProperties *	pp,
174 				const PropertyMask *		taSetMask,
175 				const TextAttribute *		taSet )
176     {
177     /*  1  */
178     utilPropMaskClear( &(ll->llParaPropertyMask) );
179 
180     if  ( PROPmaskISSET( paraMask, PPpropTAB_STOPS ) )
181 	{
182 	ll->llTabStopListNumber= pp->ppTabStopListNumber;
183 	PROPmaskADD( &(ll->llParaPropertyMask), PPpropTAB_STOPS );
184 	}
185 
186     if  ( PROPmaskISSET( paraMask, PPpropLEFT_INDENT ) )
187 	{
188 	ll->llLeftIndentTwips= pp->ppLeftIndentTwips;
189 	PROPmaskADD( &(ll->llParaPropertyMask), PPpropLEFT_INDENT );
190 	}
191 
192     if  ( PROPmaskISSET( paraMask, PPpropFIRST_INDENT ) )
193 	{
194 	ll->llFirstIndentTwips= pp->ppFirstIndentTwips;
195 	PROPmaskADD( &(ll->llParaPropertyMask), PPpropFIRST_INDENT );
196 	}
197 
198     /*  2  */
199     {
200     PropertyMask	doneMask;
201 
202     utilPropMaskClear( &doneMask );
203 
204     ll->llTextAttributeMask= *taSetMask;
205     utilUpdateTextAttribute( &doneMask, &(ll->llTextAttribute),
206 							    taSetMask, taSet );
207     }
208 
209     return 0;
210     }
211 
212 /************************************************************************/
213 /*									*/
214 /*  Return the constant text that precedes field 'idx' in the listtext	*/
215 /*  format. (Or for idx == ll->llNumberSizeBytes, return the trailing	*/
216 /*  piece.)								*/
217 /*									*/
218 /************************************************************************/
219 
docListLevelGetField(int * pConstOff,int * pConstLen,int * pConstChars,int * pLevel,const ListLevel * ll,int field)220 int docListLevelGetField(	int *			pConstOff,
221 				int *			pConstLen,
222 				int *			pConstChars,
223 				int *			pLevel,
224 				const ListLevel *	ll,
225 				int			field )
226     {
227     int		constHead= 0;
228     int		constTail= 0;
229     int		level= -1;
230 
231     if  ( field < 0 || field > ll->llLevelNumberCount )
232 	{ LLDEB(field,ll->llLevelNumberCount); return -1;	}
233 
234     if  ( field > 0 )
235 	{ constHead= ll->llLevelNumbers[field-1].lnOffsetBytes;	}
236 
237     constTail= ll->llLevelNumbers[field].lnOffsetBytes;
238 
239     if  ( field < ll->llLevelNumberCount )
240 	{ level= ll->llLevelNumbers[field].lnLevel;	}
241 
242     *pConstOff= constHead;
243     *pConstLen= constTail- constHead;
244     *pConstChars= ll->llLevelNumbers[field].lnConstChars;
245     *pLevel= level;
246 
247     return 0;
248     }
249 
250 /************************************************************************/
251 /*									*/
252 /*  Get the (constant) text before a component in the level text of a	*/
253 /*  list. (Or for idx == ll->llNumberSizeBytes, return the trailing	*/
254 /*  piece.								*/
255 /*									*/
256 /************************************************************************/
257 
docListLevelGetText(char * to,int maxsize,const ListLevel * ll,int field)258 int docListLevelGetText(	char *			to,
259 				int			maxsize,
260 				const ListLevel *	ll,
261 				int			field )
262     {
263     int			constOff;
264     int			constLen;
265     int			constChars;
266     int			level;
267 
268     if  ( docListLevelGetField( &constOff, &constLen, &constChars,
269 							&level, ll, field ) )
270 	{ LDEB(field); return -1;	}
271     if  ( constLen > maxsize )
272 	{ LLDEB(constLen,maxsize); return -1;	}
273 
274     memcpy( to, ll->llFormatString.mbBytes+ constOff, constLen );
275     to[constLen]= '\0';
276 
277     return constLen;
278     }
279 
280 /************************************************************************/
281 /*									*/
282 /*  Update a component in the level text of a list.			*/
283 /*									*/
284 /*  idx is the index in ll->llNumberIndices. The text before the	*/
285 /*  number is changed. The trailing text after the last number is	*/
286 /*  updated if idx == ll->llNumberSizeBytes.				*/
287 /*									*/
288 /*  1)  Determine stretch in ll->llTextFormat				*/
289 /*  2)  More memory needed?						*/
290 /*  3)  Insert new value.						*/
291 /*  4)  Shift indirection via ll->llNumberIndices.			*/
292 /*  5)  Remember size in ll->llTextFormat.				*/
293 /*									*/
294 /************************************************************************/
295 
docListLevelSetText(int * pChanged,ListLevel * ll,const char * text,int field)296 int docListLevelSetText(	int *			pChanged,
297 				ListLevel *		ll,
298 				const char *		text,
299 				int			field )
300     {
301     int			constOff;
302     int			nbytes;
303     int			ochars;
304     int			nchars;
305     int			obytes;
306     int			level;
307 
308     const char *	from;
309     int			i;
310 
311     if  ( ! ll->llLevelNumbers )
312 	{ PDEB(ll->llLevelNumbers); return -1;	}
313 
314     nbytes= 0; nchars= 0;
315     from= text;
316     while( *from )
317 	{
318 	unsigned short	symbol;
319 	int		step;
320 
321 	step= uniGetUtf8( &symbol, from );
322 	if  ( step < 1 )
323 	    { LDEB(step); break;	}
324 
325 	nchars++; nbytes += step; from += step;
326 	}
327 
328     /*  1  */
329     if  ( docListLevelGetField( &constOff, &obytes, &ochars, &level,
330 								ll, field ) )
331 	{ LDEB(field); return -1;	}
332 
333     if  ( nbytes == obytes						&&
334 	  ! memcmp( ll->llFormatString.mbBytes+ constOff, text, obytes ) )
335 	{ *pChanged= 0; return 0;	}
336 
337     /*  2,3  */
338     if  ( utilMemoryBufferReplaceBytes( &(ll->llFormatString),
339 					constOff, constOff+ obytes,
340 					(const unsigned char *)text, nbytes ) )
341 	{ LLDEB(obytes,nbytes); return -1;	}
342 
343     ll->llLevelNumbers[field].lnConstChars= nchars;
344 
345     /*  4  */
346     for ( i= field; i <= ll->llLevelNumberCount; i++ ) /* NOTE: <= */
347 	{ ll->llLevelNumbers[i].lnOffsetBytes += nbytes- obytes;	}
348 
349     *pChanged= 1; return 0;
350     }
351 
docListLevelSetNumber(int * pChanged,ListLevel * ll,int level,int field)352 int docListLevelSetNumber(	int *			pChanged,
353 				ListLevel *		ll,
354 				int			level,
355 				int			field )
356     {
357     if  ( field < 0 || field > ll->llLevelNumberCount )
358 	{ LLDEB(field,ll->llLevelNumberCount); return -1;	}
359 
360     if  ( field < ll->llLevelNumberCount		&&
361     	  ll->llLevelNumbers[field].lnLevel == level	)
362 	{ pChanged= 0; return 0;	}
363 
364     if  ( field < ll->llLevelNumberCount )
365 	{ ll->llLevelNumbers[field].lnLevel= level;	}
366     else{
367 	if  ( docListLevelInsertNumber( ll, level, field ) )
368 	    { LDEB(field); return -1;	}
369 	}
370 
371     *pChanged= 1; return 0;
372     }
373 
374 /************************************************************************/
375 /*									*/
376 /*  Insert a reference to a level number in the format string of a list	*/
377 /*  level.								*/
378 /*									*/
379 /************************************************************************/
380 
docListLevelInsertNumber(ListLevel * ll,int level,int field)381 int docListLevelInsertNumber(	ListLevel *		ll,
382 				int			level,
383 				int			field )
384     {
385     LevelNumber *	fresh;
386     int			count= ll->llLevelNumberCount+ 2; /* NOTE: +2 */
387     int			i;
388 
389     /*  1  */
390     if  ( field < 0 || field > ll->llLevelNumberCount )
391 	{ LLDEB(field,ll->llLevelNumberCount); return -1;	}
392 
393     /*  2  */
394     fresh= (LevelNumber *)realloc( ll->llLevelNumbers, count* sizeof(LevelNumber) );
395     if  ( ! fresh )
396 	{ LPDEB(count,fresh); return -1;	}
397 
398     ll->llLevelNumbers= fresh;
399     ll->llLevelNumberCount++;
400 
401     for ( i= ll->llLevelNumberCount; i > field; i-- )
402 	{ ll->llLevelNumbers[i]= ll->llLevelNumbers[i-1];	}
403 
404     /* ll->llLevelNumbers[field].lnOffsetBytes:= unchanged */
405     ll->llLevelNumbers[field].lnConstChars= 0;
406     ll->llLevelNumbers[field].lnLevel= level;
407 
408     return 0;
409     }
410 
411 /************************************************************************/
412 /*									*/
413 /*  Delete a reference to a level number from the format string of a	*/
414 /*  list level.								*/
415 /*									*/
416 /************************************************************************/
417 
docListLevelDeleteNumber(ListLevel * ll,int field)418 int docListLevelDeleteNumber(	ListLevel *		ll,
419 				int			field )
420     {
421     int			i;
422 
423     /*  1  */
424     if  ( field < 0 || field >= ll->llLevelNumberCount )
425 	{ LLDEB(field,ll->llLevelNumberCount); return -1;	}
426 
427     for ( i= field; i < ll->llLevelNumberCount; i++ )
428 	{ ll->llLevelNumbers[i]= ll->llLevelNumbers[i+1];	}
429 
430     ll->llLevelNumberCount--;
431 
432     return 0;
433     }
434 
435 /************************************************************************/
436 /*									*/
437 /*  Format the value of a 'listtext' field.				*/
438 /*									*/
439 /*  I.E. the text of the bullet or paragraph number at the beginning	*/
440 /*	of a paragraph that gets one because it has a list reference.	*/
441 /*									*/
442 /************************************************************************/
443 
docListLevelFormatLevelNumber(char * target,int maxsize,int val,int format)444 int docListLevelFormatLevelNumber(	char *	target,
445 					int	maxsize,
446 					int	val,
447 					int	format )
448     {
449     int		step= 0;
450 
451     if  ( maxsize < 1 )
452 	{ LDEB(maxsize); return -1;	}
453 
454     switch( format )
455 	{
456 	case DOCpnDEC:
457 	    if  ( maxsize < 11 )
458 		{ LDEB(maxsize); return -1;	}
459 	    sprintf( target, "%d", val );
460 	    step= strlen( target );
461 	    break;
462 
463 	case DOCpnUCRM:
464 	    if  ( utilRomanString( target, maxsize, val, 1 ) )
465 		{ LDEB(val); return -1;	}
466 	    step= strlen( target );
467 	    break;
468 
469 	case DOCpnLCRM:
470 	    if  ( utilRomanString( target, maxsize, val, 0 ) )
471 		{ LDEB(val); return -1;	}
472 	    step= strlen( target );
473 	    break;
474 
475 	case DOCpnUCLTR:
476 	    if  ( val == 0 )
477 		{ strcpy( target, "+" ); }
478 	    else{
479 		if  ( utilBase26String( target, maxsize, val, 1 ) )
480 		    { LDEB(val); return -1;	}
481 		}
482 	    step= strlen( target );
483 	    break;
484 
485 	case DOCpnLCLTR:
486 	    if  ( val == 0 )
487 		{ strcpy( target, "+" ); }
488 	    else{
489 		if  ( utilBase26String( target, maxsize, val, 0 ) )
490 		    { LDEB(val); return -1;	}
491 		}
492 	    step= strlen( target );
493 	    break;
494 
495 	case 22:
496 	    if  ( maxsize < 11 )
497 		{ LDEB(maxsize); return -1;	}
498 	    sprintf( target, "%02d", val );
499 	    step= strlen( target );
500 	    break;
501 
502 	case 23:
503 	    step= uniPutUtf8( target, 0xb7 );
504 	    target[step]= '\0';
505 	    break;
506 
507 	case 255:
508 	    break;
509 
510 	default:
511 	    LLDEB(format,val);
512 	    if  ( maxsize < 13 )
513 		{ LDEB(maxsize); return -1;	}
514 	    sprintf( target, "(%d)", val );
515 	    step= strlen( target );
516 	    break;
517 	}
518 
519     return step;
520     }
521 
522 /************************************************************************/
523 /*									*/
524 /*  Format a paragraph number: A listtext field.			*/
525 /*									*/
526 /************************************************************************/
527 
docListLevelFormatConst(int * pConstLen,int * pLevel,char * to,int maxbytes,const ListLevel * ll,int field)528 static int docListLevelFormatConst(	int *			pConstLen,
529 					int *			pLevel,
530 					char *			to,
531 					int			maxbytes,
532 					const ListLevel *	ll,
533 					int			field )
534     {
535     int			constOff;
536     int			constLen;
537     int			constChars;
538     int			level;
539 
540     if  ( docListLevelGetField( &constOff, &constLen, &constChars, &level,
541 								ll, field ) )
542 	{ LDEB(field); return -1;	}
543     if  ( constLen > maxbytes )
544 	{ LLDEB(constLen,maxbytes); return -1;	}
545 
546     if  ( constLen > 0 )
547 	{ memcpy( to, ll->llFormatString.mbBytes+ constOff, constLen );	}
548 
549     to[constLen]= '\0';
550 
551     *pConstLen= constLen;
552     *pLevel= level;
553 
554     return 0;
555     }
556 
docListLevelFormatParagraphNumber(char * to,int maxbytes,int * byteOffsets,int maxoffsets,int ilvl,const int * numberPath,const int * startPath,const int * formatPath,const ListLevel * ll)557 int docListLevelFormatParagraphNumber(	char *			to,
558 					int			maxbytes,
559 					int *			byteOffsets,
560 					int			maxoffsets,
561 					int			ilvl,
562 					const int *		numberPath,
563 					const int *		startPath,
564 					const int *		formatPath,
565 					const ListLevel *	ll )
566     {
567     int			bytesDone= 0;
568     int			field;
569 
570     int			constLen;
571     int			level;
572 
573     if  ( ! ll->llLevelNumbers )
574 	{ PDEB(ll->llLevelNumbers); return -1; }
575 
576     for ( field= 0; field < ll->llLevelNumberCount; field++ )
577 	{
578 	int		varLen;
579 
580 	level= -1;
581 	if  ( docListLevelFormatConst( &constLen, &level,
582 					to, maxbytes- bytesDone, ll, field ) )
583 	    { LDEB(field); return -1;	}
584 
585 	if  ( 2* field+ 0 < maxoffsets )
586 	    { byteOffsets[2* field+ 0]= bytesDone;	}
587 	if  ( constLen > 0 )
588 	    { to += constLen; bytesDone += constLen;	}
589 
590 	if  ( level > ilvl )
591 	    { LLDEB(ilvl,level); return -1;	}
592 
593 	if  ( 2* field+ 1 < maxoffsets )
594 	    { byteOffsets[2* field+ 1]= bytesDone;	}
595 
596 	varLen= docListLevelFormatLevelNumber( to, maxbytes- bytesDone,
597 				startPath[level]+ numberPath[level],
598 				formatPath[level] );
599 	if  ( varLen < 0 )
600 	    { LLDEB(level,varLen); return -1;	}
601 
602 	to += varLen; bytesDone += varLen;
603 	}
604 
605     level= -1;
606     if  ( docListLevelFormatConst( &constLen, &level,
607 					to, maxbytes- bytesDone, ll, field ) )
608 	{ LDEB(field); return -1;	}
609 
610     if  ( 2* field+ 0 < maxoffsets )
611 	{ byteOffsets[2* field+ 0]= bytesDone;	}
612     if  ( constLen > 0 )
613 	{ to += constLen; bytesDone += constLen;	}
614 
615     if  ( 2* field+ 1 < maxoffsets )
616 	{ byteOffsets[2* field+ 1]= bytesDone;	}
617 
618     to[0]= '\0';
619     return bytesDone;
620     }
621 
docDefaultListLevel(ListLevel * llTo,int level,int deftab,int levelTemplateID,const PropertyMask * taSetMask,const TextAttribute * taSet)622 int docDefaultListLevel(	ListLevel *		llTo,
623 				int			level,
624 				int			deftab,
625 				int			levelTemplateID,
626 				const PropertyMask *	taSetMask,
627 				const TextAttribute *	taSet )
628     {
629     int			rval= 0;
630 
631     unsigned char *	formatString= (unsigned char *)0;
632     LevelNumber *	levelNumbers= (LevelNumber *)0;
633 
634     int			i;
635 
636     docCleanDocumentListLevel( llTo );
637     docInitDocumentListLevel( llTo );
638 
639     /*  1  */
640     llTo->llTemplateID= levelTemplateID;
641 
642     formatString= (unsigned char *)malloc( level+ 1 );
643     if  ( ! formatString )
644 	{ LPDEB(level,formatString); rval= -1; goto ready;	}
645 
646     levelNumbers= (LevelNumber *)malloc(
647 			    (level+ 2)* sizeof(LevelNumber) ); /* NOTE: +2 */
648     if  ( ! levelNumbers )
649 	{ LPDEB(level,levelNumbers); rval= -1; goto ready;	}
650 
651     memset( formatString, '.', level );
652     formatString[level]= '\0';
653 
654     for ( i= 0; i <= level; i++ )
655 	{
656 	levelNumbers[i].lnOffsetBytes= i;
657 	levelNumbers[i].lnLevel= i;
658 	levelNumbers[i].lnConstChars= ( i > 0 );
659 	}
660     levelNumbers[i].lnOffsetBytes= i- 1;
661     levelNumbers[i].lnLevel= -1;
662     levelNumbers[i].lnConstChars= 0;
663 
664     if  ( utilMemoryBufferSetBytes( &(llTo->llFormatString), formatString, level ) )
665 	{ LDEB(level); rval= -1; goto ready;	}
666 
667     llTo->llLevelNumbers= levelNumbers;
668     levelNumbers= (LevelNumber *)0; /* steal */
669     llTo->llLevelNumberCount= level+ 1;
670 
671     llTo->llTextAttribute= *taSet;
672     llTo->llTextAttributeMask= *taSetMask;
673 
674     llTo->llFirstIndentTwips= -deftab/ 2;
675     llTo->llLeftIndentTwips= ( level+ 1 )* deftab;
676     PROPmaskADD( &(llTo->llParaPropertyMask), PPpropFIRST_INDENT );
677     PROPmaskADD( &(llTo->llParaPropertyMask), PPpropLEFT_INDENT );
678 
679   ready:
680 
681     if  ( formatString )
682 	{ free( formatString );		}
683     if  ( levelNumbers )
684 	{ free( levelNumbers );	}
685 
686     return rval;
687     }
688 
docListLevelToRtfStrings(MemoryBuffer * mbtext,MemoryBuffer * mbnumbers,const ListLevel * ll)689 int docListLevelToRtfStrings(	MemoryBuffer *		mbtext,
690 				MemoryBuffer *		mbnumbers,
691 				const ListLevel *	ll )
692     {
693     unsigned char		uc;
694     int				chars= 1;
695     int				field;
696 
697     int				constOff;
698     int				constLen;
699     int				constChars;
700     int				level;
701 
702     const unsigned char *	formatString= ll->llFormatString.mbBytes;
703 
704     utilEmptyMemoryBuffer( mbtext );
705     utilEmptyMemoryBuffer( mbnumbers );
706 
707     if  ( ! ll->llLevelNumbers )
708 	{ PDEB(ll->llLevelNumbers); return 0; }
709 
710     uc= 0;
711     if  ( utilMemoryBufferAppendBytes( mbtext, &uc, 1 ) )
712 	{ LDEB(1); return -1;	}
713 
714     for ( field= 0; field < ll->llLevelNumberCount; field++ )
715 	{
716 	if  ( docListLevelGetField( &constOff, &constLen, &constChars, &level,
717 								ll, field ) )
718 	    { LDEB(field); return -1;	}
719 
720 	if  ( utilMemoryBufferAppendBytes( mbtext,
721 					formatString+ constOff, constLen ) )
722 	    { LDEB(constLen); return -1;	}
723 
724 	chars += constChars;
725 
726 	uc= chars;
727 	if  ( utilMemoryBufferAppendBytes( mbnumbers, &uc, 1 ) )
728 	    { LDEB(1); return -1;	}
729 
730 	uc= level;
731 	if  ( utilMemoryBufferAppendBytes( mbtext, &uc, 1 ) )
732 	    { LDEB(1); return -1;	}
733 
734 	chars++;
735 	}
736 
737     if  ( docListLevelGetField( &constOff, &constLen, &constChars, &level,
738 								ll, field ) )
739 	{ LDEB(field); return -1;	}
740 
741     if  ( utilMemoryBufferAppendBytes( mbtext, formatString+ constOff, constLen ) )
742 	{ LDEB(constLen); return -1;	}
743 
744     chars += constChars;
745     mbtext->mbBytes[0]= chars- 1;
746 
747     return 0;
748     }
749 
docListLevelConstFromRtfStrings(const char * from,int constChars)750 static int docListLevelConstFromRtfStrings(
751 					const char *	from,
752 					int		constChars )
753     {
754     int		c;
755     int		constLen= 0;
756 
757     for ( c= 0; c < constChars; c++ )
758 	{
759 	unsigned short	symbol;
760 	int		step;
761 
762 	step= uniGetUtf8( &symbol, from );
763 	if  ( step < 1 )
764 	    { CLDEB(*from,step); return -1;	}
765 
766 	constLen += step; from += step;
767 	}
768 
769     return constLen;
770     }
771 
docListLevelFromRtfStrings(ListLevel * ll,const MemoryBuffer * mbtext,const MemoryBuffer * mbnumbers)772 int docListLevelFromRtfStrings(	ListLevel *		ll,
773 				const MemoryBuffer *	mbtext,
774 				const MemoryBuffer *	mbnumbers )
775     {
776     int				rval= 0;
777 
778     unsigned char *		formatString= (unsigned char *)0;
779     LevelNumber *		levelNumbers= (LevelNumber *)0;
780 
781     const unsigned char *	fbytes;
782     int				fsize= 0;
783     const unsigned char *	lbytes;
784     int				lsize= 0;
785 
786     int				field;
787     int				offsetChars= 1; /* in rtf */
788     int				constChars;
789     int				constOff= 0;
790     int				constLen= 0;
791 
792     const char *		 from;
793 
794     fbytes= utilMemoryBufferGetBytes( &fsize, mbtext );
795     lbytes= utilMemoryBufferGetBytes( &lsize, mbnumbers );
796 
797     formatString= (unsigned char *)malloc( fsize );
798     if  ( ! formatString )
799 	{ LPDEB(fsize,formatString); rval= -1; goto ready;	}
800     formatString[0]= '\0';
801 
802     levelNumbers= (LevelNumber *)malloc( (lsize+ 1)*sizeof(LevelNumber) );
803     if  ( ! levelNumbers )
804 	{ LPDEB(lsize,levelNumbers); rval= -1; goto ready;	}
805 
806     from= (char *)fbytes+ 1;
807 
808     for ( field= 0; field < lsize; field++ )
809 	{
810 	int	fieldOffsetChars= lbytes[field]; /* in rtf */
811 
812 	constChars= fieldOffsetChars- offsetChars;
813 	constLen= docListLevelConstFromRtfStrings( from, constChars );
814 
815 	if  ( constLen < 0 )
816 	    { LLDEB(field,constLen); rval= -1; goto ready;	}
817 
818 	memcpy( formatString+ constOff, from, constLen );
819 	from += constLen;
820 
821 	levelNumbers[field].lnOffsetBytes= constOff+ constLen;
822 	levelNumbers[field].lnConstChars= constChars;
823 	levelNumbers[field].lnLevel= *(from++);
824 
825 	offsetChars= fieldOffsetChars+ 1;
826 	constOff += constLen;
827 	}
828 
829     constChars= fbytes[0]+ 1- offsetChars;
830     constLen= docListLevelConstFromRtfStrings( from, constChars );
831     if  ( constLen < 0 )
832 	{ LDEB(constLen); rval= -1; goto ready;	}
833 
834     memcpy( formatString+ constOff, from, constLen );
835 
836     levelNumbers[field].lnOffsetBytes= constOff+ constLen;
837     levelNumbers[field].lnConstChars= constChars;
838     levelNumbers[field].lnLevel= -1;
839 
840     constOff += constLen;
841     formatString[constOff]= '\0';
842 
843     if  ( utilMemoryBufferSetBytes( &(ll->llFormatString), formatString, constOff ) )
844 	{ LDEB(constOff); rval= -1; goto ready;	}
845 
846     ll->llLevelNumbers= levelNumbers;
847     levelNumbers= (LevelNumber *)0; /* steal */
848     ll->llLevelNumberCount= lsize;
849 
850 #   if 0
851     SDEB(ll->llFormatString);
852     for ( field= 0; field <= ll->llLevelNumberCount; field++ )
853 	{
854 	appDebug( "%d: ob= %2d, cg= %2d, lev= %2d\n", field,
855 			ll->llLevelNumbers[field].lnOffsetBytes,
856 			ll->llLevelNumbers[field].lnConstChars,
857 			ll->llLevelNumbers[field].lnLevel );
858 	}
859     docListDocumentListLevel(-1,ll);
860 #   endif
861 
862   ready:
863 
864     if  ( formatString )
865 	{ free( formatString );	}
866     if  ( levelNumbers )
867 	{ free( levelNumbers );	}
868 
869     return rval;
870     }
871 
docSetListLevelProperty(ListLevel * ll,int prop,int val)872 int docSetListLevelProperty(	ListLevel *		ll,
873 				int			prop,
874 				int			val )
875     {
876     switch( prop )
877 	{
878 	case LLpropSTARTAT:
879 	    ll->llStartAt= val;
880 	    break;
881 
882 	case LLpropSTYLE:
883 	    ll->llNumberStyle= val;
884 	    break;
885 
886 	case LLpropJUSTIFY:
887 	    ll->llJustification= val;
888 	    break;
889 
890 	case LLpropFOLLOW:
891 	    ll->llFollow= val;
892 	    break;
893 
894 	case LLpropLEGAL:
895 	    ll->llPrevToDigits= val != 0;
896 	    break;
897 
898 	case LLpropNORESTART:
899 	    ll->llNoRestart= val != 0;
900 	    break;
901 
902 	case LLpropPICTURE:
903 	    ll->llPictureNumber= val;
904 	    break;
905 
906 	case LLpropFBIAS:
907 	    ll->llFontBias= val != 0;
908 	    break;
909 
910 	/* LLpropTEXT */
911 
912 	case LLpropTEMPLATEID:
913 	    ll->llTemplateID= val;
914 	    break;
915 
916 	/* LLpropNUMBERS */
917 
918 	case LLpropOLD:
919 	    ll->llFromOld= val != 0;
920 	    break;
921 
922 	case LLpropPREV:
923 	    ll->llUsePrevText= val != 0;
924 	    break;
925 
926 	case LLpropPREVSPACE:
927 	    ll->llUsePrevSpace= val != 0;
928 	    break;
929 
930 	case LLpropINDENT:
931 	    ll->llIndent= val;
932 	    break;
933 
934 	case LLpropSPACE:
935 	    ll->llSpace= val;
936 	    break;
937 
938 	default:
939 	    LDEB(prop); return -1;
940 	}
941 
942     return 0;
943     }
944