2
* Motif Tools Library, Version 3.1
5
* Written by David Flanagan.
6
* Copyright (c) 1992-2001 by David Flanagan.
7
* All Rights Reserved. See the file COPYRIGHT for details.
8
* This is open source software. See the file LICENSE for details.
9
* There is no warranty for this software. See NO_WARRANTY for details.
12
* Revision 1.1.1.1 2001/07/18 11:06:03 root
15
* Revision 1.2 2001/06/12 16:25:28 andre
16
* *** empty log message ***
24
#include <Xmt/ConvertersP.h>
27
/* #if XmVersion >= 2000 */
29
* Gary Merrill figured out how XmString parsing works in Motif 2.0, and
30
* how rendition tables and tabs are handled, and wrote this code for
31
* Motif 2.0. David Flanagan tweaked the resulting code a bit.
33
* The following escape sequences are supported for strings in the
36
* @t tab (relative to a tab list)
38
* @b[tag] begin rendition
39
* @e[tag] end rendition
41
* Keep in mind that renditions override font specifications.
45
#if NeedFunctionPrototypes
46
static XmIncludeStatus XmtConvertStringEscape(XtPointer *text,
49
XmStringTag string_tag,
52
XmString *str_include,
55
static XmIncludeStatus XmtConvertStringEscape(text, text_end, type, string_tag,
56
entry, pattern_length,
57
str_include, call_data)
61
XmStringTag string_tag;
64
XmString *str_include;
68
char *s, *start, *text_ptr, indicator, *tag, tag_buf[3];
69
XmStringComponentType component_type;
71
/* printf("...> '%s'\n", (char *) *text); */
73
text_ptr = (char *) *text;
74
start = s = XtNewString(*text);
76
/* s[0] should be '@'. Bump pointer to following char */
79
if (*s == '@') { /* Sequence is '@@' */
80
*str_include = XmStringComponentCreate(XmSTRING_COMPONENT_TEXT, 1, s);
89
component_type = XmSTRING_COMPONENT_TAB;
93
* treat @f the same as an unterminated @b.
94
* Using XmSTRING_COMPONENT_TAG doesn't work quite right
95
* with Motif 2.0.0, so we do it this way, which seems
96
* to make as much sense, anyway.
99
component_type = XmSTRING_COMPONENT_RENDITION_BEGIN;
102
component_type = XmSTRING_COMPONENT_RENDITION_END;
105
component_type = XmSTRING_COMPONENT_UNKNOWN;
111
switch (component_type) {
113
case XmSTRING_COMPONENT_UNKNOWN:
114
if ( indicator == '{' )
115
XmtWarningMsg("XmtCreateXmString", "badlocale",
116
"'@{' locale indicator may occur only at beginning of string.");
118
XmtWarningMsg("XmtCreateXmString", "unrecognized",
119
"Unrecognized string escape sequence '@%c' will be treated as text.",
123
*str_include = XmStringComponentCreate(XmSTRING_COMPONENT_TEXT,
131
case XmSTRING_COMPONENT_TAB:
132
*str_include = XmStringComponentCreate(component_type, 0, NULL);
134
text_ptr += s - start;
140
default: /* just drop through */
144
s++; /* go past the component_type character */
147
XmtWarningMsg("XmtCreateXmString", "syntax1",
148
"Improper '@%c' syntax in string being converted.",
155
* Now get the tag in '[ ]', after '(', or immediately
156
* after the component_type indicator.
161
while (*s && (*s != ']')) s++;
163
XmtWarningMsg("XmtCreateXmString", "syntax3",
164
"'@%c[%s' is missing ']' in string being converted",
168
*s = '\0'; /* null terminate the tag string */
173
if (!*(s+1) || !*(s+2)) {
174
XmtWarningMsg("XmtCreateXmString", "syntax2",
175
"Improper '@%c(' syntax in string being converted.",
195
*str_include = XmStringComponentCreate(component_type, strlen(tag), tag);
196
text_ptr += s - start;
204
#if NeedFunctionPrototypes
205
XmString XmtCreateXmString(StringConst str)
207
XmString XmtCreateXmString(str)
211
static Boolean parse_table_registered = False;
212
static XmParseMapping parse_table[3];
214
if (!parse_table_registered) {
219
XtSetArg(args[n], XmNpattern, "\n"); n++;
220
XtSetArg(args[n], XmNpatternType, XmMULTIBYTE_TEXT); n++;
221
XtSetArg(args[n], XmNincludeStatus, XmINSERT); n++;
222
XtSetArg(args[n], XmNsubstitute,XmStringSeparatorCreate());n++;
223
parse_table[0] = XmParseMappingCreate(args, n);
226
XtSetArg(args[n], XmNpattern, "\t"); n++;
227
XtSetArg(args[n], XmNpatternType, XmMULTIBYTE_TEXT); n++;
228
XtSetArg(args[n], XmNincludeStatus, XmINSERT); n++;
229
XtSetArg(args[n], XmNsubstitute,
230
XmStringComponentCreate(XmSTRING_COMPONENT_TAB, 0,NULL)); n++;
231
parse_table[1] = XmParseMappingCreate(args, n);
234
XtSetArg(args[n], XmNpattern, "@"); n++;
235
XtSetArg(args[n], XmNpatternType, XmMULTIBYTE_TEXT); n++;
236
XtSetArg(args[n], XmNincludeStatus, XmINVOKE); n++;
237
XtSetArg(args[n], XmNinvokeParseProc, XmtConvertStringEscape); n++;
238
parse_table[2] = XmParseMappingCreate(args, n);
240
parse_table_registered = True;
243
return XmStringParseText((XtPointer) str, NULL, NULL, XmMULTIBYTE_TEXT,
244
parse_table, XtNumber(parse_table),
248
#else /* XmVersion < 2000 */
250
#if NeedFunctionPrototypes
251
static XmString appendstring(String txt, XmString to, int sep, char *charset,
254
static XmString appendstring(txt, to, sep, charset, fixup)
271
n = mbstowcs(NULL, txt, 0);
273
ws = (wchar_t*)malloc(sizeof(wchar_t)*(n+1));
276
mbstowcs(ws, txt, (n+1));
278
for(s=t=ws; *s; s++, t++) {
280
if ((*s == L'@') && (*(s+1) == L'@')) s++;
282
*t = *s; /* copy the terminating '\0' */
283
n = wcstombs(NULL, ws, 0);
285
mtxt = (char*)malloc(sizeof(char)*(n+1));
288
wcstombs(mtxt, ws, (n+1));
296
s1 = XmStringSegmentCreate(mtxt, charset, XmSTRING_DIRECTION_L_TO_R, sep);
298
s2 = XmStringConcat(to, s1);
309
for(s=t=txt; *s; s++, t++) {
311
if ((*s == '@') && (*(s+1) == '@')) s++;
313
*t = *s; /* copy the terminating '\0' */
316
s1 = XmStringSegmentCreate(txt, charset, XmSTRING_DIRECTION_L_TO_R, sep);
318
s2 = XmStringConcat(to, s1);
325
#if NeedFunctionPrototypes
326
XmString XmtCreateXmString(StringConst str)
328
XmString XmtCreateXmString(str)
334
#ifdef XMSTRING_TO_COMPOUND_TEXT_BUG
335
String charset = XmSTRING_DEFAULT_CHARSET;
337
# if XmVersion < 1002
338
String charset = XmSTRING_DEFAULT_CHARSET;
340
String charset = XmFONTLIST_DEFAULT_TAG;
344
XmString result = NULL;
345
Boolean fixup = False;
347
if (!str) return NULL;
349
return XmStringSegmentCreate((String)str, charset,
350
XmSTRING_DIRECTION_L_TO_R, False);
352
* make a copy of the string so we can frob with it
353
* We keep pointer r so we can free it when done
355
r = s = XtNewString(str);
358
for(t = s; *s; s++) {
361
*s = '\0'; /* null terminate the string */
362
result = appendstring(t, result, True, charset, fixup);
367
if ((*s == '@') && (*(s+1) == '@')) {
368
/* set a flag to strip doubled escapes later */
373
else if (*(s+1) != 'f') break;
374
/* its a font change, so add the string up to here, if any */
375
*s = '\0'; /* null terminate the string */
377
result = appendstring(t, result, False, charset, fixup);
380
/* and now get the new charset */
381
if (*(s+2) == '\0') break;
383
if (*s == '[') { /* read till close ']' */
385
while (*s && (*s != ']')) s++;
386
if (*s == '\0') break;
387
*s = '\0'; /* null-terminate the charset string */
389
else if (*s == '(') { /* charset is next 2 chars */
390
if (*(s+1)) s++; else break;
392
if (*(s+1)) s++; else break;
394
charset_buf[2] = '\0';
395
charset = charset_buf;
397
else if (*s) { /* charset is single current character */
399
charset_buf[1] = '\0';
400
charset = charset_buf;
407
if (s != t) result = appendstring(t, result, False, charset, fixup);
415
#ifdef XMSTRING_TO_COMPOUND_TEXT_BUG
416
String charset = XmSTRING_DEFAULT_CHARSET;
418
# if XmVersion < 1002
419
String charset = XmSTRING_DEFAULT_CHARSET;
421
String charset = XmFONTLIST_DEFAULT_TAG;
425
XmString result = NULL;
426
Boolean fixup = False;
428
if (!str) return NULL;
430
return XmStringSegmentCreate((String)str, charset,
431
XmSTRING_DIRECTION_L_TO_R, False);
433
* make a copy of the string so we can frob with it
434
* We keep pointer r so we can free it when done
436
r = s = XtNewString(str);
439
for(t = s; *s; s++) {
442
*s = '\0'; /* null terminate the string */
443
result = appendstring(t, result, True, charset, fixup);
448
if ((*s == '@') && (*(s+1) == '@')) {
449
/* set a flag to strip doubled escapes later */
454
else if (*(s+1) != 'f') break;
455
/* its a font change, so add the string up to here, if any */
456
*s = '\0'; /* null terminate the string */
458
result = appendstring(t, result, False, charset, fixup);
461
/* and now get the new charset */
462
if (*(s+2) == '\0') break;
464
if (*s == '[') { /* read till close ']' */
466
while (*s && (*s != ']')) s++;
467
if (*s == '\0') break;
468
*s = '\0'; /* null-terminate the charset string */
470
else if (*s == '(') { /* charset is next 2 chars */
471
if (*(s+1)) s++; else break;
473
if (*(s+1)) s++; else break;
475
charset_buf[2] = '\0';
476
charset = charset_buf;
478
else if (*s) { /* charset is single current character */
480
charset_buf[1] = '\0';
481
charset = charset_buf;
488
if (s != t) result = appendstring(t, result, False, charset, fixup);
494
/* return XmStringCreateLocalized(str); */
497
#endif /* XmVersion >= 2000 */
500
#if NeedFunctionPrototypes
501
static XmString XmtCreateLocalizedXmString_(Screen *screen, StringConst str)
503
static XmString XmtCreateLocalizedXmString_(screen, str)
508
XmString value = NULL;
509
String category, tag, defaultstr;
510
String free_me = NULL;
512
#if NeedFunctionPrototypes
513
extern String _XmtLocalize(Screen *, StringConst,StringConst,StringConst);
515
extern String _XmtLocalize();
521
/* printf("==> '%s'\n", str); */
522
/* if this string has a tag, localize it first */
523
if ((str[0] == '@') && (str[1] == '{')) {
524
s = XtNewString(str);
527
/* printf("=-> '%s'\n", s); */
532
if (*s == '.' && !category) {
534
category = defaultstr;
537
if (*s == '.' && !tag) {
548
/* printf("-=> '%s'\n", free_me+2); */
552
if (!tag[0]) goto error;
553
if (category && !category[0]) goto error;
554
s = _XmtLocalize(screen, defaultstr, category, tag);
560
/* printf("--> '%s'\n", s); */
562
value = XmtCreateXmString(s);
564
if (!value) goto error;
565
if (free_me) XtFree(free_me);
570
if (free_me) XtFree(free_me);
575
#if NeedFunctionPrototypes
576
static void FreeConvertedXmString(XtAppContext app, XrmValue *to,
578
XrmValue *args, Cardinal *num_args)
580
static void FreeConvertedXmString(app, to, closure, args, num_args)
588
XmStringFree(*((XmString *) to->addr));
595
#if NeedFunctionPrototypes
596
Boolean XmtConvertStringToXmString(Display *dpy,
597
XrmValue *args, Cardinal *num_args,
598
XrmValue *from, XrmValue *to,
599
XtPointer *converter_data)
601
Boolean XmtConvertStringToXmString(dpy, args, num_args,
602
from, to, converter_data)
608
XtPointer *converter_data;
611
String s = (String) from->addr;
612
Screen *screen = *(Screen **)args[0].addr;
615
value = XmtCreateLocalizedXmString_(screen, s);
616
if (!value) goto error;
617
done(XmString, value);
620
XtDisplayStringConversionWarning(dpy, (String)from->addr, XmRXmString);
625
#if NeedFunctionPrototypes
626
XmString XmtCreateLocalizedXmString(Widget w, StringConst s)
628
XmString XmtCreateLocalizedXmString(w, s)
633
return XmtCreateLocalizedXmString_(XtScreen(w), s);
636
#if NeedFunctionPrototypes
637
void XmtRegisterXmStringConverter(void)
639
void XmtRegisterXmStringConverter()
642
static Boolean registered = False;
645
XtSetTypeConverter(XtRString, XmRXmString,
646
XmtConvertStringToXmString,
647
(XtConvertArgRec *)screenConvertArg, (Cardinal) 1,
648
XtCacheAll | XtCacheRefCount,
649
FreeConvertedXmString);