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 <stdio.h>
19 #include <stdlib.h>
20 #include <math.h> /* sqrt */
21
22 #include <X11/Intrinsic.h>
23 #include <X11/StringDefs.h>
24 #include <X11/Xaw/Form.h>
25 #include <X11/Xaw/SimpleMenu.h>
26 #include <X11/Xaw/Command.h>
27 #include <X11/Xaw/List.h>
28 #include <X11/Xaw/Viewport.h>
29 #include <X11/Xaw/AsciiText.h>
30 #include <X11/Xaw/Tree.h>
31
32 /* utility */
33 #include "fcintl.h"
34 #include "genlist.h"
35 #include "mem.h"
36 #include "shared.h"
37 #include "support.h"
38
39 /* common */
40 #include "city.h"
41 #include "game.h"
42 #include "government.h"
43 #include "movement.h"
44 #include "specialist.h"
45 #include "tech.h"
46 #include "unit.h"
47 #include "map.h"
48 #include "research.h"
49 #include "version.h"
50
51 /* client */
52 #include "client_main.h"
53 #include "climisc.h"
54 #include "dialogs.h"
55 #include "graphics.h"
56 #include "gui_main.h"
57 #include "gui_stuff.h"
58 #include "helpdata.h"
59 #include "tilespec.h"
60
61 #include "helpdlg.h"
62
63 static Widget help_dialog_shell;
64 static Widget help_form;
65 static Widget help_viewport;
66 static Widget help_list;
67 static Widget help_text;
68 static Widget help_close_command;
69
70 static Widget help_right_form;
71 static Widget help_title;
72
73 static Widget help_improvement_cost, help_improvement_cost_data;
74 static Widget help_improvement_upkeep, help_improvement_upkeep_data;
75 static Widget help_improvement_req, help_improvement_req_data;
76 static Widget help_wonder_obsolete, help_wonder_obsolete_data;
77
78 static Widget help_tech_tree;
79 static Widget help_tree_viewport;
80
81 static Widget help_unit_attack, help_unit_attack_data;
82 static Widget help_unit_def, help_unit_def_data;
83 static Widget help_unit_move, help_unit_move_data;
84 static Widget help_unit_hp, help_unit_hp_data;
85 static Widget help_unit_fp, help_unit_fp_data;
86 static Widget help_unit_cost, help_unit_cost_data;
87 static Widget help_unit_visrange, help_unit_visrange_data;
88 static Widget help_unit_upkeep, help_unit_upkeep_data;
89 static Widget help_unit_tile;
90
91 static Widget help_terrain_movement_defense, help_terrain_movement_defense_data;
92 static Widget help_terrain_food_shield_trade, help_terrain_food_shield_trade_data;
93 static Widget help_terrain_resources;
94 static Widget help_terrain_road_result_time, help_terrain_road_result_time_data;
95 static Widget help_terrain_irrigation_result_time, help_terrain_irrigation_result_time_data;
96 static Widget help_terrain_mining_result_time, help_terrain_mining_result_time_data;
97 static Widget help_terrain_transform_result_time, help_terrain_transform_result_time_data;
98
99
100 static void create_help_page(enum help_page_type type);
101
102 static void help_close_command_callback(Widget w, XtPointer client_data,
103 XtPointer call_data);
104 static void help_list_callback(Widget w, XtPointer client_data,
105 XtPointer call_data);
106 static void help_tree_node_callback(Widget w, XtPointer client_data,
107 XtPointer call_data);
108
109 static void create_help_dialog(void);
110 static void help_update_dialog(const struct help_item *pitem);
111
112 static void select_help_item(int item);
113 static void select_help_item_string(const char *item,
114 enum help_page_type htype);
115
116 static char *topic_list[1024];
117
118 #define TREE_NODE_UNKNOWN_TECH_BG "red"
119 #define TREE_NODE_KNOWN_TECH_BG "green"
120 #define TREE_NODE_REACHABLE_TECH_BG "yellow"
121 #define TREE_NODE_REMOVED_TECH_BG "magenta"
122
123
124 /****************************************************************
125 ...
126 *****************************************************************/
set_title_topic(const struct help_item * pitem)127 static void set_title_topic(const struct help_item *pitem)
128 {
129 if (strcmp(pitem->topic, _(HELP_ABOUT_ITEM)) == 0) {
130 xaw_set_label(help_title, freeciv_name_version());
131 } else {
132 xaw_set_label(help_title, pitem->topic);
133 }
134 }
135
136
137 /****************************************************************
138 ...
139 *****************************************************************/
popdown_help_dialog(void)140 void popdown_help_dialog(void)
141 {
142 if(help_dialog_shell) {
143 XtDestroyWidget(help_dialog_shell);
144 help_dialog_shell=0;
145 }
146 }
147
148 /****************************************************************
149 ...
150 *****************************************************************/
popup_help_dialog_typed(const char * item,enum help_page_type htype)151 void popup_help_dialog_typed(const char *item, enum help_page_type htype)
152 {
153 Position x, y;
154 Dimension width, height;
155
156 if(!help_dialog_shell) {
157 create_help_dialog();
158 XtVaGetValues(toplevel, XtNwidth, &width, XtNheight, &height, NULL);
159 XtTranslateCoords(toplevel, (Position) width/10, (Position) height/10,
160 &x, &y);
161 XtVaSetValues(help_dialog_shell, XtNx, x, XtNy, y, NULL);
162 }
163
164 XtPopup(help_dialog_shell, XtGrabNone);
165
166 select_help_item_string(item, htype);
167 }
168
169
170 /****************************************************************
171 ...
172 Not sure if this should call _(item) as it does, or whether all
173 callers of this function should do so themselves... --dwp
174 *****************************************************************/
popup_help_dialog_string(const char * item)175 void popup_help_dialog_string(const char *item)
176 {
177 popup_help_dialog_typed(Q_(item), HELP_ANY);
178 }
179
180
181 /**************************************************************************
182 ...
183 **************************************************************************/
create_help_dialog(void)184 static void create_help_dialog(void)
185 {
186 int i=0;
187
188 help_items_iterate(pitem)
189 topic_list[i++]=pitem->topic;
190 help_items_iterate_end;
191 topic_list[i]=0;
192
193
194 help_dialog_shell =
195 I_T(XtCreatePopupShell("helpdialog",
196 topLevelShellWidgetClass,
197 toplevel, NULL, 0));
198
199 help_form = XtVaCreateManagedWidget("helpform",
200 formWidgetClass,
201 help_dialog_shell, NULL);
202
203
204 help_viewport = XtVaCreateManagedWidget("helpviewport",
205 viewportWidgetClass,
206 help_form,
207 NULL);
208
209 help_list = XtVaCreateManagedWidget("helplist",
210 listWidgetClass,
211 help_viewport,
212 XtNlist,
213 (XtArgVal)topic_list,
214 NULL);
215
216
217 help_right_form=XtVaCreateManagedWidget("helprightform",
218 formWidgetClass,
219 help_form, NULL);
220
221
222 help_title=XtVaCreateManagedWidget("helptitle",
223 labelWidgetClass,
224 help_right_form,
225 NULL);
226
227
228 help_close_command =
229 I_L(XtVaCreateManagedWidget("helpclosecommand", commandWidgetClass,
230 help_form, NULL));
231
232 XtAddCallback(help_close_command, XtNcallback,
233 help_close_command_callback, NULL);
234
235 XtAddCallback(help_list, XtNcallback,
236 help_list_callback, NULL);
237
238 XtRealizeWidget(help_dialog_shell);
239
240 XSetWMProtocols(display, XtWindow(help_dialog_shell),
241 &wm_delete_window, 1);
242 XtOverrideTranslations(help_dialog_shell,
243 XtParseTranslationTable("<Message>WM_PROTOCOLS: msg-close-help()"));
244
245 /* create_help_page(HELP_IMPROVEMENT); */
246 create_help_page(HELP_TEXT);
247 }
248
249
250 /**************************************************************************
251 ...
252 **************************************************************************/
create_tech_tree(Widget tree,Widget parent,int tech,int levels)253 static void create_tech_tree(Widget tree, Widget parent, int tech, int levels)
254 {
255 const struct research *presearch = research_get(client_player());
256 Widget l;
257 int type;
258 char *bg="";
259 char label[MAX_LEN_NAME+3];
260
261 type = (tech == A_LAST ? TECH_UNKNOWN
262 : research_invention_state(presearch, tech));
263 switch(type) {
264 case TECH_UNKNOWN:
265 bg=TREE_NODE_UNKNOWN_TECH_BG;
266 break;
267 case TECH_KNOWN:
268 bg=TREE_NODE_KNOWN_TECH_BG;
269 break;
270 case TECH_PREREQS_KNOWN:
271 bg=TREE_NODE_REACHABLE_TECH_BG;
272 break;
273 }
274
275 if(tech==A_LAST ||
276 (advance_required(tech, AR_ONE)==A_LAST
277 && advance_required(tech, AR_TWO)==A_LAST)) {
278 sz_strlcpy(label, _("Removed"));
279 bg=TREE_NODE_REMOVED_TECH_BG;
280 l=XtVaCreateManagedWidget("treenode", commandWidgetClass,
281 tree,
282 XtNlabel, label,
283 XtNbackground, bg, NULL);
284 XtVaSetValues(l, XtVaTypedArg, XtNbackground,
285 XtRString, bg, strlen(bg)+1, NULL);
286 return;
287 }
288
289 fc_snprintf(label, sizeof(label),
290 "%s:%d", advance_name_translation(advance_by_number(tech)),
291 research_goal_unknown_techs(presearch, tech));
292
293 if(parent) {
294 l=XtVaCreateManagedWidget("treenode",
295 commandWidgetClass,
296 tree,
297 XtNlabel, label,
298 XtNtreeParent, parent,
299 NULL);
300 }
301 else {
302 l=XtVaCreateManagedWidget("treenode",
303 commandWidgetClass,
304 tree,
305 XtNlabel, label,
306 NULL);
307 }
308
309 XtAddCallback(l, XtNcallback, help_tree_node_callback,
310 INT_TO_XTPOINTER(tech));
311
312 XtVaSetValues(l, XtVaTypedArg, XtNbackground,
313 XtRString, bg, strlen(bg)+1, NULL);
314
315
316 if(--levels>0) {
317 if(advance_required(tech, AR_ONE)!=A_NONE)
318 create_tech_tree(tree, l, advance_required(tech, AR_ONE), levels);
319 if(advance_required(tech, AR_TWO)!=A_NONE)
320 create_tech_tree(tree, l, advance_required(tech, AR_TWO), levels);
321 }
322
323
324 }
325
326
327 /****************************************************************
328 ...
329 *****************************************************************/
create_help_page(enum help_page_type type)330 static void create_help_page(enum help_page_type type)
331 {
332 Dimension w, h, w2, h2, ay, ah;
333
334 XtVaGetValues(help_right_form, XtNwidth, &w, NULL);
335 XtVaGetValues(help_viewport, XtNheight, &h, NULL);
336 XtVaGetValues(help_title, XtNwidth, &w2, XtNheight, &h2, NULL);
337
338 XtDestroyWidget(help_right_form);
339
340 help_right_form =
341 XtVaCreateManagedWidget("helprightform",
342 formWidgetClass,
343 help_form,
344 XtNwidth, w,
345 XtNheight, h,
346 NULL);
347
348
349 help_title =
350 XtVaCreateManagedWidget("helptitle",
351 labelWidgetClass,
352 help_right_form,
353 XtNwidth, w2,
354 NULL);
355
356 help_tree_viewport = 0;
357
358 if(type==HELP_TEXT || type==HELP_ANY) {
359 help_text =
360 XtVaCreateManagedWidget("helptext",
361 asciiTextWidgetClass,
362 help_right_form,
363 XtNeditType, XawtextRead,
364 XtNscrollVertical, XawtextScrollAlways,
365 XtNwidth, w2,
366 XtNheight, h-h2-15,
367 XtNbottom, XawChainBottom,
368 NULL);
369 }
370 else if(type==HELP_IMPROVEMENT || type==HELP_WONDER) {
371 help_text =
372 XtVaCreateManagedWidget("helptext",
373 asciiTextWidgetClass,
374 help_right_form,
375 XtNeditType, XawtextRead,
376 XtNscrollVertical, XawtextScrollAlways,
377 XtNwidth, w2,
378 XtNheight, 70,
379 NULL);
380
381
382 help_improvement_cost =
383 I_L(XtVaCreateManagedWidget("helpimprcost",
384 labelWidgetClass,
385 help_right_form,
386 NULL));
387 help_improvement_cost_data =
388 XtVaCreateManagedWidget("helpimprcostdata",
389 labelWidgetClass,
390 help_right_form,
391 NULL);
392
393 help_improvement_req =
394 I_L(XtVaCreateManagedWidget("helpimprreq",
395 labelWidgetClass,
396 help_right_form,
397 NULL));
398 help_improvement_req_data =
399 XtVaCreateManagedWidget("helpimprreqdata",
400 labelWidgetClass,
401 help_right_form,
402 NULL);
403 if(type==HELP_IMPROVEMENT) {
404 help_improvement_upkeep =
405 I_L(XtVaCreateManagedWidget("helpimprupkeep",
406 labelWidgetClass,
407 help_right_form,
408 NULL));
409 help_improvement_upkeep_data =
410 XtVaCreateManagedWidget("helpimprupkeepdata",
411 labelWidgetClass,
412 help_right_form,
413 NULL);
414 } else {
415 help_wonder_obsolete =
416 I_L(XtVaCreateManagedWidget("helpwonderobsolete",
417 labelWidgetClass,
418 help_right_form,
419 NULL));
420 help_wonder_obsolete_data =
421 XtVaCreateManagedWidget("helpwonderobsoletedata",
422 labelWidgetClass,
423 help_right_form,
424 NULL);
425 }
426
427 XtVaGetValues(help_improvement_req, XtNy, &ay, XtNheight, &ah, NULL);
428
429 help_tree_viewport =
430 XtVaCreateManagedWidget("helptreeviewport",
431 viewportWidgetClass,
432 help_right_form,
433 XtNwidth, w2,
434 XtNheight, MAX(1,h-(ay+ah)-10),
435 NULL);
436 help_tech_tree =
437 XtVaCreateManagedWidget("helptree",
438 treeWidgetClass,
439 help_tree_viewport,
440 NULL);
441
442 XawTreeForceLayout(help_tech_tree);
443 }
444 else if(type==HELP_UNIT) {
445 help_text =
446 XtVaCreateManagedWidget("helptext",
447 asciiTextWidgetClass,
448 help_right_form,
449 XtNeditType, XawtextRead,
450 XtNscrollVertical, XawtextScrollAlways,
451 XtNwidth, w2,
452 XtNheight, 70,
453 NULL);
454
455 help_unit_cost =
456 I_L(XtVaCreateManagedWidget("helpunitcost",
457 labelWidgetClass,
458 help_right_form,
459 NULL));
460 help_unit_cost_data =
461 XtVaCreateManagedWidget("helpunitcostdata",
462 labelWidgetClass,
463 help_right_form,
464 NULL);
465 help_unit_attack =
466 I_L(XtVaCreateManagedWidget("helpunitattack",
467 labelWidgetClass,
468 help_right_form,
469 NULL));
470 help_unit_attack_data =
471 XtVaCreateManagedWidget("helpunitattackdata",
472 labelWidgetClass,
473 help_right_form,
474 NULL);
475 help_unit_def =
476 I_L(XtVaCreateManagedWidget("helpunitdef",
477 labelWidgetClass,
478 help_right_form,
479 NULL));
480 help_unit_def_data =
481 XtVaCreateManagedWidget("helpunitdefdata",
482 labelWidgetClass,
483 help_right_form,
484 NULL);
485 help_unit_move =
486 I_L(XtVaCreateManagedWidget("helpunitmove",
487 labelWidgetClass,
488 help_right_form,
489 NULL));
490 help_unit_move_data =
491 XtVaCreateManagedWidget("helpunitmovedata",
492 labelWidgetClass,
493 help_right_form,
494 NULL);
495 help_unit_tile =
496 XtVaCreateManagedWidget("helpunittile",
497 labelWidgetClass,
498 help_right_form,
499 XtNwidth, tileset_full_tile_width(tileset),
500 XtNheight, tileset_full_tile_height(tileset),
501 NULL);
502 XtAddCallback(help_unit_tile,
503 XtNdestroyCallback,free_bitmap_destroy_callback,
504 NULL);
505 help_unit_fp =
506 I_L(XtVaCreateManagedWidget("helpunitfp",
507 labelWidgetClass,
508 help_right_form,
509 NULL));
510 help_unit_fp_data =
511 XtVaCreateManagedWidget("helpunitfpdata",
512 labelWidgetClass,
513 help_right_form,
514 NULL);
515 help_unit_hp =
516 I_L(XtVaCreateManagedWidget("helpunithp",
517 labelWidgetClass,
518 help_right_form,
519 NULL));
520 help_unit_hp_data =
521 XtVaCreateManagedWidget("helpunithpdata",
522 labelWidgetClass,
523 help_right_form,
524 NULL);
525 help_unit_visrange =
526 I_L(XtVaCreateManagedWidget("helpunitvisrange",
527 labelWidgetClass,
528 help_right_form,
529 NULL));
530 help_unit_visrange_data =
531 XtVaCreateManagedWidget("helpunitvisrangedata",
532 labelWidgetClass,
533 help_right_form,
534 NULL);
535 help_unit_upkeep =
536 I_L(XtVaCreateManagedWidget("helpunitupkeep",
537 labelWidgetClass,
538 help_right_form,
539 NULL));
540 help_unit_upkeep_data =
541 XtVaCreateManagedWidget("helpunitupkeepdata",
542 labelWidgetClass,
543 help_right_form,
544 NULL);
545 help_improvement_req =
546 I_L(XtVaCreateManagedWidget("helpimprreq",
547 labelWidgetClass,
548 help_right_form,
549 XtNfromVert, help_unit_upkeep,
550 NULL));
551 help_improvement_req_data =
552 XtVaCreateManagedWidget("helpimprreqdata",
553 labelWidgetClass,
554 help_right_form,
555 XtNfromVert, help_unit_upkeep,
556 NULL);
557 help_wonder_obsolete =
558 I_L(XtVaCreateManagedWidget("helpwonderobsolete",
559 labelWidgetClass,
560 help_right_form,
561 XtNfromVert, help_unit_upkeep,
562 NULL));
563 help_wonder_obsolete_data =
564 XtVaCreateManagedWidget("helpwonderobsoletedata",
565 labelWidgetClass,
566 help_right_form,
567 XtNfromVert, help_unit_upkeep,
568 NULL);
569 XtVaGetValues(help_improvement_req, XtNy, &ay, XtNheight, &ah, NULL);
570 help_tree_viewport =
571 XtVaCreateManagedWidget("helptreeviewport",
572 viewportWidgetClass,
573 help_right_form,
574 XtNwidth, w2,
575 XtNheight, MAX(1,h-(ay+ah)-10),
576 NULL);
577 help_tech_tree =
578 XtVaCreateManagedWidget("helptree",
579 treeWidgetClass,
580 help_tree_viewport,
581 NULL);
582 XawTreeForceLayout(help_tech_tree);
583 }
584 else if(type==HELP_TECH) {
585 help_text =
586 XtVaCreateManagedWidget("helptext",
587 asciiTextWidgetClass,
588 help_right_form,
589 XtNeditType, XawtextRead,
590 XtNscrollVertical, XawtextScrollAlways,
591 XtNwidth, w2,
592 XtNheight, 95,
593 NULL);
594
595 XtVaGetValues(help_text, XtNy, &ay, XtNheight, &ah, NULL);
596 help_tree_viewport =
597 XtVaCreateManagedWidget("helptreeviewport",
598 viewportWidgetClass,
599 help_right_form,
600 XtNwidth, w2,
601 XtNheight, MAX(1,h-(ay+ah)-10),
602 XtNfromVert,help_text,
603 NULL);
604 help_tech_tree =
605 XtVaCreateManagedWidget("helptree",
606 treeWidgetClass,
607 help_tree_viewport,
608 NULL);
609 XawTreeForceLayout(help_tech_tree);
610 }
611 else if(type==HELP_TERRAIN) {
612 help_text =
613 XtVaCreateManagedWidget
614 (
615 "helptext",
616 asciiTextWidgetClass,
617 help_right_form,
618 XtNeditType, XawtextRead,
619 XtNscrollVertical, XawtextScrollAlways,
620 XtNwidth, w2,
621 XtNheight, 140,
622 NULL);
623
624 help_terrain_movement_defense =
625 I_L(XtVaCreateManagedWidget
626 (
627 "help_terrain_movement_defense",
628 labelWidgetClass,
629 help_right_form,
630 NULL));
631 help_terrain_movement_defense_data =
632 XtVaCreateManagedWidget
633 (
634 "help_terrain_movement_defense_data",
635 labelWidgetClass,
636 help_right_form,
637 NULL);
638
639 help_terrain_food_shield_trade =
640 I_L(XtVaCreateManagedWidget
641 (
642 "help_terrain_food_shield_trade",
643 labelWidgetClass,
644 help_right_form,
645 NULL));
646 help_terrain_food_shield_trade_data =
647 XtVaCreateManagedWidget
648 (
649 "help_terrain_food_shield_trade_data",
650 labelWidgetClass,
651 help_right_form,
652 NULL);
653
654 help_terrain_resources =
655 XtVaCreateManagedWidget
656 (
657 "help_terrain_resources",
658 labelWidgetClass,
659 help_right_form,
660 XtNwidth, (w2-15)/2,
661 XtNjustify,XtJustifyCenter,
662 NULL);
663
664 help_terrain_road_result_time =
665 I_L(XtVaCreateManagedWidget
666 (
667 "help_terrain_road_result_time",
668 labelWidgetClass,
669 help_right_form,
670 NULL));
671 help_terrain_road_result_time_data =
672 XtVaCreateManagedWidget
673 (
674 "help_terrain_road_result_time_data",
675 labelWidgetClass,
676 help_right_form,
677 NULL);
678
679 help_terrain_irrigation_result_time =
680 I_L(XtVaCreateManagedWidget
681 (
682 "help_terrain_irrigation_result_time",
683 labelWidgetClass,
684 help_right_form,
685 NULL));
686 help_terrain_irrigation_result_time_data =
687 XtVaCreateManagedWidget
688 (
689 "help_terrain_irrigation_result_time_data",
690 labelWidgetClass,
691 help_right_form,
692 NULL);
693
694 help_terrain_mining_result_time =
695 I_L(XtVaCreateManagedWidget
696 (
697 "help_terrain_mining_result_time",
698 labelWidgetClass,
699 help_right_form,
700 NULL));
701 help_terrain_mining_result_time_data =
702 XtVaCreateManagedWidget
703 (
704 "help_terrain_mining_result_time_data",
705 labelWidgetClass,
706 help_right_form,
707 NULL);
708
709 help_terrain_transform_result_time =
710 I_L(XtVaCreateManagedWidget
711 (
712 "help_terrain_transform_result_time",
713 labelWidgetClass,
714 help_right_form,
715 NULL));
716 help_terrain_transform_result_time_data =
717 XtVaCreateManagedWidget
718 (
719 "help_terrain_transform_result_time_data",
720 labelWidgetClass,
721 help_right_form,
722 NULL);
723 }
724 }
725
726 /**************************************************************************
727 ...
728 **************************************************************************/
help_update_improvement(const struct help_item * pitem,char * title)729 static void help_update_improvement(const struct help_item *pitem,
730 char *title)
731 {
732 char buf[64000];
733 struct impr_type *imp = improvement_by_translated_name(title);
734
735 create_help_page(HELP_IMPROVEMENT);
736
737 if (imp && !is_great_wonder(imp)) {
738 char req_buf[512];
739 int i;
740
741 sprintf(buf, "%d ", impr_build_shield_cost(imp));
742 xaw_set_label(help_improvement_cost_data, buf);
743 sprintf(buf, "%d ", imp->upkeep);
744 xaw_set_label(help_improvement_upkeep_data, buf);
745 /*if (imp->tech_req == A_LAST) {
746 xaw_set_label(help_improvement_req_data, _("(Never)"));
747 } else {
748 xaw_set_label(help_improvement_req_data,
749 advance_name_translation(advance_by_number(imp->tech_req)));
750 }*/
751
752 /* FIXME: this should show ranges, negated reqs, and all the
753 * MAX_NUM_REQS reqs.
754 * Currently it's limited to 1 req but this code is partially prepared
755 * to be extended. Remember MAX_NUM_REQS is a compile-time
756 * definition. */
757 i = 0;
758 requirement_vector_iterate(&imp->reqs, preq) {
759 if (!preq->present) {
760 continue;
761 }
762 xaw_set_label(help_improvement_req_data,
763 universal_name_translation(&preq->source,
764 req_buf, sizeof(req_buf)));
765 i++;
766 break;
767 } requirement_vector_iterate_end;
768 /* create_tech_tree(help_tech_tree, 0,
769 imp->req[0].source.value.advance, 3);
770 */
771 } else {
772 xaw_set_label(help_improvement_cost_data, "0 ");
773 xaw_set_label(help_improvement_upkeep_data, "0 ");
774 xaw_set_label(help_improvement_req_data, _("(Never)"));
775 create_tech_tree(help_tech_tree, 0, A_LAST, 3);
776 }
777 set_title_topic(pitem);
778 helptext_building(buf, sizeof(buf), client.conn.playing, pitem->text, imp);
779 XtVaSetValues(help_text, XtNstring, buf, NULL);
780 }
781
782 /**************************************************************************
783 Update wonder help.
784 **************************************************************************/
help_update_wonder(const struct help_item * pitem,char * title)785 static void help_update_wonder(const struct help_item *pitem,
786 char *title)
787 {
788 char buf[64000];
789 struct impr_type *imp = improvement_by_translated_name(title);
790
791 create_help_page(HELP_WONDER);
792
793 if (imp && is_great_wonder(imp)) {
794 char req_buf[512];
795 int i;
796 struct advance *obs_tech = NULL;
797
798 sprintf(buf, "%d ", impr_build_shield_cost(imp));
799 xaw_set_label(help_improvement_cost_data, buf);
800 /* FIXME: this should show ranges, negated reqs, and all the
801 * MAX_NUM_REQS reqs.
802 * Currently it's limited to 1 req but this code is partially prepared
803 * to be extended. Remember MAX_NUM_REQS is a compile-time
804 * definition. */
805 i = 0;
806 requirement_vector_iterate(&imp->reqs, preq) {
807 if (!preq->present) {
808 continue;
809 }
810 xaw_set_label(help_improvement_req_data,
811 universal_name_translation(&preq->source,
812 req_buf, sizeof(req_buf)));
813 i++;
814 break;
815 } requirement_vector_iterate_end;
816
817 requirement_vector_iterate(&imp->obsolete_by, pobs) {
818 if (pobs->source.kind == VUT_ADVANCE) {
819 obs_tech = pobs->source.value.advance;
820 break;
821 }
822 } requirement_vector_iterate_end;
823
824 if (obs_tech != NULL) {
825 xaw_set_label(help_wonder_obsolete_data,
826 advance_name_translation(obs_tech));
827 } else {
828 xaw_set_label(help_wonder_obsolete_data, _("(Never)"));
829 }
830 /* create_tech_tree(help_tech_tree, 0,
831 imp->req[0].source.value.advance, 3);
832 */
833 } else {
834 /* can't find wonder */
835 xaw_set_label(help_improvement_cost_data, "0 ");
836 xaw_set_label(help_improvement_req_data, _("(Never)"));
837 xaw_set_label(help_wonder_obsolete_data, Q_("?tech:None"));
838 create_tech_tree(help_tech_tree, 0, advance_count(), 3);
839 }
840 set_title_topic(pitem);
841 helptext_building(buf, sizeof(buf), client.conn.playing, pitem->text, imp);
842 XtVaSetValues(help_text, XtNstring, buf, NULL);
843 }
844
845 /**************************************************************************
846 ...
847 **************************************************************************/
help_update_unit_type(const struct help_item * pitem,char * title)848 static void help_update_unit_type(const struct help_item *pitem,
849 char *title)
850 {
851 char buf[64000];
852 struct unit_type *punittype = unit_type_by_translated_name(title);
853
854 create_help_page(HELP_UNIT);
855 if (punittype) {
856 /* struct unit_type *punittype = utype_by_number(i);*/
857 sprintf(buf, "%d ", utype_build_shield_cost(punittype));
858 xaw_set_label(help_unit_cost_data, buf);
859 sprintf(buf, "%d ", punittype->attack_strength);
860 xaw_set_label(help_unit_attack_data, buf);
861 sprintf(buf, "%d ", punittype->defense_strength);
862 xaw_set_label(help_unit_def_data, buf);
863 sprintf(buf, "%s ", move_points_text(punittype->move_rate, TRUE));
864 xaw_set_label(help_unit_move_data, buf);
865 sprintf(buf, "%d ", punittype->firepower);
866 xaw_set_label(help_unit_fp_data, buf);
867 sprintf(buf, "%d ", punittype->hp);
868 xaw_set_label(help_unit_hp_data, buf);
869 sprintf(buf, "%d ", (int)sqrt((double)punittype->vision_radius_sq));
870 xaw_set_label(help_unit_visrange_data, buf);
871 xaw_set_label(help_unit_upkeep_data,
872 helptext_unit_upkeep_str(punittype));
873 if (A_NEVER == punittype->require_advance) {
874 xaw_set_label(help_improvement_req_data, _("(Never)"));
875 } else {
876 xaw_set_label(help_improvement_req_data,
877 research_advance_name_translation
878 (research_get(client_player()),
879 advance_number(punittype->require_advance)));
880 }
881 create_tech_tree(help_tech_tree, 0, advance_number(punittype->require_advance), 3);
882 if (U_NOT_OBSOLETED == punittype->obsoleted_by) {
883 xaw_set_label(help_wonder_obsolete_data, Q_("?tech:None"));
884 } else {
885 xaw_set_label(help_wonder_obsolete_data,
886 utype_name_translation(punittype->obsoleted_by));
887 }
888 /* add text for transport_capacity, fuel, and flags: */
889 helptext_unit(buf, sizeof(buf), client.conn.playing, pitem->text, punittype);
890 XtVaSetValues(help_text, XtNstring, buf, NULL);
891 }
892 else {
893 xaw_set_label(help_unit_cost_data, "0 ");
894 xaw_set_label(help_unit_attack_data, "0 ");
895 xaw_set_label(help_unit_def_data, "0 ");
896 xaw_set_label(help_unit_move_data, "0 ");
897 xaw_set_label(help_unit_fp_data, "0 ");
898 xaw_set_label(help_unit_hp_data, "0 ");
899 xaw_set_label(help_unit_visrange_data, "0 ");
900 xaw_set_label(help_improvement_req_data, _("(Never)"));
901 create_tech_tree(help_tech_tree, 0, advance_count(), 3);
902 xaw_set_label(help_wonder_obsolete_data, Q_("?tech:None"));
903 XtVaSetValues(help_text, XtNstring, pitem->text, NULL);
904 }
905 xaw_set_bitmap(help_unit_tile, create_overlay_unit(punittype));
906 set_title_topic(pitem);
907 }
908
909 /**************************************************************************
910 ...
911 **************************************************************************/
help_update_tech(const struct help_item * pitem,char * title)912 static void help_update_tech(const struct help_item *pitem, char *title)
913 {
914 char buf[4096];
915 int i;
916 struct advance *padvance = advance_by_translated_name(title);
917
918 create_help_page(HELP_TECH);
919 set_title_topic(pitem);
920
921 if (padvance && !is_future_tech(i = advance_number(padvance))) {
922 create_tech_tree(help_tech_tree, 0, i, 3);
923 helptext_advance(buf, sizeof(buf), client.conn.playing, pitem->text, i);
924
925 improvement_iterate(pimprove) {
926 /*if (i == j->tech_req)
927 sprintf(buf+strlen(buf), _("Allows %s.\n"),
928 improvement_name_translation(j));
929 */
930
931 /* FIXME: need a more general mechanism for this, since this
932 * helptext needs to be shown in all possible req source types. */
933 requirement_vector_iterate(&pimprove->reqs, preq) {
934 if (VUT_IMPROVEMENT == preq->source.kind
935 && preq->source.value.building == pimprove) {
936 sprintf(buf+strlen(buf), _("Allows %s.\n"),
937 improvement_name_translation(pimprove));
938 }
939 } requirement_vector_iterate_end;
940 requirement_vector_iterate(&pimprove->obsolete_by, pobs) {
941 if (pobs->source.kind == VUT_ADVANCE
942 && pobs->source.value.advance == padvance) {
943 sprintf(buf+strlen(buf), _("Obsoletes %s.\n"),
944 improvement_name_translation(pimprove));
945 }
946 } requirement_vector_iterate_end;
947 } improvement_iterate_end;
948
949 unit_type_iterate(punittype) {
950 if (padvance != punittype->require_advance) {
951 continue;
952 }
953 sprintf(buf + strlen(buf), _("Allows %s.\n"),
954 utype_name_translation(punittype));
955 } unit_type_iterate_end;
956
957 advance_iterate(A_NONE, ptest) {
958 if (padvance == advance_requires(ptest, AR_ONE)) {
959 if (advance_by_number(A_NONE) == advance_requires(ptest, AR_TWO))
960 sprintf(buf+strlen(buf), _("Allows %s.\n"),
961 advance_name_translation(ptest));
962 else
963 sprintf(buf+strlen(buf), _("Allows %s (with %s).\n"),
964 advance_name_translation(ptest),
965 advance_name_translation(advance_requires(ptest, AR_TWO)));
966 }
967 if (padvance == advance_requires(ptest, AR_TWO)) {
968 sprintf(buf+strlen(buf), _("Allows %s (with %s).\n"),
969 advance_name_translation(ptest),
970 advance_name_translation(advance_requires(ptest, AR_ONE)));
971 }
972 } advance_iterate_end;
973 if (strlen(buf)) strcat(buf, "\n");
974 /*
975 if (advances[i].helptext) {
976 sprintf(buf+strlen(buf), "%s\n", _(advances[i].helptext));
977 }
978 */
979 } else {
980 create_help_page(HELP_TECH);
981 create_tech_tree(help_tech_tree, 0, advance_count(), 3);
982 strcpy(buf, pitem->text);
983 }
984 fc_break_lines(buf, 68);
985 XtVaSetValues(help_text, XtNstring, buf, NULL);
986 }
987
988 /**************************************************************************
989 ...
990 **************************************************************************/
help_update_terrain(const struct help_item * pitem,char * title)991 static void help_update_terrain(const struct help_item *pitem,
992 char *title)
993 {
994 char buf[4096];
995 struct terrain *pterrain = terrain_by_translated_name(title);
996
997 create_help_page(HELP_TERRAIN);
998 set_title_topic(pitem);
999
1000 helptext_terrain(buf, sizeof(buf), client.conn.playing, pitem->text, pterrain);
1001 XtVaSetValues(help_text, XtNstring, buf, NULL);
1002
1003 if (pterrain) {
1004 sprintf(buf, "%d/%d.%d",
1005 pterrain->movement_cost,
1006 (int)((pterrain->defense_bonus + 100) / 100),
1007 (pterrain->defense_bonus + 100) % 100 / 10);
1008 xaw_set_label(help_terrain_movement_defense_data, buf);
1009
1010 sprintf(buf, "%d/%d/%d",
1011 pterrain->output[O_FOOD],
1012 pterrain->output[O_SHIELD],
1013 pterrain->output[O_TRADE]);
1014 xaw_set_label(help_terrain_food_shield_trade_data, buf);
1015
1016 buf[0] = '\0';
1017 if (*(pterrain->resources)) {
1018 struct resource **r;
1019
1020 for (r = pterrain->resources; *r; r++) {
1021 /* TRANS: " Whales (2/1/2)," */
1022 sprintf (buf + strlen (buf), " %s (%d/%d/%d),",
1023 resource_name_translation(*r),
1024 pterrain->output[O_FOOD] + (*r)->output[O_FOOD],
1025 pterrain->output[O_SHIELD] + (*r)->output[O_SHIELD],
1026 pterrain->output[O_TRADE] + (*r)->output[O_TRADE]);
1027 }
1028 buf[strlen (buf) - 1] = '.';
1029 } else {
1030 /* TRANS: "Resources: (none)". */
1031 sprintf (buf + strlen (buf), _("(none)"));
1032 }
1033 xaw_set_label(help_terrain_resources, buf);
1034
1035 sprintf(buf, "%d%%/%d%%/%d%% / %d",
1036 pterrain->road_output_incr_pct[O_FOOD],
1037 pterrain->road_output_incr_pct[O_SHIELD],
1038 pterrain->road_output_incr_pct[O_TRADE],
1039 pterrain->road_time);
1040 xaw_set_label(help_terrain_road_result_time_data, buf);
1041
1042 strcpy(buf, _("n/a"));
1043 if (pterrain->irrigation_result == pterrain) {
1044 if (pterrain->irrigation_food_incr > 0) {
1045 sprintf(buf, _("+%d Food / %d"),
1046 pterrain->irrigation_food_incr,
1047 pterrain->irrigation_time);
1048 }
1049 } else if (pterrain->irrigation_result != T_NONE) {
1050 sprintf(buf, "%s / %d",
1051 terrain_name_translation(pterrain->irrigation_result),
1052 pterrain->irrigation_time);
1053 }
1054 xaw_set_label(help_terrain_irrigation_result_time_data, buf);
1055
1056 strcpy(buf, _("n/a"));
1057 if (pterrain->mining_result == pterrain) {
1058 if (pterrain->mining_shield_incr > 0) {
1059 sprintf(buf, _("+%d Res. / %d"),
1060 pterrain->mining_shield_incr,
1061 pterrain->mining_time);
1062 }
1063 } else if (pterrain->mining_result != T_NONE) {
1064 sprintf(buf, "%s / %d",
1065 terrain_name_translation(pterrain->mining_result),
1066 pterrain->mining_time);
1067 }
1068 xaw_set_label (help_terrain_mining_result_time_data, buf);
1069
1070 if (pterrain->transform_result != T_NONE) {
1071 sprintf(buf, "%s / %d",
1072 terrain_name_translation(pterrain->transform_result),
1073 pterrain->transform_time);
1074 } else {
1075 strcpy(buf, _("n/a"));
1076 }
1077 xaw_set_label (help_terrain_transform_result_time_data, buf);
1078 }
1079 }
1080
1081 /**************************************************************************
1082 Help page for extras.
1083 **************************************************************************/
help_update_extra(const struct help_item * pitem,char * title)1084 static void help_update_extra(const struct help_item *pitem,
1085 char *title)
1086 {
1087 char buf[4096];
1088 struct extra_type *pextra = extra_type_by_translated_name(title);
1089
1090 buf[0] = '\0';
1091 if (pextra == NULL) {
1092 strcat(buf, pitem->text);
1093 } else {
1094 struct road_type *proad = extra_road_get(pextra);
1095
1096 /* FIXME use actual widgets */
1097 const char *sep = "";
1098
1099 buf[0] = '\0';
1100 if (pextra->buildable && pextra->build_time > 0) {
1101 /* TRANS: Build cost for bases in help. "MP" = movement points */
1102 sprintf(buf, _("Build: %d MP\n"), pextra->build_time);
1103 }
1104 /* TRANS: Base conflicts in help. Will be followed by a list of bases
1105 * that can't be built on the same tile as this one. */
1106 sprintf(buf + strlen(buf), _("Conflicts with: "));
1107 extra_type_iterate(pextra2) {
1108 if (!can_extras_coexist(pextra, pextra2)) {
1109 strcat(buf, sep);
1110 strcat(buf, extra_name_translation(pextra2));
1111 sep = "/";
1112 }
1113 } extra_type_iterate_end;
1114 if (!*sep) {
1115 /* TRANS: "Conflicts with: (none)" (extras) */
1116 strcat(buf, _("(none)"));
1117 }
1118 if (buf[0] != '\0') {
1119 strcat(buf, "\n");
1120 }
1121
1122 if (proad != NULL) {
1123 bool terrain_specific = FALSE;
1124
1125 output_type_iterate(o) {
1126 if (proad->tile_incr[o] > 0) {
1127 terrain_specific = TRUE;
1128 break;
1129 }
1130 } output_type_iterate_end;
1131 if (!terrain_specific) {
1132 /* TRANS: Road bonus in help. %s is food/production/trade
1133 * stats like "0/0/+1", "0/+50%/0" */
1134 sprintf(buf + strlen(buf), _("Bonus (F/P/T): %s\n"),
1135 helptext_road_bonus_str(NULL, proad));
1136 }
1137 }
1138 if (buf[0] != '\0') {
1139 strcat(buf, "\n");
1140 }
1141 helptext_extra(buf + strlen(buf), sizeof(buf) - strlen(buf),
1142 client.conn.playing, pitem->text, pextra);
1143 }
1144 create_help_page(HELP_TEXT);
1145 set_title_topic(pitem);
1146 XtVaSetValues(help_text, XtNstring, buf, NULL);
1147 }
1148
1149 /**************************************************************************
1150 This is currently just a text page, with special text:
1151 **************************************************************************/
help_update_specialist(const struct help_item * pitem,char * title)1152 static void help_update_specialist(const struct help_item *pitem,
1153 char *title)
1154 {
1155 char buf[4096];
1156 struct specialist *pspecialist = specialist_by_translated_name(title);
1157
1158 if (!pspecialist) {
1159 strcat(buf, pitem->text);
1160 } else {
1161 helptext_specialist(buf, sizeof(buf), client.conn.playing, pitem->text,
1162 pspecialist);
1163 }
1164 create_help_page(HELP_TEXT);
1165 set_title_topic(pitem);
1166 XtVaSetValues(help_text, XtNstring, buf, NULL);
1167 }
1168
1169 /**************************************************************************
1170 This is currently just a text page, with special text:
1171 **************************************************************************/
help_update_government(const struct help_item * pitem,char * title)1172 static void help_update_government(const struct help_item *pitem,
1173 char *title)
1174 {
1175 char buf[4096];
1176 struct government *pgovernment = government_by_translated_name(title);
1177
1178 if (!pgovernment) {
1179 strcat(buf, pitem->text);
1180 } else {
1181 helptext_government(buf, sizeof(buf), client.conn.playing, pitem->text, pgovernment);
1182 }
1183 create_help_page(HELP_TEXT);
1184 set_title_topic(pitem);
1185 XtVaSetValues(help_text, XtNstring, buf, NULL);
1186 }
1187
1188 /****************************************************************************
1189 This is currently just a text page, with special text
1190 ****************************************************************************/
help_update_nation(const struct help_item * pitem,char * title,struct nation_type * pnation)1191 static void help_update_nation(const struct help_item *pitem, char *title,
1192 struct nation_type *pnation)
1193 {
1194 char buf[4096];
1195
1196 if (!pnation) {
1197 strcat(buf, pitem->text);
1198 } else {
1199 helptext_nation(buf, sizeof(buf), pnation, pitem->text);
1200 }
1201 create_help_page(HELP_TEXT);
1202 set_title_topic(pitem);
1203 XtVaSetValues(help_text, XtNstring, buf, NULL);
1204 }
1205
1206 /**************************************************************************
1207 ...
1208 **************************************************************************/
help_update_dialog(const struct help_item * pitem)1209 static void help_update_dialog(const struct help_item *pitem)
1210 {
1211 char *top;
1212
1213 /* figure out what kind of item is required for pitem ingo */
1214
1215 for (top = pitem->topic; *top == ' '; top++) {
1216 /* nothing */
1217 }
1218
1219 switch(pitem->type) {
1220 case HELP_IMPROVEMENT:
1221 help_update_improvement(pitem, top);
1222 break;
1223 case HELP_WONDER:
1224 help_update_wonder(pitem, top);
1225 break;
1226 case HELP_UNIT:
1227 help_update_unit_type(pitem, top);
1228 break;
1229 case HELP_TECH:
1230 help_update_tech(pitem, top);
1231 break;
1232 case HELP_TERRAIN:
1233 help_update_terrain(pitem, top);
1234 break;
1235 case HELP_EXTRA:
1236 help_update_extra(pitem, top);
1237 break;
1238 case HELP_SPECIALIST:
1239 help_update_specialist(pitem, top);
1240 break;
1241 case HELP_GOVERNMENT:
1242 help_update_government(pitem, top);
1243 break;
1244 case HELP_NATIONS:
1245 help_update_nation(pitem, top, nation_by_translated_plural(top));
1246 break;
1247 case HELP_TEXT:
1248 default:
1249 /* it was a pure text item */
1250 create_help_page(HELP_TEXT);
1251 set_title_topic(pitem);
1252 XtVaSetValues(help_text, XtNstring, pitem->text, NULL);
1253 }
1254
1255 if (help_tree_viewport) {
1256 /* Buggy sun athena may require this? --dwp */
1257 /* And it possibly looks better anyway... */
1258 XtVaSetValues(help_tree_viewport, XtNforceBars, True, NULL);
1259 }
1260 }
1261
1262 /**************************************************************************
1263 ...
1264 **************************************************************************/
help_tree_destroy_children(Widget w)1265 static int help_tree_destroy_children(Widget w)
1266 {
1267 Widget *children=0;
1268 Cardinal cnt;
1269 int did_destroy=0;
1270
1271 XtVaGetValues(help_tech_tree,
1272 XtNchildren, &children,
1273 XtNnumChildren, &cnt,
1274 NULL);
1275
1276 for (; cnt > 0; cnt--, children++) {
1277 if(XtIsSubclass(*children, commandWidgetClass)) {
1278 Widget par;
1279 XtVaGetValues(*children, XtNtreeParent, &par, NULL);
1280 if(par==w) {
1281 help_tree_destroy_children(*children);
1282 XtDestroyWidget(*children);
1283 did_destroy=1;
1284 }
1285 }
1286 }
1287
1288 return did_destroy;
1289 }
1290
1291
1292 /**************************************************************************
1293 ...
1294 **************************************************************************/
help_tree_node_callback(Widget w,XtPointer client_data,XtPointer call_data)1295 static void help_tree_node_callback(Widget w, XtPointer client_data,
1296 XtPointer call_data)
1297 {
1298 size_t tech=(size_t)client_data;
1299
1300 if(!help_tree_destroy_children(w)) {
1301 if(advance_required(tech, AR_ONE)!=A_NONE)
1302 create_tech_tree(help_tech_tree, w, advance_required(tech, AR_ONE), 1);
1303 if(advance_required(tech, AR_TWO)!=A_NONE)
1304 create_tech_tree(help_tech_tree, w, advance_required(tech, AR_TWO), 1);
1305 }
1306
1307 }
1308
1309
1310 /**************************************************************************
1311 ...
1312 **************************************************************************/
help_list_callback(Widget w,XtPointer client_data,XtPointer call_data)1313 static void help_list_callback(Widget w, XtPointer client_data,
1314 XtPointer call_data)
1315 {
1316 XawListReturnStruct *ret;
1317
1318 ret=XawListShowCurrent(help_list);
1319
1320 if(ret->list_index!=XAW_LIST_NONE) {
1321 const struct help_item *pitem=get_help_item(ret->list_index);
1322 if(pitem) {
1323 help_update_dialog(pitem);
1324 set_title_topic(pitem);
1325 }
1326 XawListHighlight(help_list, ret->list_index);
1327 }
1328 }
1329
1330 /**************************************************************************
1331 ...
1332 **************************************************************************/
help_close_command_callback(Widget w,XtPointer client_data,XtPointer call_data)1333 static void help_close_command_callback(Widget w, XtPointer client_data,
1334 XtPointer call_data)
1335 {
1336 XtDestroyWidget(help_dialog_shell);
1337 help_dialog_shell=0;
1338 }
1339
1340 /****************************************************************
1341 ...
1342 *****************************************************************/
helpdlg_msg_close(Widget w)1343 void helpdlg_msg_close(Widget w)
1344 {
1345 help_close_command_callback(w, NULL, NULL);
1346 }
1347
1348 /**************************************************************************
1349 ...
1350 **************************************************************************/
select_help_item(int item)1351 static void select_help_item(int item)
1352 {
1353 int nitems, pos;
1354 Dimension height;
1355
1356 XtVaGetValues(help_list, XtNnumberStrings, &nitems, NULL);
1357 XtVaGetValues(help_list, XtNheight, &height, NULL);
1358 pos= (((double)item)/nitems)*height;
1359 XawViewportSetCoordinates(help_viewport, 0, pos);
1360 XawListHighlight(help_list, item);
1361 }
1362
1363 /****************************************************************
1364 ...
1365 *****************************************************************/
select_help_item_string(const char * item,enum help_page_type htype)1366 static void select_help_item_string(const char *item,
1367 enum help_page_type htype)
1368 {
1369 const struct help_item *pitem;
1370 int idx;
1371
1372 pitem = get_help_item_spec(item, htype, &idx);
1373 if(idx==-1) idx = 0;
1374 select_help_item(idx);
1375 help_update_dialog(pitem);
1376 }
1377