Blame lib/Xm/XmStringSeg.c

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
#ifdef HAVE_CONFIG_H
Packit b099d7
#include <config.h>
Packit b099d7
#endif
Packit b099d7
Packit b099d7
Packit b099d7
#ifdef REV_INFO
Packit b099d7
#ifndef lint
Packit b099d7
static char rcsid[] = "$XConsortium: XmStringSeg.c /main/7 1995/09/19 23:13:59 cde-sun $"
Packit b099d7
#endif
Packit b099d7
#endif
Packit b099d7
Packit b099d7
#include <Xm/XmosP.h>
Packit b099d7
Packit b099d7
#include "XmI.h"
Packit b099d7
#include "XmStringI.h"
Packit b099d7
#include "XmRenderTI.h"
Packit b099d7
Packit b099d7
Packit b099d7
/*
Packit b099d7
 * _XmStringGetSegment: A generalized version of XmStringGetNextSegment.
Packit b099d7
 *	Returns char_count, and allows explicit control over peeking
Packit b099d7
 *	and copying of data.  Interleaving of calls to _XmStringGetSegment()
Packit b099d7
 *	and XmeStringGetComponent() is supported.
Packit b099d7
 */
Packit b099d7
Boolean
Packit b099d7
_XmStringGetSegment(_XmStringContext   context, 
Packit b099d7
		    Boolean	       update_context,
Packit b099d7
		    Boolean	       copy_data,
Packit b099d7
		    XtPointer         *text, 
Packit b099d7
		    XmStringTag       *tag, 
Packit b099d7
		    XmTextType        *type, 
Packit b099d7
		    XmStringTag      **rendition_tags, 
Packit b099d7
		    unsigned int      *tag_count,
Packit b099d7
		    XmStringDirection *direction,
Packit b099d7
		    Boolean           *separator, 
Packit b099d7
		    unsigned char     *tabs,
Packit b099d7
		    short             *char_count,
Packit b099d7
		    XmDirection       *push_before,
Packit b099d7
		    Boolean	      *pop_after)
