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 /***********************************************************************
15                           menu.c  -  description
16                              -------------------
17     begin                : Wed Sep 04 2002
18     copyright            : (C) 2002 by Rafał Bursig
19     email                : Rafał Bursig <bursig@poczta.fm>
20 ***********************************************************************/
21 
22 #ifdef HAVE_CONFIG_H
23 #include <fc_config.h>
24 #endif
25 
26 /* SDL2 */
27 #ifdef SDL2_PLAIN_INCLUDE
28 #include <SDL.h>
29 #else  /* SDL2_PLAIN_INCLUDE */
30 #include <SDL2/SDL.h>
31 #endif /* SDL2_PLAIN_INCLUDE */
32 
33 /* utility */
34 #include "fcintl.h"
35 #include "log.h"
36 
37 /* common */
38 #include "clientutils.h"
39 #include "game.h"
40 #include "road.h"
41 #include "traderoutes.h"
42 #include "unitlist.h"
43 
44 /* client */
45 #include "client_main.h" /* client_state */
46 #include "climisc.h"
47 #include "control.h"
48 
49 /* gui-sdl2 */
50 #include "dialogs.h"
51 #include "gotodlg.h"
52 #include "graphics.h"
53 #include "gui_iconv.h"
54 #include "gui_id.h"
55 #include "gui_main.h"
56 #include "gui_tilespec.h"
57 #include "mapctrl.h"
58 #include "mapview.h"
59 #include "pages.h"
60 #include "widget.h"
61 
62 #include "menu.h"
63 
64 extern struct widget *pOptions_Button;
65 
66 static struct widget *pBeginOrderWidgetList;
67 static struct widget *pEndOrderWidgetList;
68 
69 static struct widget *pOrder_Fallout_Button;
70 static struct widget *pOrder_Pollution_Button;
71 static struct widget *pOrder_Airbase_Button;
72 static struct widget *pOrder_Fortress_Button;
73 static struct widget *pOrder_Build_AddTo_City_Button;
74 static struct widget *pOrder_Mine_Button;
75 static struct widget *pOrder_Irrigation_Button;
76 static struct widget *pOrder_Road_Button;
77 static struct widget *pOrder_Transform_Button;
78 static struct widget *pOrder_Trade_Button;
79 
80 #define local_show(ID)                                                \
81   clear_wflag(get_widget_pointer_from_id(pBeginOrderWidgetList, ID, SCAN_FORWARD), \
82               WF_HIDDEN)
83 
84 #define local_hide(ID)                                             \
85   set_wflag(get_widget_pointer_from_id(pBeginOrderWidgetList, ID, SCAN_FORWARD), \
86             WF_HIDDEN )
87 
88 
89 /**************************************************************************
90   User interacted with some unit order widget.
91 **************************************************************************/
unit_order_callback(struct widget * pOrder_Widget)92 static int unit_order_callback(struct widget *pOrder_Widget)
93 {
94   if (PRESSED_EVENT(Main.event)) {
95     struct unit *pUnit = head_of_units_in_focus();
96 
97     set_wstate(pOrder_Widget, FC_WS_SELECTED);
98     selected_widget = pOrder_Widget;
99 
100     if (!pUnit) {
101       return -1;
102     }
103 
104     switch (pOrder_Widget->ID) {
105     case ID_UNIT_ORDER_BUILD_CITY:
106       /* Enable the button for adding to a city in all cases, so we
107          get an eventual error message from the server if we try. */
108       key_unit_build_city();
109       break;
110     case ID_UNIT_ORDER_BUILD_WONDER:
111       key_unit_build_wonder();
112       break;
113     case ID_UNIT_ORDER_ROAD:
114       key_unit_road();
115       break;
116     case ID_UNIT_ORDER_TRADE_ROUTE:
117       key_unit_trade_route();
118       break;
119     case ID_UNIT_ORDER_IRRIGATE:
120       key_unit_irrigate();
121       break;
122     case ID_UNIT_ORDER_MINE:
123       key_unit_mine();
124       break;
125     case ID_UNIT_ORDER_TRANSFORM:
126       key_unit_transform();
127       break;
128     case ID_UNIT_ORDER_FORTRESS:
129       key_unit_fortress();
130       break;
131     case ID_UNIT_ORDER_FORTIFY:
132       key_unit_fortify();
133       break;
134     case ID_UNIT_ORDER_AIRBASE:
135       key_unit_airbase();
136       break;
137     case ID_UNIT_ORDER_POLLUTION:
138       key_unit_pollution();
139       break;
140     case ID_UNIT_ORDER_PARADROP:
141       key_unit_paradrop();
142       break;
143     case ID_UNIT_ORDER_FALLOUT:
144       key_unit_fallout();
145       break;
146     case ID_UNIT_ORDER_SENTRY:
147       key_unit_sentry();
148       break;
149     case ID_UNIT_ORDER_PILLAGE:
150       key_unit_pillage();
151       break;
152     case ID_UNIT_ORDER_HOMECITY:
153       key_unit_homecity();
154       break;
155     case ID_UNIT_ORDER_UNLOAD_TRANSPORTER:
156       key_unit_unload_all();
157       break;
158     case ID_UNIT_ORDER_LOAD:
159       unit_list_iterate(get_units_in_focus(), punit) {
160         request_unit_load(punit, NULL, unit_tile(punit));
161       } unit_list_iterate_end;
162       break;
163     case ID_UNIT_ORDER_UNLOAD:
164       unit_list_iterate(get_units_in_focus(), punit) {
165         request_unit_unload(punit);
166       } unit_list_iterate_end;
167       break;
168     case ID_UNIT_ORDER_WAKEUP_OTHERS:
169       key_unit_wakeup_others();
170       break;
171     case ID_UNIT_ORDER_AUTO_SETTLER:
172       unit_list_iterate(get_units_in_focus(), punit) {
173         request_unit_autosettlers(punit);
174       } unit_list_iterate_end;
175       break;
176     case ID_UNIT_ORDER_AUTO_EXPLORE:
177       key_unit_auto_explore();
178       break;
179     case ID_UNIT_ORDER_CONNECT_IRRIGATE:
180       {
181         struct extra_type_list *extras = extra_type_list_by_cause(EC_IRRIGATION);
182 
183         if (extra_type_list_size(extras) > 0) {
184           struct extra_type *pextra;
185 
186           pextra = extra_type_list_get(extra_type_list_by_cause(EC_IRRIGATION), 0);
187 
188           key_unit_connect(ACTIVITY_IRRIGATE, pextra);
189         }
190       }
191       break;
192     case ID_UNIT_ORDER_CONNECT_ROAD:
193       {
194         struct road_type *proad = road_by_compat_special(ROCO_ROAD);
195 
196         if (proad != NULL) {
197           struct extra_type *tgt;
198 
199           tgt = road_extra_get(proad);
200 
201           key_unit_connect(ACTIVITY_GEN_ROAD, tgt);
202         }
203       }
204       break;
205     case ID_UNIT_ORDER_CONNECT_RAILROAD:
206       {
207         struct road_type *prail = road_by_compat_special(ROCO_RAILROAD);
208 
209         if (prail != NULL) {
210           struct extra_type *tgt;
211 
212           tgt = road_extra_get(prail);
213 
214           key_unit_connect(ACTIVITY_GEN_ROAD, tgt);
215         }
216       }
217       break;
218     case ID_UNIT_ORDER_PATROL:
219       key_unit_patrol();
220       break;
221     case ID_UNIT_ORDER_GOTO:
222       key_unit_goto();
223       break;
224     case ID_UNIT_ORDER_GOTO_CITY:
225       popup_goto_dialog();
226       break;
227     case ID_UNIT_ORDER_AIRLIFT:
228       popup_airlift_dialog();
229       break;
230     case ID_UNIT_ORDER_RETURN:
231       unit_list_iterate(get_units_in_focus(), punit) {
232         request_unit_return(punit);
233       } unit_list_iterate_end;
234       break;
235     case ID_UNIT_ORDER_UPGRADE:
236       popup_unit_upgrade_dlg(pUnit, FALSE);
237       break;
238     case ID_UNIT_ORDER_CONVERT:
239       key_unit_convert();
240       break;
241     case ID_UNIT_ORDER_DISBAND:
242       popup_unit_disband_dlg(pUnit, FALSE);
243       break;
244     case ID_UNIT_ORDER_DIPLOMAT_DLG:
245       key_unit_action_select_tgt();
246       break;
247     case ID_UNIT_ORDER_NUKE:
248       key_unit_nuke();
249       break;
250     case ID_UNIT_ORDER_WAIT:
251       key_unit_wait();
252       flush_dirty();
253       break;
254     case ID_UNIT_ORDER_DONE:
255       key_unit_done();
256       flush_dirty();
257       break;
258 
259     default:
260       break;
261     }
262   }
263 
264   return -1;
265 }
266 
267 /**************************************************************************
268    Refresh order widgets.
269 **************************************************************************/
redraw_order_widgets(void)270 static Uint16 redraw_order_widgets(void)
271 {
272   Uint16 count = 0;
273   struct widget *pTmpWidget = pBeginOrderWidgetList;
274 
275   while (TRUE) {
276     if (!(get_wflags(pTmpWidget) & WF_HIDDEN)) {
277       if (get_wflags(pTmpWidget) & WF_RESTORE_BACKGROUND) {
278         refresh_widget_background(pTmpWidget);
279       }
280       widget_redraw(pTmpWidget);
281       widget_mark_dirty(pTmpWidget);
282       count++;
283     }
284 
285     if (pTmpWidget == pEndOrderWidgetList) {
286       break;
287     }
288 
289     pTmpWidget = pTmpWidget->next;
290   }
291 
292   return count;
293 }
294 
295 /**************************************************************************
296    Reposition order widgets as they fit.
297 **************************************************************************/
set_new_order_widget_start_pos(void)298 static void set_new_order_widget_start_pos(void)
299 {
300   struct widget *pMiniMap = get_minimap_window_widget();
301   struct widget *pInfoWind = get_unit_info_window_widget();
302   struct widget *pTmpWidget = pBeginOrderWidgetList;
303   Sint16 sx, sy, xx, yy = 0;
304   int count = 0, lines = 1, w = 0, count_on_line;
305 
306   xx = pMiniMap->dst->dest_rect.x + pMiniMap->size.w + adj_size(10);
307   w = (pInfoWind->dst->dest_rect.x - adj_size(10)) - xx;
308 
309   if (w < (pTmpWidget->size.w + adj_size(10)) * 2) {
310     if (pMiniMap->size.h == pInfoWind->size.h) {
311       xx = 0;
312       w = main_window_width();
313       yy = pInfoWind->size.h;
314     } else {
315       if (pMiniMap->size.h > pInfoWind->size.h) {
316         w = main_window_width() - xx - adj_size(20);
317         if (w < (pTmpWidget->size.w + adj_size(10)) * 2) {
318 	  xx = 0;
319 	  w = pMiniMap->size.w;
320 	  yy = pMiniMap->size.h;
321         } else {
322           yy = pInfoWind->size.h;
323         }
324       } else {
325 	w = pInfoWind->dst->dest_rect.x - adj_size(20);
326         if (w < (pTmpWidget->size.w + adj_size(10)) * 2) {
327 	  xx = pInfoWind->dst->dest_rect.x;
328 	  w = pInfoWind->size.w;
329 	  yy = pInfoWind->size.h;
330         } else {
331 	  xx = adj_size(10);
332           yy = pMiniMap->size.h;
333         }
334       }
335     }
336   }
337 
338   count_on_line = w / (pTmpWidget->size.w + adj_size(5));
339 
340   /* find how many to reposition */
341   while (TRUE) {
342     if (!(get_wflags(pTmpWidget) & WF_HIDDEN)) {
343       count++;
344     }
345 
346     if (pTmpWidget == pEndOrderWidgetList) {
347       break;
348     }
349 
350     pTmpWidget = pTmpWidget->next;
351   }
352 
353   pTmpWidget = pBeginOrderWidgetList;
354 
355   if (count - count_on_line > 0) {
356     lines = (count + (count_on_line - 1)) / count_on_line;
357 
358     count = count_on_line - ((count_on_line * lines) - count);
359   }
360 
361   sx = xx + (w - count * (pTmpWidget->size.w + adj_size(5))) / 2;
362 
363   sy = pTmpWidget->dst->surface->h - yy - lines * (pTmpWidget->size.h + adj_size(5));
364 
365   while (TRUE) {
366     if (!(get_wflags(pTmpWidget) & WF_HIDDEN)) {
367       pTmpWidget->size.x = sx;
368       pTmpWidget->size.y = sy;
369 
370       count--;
371       sx += (pTmpWidget->size.w + adj_size(5));
372       if (!count) {
373 	count = count_on_line;
374 	lines--;
375 
376 	sx = xx + (w - count * (pTmpWidget->size.w + adj_size(5))) / 2;
377 
378 	sy = pTmpWidget->dst->surface->h - yy - lines * (pTmpWidget->size.h + adj_size(5));
379       }
380     }
381 
382     if (pTmpWidget == pEndOrderWidgetList) {
383       break;
384     }
385 
386     pTmpWidget = pTmpWidget->next;
387   }
388 }
389 
390 /* ================================ PUBLIC ================================ */
391 
392 /**************************************************************************
393    Create units order widgets.
394 **************************************************************************/
create_units_order_widgets(void)395 void create_units_order_widgets(void)
396 {
397   struct widget *pBuf = NULL;
398   char cBuf[128];
399   struct road_type *proad;
400   struct road_type *prail;
401 
402   /* No orders */
403   fc_snprintf(cBuf, sizeof(cBuf),"%s (%s)", _("No Orders"),
404               /* TRANS: "Space" refers to the space bar on a keyboard. */
405               _("Space"));
406   pBuf = create_themeicon(current_theme->ODone_Icon, Main.gui,
407                           WF_HIDDEN | WF_RESTORE_BACKGROUND
408                           | WF_WIDGET_HAS_INFO_LABEL);
409   set_wstate(pBuf, FC_WS_NORMAL);
410   pBuf->action = unit_order_callback;
411   pBuf->info_label = create_utf8_from_char(cBuf, adj_font(10));
412   pBuf->key = SDLK_SPACE;
413   add_to_gui_list(ID_UNIT_ORDER_DONE, pBuf);
414   /* --------- */
415 
416   pEndOrderWidgetList = pBuf;
417 
418   /* Wait */
419   fc_snprintf(cBuf, sizeof(cBuf),"%s (%s)", _("Wait"), "W");
420   pBuf = create_themeicon(current_theme->OWait_Icon, Main.gui,
421                           WF_HIDDEN | WF_RESTORE_BACKGROUND
422                           | WF_WIDGET_HAS_INFO_LABEL);
423   set_wstate(pBuf, FC_WS_NORMAL);
424   pBuf->action = unit_order_callback;
425   pBuf->info_label = create_utf8_from_char(cBuf, adj_font(10));
426   pBuf->key = SDLK_w;
427   add_to_gui_list(ID_UNIT_ORDER_WAIT, pBuf);
428   /* --------- */
429 
430   /* Explode Nuclear */
431   fc_snprintf(cBuf, sizeof(cBuf),"%s (%s)", _("Explode Nuclear"), "Shift+N");
432   pBuf = create_themeicon(current_theme->ONuke_Icon, Main.gui,
433                           WF_HIDDEN | WF_RESTORE_BACKGROUND
434                           | WF_WIDGET_HAS_INFO_LABEL);
435   set_wstate(pBuf, FC_WS_NORMAL);
436   pBuf->action = unit_order_callback;
437   pBuf->info_label = create_utf8_from_char(cBuf, adj_font(10));
438   pBuf->key = SDLK_n;
439   pBuf->mod = KMOD_SHIFT;
440   add_to_gui_list(ID_UNIT_ORDER_NUKE, pBuf);
441   /* --------- */
442 
443   /* Act against the specified tile. */
444   /* TRANS: Button to bring up the action selection dialog. */
445   fc_snprintf(cBuf, sizeof(cBuf),"%s (%s)", _("Do..."), "D");
446   pBuf = create_themeicon(current_theme->OSpy_Icon, Main.gui,
447                           WF_HIDDEN | WF_RESTORE_BACKGROUND
448                           | WF_WIDGET_HAS_INFO_LABEL);
449   set_wstate(pBuf, FC_WS_NORMAL);
450   pBuf->action = unit_order_callback;
451   pBuf->info_label = create_utf8_from_char(cBuf, adj_font(10));
452   pBuf->key = SDLK_d;
453   add_to_gui_list(ID_UNIT_ORDER_DIPLOMAT_DLG, pBuf);
454   /* --------- */
455 
456   /* Disband */
457   fc_snprintf(cBuf, sizeof(cBuf),"%s (%s)", _("Disband Unit"), "Shift+D");
458   pBuf = create_themeicon(current_theme->ODisband_Icon, Main.gui,
459                           WF_HIDDEN | WF_RESTORE_BACKGROUND
460                           | WF_WIDGET_HAS_INFO_LABEL);
461   set_wstate(pBuf, FC_WS_NORMAL);
462   pBuf->action = unit_order_callback;
463   pBuf->info_label = create_utf8_from_char(cBuf, adj_font(10));
464   pBuf->key = SDLK_d;
465   pBuf->mod = KMOD_SHIFT;
466   add_to_gui_list(ID_UNIT_ORDER_DISBAND, pBuf);
467   /* --------- */
468 
469   /* Upgrade */
470   fc_snprintf(cBuf, sizeof(cBuf),"%s (%s)", _("Upgrade Unit"), "Shift+U");
471   pBuf = create_themeicon(current_theme->Order_Icon, Main.gui,
472                           WF_HIDDEN | WF_RESTORE_BACKGROUND
473                           | WF_WIDGET_HAS_INFO_LABEL);
474   set_wstate(pBuf, FC_WS_NORMAL);
475   pBuf->action = unit_order_callback;
476   pBuf->info_label = create_utf8_from_char(cBuf, adj_font(10));
477   pBuf->key = SDLK_u;
478   pBuf->mod = KMOD_SHIFT;
479   add_to_gui_list(ID_UNIT_ORDER_UPGRADE, pBuf);
480   /* --------- */
481 
482   /* Convert */
483   fc_snprintf(cBuf, sizeof(cBuf),"%s (%s)", _("Convert Unit"), "Shift+O");
484   pBuf = create_themeicon(current_theme->Order_Icon, Main.gui,
485                           WF_HIDDEN | WF_RESTORE_BACKGROUND
486                           | WF_WIDGET_HAS_INFO_LABEL);
487   set_wstate(pBuf, FC_WS_NORMAL);
488   pBuf->action = unit_order_callback;
489   pBuf->info_label = create_utf8_from_char(cBuf, adj_font(10));
490   pBuf->key = SDLK_o;
491   pBuf->mod = KMOD_SHIFT;
492   add_to_gui_list(ID_UNIT_ORDER_CONVERT, pBuf);
493   /* --------- */
494 
495   /* Return to nearest city */
496   fc_snprintf(cBuf, sizeof(cBuf),"%s (%s)", _("Return to Nearest City"), "Shift+G");
497   pBuf = create_themeicon(current_theme->OReturn_Icon, Main.gui,
498                           WF_HIDDEN | WF_RESTORE_BACKGROUND
499                           | WF_WIDGET_HAS_INFO_LABEL);
500   set_wstate(pBuf, FC_WS_NORMAL);
501   pBuf->action = unit_order_callback;
502   pBuf->info_label = create_utf8_from_char(cBuf, adj_font(10));
503   pBuf->key = SDLK_g;
504   pBuf->mod = KMOD_SHIFT;
505   add_to_gui_list(ID_UNIT_ORDER_RETURN, pBuf);
506   /* --------- */
507 
508   /* Goto City */
509   fc_snprintf(cBuf, sizeof(cBuf),"%s (%s)", _("Go to City"), "T");
510   pBuf = create_themeicon(current_theme->OGotoCity_Icon, Main.gui,
511                           WF_HIDDEN | WF_RESTORE_BACKGROUND
512                           | WF_WIDGET_HAS_INFO_LABEL);
513   set_wstate(pBuf, FC_WS_NORMAL);
514   pBuf->action = unit_order_callback;
515   pBuf->info_label = create_utf8_from_char(cBuf, adj_font(10));
516   pBuf->key = SDLK_t;
517   add_to_gui_list(ID_UNIT_ORDER_GOTO_CITY, pBuf);
518   /* --------- */
519 
520   /* Airlift */
521   fc_snprintf(cBuf, sizeof(cBuf),"%s (%s)", _("Airlift to City"), "T");
522   pBuf = create_themeicon(current_theme->Order_Icon, Main.gui,
523                           WF_HIDDEN | WF_RESTORE_BACKGROUND
524                           | WF_WIDGET_HAS_INFO_LABEL);
525   set_wstate(pBuf, FC_WS_NORMAL);
526   pBuf->action = unit_order_callback;
527   pBuf->info_label = create_utf8_from_char(cBuf, adj_font(10));
528   pBuf->key = SDLK_t;
529   add_to_gui_list(ID_UNIT_ORDER_AIRLIFT, pBuf);
530   /* --------- */
531 
532   /* Goto location */
533   fc_snprintf(cBuf, sizeof(cBuf),"%s (%s)", _("Go to Tile"), "G");
534   pBuf = create_themeicon(current_theme->OGoto_Icon, Main.gui,
535                           WF_HIDDEN | WF_RESTORE_BACKGROUND
536                           | WF_WIDGET_HAS_INFO_LABEL);
537   set_wstate(pBuf, FC_WS_NORMAL);
538   pBuf->action = unit_order_callback;
539   pBuf->info_label = create_utf8_from_char(cBuf, adj_font(10));
540   pBuf->key = SDLK_g;
541   add_to_gui_list(ID_UNIT_ORDER_GOTO, pBuf);
542   /* --------- */
543 
544   /* Patrol */
545   fc_snprintf(cBuf, sizeof(cBuf),"%s (%s)", _("Patrol"), "Q");
546   pBuf = create_themeicon(current_theme->OPatrol_Icon, Main.gui,
547                           WF_HIDDEN | WF_RESTORE_BACKGROUND
548                           | WF_WIDGET_HAS_INFO_LABEL);
549   set_wstate(pBuf, FC_WS_NORMAL);
550   pBuf->action = unit_order_callback;
551   pBuf->info_label = create_utf8_from_char(cBuf, adj_font(10));
552   pBuf->key = SDLK_q;
553   add_to_gui_list(ID_UNIT_ORDER_PATROL, pBuf);
554   /* --------- */
555 
556   /* Connect irrigation */
557   fc_snprintf(cBuf, sizeof(cBuf),"%s (%s)", _("Connect With Irrigation"), "Shift+I");
558   pBuf = create_themeicon(current_theme->OAutoConnect_Icon, Main.gui,
559                           WF_HIDDEN | WF_RESTORE_BACKGROUND
560                           | WF_WIDGET_HAS_INFO_LABEL);
561   set_wstate(pBuf, FC_WS_NORMAL);
562   pBuf->action = unit_order_callback;
563   pBuf->info_label = create_utf8_from_char(cBuf, adj_font(10));
564   pBuf->key = SDLK_i;
565   pBuf->mod = KMOD_SHIFT;
566   add_to_gui_list(ID_UNIT_ORDER_CONNECT_IRRIGATE, pBuf);
567   /* --------- */
568 
569   /* Connect road */
570   proad = road_by_compat_special(ROCO_ROAD);
571 
572   if (proad != NULL) {
573     fc_snprintf(cBuf, sizeof(cBuf),
574                 _("Connect With %s (%s)"),
575                 extra_name_translation(road_extra_get(proad)),
576                 "Shift+R");
577     pBuf = create_themeicon(current_theme->OAutoConnect_Icon, Main.gui,
578                             WF_HIDDEN | WF_RESTORE_BACKGROUND
579                             | WF_WIDGET_HAS_INFO_LABEL);
580     set_wstate(pBuf, FC_WS_NORMAL);
581     pBuf->action = unit_order_callback;
582     pBuf->info_label = create_utf8_from_char(cBuf, adj_font(10));
583     pBuf->key = SDLK_r;
584     pBuf->mod = KMOD_SHIFT;
585     add_to_gui_list(ID_UNIT_ORDER_CONNECT_ROAD, pBuf);
586   }
587   /* --------- */
588 
589   /* Connect railroad */
590   prail = road_by_compat_special(ROCO_RAILROAD);
591   if (prail != NULL) {
592     fc_snprintf(cBuf, sizeof(cBuf),
593                 _("Connect With %s (%s)"),
594                 extra_name_translation(road_extra_get(prail)),
595                 "Shift+L");
596     pBuf = create_themeicon(current_theme->OAutoConnect_Icon, Main.gui,
597                             WF_HIDDEN | WF_RESTORE_BACKGROUND
598                             | WF_WIDGET_HAS_INFO_LABEL);
599     set_wstate(pBuf, FC_WS_NORMAL);
600     pBuf->action = unit_order_callback;
601     pBuf->info_label = create_utf8_from_char(cBuf, adj_font(10));
602     pBuf->key = SDLK_l;
603     pBuf->mod = KMOD_SHIFT;
604     add_to_gui_list(ID_UNIT_ORDER_CONNECT_RAILROAD, pBuf);
605   }
606   /* --------- */
607 
608   /* Auto-Explore */
609   fc_snprintf(cBuf, sizeof(cBuf),"%s (%s)", _("Auto Explore"), "X");
610   pBuf = create_themeicon(current_theme->OAutoExp_Icon, Main.gui,
611                           WF_HIDDEN | WF_RESTORE_BACKGROUND
612                           | WF_WIDGET_HAS_INFO_LABEL);
613   set_wstate(pBuf, FC_WS_NORMAL);
614   pBuf->action = unit_order_callback;
615   pBuf->info_label = create_utf8_from_char(cBuf, adj_font(10));
616   pBuf->key = SDLK_x;
617   add_to_gui_list(ID_UNIT_ORDER_AUTO_EXPLORE, pBuf);
618   /* --------- */
619 
620   /* Auto-Settler */
621   fc_snprintf(cBuf, sizeof(cBuf),"%s (%s)", _("Auto Settler"), "A");
622 
623   pBuf = create_themeicon(current_theme->OAutoSett_Icon, Main.gui,
624                           WF_HIDDEN | WF_RESTORE_BACKGROUND
625                           | WF_WIDGET_HAS_INFO_LABEL);
626   set_wstate(pBuf, FC_WS_NORMAL);
627   pBuf->action = unit_order_callback;
628   pBuf->info_label = create_utf8_from_char(cBuf, adj_font(10));
629   pBuf->key = SDLK_a;
630   add_to_gui_list(ID_UNIT_ORDER_AUTO_SETTLER, pBuf);
631   /* --------- */
632 
633   /* Wake Up Others */
634   fc_snprintf(cBuf, sizeof(cBuf),"%s (%s)", _("Unsentry All On Tile"), "Shift+S");
635   pBuf = create_themeicon(current_theme->OWakeUp_Icon, Main.gui,
636                           WF_HIDDEN | WF_RESTORE_BACKGROUND
637                           | WF_WIDGET_HAS_INFO_LABEL);
638   set_wstate(pBuf, FC_WS_NORMAL);
639   pBuf->action = unit_order_callback;
640   pBuf->info_label = create_utf8_from_char(cBuf, adj_font(10));
641   pBuf->key = SDLK_s;
642   pBuf->mod = KMOD_SHIFT;
643   add_to_gui_list(ID_UNIT_ORDER_WAKEUP_OTHERS, pBuf);
644   /* --------- */
645 
646   /* Unload */
647   fc_snprintf(cBuf, sizeof(cBuf),"%s (%s)", _("Unload All From Transporter"), "Shift+T");
648   pBuf = create_themeicon(current_theme->OUnload_Icon, Main.gui,
649                           WF_HIDDEN | WF_RESTORE_BACKGROUND
650                           | WF_WIDGET_HAS_INFO_LABEL);
651   set_wstate(pBuf, FC_WS_NORMAL);
652   pBuf->action = unit_order_callback;
653   pBuf->info_label = create_utf8_from_char(cBuf, adj_font(10));
654   pBuf->mod = KMOD_SHIFT;
655   pBuf->key = SDLK_t;
656   add_to_gui_list(ID_UNIT_ORDER_UNLOAD_TRANSPORTER, pBuf);
657   /* --------- */
658 
659   /* Load */
660   fc_snprintf(cBuf, sizeof(cBuf),"%s (%s)", _("Load Unit"), "L");
661   pBuf = create_themeicon(current_theme->OLoad_Icon, Main.gui,
662                           WF_HIDDEN | WF_RESTORE_BACKGROUND
663                           | WF_WIDGET_HAS_INFO_LABEL);
664   set_wstate(pBuf, FC_WS_NORMAL);
665   pBuf->action = unit_order_callback;
666   pBuf->info_label = create_utf8_from_char(cBuf, adj_font(10));
667   pBuf->key = SDLK_l;
668   add_to_gui_list(ID_UNIT_ORDER_LOAD, pBuf);
669   /* --------- */
670 
671   /* Unload */
672   fc_snprintf(cBuf, sizeof(cBuf),"%s (%s)", _("Unload Unit"), "U");
673   pBuf = create_themeicon(current_theme->OUnload_Icon, Main.gui,
674                           WF_HIDDEN | WF_RESTORE_BACKGROUND
675                           | WF_WIDGET_HAS_INFO_LABEL);
676   set_wstate(pBuf, FC_WS_NORMAL);
677   pBuf->action = unit_order_callback;
678   pBuf->info_label = create_utf8_from_char(cBuf, adj_font(10));
679   pBuf->key = SDLK_u;
680   add_to_gui_list(ID_UNIT_ORDER_UNLOAD, pBuf);
681   /* --------- */
682 
683   /* Find Homecity */
684   fc_snprintf(cBuf, sizeof(cBuf),"%s (%s)", _("Find Home City"), "H");
685   pBuf = create_themeicon(current_theme->OHomeCity_Icon, Main.gui,
686                           WF_HIDDEN | WF_RESTORE_BACKGROUND
687                           | WF_WIDGET_HAS_INFO_LABEL);
688   set_wstate(pBuf, FC_WS_NORMAL);
689   pBuf->action = unit_order_callback;
690   pBuf->info_label = create_utf8_from_char(cBuf, adj_font(10));
691   pBuf->key = SDLK_h;
692   add_to_gui_list(ID_UNIT_ORDER_HOMECITY, pBuf);
693   /* --------- */
694 
695   /* Pillage */
696   fc_snprintf(cBuf, sizeof(cBuf),"%s (%s)", _("Pillage"), "Shift+P");
697   pBuf = create_themeicon(current_theme->OPillage_Icon, Main.gui,
698                           WF_HIDDEN | WF_RESTORE_BACKGROUND
699                           | WF_WIDGET_HAS_INFO_LABEL);
700   set_wstate(pBuf, FC_WS_NORMAL);
701   pBuf->action = unit_order_callback;
702   pBuf->info_label = create_utf8_from_char(cBuf, adj_font(10));
703   pBuf->key = SDLK_p;
704   pBuf->mod = KMOD_SHIFT;
705   add_to_gui_list(ID_UNIT_ORDER_PILLAGE, pBuf);
706   /* --------- */
707 
708   /* Sentry */
709   fc_snprintf(cBuf, sizeof(cBuf),"%s (%s)", _("Sentry Unit"), "S");
710   pBuf = create_themeicon(current_theme->OSentry_Icon, Main.gui,
711                           WF_HIDDEN | WF_RESTORE_BACKGROUND
712                           | WF_WIDGET_HAS_INFO_LABEL);
713   set_wstate(pBuf, FC_WS_NORMAL);
714   pBuf->action = unit_order_callback;
715   pBuf->info_label = create_utf8_from_char(cBuf, adj_font(10));
716   pBuf->key = SDLK_s;
717   add_to_gui_list(ID_UNIT_ORDER_SENTRY, pBuf);
718   /* --------- */
719 
720   /* Clean Nuclear Fallout */
721   /* Label will be replaced by real_menus_update() before it's seen */
722   fc_snprintf(cBuf, sizeof(cBuf), "placeholder");
723   pBuf = create_themeicon(current_theme->OFallout_Icon, Main.gui,
724                           WF_HIDDEN | WF_RESTORE_BACKGROUND
725                           | WF_WIDGET_HAS_INFO_LABEL);
726   set_wstate(pBuf, FC_WS_NORMAL);
727   pBuf->action = unit_order_callback;
728   pBuf->info_label = create_utf8_from_char(cBuf, adj_font(10));
729   pBuf->key = SDLK_n;
730   pOrder_Fallout_Button = pBuf;
731   add_to_gui_list(ID_UNIT_ORDER_FALLOUT, pBuf);
732   /* --------- */
733 
734   /* Paradrop */
735   fc_snprintf(cBuf, sizeof(cBuf),"%s (%s)", _("Drop Paratrooper"), "P");
736   pBuf = create_themeicon(current_theme->OParaDrop_Icon, Main.gui,
737                           WF_HIDDEN | WF_RESTORE_BACKGROUND
738                           | WF_WIDGET_HAS_INFO_LABEL);
739   set_wstate(pBuf, FC_WS_NORMAL);
740   pBuf->action = unit_order_callback;
741   pBuf->info_label =  create_utf8_from_char(cBuf, adj_font(10));
742   pBuf->key = SDLK_p;
743   add_to_gui_list(ID_UNIT_ORDER_PARADROP, pBuf);
744   /* --------- */
745 
746   /* Clean Pollution */
747   /* Label will be replaced by real_menus_update() before it's seen */
748   fc_snprintf(cBuf, sizeof(cBuf), "placeholder");
749   pBuf = create_themeicon(current_theme->OPollution_Icon, Main.gui,
750                           WF_HIDDEN | WF_RESTORE_BACKGROUND
751                           | WF_WIDGET_HAS_INFO_LABEL);
752   set_wstate(pBuf, FC_WS_NORMAL);
753   pBuf->action = unit_order_callback;
754   pBuf->info_label = create_utf8_from_char(cBuf, adj_font(10));
755   pBuf->key = SDLK_p;
756   pOrder_Pollution_Button = pBuf;
757   add_to_gui_list(ID_UNIT_ORDER_POLLUTION, pBuf);
758   /* --------- */
759 
760   /* Build Airbase */
761   /* Label will be replaced by real_menus_update() before it's seen */
762   fc_snprintf(cBuf, sizeof(cBuf), "placeholder");
763   pBuf = create_themeicon(current_theme->OAirBase_Icon, Main.gui,
764                           WF_HIDDEN | WF_RESTORE_BACKGROUND
765                           | WF_WIDGET_HAS_INFO_LABEL);
766   set_wstate(pBuf, FC_WS_NORMAL);
767   pBuf->action = unit_order_callback;
768   pBuf->info_label = create_utf8_from_char(cBuf, adj_font(10));
769   pBuf->key = SDLK_e;
770   pBuf->mod = KMOD_SHIFT;
771   pOrder_Airbase_Button = pBuf;
772   add_to_gui_list(ID_UNIT_ORDER_AIRBASE, pBuf);
773   /* --------- */
774 
775   /* Fortify */
776   fc_snprintf(cBuf, sizeof(cBuf),"%s (%s)", _("Fortify Unit"), "F");
777   pBuf = create_themeicon(current_theme->OFortify_Icon, Main.gui,
778                           WF_HIDDEN | WF_RESTORE_BACKGROUND
779                           | WF_WIDGET_HAS_INFO_LABEL);
780   set_wstate(pBuf, FC_WS_NORMAL);
781   pBuf->action = unit_order_callback;
782   pBuf->info_label = create_utf8_from_char(cBuf, adj_font(10));
783   pBuf->key = SDLK_f;
784   add_to_gui_list(ID_UNIT_ORDER_FORTIFY, pBuf);
785   /* --------- */
786 
787   /* Build Fortress */
788   /* Label will be replaced by real_menus_update() before it's seen */
789   fc_snprintf(cBuf, sizeof(cBuf), "placeholder");
790   pBuf = create_themeicon(current_theme->OFortress_Icon, Main.gui,
791                           WF_HIDDEN | WF_RESTORE_BACKGROUND
792                           | WF_WIDGET_HAS_INFO_LABEL);
793   set_wstate(pBuf, FC_WS_NORMAL);
794   pBuf->action = unit_order_callback;
795   pBuf->info_label = create_utf8_from_char(cBuf, adj_font(10));
796   pBuf->key = SDLK_f;
797   pBuf->mod = KMOD_SHIFT;
798   pOrder_Fortress_Button = pBuf;
799   add_to_gui_list(ID_UNIT_ORDER_FORTRESS, pBuf);
800   /* --------- */
801 
802   /* Transform Tile */
803   /* Label will be replaced by real_menus_update() before it's seen */
804   fc_snprintf(cBuf, sizeof(cBuf), "placeholder");
805   pBuf = create_themeicon(current_theme->OTransform_Icon, Main.gui,
806                           WF_HIDDEN | WF_RESTORE_BACKGROUND
807                           | WF_WIDGET_HAS_INFO_LABEL);
808   set_wstate(pBuf, FC_WS_NORMAL);
809   pBuf->action = unit_order_callback;
810   pBuf->info_label = create_utf8_from_char(cBuf, adj_font(10));
811   pBuf->key = SDLK_o;
812   pOrder_Transform_Button = pBuf;
813   add_to_gui_list(ID_UNIT_ORDER_TRANSFORM, pBuf);
814   /* --------- */
815 
816   /* Build Mine */
817   /* Label will be replaced by real_menus_update() before it's seen */
818   fc_snprintf(cBuf, sizeof(cBuf), "placeholder");
819   pBuf = create_themeicon(current_theme->OMine_Icon, Main.gui,
820                           WF_HIDDEN | WF_RESTORE_BACKGROUND
821                           | WF_WIDGET_HAS_INFO_LABEL);
822   set_wstate(pBuf, FC_WS_NORMAL);
823   pBuf->action = unit_order_callback;
824   pBuf->info_label = create_utf8_from_char(cBuf, adj_font(10));
825   pBuf->key = SDLK_m;
826   add_to_gui_list(ID_UNIT_ORDER_MINE, pBuf);
827 
828   pOrder_Mine_Button = pBuf;
829   /* --------- */
830 
831   /* Build Irrigation */
832   /* Label will be replaced by real_menus_update() before it's seen */
833   fc_snprintf(cBuf, sizeof(cBuf), "placeholder");
834   pBuf = create_themeicon(current_theme->OIrrigation_Icon, Main.gui,
835                           WF_HIDDEN | WF_RESTORE_BACKGROUND
836                           | WF_WIDGET_HAS_INFO_LABEL);
837   set_wstate(pBuf, FC_WS_NORMAL);
838   pBuf->action = unit_order_callback;
839   pBuf->key = SDLK_i;
840   pBuf->info_label = create_utf8_from_char(cBuf, adj_font(10));
841   add_to_gui_list(ID_UNIT_ORDER_IRRIGATE, pBuf);
842 
843   pOrder_Irrigation_Button = pBuf;
844   /* --------- */
845 
846   /* Establish Trade route */
847   /* Label will be replaced by real_menus_update() before it's seen */
848   fc_snprintf(cBuf, sizeof(cBuf), "placeholder");
849   pBuf = create_themeicon(current_theme->OTrade_Icon, Main.gui,
850                           WF_HIDDEN | WF_RESTORE_BACKGROUND
851                           | WF_WIDGET_HAS_INFO_LABEL);
852   set_wstate(pBuf, FC_WS_NORMAL);
853   pBuf->action = unit_order_callback;
854   pBuf->info_label = create_utf8_from_char(cBuf, adj_font(10));
855   pBuf->key = SDLK_r;
856   add_to_gui_list(ID_UNIT_ORDER_TRADE_ROUTE, pBuf);
857 
858   pOrder_Trade_Button = pBuf;
859   /* --------- */
860 
861   /* Build (Rail-)Road */
862   /* Label will be replaced by real_menus_update() before it's seen */
863   fc_snprintf(cBuf, sizeof(cBuf), "placeholder");
864   pBuf = create_themeicon(current_theme->ORoad_Icon, Main.gui,
865                           WF_HIDDEN | WF_RESTORE_BACKGROUND
866                           | WF_WIDGET_HAS_INFO_LABEL);
867   set_wstate(pBuf, FC_WS_NORMAL);
868   pBuf->action = unit_order_callback;
869   pBuf->info_label = create_utf8_from_char(cBuf, adj_font(10));
870   pBuf->key = SDLK_r;
871   add_to_gui_list(ID_UNIT_ORDER_ROAD, pBuf);
872 
873   pOrder_Road_Button = pBuf;
874   /* --------- */
875 
876   /* Help Build Wonder */
877   fc_snprintf(cBuf, sizeof(cBuf),"%s (%s)",
878               action_id_name_translation(ACTION_HELP_WONDER), "B");
879   pBuf = create_themeicon(current_theme->OWonder_Icon, Main.gui,
880                           WF_HIDDEN | WF_RESTORE_BACKGROUND
881                           | WF_WIDGET_HAS_INFO_LABEL);
882   set_wstate(pBuf, FC_WS_NORMAL);
883   pBuf->action = unit_order_callback;
884   pBuf->info_label = create_utf8_from_char(cBuf, adj_font(10));
885   pBuf->key = SDLK_b;
886   add_to_gui_list(ID_UNIT_ORDER_BUILD_WONDER, pBuf);
887   /* --------- */
888 
889   /* Add to City / Build New City */
890   /* Label will be replaced by real_menus_update() before it's seen */
891   fc_snprintf(cBuf, sizeof(cBuf), "placeholder");
892   pBuf = create_themeicon(current_theme->OBuildCity_Icon, Main.gui,
893                           WF_HIDDEN | WF_RESTORE_BACKGROUND
894                           | WF_WIDGET_HAS_INFO_LABEL);
895   set_wstate(pBuf, FC_WS_NORMAL);
896   pBuf->action = unit_order_callback;
897   pBuf->info_label = create_utf8_from_char(cBuf, adj_font(10));
898   pBuf->key = SDLK_b;
899   add_to_gui_list(ID_UNIT_ORDER_BUILD_CITY, pBuf);
900 
901   pOrder_Build_AddTo_City_Button = pBuf;
902   /* --------- */
903 
904   pBeginOrderWidgetList = pBuf;
905 
906   SDL_Client_Flags |= CF_ORDERS_WIDGETS_CREATED;
907 }
908 
909 /**************************************************************************
910    Free resources allocated for unit order widgets.
911 **************************************************************************/
delete_units_order_widgets(void)912 void delete_units_order_widgets(void)
913 {
914   del_group(pBeginOrderWidgetList, pEndOrderWidgetList);
915 
916   pBeginOrderWidgetList = NULL;
917   pEndOrderWidgetList = NULL;
918   SDL_Client_Flags &= ~CF_ORDERS_WIDGETS_CREATED;
919 }
920 
921 /**************************************************************************
922    Draw order widgets to their currently correct place.
923 **************************************************************************/
update_order_widgets(void)924 void update_order_widgets(void)
925 {
926   set_new_order_widget_start_pos();
927   redraw_order_widgets();
928 }
929 
930 /**************************************************************************
931    Clear unit order widgets from view.
932 **************************************************************************/
undraw_order_widgets(void)933 void undraw_order_widgets(void)
934 {
935   struct widget *pTmpWidget = pBeginOrderWidgetList;
936 
937   if (pTmpWidget == NULL) {
938     return;
939   }
940 
941   while (TRUE) {
942     if (!(get_wflags(pTmpWidget) & WF_HIDDEN) && (pTmpWidget->gfx)) {
943       widget_undraw(pTmpWidget);
944       widget_mark_dirty(pTmpWidget);
945     }
946 
947     if (pTmpWidget == pEndOrderWidgetList) {
948       break;
949     }
950 
951     pTmpWidget = pTmpWidget->next;
952   }
953 }
954 
955 /* ============================== Native =============================== */
956 
957 /**************************************************************************
958   Initialize menus (sensitivity, name, etc.) based on the
959   current state and current ruleset, etc.  Call menus_update().
960 **************************************************************************/
real_menus_init(void)961 void real_menus_init(void)
962 {
963   /* PORTME */
964 }
965 
966 /**************************************************************************
967   Update all of the menus (sensitivity, etc.) based on the current state.
968 **************************************************************************/
real_menus_update(void)969 void real_menus_update(void)
970 {
971   static Uint16 counter = 0;
972   struct unit_list *punits = NULL;
973   struct unit *pUnit = NULL;
974   static char cBuf[128];
975 
976   if ((C_S_RUNNING != client_state())
977       || (get_client_page() != PAGE_GAME)) {
978 
979     SDL_Client_Flags |= CF_GAME_JUST_STARTED;
980 
981     if (SDL_Client_Flags & CF_MAP_UNIT_W_CREATED) {
982       set_wflag(pOptions_Button, WF_HIDDEN);
983       hide_minimap_window_buttons();
984       hide_unitinfo_window_buttons();
985     }
986 
987     if (SDL_Client_Flags & CF_ORDERS_WIDGETS_CREATED) {
988       hide_group(pBeginOrderWidgetList, pEndOrderWidgetList);
989     }
990 
991   } else {
992     /* Running state */
993     if (SDL_Client_Flags & CF_MAP_UNIT_W_CREATED) {
994       /* show options button */
995       clear_wflag(pOptions_Button, WF_HIDDEN);
996       widget_redraw(pOptions_Button);
997       widget_mark_dirty(pOptions_Button);
998     }
999 
1000     if (NULL == client.conn.playing) {
1001       /* Global observer */
1002       if (SDL_Client_Flags & CF_MAP_UNIT_W_CREATED) {
1003         /* show minimap buttons and unitinfo buttons */
1004         show_minimap_window_buttons();
1005         show_unitinfo_window_buttons();
1006         /* disable minimap buttons and unitinfo buttons */
1007         disable_minimap_window_buttons();
1008         disable_unitinfo_window_buttons();
1009       }
1010 
1011       return;
1012 
1013     } else {
1014       /* running state with player */
1015 
1016       if (get_wstate(pEndOrderWidgetList) == FC_WS_DISABLED) {
1017         enable_group(pBeginOrderWidgetList, pEndOrderWidgetList);
1018       }
1019 
1020       if (counter) {
1021         undraw_order_widgets();
1022       }
1023 
1024       if (SDL_Client_Flags & CF_GAME_JUST_STARTED) {
1025         SDL_Client_Flags &= ~CF_GAME_JUST_STARTED;
1026 
1027         /* show minimap buttons and unitinfo buttons */
1028         show_minimap_window_buttons();
1029         show_unitinfo_window_buttons();
1030 
1031         counter = 0;
1032       }
1033     }
1034 
1035     punits = get_units_in_focus();
1036     pUnit = unit_list_get(punits, 0);
1037 
1038     if (pUnit && !pUnit->ai_controlled) {
1039       struct city *pHomecity;
1040       int time;
1041       struct tile *pTile = unit_tile(pUnit);
1042       struct city *pCity = tile_city(pTile);
1043       struct terrain *pTerrain = tile_terrain(pTile);
1044       struct base_type *pbase;
1045       struct extra_type *pextra;
1046 
1047       if (!counter) {
1048 	local_show(ID_UNIT_ORDER_GOTO);
1049 	local_show(ID_UNIT_ORDER_DISBAND);
1050 
1051 	local_show(ID_UNIT_ORDER_WAIT);
1052 	local_show(ID_UNIT_ORDER_DONE);
1053       }
1054 
1055       /* Enable the button for adding to a city in all cases, so we
1056        * get an eventual error message from the server if we try. */
1057 
1058       if (unit_can_add_or_build_city(pUnit)) {
1059 	if (pCity) {
1060 	  fc_snprintf(cBuf, sizeof(cBuf),"%s (%s)", _("Add to City"), "B");
1061 	} else {
1062 	  fc_snprintf(cBuf, sizeof(cBuf),"%s (%s)", _("Build City"), "B");
1063 	}
1064         copy_chars_to_utf8_str(pOrder_Build_AddTo_City_Button->info_label,
1065                                cBuf);
1066 	clear_wflag(pOrder_Build_AddTo_City_Button, WF_HIDDEN);
1067       } else {
1068 	set_wflag(pOrder_Build_AddTo_City_Button, WF_HIDDEN);
1069       }
1070 
1071       if (unit_can_help_build_wonder_here(pUnit)) {
1072 	local_show(ID_UNIT_ORDER_BUILD_WONDER);
1073       } else {
1074 	local_hide(ID_UNIT_ORDER_BUILD_WONDER);
1075       }
1076 
1077       pextra = next_extra_for_tile(pTile, EC_ROAD,
1078                                    unit_owner(pUnit), pUnit);
1079       if (pextra != NULL
1080           && can_unit_do_activity_targeted(pUnit, ACTIVITY_GEN_ROAD, pextra)) {
1081         struct road_type *proad = extra_road_get(pextra);
1082         enum road_compat compat = road_compat_special(proad);
1083 
1084         time = turns_to_activity_done(pTile, ACTIVITY_GEN_ROAD, pextra, pUnit);
1085 
1086         /* TRANS: "Build Railroad (R) 3 turns" */
1087 	fc_snprintf(cBuf, sizeof(cBuf), _("Build %s (%s) %d %s"),
1088                     extra_name_translation(pextra),
1089                     "R", time,
1090                     PL_("turn", "turns", time));
1091 
1092 	if (compat == ROCO_RAILROAD) {
1093 	  pOrder_Road_Button->theme = current_theme->ORailRoad_Icon;
1094 	} else {
1095 	  pOrder_Road_Button->theme = current_theme->ORoad_Icon;
1096 	}
1097         copy_chars_to_utf8_str(pOrder_Road_Button->info_label, cBuf);
1098 	clear_wflag(pOrder_Road_Button, WF_HIDDEN);
1099       } else {
1100 	set_wflag(pOrder_Road_Button, WF_HIDDEN);
1101       }
1102 
1103       /* unit_can_est_trade_route_here(pUnit) */
1104       if (pCity && utype_can_do_action(unit_type_get(pUnit),
1105                                        ACTION_TRADE_ROUTE)
1106           && (pHomecity = game_city_by_number(pUnit->homecity))
1107           && can_cities_trade(pHomecity, pCity)) {
1108         int revenue = get_caravan_enter_city_trade_bonus(pHomecity, pCity,
1109                                                          TRUE);
1110 
1111         if (can_establish_trade_route(pHomecity, pCity)) {
1112           fc_snprintf(cBuf, sizeof(cBuf),
1113                       _("%s With %s ( %d one time bonus + %d trade ) (R)"),
1114                       action_id_name_translation(ACTION_TRADE_ROUTE),
1115                       city_name_get(pHomecity),
1116                       revenue,
1117                       trade_between_cities(pHomecity, pCity));
1118         } else {
1119           revenue = (revenue + 2) / 3;
1120           fc_snprintf(cBuf, sizeof(cBuf),
1121                       _("%s Of %s ( %d one time bonus ) (R)"),
1122                       action_id_name_translation(ACTION_MARKETPLACE),
1123                       city_name_get(pHomecity),
1124                       revenue);
1125         }
1126         copy_chars_to_utf8_str(pOrder_Trade_Button->info_label, cBuf);
1127         clear_wflag(pOrder_Trade_Button, WF_HIDDEN);
1128       } else {
1129         set_wflag(pOrder_Trade_Button, WF_HIDDEN);
1130       }
1131 
1132       if (can_unit_do_activity(pUnit, ACTIVITY_IRRIGATE)) {
1133         if (is_build_activity(ACTIVITY_IRRIGATE, pTile)) {
1134           /* Activity results in extra */
1135           struct extra_type *irrig_extra = next_extra_for_tile(pTile, EC_IRRIGATION,
1136                                                                unit_owner(pUnit),
1137                                                                pUnit);
1138 
1139           time = turns_to_activity_done(pTile, ACTIVITY_IRRIGATE,
1140                                         irrig_extra, pUnit);
1141           /* TRANS: "Build Irrigation (I) 5 turns" */
1142           fc_snprintf(cBuf, sizeof(cBuf), _("Build %s (%s) %d %s"),
1143                       extra_name_translation(irrig_extra), "I", time,
1144                       PL_("turn", "turns", time));
1145           pOrder_Irrigation_Button->theme = current_theme->OIrrigation_Icon;
1146         } else {
1147           /* Activity results in terrain change */
1148           time = turns_to_activity_done(pTile, ACTIVITY_IRRIGATE,
1149                                         NULL, pUnit);
1150 
1151           /* FIXME: get rid of this ruleset-specific hardcoding */
1152           if (!strcmp(terrain_rule_name(pTerrain), "Forest")
1153               || !strcmp(terrain_rule_name(pTerrain), "Jungle")) {
1154             /* set Crop Forest Icon */
1155             fc_snprintf(cBuf, sizeof(cBuf),"%s %s (%s) %d %s",
1156                         _("Cut Down to"),
1157                         terrain_name_translation(pTerrain->irrigation_result),
1158                         "I", time , PL_("turn", "turns", time));
1159             pOrder_Irrigation_Button->theme = current_theme->OCutDownForest_Icon;
1160           } else {
1161             /* TRANS: "Change to Grassland (I) 10 turns" */
1162             fc_snprintf(cBuf, sizeof(cBuf), _("Change to %s (%s) %d %s"),
1163                         terrain_name_translation(pTerrain->irrigation_result),
1164                         "I", time , PL_("turn", "turns", time));
1165             pOrder_Irrigation_Button->theme = current_theme->OIrrigation_Icon;
1166           }
1167         }
1168 
1169         copy_chars_to_utf8_str(pOrder_Irrigation_Button->info_label, cBuf);
1170         clear_wflag(pOrder_Irrigation_Button, WF_HIDDEN);
1171       } else {
1172         set_wflag(pOrder_Irrigation_Button, WF_HIDDEN);
1173       }
1174 
1175       if (can_unit_do_activity(pUnit, ACTIVITY_MINE)) {
1176         if (is_build_activity(ACTIVITY_MINE, pTile)) {
1177           /* Activity results in extra */
1178           struct extra_type *mine_extra = next_extra_for_tile(pTile, EC_MINE,
1179                                                               unit_owner(pUnit),
1180                                                               pUnit);
1181 
1182           time = turns_to_activity_done(pTile, ACTIVITY_MINE, mine_extra, pUnit);
1183           /* TRANS: "Build Mine (M) 5 turns" */
1184           fc_snprintf(cBuf, sizeof(cBuf), _("Build %s (%s) %d %s"),
1185                       extra_name_translation(mine_extra), "M", time,
1186                       PL_("turn", "turns", time));
1187           pOrder_Mine_Button->theme = current_theme->OMine_Icon;
1188         } else {
1189           /* Activity results in terrain change */
1190           time = turns_to_activity_done(pTile, ACTIVITY_MINE, NULL, pUnit);
1191 
1192           /* FIXME: get rid of this ruleset-specific hardcoding */
1193           if (!strcmp(terrain_rule_name(pTerrain->mining_result), "Forest")) {
1194             /* set Forest Icon -> plant Forest */
1195             fc_snprintf(cBuf, sizeof(cBuf), "%s (%s) %d %s",
1196                         _("Plant Forest"), "M", time,
1197                         PL_("turn", "turns", time));
1198             pOrder_Mine_Button->theme = current_theme->OPlantForest_Icon;
1199           } else {
1200             /* TRANS: "Change to Swamp (M) 10 turns" */
1201             fc_snprintf(cBuf, sizeof(cBuf), _("Change to %s (%s) %d %s"),
1202                         terrain_name_translation(pTerrain->mining_result),
1203                         "M", time , PL_("turn", "turns", time));
1204             if (!strcmp(terrain_rule_name(pTerrain->mining_result), "Swamp")) {
1205               /* set Irrigate Icon -> make swamp */
1206               pOrder_Mine_Button->theme = current_theme->OIrrigation_Icon;
1207             } else {
1208               pOrder_Mine_Button->theme = current_theme->OPlantForest_Icon;
1209             }
1210           }
1211         }
1212 
1213         copy_chars_to_utf8_str(pOrder_Mine_Button->info_label, cBuf);
1214         clear_wflag(pOrder_Mine_Button, WF_HIDDEN);
1215       } else {
1216         set_wflag(pOrder_Mine_Button, WF_HIDDEN);
1217       }
1218 
1219       if (can_unit_do_activity(pUnit, ACTIVITY_TRANSFORM)) {
1220         /* Activity always results in terrain change */
1221         time = turns_to_activity_done(pTile, ACTIVITY_TRANSFORM, NULL, pUnit);
1222         fc_snprintf(cBuf, sizeof(cBuf),"%s %s (%s) %d %s",
1223                     _("Transform to"),
1224                     terrain_name_translation(pTerrain->transform_result),
1225                     "O", time, PL_("turn", "turns", time));
1226         copy_chars_to_utf8_str(pOrder_Transform_Button->info_label, cBuf);
1227         clear_wflag(pOrder_Transform_Button, WF_HIDDEN);
1228       } else {
1229         set_wflag(pOrder_Transform_Button, WF_HIDDEN);
1230       }
1231 
1232       pbase = get_base_by_gui_type(BASE_GUI_FORTRESS, pUnit, pTile);
1233       if (pbase != NULL) {
1234         struct extra_type *base_extra = base_extra_get(pbase);
1235 
1236         time = turns_to_activity_done(pTile, ACTIVITY_BASE, base_extra, pUnit);
1237         /* TRANS: "Build Fortress (Shift+F) 5 turns" */
1238         fc_snprintf(cBuf, sizeof(cBuf), _("Build %s (%s) %d %s"),
1239                     extra_name_translation(base_extra), "Shift+F", time,
1240                     PL_("turn", "turns", time));
1241         copy_chars_to_utf8_str(pOrder_Fortress_Button->info_label, cBuf);
1242         clear_wflag(pOrder_Fortress_Button, WF_HIDDEN);
1243       } else {
1244         set_wflag(pOrder_Fortress_Button, WF_HIDDEN);
1245       }
1246 
1247       if (can_unit_do_activity(pUnit, ACTIVITY_FORTIFYING)) {
1248         local_show(ID_UNIT_ORDER_FORTIFY);
1249       } else {
1250         local_hide(ID_UNIT_ORDER_FORTIFY);
1251       }
1252 
1253       pbase = get_base_by_gui_type(BASE_GUI_AIRBASE, pUnit, pTile);
1254       if (pbase != NULL) {
1255         struct extra_type *base_extra = base_extra_get(pbase);
1256 
1257         time = turns_to_activity_done(pTile, ACTIVITY_BASE, base_extra, pUnit);
1258         /* TRANS: "Build Airbase (Shift+E) 5 turns" */
1259         fc_snprintf(cBuf, sizeof(cBuf), _("Build %s (%s) %d %s"),
1260                     extra_name_translation(base_extra), "Shift+E", time,
1261                     PL_("turn", "turns", time));
1262         copy_chars_to_utf8_str(pOrder_Airbase_Button->info_label, cBuf);
1263         clear_wflag(pOrder_Airbase_Button, WF_HIDDEN);
1264       } else {
1265         set_wflag(pOrder_Airbase_Button, WF_HIDDEN);
1266       }
1267 
1268       pextra = prev_extra_in_tile(pTile, ERM_CLEANPOLLUTION,
1269                                   unit_owner(pUnit), pUnit);
1270       if (pextra != NULL
1271           && can_unit_do_activity_targeted(pUnit, ACTIVITY_POLLUTION, pextra)) {
1272         time = turns_to_activity_done(pTile, ACTIVITY_POLLUTION, pextra,
1273                                       pUnit);
1274         /* TRANS: "Clean Pollution (P) 3 turns" */
1275         fc_snprintf(cBuf, sizeof(cBuf), _("Clean %s (%s) %d %s"),
1276                     extra_name_translation(pextra), "P", time,
1277                     PL_("turn", "turns", time));
1278         copy_chars_to_utf8_str(pOrder_Pollution_Button->info_label, cBuf);
1279         clear_wflag(pOrder_Pollution_Button, WF_HIDDEN);
1280       } else {
1281         set_wflag(pOrder_Pollution_Button, WF_HIDDEN);
1282       }
1283 
1284       if (can_unit_paradrop(pUnit)) {
1285         local_show(ID_UNIT_ORDER_PARADROP);
1286       } else {
1287         local_hide(ID_UNIT_ORDER_PARADROP);
1288       }
1289 
1290       pextra = prev_extra_in_tile(pTile, ERM_CLEANFALLOUT,
1291                                   unit_owner(pUnit), pUnit);
1292       if (pextra != NULL
1293           && can_unit_do_activity_targeted(pUnit, ACTIVITY_FALLOUT, pextra)) {
1294         time = turns_to_activity_done(pTile, ACTIVITY_FALLOUT, pextra,
1295                                       pUnit);
1296         /* TRANS: "Clean Fallout (N) 3 turns" */
1297         fc_snprintf(cBuf, sizeof(cBuf), _("Clean %s (%s) %d %s"),
1298                     extra_name_translation(pextra), "N", time,
1299                     PL_("turn", "turns", time));
1300         copy_chars_to_utf8_str(pOrder_Fallout_Button->info_label, cBuf);
1301         clear_wflag(pOrder_Fallout_Button, WF_HIDDEN);
1302       } else {
1303         set_wflag(pOrder_Fallout_Button, WF_HIDDEN);
1304       }
1305 
1306       if (can_unit_do_activity(pUnit, ACTIVITY_SENTRY)) {
1307         local_show(ID_UNIT_ORDER_SENTRY);
1308       } else {
1309         local_hide(ID_UNIT_ORDER_SENTRY);
1310       }
1311 
1312       if (can_unit_do_activity(pUnit, ACTIVITY_PILLAGE)) {
1313         local_show(ID_UNIT_ORDER_PILLAGE);
1314       } else {
1315         local_hide(ID_UNIT_ORDER_PILLAGE);
1316       }
1317 
1318       if (pCity && can_unit_change_homecity(pUnit)
1319           && pCity->id != pUnit->homecity) {
1320         local_show(ID_UNIT_ORDER_HOMECITY);
1321       } else {
1322         local_hide(ID_UNIT_ORDER_HOMECITY);
1323       }
1324 
1325       if (pUnit->client.occupied) {
1326         local_show(ID_UNIT_ORDER_UNLOAD_TRANSPORTER);
1327       } else {
1328         local_hide(ID_UNIT_ORDER_UNLOAD_TRANSPORTER);
1329       }
1330 
1331       if (units_can_load(punits)) {
1332         local_show(ID_UNIT_ORDER_LOAD);
1333       } else {
1334         local_hide(ID_UNIT_ORDER_LOAD);
1335       }
1336 
1337       if (units_can_unload(punits)) {
1338         local_show(ID_UNIT_ORDER_UNLOAD);
1339       } else {
1340         local_hide(ID_UNIT_ORDER_UNLOAD);
1341       }
1342 
1343       if (is_unit_activity_on_tile(ACTIVITY_SENTRY, unit_tile(pUnit))) {
1344         local_show(ID_UNIT_ORDER_WAKEUP_OTHERS);
1345       } else {
1346         local_hide(ID_UNIT_ORDER_WAKEUP_OTHERS);
1347       }
1348 
1349       if (can_unit_do_autosettlers(pUnit)) {
1350         local_show(ID_UNIT_ORDER_AUTO_SETTLER);
1351       } else {
1352         local_hide(ID_UNIT_ORDER_AUTO_SETTLER);
1353       }
1354 
1355       if (can_unit_do_activity(pUnit, ACTIVITY_EXPLORE)) {
1356         local_show(ID_UNIT_ORDER_AUTO_EXPLORE);
1357       } else {
1358         local_hide(ID_UNIT_ORDER_AUTO_EXPLORE);
1359       }
1360 
1361       {
1362         bool conn_possible = FALSE;
1363         struct extra_type_list *extras;
1364 
1365         extras = extra_type_list_by_cause(EC_IRRIGATION);
1366 
1367         if (extra_type_list_size(extras) > 0) {
1368           struct extra_type *tgt;
1369 
1370           tgt = extra_type_list_get(extras, 0);
1371           conn_possible = can_units_do_connect(punits, ACTIVITY_IRRIGATE, tgt);
1372         }
1373 
1374         if (conn_possible) {
1375           local_show(ID_UNIT_ORDER_CONNECT_IRRIGATE);
1376         } else {
1377           local_hide(ID_UNIT_ORDER_CONNECT_IRRIGATE);
1378         }
1379       }
1380 
1381       {
1382         struct road_type *proad = road_by_compat_special(ROCO_ROAD);
1383         bool road_conn_possible;
1384 
1385         if (proad != NULL) {
1386           struct extra_type *tgt;
1387 
1388           tgt = road_extra_get(proad);
1389 
1390           road_conn_possible = can_unit_do_connect(pUnit, ACTIVITY_GEN_ROAD, tgt);
1391         } else {
1392           road_conn_possible = FALSE;
1393         }
1394 
1395         if (road_conn_possible) {
1396           local_show(ID_UNIT_ORDER_CONNECT_ROAD);
1397         } else {
1398           local_hide(ID_UNIT_ORDER_CONNECT_ROAD);
1399         }
1400       }
1401 
1402       {
1403         struct road_type *proad = road_by_compat_special(ROCO_RAILROAD);
1404         bool road_conn_possible;
1405 
1406         if (proad != NULL) {
1407           struct extra_type *tgt;
1408 
1409           tgt = road_extra_get(proad);
1410 
1411           road_conn_possible = can_unit_do_connect(pUnit, ACTIVITY_GEN_ROAD, tgt);
1412         } else {
1413           road_conn_possible = FALSE;
1414         }
1415 
1416         if (road_conn_possible) {
1417           local_show(ID_UNIT_ORDER_CONNECT_RAILROAD);
1418         } else {
1419           local_hide(ID_UNIT_ORDER_CONNECT_RAILROAD);
1420         }
1421       }
1422 
1423      if (unit_can_do_action(pUnit, ACTION_ANY)) {
1424        local_show(ID_UNIT_ORDER_DIPLOMAT_DLG);
1425       } else {
1426        local_hide(ID_UNIT_ORDER_DIPLOMAT_DLG);
1427       }
1428 
1429       if (unit_has_type_flag(pUnit, UTYF_NUCLEAR)) {
1430         local_show(ID_UNIT_ORDER_NUKE);
1431       } else {
1432         local_hide(ID_UNIT_ORDER_NUKE);
1433       }
1434 
1435       if (pCity && pCity->airlift) {
1436         local_show(ID_UNIT_ORDER_AIRLIFT);
1437         hide(ID_UNIT_ORDER_GOTO_CITY);
1438       } else {
1439         local_show(ID_UNIT_ORDER_GOTO_CITY);
1440         local_hide(ID_UNIT_ORDER_AIRLIFT);
1441       }
1442 
1443       if (pCity && can_upgrade_unittype(client.conn.playing,
1444                                         unit_type_get(pUnit))) {
1445         local_show(ID_UNIT_ORDER_UPGRADE);
1446       } else {
1447         local_hide(ID_UNIT_ORDER_UPGRADE);
1448       }
1449 
1450       if (unit_can_convert(pUnit)) {
1451         local_show(ID_UNIT_ORDER_CONVERT);
1452       } else {
1453         local_hide(ID_UNIT_ORDER_CONVERT);
1454       }
1455 
1456       set_new_order_widget_start_pos();
1457       counter = redraw_order_widgets();
1458 
1459     } else {
1460       if (counter) {
1461         hide_group(pBeginOrderWidgetList, pEndOrderWidgetList);
1462       }
1463 
1464       counter = 0;
1465     }
1466   }
1467 }
1468 
1469 /**************************************************************************
1470   Disable all unit order buttons.
1471 **************************************************************************/
disable_order_buttons(void)1472 void disable_order_buttons(void)
1473 {
1474   undraw_order_widgets();
1475   disable_group(pBeginOrderWidgetList, pEndOrderWidgetList);
1476   redraw_order_widgets();
1477 }
1478 
1479 /**************************************************************************
1480   Enable all unit order buttons.
1481 **************************************************************************/
enable_order_buttons(void)1482 void enable_order_buttons(void)
1483 {
1484   if (can_client_issue_orders()) {
1485     undraw_order_widgets();
1486     enable_group(pBeginOrderWidgetList, pEndOrderWidgetList);
1487     redraw_order_widgets();
1488   }
1489 }
1490