2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
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
23 /* $XConsortium: FormatUtil.c /main/9 1996/11/01 10:12:14 drk $ */
24 /************************************<+>*************************************
25 ****************************************************************************
29 ** Project: Text Graphic Display Library
32 ** Description: Semi private format utility functions that do not
33 ** require the Display Area, Motif, Xt or X11.
36 ** (c) Copyright 1987, 1988, 1989, 1990, 1991, 1992 Hewlett-Packard Company
38 ** (c) Copyright 1993, 1994 Hewlett-Packard Company
39 ** (c) Copyright 1993, 1994 International Business Machines Corp.
40 ** (c) Copyright 1993, 1994 Sun Microsystems, Inc.
41 ** (c) Copyright 1993, 1994 Novell, Inc.
44 ****************************************************************************
45 ************************************<+>*************************************/
65 * Canvas Engine includes
68 #include "CanvasSegP.h"
73 #include "CanvasError.h"
75 #include "FormatUtilI.h"
77 #if defined(NLS16) || !defined(NO_MESSAGE_CATALOG)
82 static const int NL_CAT_LOCALE = 0;
85 /******** Private Function Declarations ********/
86 /******** End Private Function Declarations ********/
88 /******************************************************************************
90 * Private variables and defines.
92 *****************************************************************************/
95 /******************************************************************************
99 *****************************************************************************/
100 /******************************************************************************
102 * Semi Public Functions
104 *****************************************************************************/
105 /******************************************************************************
106 * Function: int _DtHelpCeAddOctalToBuf (char *src, char **dst,
108 * int *dst_max, int grow_size)
111 * src Specifies a pointer to a string.
112 * dst Specifies a pointer to the buffer to
113 * to hold the information.
114 * dst_size Specifies the current size of 'dst'.
115 * Returns the new size of 'dst'.
116 * dst_max Specifies the current maximum size of 'dst'.
117 * Returns the new maximum size of 'dst'.
118 * grow_size Specifies the minimum grow size of 'dst'
119 * when a malloc/realloc occurs.
120 * If this is less than one, 'dst' will
121 * grow only large enough to hold
124 * Returns: 0 if successful, -1 if errors.
130 * Purpose: (Re-)Allocates, if necessary, enough memory to hold the old
131 * information plus the byte.
132 * Coverts the 0xXX value pointed to by src to a 0-256 by value.
133 * Appends the character to the buffer pointed to 'dst'.
134 * Updates 'dst_size' to include the new character.
135 * Updates 'dst_max' to the new size of 'dst' if a
136 * malloc/realloc occurred.
138 *****************************************************************************/
140 _DtHelpCeAddOctalToBuf(
152 dst == NULL || dst_size == NULL || dst_max == NULL ||
153 (*dst == NULL && (*dst_size || *dst_max)))
160 if ((*dst_size + 2) >= *dst_max)
162 if (grow_size > *dst_size + 3 - *dst_max)
163 *dst_max = *dst_max + grow_size;
165 *dst_max = *dst_size + 3;
168 dstPtr = (char *) realloc ((void *) dstPtr, *dst_max);
171 dstPtr = (char *) malloc (sizeof(char) * (*dst_max));
178 * check to see if we have good memory
182 errno = CEErrorMalloc;
188 value = strtoul (src, NULL, 16);
191 if ((value == ULONG_MAX && errno == ERANGE) || value > 255 || value < 1)
193 errno = CEErrorFormattingValue;
198 * copy the source into the destination
200 dstPtr[*dst_size] = (char ) value;
203 * adjust the pointers.
205 *dst_size = *dst_size + 1;
208 * null the end of the buffer.
210 dstPtr[*dst_size] = '\0';
215 /******************************************************************************
216 * Function: int __CEAppendCharToInfo (char **src, char **dst, int *dst_size,
217 * int *dst_max, int grow_size)
220 * src Specifies a pointer to a string.
221 * dst Specifies a pointer to the buffer to
222 * to hold the information.
223 * dst_size Specifies the current size of 'dst'.
224 * Returns the new size of 'dst'.
225 * dst_max Specifies the current maximum size of 'dst'.
226 * Returns the new maximum size of 'dst'.
227 * grow_size Specifies the minimum grow size of 'dst'
228 * when a malloc/realloc occurs.
229 * If this is less than one, 'dst' will
230 * grow only large enough to hold
233 * Returns: 0 if successful, -1 if errors.
239 * Purpose: (Re-)Allocates, if necessary, enough memory to hold the old
240 * information plus the new.
241 * Appends the character pointed to by 'src' to the buffer
243 * Updates 'src' to point to the next character after the
244 * one appended to 'dst'.
245 * Updates 'dst_size' to include the new character.
246 * Updates 'dst_max' to the new size of 'dst' if a
247 * malloc/realloc occurred.
249 *****************************************************************************/
251 _DtHelpCeAddCharToBuf(
261 if (src == NULL || *src == NULL ||
262 dst == NULL || dst_size == NULL || dst_max == NULL ||
263 (*dst == NULL && (*dst_size || *dst_max)))
271 if ((*dst_size + 2) >= *dst_max)
273 if (grow_size > *dst_size + 3 - *dst_max)
274 *dst_max = *dst_max + grow_size;
276 *dst_max = *dst_size + 3;
279 dstPtr = (char *) realloc ((void *) dstPtr, *dst_max);
282 dstPtr = (char *) malloc (*dst_max);
289 * check to see if we have good memory
293 errno = CEErrorMalloc;
298 * copy the source into the destination
300 dstPtr[*dst_size] = *srcPtr++;
303 * adjust the pointers.
306 *dst_size = *dst_size + 1;
309 * null the end of the buffer.
311 dstPtr[*dst_size] = '\0';
316 /******************************************************************************
317 * Function: int _DtHelpCeAddStrToBuf (char **src, char **dst, int *dst_size,
318 * int *dst_max, int copy_size, int grow_size)
321 * src Specifies a pointer to a string.
322 * dst Specifies a pointer to the buffer to
323 * to hold the information.
324 * dst_size Specifies the current size of 'dst'.
325 * Returns the new size of 'dst'.
326 * dst_max Specifies the current maximum size of 'dst'.
327 * Returns the new maximum size of 'dst'.
328 * copy_size Specifies the number of characters to
329 * copy from 'src' to 'dst'.
330 * grow_size Specifies the minimum grow size of 'dst'
331 * when a malloc/realloc occurs.
332 * If this is less than one, 'dst' will
333 * grow only large enough to hold
336 * Returns: 0 if successful, -1 if errors.
342 * Purpose: Copys 'copy_size' number of characters of 'src'
344 * Updates 'src', to point after 'copy_size' number of
346 * Updates the 'dst_size' to reflect the number of characters
348 * If required, increments dst_max and (re)allocs memory
349 * to hold the extra 'copy_size' number of characters.
351 *****************************************************************************/
353 _DtHelpCeAddStrToBuf (
367 if (src == NULL || *src == NULL || (((int)strlen(*src)) < copy_size)
368 || dst == NULL || dst_size == NULL || dst_max == NULL
369 || (*dst == NULL && (*dst_size || *dst_max)))
378 if ((*dst_size + copy_size + 1) >= *dst_max)
380 if (grow_size > (*dst_size + copy_size + 2 - *dst_max))
381 *dst_max = *dst_max + grow_size;
383 *dst_max = *dst_size + copy_size + 2;
386 dstPtr = (char *) realloc ((void *) dstPtr, *dst_max);
389 dstPtr = (char *) malloc (*dst_max);
397 errno = CEErrorMalloc;
402 * make sure there is a null byte to append to.
404 dstPtr[*dst_size] = '\0';
407 * copy the source into the destination
409 strncat (dstPtr, srcPtr, copy_size);
412 * adjust the pointers
414 *src = srcPtr + copy_size;
415 *dst_size = *dst_size + copy_size;
420 /******************************************************************************
421 * Function: int _DtHelpCeGetNxtBuf (FILE *file, char *dst, char **src,
425 * file Specifies a stream to read from.
426 * dst Specifies the buffer where new information
428 * src Specifies a pointer into 'dst'. If there
429 * is information left over, it
430 * is moved to the begining of 'dst'.
431 * Returns 'src' pointing to 'dst'.
432 * max_size Specifies the maximum size of 'dst'.
434 * Returns: 0 if this is the last buffer that can be read for the topic.
436 * >0 if more to be read.
439 * read (2) Errors set via a read call.
443 * Purpose: Reads the next buffer of information.
445 *****************************************************************************/
462 (void ) strcpy (dst, (*src));
463 leftOver = strlen (dst);
465 result = _DtHelpCeReadBuf (file, &(dst[leftOver]), (max_size - leftOver));
468 * check to see if we ran into trouble reading this buffer
469 * of information. If not reset the pointer to the beginning
479 /******************************************************************************
480 * Function: int _DtHelpCeReadBuf (FILE *file, char *buffer, int size)
482 * Parameters: FILE Specifies the stream to read from.
483 * buffer Specifies a buffer to read information
485 * size Specifies the maximum number of bytes
486 * 'buffer' can contain. It should never be
487 * larger than 'buffer' can hold, but it can
490 * Returns: 0 if this is the last buffer that can be read for the topic.
492 * >0 if more to be read.
495 * read (2) Errors set via a read call.
497 * Purpose: Get size-1 number of bytes into a buffer and possibly
498 * check for page markers imbedded within the text.
500 *****************************************************************************/
510 * take into account the last byte must be an end of string marker.
514 flag = _DtHelpCeBufFileRd(file, buffer, size);
521 } /* End _DtHelpCeReadBuf */
523 /******************************************************************************
524 * Function: char *_DtHelpGetNxtToken (char *str, char **retToken)
527 * str The string (in memory) which is being
529 * retToken Returns the next token from the input.
530 * Valid tokens are strings of non-whitespace
531 * characters, newline ("\n"), and
532 * end-of-data (indicated by a zero length
535 * A NULL value indicates an error.
537 * Newline or zero length strings are
538 * not owned by the caller.
540 * Otherwise, the memory for the returned
541 * token is owned by the caller.
543 * Return Value: Returns the pointer to the next unparsed character in
544 * the input string. A NULL value indicates an error.
550 * Purpose: Parse tokens in resource string values.
552 *****************************************************************************/
564 if (retToken) *retToken = NULL; /* tested in caller code */
566 if (str == NULL || *str == '\0' || retToken == NULL)
572 /* Find the next token in the string. The parsing rules are:
574 - Whitespace (except for \n) separates tokens.
575 - \n is a token itself.
576 - The \0 at the end of the string is a token.
579 /* Skip all of the whitespace (except for \n). */
580 while (*str && (*str != '\n') && isspace (*str))
583 /* Str is pointing at the start of the next token. Depending on the
584 type of token, malloc the memory and copy the token value. */
587 else if (*str == '\n') {
592 /* We have some non-whitespace characters. Find the end of */
593 /* them and copy them into new memory. */
594 if ((MB_CUR_MAX == 1 || mblen (str, MB_CUR_MAX) == 1) && *str == '\"')
597 * found a quoted token - skip the quote.
604 while (*str && !done)
607 * get the length of the item.
612 len = mblen (str, MB_CUR_MAX);
619 * check for the token terminator
621 if ((quote && *str == '\"') ||
622 (!quote && (isspace (*str) || *str == '\n')))
632 * determine the length of the token.
634 token = (char *) malloc ((str - start + 1) * sizeof (char));
637 strncpy (token, start, str - start);
638 *(token + (str - start)) = '\0';
641 errno = CEErrorMalloc;
644 * skip the quote terminator
646 if (quote && len == 1 && *str == '\"')
654 /******************************************************************************
655 * Function: _DtCvSegment *_DtHelpAllocateSegments(int malloc_size)
658 * malloc_size Specifies the number of segments to
659 * allocate if 'alloc_size' is NULL or less
660 * than 1 or if '*next_seg' is NULL. The
661 * first one is returned to the caller with
662 * the rest in 'next_seg' if 'next_seg' is
666 * non-null If succeeds.
669 * Purpose: Allocate a block of segments, zeros the structures, and
670 * sets the link_idx of each structure to -1.
672 *****************************************************************************/
674 _DtHelpAllocateSegments (
678 _DtCvSegment *newSeg;
682 * don't allow zero or negative allocations
688 * allocate the block of segments
690 newSeg = (_DtCvSegment *) calloc (sizeof(_DtCvSegment), malloc_size);
694 * now allocate the same number of private information structures
696 p = (FrmtPrivateInfo *) calloc (sizeof(FrmtPrivateInfo), malloc_size);
700 * mark the first item as the top block. Since it will be
701 * attached to the first segment, it marks both the segment
702 * and the private information blocks for later frees.
705 for (i = 0; i < malloc_size; i++)
708 * invalidate the link index and attach a private
709 * information structure to each segment
711 newSeg[i].link_idx = -1;
712 newSeg[i].client_use = p++;
718 * had trouble allocating the private information.
719 * free the new segment list and return NULL as an error.
729 /******************************************************************************
730 * Function: int _DtHelpFmtFindBreak (char *ptr, int mb_len, int *num_chars)
733 * ptr Specifies the string to check.
734 * mb_len Specifies if the sequence should be single
735 * byte or multi-byte.
736 * num_chars Returns the character count.
738 * Returns number of bytes in the sequence.
742 * Purpose: Find a length of 'ptr' comprised of multi or single byte
745 *****************************************************************************/
747 _DtHelpFmtFindBreak (
757 while (0 == done && '\0' != *ptr)
759 mySize = mblen(ptr, MB_CUR_MAX);
762 ((1 != mb_len && 1 != mySize) || (1 == mb_len && 1 == mySize)))
771 *num_chars = numChars;
775 /******************************************************************************
776 * Function: _DtHelpLoadMultiInfo
778 * Returns: Loads the multi-byte formatting table for the current locale.
780 *****************************************************************************/
782 _DtHelpLoadMultiInfo (
783 wchar_t **cant_begin_chars,
784 wchar_t **cant_end_chars,
787 #ifndef NO_MESSAGE_CATALOG
792 cat_fd = catopen ("fmt_tbl", NL_CAT_LOCALE);
793 if (cat_fd != ((nl_catd) -1))
796 * Get the list of characters that can't begin a line.
798 ptr = catgets (cat_fd, 1, 1, "");
799 len = strlen (ptr) + 1;
800 *cant_begin_chars = (wchar_t *) malloc (len * sizeof (wchar_t));
801 if (NULL != *cant_begin_chars &&
802 mbstowcs(*cant_begin_chars, ptr, len) == -1)
804 free (*cant_begin_chars);
805 *cant_begin_chars = NULL;
809 * Get the list of characters that can't end a line.
811 ptr = catgets (cat_fd, 1, 2, "");
812 len = strlen (ptr) + 1;
813 *cant_end_chars = (wchar_t *) malloc (len * sizeof (wchar_t));
814 if (*cant_end_chars != NULL &&
815 mbstowcs(*cant_end_chars, ptr, len) == -1)
817 free (*cant_end_chars);
818 *cant_end_chars = NULL;
822 * Get the spacing flag. I.E. when does a internal newline
823 * get turned into a space.
824 * 1 means all the time.
825 * 0 means only between a multibyte string and
826 * a singlebyte string.
828 ptr = catgets (cat_fd, 1, 3, "1");
829 *nl_to_space = atoi(ptr);
836 *cant_begin_chars = NULL;
837 *cant_end_chars = NULL;