Partially updated en_GB translation for S2_5.
[freeciv.git] / tools / civmanual.c
blob29d30c117b9f995dda3a7f5bbe09498ae436211e
1 /**********************************************************************
2 Freeciv - Copyright (C) 2004 - The Freeciv Project
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.
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 ***********************************************************************/
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
18 #include <assert.h>
19 #include <stdarg.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
24 #ifdef HAVE_SIGNAL_H
25 #include <signal.h>
26 #endif
28 /* utility */
29 #include "capability.h"
30 #include "fciconv.h"
31 #include "fcintl.h"
32 #include "log.h"
33 #include "mem.h"
34 #include "registry.h"
35 #include "shared.h"
36 #include "support.h"
38 /* common */
39 #include "connection.h"
40 #include "events.h"
41 #include "fc_cmdhelp.h"
42 #include "fc_types.h" /* LINE_BREAK */
43 #include "game.h"
44 #include "government.h"
45 #include "improvement.h"
46 #include "map.h"
47 #include "player.h"
48 #include "version.h"
50 /* client */
51 #include "client_main.h"
52 #include "climisc.h"
53 #include "helpdata.h"
54 #include "helpdlg_g.h"
56 /* server */
57 #include "citytools.h"
58 #include "commands.h"
59 #include "connecthand.h"
60 #include "console.h"
61 #include "diplhand.h"
62 #include "gamehand.h"
63 #include "plrhand.h"
64 #include "report.h"
65 #include "ruleset.h"
66 #include "settings.h"
67 #include "sernet.h"
68 #include "srv_main.h"
69 #include "stdinhand.h"
71 enum manuals {
72 MANUAL_SETTINGS,
73 MANUAL_COMMANDS,
74 MANUAL_TERRAIN,
75 MANUAL_BUILDINGS,
76 MANUAL_WONDERS,
77 MANUAL_GOVS,
78 MANUAL_COUNT
81 /* This formats the manual for an HTML wiki. */
82 #ifdef USE_HTML
83 #define HEADER "<html><head><link rel=\"stylesheet\" type=\"text/css\" "\
84 "href=\"manual.css\"/><meta http-equiv=\"Content-Type\" "\
85 "content=\"text/html; charset=UTF-8\"/></head><body>\n\n"
86 #define SECTION_BEGIN "<h3>"
87 #define SECTION_END "</h3>"
88 #define IMAGE_BEGIN "<img src=\""
89 #define IMAGE_END ".png\">"
90 #define SEPARATOR " "
91 #define TAIL "</body></html>"
92 #else
93 #define HEADER " "
94 #define SECTION_BEGIN "==="
95 #define SECTION_END "==="
96 #define IMAGE_BEGIN "[[Image:"
97 #define IMAGE_END ".png]]"
98 #define SEPARATOR "----\n\n"
99 #define TAIL " "
100 #endif
102 /* Needed for "About Freeciv" help */
103 const char *client_string = "freeciv-manual";
105 static char *ruleset = NULL;
107 /**************************************************************************
108 Replace html special characters ('&', '<' and '>').
109 **************************************************************************/
110 static char *html_special_chars(char *str, size_t *len)
112 char *buf;
114 buf = fc_strrep_resize(str, len, "&", "&amp;");
115 buf = fc_strrep_resize(buf, len, "<", "&lt;");
116 buf = fc_strrep_resize(buf, len, ">", "&gt;");
118 return buf;
121 /**************************************************************************
122 Useless stubs for compiling client code.
123 **************************************************************************/
124 void popup_help_dialog_string(const char *item)
126 /* Empty stub. */
129 void popdown_help_dialog(void)
131 /* Empty stub. */
134 enum client_states client_state(void)
136 return C_S_INITIAL;
139 bool client_nation_is_in_current_set(const struct nation_type *pnation)
141 /* Currently, there is no way to select a nation set for freeciv-manual.
142 * Then, let's assume we want to print help for all nations. */
143 return TRUE;
146 /**************************************************************************
147 Write a server manual in html format, then quit.
148 **************************************************************************/
149 static bool manual_command(void)
151 FILE *doc;
152 char filename[40];
153 enum manuals manuals;
154 struct connection my_conn;
156 /* Default client access. */
157 connection_common_init(&my_conn);
158 my_conn.access_level = ALLOW_CTRL;
160 /* Reset aifill to zero */
161 game.info.aifill = 0;
163 if (!load_rulesets(NULL, FALSE)) {
164 /* Failed to load correct ruleset */
165 return FALSE;
168 for (manuals = 0; manuals < MANUAL_COUNT; manuals++) {
169 int i;
170 int ri;
172 fc_snprintf(filename, sizeof(filename), "manual%d.html", manuals + 1);
174 if (!is_reg_file_for_access(filename, TRUE)
175 || !(doc = fc_fopen(filename, "w"))) {
176 log_error(_("Could not write manual file %s."), filename);
177 return FALSE;
180 fprintf(doc, HEADER);
181 fprintf(doc, "<!-- Generated by freeciv-manual version %s -->\n\n",
182 freeciv_datafile_version());
184 switch (manuals) {
185 case MANUAL_SETTINGS:
186 fprintf(doc, _("<h1>Freeciv %s server options</h1>\n\n"), VERSION_STRING);
187 settings_iterate(SSET_ALL, pset) {
188 char buf[256];
190 fprintf(doc, SEPARATOR);
191 fprintf(doc, "%s%s - %s%s\n\n", SECTION_BEGIN, setting_name(pset),
192 _(setting_short_help(pset)), SECTION_END);
193 if (strlen(setting_extra_help(pset)) > 0) {
194 char *help = fc_strdup(_(setting_extra_help(pset)));
195 size_t help_len = strlen(help) + 1;
197 fc_break_lines(help, LINE_BREAK);
198 help = html_special_chars(help, &help_len);
199 fprintf(doc, "<pre>%s</pre>\n\n", help);
200 FC_FREE(help);
202 fprintf(doc, "<p class=\"misc\">");
203 fprintf(doc, _("Level: %s.<br>"),
204 _(sset_level_name(setting_level(pset))));
205 fprintf(doc, _("Category: %s.<br>"),
206 _(sset_category_name(setting_category(pset))));
208 /* first check if the setting is locked because this is included in
209 * the function setting_is_changeable() */
210 if (setting_locked(pset)) {
211 fprintf(doc, _("Is locked by the ruleset."));
212 } else if (!setting_is_changeable(pset, &my_conn, NULL, 0)) {
213 fprintf(doc, _("Can only be used in server console."));
216 fprintf(doc, "</p>\n\n");
217 setting_default_name(pset, TRUE, buf, sizeof(buf));
218 switch (setting_type(pset)) {
219 case SSET_INT:
220 fprintf(doc, "<p class=\"bounds\">%s %d, %s %s, %s %d</p>\n\n",
221 _("Minimum:"), setting_int_min(pset),
222 _("Default:"), buf,
223 _("Maximum:"), setting_int_max(pset));
224 break;
225 case SSET_ENUM:
227 const char *value;
229 fprintf(doc, "<p class=\"bounds\">%s</p>\n",
230 _("Possible values:"));
231 for (i = 0; (value = setting_enum_val(pset, i, FALSE)); i++) {
232 fprintf(doc, "<p class=\"bounds\"><li/> %s: \"%s\"</p>\n",
233 value, setting_enum_val(pset, i, TRUE));
236 break;
237 case SSET_BITWISE:
239 const char *value;
241 fprintf(doc, "<p class=\"bounds\">%s</p>\n",
242 _("Possible values (option can take any number of these):"));
243 for (i = 0; (value = setting_bitwise_bit(pset, i, FALSE)); i++) {
244 fprintf(doc, "<p class=\"bounds\"><li/> %s: \"%s\"</p>\n",
245 value, setting_bitwise_bit(pset, i, TRUE));
248 break;
249 case SSET_BOOL:
250 case SSET_STRING:
251 break;
253 if (SSET_INT != setting_type(pset)) {
254 fprintf(doc, "<p class=\"bounds\">%s %s</p>\n\n",
255 _("Default:"), buf);
257 if (setting_changed(pset)) {
258 fprintf(doc, _("<p class=\"changed\">Value set to %s</p>\n\n"),
259 setting_value_name(pset, TRUE, buf, sizeof(buf)));
261 } settings_iterate_end;
262 break;
264 case MANUAL_COMMANDS:
265 fprintf(doc, _("<h1>Freeciv %s server commands</h1>\n\n"),
266 VERSION_STRING);
267 for (i = 0; i < CMD_NUM; i++) {
268 const struct command *cmd = command_by_number(i);
270 fprintf(doc, SEPARATOR);
271 fprintf(doc, "%s%s - %s%s\n\n", SECTION_BEGIN, command_name(cmd),
272 command_short_help(cmd), SECTION_END);
273 if (command_synopsis(cmd)) {
274 char *cmdstr = fc_strdup(command_synopsis(cmd));
275 size_t cmdstr_len = strlen(cmdstr) + 1;
277 cmdstr = html_special_chars(cmdstr, &cmdstr_len);
278 fprintf(doc, _("<table>\n<tr>\n<td valign=\"top\">"
279 "<pre>Synopsis:</pre></td>\n<td>"));
280 fprintf(doc, "<pre>%s</pre></td></tr></table>", cmdstr);
281 FC_FREE(cmdstr);
283 fprintf(doc, _("<p class=\"level\">Level: %s</p>\n\n"),
284 cmdlevel_name(command_level(cmd)));
286 char *help = command_extra_help(cmd);
287 if (help) {
288 size_t help_len = strlen(help) + 1;
290 fc_break_lines(help, LINE_BREAK);
291 help = html_special_chars(help, &help_len);
292 fprintf(doc, _("<p>Description:</p>\n\n"));
293 fprintf(doc, "<pre>%s</pre>\n\n", help);
294 FC_FREE(help);
298 break;
300 case MANUAL_TERRAIN:
301 fprintf(doc, _("<h1>Freeciv %s terrain help</h1>\n\n"),
302 VERSION_STRING);
303 fprintf(doc, "<table><tr bgcolor=#9bc3d1><th colspan=2>%s</th>", _("Terrain"));
304 fprintf(doc, "<th>F/P/T</th><th>%s</th>", _("Resources"));
305 fprintf(doc, "<th>%s<br/>%s</th>", _("Move cost"), _("Defense bonus"));
306 fprintf(doc, "<th>%s<br/>%s<br/>%s<br/>%s<br/>(%s)</th>",
307 _("Irrigation"), _("Mining"), _("Transform"),
308 /* xgettext:no-c-format */
309 _("% of Road bonus"), _("turns"));
310 fprintf(doc, "<th>%s<br/>%s</th>",
311 _("Clean pollution"), _("Clean fallout"));
312 ri = 0;
313 if (game.control.num_road_types > 0) {
314 fprintf(doc, "<th>");
316 road_type_iterate(proad) {
317 if (++ri < game.control.num_road_types) {
318 fprintf(doc, "%s<br/>", road_name_translation(proad));
319 } else {
320 /* Last one */
321 fprintf(doc, "%s</th>", road_name_translation(proad));
323 } road_type_iterate_end;
324 fprintf(doc, "</tr>\n\n");
325 terrain_type_iterate(pterrain) {
326 struct resource **r;
328 if (0 == strlen(terrain_rule_name(pterrain))) {
329 /* Must be a disabled piece of terrain */
330 continue;
333 fprintf(doc, "<tr><td>" IMAGE_BEGIN "%s" IMAGE_END "</td><td>%s</td>",
334 pterrain->graphic_str, terrain_name_translation(pterrain));
335 fprintf(doc, "<td>%d/%d/%d</td>\n",
336 pterrain->output[O_FOOD], pterrain->output[O_SHIELD],
337 pterrain->output[O_TRADE]);
339 fprintf(doc, "<td><table width=\"100%%\">\n");
340 for (r = pterrain->resources; *r; r++) {
341 fprintf(doc, "<tr><td>" IMAGE_BEGIN "%s" IMAGE_END "</td><td>%s</td>"
342 "<td align=\"right\">%d/%d/%d</td></tr>\n",
343 (*r)->graphic_str,
344 resource_name_translation(*r),
345 (*r)->output[O_FOOD],
346 (*r)->output[O_SHIELD],
347 (*r)->output[O_TRADE]);
349 fprintf(doc, "</table></td>\n");
351 fprintf(doc, "<td align=\"center\">%d<br/>+%d%%</td>\n",
352 pterrain->movement_cost, pterrain->defense_bonus);
354 fprintf(doc, "<td><table width=\"100%%\">\n");
355 if (pterrain->irrigation_result == pterrain) {
356 fprintf(doc, "<tr><td>+%d F</td><td align=\"right\">(%d)</td></tr>\n",
357 pterrain->irrigation_food_incr, pterrain->irrigation_time);
358 } else if (pterrain->irrigation_result == T_NONE) {
359 fprintf(doc, "<tr><td>%s</td></tr>\n", _("impossible"));
360 } else {
361 fprintf(doc, "<tr><td>%s</td><td align=\"right\">(%d)</td></tr>\n",
362 terrain_name_translation(pterrain->irrigation_result),
363 pterrain->irrigation_time);
365 if (pterrain->mining_result == pterrain) {
366 fprintf(doc, "<tr><td>+%d P</td><td align=\"right\">(%d)</td></tr>\n",
367 pterrain->mining_shield_incr, pterrain->mining_time);
368 } else if (pterrain->mining_result == T_NONE) {
369 fprintf(doc, "<tr><td>%s</td></tr>\n", _("impossible"));
370 } else {
371 fprintf(doc, "<tr><td>%s</td><td align=\"right\">(%d)</td></tr>\n",
372 terrain_name_translation(pterrain->mining_result),
373 pterrain->mining_time);
376 if (pterrain->transform_result) {
377 fprintf(doc, "<tr><td>%s</td><td align=\"right\">(%d)</td></tr>\n",
378 terrain_name_translation(pterrain->transform_result),
379 pterrain->transform_time);
380 } else {
381 fprintf(doc, "<tr><td>-</td><td align=\"right\">(-)</td></tr>\n");
383 fprintf(doc, "<tr><td>%d / %d / %d</td></tr>\n</table></td>\n",
384 pterrain->road_output_incr_pct[O_FOOD],
385 pterrain->road_output_incr_pct[O_SHIELD],
386 pterrain->road_output_incr_pct[O_TRADE]);
388 fprintf(doc, "<td align=\"center\">%d / %d</td>",
389 pterrain->clean_pollution_time, pterrain->clean_fallout_time);
391 ri = 0;
392 if (game.control.num_road_types > 0) {
393 fprintf(doc, "<td>");
395 road_type_iterate(proad) {
396 if (++ri < game.control.num_road_types) {
397 fprintf(doc, "%d / ", terrain_road_time(pterrain,
398 road_number(proad)));
399 } else {
400 fprintf(doc, "%d</td>", terrain_road_time(pterrain,
401 road_number(proad)));
403 } road_type_iterate_end;
404 fprintf(doc, "</tr>\n\n");
405 } terrain_type_iterate_end;
407 fprintf(doc, "</table>\n");
409 break;
411 case MANUAL_BUILDINGS:
412 case MANUAL_WONDERS:
413 if (manuals == MANUAL_BUILDINGS) {
414 fprintf(doc, _("<h1>Freeciv %s buildings help</h1>\n\n"), VERSION_STRING);
415 } else {
416 fprintf(doc, _("<h1>Freeciv %s wonders help</h1>\n\n"), VERSION_STRING);
419 fprintf(doc, "<table>\n<tr bgcolor=#9bc3d1><th colspan=2>%s</th>"
420 "<th>%s<br/>%s</th><th>%s<br/>%s</th><th>%s</th></tr>\n\n",
421 _("Name"), _("Cost"), _("Upkeep"),
422 _("Requirement"), _("Obsolete by"), _("More info"));
424 improvement_iterate(pimprove) {
425 char buf[64000];
427 if (!valid_improvement(pimprove)
428 || is_great_wonder(pimprove) == (manuals == MANUAL_BUILDINGS)) {
429 continue;
432 helptext_building(buf, sizeof(buf), NULL, NULL, pimprove);
434 fprintf(doc, "<tr><td>" IMAGE_BEGIN "%s" IMAGE_END "</td><td>%s</td>\n"
435 "<td align=\"center\"><b>%d</b><br/>%d</td>\n<td>",
436 pimprove->graphic_str,
437 improvement_name_translation(pimprove),
438 pimprove->build_cost,
439 pimprove->upkeep);
441 requirement_vector_iterate(&pimprove->reqs, req) {
442 char text[512], text2[512];
443 fc_snprintf(text2, sizeof(text2),
444 /* TRANS: improvement requires a feature to be absent. */
445 req->negated ? _("no %s") : "%s",
446 VUT_NONE != req->source.kind
447 ? universal_name_translation(&req->source,
448 text, sizeof(text))
449 : _("None"));
450 fprintf(doc, "%s<br/>", text2);
451 } requirement_vector_iterate_end;
453 fprintf(doc, "<em>%s</em></td>\n",
454 valid_advance(pimprove->obsolete_by)
455 ? advance_name_translation(pimprove->obsolete_by)
456 : _("None"));
457 fprintf(doc, "<td>%s</td>\n</tr>\n\n", buf);
458 } improvement_iterate_end;
459 break;
461 case MANUAL_GOVS:
462 /* FIXME: this doesn't resemble the wiki manual at all. */
463 fprintf(doc, _("<h1>Freeciv %s governments help</h1>\n\n"), VERSION_STRING);
464 governments_iterate(pgov) {
465 char buf[64000];
466 fprintf(doc, "%s%s%s\n\n", SECTION_BEGIN,
467 government_name_translation(pgov), SECTION_END);
468 helptext_government(buf, sizeof(buf), NULL, NULL, pgov);
469 fprintf(doc, "%s\n\n", buf);
470 } governments_iterate_end;
471 break;
473 case MANUAL_COUNT:
474 break;
476 } /* switch */
478 fprintf(doc, TAIL);
479 fclose(doc);
480 log_normal(_("Manual file %s successfully written."), filename);
481 } /* manuals */
483 return TRUE;
486 /**************************************************************************
487 Entry point of whole freeciv-manual program
488 **************************************************************************/
489 int main(int argc, char **argv)
491 int inx;
492 bool showhelp = FALSE;
493 bool showvers = FALSE;
494 char *option = NULL;
495 int retval = EXIT_SUCCESS;
497 init_nls();
498 registry_module_init();
499 init_character_encodings(FC_DEFAULT_DATA_ENCODING, FALSE);
501 /* Set the default log level. */
502 srvarg.loglevel = LOG_NORMAL;
504 /* parse command-line arguments... */
505 inx = 1;
506 while (inx < argc) {
507 if ((option = get_option_malloc("--ruleset", argv, &inx, argc))) {
508 if (ruleset != NULL) {
509 log_error(_("Multiple rulesets requested. Only one ruleset at time supported"));
510 free(option);
511 } else {
512 ruleset = option;
514 } else if (is_option("--help", argv[inx])) {
515 showhelp = TRUE;
516 break;
517 } else if (is_option("--version", argv[inx])) {
518 showvers = TRUE;
519 } else if ((option = get_option_malloc("--log", argv, &inx, argc))) {
520 srvarg.log_filename = option; /* Never freed. */
521 #ifndef NDEBUG
522 } else if (is_option("--Fatal", argv[inx])) {
523 if (inx + 1 >= argc || '-' == argv[inx + 1][0]) {
524 srvarg.fatal_assertions = SIGABRT;
525 } else if (str_to_int(argv[inx + 1], &srvarg.fatal_assertions)) {
526 inx++;
527 } else {
528 fc_fprintf(stderr, _("Invalid signal number \"%s\".\n"),
529 argv[inx + 1]);
530 inx++;
531 showhelp = TRUE;
533 #endif /* NDEBUG */
534 } else if ((option = get_option_malloc("--debug", argv, &inx, argc))) {
535 if (!log_parse_level_str(option, &srvarg.loglevel)) {
536 showhelp = TRUE;
537 break;
539 free(option);
540 } else {
541 fc_fprintf(stderr, _("Unrecognized option: \"%s\"\n"), argv[inx]);
542 exit(EXIT_FAILURE);
544 inx++;
547 /* must be before con_log_init() */
548 init_connections();
549 con_log_init(srvarg.log_filename, srvarg.loglevel,
550 srvarg.fatal_assertions);
551 /* logging available after this point */
553 /* Imitate a server - this is needed for as some function only work if this
554 * is set. */
555 i_am_server();
557 /* Initialize game with default values */
558 game_init();
560 /* Set ruleset user requested in to use */
561 if (ruleset != NULL) {
562 sz_strlcpy(game.server.rulesetdir, ruleset);
565 settings_init(FALSE);
567 if (showvers && !showhelp) {
568 fc_fprintf(stderr, "%s \n", freeciv_name_version());
569 exit(EXIT_SUCCESS);
570 } else if (showhelp) {
571 struct cmdhelp *help = cmdhelp_new(argv[0]);
573 #ifdef DEBUG
574 cmdhelp_add(help, "d",
575 /* TRANS: "debug" is exactly what user must type, do not translate. */
576 _("debug NUM"),
577 _("Set debug log level (%d to %d, or %d:file1,min,max:...)"),
578 LOG_FATAL, LOG_DEBUG, LOG_DEBUG);
579 #else
580 cmdhelp_add(help, "d",
581 /* TRANS: "debug" is exactly what user must type, do not translate. */
582 _("debug NUM"),
583 _("Set debug log level (%d to %d)"),
584 LOG_FATAL, LOG_VERBOSE);
585 #endif /* DEBUG */
586 #ifndef NDEBUG
587 cmdhelp_add(help, "F",
588 /* TRANS: "Fatal" is exactly what user must type, do not translate. */
589 _("Fatal [SIGNAL]"),
590 _("Raise a signal on failed assertion"));
591 #endif /* NDEBUG */
592 cmdhelp_add(help, "h", "help",
593 _("Print a summary of the options"));
594 cmdhelp_add(help, "l",
595 /* TRANS: "log" is exactly what user must type, do not translate. */
596 _("log FILE"),
597 _("Use FILE as logfile"));
598 cmdhelp_add(help, "r",
599 /* TRANS: "ruleset" is exactly what user must type, do not translate. */
600 _("ruleset RULESET"),
601 _("Make manual for RULESET"));
602 cmdhelp_add(help, "v", "version",
603 _("Print the version number"));
605 /* The function below prints a header and footer for the options.
606 * Furthermore, the options are sorted. */
607 cmdhelp_display(help, TRUE, FALSE, TRUE);
608 cmdhelp_destroy(help);
610 exit(EXIT_SUCCESS);
613 if (!manual_command()) {
614 retval = EXIT_FAILURE;
617 FC_FREE(ruleset);
619 con_log_close();
620 registry_module_close();
621 free_nls();
623 return retval;