1 /*****************************************************************************/
2 /*
3 XmString Converter
4
5 Author: Krist Paquay
6 krist@tpg.tpg.oz.au
7
8 24/2/95
9
10 */
11 /*****************************************************************************/
12
13 #include "xhead.h"
14 #include "mxascii.h"
15 #include "converter.h"
16
17 /*****************************************************************************/
18
19 XmString
XitStringToXmString(string)20 XitStringToXmString (string)
21 String
22 string;
23 {
24 XmString the_xm_string, xm_sub_string, new_xm_string;
25 int len, i, j;
26 char *sub_string, *tag;
27 Boolean in_tag;
28
29 len = strlen(string);
30
31 sub_string = XtMalloc(len+1);
32 tag = XtMalloc(len+1);
33
34 tag[0] = sub_string[0] = '\0';
35
36 in_tag = False;
37
38 the_xm_string = NULL;
39
40 for (i=0, j=0; i<len; i++)
41 {
42 switch (string[i])
43 {
44 case '<':
45 if (in_tag)
46 tag[j++] = string[i];
47 else if (i>0 && string[i-1] == '\\')
48 sub_string[j-1] = string[i];
49 else if (j>0)
50 {
51 sub_string[j] = '\0';
52
53 xm_sub_string = XmStringCreateLtoR(sub_string,
54 (tag[0] == '\0' ? XmSTRING_DEFAULT_CHARSET : tag));
55 new_xm_string = XmStringConcat(the_xm_string, xm_sub_string);
56 XmStringFree(the_xm_string);
57 XmStringFree(xm_sub_string);
58 the_xm_string = new_xm_string;
59
60 j = 0;
61 in_tag = True;
62 }
63 else
64 in_tag = True;
65 break;
66
67 case '>':
68 if (in_tag)
69 {
70 tag[j] = '\0';
71 in_tag = False;
72 j = 0;
73 }
74 else
75 sub_string[j++] = string[i];
76 break;
77
78 default:
79 if (in_tag)
80 tag[j++] = string[i];
81 else
82 sub_string[j++] = string[i];
83 break;
84 }
85 }
86
87 if (in_tag)
88 {
89 fprintf(stderr, "XitStringToXmString(): Unclosed Tag, '>' missing !\n");
90 }
91 else
92 {
93 sub_string[j] = '\0';
94
95 xm_sub_string = XmStringCreateLtoR(sub_string,
96 (tag[0] == '\0' ? XmSTRING_DEFAULT_CHARSET :tag));
97 new_xm_string = XmStringConcat(the_xm_string, xm_sub_string);
98 XmStringFree(the_xm_string);
99 XmStringFree(xm_sub_string);
100 the_xm_string = new_xm_string;
101 }
102
103 XtFree(sub_string);
104 XtFree(tag);
105
106 return the_xm_string;
107 }
108
109 /*****************************************************************************/
110
111 #define done(type, value) \
112 { \
113 if (toVal->addr != NULL) { \
114 if (toVal->size < sizeof(type)) { \
115 toVal->size = sizeof(type); \
116 return False; \
117 } \
118 *(type*)(toVal->addr) = (value); \
119 } \
120 else { \
121 static type static_val; \
122 static_val = (value); \
123 toVal->addr = (XPointer)&static_val; \
124 } \
125 toVal->size = sizeof(type); \
126 return True; \
127 }
128
129 /*****************************************************************************/
130
131 static Boolean
XitCvtStringToXmString(display,args,num_args,fromVal,toVal,converter_data)132 XitCvtStringToXmString (display,args,num_args,fromVal,toVal,
133 converter_data)
134 Display
135 *display;
136 XrmValuePtr
137 args;
138 Cardinal
139 *num_args;
140 XrmValuePtr
141 fromVal;
142 XrmValuePtr
143 toVal;
144 XtPointer
145 *converter_data;
146
147 {
148 char *name = (char *)fromVal->addr;
149 XmString the_xm_string;
150
151 if (*num_args != 0)
152 {
153 XtErrorMsg("wrongParameters","XitCvtStringToXmString","XtToolkitError",
154 "String to XmString conversion needs no arguments",
155 (String *)NULL, (Cardinal *)NULL);
156
157 return False;
158 }
159
160 /*
161 If the input string doesn't start with '<' we just do what
162 the standard Motif converter does.
163 This is only for performance reasons.
164 The function XitStringToXmString() can handle
165 input not starting with '<'.
166 */
167
168 if (name && name[0] == '<')
169 {
170 the_xm_string = XitStringToXmString(name);
171 }
172 else
173 the_xm_string = XmStringCreateLtoR(name, XmSTRING_DEFAULT_CHARSET);
174
175 if (the_xm_string)
176 {
177 done(XmString, the_xm_string)
178 }
179 else
180 {
181 XtStringConversionWarning(name, "XmString");
182 return False;
183 }
184 }
185
186 /*****************************************************************************/
187
188 static void
XitCvtFreeXmString(app,toVal,converter_data,args,num_args)189 XitCvtFreeXmString (app,toVal,converter_data,args,num_args)
190 XtAppContext
191 app;
192 XrmValuePtr
193 toVal;
194 XtPointer
195 converter_data;
196 XrmValuePtr
197 args;
198 Cardinal
199 *num_args;
200 {
201 XmString the_xm_string;
202
203 the_xm_string = *((XmString *)toVal->addr);
204
205 XmStringFree(the_xm_string);
206 }
207
208 /*****************************************************************************/
209
210 void
XitAddXmStringConverter(app_context)211 XitAddXmStringConverter (app_context)
212 XtAppContext
213 app_context;
214 {
215 /* String to XmString */
216
217 /*
218 Register our Converter and Destructor
219 The caching style is "XtCacheAll | XtCacheRefCount".
220 Thus we cache everything until the relevant widget is destroyed
221 and there and no more references.
222 */
223
224 XtAppSetTypeConverter(app_context, XtRString, XmRXmString,
225 XitCvtStringToXmString, NULL, 0,
226 XtCacheAll | XtCacheRefCount, XitCvtFreeXmString);
227
228 /*
229 Not the same caching as the original Motif converter !
230 Motif uses (XtCacheNone | XtCacheRefCount)
231 but i think caching is better...
232 */
233 }
234