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