1 /**********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12 ***********************************************************************/
13
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
17
18 #include <stdlib.h>
19 #include <string.h>
20
21 #include <X11/Intrinsic.h>
22 #include <X11/IntrinsicP.h>
23 #include <X11/StringDefs.h>
24 #include <X11/Shell.h>
25 #include <X11/Xaw/Form.h>
26
27 #include "astring.h"
28 #include "fcintl.h"
29 #include "mem.h"
30
31 #include "gui_main.h"
32
33 #include "gui_stuff.h"
34
35 void put_line_8(char *psrc, char *pdst, int dst_w, int xoffset_table[]);
36 void put_line_16(char *psrc, char *pdst, int dst_w, int xoffset_table[]);
37 void put_line_24(char *psrc, char *pdst, int dst_w, int xoffset_table[]);
38 void put_line_32(char *psrc, char *pdst, int dst_w, int xoffset_table[]);
39
40 /**************************************************************************
41 ...
42 **************************************************************************/
xaw_set_relative_position(Widget ref,Widget w,int px,int py)43 void xaw_set_relative_position(Widget ref, Widget w, int px, int py)
44 {
45 Position x, y;
46 Dimension width, height;
47
48 XtVaGetValues(ref, XtNwidth, &width, XtNheight, &height, NULL);
49 XtTranslateCoords(ref, (Position) px*width/100, (Position) py*height/100, &x, &y);
50 XtVaSetValues(w, XtNx, x, XtNy, y, NULL);
51 }
52
53
54 /**************************************************************************
55 ...
56 **************************************************************************/
xaw_horiz_center(Widget w)57 void xaw_horiz_center(Widget w)
58 {
59 Dimension width, width2;
60
61 XtVaGetValues(XtParent(w), XtNwidth, &width, NULL);
62 XtVaGetValues(w, XtNwidth, &width2, NULL);
63 XtVaSetValues(w, XtNhorizDistance, (width-width2)/2, NULL);
64 }
65
66 /**************************************************************************
67 ...
68 **************************************************************************/
xaw_set_bitmap(Widget w,Pixmap pm)69 void xaw_set_bitmap(Widget w, Pixmap pm)
70 {
71 XtVaSetValues(w, XtNbitmap, (XtArgVal)pm, NULL);
72 xaw_expose_now(w);
73 }
74
75
76 /**************************************************************************
77 ...
78 **************************************************************************/
xaw_set_label(Widget w,const char * text)79 void xaw_set_label(Widget w, const char *text)
80 {
81 String str;
82
83 XtVaGetValues(w, XtNlabel, &str, NULL);
84 if (strcmp(str, text) != 0) {
85 XtVaSetValues(w, XtNlabel, (XtArgVal)text, NULL);
86 xaw_expose_now(w);
87 }
88
89 }
90
91 /**************************************************************************
92 ...
93 **************************************************************************/
xaw_expose_now(Widget w)94 void xaw_expose_now(Widget w)
95 {
96 Dimension width, height;
97 XExposeEvent xeev;
98
99 xeev.type = Expose;
100 xeev.display = XtDisplay (w);
101 xeev.window = XtWindow(w);
102 xeev.x = 0;
103 xeev.y = 0;
104 XtVaGetValues(w, XtNwidth, &width, XtNheight, &height, NULL);
105 (XtClass(w))->core_class.expose(w, (XEvent *)&xeev, NULL);
106 }
107
108 /**************************************************************************
109 ...
110 **************************************************************************/
x_simulate_button_click(Widget w)111 void x_simulate_button_click(Widget w)
112 {
113 XButtonEvent ev;
114
115 ev.display = XtDisplay(w);
116 ev.window = XtWindow(w);
117 ev.type=ButtonPress;
118 ev.button=Button1;
119 ev.x=10;
120 ev.y=10;
121
122 XtDispatchEvent((XEvent *)&ev);
123 ev.type=ButtonRelease;
124 XtDispatchEvent((XEvent *)&ev);
125 }
126
127 /**************************************************************************
128 ...
129 **************************************************************************/
x_scale_pixmap(Pixmap src,int src_w,int src_h,int dst_w,int dst_h,Window root)130 Pixmap x_scale_pixmap(Pixmap src, int src_w, int src_h, int dst_w, int dst_h,
131 Window root)
132 {
133 Pixmap dst;
134 XImage *xi_src, *xi_dst;
135 int xoffset_table[4096];
136 int x, xoffset, xadd, xremsum, xremadd;
137 int y, yoffset, yadd, yremsum, yremadd;
138 char *pdst_data;
139 char *psrc_data;
140
141 xi_src=XGetImage(display, src, 0, 0, src_w, src_h, AllPlanes, ZPixmap);
142 xi_dst=XCreateImage(display, DefaultVisual(display, screen_number),
143 xi_src->depth, ZPixmap,
144 0, NULL,
145 dst_w, dst_h,
146 xi_src->bitmap_pad, 0);
147
148 xi_dst->data=fc_calloc(xi_dst->bytes_per_line * xi_dst->height, 1);
149
150 /* for each pixel in dst, calculate pixel offset in src */
151 xadd=src_w/dst_w;
152 xremadd=src_w%dst_w;
153 xoffset=0;
154 xremsum=dst_w/2;
155
156 for (x = 0; x < dst_w; x++) {
157 xoffset_table[x]=xoffset;
158 xoffset+=xadd;
159 xremsum+=xremadd;
160 if(xremsum>=dst_w) {
161 xremsum-=dst_w;
162 xoffset++;
163 }
164 }
165
166 yadd=src_h/dst_h;
167 yremadd=src_h%dst_h;
168 yoffset=0;
169 yremsum=dst_h/2;
170
171 for (y = 0; y < dst_h; y++) {
172 psrc_data=xi_src->data + (yoffset * xi_src->bytes_per_line);
173 pdst_data=xi_dst->data + (y * xi_dst->bytes_per_line);
174
175 switch(xi_src->bits_per_pixel) {
176 case 8:
177 put_line_8(psrc_data, pdst_data, dst_w, xoffset_table);
178 break;
179 case 16:
180 put_line_16(psrc_data, pdst_data, dst_w, xoffset_table);
181 break;
182 case 24:
183 put_line_24(psrc_data, pdst_data, dst_w, xoffset_table);
184 break;
185 case 32:
186 put_line_32(psrc_data, pdst_data, dst_w, xoffset_table);
187 break;
188 default:
189 memcpy(pdst_data, psrc_data, (src_w<dst_w) ? src_w : dst_w);
190 break;
191 }
192
193 yoffset+=yadd;
194 yremsum+=yremadd;
195 if(yremsum>=dst_h) {
196 yremsum-=dst_h;
197 yoffset++;
198 }
199 }
200
201 dst=XCreatePixmap(display, root, dst_w, dst_h, display_depth);
202 XPutImage(display, dst, civ_gc, xi_dst, 0, 0, 0, 0, dst_w, dst_h);
203
204 xi_src->f.destroy_image(xi_src);
205 xi_dst->f.destroy_image(xi_dst);
206
207 return dst;
208 }
209
put_line_8(char * psrc,char * pdst,int dst_w,int xoffset_table[])210 void put_line_8(char *psrc, char *pdst, int dst_w, int xoffset_table[])
211 {
212 int x;
213 for (x = 0; x < dst_w; x++)
214 *pdst++=*(psrc+xoffset_table[x]+0);
215 }
216
put_line_16(char * psrc,char * pdst,int dst_w,int xoffset_table[])217 void put_line_16(char *psrc, char *pdst, int dst_w, int xoffset_table[])
218 {
219 int x;
220 for (x = 0; x < dst_w; x++) {
221 *pdst++=*(psrc+2*xoffset_table[x]+0);
222 *pdst++=*(psrc+2*xoffset_table[x]+1);
223 }
224 }
225
put_line_24(char * psrc,char * pdst,int dst_w,int xoffset_table[])226 void put_line_24(char *psrc, char *pdst, int dst_w, int xoffset_table[])
227 {
228 int x;
229 for (x = 0; x < dst_w; x++) {
230 *pdst++=*(psrc+3*xoffset_table[x]+0);
231 *pdst++=*(psrc+3*xoffset_table[x]+1);
232 *pdst++=*(psrc+3*xoffset_table[x]+2);
233 }
234 }
235
put_line_32(char * psrc,char * pdst,int dst_w,int xoffset_table[])236 void put_line_32(char *psrc, char *pdst, int dst_w, int xoffset_table[])
237 {
238 int x;
239 for (x = 0; x < dst_w; x++) {
240 *pdst++=*(psrc+4*xoffset_table[x]+0);
241 *pdst++=*(psrc+4*xoffset_table[x]+1);
242 *pdst++=*(psrc+4*xoffset_table[x]+2);
243 *pdst++=*(psrc+4*xoffset_table[x]+3);
244 }
245 }
246
247
248 /**************************************************************************
249 Returns 1 if string has gettext markings _inside_ string
250 (marking must be strictly at ends of string).
251 **************************************************************************/
has_intl_marking(const char * str)252 static int has_intl_marking(const char *str)
253 {
254 int len;
255
256 if (!(str[0] == '_' && str[1] == '(' && str[2] == '\"'))
257 return 0;
258
259 len = strlen(str);
260
261 return (len >= 5 && str[len-2] == '\"' && str[len-1] == ')');
262 }
263
264 /**************************************************************************
265 For a string which _has_ intl marking (caller should check beforehand)
266 returns gettext result of string inside marking.
267 Below buf is an internal buffer which is never free'd.
268 **************************************************************************/
convert_intl_marking(const char * str)269 static const char *convert_intl_marking(const char *str)
270 {
271 static struct astring buf = ASTRING_INIT;
272 int len = strlen(str);
273
274 fc_assert_ret_val(len >= 5, str);
275 astr_set(&buf, "%s", str + 3);
276 *((char *) &astr_str(&buf)[len - 5]) = '\0';
277
278 return Q_(astr_str(&buf));
279 }
280
281 /**************************************************************************
282 Check if the current widget label has i18n/gettext markings
283 _inside_ the string (for full string only). If so, then
284 strip off those markings, pass to gettext, and re-set label
285 to gettext-returned string. Note this is intended for resources
286 which are specified in data/Freeciv; if the label is set via
287 code, it should be gettext'd via code before/when set.
288 Note all this is necessary even if not using gettext, to
289 remove the gettext markings!
290 Returns the same widget (eg, to nest calls of this and following funcs).
291 **************************************************************************/
xaw_intl_label(Widget w)292 Widget xaw_intl_label(Widget w)
293 {
294 String str;
295 Boolean rszbl;
296
297 XtVaGetValues(w, XtNlabel, &str, XtNresizable, &rszbl, NULL);
298
299 if (has_intl_marking(str)) {
300 if (!rszbl)
301 XtVaSetValues(w, XtNresizable, (XtArgVal)True, NULL);
302 XtVaSetValues(w, XtNlabel, (XtArgVal)convert_intl_marking(str), NULL);
303 if (!rszbl)
304 XtVaSetValues(w, XtNresizable, (XtArgVal)False, NULL);
305 }
306
307 return w;
308 }
309
310 /**************************************************************************
311 As above, but also making sure to preserve the widget width.
312 Should probably use this version rather than above
313 when data/Freeciv specifies the width.
314 **************************************************************************/
xaw_intl_label_width(Widget w)315 Widget xaw_intl_label_width(Widget w)
316 {
317 String str;
318 Boolean rszbl;
319 Dimension width;
320
321 XtVaGetValues(w, XtNlabel, &str, XtNresizable, &rszbl,
322 XtNwidth, &width, NULL);
323
324 if (has_intl_marking(str)) {
325 if (!rszbl)
326 XtVaSetValues(w, XtNresizable, (XtArgVal)True, NULL);
327 XtVaSetValues(w, XtNlabel, (XtArgVal)convert_intl_marking(str),
328 XtNwidth, width, NULL);
329 if (!rszbl)
330 XtVaSetValues(w, XtNresizable, (XtArgVal)False, NULL);
331 }
332
333 return w;
334 }
335
336 /**************************************************************************
337 As above, for widget title.
338 **************************************************************************/
xaw_intl_title(Widget w)339 Widget xaw_intl_title(Widget w)
340 {
341 String str;
342
343 XtVaGetValues(w, XtNtitle, &str, NULL);
344
345 if (has_intl_marking(str))
346 XtVaSetValues(w, XtNtitle, (XtArgVal)convert_intl_marking(str), NULL);
347 return w;
348 }
349
350 /**************************************************************************
351 As above, for widget icon name.
352 **************************************************************************/
xaw_intl_icon_name(Widget w)353 Widget xaw_intl_icon_name(Widget w)
354 {
355 String str;
356
357 XtVaGetValues(w, XtNiconName, &str, NULL);
358
359 if (has_intl_marking(str))
360 XtVaSetValues(w, XtNiconName, (XtArgVal)convert_intl_marking(str), NULL);
361 return w;
362 }
363
364 /**************************************************************************
365 As above, for widget String contents.
366 **************************************************************************/
xaw_intl_string(Widget w)367 Widget xaw_intl_string(Widget w)
368 {
369 String str;
370 Boolean rszbl;
371
372 XtVaGetValues(w, XtNstring, &str, XtNresizable, &rszbl, NULL);
373
374 if (has_intl_marking(str)) {
375 if (!rszbl)
376 XtVaSetValues(w, XtNresizable, (XtArgVal)True, NULL);
377 XtVaSetValues(w, XtNstring, (XtArgVal)convert_intl_marking(str), NULL);
378 if (!rszbl)
379 XtVaSetValues(w, XtNresizable, (XtArgVal)False, NULL);
380 }
381
382 return w;
383 }
384
385 /**************************************************************************
386 As label_width above, for widget String contents.
387 **************************************************************************/
xaw_intl_string_width(Widget w)388 Widget xaw_intl_string_width(Widget w)
389 {
390 String str;
391 Boolean rszbl;
392 Dimension width;
393
394 XtVaGetValues(w, XtNstring, &str, XtNresizable, &rszbl,
395 XtNwidth, &width, NULL);
396
397 if (has_intl_marking(str)) {
398 if (!rszbl)
399 XtVaSetValues(w, XtNresizable, (XtArgVal)True, NULL);
400 XtVaSetValues(w, XtNstring, (XtArgVal)convert_intl_marking(str),
401 XtNwidth, width, NULL);
402 if (!rszbl)
403 XtVaSetValues(w, XtNresizable, (XtArgVal)False, NULL);
404 }
405
406 return w;
407 }
408