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)
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 ***********************************************************************/
15 #include <fc_config.h>
22 #ifdef HAVE_LIBREADLINE
23 #include <readline/readline.h>
27 #include "fcbacktrace.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
;
48 static int con_dump(enum rfc_status rfc_status
, const char *message
, ...);
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
,
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;
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"),
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
);
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
)
93 #ifdef HAVE_LIBREADLINE
94 if (readline_received_enter
) {
95 readline_received_enter
= FALSE
;
97 rl_forced_update_display();
99 #else /* HAVE_LIBREADLINE */
100 con_dump(C_READY
,"> ");
102 #endif /* HAVE_LIBREADLINE */
104 console_prompt_is_showing
= TRUE
;
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];
121 strftime(timestr
, sizeof(timestr
), "%Y/%m/%d %H:%M:%S",
122 localtime(×tamp
));
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 */
134 /************************************************************************
135 Initialize logging via console.
136 ************************************************************************/
137 void con_log_init(const char *log_filename
, enum log_level level
,
138 int fatal_assertions
)
141 log_init(log_filename
, level
, con_handle_log
, log_prefix
,
144 log_init(log_filename
, level
, con_handle_log
, NULL
,
150 /************************************************************************
152 ************************************************************************/
153 void con_log_close(void)
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
];
169 va_start(args
, message
);
170 fc_vsnprintf(buf
, sizeof(buf
), message
, args
);
173 if (console_prompt_is_showing
) {
176 if ((console_rfcstyle
) && (rfc_status
>= 0)) {
177 fc_printf("%.3d %s", rfc_status
, buf
);
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
];
196 va_start(args
, message
);
197 fc_vsnprintf(buf1
, sizeof(buf1
), message
, 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
) {
217 if ((console_rfcstyle
) && (rfc_status
>= 0)) {
218 fc_printf("%.3d %s\n", rfc_status
, str
);
220 fc_printf("%s\n", str
);
222 console_prompt_is_showing
= FALSE
;
226 /************************************************************************
227 Ensure timely update.
228 ************************************************************************/
234 /************************************************************************
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."));
243 con_puts(C_OK
, _("Ok. Standard style set."));
246 /************************************************************************
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
;
262 con_puts(C_COMMENT
, "");
263 con_puts(C_COMMENT
, _("For introductory help, type 'help'."));
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
;
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
;
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
;