Some miscellaneous updates to main help, for new features and otherwise.
[freeciv.git] / server / console.c
blobabe36666250ea583d3d3d3da5cff76eafdd859ab
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.
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 <stdarg.h>
19 #include <stdio.h>
20 #include <string.h>
22 #ifdef HAVE_LIBREADLINE
23 #include <readline/readline.h>
24 #endif
26 /* utility */
27 #include "fcbacktrace.h"
28 #include "fciconv.h"
29 #include "fcintl.h"
30 #include "log.h"
31 #include "support.h"
33 /* common */
34 #include "game.h"
36 /* server */
37 #include "notify.h"
38 #include "srv_main.h"
40 #include "console.h"
42 static bool console_show_prompt = FALSE;
43 static bool console_prompt_is_showing = FALSE;
44 static bool console_rfcstyle = FALSE;
45 #ifdef HAVE_LIBREADLINE
46 static bool readline_received_enter = TRUE;
47 #else
48 static int con_dump(enum rfc_status rfc_status, const char *message, ...);
49 #endif
51 /************************************************************************
52 Function to handle log messages.
53 This must match the log_callback_fn typedef signature.
54 ************************************************************************/
55 static void con_handle_log(enum log_level level, const char *message,
56 bool file_too)
58 if (LOG_ERROR == level) {
59 notify_conn(NULL, NULL, E_LOG_ERROR, ftc_warning, "%s", message);
60 } else if (LOG_FATAL >= level) {
61 /* Make sure that message is not left to buffers when server dies */
62 conn_list_iterate(game.est_connections, pconn) {
63 pconn->send_buffer->do_buffer_sends = 0;
64 #ifdef USE_COMPRESSION
65 pconn->compression.frozen_level = 0;
66 #endif
67 } conn_list_iterate_end;
69 notify_conn(NULL, NULL, E_LOG_FATAL, ftc_warning, "%s", message);
70 notify_conn(NULL, NULL, E_LOG_FATAL, ftc_warning,
71 _("Please report this message at %s"),
72 BUG_URL);
75 /* Write debug/verbose message to console only when not written to file. */
76 if (!file_too || level <= LOG_NORMAL) {
77 if (console_rfcstyle) {
78 con_write(C_LOG_BASE + level, "%s", message);
79 } else {
80 con_write(C_LOG_BASE + level, "%d: %s", level, message);
85 /************************************************************************
86 Print the prompt if it is not the last thing printed.
87 ************************************************************************/
88 static void con_update_prompt(void)
90 if (console_prompt_is_showing || !console_show_prompt)
91 return;
93 #ifdef HAVE_LIBREADLINE
94 if (readline_received_enter) {
95 readline_received_enter = FALSE;
96 } else {
97 rl_forced_update_display();
99 #else /* HAVE_LIBREADLINE */
100 con_dump(C_READY,"> ");
101 con_flush();
102 #endif /* HAVE_LIBREADLINE */
104 console_prompt_is_showing = TRUE;
107 #ifdef DEBUG
108 /************************************************************************
109 Prefix for log messages saved to file. At the moment the turn and the
110 current date and time are used.
111 ************************************************************************/
112 static const char *log_prefix(void)
114 static char buf[128];
116 #ifdef LOG_TIMERS
117 char timestr[32];
118 time_t timestamp;
120 time(&timestamp);
121 strftime(timestr, sizeof(timestr), "%Y/%m/%d %H:%M:%S",
122 localtime(&timestamp));
124 fc_snprintf(buf, sizeof(buf), "T%03d - %s", game.info.turn, timestr);
126 #else /* LOG_TIMERS */
127 fc_snprintf(buf, sizeof(buf), "T%03d", game.info.turn);
128 #endif /* LOG_TIMERS */
130 return buf;
132 #endif /* DEBUG */
134 /************************************************************************
135 Initialize logging via console.
136 ************************************************************************/
137 void con_log_init(const char *log_filename, enum log_level level,
138 int fatal_assertions)
140 #ifdef DEBUG
141 log_init(log_filename, level, con_handle_log, log_prefix,
142 fatal_assertions);
143 #else
144 log_init(log_filename, level, con_handle_log, NULL,
145 fatal_assertions);
146 #endif /* DEBUG */
147 backtrace_init();
150 /************************************************************************
151 Deinitialize logging
152 ************************************************************************/
153 void con_log_close(void)
155 backtrace_deinit();
157 log_close();
160 #ifndef HAVE_LIBREADLINE
161 /************************************************************************
162 Write to console without line-break, don't print prompt.
163 ************************************************************************/
164 static int con_dump(enum rfc_status rfc_status, const char *message, ...)
166 static char buf[MAX_LEN_CONSOLE_LINE];
167 va_list args;
169 va_start(args, message);
170 fc_vsnprintf(buf, sizeof(buf), message, args);
171 va_end(args);
173 if (console_prompt_is_showing) {
174 fc_printf("\n");
176 if ((console_rfcstyle) && (rfc_status >= 0)) {
177 fc_printf("%.3d %s", rfc_status, buf);
178 } else {
179 fc_printf("%s", buf);
181 console_prompt_is_showing = FALSE;
182 return (int) strlen(buf);
184 #endif /* HAVE_LIBREADLINE */
186 /************************************************************************
187 Write to console and add line-break, and show prompt if required.
188 ************************************************************************/
189 void con_write(enum rfc_status rfc_status, const char *message, ...)
191 /* First buffer contains featured text tags */
192 static char buf1[(MAX_LEN_CONSOLE_LINE * 3) / 2];
193 static char buf2[MAX_LEN_CONSOLE_LINE];
194 va_list args;
196 va_start(args, message);
197 fc_vsnprintf(buf1, sizeof(buf1), message, args);
198 va_end(args);
200 /* remove all format tags */
201 featured_text_to_plain_text(buf1, buf2, sizeof(buf2), NULL, FALSE);
202 con_puts(rfc_status, buf2);
205 /************************************************************************
206 Write to console and add line-break, and show prompt if required.
207 Same as con_write, but without the format string stuff.
208 The real reason for this is because __attribute__ complained
209 with con_write(C_COMMENT,"") of "warning: zero-length format string";
210 this allows con_puts(C_COMMENT,"");
211 ************************************************************************/
212 void con_puts(enum rfc_status rfc_status, const char *str)
214 if (console_prompt_is_showing) {
215 fc_printf("\n");
217 if ((console_rfcstyle) && (rfc_status >= 0)) {
218 fc_printf("%.3d %s\n", rfc_status, str);
219 } else {
220 fc_printf("%s\n", str);
222 console_prompt_is_showing = FALSE;
223 con_update_prompt();
226 /************************************************************************
227 Ensure timely update.
228 ************************************************************************/
229 void con_flush(void)
231 fflush(stdout);
234 /************************************************************************
235 Set style.
236 ************************************************************************/
237 void con_set_style(bool i)
239 console_rfcstyle = i;
240 if (console_rfcstyle)
241 con_puts(C_OK, _("Ok. RFC-style set."));
242 else
243 con_puts(C_OK, _("Ok. Standard style set."));
246 /************************************************************************
247 Returns rfc-style.
248 ************************************************************************/
249 bool con_get_style(void)
251 return console_rfcstyle;
254 /************************************************************************
255 Initialize prompt; display initial message.
256 ************************************************************************/
257 void con_prompt_init(void)
259 static bool first = TRUE;
261 if (first) {
262 con_puts(C_COMMENT, "");
263 con_puts(C_COMMENT, _("For introductory help, type 'help'."));
264 first = FALSE;
268 /************************************************************************
269 Make sure a prompt is printed, and re-printed after every message.
270 ************************************************************************/
271 void con_prompt_on(void)
273 console_show_prompt = TRUE;
274 con_update_prompt();
277 /************************************************************************
278 Do not print a prompt after log messages.
279 ************************************************************************/
280 void con_prompt_off(void)
282 console_show_prompt = FALSE;
285 /************************************************************************
286 User pressed enter: will need a new prompt
287 ************************************************************************/
288 void con_prompt_enter(void)
290 console_prompt_is_showing = FALSE;
291 #ifdef HAVE_LIBREADLINE
292 readline_received_enter = TRUE;
293 #endif
296 /************************************************************************
297 Clear "user pressed enter" state (used in special cases).
298 ************************************************************************/
299 void con_prompt_enter_clear(void)
301 console_prompt_is_showing = TRUE;
302 #ifdef HAVE_LIBREADLINE
303 readline_received_enter = FALSE;
304 #endif