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