Blame lib/Xm/TxtPropCv.c

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