|
Packit |
b099d7 |
/* $TOG: TxtPropCv.c /main/15 1997/06/18 17:46:05 samborn $ */
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Motif
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* Copyright (c) 1987-2012, The Open Group. All rights reserved.
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* These libraries and programs are free software; you can
|
|
Packit |
b099d7 |
* redistribute them and/or modify them under the terms of the GNU
|
|
Packit |
b099d7 |
* Lesser General Public License as published by the Free Software
|
|
Packit |
b099d7 |
* Foundation; either version 2 of the License, or (at your option)
|
|
Packit |
b099d7 |
* any later version.
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* These libraries and programs are distributed in the hope that
|
|
Packit |
b099d7 |
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
|
Packit |
b099d7 |
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
Packit |
b099d7 |
* PURPOSE. See the GNU Lesser General Public License for more
|
|
Packit |
b099d7 |
* details.
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit |
b099d7 |
* License along with these librararies and programs; if not, write
|
|
Packit |
b099d7 |
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
Packit |
b099d7 |
* Floor, Boston, MA 02110-1301 USA
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* HISTORY
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
#ifdef HAVE_CONFIG_H
|
|
Packit |
b099d7 |
#include <config.h>
|
|
Packit |
b099d7 |
#endif
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
#include <stdio.h>
|
|
Packit |
b099d7 |
#ifndef X_NOT_STDC_ENV
|
|
Packit |
b099d7 |
#include <stdlib.h>
|
|
Packit |
b099d7 |
#endif
|
|
Packit |
b099d7 |
#include <string.h>
|
|
Packit |
b099d7 |
#include <ctype.h>
|
|
Packit |
b099d7 |
#include <Xm/XmosP.h>
|
|
Packit |
b099d7 |
#include "XmI.h"
|
|
Packit |
b099d7 |
#include "XmStringI.h"
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
static Atom
|
|
Packit |
b099d7 |
GetLocaleEncodingAtom(Display *dpy)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
int ret_status = 0;
|
|
Packit |
b099d7 |
XTextProperty tmp_prop;
|
|
Packit |
b099d7 |
char * tmp_string = "ABC"; /* these are characters in XPCS, so... safe */
|
|
Packit |
b099d7 |
Atom encoding;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
tmp_prop.value = NULL; /* just in case X doesn't do it */
|
|
Packit |
b099d7 |
ret_status = XmbTextListToTextProperty(dpy, &tmp_string, 1,
|
|
Packit |
b099d7 |
(XICCEncodingStyle)XTextStyle,
|
|
Packit |
b099d7 |
&tmp_prop);
|
|
Packit |
b099d7 |
if (ret_status == Success)
|
|
Packit |
b099d7 |
encoding = tmp_prop.encoding;
|
|
Packit |
b099d7 |
else
|
|
Packit |
b099d7 |
encoding = None; /* XmbTextList... should always be able
|
|
Packit |
b099d7 |
* to convert XPCS characters; but in
|
|
Packit |
b099d7 |
* case its broken, this prevents a core
|
|
Packit |
b099d7 |
* dump.
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
if (tmp_prop.value != NULL) XFree((char *)tmp_prop.value);
|
|
Packit |
b099d7 |
return(encoding);
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/************************************************************************
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* TextPropertyToSingleTextItem
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
************************************************************************/
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
static int
|
|
Packit |
b099d7 |
TextPropertyToSingleTextItem(Display *display, XTextProperty *text_prop,
|
|
Packit |
b099d7 |
char **text_item)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
int result, count;
|
|
Packit |
b099d7 |
char **textlist;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
result = XmbTextPropertyToTextList(display, text_prop, &textlist,
|
|
Packit |
b099d7 |
&count);
|
|
Packit |
b099d7 |
if (result != Success) return(result);
|
|
Packit |
b099d7 |
if (count == 1)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
/* Otherwise just return the first element of the
|
|
Packit |
b099d7 |
text list */
|
|
Packit |
b099d7 |
*text_item = XtNewString(textlist[0]);
|
|
Packit |
b099d7 |
XFreeStringList(textlist);
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
else if (count > 1)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
/* If we got back more than one string, then
|
|
Packit |
b099d7 |
let's concatenate them all together. */
|
|
Packit |
b099d7 |
int i, length = 0;
|
|
Packit |
b099d7 |
char *newstring;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* First figure out how big the final string will be */
|
|
Packit |
b099d7 |
for (i = 0; i < count; ++i)
|
|
Packit |
b099d7 |
length += strlen(textlist[i]);
|
|
Packit |
b099d7 |
/* Allocate a buffer and jam all the strings into it */
|
|
Packit |
b099d7 |
newstring = (char *)XtMalloc(sizeof(char)*(length+1));
|
|
Packit |
b099d7 |
newstring[0] = '\0';
|
|
Packit |
b099d7 |
for (i = 0; i < count; ++i)
|
|
Packit |
b099d7 |
strcat(newstring, textlist[i]);
|
|
Packit |
b099d7 |
*text_item = newstring;
|
|
Packit |
b099d7 |
XFreeStringList(textlist);
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
return(Success);
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/************************************************************************
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* GetTextSegment
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* This function gets the next full segment from the given xmstring using
|
|
Packit |
b099d7 |
* the given xmcontext and tries to extract either locale text or
|
|
Packit |
b099d7 |
* string text (i.e. ISO8859-1 text) based on the texttype argument.
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* This function can return one of three return values:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* _VALID_SEGMENT: we found a segment that we could decompose. The
|
|
Packit |
b099d7 |
* appropriate text has been stored in the given buffer
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* _INVALID_SEGMENT: we could not decompose the segment. The given
|
|
Packit |
b099d7 |
* buffer does not contain valid data
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* _NO_MORE_SEGMENTS: there are no more segments available in the
|
|
Packit |
b099d7 |
* xmstring using the xmcontext.
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
************************************************************************/
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* Segment type return value */
|
|
Packit |
b099d7 |
enum { _VALID_SEGMENT, _INVALID_SEGMENT, _NO_MORE_SEGMENTS };
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* Valid text types */
|
|
Packit |
b099d7 |
enum { _LOCALE_TEXT, _STRING_TEXT };
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*ARGSUSED*/
|
|
Packit |
b099d7 |
static unsigned char
|
|
Packit |
b099d7 |
GetTextSegment(Display *display, /* unused */
|
|
Packit |
b099d7 |
XmStringContext xmcontext,
|
|
Packit |
b099d7 |
XmString xmstring, /* unused */
|
|
Packit |
b099d7 |
char **buffer,
|
|
Packit |
b099d7 |
unsigned char texttype)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
XtPointer text;
|
|
Packit |
b099d7 |
XmStringTag tag, *rendition_tags;
|
|
Packit |
b099d7 |
XmTextType type;
|
|
Packit |
b099d7 |
XmStringDirection direction;
|
|
Packit |
b099d7 |
XmDirection push_before;
|
|
Packit |
b099d7 |
Boolean separator, pop_after;
|
|
Packit |
b099d7 |
unsigned int tag_count;
|
|
Packit |
b099d7 |
unsigned char return_status, tabs;
|
|
Packit |
b099d7 |
short char_count;
|
|
Packit |
b099d7 |
char *encoding;
|
|
Packit |
b099d7 |
int i;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* Initialize the locale_buffer just in case we need to return
|
|
Packit |
b099d7 |
Failure at any point along the way. */
|
|
Packit |
b099d7 |
*buffer = NULL;
|
|
Packit |
b099d7 |
return_status = _VALID_SEGMENT;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* Decompose the xmstring and handle each segment separately. */
|
|
Packit |
b099d7 |
if (_XmStringGetSegment(xmcontext, TRUE, FALSE, &text, &tag, &type,
|
|
Packit |
b099d7 |
&rendition_tags, &tag_count, &direction,
|
|
Packit |
b099d7 |
&separator, &tabs, &char_count,
|
|
Packit |
b099d7 |
&push_before, &pop_after))
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
switch (type)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
case XmMULTIBYTE_TEXT:
|
|
Packit |
b099d7 |
case XmWIDECHAR_TEXT:
|
|
Packit |
b099d7 |
if (texttype == _LOCALE_TEXT)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
/* The text should be already be valid locale text */
|
|
Packit |
b099d7 |
char *tmp = XtMalloc(char_count + sizeof(wchar_t));
|
|
Packit |
b099d7 |
memcpy(tmp, text, char_count);
|
|
Packit |
b099d7 |
bzero(tmp + char_count, sizeof(wchar_t));
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
*buffer = tmp;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
else if (texttype == _STRING_TEXT)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
*buffer = NULL;
|
|
Packit |
b099d7 |
return(_INVALID_SEGMENT);
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
break;
|
|
Packit |
b099d7 |
case XmCHARSET_TEXT:
|
|
Packit |
b099d7 |
/* "tag" is the charset when type is CHARSET_TEXT */
|
|
Packit |
b099d7 |
encoding = XmMapSegmentEncoding(tag);
|
|
Packit |
b099d7 |
if (encoding != NULL)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
if (texttype == _LOCALE_TEXT &&
|
|
Packit |
b099d7 |
(strcmp(encoding, _MOTIF_DEFAULT_LOCALE) == 0 ||
|
|
Packit |
b099d7 |
strcmp(encoding, XmFONTLIST_DEFAULT_TAG) == 0))
|
|
Packit |
b099d7 |
/* @@ Is ISO8859-1 valid here? */
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
/* Given the above charset encodings, the text should
|
|
Packit |
b099d7 |
already be valid locale text. */
|
|
Packit |
b099d7 |
char *tmp = XtMalloc(char_count + sizeof(wchar_t));
|
|
Packit |
b099d7 |
memcpy(tmp, text, char_count);
|
|
Packit |
b099d7 |
bzero(tmp + char_count, sizeof(wchar_t));
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
*buffer = tmp;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
else if (texttype == _STRING_TEXT &&
|
|
Packit |
b099d7 |
(strcmp(encoding, "ISO8859-1") == 0))
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
/* The text is valid STRING text */
|
|
Packit |
b099d7 |
char *tmp = XtMalloc(char_count + sizeof(wchar_t));
|
|
Packit |
b099d7 |
memcpy(tmp, text, char_count);
|
|
Packit |
b099d7 |
bzero(tmp + char_count, sizeof(wchar_t));
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
*buffer = tmp;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
else return(_INVALID_SEGMENT);
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
else return(_INVALID_SEGMENT); /* the encoding was unregistered */
|
|
Packit |
b099d7 |
break;
|
|
Packit |
b099d7 |
case XmNO_TEXT:
|
|
Packit |
b099d7 |
break;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
/* Before returning Success, check to see whether we need to
|
|
Packit |
b099d7 |
prepend any tabs or append any newlines. */
|
|
Packit |
b099d7 |
if ((return_status == _VALID_SEGMENT) &&
|
|
Packit |
b099d7 |
(separator == True || tabs != 0))
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
int newlength;
|
|
Packit |
b099d7 |
char *newstring;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
newlength =
|
|
Packit |
b099d7 |
strlen(*buffer) + (separator ? 1 : 0) + tabs;
|
|
Packit |
b099d7 |
newstring = (char *)XtMalloc(sizeof(char) * (newlength + 1));
|
|
Packit |
b099d7 |
for (i = 0; i < tabs; i++) newstring[i] = '\t';
|
|
Packit |
b099d7 |
strcpy(&newstring[i], *buffer);
|
|
Packit |
b099d7 |
strcat(newstring, "\n");
|
|
Packit |
b099d7 |
XtFree(*buffer);
|
|
Packit |
b099d7 |
*buffer = newstring;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
return(return_status);
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
else
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
/* Return NULL text but a value of Success to designate that
|
|
Packit |
b099d7 |
there are no more segments to process. */
|
|
Packit |
b099d7 |
*buffer = NULL;
|
|
Packit |
b099d7 |
return(_NO_MORE_SEGMENTS);
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/************************************************************************
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* GetUseableText
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* Given an XmString, decompose it into text specified by the texttype
|
|
Packit |
b099d7 |
* argument. Valid text types are _LOCALE_TEXT for text encoded in the
|
|
Packit |
b099d7 |
* current locale and _STRING_TEXT for text encoded in ISO8859-1 with
|
|
Packit |
b099d7 |
* newlines and tabs.
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* If the "strict" argument is False, then any compound strings which
|
|
Packit |
b099d7 |
* have a segment that can not be decomposed as specified will be converted
|
|
Packit |
b099d7 |
* to compound text and then converted to the appropriate text by using
|
|
Packit |
b099d7 |
* a series of XmbTextListToTextProperty and XmbTextPropertyToTextList
|
|
Packit |
b099d7 |
* calls to acchive the conversion.
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* If the "strict" argument is True, then all compound strings must be
|
|
Packit |
b099d7 |
* fully convertible to the specified text type. If one is not in any
|
|
Packit |
b099d7 |
* way, then XLocaleNotSupported is returned.
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
************************************************************************/
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
static int
|
|
Packit |
b099d7 |
GetUseableText(Display *display, XmString xmstring, char **buffer,
|
|
Packit |
b099d7 |
Boolean strict, unsigned char texttype)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
_XmStringContextRec stack_context;
|
|
Packit |
b099d7 |
XTextProperty text_prop_return;
|
|
Packit |
b099d7 |
char *text = NULL, *final_string = NULL, *text_item, *compound_text;
|
|
Packit |
b099d7 |
unsigned char return_status;
|
|
Packit |
b099d7 |
int result, size_so_far = 1; /* initialized for the ending NULL */
|
|
Packit |
b099d7 |
XICCEncodingStyle encoding_style;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* Initialize the buffer in case we have to abort and return
|
|
Packit |
b099d7 |
failure. */
|
|
Packit |
b099d7 |
*buffer = NULL;
|
|
Packit |
b099d7 |
switch(texttype)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
case _LOCALE_TEXT:
|
|
Packit |
b099d7 |
encoding_style = XTextStyle;
|
|
Packit |
b099d7 |
break;
|
|
Packit |
b099d7 |
case _STRING_TEXT:
|
|
Packit |
b099d7 |
encoding_style = XStringStyle;
|
|
Packit |
b099d7 |
break;
|
|
Packit |
b099d7 |
default:
|
|
Packit |
b099d7 |
return(XLocaleNotSupported);
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* Decompose the xmstring and handle each segment separately. */
|
|
Packit |
b099d7 |
_XmStringContextReInit(&stack_context, xmstring);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* Get text for each segment of the compound string. Concatenate
|
|
Packit |
b099d7 |
all the text from the segments together into one string that will
|
|
Packit |
b099d7 |
be returned in the buffer. */
|
|
Packit |
b099d7 |
while((return_status =
|
|
Packit |
b099d7 |
GetTextSegment(display, &stack_context, xmstring,
|
|
Packit |
b099d7 |
&text, texttype)) == _VALID_SEGMENT)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
size_so_far += strlen(text);
|
|
Packit |
b099d7 |
final_string = (char *)XtRealloc(final_string, size_so_far);
|
|
Packit |
b099d7 |
final_string[0] = '\0';
|
|
Packit |
b099d7 |
strcat(final_string, text);
|
|
Packit |
b099d7 |
XtFree(text);
|
|
Packit |
b099d7 |
text = NULL;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* If we encountered an invalid segment, then we will throw up our
|
|
Packit |
b099d7 |
hands and try all over again by converting the compound string to
|
|
Packit |
b099d7 |
compound text and then converting the compound text to a text
|
|
Packit |
b099d7 |
property and from a text property back to a text list. This should
|
|
Packit |
b099d7 |
result in text but with possible loss of information. */
|
|
Packit |
b099d7 |
if (return_status == _INVALID_SEGMENT)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
int txt_len;
|
|
Packit |
b099d7 |
char *txt_value;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* First, free what we've malloc'ed already */
|
|
Packit |
b099d7 |
if (final_string) XtFree(final_string);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* If we are in strict mode, then return XLocaleNotSupported to
|
|
Packit |
b099d7 |
let the caller know that we could not decompose one of the
|
|
Packit |
b099d7 |
XmStrings in the context of the current locale */
|
|
Packit |
b099d7 |
if (strict)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
_XmStringContextFree(&stack_context);
|
|
Packit |
b099d7 |
return(XLocaleNotSupported);
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* Now convert the compound string to compound text ... */
|
|
Packit |
b099d7 |
if ((compound_text = XmCvtXmStringToCT(xmstring))
|
|
Packit |
b099d7 |
== (char *)NULL)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
_XmStringContextFree(&stack_context);
|
|
Packit |
b099d7 |
return (XLocaleNotSupported);
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
/* then to a text property in TextStyle encoding ... */
|
|
Packit |
b099d7 |
txt_len = strlen(compound_text) + 1;
|
|
Packit |
b099d7 |
txt_value = XtMalloc((txt_len + 1) * sizeof(char));
|
|
Packit |
b099d7 |
strcpy(txt_value, compound_text);
|
|
Packit |
b099d7 |
text_prop_return.value = (unsigned char *) txt_value;
|
|
Packit |
b099d7 |
text_prop_return.value[txt_len] = '\0';
|
|
Packit |
b099d7 |
text_prop_return.nitems = txt_len;
|
|
Packit |
b099d7 |
text_prop_return.encoding =
|
|
Packit |
b099d7 |
XInternAtom(display, XmSCOMPOUND_TEXT, False);
|
|
Packit |
b099d7 |
text_prop_return.format = 8;
|
|
Packit |
b099d7 |
XtFree(compound_text);
|
|
Packit |
b099d7 |
/* then to a text list, which should result in text. */
|
|
Packit |
b099d7 |
result = TextPropertyToSingleTextItem(display, &text_prop_return,
|
|
Packit |
b099d7 |
&text_item);
|
|
Packit |
b099d7 |
if (text_prop_return.value != NULL)
|
|
Packit |
b099d7 |
XtFree((char *)text_prop_return.value);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
if (result != Success)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
_XmStringContextFree(&stack_context);
|
|
Packit |
b099d7 |
return(result);
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
final_string = text_item;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* Otherwise, we should have valid text */
|
|
Packit |
b099d7 |
*buffer = final_string;
|
|
Packit |
b099d7 |
_XmStringContextFree(&stack_context);
|
|
Packit |
b099d7 |
return(Success);
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/************************************************************************
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* XmCvtXmStringTableToTextProperty
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
************************************************************************/
|
|
Packit |
b099d7 |
int
|
|
Packit |
b099d7 |
XmCvtXmStringTableToTextProperty(Display *display,
|
|
Packit |
b099d7 |
XmStringTable string_table,
|
|
Packit |
b099d7 |
int count,
|
|
Packit |
b099d7 |
XmICCEncodingStyle style,
|
|
Packit |
b099d7 |
XTextProperty *text_prop_return)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
char **compound_text, **useable_text, *xm_compound_text, *ptr;
|
|
Packit |
b099d7 |
unsigned char *ubufptr, *bufptr, texttype =_LOCALE_TEXT , *final_string;
|
|
Packit |
b099d7 |
int i, result, total_size;
|
|
Packit |
b099d7 |
Boolean strict = True;
|
|
Packit |
b099d7 |
Atom encoding = 0;
|
|
Packit |
b099d7 |
_XmDisplayToAppContext(display);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
_XmAppLock(app);
|
|
Packit |
b099d7 |
switch (style)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
case XmSTYLE_COMPOUND_TEXT:
|
|
Packit |
b099d7 |
compound_text = (char **)XtMalloc(sizeof(char *) * count);
|
|
Packit |
b099d7 |
/* Convert each XmString to Compound Text */
|
|
Packit |
b099d7 |
for (i = 0, total_size = 0; i < count; ++i) {
|
|
Packit |
b099d7 |
compound_text[i] = XmCvtXmStringToCT(string_table[i]);
|
|
Packit |
b099d7 |
total_size += (compound_text[i] ? strlen(compound_text[i]) : 0) +1;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
/* Generate the resulting XTextProperty value as a set of
|
|
Packit |
b099d7 |
null-separated compound text elements. A final terminating
|
|
Packit |
b099d7 |
null is stored at the end of the value field of text_prop_return
|
|
Packit |
b099d7 |
but is not included in the nitems member. */
|
|
Packit |
b099d7 |
ptr = xm_compound_text =
|
|
Packit |
b099d7 |
(char *) XtMalloc(sizeof(char) * (total_size + 1));
|
|
Packit |
b099d7 |
for (i = 0; i < count; i++)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
if (compound_text[i])
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
strcpy(ptr, compound_text[i]);
|
|
Packit |
b099d7 |
XtFree(compound_text[i]);
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
else
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
*ptr = '\0';
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
ptr += strlen(ptr) + 1;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
*ptr = '\0';
|
|
Packit |
b099d7 |
XtFree((char *) compound_text);
|
|
Packit |
b099d7 |
text_prop_return->value = (unsigned char *) xm_compound_text;
|
|
Packit |
b099d7 |
text_prop_return->encoding =
|
|
Packit |
b099d7 |
XInternAtom(display, XmSCOMPOUND_TEXT, False);
|
|
Packit |
b099d7 |
text_prop_return->format = 8;
|
|
Packit |
b099d7 |
text_prop_return->nitems = total_size;
|
|
Packit |
b099d7 |
_XmAppUnlock(app);
|
|
Packit |
b099d7 |
return(Success);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
case XmSTYLE_COMPOUND_STRING:
|
|
Packit |
b099d7 |
/* First calculate how much space the compound strings will occupy
|
|
Packit |
b099d7 |
when they are all converted to ASN1 strings. */
|
|
Packit |
b099d7 |
for (i = 0, total_size = 0; i < count; ++i)
|
|
Packit |
b099d7 |
total_size += XmCvtXmStringToByteStream(string_table[i],NULL);
|
|
Packit |
b099d7 |
/* Allocate that amount of space and convert the compound strings
|
|
Packit |
b099d7 |
to ASN1 strings, putting them directly into the buffer. */
|
|
Packit |
b099d7 |
text_prop_return->value = ubufptr =
|
|
Packit |
b099d7 |
(unsigned char *) XtMalloc(sizeof(unsigned char) * total_size);
|
|
Packit |
b099d7 |
for (i = 0; i < count; ++i)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
int size;
|
|
Packit |
b099d7 |
size = XmCvtXmStringToByteStream(string_table[i],&bufptr);
|
|
Packit |
b099d7 |
memcpy(ubufptr, bufptr, size);
|
|
Packit |
b099d7 |
XtFree((char *) bufptr);
|
|
Packit |
b099d7 |
ubufptr += size;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
*(++ubufptr) = '\0';
|
|
Packit |
b099d7 |
text_prop_return->nitems = total_size;
|
|
Packit |
b099d7 |
text_prop_return->format = 8;
|
|
Packit |
b099d7 |
text_prop_return->encoding =
|
|
Packit |
b099d7 |
XInternAtom(display, XmS_MOTIF_COMPOUND_STRING, False);
|
|
Packit |
b099d7 |
_XmAppUnlock(app);
|
|
Packit |
b099d7 |
return(Success);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
case XmSTYLE_LOCALE:
|
|
Packit |
b099d7 |
case XmSTYLE_TEXT:
|
|
Packit |
b099d7 |
case XmSTYLE_STRING:
|
|
Packit |
b099d7 |
case XmSTYLE_STANDARD_ICC_TEXT:
|
|
Packit |
b099d7 |
/* We do mostly the same thing for these four styles. Do another
|
|
Packit |
b099d7 |
switch to set up some parameters which will change the behavior
|
|
Packit |
b099d7 |
slightly depending on which style is being requested. */
|
|
Packit |
b099d7 |
switch (style) {
|
|
Packit |
b099d7 |
case XmSTYLE_LOCALE:
|
|
Packit |
b099d7 |
strict = False;
|
|
Packit |
b099d7 |
texttype = _LOCALE_TEXT;
|
|
Packit |
b099d7 |
encoding = GetLocaleEncodingAtom(display);
|
|
Packit |
b099d7 |
break;
|
|
Packit |
b099d7 |
case XmSTYLE_TEXT:
|
|
Packit |
b099d7 |
strict = True;
|
|
Packit |
b099d7 |
texttype = _LOCALE_TEXT;
|
|
Packit |
b099d7 |
encoding = GetLocaleEncodingAtom(display);
|
|
Packit |
b099d7 |
break;
|
|
Packit |
b099d7 |
case XmSTYLE_STRING:
|
|
Packit |
b099d7 |
strict = False;
|
|
Packit |
b099d7 |
texttype = _STRING_TEXT;
|
|
Packit |
b099d7 |
encoding = XA_STRING;
|
|
Packit |
b099d7 |
break;
|
|
Packit |
b099d7 |
case XmSTYLE_STANDARD_ICC_TEXT:
|
|
Packit |
b099d7 |
strict = True;
|
|
Packit |
b099d7 |
texttype = _STRING_TEXT;
|
|
Packit |
b099d7 |
encoding = XA_STRING;
|
|
Packit |
b099d7 |
break;
|
|
Packit |
b099d7 |
case XmSTYLE_COMPOUND_TEXT:
|
|
Packit |
b099d7 |
case XmSTYLE_COMPOUND_STRING:
|
|
Packit |
b099d7 |
break;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
/* Get useable text for each compound string */
|
|
Packit |
b099d7 |
useable_text = (char **)XtMalloc(sizeof(char *) * count);
|
|
Packit |
b099d7 |
for (i = 0; i < count; ++i)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
result = GetUseableText(display, string_table[i],
|
|
Packit |
b099d7 |
&useable_text[i], strict, texttype);
|
|
Packit |
b099d7 |
if (result != Success)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
/* Free up what we have so far ... */
|
|
Packit |
b099d7 |
--i; /* skip the one that failed */
|
|
Packit |
b099d7 |
while (i >= 0) XtFree(useable_text[i--]);
|
|
Packit |
b099d7 |
if (strict)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
/* If we got back XLocaleNotSupported, then pretend the
|
|
Packit |
b099d7 |
caller asked for COMPOUND_TEXT style. */
|
|
Packit |
b099d7 |
if (result == XLocaleNotSupported)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
/* Try to do a straight COMPOUND_TEXT conversion
|
|
Packit |
b099d7 |
and return whatever we got back. */
|
|
Packit |
b099d7 |
_XmAppUnlock(app);
|
|
Packit |
b099d7 |
return (XmCvtXmStringTableToTextProperty
|
|
Packit |
b099d7 |
(display, string_table, count,
|
|
Packit |
b099d7 |
XmSTYLE_COMPOUND_TEXT, text_prop_return));
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
else
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
/* Otherwise, we got back an error we didn't know how
|
|
Packit |
b099d7 |
to handle. Just return it. */
|
|
Packit |
b099d7 |
_XmAppUnlock(app);
|
|
Packit |
b099d7 |
return(result);
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
else
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
/* If we are not being strict, then an error was really
|
|
Packit |
b099d7 |
an error that we could not handle. */
|
|
Packit |
b099d7 |
_XmAppUnlock(app);
|
|
Packit |
b099d7 |
return(result);
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
/* Now take the useable_text array and convert it to one
|
|
Packit |
b099d7 |
long string with null separated elements. */
|
|
Packit |
b099d7 |
for (i = 0, total_size = 0; i < count; ++i)
|
|
Packit |
b099d7 |
total_size += strlen(useable_text[i]) + 1;
|
|
Packit |
b099d7 |
final_string =
|
|
Packit |
b099d7 |
(unsigned char *)XtMalloc(sizeof(char) * (total_size + 1));
|
|
Packit |
b099d7 |
final_string[0] = '\0';
|
|
Packit |
b099d7 |
bufptr = final_string;
|
|
Packit |
b099d7 |
for (i = 0; i < count; ++i)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
strcpy((char *)bufptr, useable_text[i]);
|
|
Packit |
b099d7 |
bufptr += strlen(useable_text[i]) + 1;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
*bufptr = '\0';
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* Fill in the text property with the data */
|
|
Packit |
b099d7 |
text_prop_return->encoding = encoding;
|
|
Packit |
b099d7 |
text_prop_return->value = final_string;
|
|
Packit |
b099d7 |
text_prop_return->nitems = total_size;
|
|
Packit |
b099d7 |
text_prop_return->format = 8;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* Clean up and leave town */
|
|
Packit |
b099d7 |
for (i = 0; i < count; ++i) XtFree(useable_text[i]);
|
|
Packit |
b099d7 |
XtFree((char *) useable_text);
|
|
Packit |
b099d7 |
_XmAppUnlock(app);
|
|
Packit |
b099d7 |
return(Success);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
default:
|
|
Packit |
b099d7 |
_XmAppUnlock(app);
|
|
Packit |
b099d7 |
return(XLocaleNotSupported);
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/************************************************************************
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* XmCvtTextPropertyToXmStringTable
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
************************************************************************/
|
|
Packit |
b099d7 |
int
|
|
Packit |
b099d7 |
XmCvtTextPropertyToXmStringTable(Display *display,
|
|
Packit |
b099d7 |
XTextProperty *text_prop,
|
|
Packit |
b099d7 |
XmStringTable *string_table_return,
|
|
Packit |
b099d7 |
int *count_return)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
enum { XmACOMPOUND_TEXT, XmA_MOTIF_COMPOUND_STRING,
|
|
Packit |
b099d7 |
#ifdef UTF8_SUPPORTED
|
|
Packit |
b099d7 |
XmAUTF8_STRING,
|
|
Packit |
b099d7 |
#endif
|
|
Packit |
b099d7 |
NUM_ATOMS };
|
|
Packit |
b099d7 |
static char* atom_names[] = { XmSCOMPOUND_TEXT, XmS_MOTIF_COMPOUND_STRING,
|
|
Packit |
b099d7 |
#ifdef UTF8_SUPPORTED
|
|
Packit |
b099d7 |
XmSUTF8_STRING
|
|
Packit |
b099d7 |
#endif
|
|
Packit |
b099d7 |
};
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
char **text_list;
|
|
Packit |
b099d7 |
int i, result, elements = 0;
|
|
Packit |
b099d7 |
XmStringTable string_table;
|
|
Packit |
b099d7 |
XmStringTag tag;
|
|
Packit |
b099d7 |
XmTextType type;
|
|
Packit |
b099d7 |
Atom LOCALE_ATOM = GetLocaleEncodingAtom(display);
|
|
Packit |
b099d7 |
Atom atoms[XtNumber(atom_names)];
|
|
Packit |
b099d7 |
_XmDisplayToAppContext(display);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
assert(XtNumber(atom_names) == NUM_ATOMS);
|
|
Packit |
b099d7 |
XInternAtoms(display, atom_names, XtNumber(atom_names), False, atoms);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
_XmAppLock(app);
|
|
Packit |
b099d7 |
if (text_prop->encoding == atoms[XmACOMPOUND_TEXT])
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
char *ptr;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* First found how many XmString we need to allocate. */
|
|
Packit |
b099d7 |
for (*count_return = 1, i = 0; i < text_prop->nitems; i++)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
if (text_prop->value[i] == '\0')
|
|
Packit |
b099d7 |
(*count_return)++;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
string_table =
|
|
Packit |
b099d7 |
(XmStringTable)XtMalloc(sizeof(XmString) * (*count_return));
|
|
Packit |
b099d7 |
/* Now convert each compound text to an XmString. */
|
|
Packit |
b099d7 |
for (i = 0, ptr = (char *)text_prop->value;
|
|
Packit |
b099d7 |
i < *count_return;
|
|
Packit |
b099d7 |
i++, ptr += strlen(ptr) + 1)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
XmString tempstr;
|
|
Packit |
b099d7 |
tempstr = XmCvtCTToXmString(ptr);
|
|
Packit |
b099d7 |
string_table[i] = tempstr;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
*string_table_return = string_table;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
_XmAppUnlock(app);
|
|
Packit |
b099d7 |
return(Success);
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
else if (text_prop->encoding == atoms[XmA_MOTIF_COMPOUND_STRING])
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
unsigned char *asn1_head;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* First calculate how many elements there are */
|
|
Packit |
b099d7 |
asn1_head = text_prop->value;
|
|
Packit |
b099d7 |
for (elements = 0; *asn1_head != '\0'; ++elements)
|
|
Packit |
b099d7 |
asn1_head += XmStringByteStreamLength(asn1_head);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* Now allocate a string table to put them in */
|
|
Packit |
b099d7 |
string_table = (XmStringTable)XtMalloc(sizeof(XmString) * elements);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* Run through again, converting the strings. */
|
|
Packit |
b099d7 |
asn1_head = text_prop->value;
|
|
Packit |
b099d7 |
for (elements = 0; *asn1_head != '\0'; ++elements)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
string_table[elements] = XmCvtByteStreamToXmString(asn1_head);
|
|
Packit |
b099d7 |
/* If the string is NULL, then we don't know what to do */
|
|
Packit |
b099d7 |
if (string_table[elements] == (XmString) NULL)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
while (elements > 0) XtFree((char *)string_table[--elements]);
|
|
Packit |
b099d7 |
XtFree((char *)string_table);
|
|
Packit |
b099d7 |
_XmAppUnlock(app);
|
|
Packit |
b099d7 |
return(XConverterNotFound);
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
/* Find the next asn1 string header */
|
|
Packit |
b099d7 |
asn1_head += XmStringByteStreamLength(asn1_head);
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
*string_table_return = string_table;
|
|
Packit |
b099d7 |
*count_return = elements;
|
|
Packit |
b099d7 |
_XmAppUnlock(app);
|
|
Packit |
b099d7 |
return(Success);
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
else if (text_prop->encoding == LOCALE_ATOM)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
tag = _MOTIF_DEFAULT_LOCALE;
|
|
Packit |
b099d7 |
type = XmMULTIBYTE_TEXT;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
else if (text_prop->encoding == XA_STRING)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
tag = "ISO8859-1";
|
|
Packit |
b099d7 |
type = XmCHARSET_TEXT;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
#ifdef UTF8_SUPPORTED
|
|
Packit |
b099d7 |
else if (text_prop->encoding == atoms[XmAUTF8_STRING])
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
tag = "UTF-8";
|
|
Packit |
b099d7 |
type = XmCHARSET_TEXT;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
#endif
|
|
Packit |
b099d7 |
else {
|
|
Packit |
b099d7 |
_XmAppUnlock(app);
|
|
Packit |
b099d7 |
return(XLocaleNotSupported);
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* We fell through the else-if's so pull apart the data in the text
|
|
Packit |
b099d7 |
property and set up a return string table. */
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* First count up how many string elements there are in the value. */
|
|
Packit |
b099d7 |
for (i = 0, elements = 1; i < text_prop->nitems - 1; ++i)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
/* The text prop value will have two NULL's at the end,
|
|
Packit |
b099d7 |
one for the end of the last string and one to terminate
|
|
Packit |
b099d7 |
the entire value. The terminating NULL will be excluded
|
|
Packit |
b099d7 |
by looping until i == nitems since the terminating NULL
|
|
Packit |
b099d7 |
is not included in the nitems calculation. */
|
|
Packit |
b099d7 |
if (text_prop->value[i] == '\0')
|
|
Packit |
b099d7 |
++elements;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
/* Create an appropriately sized array of xmstrings */
|
|
Packit |
b099d7 |
string_table =
|
|
Packit |
b099d7 |
(XmStringTable)XtMalloc(sizeof(XmString) * (elements));
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* Create XmStrings from each string in the value field */
|
|
Packit |
b099d7 |
string_table[0] = XmStringGenerate((XtPointer)text_prop->value,
|
|
Packit |
b099d7 |
tag, type, NULL);
|
|
Packit |
b099d7 |
for (i = 0, elements = 1; i < text_prop->nitems - 1; ++i)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
if (text_prop->value[i] == '\0')
|
|
Packit |
b099d7 |
string_table[elements++] =
|
|
Packit |
b099d7 |
XmStringGenerate((XtPointer) &(text_prop->value[i + 1]),
|
|
Packit |
b099d7 |
tag, type, NULL);
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
*string_table_return = string_table;
|
|
Packit |
b099d7 |
*count_return = elements;
|
|
Packit |
b099d7 |
_XmAppUnlock(app);
|
|
Packit |
b099d7 |
return(Success);
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|