Blame lib/Xm/XmStringFunc.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[] = "$TOG: XmStringFunc.c /main/9 1999/10/14 11:20:50 mgreess $"
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
#include "XmTabListI.h"
Packit b099d7
Packit b099d7
/********    Static Function Declarations    ********/
Packit b099d7
Packit b099d7
static void new_line(_XmString string) ;
Packit b099d7
Packit b099d7
/********    End Static Function Declarations    ********/
Packit b099d7
Packit b099d7

Packit b099d7
XmStringComponentType
Packit b099d7
XmStringPeekNextTriple(XmStringContext context)
Packit b099d7
{
Packit b099d7
  unsigned int len;
Packit b099d7
  XtPointer    val;
Packit b099d7
Packit b099d7
  return XmeStringGetComponent((_XmStringContext) context, False, False, &len, &val;;
Packit b099d7
}
Packit b099d7
Packit b099d7
Boolean 
Packit b099d7
XmStringHasSubstring(
Packit b099d7
        XmString string,
Packit b099d7
        XmString substring )
Packit b099d7
{
Packit b099d7
  _XmStringContextRec stack_context;
Packit b099d7
  char               *text;
Packit b099d7
  char               *subtext;
Packit b099d7
  short               char_count;
Packit b099d7
  short               subchar_count;
Packit b099d7
  Boolean             found;
Packit b099d7
  int                 i, j, max;
Packit b099d7
  _XmStringEntry      line, *entry, seg;
Packit b099d7
  XmStringComponentType type;
Packit b099d7
  unsigned int        len;
Packit b099d7
  XtPointer	      val;
Packit b099d7
    
Packit b099d7
  _XmProcessLock();
Packit b099d7
  if ((string == NULL) || (substring == NULL) || (XmStringEmpty(substring))) {
Packit b099d7
    _XmProcessUnlock();
Packit b099d7
    return (FALSE);
Packit b099d7
  }
Packit b099d7
Packit b099d7
  /*
Packit b099d7
   * The substring must be a one line/one segment string.
Packit b099d7
   */
Packit b099d7
  
Packit b099d7
  if (_XmStrEntryCountGet(substring) != 1) {
Packit b099d7
    _XmProcessUnlock();
Packit b099d7
    return (FALSE);
Packit b099d7
  }
Packit b099d7
Packit b099d7
  if (((entry = _XmStrEntryGet(substring)) != NULL) && 
Packit b099d7
      _XmEntrySegmentCountGet(entry[0]) > 1) {
Packit b099d7
    _XmProcessUnlock();
Packit b099d7
    return (FALSE);
Packit b099d7
  }
Packit b099d7
Packit b099d7
  /*
Packit b099d7
   * Get the text out of the substring.
Packit b099d7
   */
Packit b099d7
Packit b099d7
  if (_XmStrOptimized(substring))
Packit b099d7
    {
Packit b099d7
      subchar_count = (short)_XmStrByteCount(substring);
Packit b099d7
      subtext = (char *)_XmStrText(substring);
Packit b099d7
    }
Packit b099d7
  else if (_XmStrMultiple(substring))
Packit b099d7
    {
Packit b099d7
      line = entry[0];
Packit b099d7
      
Packit b099d7
      if (_XmEntryMultiple(line))
Packit b099d7
	{
Packit b099d7
	  seg = (_XmStringEntry)_XmEntrySegmentGet(line)[0];
Packit b099d7
	  
Packit b099d7
	  subchar_count = (short)_XmEntryByteCountGet(seg);
Packit b099d7
	  subtext = (char*) _XmEntryTextGet(seg);
Packit b099d7
	}
Packit b099d7
      else
Packit b099d7
	{
Packit b099d7
	  subchar_count = (short)_XmEntryByteCountGet(line);
Packit b099d7
	  subtext = (char*) _XmEntryTextGet(line);
Packit b099d7
	}
Packit b099d7
    }
Packit b099d7
  else { 		  /* Oops, some weird string! */
Packit b099d7
    _XmProcessUnlock();
Packit b099d7
    return (FALSE);
Packit b099d7
  }
Packit b099d7
  
Packit b099d7
    
Packit b099d7
  if ((subchar_count == 0) || (subtext == NULL)) {
Packit b099d7
    _XmProcessUnlock();
Packit b099d7
    return (FALSE);
Packit b099d7
  }
Packit b099d7
Packit b099d7
  /** Find a text component that matches. **/
Packit b099d7
  if (string) {
Packit b099d7
    _XmStringContextReInit(&stack_context, string);
Packit b099d7
    while ((type = XmeStringGetComponent(&stack_context, TRUE, FALSE, 
Packit b099d7
					 &len, &val)) != 
Packit b099d7
	   XmSTRING_COMPONENT_END)
Packit b099d7
      {
Packit b099d7
	switch(type) 
Packit b099d7
	  {
Packit b099d7
	  case XmSTRING_COMPONENT_TEXT:
Packit b099d7
	  case XmSTRING_COMPONENT_LOCALE_TEXT:
Packit b099d7
	  case XmSTRING_COMPONENT_WIDECHAR_TEXT:
Packit b099d7
Packit b099d7
	    char_count = len;
Packit b099d7
	    text = (char *)val;
Packit b099d7
	      
Packit b099d7
	    if (char_count >= subchar_count) {
Packit b099d7
	      max = char_count - subchar_count;
Packit b099d7
	      for (i = 0; i <= max; i++) {
Packit b099d7
		found = TRUE;
Packit b099d7
	      
Packit b099d7
		for (j = 0; j < subchar_count; j++) {
Packit b099d7
		  if (text[i+j] != subtext[j])  {
Packit b099d7
		    found = FALSE;
Packit b099d7
		    break;
Packit b099d7
		  }
Packit b099d7
		}
Packit b099d7
		if (found) {
Packit b099d7
		  _XmStringContextFree(&stack_context);
Packit b099d7
    		  _XmProcessUnlock();
Packit b099d7
		  return(TRUE);
Packit b099d7
		}
Packit b099d7
	      }
Packit b099d7
	    }
Packit b099d7
	    break;
Packit b099d7
	  default:
Packit b099d7
	    break;
Packit b099d7
	  }
Packit b099d7
      }
Packit b099d7
    _XmStringContextFree(&stack_context);
Packit b099d7
  }
Packit b099d7
  _XmProcessUnlock();
Packit b099d7
  return (FALSE);
Packit b099d7
}
Packit b099d7

Packit b099d7
XmStringTable
Packit b099d7
XmStringTableParseStringArray(XtPointer   *strings,
Packit b099d7
			      Cardinal     count,
Packit b099d7
			      XmStringTag  tag, 
Packit b099d7
			      XmTextType   type, 
Packit b099d7
			      XmParseTable parse, 
Packit b099d7
			      Cardinal     parse_count,
Packit b099d7
			      XtPointer    call_data)
Packit b099d7
{
Packit b099d7
  int	i;
Packit b099d7
  XmStringTable strs;
Packit b099d7
Packit b099d7
  _XmProcessLock();
Packit b099d7
  if ((strings == NULL) || (count == 0)) {
Packit b099d7
    _XmProcessUnlock();
Packit b099d7
    return(NULL);
Packit b099d7
  }
Packit b099d7
  
Packit b099d7
  strs = (XmStringTable)XtMalloc(count * sizeof(XmString));
Packit b099d7
  
Packit b099d7
  for (i = 0; i < count; i++)
Packit b099d7
    {
Packit b099d7
      strs[i] = XmStringParseText(strings[i], NULL, tag, type, 
Packit b099d7
				  parse, parse_count, call_data);
Packit b099d7
    }
Packit b099d7
Packit b099d7
  _XmProcessUnlock();
Packit b099d7
  return(strs);
Packit b099d7
}
Packit b099d7
Packit b099d7
XtPointer *
Packit b099d7
XmStringTableUnparse(XmStringTable     table,
Packit b099d7
		     Cardinal	       count,
Packit b099d7
		     XmStringTag       tag, 
Packit b099d7
		     XmTextType        tag_type, 
Packit b099d7
		     XmTextType        output_type, 
Packit b099d7
		     XmParseTable      parse, 
Packit b099d7
		     Cardinal          parse_count, 
Packit b099d7
		     XmParseModel      parse_model)
Packit b099d7
{
Packit b099d7
  XtPointer	*strs;
Packit b099d7
  int		i;
Packit b099d7
  
Packit b099d7
  _XmProcessLock();
Packit b099d7
  if ((table == NULL) || (count == 0)) {
Packit b099d7
    _XmProcessUnlock();
Packit b099d7
    return(NULL);
Packit b099d7
  }
Packit b099d7
  
Packit b099d7
  strs = (XtPointer *)XtMalloc(count * sizeof(XtPointer));
Packit b099d7
  
Packit b099d7
  for (i = 0; i < count; i++)
Packit b099d7
    strs[i] = XmStringUnparse(table[i], tag, tag_type, output_type,
Packit b099d7
			      parse, parse_count, parse_model);
Packit b099d7
  _XmProcessUnlock();
Packit b099d7
  return(strs);
Packit b099d7
}
Packit b099d7
Packit b099d7
XmString
Packit b099d7
XmStringTableToXmString(XmStringTable  table,
Packit b099d7
			Cardinal       count,
Packit b099d7
			XmString       break_comp)
Packit b099d7
{
Packit b099d7
  /* Note: this is a very expensive way to do this.  Fix for Beta */
Packit b099d7
  int		i;
Packit b099d7
  XmString	str = NULL, tmp1, tmp2;
Packit b099d7
Packit b099d7
  _XmProcessLock();
Packit b099d7
  tmp1 = NULL;
Packit b099d7
Packit b099d7
  for (i = 0; i < count; i++)
Packit b099d7
    {
Packit b099d7
      tmp2 = XmStringConcatAndFree(tmp1, XmStringCopy(table[i]));
Packit b099d7
      str = XmStringConcatAndFree(tmp2, XmStringCopy(break_comp));
Packit b099d7
Packit b099d7
      tmp1 = str;
Packit b099d7
    }
Packit b099d7
  
Packit b099d7
  _XmProcessUnlock();
Packit b099d7
  return(str);
Packit b099d7
}
Packit b099d7

Packit b099d7
XmString
Packit b099d7
XmStringPutRendition(XmString string,
Packit b099d7
		     XmStringTag rendition)
Packit b099d7
{
Packit b099d7
  /* Quick and dirty.  Fix for beta! */
Packit b099d7
  XmString	str, tmp1, tmp2;
Packit b099d7
  
Packit b099d7
  tmp1 = XmStringComponentCreate(XmSTRING_COMPONENT_RENDITION_BEGIN,
Packit b099d7
				 strlen(rendition), (XtPointer)rendition);
Packit b099d7
  tmp2 = XmStringConcatAndFree(tmp1, XmStringCopy(string));
Packit b099d7
Packit b099d7
  tmp1 = XmStringComponentCreate(XmSTRING_COMPONENT_RENDITION_END,
Packit b099d7
				 strlen(rendition), (XtPointer)rendition);
Packit b099d7
  str = XmStringConcatAndFree(tmp2, tmp1);
Packit b099d7
  
Packit b099d7
  return(str);
Packit b099d7
}
Packit b099d7

Packit b099d7
void 
Packit b099d7
XmParseMappingGetValues(XmParseMapping mapping,
Packit b099d7
			ArgList        arg_list,
Packit b099d7
			Cardinal       arg_count)
Packit b099d7
{
Packit b099d7
  register Cardinal i;
Packit b099d7
  register String arg_name;
Packit b099d7
Packit b099d7
  _XmProcessLock();
Packit b099d7
  /* Do a little error checking. */
Packit b099d7
  if (mapping == NULL) {
Packit b099d7
    _XmProcessUnlock();
Packit b099d7
    return;
Packit b099d7
  }
Packit b099d7
Packit b099d7
  /* Modify the specified values. */
Packit b099d7
  for (i = 0; i < arg_count; i++)
Packit b099d7
    {
Packit b099d7
      arg_name = arg_list[i].name;
Packit b099d7
Packit b099d7
      if ((arg_name == XmNpattern) ||
Packit b099d7
	  (strcmp(arg_name, XmNpattern) == 0))
Packit b099d7
	*((XtPointer*)arg_list[i].value) = mapping->pattern;
Packit b099d7
      else if ((arg_name == XmNpatternType) ||
Packit b099d7
	       (strcmp(arg_name, XmNpatternType) == 0))
Packit b099d7
	*((XmTextType*)arg_list[i].value) = mapping->pattern_type;
Packit b099d7
      else if ((arg_name == XmNsubstitute) ||
Packit b099d7
	       (strcmp(arg_name, XmNsubstitute) == 0))
Packit b099d7
	*((XmString*)arg_list[i].value) = XmStringCopy(mapping->substitute);
Packit b099d7
      else if ((arg_name == XmNinvokeParseProc) ||
Packit b099d7
	       (strcmp(arg_name, XmNinvokeParseProc) == 0))
Packit b099d7
	*((XmParseProc*)arg_list[i].value) = mapping->parse_proc;
Packit b099d7
      else if ((arg_name == XmNclientData) ||
Packit b099d7
	       (strcmp(arg_name, XmNclientData) == 0))
Packit b099d7
	*((XtPointer*)arg_list[i].value) = mapping->client_data;
Packit b099d7
      else if ((arg_name == XmNincludeStatus) ||
Packit b099d7
	       (strcmp(arg_name, XmNincludeStatus) == 0))
Packit b099d7
	*((XmIncludeStatus*)arg_list[i].value) = mapping->include_status;
Packit b099d7
    }
Packit b099d7
  _XmProcessUnlock();
Packit b099d7
}
Packit b099d7

Packit b099d7
void 
Packit b099d7
XmParseMappingFree(XmParseMapping mapping)
Packit b099d7
{
Packit b099d7
  _XmProcessLock();
Packit b099d7
  if (mapping != NULL)
Packit b099d7
    {
Packit b099d7
      /* Free copied data. */
Packit b099d7
      XmStringFree(mapping->substitute);
Packit b099d7
Packit b099d7
      /* Free the record. */
Packit b099d7
      XtFree((char*) mapping);
Packit b099d7
    }
Packit b099d7
  _XmProcessUnlock();
Packit b099d7
}
Packit b099d7

Packit b099d7
void 
Packit b099d7
XmParseTableFree(XmParseTable parse_table,
Packit b099d7
		 Cardinal     parse_count)
Packit b099d7
{
Packit b099d7
  /* Free each entry in the table. */
Packit b099d7
  Cardinal i;
Packit b099d7
Packit b099d7
  _XmProcessLock();
Packit b099d7
  for (i = 0; i < parse_count; i++)
Packit b099d7
    XmParseMappingFree(parse_table[i]);
Packit b099d7
Packit b099d7
  /* Free the table itself. */
Packit b099d7
  XtFree((char*) parse_table);
Packit b099d7
  _XmProcessUnlock();
Packit b099d7
}
Packit b099d7

Packit b099d7
/*
Packit b099d7
 * XmeGetNextCharacter: An XmParseProc to consume the triggering
Packit b099d7
 *	character and insert the following character.
Packit b099d7
 */
Packit b099d7
/*ARGSUSED*/
Packit b099d7
XmIncludeStatus
Packit b099d7
XmeGetNextCharacter(XtPointer     *in_out, 
Packit b099d7
		    XtPointer      text_end,
Packit b099d7
		    XmTextType     type, 
Packit b099d7
		    XmStringTag    tag, 
Packit b099d7
		    XmParseMapping entry, /* unused */
Packit b099d7
		    int		   pattern_length,
Packit b099d7
		    XmString      *str_include,
Packit b099d7
		    XtPointer      call_data) /* unused */
Packit b099d7
{
Packit b099d7
  char* ptr = (char*) *in_out;
Packit b099d7
  int len = 0;
Packit b099d7
  XmStringComponentType comp_type;
Packit b099d7
  assert(in_out != NULL);
Packit b099d7
Packit b099d7
  _XmProcessLock();
Packit b099d7
  /* Initialize the out parameters */
Packit b099d7
  *str_include = NULL;
Packit b099d7
Packit b099d7
  /* Consume the triggering characters. */
Packit b099d7
  ptr += pattern_length;
Packit b099d7
Packit b099d7
  /* Select the component type. */
Packit b099d7
  switch (type)
Packit b099d7
    {
Packit b099d7
    case XmCHARSET_TEXT:
Packit b099d7
      if ((tag != NULL) && (strcmp(XmFONTLIST_DEFAULT_TAG, tag) == 0))
Packit b099d7
	comp_type = XmSTRING_COMPONENT_LOCALE_TEXT;
Packit b099d7
      else
Packit b099d7
	comp_type = XmSTRING_COMPONENT_TEXT;
Packit b099d7
      if ((text_end == NULL) || (ptr < (char*) text_end))
Packit b099d7
#ifndef NO_MULTIBYTE
Packit b099d7
	len = mblen(ptr, MB_CUR_MAX);
Packit b099d7
#else
Packit b099d7
        len = *ptr ? 1 : 0;
Packit b099d7
#endif
Packit b099d7
      break;
Packit b099d7
Packit b099d7
    case XmMULTIBYTE_TEXT:
Packit b099d7
      /* In Motif 2.0 dynamic switching of locales isn't supported. */
Packit b099d7
      comp_type = XmSTRING_COMPONENT_LOCALE_TEXT;
Packit b099d7
      if ((text_end == NULL) || (ptr < (char*) text_end))
Packit b099d7
#ifndef NO_MULTIBYTE
Packit b099d7
	len = mblen(ptr, MB_CUR_MAX);
Packit b099d7
#else
Packit b099d7
        len = *ptr ? 1 : 0;
Packit b099d7
#endif
Packit b099d7
      break;
Packit b099d7
Packit b099d7
    case XmWIDECHAR_TEXT:
Packit b099d7
      comp_type = XmSTRING_COMPONENT_WIDECHAR_TEXT;
Packit b099d7
      if ((text_end == NULL) || (ptr < (char*) text_end))
Packit b099d7
	len = sizeof(wchar_t);
Packit b099d7
      break;
Packit b099d7
Packit b099d7
    default:
Packit b099d7
      comp_type = XmSTRING_COMPONENT_UNKNOWN;
Packit b099d7
      break;
Packit b099d7
    }
Packit b099d7
Packit b099d7
  /* Quit if mblen() failed or if type was unrecognized. */
Packit b099d7
  if ((len <= 0) || (comp_type == XmSTRING_COMPONENT_UNKNOWN))
Packit b099d7
    {
Packit b099d7
      *in_out = (XtPointer) ptr;
Packit b099d7
      _XmProcessUnlock();
Packit b099d7
      return XmINSERT;
Packit b099d7
    }
Packit b099d7
Packit b099d7
  /* Create a component containing the next character. */
Packit b099d7
  *str_include = XmStringComponentCreate(comp_type, len, ptr);
Packit b099d7
  ptr += len;
Packit b099d7
  *in_out = (XtPointer) ptr;
Packit b099d7
  
Packit b099d7
  _XmProcessUnlock();
Packit b099d7
  return XmINSERT;
Packit b099d7
}
Packit b099d7

Packit b099d7
static void 
Packit b099d7
new_line(
Packit b099d7
        _XmString string )
Packit b099d7
{
Packit b099d7
    int lc = _XmStrEntryCount(string);
Packit b099d7
    _XmStringEntry line;
Packit b099d7
    
Packit b099d7
    _XmStrImplicitLine(string) = TRUE;
Packit b099d7
Packit b099d7
    _XmStrEntry(string) = (_XmStringEntry *) 
Packit b099d7
      XtRealloc((char *) _XmStrEntry(string), 
Packit b099d7
		sizeof(_XmStringEntry) * (lc + 1));
Packit b099d7
    
Packit b099d7
    _XmEntryCreate(line, XmSTRING_ENTRY_ARRAY);
Packit b099d7
    _XmStrEntry(string)[lc] = line;
Packit b099d7
Packit b099d7
    _XmEntrySegmentCount(line) = 0;
Packit b099d7
    _XmEntrySegment(line) = NULL;
Packit b099d7
Packit b099d7
    _XmStrEntryCount(string)++;
Packit b099d7
}
Packit b099d7
Packit b099d7
static XmString
Packit b099d7
MakeStrFromSeg(XmStringContext start)
Packit b099d7
{
Packit b099d7
  _XmStringEntry	*line;
Packit b099d7
  _XmStringEntry	*segs, seg;
Packit b099d7
  _XmString		str;
Packit b099d7
  
Packit b099d7
  if (_XmStrContOpt(start)) {
Packit b099d7
    _XmStrContError(start) = TRUE;
Packit b099d7
    return(XmStringCopy(_XmStrContString(start)));
Packit b099d7
  } else {
Packit b099d7
    /* get segment */
Packit b099d7
    line = _XmStrEntry(_XmStrContString(start));
Packit b099d7
    
Packit b099d7
    /* Create XmString structure */
Packit b099d7
    _XmStrCreate(str, XmSTRING_MULTIPLE_ENTRY, 0);
Packit b099d7
    
Packit b099d7
    if (_XmEntryMultiple(line[_XmStrContCurrLine(start)])) {
Packit b099d7
      segs = (_XmStringEntry*)_XmEntrySegment(line[_XmStrContCurrLine(start)]);
Packit b099d7
      
Packit b099d7
      new_line(str);
Packit b099d7
    
Packit b099d7
      if (_XmStrContCurrSeg(start) < _XmEntrySegmentCount(line)) {
Packit b099d7
	seg = segs[_XmStrContCurrSeg(start)];
Packit b099d7
	
Packit b099d7
	_XmStringSegmentNew(str, 0, seg, True);
Packit b099d7
	
Packit b099d7
	_XmStrContCurrSeg(start)++;
Packit b099d7
	
Packit b099d7
	_XmStrContDir(start)     = _XmEntryDirectionGet(seg);
Packit b099d7
	_XmStrContTag(start)     = _XmEntryTag(seg);
Packit b099d7
	_XmStrContTagType(start) = (XmTextType) _XmEntryTextTypeGet(seg);
Packit b099d7
      } else {
Packit b099d7
	new_line(str);
Packit b099d7
	_XmStrContCurrSeg(start) = 0;
Packit b099d7
	_XmStrContCurrLine(start)++;
Packit b099d7
      }
Packit b099d7
    } else {
Packit b099d7
      seg = line[_XmStrContCurrLine(start)];
Packit b099d7
      _XmStringSegmentNew(str, 0, seg, True);
Packit b099d7
      
Packit b099d7
      _XmStrContCurrSeg(start) = 0;
Packit b099d7
      _XmStrContCurrLine(start)++;
Packit b099d7
      
Packit b099d7
      _XmStrContDir(start)     = _XmEntryDirectionGet(seg);
Packit b099d7
      _XmStrContTag(start)     = _XmEntryTag(seg);
Packit b099d7
      _XmStrContTagType(start) = (XmTextType) _XmEntryTextTypeGet(seg);
Packit b099d7
    }
Packit b099d7
    _XmStrContState(start)   = PUSH_STATE;
Packit b099d7
  }
Packit b099d7
  return(str);
Packit b099d7
}
Packit b099d7
Packit b099d7
static Boolean
Packit b099d7
LastSeg(XmStringContext start)
Packit b099d7
{
Packit b099d7
  _XmStringEntry	*line;
Packit b099d7
  
Packit b099d7
  if (_XmStrContOpt(start)) 
Packit b099d7
    {
Packit b099d7
      return(TRUE);
Packit b099d7
    } else {
Packit b099d7
      line = _XmStrEntry(_XmStrContString(start));
Packit b099d7
    
Packit b099d7
      if (_XmEntryMultiple(line[_XmStrContCurrLine(start)]))
Packit b099d7
	return(_XmStrContCurrSeg(start) == _XmEntrySegmentCount(line));
Packit b099d7
      else return(TRUE);
Packit b099d7
    }
Packit b099d7
}
Packit b099d7
Packit b099d7
static Boolean
Packit b099d7
ContextsMatch(XmStringContext a,
Packit b099d7
	      XmStringContext b)
Packit b099d7
{
Packit b099d7
  if ((_XmStrContCurrLine(a) == _XmStrContCurrLine(b)) &&
Packit b099d7
      (_XmStrContCurrSeg(a) == _XmStrContCurrSeg(b)) &&
Packit b099d7
      (_XmStrContState(a) == _XmStrContState(b)))
Packit b099d7
Packit b099d7
    if (((_XmStrContState(a) == BEGIN_REND_STATE) ||
Packit b099d7
	(_XmStrContState(a) == END_REND_STATE)))
Packit b099d7
Packit b099d7
      if (_XmStrContRendIndex(a) == _XmStrContRendIndex(b))
Packit b099d7
	return(TRUE);
Packit b099d7
      else return(FALSE);
Packit b099d7
Packit b099d7
    else return(TRUE);
Packit b099d7
Packit b099d7
  else return(FALSE);
Packit b099d7
}
Packit b099d7
Packit b099d7
static XmString
Packit b099d7
MakeStr(XmStringContext start,
Packit b099d7
	XmStringContext end)
Packit b099d7
{
Packit b099d7
  /* This is quick and dirty, need to be smarter about it before Beta. */
Packit b099d7
  XmStringComponentType	type;
Packit b099d7
  unsigned int		len;
Packit b099d7
  XtPointer		val;
Packit b099d7
  XmString		str;
Packit b099d7
  
Packit b099d7
Packit b099d7
  /* Next component over start until at segment break */
Packit b099d7
  str = NULL;
Packit b099d7
  
Packit b099d7
  while (_XmStrContState(start) != PUSH_STATE)
Packit b099d7
    {
Packit b099d7
      type = XmeStringGetComponent(start, TRUE, FALSE, &len, &val;;
Packit b099d7
Packit b099d7
      if (ContextsMatch(start, end)) return(str);
Packit b099d7
Packit b099d7
      str = XmStringConcatAndFree(str,
Packit b099d7
				  XmStringComponentCreate(type, len, val));
Packit b099d7
    }
Packit b099d7
       
Packit b099d7
  /* Next segment over start incrementing until one segment before context */
Packit b099d7
  while ((_XmStrContCurrLine(start) < (_XmStrContCurrLine(end) - 1)) ||
Packit b099d7
	 ((_XmStrContCurrLine(start) == _XmStrContCurrLine(end)) &&
Packit b099d7
	  (_XmStrContCurrSeg(start) < _XmStrContCurrSeg(end))) ||
Packit b099d7
	 !LastSeg(start))
Packit b099d7
    {
Packit b099d7
      str = XmStringConcatAndFree(str, MakeStrFromSeg(start));
Packit b099d7
    }
Packit b099d7
Packit b099d7
  /* Next component over start until it matches context */
Packit b099d7
  type = XmeStringGetComponent(start, TRUE, FALSE, &len, &val;;
Packit b099d7
  while (!ContextsMatch(start, end))
Packit b099d7
    {
Packit b099d7
      str = XmStringConcatAndFree(str, XmStringComponentCreate(type, len, val));
Packit b099d7
      type = XmeStringGetComponent(start, TRUE, FALSE, &len, &val;;
Packit b099d7
  }
Packit b099d7
    
Packit b099d7
  return(str);
Packit b099d7
}
Packit b099d7

Packit b099d7
Cardinal
Packit b099d7
XmStringToXmStringTable(XmString string, 
Packit b099d7
			XmString break_component,
Packit b099d7
			XmStringTable *table)
Packit b099d7
{
Packit b099d7
  /* Note: this is a very expensive way to do this.  Fix for Beta */
Packit b099d7
  _XmStringContextRec	stack_context, stack_start;
Packit b099d7
  XmStringComponentType	type, b_type;
Packit b099d7
  unsigned int		len, b_len;
Packit b099d7
  XtPointer		val, b_val;
Packit b099d7
  int			i, count;
Packit b099d7
  
Packit b099d7
  _XmProcessLock();
Packit b099d7
  /* Get triple for first component of break_component */
Packit b099d7
  if (break_component)
Packit b099d7
    {
Packit b099d7
      _XmStringContextReInit(&stack_context, break_component);
Packit b099d7
      b_type = XmeStringGetComponent(&stack_context, TRUE, FALSE, 
Packit b099d7
				     &b_len, &b_val);
Packit b099d7
      _XmStringContextFree(&stack_context);
Packit b099d7
    }
Packit b099d7
  else
Packit b099d7
    /* Nothing to match against.  Return complete string. */
Packit b099d7
    {
Packit b099d7
      if (table != NULL)
Packit b099d7
	{
Packit b099d7
	  *table = (XmStringTable)XtMalloc(sizeof(XmString));
Packit b099d7
	  *table[0] = XmStringCopy(string);
Packit b099d7
	}
Packit b099d7
      _XmProcessUnlock();
Packit b099d7
      return(1);
Packit b099d7
    }
Packit b099d7
Packit b099d7
  /* Get context */
Packit b099d7
  if (!string)
Packit b099d7
    {
Packit b099d7
      if (table != NULL) *table = NULL;
Packit b099d7
      _XmProcessUnlock();
Packit b099d7
      return(0);
Packit b099d7
    }
Packit b099d7
  _XmStringContextReInit(&stack_context, string);
Packit b099d7
  
Packit b099d7
  /* Count number of entries for table */
Packit b099d7
  count = 0;
Packit b099d7
  while ((type = XmeStringGetComponent(&stack_context, TRUE, FALSE, 
Packit b099d7
				       &len, &val)) != 
Packit b099d7
	 XmSTRING_COMPONENT_END)
Packit b099d7
    {
Packit b099d7
      if ((type == b_type) && (len == b_len) &&
Packit b099d7
	  (memcmp(val, b_val, len) == 0))
Packit b099d7
	count++;
Packit b099d7
    }
Packit b099d7
Packit b099d7
  /* Allocate table and insert new strings */
Packit b099d7
  if (table != NULL)
Packit b099d7
    {
Packit b099d7
      *table = (XmStringTable)XtMalloc(count * sizeof(XmString));
Packit b099d7
      
Packit b099d7
      _XmStringContextReInit(&stack_context, string);
Packit b099d7
      _XmStringContextReInit(&stack_start, string);
Packit b099d7
      
Packit b099d7
      i = 0;
Packit b099d7
      
Packit b099d7
      while ((type = XmeStringGetComponent(&stack_context, TRUE, FALSE, 
Packit b099d7
					   &len, &val)) != 
Packit b099d7
	     XmSTRING_COMPONENT_END)
Packit b099d7
	{
Packit b099d7
	  if ((type == b_type) && (len == b_len) &&
Packit b099d7
	      (memcmp(val, b_val, len) == 0))
Packit b099d7
	    {
Packit b099d7
	      /* make XmString from start to end */
Packit b099d7
	      (*table)[i] = MakeStr(&stack_start, &stack_context);
Packit b099d7
	      i++;
Packit b099d7
	    }
Packit b099d7
	} 
Packit b099d7
Packit b099d7
      _XmStringContextFree(&stack_start);
Packit b099d7
    }
Packit b099d7
  _XmStringContextFree(&stack_context);
Packit b099d7
Packit b099d7
  _XmProcessUnlock();
Packit b099d7
  return(count);
Packit b099d7
}
Packit b099d7

Packit b099d7
Packit b099d7
Packit b099d7
XmTabList
Packit b099d7
XmStringTableProposeTablist(XmStringTable strings,
Packit b099d7
			    Cardinal num_strings,
Packit b099d7
			    Widget widget,
Packit b099d7
			    float pad_value,
Packit b099d7
			    XmOffsetModel offset_model)
Packit b099d7
{
Packit b099d7
  int			i, j;
Packit b099d7
  _XmStringContextRec	stack_ctx;
Packit b099d7
  XmTabList		tl;
Packit b099d7
  XmTab			tab, prev, start;
Packit b099d7
  float			width, val;
Packit b099d7
  unsigned char		units;
Packit b099d7
  Arg			args[1];
Packit b099d7
  int			n;
Packit b099d7
  _XmRenditionRec	scratch;
Packit b099d7
  XmRendition		rend;
Packit b099d7
  _XmRendition		tmp;
Packit b099d7
  XmRenderTable		rt;
Packit b099d7
  NextTabResult		ret_val;
Packit b099d7
  
Packit b099d7
  _XmProcessLock();
Packit b099d7
  if ((strings == NULL) || (num_strings == 0)) {
Packit b099d7
    _XmProcessUnlock();
Packit b099d7
    return ((XmTabList)NULL);
Packit b099d7
  }
Packit b099d7
  
Packit b099d7
  bzero((char*) &scratch, sizeof(_XmRenditionRec));
Packit b099d7
  tmp = &scratch;
Packit b099d7
  rend = &tm;;
Packit b099d7
  
Packit b099d7
  _XmRendDisplay(rend) = XtDisplayOfObject(widget);
Packit b099d7
Packit b099d7
  n = 0;
Packit b099d7
  XtSetArg(args[n], XmNrenderTable, &rt); n++;
Packit b099d7
  XtGetValues(widget, args, n);
Packit b099d7
Packit b099d7
  /* Work around weird bug with XtGetValues. */
Packit b099d7
  n = 0;
Packit b099d7
  XtSetArg(args[n], XmNunitType, &units); n++;
Packit b099d7
  XtGetValues(widget, args, n);
Packit b099d7
Packit b099d7
  if (rt == NULL) rt = XmeGetDefaultRenderTable(widget, XmTEXT_FONTLIST);
Packit b099d7
Packit b099d7
  tab = XmTabCreate(0.0, units, offset_model, XmALIGNMENT_BEGINNING, ".");
Packit b099d7
Packit b099d7
  tl = XmTabListInsertTabs(NULL, &tab, 1, 0);
Packit b099d7
  
Packit b099d7
  XmTabFree(tab);
Packit b099d7
  
Packit b099d7
  for (i = 0; i < num_strings; i++)
Packit b099d7
    {
Packit b099d7
      if (!strings[i])
Packit b099d7
	{
Packit b099d7
	  /* Clean up */
Packit b099d7
	  XmTabListFree(tl);
Packit b099d7
	  _XmProcessUnlock();
Packit b099d7
	  return((XmTabList)NULL);
Packit b099d7
	}
Packit b099d7
      _XmStringContextReInit(&stack_ctx, strings[i]);      
Packit b099d7
Packit b099d7
      tab = _XmTabLStart(tl);
Packit b099d7
      val = 0.0;
Packit b099d7
      
Packit b099d7
      /* Scan str for tabs, update tl if necessary. */
Packit b099d7
      j = 0;
Packit b099d7
      
Packit b099d7
      while ((ret_val = _XmStringGetNextTabWidth(&stack_ctx, widget, units, 
Packit b099d7
						 rt, &width, &rend)) != 
Packit b099d7
	     XmTAB_EOS)
Packit b099d7
	{
Packit b099d7
	  if (ret_val == XmTAB_NEWLINE) 
Packit b099d7
	    {
Packit b099d7
	      tab = _XmTabLStart(tl);
Packit b099d7
	      j = 0;
Packit b099d7
	      continue;
Packit b099d7
	    }
Packit b099d7
	  
Packit b099d7
	  val = width + pad_value;
Packit b099d7
	  
Packit b099d7
	  if (j >= _XmTabLCount(tl))
Packit b099d7
	    /* Need to add a tab */
Packit b099d7
	    {
Packit b099d7
	      tab = XmTabCreate(0.0, units, offset_model,
Packit b099d7
				XmALIGNMENT_BEGINNING, ".");
Packit b099d7
	      start = _XmTabLStart(tl);
Packit b099d7
	      prev = _XmTabPrev(start);
Packit b099d7
	      
Packit b099d7
	      _XmTabNext(prev) = tab;
Packit b099d7
	      _XmTabPrev(tab) = prev;
Packit b099d7
	      _XmTabNext(tab) = start;
Packit b099d7
	      _XmTabPrev(start) = tab;
Packit b099d7
	      _XmTabLCount(tl)++;
Packit b099d7
	    }
Packit b099d7
	  else if (j > 0)
Packit b099d7
	    {
Packit b099d7
	      tab = _XmTabNext(tab);
Packit b099d7
	    }
Packit b099d7
Packit b099d7
	  if (val > _XmTabValue(tab)) XmTabSetValue(tab, val);
Packit b099d7
	  else val = _XmTabValue(tab);
Packit b099d7
	  j++;
Packit b099d7
	}
Packit b099d7
      
Packit b099d7
      _XmStringContextFree(&stack_ctx);
Packit b099d7
    }
Packit b099d7
  
Packit b099d7
  if (offset_model == XmABSOLUTE)
Packit b099d7
    {
Packit b099d7
      start = _XmTabLStart(tl);
Packit b099d7
      val = _XmTabValue(start);
Packit b099d7
      
Packit b099d7
      for (tab = _XmTabNext(start); tab != start; tab = _XmTabNext(tab))
Packit b099d7
	{
Packit b099d7
	  val += _XmTabValue(tab);
Packit b099d7
	  XmTabSetValue(tab, val);
Packit b099d7
	}
Packit b099d7
    }
Packit b099d7
  
Packit b099d7
  _XmProcessUnlock();
Packit b099d7
  return(tl);
Packit b099d7
}
Packit b099d7
Packit b099d7
/*
Packit b099d7
 * Helper function for XmTabList.c
Packit b099d7
 * This routine performs successive reads on an XmStringContext
Packit b099d7
 * and returns the width (in units of XmNunitType of widget) of
Packit b099d7
 * the text segments between the previous and next tab or end of line.  
Packit b099d7
 * It uses the XmNrenderTable from widget to calculate the width.  It 
Packit b099d7
 * returns XmTAB_EOS if the end of the string has been reached, XmTAB_NEWLINE
Packit b099d7
 * if the end of line is reached and XmTAB_NEXT if a tab is encountered.
Packit b099d7
 */
Packit b099d7
NextTabResult
Packit b099d7
_XmStringGetNextTabWidth(XmStringContext ctx,
Packit b099d7
			 Widget widget,
Packit b099d7
			 unsigned char units,
Packit b099d7
			 XmRenderTable rt,
Packit b099d7
			 float *width,
Packit b099d7
			 XmRendition *rend)
Packit b099d7
{
Packit b099d7
  float 	divisor;
Packit b099d7
  int		toType;			  /*  passed to XmConvertUnits */
Packit b099d7
  Dimension	w_sum, w_cur;
Packit b099d7
  
Packit b099d7
  if (_XmStrContError(ctx))
Packit b099d7
    {
Packit b099d7
      *width = 0.0;
Packit b099d7
      return(XmTAB_EOS);
Packit b099d7
    }
Packit b099d7
  
Packit b099d7
  w_sum = 0;
Packit b099d7
  *width = 0.0;
Packit b099d7
Packit b099d7
  /* Big units need to be converted to small ones. */
Packit b099d7
  toType = _XmConvertFactor(units, &divisor);
Packit b099d7
      
Packit b099d7
  /* Calculate the width to the next tab. */
Packit b099d7
  if (_XmStrContOpt(ctx))
Packit b099d7
    {
Packit b099d7
      _XmStrContError(ctx) = True;
Packit b099d7
      return(XmTAB_EOS);
Packit b099d7
    } 
Packit b099d7
  else 
Packit b099d7
    {
Packit b099d7
      _XmString 		str = _XmStrContString(ctx);
Packit b099d7
      _XmStringEntry 		line;
Packit b099d7
      int			line_count;
Packit b099d7
      _XmStringEntry 		seg;
Packit b099d7
      int			seg_count;
Packit b099d7
      _XmStringArraySegRec	array_seg;
Packit b099d7
      
Packit b099d7
      line_count = _XmStrLineCountGet(str);
Packit b099d7
      
Packit b099d7
      /* Keep checking lines and segments until we run out or hit a tab. */
Packit b099d7
      if (_XmStrContCurrLine(ctx) < line_count) 
Packit b099d7
	{
Packit b099d7
	  if (_XmStrImplicitLine(str))
Packit b099d7
	    {
Packit b099d7
	      line = _XmStrEntry(str)[_XmStrContCurrLine(ctx)];
Packit b099d7
	    }
Packit b099d7
	  else
Packit b099d7
	    {
Packit b099d7
	      _XmEntryType(&array_seg) = XmSTRING_ENTRY_ARRAY;
Packit b099d7
	      _XmEntrySegmentCount(&array_seg) = _XmStrEntryCount(str);
Packit b099d7
	      _XmEntrySegment(&array_seg) = (_XmStringNREntry *)_XmStrEntry(str);
Packit b099d7
	      line = (_XmStringEntry)&array_seg;
Packit b099d7
	    }
Packit b099d7
      
Packit b099d7
	  if (_XmEntryMultiple(line)) 
Packit b099d7
	    seg_count = _XmEntrySegmentCount(line);
Packit b099d7
	  else 
Packit b099d7
	    seg_count = 1;
Packit b099d7
Packit b099d7
	  if (seg_count == 0) {
Packit b099d7
	    /* Empty line. */
Packit b099d7
	    _XmStrContCurrLine(ctx)++;
Packit b099d7
	    *width = 0.0;
Packit b099d7
	    return(XmTAB_NEWLINE);
Packit b099d7
	  }
Packit b099d7
Packit b099d7
	  while (_XmStrContCurrSeg(ctx) < seg_count)
Packit b099d7
	    {
Packit b099d7
	      if (_XmEntryMultiple(line)) 
Packit b099d7
		seg = (_XmStringEntry)_XmEntrySegment(line)[_XmStrContCurrSeg(ctx)];
Packit b099d7
	      else
Packit b099d7
		seg = line;
Packit b099d7
Packit b099d7
	      w_cur = 0;
Packit b099d7
	
Packit b099d7
	      if (_XmStrContTabCount(ctx) < _XmEntryTabsGet(seg)) {
Packit b099d7
		_XmStrContTabCount(ctx)++;
Packit b099d7
		*width = (XmConvertUnits(widget, XmHORIZONTAL,
Packit b099d7
					 XmPIXELS, w_sum, toType) / divisor);
Packit b099d7
		return(XmTAB_NEXT);
Packit b099d7
	      }
Packit b099d7
Packit b099d7
	      (void)_XmStringSegmentExtents(seg, rt, rend, NULL,
Packit b099d7
					    &w_cur, NULL, NULL, NULL);
Packit b099d7
	      w_sum += w_cur;
Packit b099d7
	
Packit b099d7
	      _XmStrContCurrSeg(ctx)++;
Packit b099d7
	      _XmStrContTabCount(ctx) = 0;
Packit b099d7
	    }
Packit b099d7
Packit b099d7
	  _XmStrContCurrLine(ctx)++;
Packit b099d7
	  _XmStrContCurrSeg(ctx) = 0;
Packit b099d7
	  _XmStrContTabCount(ctx) = 0;
Packit b099d7
	  
Packit b099d7
	  return(XmTAB_NEWLINE);
Packit b099d7
	}
Packit b099d7
Packit b099d7
      _XmStrContError(ctx) = True;
Packit b099d7
      return(XmTAB_EOS);
Packit b099d7
    }
Packit b099d7
}
Packit b099d7