Packit b099d7
{
Packit b099d7
  XmStringTag*   	perm_rends = NULL;
Packit b099d7
  _XmStringContextRec	local_context_data;
Packit b099d7
  _XmStringContext	local_context = context;
Packit b099d7
  Boolean		result = FALSE;
Packit b099d7
  Boolean 		done;
Packit b099d7
  Boolean		new_renditions;
Packit b099d7
  XmStringComponentType ctype;
Packit b099d7
  unsigned int 		len;
Packit b099d7
  XtPointer 		val;
Packit b099d7
  
Packit b099d7
  /* Initialize the out parameters */
Packit b099d7
  if (text)           *text           = NULL;
Packit b099d7
  if (tag)            *tag            = NULL;
Packit b099d7
  if (type)           *type           = XmCHARSET_TEXT;
Packit b099d7
  if (rendition_tags) *rendition_tags = NULL;
Packit b099d7
  if (tag_count)      *tag_count      = 0;
Packit b099d7
  if (direction)      *direction      = _XmStrContDir(context);	/* for BC */
Packit b099d7
  if (separator)      *separator      = False;
Packit b099d7
  if (tabs)           *tabs           = 0;
Packit b099d7
  if (char_count)     *char_count     = 0;
Packit b099d7
  if (push_before)    *push_before    = 0;
Packit b099d7
  if (pop_after)      *pop_after      = False;
Packit b099d7
  
Packit b099d7
  /* No NULL pointers allowed. */
Packit b099d7
  if (! (context && text && tag && type && rendition_tags && tag_count
Packit b099d7
	 && direction && separator && tabs && char_count && push_before
Packit b099d7
	 && pop_after))
Packit b099d7
    return False;
Packit b099d7
Packit b099d7
  if (_XmStrContError(context))
Packit b099d7
    return False;
Packit b099d7
Packit b099d7
  /* Setup a writable context. */
Packit b099d7
  if (!update_context)
Packit b099d7
    {
Packit b099d7
      local_context = &local_context_data;
Packit b099d7
      _XmStringContextCopy(local_context, context);
Packit b099d7
    }
Packit b099d7
Packit b099d7
  /* N.B.: This code relies on the order of components from XmeStringGetComponent()! */
Packit b099d7
  done = new_renditions = FALSE;
Packit b099d7
  while (!done)
Packit b099d7
    {
Packit b099d7
      /* Peek at components before consuming them. */
Packit b099d7
      ctype = XmeStringGetComponent(local_context, FALSE, FALSE, &len, &val;;
Packit b099d7
      switch (ctype)
Packit b099d7
	{
Packit b099d7
	case XmSTRING_COMPONENT_LAYOUT_PUSH:
Packit b099d7
	  if (*tabs || *text)
Packit b099d7
	    done = TRUE;
Packit b099d7
	  else
Packit b099d7
	    *push_before = *((XmDirection *) val);
Packit b099d7
	  break;
Packit b099d7
Packit b099d7
	case XmSTRING_COMPONENT_RENDITION_BEGIN:
Packit b099d7
	  if (*text)
Packit b099d7
	    done = TRUE;
Packit b099d7
	  else if (*tabs)
Packit b099d7
	    new_renditions = TRUE;
Packit b099d7
	  break;
Packit b099d7
Packit b099d7
	case XmSTRING_COMPONENT_CHARSET:
Packit b099d7
	case XmSTRING_COMPONENT_LOCALE:
Packit b099d7
	  if (*text)
Packit b099d7
	    done = TRUE;
Packit b099d7
	  else
Packit b099d7
	    *tag = (XmStringTag) val;
Packit b099d7
	  break;
Packit b099d7
Packit b099d7
	case XmSTRING_COMPONENT_TAB:
Packit b099d7
	  if (*text)
Packit b099d7
	    done = TRUE;
Packit b099d7
	  else
Packit b099d7
	    {
Packit b099d7
	      /* Save the renditions now. */
Packit b099d7
	      if ((*tag_count == 0) && _XmStrContRendCount(local_context))
Packit b099d7
		{
Packit b099d7
		  *tag_count = _XmStrContRendCount(local_context);
Packit b099d7
		  if (copy_data)
Packit b099d7
		    {
Packit b099d7
		      int tmp;
Packit b099d7
		      *rendition_tags = (XmStringTag *)
Packit b099d7
			XtMalloc(sizeof(XmStringTag) * *tag_count);
Packit b099d7
		      for (tmp = 0; tmp < *tag_count; tmp++)
Packit b099d7
			(*rendition_tags)[tmp] = 
Packit b099d7
			  XtNewString(_XmStrContRendTags(local_context)[tmp]);
Packit b099d7
		    }
Packit b099d7
		  else
Packit b099d7
		    {
Packit b099d7
		      perm_rends = (XmStringTag *)
Packit b099d7
			XtMalloc(sizeof(XmStringTag) * *tag_count);
Packit b099d7
		      memcpy((char*) perm_rends,
Packit b099d7
			     _XmStrContRendTags(local_context),
Packit b099d7
			     sizeof(XmStringTag) * *tag_count);
Packit b099d7
		      *rendition_tags = perm_rends;
Packit b099d7
		    }
Packit b099d7
		}
Packit b099d7
Packit b099d7
	      /* Return at the end of this line. */
Packit b099d7
	      (*tabs)++;
Packit b099d7
	      result = TRUE;
Packit b099d7
	    }
Packit b099d7
	  break;
Packit b099d7
Packit b099d7
	case XmSTRING_COMPONENT_DIRECTION:
Packit b099d7
	  if (*text)
Packit b099d7
	    done = TRUE;
Packit b099d7
	  else
Packit b099d7
	    *direction = *((XmStringDirection *) val);
Packit b099d7
	  break;
Packit b099d7
Packit b099d7
	case XmSTRING_COMPONENT_TEXT:
Packit b099d7
	case XmSTRING_COMPONENT_LOCALE_TEXT:
Packit b099d7
	case XmSTRING_COMPONENT_WIDECHAR_TEXT:
Packit b099d7
	  if (*text)
Packit b099d7
	    done = TRUE;
Packit b099d7
	  else if (*tabs && new_renditions)
Packit b099d7
	    {
Packit b099d7
	      /* Tabs had a different set of renditions than the text, */
Packit b099d7
	      /* so we can't return both tabs and text at once. */
Packit b099d7
	      done = TRUE;
Packit b099d7
	    }
Packit b099d7
	  else
Packit b099d7
	    {
Packit b099d7
	      *char_count = len;
Packit b099d7
	      *text = val;
Packit b099d7
	      
Packit b099d7
	      if (ctype == XmSTRING_COMPONENT_TEXT)
Packit b099d7
		*type = XmCHARSET_TEXT;
Packit b099d7
	      else if (ctype == XmSTRING_COMPONENT_LOCALE_TEXT)
Packit b099d7
		*type = XmMULTIBYTE_TEXT;
Packit b099d7
	      else if (ctype == XmSTRING_COMPONENT_WIDECHAR_TEXT)
Packit b099d7
		*type = XmWIDECHAR_TEXT;
Packit b099d7
	      else
Packit b099d7
		{ assert(FALSE); }
Packit b099d7
	      
Packit b099d7
	      /* Force a tag for backward compatibility with Motif 1.2 */
Packit b099d7
	      if (! *tag)
Packit b099d7
		*tag = _XmStrContTag(local_context);
Packit b099d7
Packit b099d7
	      result = TRUE;
Packit b099d7
	      
Packit b099d7
	      /* Save the renditions now. */
Packit b099d7
	      if ((*tag_count == 0) && _XmStrContRendCount(local_context))
Packit b099d7
		{
Packit b099d7
		  *tag_count = _XmStrContRendCount(local_context);
Packit b099d7
		  if (copy_data)
Packit b099d7
		    {
Packit b099d7
		      int tmp;
Packit b099d7
		      *rendition_tags = (XmStringTag*)
Packit b099d7
			XtMalloc(sizeof(XmStringTag) * *tag_count);
Packit b099d7
		      for (tmp = 0; tmp < *tag_count; tmp++)
Packit b099d7
			(*rendition_tags)[tmp] = 
Packit b099d7
			  XtNewString(_XmStrContRendTags(local_context)[tmp]);
Packit b099d7
		    }
Packit b099d7
		  else
Packit b099d7
		    {
Packit b099d7
		      perm_rends = (XmStringTag *)
Packit b099d7
			XtMalloc(sizeof(XmStringTag) * *tag_count);
Packit b099d7
		      memcpy((char*) perm_rends,
Packit b099d7
			     _XmStrContRendTags(local_context),
Packit b099d7
			     sizeof(XmStringTag) * *tag_count);
Packit b099d7
		      *rendition_tags = perm_rends;
Packit b099d7
		    }
Packit b099d7
		}
Packit b099d7
	    }
Packit b099d7
	  break;
Packit b099d7
	      
Packit b099d7
	case XmSTRING_COMPONENT_RENDITION_END:
Packit b099d7
	  break;
Packit b099d7
	      
Packit b099d7
	case XmSTRING_COMPONENT_LAYOUT_POP:
Packit b099d7
	  if (*tabs || *text)
Packit b099d7
	    {
Packit b099d7
	      /* We're almost done, so record this pop. */
Packit b099d7
	      *pop_after = TRUE;
Packit b099d7
	    }
Packit b099d7
	  else
Packit b099d7
	    {
Packit b099d7
	      /* We're ignoring this pop, so discard any recorded push. */
Packit b099d7
	      *push_before = 0;
Packit b099d7
	    }
Packit b099d7
	  break;
Packit b099d7
Packit b099d7
	case XmSTRING_COMPONENT_SEPARATOR:
Packit b099d7
	  if (*tabs || *text)
Packit b099d7
	    {
Packit b099d7
	      *separator = TRUE;
Packit b099d7
	      done = TRUE;
Packit b099d7
	    }
Packit b099d7
	  break;
Packit b099d7
	  
Packit b099d7
	case XmSTRING_COMPONENT_END:
Packit b099d7
	default:
Packit b099d7
	  done = TRUE;
Packit b099d7
	  break;
Packit b099d7
	}
Packit b099d7
Packit b099d7
      /* Consume the component if we aren't done. */
Packit b099d7
      if (!done)
Packit b099d7
	(void) XmeStringGetComponent(local_context, TRUE, FALSE, &len, &val;;
Packit b099d7
    }
Packit b099d7
Packit b099d7
  if (copy_data && result)
Packit b099d7
    {
Packit b099d7
      /* Copy the tag. */
Packit b099d7
      if (*tag)
Packit b099d7
	*tag = XtNewString(*tag);
Packit b099d7
Packit b099d7
      /* Copy the text. */
Packit b099d7
      if (*text)
Packit b099d7
	{
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
	  *text = (XtPointer) tmp;
Packit b099d7
	}
Packit b099d7
    }
Packit b099d7
Packit b099d7
  /* Free the local context. */
Packit b099d7
  if (local_context == &local_context_data)
Packit b099d7
    _XmStringContextFree(local_context);
Packit b099d7
Packit b099d7
  return result;
Packit b099d7
}
Packit b099d7

Packit b099d7
Boolean 
Packit b099d7
_XmStringGetNextSegment(
Packit b099d7
        _XmStringContext context,
Packit b099d7
        XmStringTag *tag,
Packit b099d7
        XmStringDirection *direction,
Packit b099d7
        char **text,
Packit b099d7
        short *char_count,
Packit b099d7
        Boolean *separator )
Packit b099d7
{
Packit b099d7
  Boolean       result;
Packit b099d7
  XmTextType    type;
Packit b099d7
  XmStringTag * rendition_tags;
Packit b099d7
  unsigned int  tag_count;
Packit b099d7
  unsigned char tabs;
Packit b099d7
  XmDirection   push_before;
Packit b099d7
  Boolean	pop_after;
Packit b099d7
Packit b099d7
  /* Get all the fields and discard the ones we don't want. */
Packit b099d7
  result = _XmStringGetSegment(context, True, True, (XtPointer*) text, tag,
Packit b099d7
		       &type, &rendition_tags, &tag_count, direction,
Packit b099d7
		       separator, &tabs, char_count, &push_before, &pop_after);
Packit b099d7
  if (result) {
Packit b099d7
    if (rendition_tags)
Packit b099d7
      {
Packit b099d7
	while (tag_count-- > 0)
Packit b099d7
	  XtFree((char*) rendition_tags[tag_count]);
Packit b099d7
	XtFree((char*) rendition_tags);
Packit b099d7
      }
Packit b099d7
    
Packit b099d7
    if (type == XmWIDECHAR_TEXT && *text) {
Packit b099d7
      /* must convert (this should be done in segment's locale instead) */
Packit b099d7
      int len;
Packit b099d7
      wchar_t *wtext = (wchar_t *)(*text);
Packit b099d7
Packit b099d7
      /* should be enough */
Packit b099d7
      len = ((*char_count)*MB_CUR_MAX)/sizeof(wchar_t);
Packit b099d7
Packit b099d7
      *text = (char *)XtMalloc(len+1);
Packit b099d7
      *char_count = wcstombs(*text, wtext, len);
Packit b099d7
      if ((*char_count) == (size_t)-1) {
Packit b099d7
	result = False;
Packit b099d7
	XtFree(*text); *text = NULL;
Packit b099d7
	XtFree((char *)*tag); *tag = NULL;
Packit b099d7
      } else
Packit b099d7
	(*text)[*char_count] = '\0';
Packit b099d7
      XtFree((char *)wtext);
Packit b099d7
    } 
Packit b099d7
  }
Packit b099d7
	  
Packit b099d7
  return result;
Packit b099d7
}
Packit b099d7

Packit b099d7
/*
Packit b099d7
 * fetch the next 'segment' of the external TCS
Packit b099d7
 */
Packit b099d7
Boolean 
Packit b099d7
XmStringGetNextSegment(XmStringContext context,
Packit b099d7
		       char **text,
Packit b099d7
		       XmStringTag *tag,
Packit b099d7
		       XmStringDirection *direction,
Packit b099d7
		       Boolean *separator )
Packit b099d7
{
Packit b099d7
  short char_count;
Packit b099d7
  Boolean ret_val;
Packit b099d7
  
Packit b099d7
  _XmProcessLock();
Packit b099d7
  ret_val = _XmStringGetNextSegment((_XmStringContext)context, 
Packit b099d7
		 tag, direction, text, &char_count, separator);
Packit b099d7
  _XmProcessUnlock();
Packit b099d7
  return ret_val;
Packit b099d7
}