|
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 |
}
|