Merge branch 'master' into cde-next
[oweals/cde.git] / cde / lib / DtHelp / UtilSDL.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these libraries and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $XConsortium: UtilSDL.c /main/10 1996/08/30 13:43:15 cde-hp $ */
24 /************************************<+>*************************************
25  ****************************************************************************
26  **
27  **   File:        UtilSDL.c
28  **
29  **   Project:     Cde Help System
30  **
31  **   Description: Utility functions for parsing an SDL volume.
32  **
33  **  (c) Copyright 1987, 1988, 1989, 1990, 1991, 1992 Hewlett-Packard Company
34  **
35  **  (c) Copyright 1993, 1994 Hewlett-Packard Company
36  **  (c) Copyright 1993, 1994 International Business Machines Corp.
37  **  (c) Copyright 1993, 1994 Sun Microsystems, Inc.
38  **  (c) Copyright 1993, 1994 Novell, Inc.
39  **
40  ****************************************************************************
41  ************************************<+>*************************************/
42
43 /*
44  * system includes
45  */
46 #include <fcntl.h>
47 #include <limits.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <unistd.h>
52
53 /*
54  * Canvas Engine includes
55  */
56 #include "CanvasP.h"
57 #include "CanvasSegP.h"
58
59 /*
60  * private includes
61  */
62 #include "Access.h"
63 #include "FontAttrI.h"
64 #include "AccessSDLP.h"
65 #include "CanvasError.h"
66 #include "bufioI.h"
67 #include "FormatUtilI.h"
68 #include "SDLI.h"
69 #include "FormatSDLI.h"
70 #include "StringFuncsI.h"
71 #include "UtilSDLI.h"
72
73 #ifdef NLS16
74 #endif
75
76 /********    Private Function Declarations    ********/
77 /********    End Private Function Declarations    ********/
78
79 /******************************************************************************
80  *
81  * Private defines.
82  *
83  *****************************************************************************/
84 #ifndef FALSE
85 #define FALSE   0
86 #endif
87
88 #ifndef False
89 #define False   0
90 #endif
91
92 #ifndef TRUE
93 #define TRUE    1
94 #endif
95
96 #ifndef True
97 #define True    1
98 #endif
99
100 #define GROW_SIZE   10
101 #define MAX_ELEMENT_SIZE   30
102
103 typedef struct  _classStyleMatrix
104   {
105     SdlOption      start;
106     SdlOption      end;
107     enum SdlElement     style;
108   } ClassStyleMatrix;
109
110 /******************************************************************************
111  *
112  * Private macros.
113  *
114  *****************************************************************************/
115 #define IsWhiteSpace(x) \
116                 (((x) == '\n' || (x) == ' ' || (x) == '\t') ? 1 : 0)
117
118 #define IsNumber(x) \
119                 (((x) >= '0' && (x) <= '9') ? 1 : 0)
120
121 /******************************************************************************
122  *
123  * Private data.
124  *
125  *****************************************************************************/
126 static ClassStyleMatrix ClassToStyle[] =
127   {
128     { SdlClassAcro  , SdlClassUdefkey  , SdlElementKeyStyle  },
129     { SdlClassLabel , SdlClassUdefhead , SdlElementHeadStyle },
130     { SdlClassTable , SdlClassUdeffrmt , SdlElementFormStyle },
131     { SdlClassTable , SdlClassUdeffrmt , SdlElementFrmtStyle },
132     { SdlClassFigure, SdlClassUdefgraph, SdlElementGrphStyle },
133     { SdlOptionBad  , SdlOptionBad     , SdlElementNone      },
134   };
135
136 /******************************************************************************
137  *
138  * Private Functions
139  *
140  *****************************************************************************/
141 /******************************************************************************
142  * Function:    static int SkipWhiteSpace (BufFilePtr f)
143  *
144  * Parameters:
145  *
146  * Returns       0 if successfully skipped white space.
147  *              -1 if errors.
148  *
149  * errno Values:
150  *
151  * Purpose:
152  *
153  *****************************************************************************/
154 static int
155 SkipWhiteSpace (
156     BufFilePtr   f)
157 {
158     char   c;
159
160     do {
161         c = BufFileGet(f);
162         if (c == BUFFILEEOF)
163             return -1;
164
165     } while (IsWhiteSpace(c));
166
167     BufFilePutBack(c, f);
168
169
170     return 0;
171 }
172
173 /******************************************************************************
174  * Function:    static int CheckSDLAttributeNameStart (char c)
175  *
176  * Parameters:
177  *
178  * Returns       0 if starts correctly,
179  *              -1 if does not start correctly for an attribute name
180  *
181  * errno Values:
182  *
183  * Purpose:
184  *
185  *****************************************************************************/
186 static int
187 CheckSDLAttributeNameStart (char c)
188 {
189     if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'))
190         return 0;
191
192     return -1;
193 }
194
195 /******************************************************************************
196  * Function:    int GetSDLElement (BufFilePtr f, char **string)
197  *
198  * Parameters:
199  *
200  * Returns       0 if got an element (subject to verification).
201  *               1 if end of file/compressed section.
202  *              -1 if errors.
203  *
204  * errno Values:
205  *
206  * Memory owned:  the returned string.
207  *
208  * Purpose:
209  *
210  *****************************************************************************/
211 static int
212 GetSDLElement (
213     BufFilePtr   f,
214     int          max_allowed,
215     char        *string)
216 {
217     _DtCvValue     done     = False;
218     _DtCvValue     first    = True;
219     _DtCvValue     nonWhite = False;
220     _DtCvValue     startEl  = False;
221     int           len      = 0;
222     char    c;
223
224     do {
225         c = BufFileGet(f);
226
227         /*
228          * [chars][space]       (nonWhite == True  && IsWhiteSpace(c))
229          * <element>            (startEl  == True  && c == '>')
230          * [chars]<element..    (first    == False && c == '<')
231          */
232         if (c == BUFFILEEOF || (nonWhite == True && IsWhiteSpace(c))
233                 || (startEl == True  && c == '>')
234                 || (first   == False && c == '<'))
235           {
236             if (c == '>'  || c == '<' || (nonWhite == True && IsWhiteSpace(c)))
237                 BufFilePutBack(c,f);
238             done = True;
239           }
240         else
241           {
242             if (first == True && c == '<')
243                 startEl = True;
244
245             first = False;
246             if (nonWhite == False && IsWhiteSpace(c) == False)
247                 nonWhite = True;
248
249             string[len++] = c;
250
251             if (len >= max_allowed)
252                 done = True;
253           }
254     } while (!done);
255
256     string[len] = '\0';
257
258     if (len == 0)
259       {
260         if (c != BUFFILEEOF)
261             return -1;
262
263         else /* if (c == BUFFILEEOF) */
264             return 1;
265       }
266
267     return 0;
268 }
269
270 /******************************************************************************
271  *
272  * Semi Public Functions
273  *
274  *****************************************************************************/
275 /******************************************************************************
276  * Function:    int _DtHelpCeMatchSdlElement (BufFilePtr my_file,
277  *                                      const char *element_str, int sig_chars)
278  *
279  * Parameters:
280  *
281  * Returns       0 if successfully matched element_str,
282  *               1 if did not match,
283  *              -1 if errors.
284  *
285  * errno Values:
286  *
287  * Purpose:
288  *
289  *****************************************************************************/
290 int
291 _DtHelpCeMatchSdlElement (
292     BufFilePtr   f,
293     const char  *element_str,
294     int          sig_chars)
295 {
296     int   len;
297     int   different = False;
298     char  nextEl[MAX_ELEMENT_SIZE + 2];
299     char *ptr;
300     char  c;
301
302     /*
303      * get the next element in the stream
304      */
305     do {
306         if (GetSDLElement(f, MAX_ELEMENT_SIZE, nextEl) != 0)
307             return -1;
308
309         /*
310          * now skip the white space
311          */
312         ptr = nextEl;
313         while (IsWhiteSpace(*ptr)) ptr++;
314
315       } while (*ptr == '\0');
316
317     len = strlen(element_str);
318
319     do {
320         /*
321          * get the lowered version of the character
322          */
323         c = _DtHelpCeToLower(*ptr);
324         if (c != *element_str)
325             different = True;
326
327         len--;
328         sig_chars--;
329         element_str++;
330         ptr++;
331
332     } while (len && sig_chars && !different && *ptr != '\0');
333
334     if (!different && sig_chars > 0 && len > 0)
335         different = True;
336
337     return different;
338 }
339
340 /******************************************************************************
341  * Function:    int _DtHelpCeGetSdlAttribute (BufFilePtr f,
342  *                                      char *attribute_name)
343  *
344  * Parameters:
345  *              f               Specifies the buf file to read.
346  *              max_len         Specifies the maximum number of characters
347  *                              that can fit in 'attribute_name'. Does
348  *                              *NOT* include the terminating null byte.
349  *              attribute_name  Specifies the buffer in which to place
350  *                              the attribute.
351  *
352  *
353  * Returns       0 if successfully retrieved an attribute name.
354  *               1 if there is no more attributes (eats the element end).
355  *              -1 if errors.
356  *
357  * errno Values:
358  *
359  * Purpose:     Reads the an attribute.
360  *              Lower cases the attribute.
361  *
362  *****************************************************************************/
363 int
364 _DtHelpCeGetSdlAttribute (
365     BufFilePtr   f,
366     int          max_len,
367     char        *attribute_name)
368 {
369     int   len = 0;
370     char  c;
371
372     if (SkipWhiteSpace(f) != 0)
373         return -1;
374
375     /*
376      * check that the attribute name starts correctly
377      */
378     c = BufFileGet(f);
379     if (c == '>')
380         return 1;
381
382     if (CheckSDLAttributeNameStart(c) != 0)
383         return -1;
384
385     do {
386         c = _DtHelpCeToLower(c);
387
388         attribute_name[len++] = c;
389
390         c = BufFileGet(f);
391
392     } while (c != BUFFILEEOF && !IsWhiteSpace(c) && c != '=' && len < max_len);
393
394     while (c != '=')
395       {
396         c = BufFileGet(f);
397         if (c == BUFFILEEOF)
398             return -1;
399       }
400
401     if (len == 0 || len >= max_len)
402         return -1;
403
404     attribute_name[len] = '\0';
405
406     return 0;
407 }
408
409 /******************************************************************************
410  * Function:    int _DtHelpCeReturnSdlElement ()
411  *
412  * Parameters:
413  *
414  *
415  * Returns       0 if matched an element in the list
416  *               1 hit eof on the file/compressed section.
417  *              -1 if errors.
418  *
419  * errno Values:
420  *
421  * Purpose:
422  *
423  * Memory Owned By Caller:      number_str
424  *
425  *****************************************************************************/
426 int
427 _DtHelpCeReturnSdlElement (
428     BufFilePtr            f,
429     const SDLElementInfo *el_list,
430     _DtCvValue            cdata_flag,
431     enum SdlElement      *ret_el_define,
432     char                **ret_data,
433     _DtCvValue           *ret_end_flag)
434 {
435     int        result;
436     int        lowerChar;
437     _DtCvValue  endFlag   = False;
438     _DtCvValue  different = True;
439     char       nextEl[MAX_ELEMENT_SIZE + 2];
440     char      *ptr;
441
442     *ret_el_define = SdlElementCdata;
443     *ret_end_flag  = False;
444     if (ret_data)
445         *ret_data = NULL;
446
447     /*
448      * get the next element
449      */
450     do {
451         result = GetSDLElement(f, MAX_ELEMENT_SIZE, nextEl);
452         if (result == 1)
453           {
454             *ret_el_define = SdlElementNone;
455             return 1;
456           }
457         else if (result == -1)
458             return -1;
459
460         /*
461          * lower case the element. String dup it first incase this is data
462          * and not an element. Then skip the leading white space.
463          */
464         ptr     = nextEl;
465         while (IsWhiteSpace(*ptr) == True) ptr++;
466       } while (cdata_flag == False && *ptr == '\0');
467
468     /*
469      * An element starts with a less than sign,
470      * An end element starts with a less than sign and a forward slash.
471      */
472
473     /*
474      * if all we've got is white space, or a non starting character,
475      * then skip the loop
476      */
477     if (*ptr == '<')
478       {
479         /*
480          * skip the less than sign.
481          */
482         ptr++;
483
484         /*
485          * is this an end element?
486          */
487         if (*ptr == '/')
488           {
489             endFlag = True;
490             ptr++;
491           }
492
493         lowerChar = (int) _DtHelpCeToLower(*ptr);
494
495         while (different && el_list->element_str != NULL)
496           {
497             if (endFlag == True && el_list->element_end_str != NULL &&
498                 lowerChar == ((int)(el_list->element_end_str[2])) &&
499                 _DtHelpCeStrNCaseCmpLatin1(&(el_list->element_end_str[2]),
500                                         ptr, el_list->end_sig_chars - 2) == 0)
501               {
502                 different = False;
503                 *ret_end_flag = True;
504               }
505             else if (endFlag == False &&
506                 lowerChar == ((int)(el_list->element_str[1])) &&
507                  _DtHelpCeStrNCaseCmpLatin1(&(el_list->element_str[1]), ptr,
508                                         el_list->str_sig_chars - 1) == 0)
509                 different = False;
510             else
511                 el_list++;
512           }
513         *ret_el_define = el_list->sdl_element;
514       }
515
516     if (*ret_el_define == SdlElementCdata && ret_data != NULL)
517         *ret_data = strdup(nextEl);
518
519     return 0;
520 }
521
522 /******************************************************************************
523  * Function:    int _DtHelpCeGetSdlCdata (BufFilePtr f, char **string)
524  *
525  * Parameters:
526  *
527  *
528  * Returns       0 if successfully retrieved data.
529  *               1 if returning because type != SdlTypeDynamic and a newline
530  *                 was found.
531  *               2 if returning because ran into a non-breaking character.
532  *              -1 if errors.
533  *
534  * errno Values:
535  *
536  * Purpose:
537  *
538  * Memory Owned By Caller:      attribute_name
539  *
540  *****************************************************************************/
541 int
542 _DtHelpCeGetSdlCdata (
543     BufFilePtr     f,
544     SdlOption      type,
545     int            max_mb,
546     _DtCvValue     nl_to_space,
547     _DtCvValue    *cur_space,
548     _DtCvValue    *cur_nl,
549     _DtCvValue    *cur_mb,
550     char         *non_break_char,
551     char        **string,
552     int          *str_max)
553 {
554     _DtCvValue  lastWasSpace = *cur_space;
555     _DtCvValue  lastWasNl    = *cur_nl;
556     _DtCvValue  lastWasMb    = *cur_mb;
557     _DtCvValue  ignore  = False;
558     _DtCvValue  done    = False;
559     _DtCvValue  escaped = False;
560     int        strSize = 0;
561     int        reason  = 0;
562     int        len     = 0;
563     int        strMB   = 1;
564     char      *ptr;
565     char       buf[MB_LEN_MAX + 1];
566 #define ESC_STR_LEN     4
567     char       escStr[ESC_STR_LEN];
568     char       c;
569
570     if (string == NULL)
571         ignore = True;
572     else if (*string != NULL)
573       {
574         strSize = strlen(*string);
575         if (*str_max < strSize)
576            *str_max = strSize;
577       }
578
579     do {
580         c = BufFileGet(f);
581
582         buf[len++] = c;
583         buf[len]   = '\0';
584
585         if (c != BUFFILEEOF && max_mb != 1)
586             strMB = mblen(buf, max_mb);
587
588         if (c == BUFFILEEOF || (escaped == False && strMB == 1 &&
589                 (c == '<' ||
590                     ((type == SdlTypeLiteral || type == SdlTypeLined) &&
591                         c == '\n'))))
592           {
593             if (c == '\n')
594                 reason = 1;
595             else if (c == '<')
596                 BufFilePutBack(c,f);
597
598             done = True;
599           }
600         else if (strMB == 1)
601           {
602             len = 0;
603
604             if (lastWasNl == True)
605               {
606                 ptr = " ";
607                 if (_DtHelpCeAddCharToBuf(&ptr, string, &strSize,
608                                                         str_max, 32) == -1)
609                     return -1;
610                 lastWasSpace = True;
611               }
612
613             lastWasMb = False;
614             lastWasNl = False;
615
616             if (escaped == True)
617               {
618                 if (c == '#')
619                   {
620                     /*
621                      * process the SGML numeric character reference
622                      * entity.  '&#d[d[d]][;]' - 'ddd' represent
623                      * characters of '0' to '9'.  The semi-colon is
624                      * required iff the next character is a numeric
625                      * character of '0' to '9'.  Otherwise it is
626                      * optional.
627                      */
628                     int  value;
629
630                     len = 0; /* len should be zero here, but let's make sure */
631                     do
632                       {
633                         /*
634                          * get the next character.
635                          */
636                         c = BufFileGet(f);
637
638                         /*
639                          * if it is the first character of the numeric entity,
640                          * it has to be a numeric character.
641                          */
642                         if (c == BUFFILEEOF ||
643                                         (len == 0 && (c < '0' || c > '9')))
644                             return -1;
645
646                         /*
647                          * put the character in the buffer
648                          */
649                         escStr[len++] = c;
650
651                       } while (len < ESC_STR_LEN && c >= '0' && c <= '9');
652
653                     /*
654                      * the ending character of the entity has to be a
655                      * non-numeric character.
656                      */
657                     if (c >= '0' && c <= '9')
658                         return -1;
659                     /*
660                      * if the optional semi-colon is not present, replace
661                      * the terminating character back in the input buffer
662                      * to be processed in the next pass.
663                      */
664                     else if (c != ';')
665                         BufFilePutBack(c, f);
666
667                     /*
668                      * get the integer value. It has to be less than 256.
669                      */
670                     value = atoi(escStr);
671                     if (value > 255)
672                         return -1;
673
674                     /*
675                      * transfer the value to the character variable
676                      * and zero the index for the general buffer.
677                      */
678                     c   = value;
679                     len = 0;
680
681                      /*
682                       * set up for the return information
683                       */
684                      done   = True;
685                      reason = 2;
686                      *non_break_char = c;
687                   }
688
689                 /*
690                  * clear the escaped flag, so that the character gets
691                  * put in the output buffer.
692                  */
693                 escaped = False;
694               }
695             else if (c == '\n')
696               {
697                 if (type == SdlTypeCdata)
698                     lastWasSpace = False;
699                 else if (lastWasSpace == False)
700                     lastWasNl = True;
701                 continue;
702               }
703             else if (c == '&')
704                 escaped = True;
705
706             if (escaped == False && ignore == False)
707               {
708                 if (c == '\t')
709                     c = ' ';
710
711                 ptr = &c;
712                 if (c == '\n')
713                   {
714                     lastWasSpace = True;
715                     reason       = 1;
716                     done         = True;
717                   }
718                 /*
719                  * as long as we aren't processing a non break character,
720                  * add it to the buffer.
721                  */
722                 else if (2 != reason)
723                   {
724                     if (c != ' ')
725                         lastWasSpace = False;
726
727                     if ((lastWasSpace == False || type == SdlTypeLiteral ||
728                                                 type == SdlTypeUnlinedLiteral)
729                                 &&
730                         _DtHelpCeAddCharToBuf(&ptr, string, &strSize,
731                                                         str_max, 32) == -1)
732                             return -1;
733
734                     if (type != SdlTypeLiteral &&
735                                 type != SdlTypeUnlinedLiteral && c == ' ')
736                         lastWasSpace = True;
737                   }
738               }
739           }
740         else if (strMB > 1)
741           {
742             if (ignore == False)
743               {
744                 if (lastWasNl == True)
745                   {
746                     if (nl_to_space == True || lastWasMb == False)
747                       {
748                         ptr = " ";
749                         if (_DtHelpCeAddCharToBuf(&ptr, string, &strSize,
750                                                         str_max, 32) == -1)
751                             return -1;
752                       }
753                   }
754
755                 ptr = buf;
756                 if (_DtHelpCeAddStrToBuf(&ptr,string,&strSize,str_max,len,32)
757                                                 == -1)
758                     return -1;
759               }
760             lastWasMb    = True;
761             lastWasNl    = False;
762             lastWasSpace = False;
763             escaped      = False;
764             len          = 0;
765           }
766         else if (strMB == 0 || len > max_mb || len >= MB_LEN_MAX)
767             return -1;
768
769     } while (done == False);
770
771     *cur_space = lastWasSpace;
772     *cur_nl    = lastWasNl;
773     *cur_mb    = lastWasMb;
774     return reason;
775 }
776
777 /******************************************************************************
778  * Function:    int _DtHelpCeGetSdlAttributeCdata (BufFilePtr f, char **string);
779  *
780  * Parameters:
781  *
782  *
783  * Returns       0 if successfully retrieved an attribute name.
784  *              -1 if errors.
785  *
786  * errno Values:
787  *
788  * Purpose:     Parses the CDATA value for an element attribute. Expects the
789  *              pointer to be after the equals sign of the attribute.  The
790  *              CDATA must be included in quotes (either single or double)
791  *              and can have white space (spaces, newlines or tabs) preceding
792  *              it.  Any newline encountered within the CDATA value is turned
793  *              into a space.  Any quote enclosed in the CDATA must not be the
794  *              same type as what is used to delimit the CDATA value.  I.E.
795  *              if a single quote is used in the CDATA, the CDATA value must
796  *              be enclosed in double quotes.
797  *
798  * Memory Owned By Caller:      attribute_name
799  *
800  *****************************************************************************/
801 int
802 _DtHelpCeGetSdlAttributeCdata (
803     BufFilePtr    f,
804     _DtCvValue    limit,
805     char        **string)
806 {
807     _DtCvValue   ignore      = False;
808     _DtCvValue   done        = False;
809     _DtCvValue   firstChar   = True;
810     int         strSize     = 0;
811     int         strMax      = 0;
812     char       *myStr       = NULL;
813     char        c;
814     char        testChar;
815
816     if (string == NULL)
817         ignore = True;
818     else if (limit == True)
819         myStr = *string;
820
821     if (SkipWhiteSpace(f) != 0)
822         return -1;
823
824     do {
825         c = BufFileGet(f);
826         if (c == BUFFILEEOF)
827           {
828             if (myStr != NULL)
829                 free(myStr);
830             return -1;
831           }
832
833         if (firstChar)
834           {
835             if (c == '\'' || c == '\"')
836               {
837                 testChar  = c;
838                 firstChar = False;
839               }
840             else
841               {
842                 if (myStr != NULL)
843                     free(myStr);
844                 return -1;
845               }
846           }
847         else if (c == testChar)
848             done = True;
849         else if (ignore == False)
850           {
851             if (c == '\n')
852                 c = ' ';
853
854             if (limit == True && strSize >= DTD_NAMELEN)
855               {
856                 if (myStr != NULL)
857                     free(myStr);
858                 return -1;
859               }
860             else if (limit == False && strSize >= strMax)
861               {
862                 strMax += 64;
863                 if (strSize == 0)
864                     myStr = (char *) malloc (sizeof(char) * 65);
865                 else
866                     myStr = (char *) realloc (myStr,(sizeof(char)*(strMax+1)));
867
868                 if (myStr == NULL)
869                     return -1;
870               }
871
872             myStr[strSize++] = c;
873           }
874     } while (done == False);
875
876     if (ignore == False)
877       {
878         if (myStr != NULL)
879             myStr[strSize] = '\0';
880         if (limit == False)
881             *string = myStr;
882       }
883
884     return 0;
885 }
886
887 /******************************************************************************
888  * Function:    int _DtHelpCeSkipCdata (BufFilePtr f, _DtCvValue Flag)
889  *
890  * Parameters:
891  *
892  *
893  * Returns       0 if successfully retrieved an attribute name.
894  *              -1 if errors.
895  *
896  * errno Values:
897  *
898  * Purpose:
899  *
900  * Memory Owned By Caller:      attribute_name
901  *
902  *****************************************************************************/
903 int
904 _DtHelpCeSkipCdata (
905     BufFilePtr    f,
906     _DtCvValue    flag)
907 {
908     _DtCvValue   done        = False;
909     _DtCvValue   singleQuote = False;
910     _DtCvValue   doubleQuote = False;
911     _DtCvValue   comment     = False;
912     _DtCvValue   element     = False;
913     _DtCvValue   bracket     = False;
914     _DtCvValue   processing  = True;
915     char        c;
916
917     do {
918         c = BufFileGet(f);
919         if (c == BUFFILEEOF)
920             return -1;
921
922         if (processing)
923           {
924             if (c == '\'')
925               {
926                 singleQuote = True;
927                 processing  = False;
928               }
929             else if (c == '\"')
930               {
931                 doubleQuote = True;
932                 processing  = False;
933               }
934             else if (c == '-')
935               {
936                 c = BufFileGet(f);
937                 if (c == BUFFILEEOF)
938                 return -1;
939             
940                 if (c == '-')
941                   {
942                     comment    = True;
943                     processing = False;
944                   }
945                 else
946                     BufFilePutBack(c,f);
947               }
948             else if (!element && c == '<')
949                   element = True;
950
951             else if (c == '>')
952               {
953                 if (element)
954                     element = False;
955                 else
956                   {
957                     BufFilePutBack(c,f);
958                     done = True;
959                   }
960               }
961             else if (flag && c == '[')
962                 bracket = True;
963
964             else if (bracket && c == ']')
965               {
966                 bracket = False;
967                 flag    = False;
968               }
969           }
970         else
971           {
972             if (singleQuote && c == '\'')
973               {
974                 singleQuote = False;
975                 processing  = True;
976               }
977             else if (doubleQuote && c == '\"')
978               {
979                 doubleQuote = False;
980                 processing  = True;
981               }
982             else if (comment && c == '-')
983               {
984                 c = BufFileGet(f);
985                 if (c == BUFFILEEOF)
986                     return -1;
987             
988                 if (c == '-')
989                   {
990                     comment     = False;
991                     processing  = True;
992                   }
993                 else
994                     BufFilePutBack(c,f);
995               }
996           }
997     } while (done == False);
998
999     if (flag)
1000         return -1;
1001
1002     return 0;
1003 }
1004
1005 /******************************************************************************
1006  * Function:    int _DtHelpCeGetSdlId (BufFilePtr f, char **id_value)
1007  *
1008  * Parameters:
1009  *
1010  *
1011  * Returns       0 if successfully retrieved an attribute name.
1012  *              -1 if errors.
1013  *
1014  * errno Values:
1015  *
1016  * Purpose:
1017  *
1018  * Memory Owned By Caller:      id_value
1019  *
1020  *****************************************************************************/
1021 int
1022 _DtHelpCeGetSdlId (
1023     BufFilePtr   f,
1024     char        **id_value)
1025 {
1026     *id_value = NULL;
1027
1028     if (_DtHelpCeGetSdlAttributeCdata (f, False, id_value) != 0)
1029         return -1;
1030
1031     /*
1032      * check that the attribute name starts correctly
1033      */
1034     if (CheckSDLAttributeNameStart(**id_value) != 0)
1035         return -1;
1036
1037     return 0;
1038 }
1039
1040 /******************************************************************************
1041  * Function:    int _DtHelpCeGetSdlNumber (BufFilePtr f, char **number_str)
1042  *
1043  * Parameters:
1044  *
1045  *
1046  * Returns       0 if successfully retrieved an attribute name.
1047  *              -1 if errors.
1048  *
1049  * errno Values:
1050  *
1051  * Purpose:
1052  *
1053  * Memory Owned By Caller:      number_str
1054  *
1055  *****************************************************************************/
1056 int
1057 _DtHelpCeGetSdlNumber (
1058     BufFilePtr   f,
1059     char        *number_str)
1060 {
1061     if (_DtHelpCeGetSdlAttributeCdata(f, True, &number_str) != 0)
1062         return -1;
1063
1064     /*
1065      * check that the attribute name starts correctly
1066      */
1067     if (!IsNumber(*number_str))
1068         return -1;
1069
1070     return 0;
1071 }
1072
1073 /******************************************************************************
1074  * Function:    int _DtHelpCeFindSkipSdlElementEnd (BufFilePtr f)
1075  *
1076  * Parameters:
1077  *
1078  *
1079  * Returns       0 if successfully retrieved an attribute name.
1080  *              -1 if errors.
1081  *
1082  * errno Values:
1083  *
1084  * Purpose:
1085  *
1086  * Memory Owned By Caller:      attribute_name
1087  *
1088  *****************************************************************************/
1089 int
1090 _DtHelpCeFindSkipSdlElementEnd (
1091     BufFilePtr   f)
1092 {
1093     char  c;
1094
1095     if (SkipWhiteSpace(f) != 0)
1096         return -1;
1097
1098     do {
1099         c = BufFileGet(f);
1100         if (c == BUFFILEEOF)
1101           return -1;
1102
1103     } while (c != '>');
1104
1105     return 0;
1106 }
1107
1108 /******************************************************************************
1109  * Function:    int _DtHelpCeMergeSdlAttribInfo (_DtCanvasStruct canvas,
1110  *                              _DtCvSegment *src_el,
1111  *                              _DtCvSegment *dst_el);
1112  *
1113  * Parameters:
1114  *
1115  * Returns:     nothing
1116  *
1117  * Purpose: Merge the src specified attributes into the dst.
1118  *          THIS WILL NOT MERGE THE SSI or RSSI values.
1119  *
1120  ******************************************************************************/
1121 void
1122 _DtHelpCeMergeSdlAttribInfo(
1123     _DtCvSegment                *src_seg,
1124     _DtCvSegment                *dst_seg,
1125     _DtHelpFontHints            *dst_fonts,
1126     void                        *el_info,
1127     unsigned long               *str1_values,
1128     unsigned long               *str2_values)
1129 {
1130     unsigned long        flag;
1131     const SDLAttribute  *pAttr;
1132     SdlOption           *dstEnum;
1133     SdlOption           *srcEnum;
1134     SDLNumber           *dstNum;
1135     SDLNumber           *srcNum;
1136     SDLCdata            *dstStr;
1137     SDLCdata            *srcStr;
1138     SDLTossInfo         *tossInfo;
1139     char                *src;
1140     char                *dst;
1141
1142     if (src_seg != NULL)
1143       {
1144         tossInfo = _SdlSegPtrToTossInfo(src_seg);
1145         for (pAttr = _DtHelpCeGetSdlAttributeList();
1146                         pAttr->data_type != SdlAttrDataTypeInvalid; pAttr++)
1147           {
1148             if ((pAttr->struct_type == SdlFontSpecific ||
1149                                 pAttr->struct_type == SdlContainerSpecific)
1150                         &&
1151                 SDLIsAttrSet(*tossInfo, pAttr->sdl_attr_define)
1152                         &&
1153                 !(ATTRS_EQUAL(pAttr->data_type, pAttr->sdl_attr_define,
1154                                 SDL_ATTR_SSI) ||
1155                   ATTRS_EQUAL(pAttr->data_type, pAttr->sdl_attr_define,
1156                                 SDL_ATTR_RSSI)))
1157               {
1158                 if (pAttr->struct_type == SdlFontSpecific)
1159                   {
1160                     src = ((char *)(&(_SdlTossInfoPtrFontSpecs(tossInfo))));
1161                     dst = ((char *) dst_fonts);
1162                   }
1163                 else /* if (pAttr->struct_type == SdlContainerSpecific) */
1164                   {
1165                     src = ((char *)_SdlContainerPtrOfSeg(src_seg));
1166                     dst = ((char *)_SdlContainerPtrOfSeg(dst_seg));
1167                   }
1168
1169                 switch (SDLAttrFlagType(pAttr->sdl_attr_define))
1170                   {
1171                     case ENUM_VALUE:
1172                         dstEnum  = (SdlOption *)
1173                                         (((char *)dst) + pAttr->field_ptr);
1174                         srcEnum  = (SdlOption *)
1175                                         (((char *)src) + pAttr->field_ptr);
1176                         *dstEnum = *srcEnum;
1177                         break;
1178
1179                     case NUMBER_VALUE:
1180                         dstNum  = (SDLNumber *)
1181                                         (((char *)dst) + pAttr->field_ptr);
1182                         srcNum  = (SDLNumber *)
1183                                         (((char *)src) + pAttr->field_ptr);
1184                         *dstNum = *srcNum;
1185                         break;
1186
1187                     case STRING1_VALUE:
1188                     case STRING2_VALUE:
1189                         dstStr  = (SDLCdata *)
1190                                         (((char *)dst) + pAttr->field_ptr);
1191                         srcStr  = (SDLCdata *)
1192                                         (((char *)src) + pAttr->field_ptr);
1193                         *dstStr = *srcStr;
1194                         break;
1195
1196                   }
1197               }
1198             else if (NULL != el_info &&
1199                         pAttr->struct_type == SdlElementSpecific &&
1200                                 SDLIsAttrSet(*tossInfo, pAttr->sdl_attr_define))
1201               {
1202                 flag = pAttr->sdl_attr_define & ~(VALUE_MASK);
1203
1204                 dstStr = (SDLCdata *)(((char *)el_info) + pAttr->field_ptr);
1205                 if (SDL_ATTR_COLW == pAttr->sdl_attr_define)
1206                     *dstStr = _SdlTossInfoPtrColW(tossInfo);
1207                 else if (SDL_ATTR_COLJ == pAttr->sdl_attr_define)
1208                     *dstStr = _SdlTossInfoPtrColJ(tossInfo);
1209                 else if (SDL_ATTR_ENTER == pAttr->sdl_attr_define)
1210                     *dstStr = _SdlTossInfoPtrEnter(tossInfo);
1211                 else if (SDL_ATTR_EXIT == pAttr->sdl_attr_define)
1212                     *dstStr = _SdlTossInfoPtrExit(tossInfo);
1213
1214                 if (STRING1_VALUE == (pAttr->sdl_attr_define & VALUE_MASK))
1215                    *str1_values = *str1_values | flag;
1216                 else if (STRING2_VALUE == (pAttr->sdl_attr_define & VALUE_MASK))
1217                    *str2_values = *str2_values | flag;
1218               }
1219           }
1220       }
1221 }
1222
1223 /******************************************************************************
1224  * Function:    void _DtHelpCeAddSegToList (_DtCvSegment *seg_ptr,
1225  *                              _DtCvSegment **seg_list,
1226  *                              _DtCvSegment **last_seg)
1227  *
1228  * Parameters:
1229  *
1230  * Returns:     0 if successful, -1 if errors
1231  *
1232  * errno Values:
1233  *
1234  * Purpose:     Allocates a memory
1235  *
1236  ******************************************************************************/
1237 void
1238 _DtHelpCeAddSegToList(
1239     _DtCvSegment        *seg_ptr,
1240     _DtCvSegment **seg_list,
1241     _DtCvSegment **last_seg)
1242 {
1243     if (*seg_list == NULL)
1244         *seg_list = seg_ptr;
1245     else
1246         (*last_seg)->next_seg = seg_ptr;
1247
1248     while (NULL != seg_ptr->next_seg)
1249         seg_ptr = seg_ptr->next_seg;
1250
1251     *last_seg = seg_ptr;
1252 }
1253
1254 /******************************************************************************
1255  * Function:    int _DtHelpCeAllocSegment (
1256  *                                      int  malloc_size,
1257  *                                      int *alloc_size,
1258  *                                      _DtCvSegment **next_seg,
1259  *                                      _DtCvSegment **seg_ptr);
1260  *
1261  * Parameters:
1262  *              malloc_size     Specifies the number of blocks to
1263  *                              malloc. The first one is returned in
1264  *                              'seg_ptr' with the rest in 'next_seg',
1265  *                              if 'next_seg' is non-NULL.
1266  *              alloc_size      Ignored if NULL. If non-NULL, indicates
1267  *                              the number of blocks in 'next_seg' if
1268  *                              'next_seg' is non-NULL and the 'next_seg'
1269  *                              pointer is non-NULL.
1270  *              next_seg        Specifies the block of memory to take the
1271  *                              next segment from.
1272  *                              Returns the pointer to the next segment.
1273  *              seg_ptr         Returns a pointer to the segment to use.
1274  *
1275  * Returns:     0 if successful, -1 if errors
1276  *
1277  * Purpose:     Allocates a memory
1278  *
1279  ******************************************************************************/
1280 int
1281 _DtHelpCeAllocSegment(
1282     int           malloc_size,
1283     int          *alloc_size,
1284     _DtCvSegment   **next_seg,
1285     _DtCvSegment   **seg_ptr)
1286 {
1287     int          cnt    = 0;
1288     _DtCvSegment        *newSeg = NULL;
1289
1290     if (next_seg != NULL)
1291         newSeg = *next_seg;
1292
1293     if (alloc_size != NULL && newSeg != NULL)
1294         cnt = *alloc_size;
1295
1296     if (cnt < 1)
1297       {
1298         newSeg = _DtHelpAllocateSegments(malloc_size);
1299         if (newSeg == NULL)
1300             return -1;
1301
1302         cnt    = --malloc_size;
1303       }
1304     else
1305         cnt--;
1306
1307     *seg_ptr    = newSeg++;
1308     if (next_seg != NULL)
1309       {
1310         *next_seg = NULL;
1311         if (cnt > 0)
1312             *next_seg   = newSeg;
1313       }
1314     if (alloc_size != NULL)
1315         *alloc_size = cnt;
1316
1317     return 0;
1318 }
1319
1320 /******************************************************************************
1321  * Function:    int _DtHelpCeSaveString (
1322  *                              string, multi_len)
1323  *
1324  * Parameters:
1325  *
1326  * Returns:     0 if successful, -1 if errors
1327  *
1328  * errno Values:
1329  *
1330  * Purpose:     Looks for the virtual page beginning.
1331  *
1332  ******************************************************************************/
1333 int
1334 _DtHelpCeSaveString(
1335     _DtCvPointer  client_data,
1336     _DtCvSegment        **seg_list,
1337     _DtCvSegment        **last_seg,
1338     _DtCvSegment        **prev_seg,
1339     char         *string,
1340     _DtHelpFontHints   *font_specs,
1341     int           link_index,
1342     int           multi_len,
1343     int           flags,
1344     void        (*load_font)(),
1345     _SdlFontMode  resolve_font,
1346     _DtCvValue     newline)
1347 {
1348
1349     int        len;
1350     int        size;
1351     int        numChars = 0;
1352     int        junk    = 0;
1353     char       tmpChar;
1354     char         *ptr     = string;
1355     _DtCvSegment    *pSeg = NULL;
1356     _DtCvSegment    *junkSeg  = NULL;
1357     _DtHelpFontHints   *fontSpec = NULL;
1358     _DtCvValue addToList = False;
1359     _DtCvPointer useFont = (_DtCvPointer) -1;
1360
1361     if (*ptr == '\0')
1362       {
1363         if (newline == True)
1364           {
1365             if (_DtHelpCeAllocSegment(1, &junk, &junkSeg, &pSeg) != 0)
1366                 return -1;
1367             addToList = True;
1368           }
1369       }
1370     else
1371       {
1372         if (_SdlFontModeResolve == resolve_font)
1373             (*load_font)(client_data, _DtHelpFontHintsLang(*font_specs),
1374                                 _DtHelpFontHintsCharSet(*font_specs),
1375                                 *font_specs, &useFont);
1376
1377         while (*ptr != '\0')
1378           {
1379             if (_DtHelpCeAllocSegment(1, &junk, &junkSeg, &pSeg) != 0)
1380                 return -1;
1381
1382             if (_SdlFontModeSave == resolve_font)
1383               {
1384                 fontSpec = (_DtHelpFontHints *) malloc (sizeof(_DtHelpFontHints));
1385                 if (NULL == fontSpec)
1386                   {
1387                     free(pSeg);
1388                     return -1;
1389                   }
1390
1391                 /*
1392                  * copy the current fonts over
1393                  */
1394                 *fontSpec = *font_specs;
1395                 useFont   = (_DtCvPointer) fontSpec;
1396               }
1397
1398             /*
1399              * set the type
1400              */
1401             pSeg->type = _DtCvSetTypeToString(flags);
1402
1403             /*
1404              * set the wide char flag if necessary.
1405              */
1406             len = 1;
1407             if (multi_len != 1)
1408               {
1409                 len  = mblen (ptr, MB_CUR_MAX);
1410                 size = _DtHelpFmtFindBreak(ptr, len, &numChars);
1411                 if (1 != len)
1412                     pSeg->type = _DtCvSetTypeToWideChar(pSeg->type);
1413               }
1414             else
1415                 size = strlen(ptr);
1416     
1417             /*
1418              * set the link flag
1419              */
1420             if (link_index != -1)
1421               {
1422                 pSeg->type = _DtCvSetTypeToHyperText(pSeg->type);
1423                 pSeg->link_idx = link_index;
1424               }
1425     
1426             tmpChar   = ptr[size];
1427             ptr[size] = '\0';
1428     
1429             /*
1430              * save the string appropriately.
1431              */
1432             if (_DtCvIsSegWideChar(pSeg))
1433               {
1434                 wchar_t *pwcs;
1435                 size_t   convSize;
1436
1437                 /*
1438                  * include the terminating byte in the conversion.
1439                  */
1440                 numChars++;
1441
1442                 /*
1443                  * malloc the memory
1444                  */
1445                 pwcs = (wchar_t *) malloc(sizeof(wchar_t) * numChars);
1446                 if (NULL != pwcs)
1447                   {
1448                     /* convert */
1449                     convSize = mbstowcs(pwcs, string, ((size_t) numChars));
1450
1451                     /* check to see if it converted everything */
1452                     if (convSize + 1 == numChars)
1453                         _DtCvStringOfStringSeg(pSeg) = (void *) pwcs;
1454                     else
1455                         free(pwcs);
1456                   }
1457               }
1458             else
1459                 _DtCvStringOfStringSeg(pSeg) = (void *) strdup(string);
1460
1461             if (NULL == _DtCvStringOfStringSeg(pSeg))
1462                 return -1;
1463
1464             /*
1465              * set the font
1466              */
1467             _DtCvFontOfStringSeg(pSeg)  = useFont;
1468
1469             /*
1470              * setup the list pointers
1471              */
1472             if (*prev_seg != NULL)
1473                 (*prev_seg)->next_disp = pSeg;
1474     
1475             *prev_seg = pSeg;
1476     
1477             _DtHelpCeAddSegToList(pSeg, seg_list, last_seg);
1478     
1479             ptr[size] = tmpChar;
1480             ptr      += size;
1481             string    = ptr;
1482           }
1483       }
1484
1485     if (newline == True)
1486       {
1487         pSeg->type = _DtCvSetTypeToNewLine(pSeg->type);
1488
1489         if (addToList == True)
1490           {
1491             if (*prev_seg != NULL)
1492                 (*prev_seg)->next_disp = pSeg;
1493             *prev_seg = pSeg;
1494             _DtHelpCeAddSegToList(pSeg, seg_list, last_seg);
1495           }
1496       }
1497
1498     return 0;
1499 }
1500
1501 /******************************************************************************
1502  * Function:    _DtCvSegment *_DtHelpCeMatchSemanticStyle (CESDLSegment *toss,
1503  *                                              enum SDLClass clan,
1504  *                                              char *ssi);
1505  * Parameters:
1506  *
1507  * Returns:     Nothing.
1508  *
1509  *****************************************************************************/
1510 _DtCvSegment *
1511 _DtHelpCeMatchSemanticStyle (
1512     _DtCvSegment        *toss,
1513     SdlOption            clan,
1514     int                  level,
1515     char                *ssi)
1516 {
1517     _DtCvSegment                *pSeg;
1518     SDLTossInfo         *pEl;
1519     const ClassStyleMatrix *pClassStyle;
1520
1521     /*
1522      * initalize the starting style.
1523      */
1524     pSeg = toss;
1525     pClassStyle = ClassToStyle;
1526
1527     do
1528       {
1529         /*
1530          * figure out which element style this class is associated with
1531          */
1532         while (pClassStyle->start != SdlOptionBad && 
1533                 !(pClassStyle->start <= clan && clan <= pClassStyle->end))
1534             pClassStyle++;
1535
1536         if (pClassStyle->start != SdlOptionBad)
1537           {
1538             /*
1539              * skip those not matching the style this class belongs to.
1540              * But don't go past the ones after, because they might match
1541              * too.
1542              */
1543             while (pSeg != NULL &&
1544                 _SdlSegPtrToTossType(pSeg) != pClassStyle->style &&
1545                 _SdlSegPtrToTossType(pSeg) != pClassStyle[1].style)
1546                 pSeg = pSeg->next_seg;
1547     
1548             /*
1549              * the class matches the style, look for a specific class, ssi and
1550              * level match.
1551              */
1552             while (pSeg != NULL &&
1553                 _SdlSegPtrToTossType(pSeg) == pClassStyle->style)
1554               {
1555                 pEl = _SdlSegPtrToTossInfo(pSeg);
1556                 if (_SdlTossInfoPtrClan(pEl) == clan &&
1557                     (_SdlTossInfoPtrRlevel(pEl) == -1 ||
1558                                   _SdlTossInfoPtrRlevel(pEl) == level) &&
1559                     (_SdlTossInfoPtrSsi(pEl) == NULL ||
1560                        (ssi != NULL &&
1561                        _DtHelpCeStrCaseCmp(_SdlTossInfoPtrSsi(pEl), ssi) == 0)))
1562                     return pSeg;
1563
1564                 /*
1565                  * skip to the next element
1566                  */
1567                 pSeg = pSeg->next_seg;
1568               }
1569
1570             /*
1571              * went through those styles, try more
1572              */
1573             pClassStyle++;
1574           }
1575       } while (pClassStyle->start != SdlOptionBad);
1576
1577     return NULL;
1578 }
1579
1580 /******************************************************************************
1581  * Function:    int _DtHelpCeAllocateFontStruct (int num, _DtHelpFontHints *ret_ptr)
1582  *
1583  * Parameters:
1584  *
1585  * Returns      ptr to the allocated structure.
1586  *
1587  * errno Values:
1588  *
1589  * Purpose:     Allocate the number of structure specified
1590  *
1591  *****************************************************************************/
1592 int
1593 _DtHelpCeAllocateFontStruct (
1594     int   size,
1595     _DtHelpFontHints **ret_ptr)
1596 {
1597     _DtHelpFontHints *font;
1598
1599     font = (_DtHelpFontHints *) malloc (sizeof (_DtHelpFontHints) * size);
1600     if (NULL == font)
1601         return -1;
1602
1603     *ret_ptr = font;
1604     return 0;
1605 }
1606