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