Freeciv-3.1
Loading...
Searching...
No Matches
luaconsole.c
Go to the documentation of this file.
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 <gdk/gdkkeysyms.h>
19
20/* utility */
21#include "fcintl.h"
22#include "log.h"
23#include "shared.h"
24
25/* common */
26#include "featured_text.h"
27#include "game.h"
28
29/* client */
30#include "options.h"
31
32/* client/gui-gtk-3.0 */
33#include "chatline.h"
34#include "gui_main.h"
35#include "gui_stuff.h"
36
37/* client/luascript */
38#include "script_client.h"
39
40#include "luaconsole.h"
41
45
46#define MAX_LUACONSOLE_HISTORY 20
47
50 GtkTextBuffer *message_buffer;
51 GtkTextView *message_area;
52 GtkWidget *entry;
53
56};
57
58static struct luaconsole_data *luaconsole = NULL;
59
60
61static struct luaconsole_data *luaconsole_dialog_get(void);
62static void luaconsole_dialog_create(struct luaconsole_data *pdialog);
63static void luaconsole_dialog_refresh(struct luaconsole_data *pdialog);
64static void luaconsole_dialog_destroy(struct luaconsole_data *pdialog);
65
66static void luaconsole_dialog_area_size_allocate(GtkWidget *widget,
67 GtkAllocation *allocation,
68 gpointer data);
70
71static void luaconsole_input_return(GtkEntry *w, gpointer data);
72static gboolean luaconsole_input_handler(GtkWidget *w, GdkEventKey *ev);
73
74static void luaconsole_response_callback(struct gui_dialog *pgui_dialog,
75 int response, gpointer data);
76static void luaconsole_load_file_popup(void);
77static void luaconsole_load_file_callback(GtkWidget *widget, gint response,
78 gpointer data);
79
80/*************************************************************************/
84{
86
87 /* Create a container for the dialog. */
88 luaconsole = fc_calloc(1, sizeof(*luaconsole));
89 luaconsole->message_buffer = gtk_text_buffer_new(NULL);
90 luaconsole->shell = NULL;
91
94
96}
97
98/*************************************************************************/
102{
103 if (luaconsole != NULL) {
106 }
107
109 free(luaconsole);
110
111 luaconsole = NULL;
112 }
113}
114
115/*************************************************************************/
119{
120 return luaconsole;
121}
122
123/*************************************************************************/
127{
128 struct luaconsole_data *pdialog = luaconsole_dialog_get();
129
130 fc_assert_ret(pdialog);
131 if (pdialog->shell == NULL) {
133 }
134
135 gui_dialog_present(pdialog->shell);
136 if (raise) {
137 gui_dialog_raise(pdialog->shell);
138 }
139}
140
141/*************************************************************************/
145{
146 struct luaconsole_data *pdialog = luaconsole_dialog_get();
147
148 fc_assert_ret(pdialog);
149 if (pdialog->shell == NULL) {
151 }
152}
153
154/*************************************************************************/
158{
159 struct luaconsole_data *pdialog = luaconsole_dialog_get();
160
161 fc_assert_ret_val(pdialog, FALSE);
162
163 return (NULL != pdialog->shell);
164}
165
166/*************************************************************************/
170{
171 struct luaconsole_data *pdialog = luaconsole_dialog_get();
172
173 fc_assert_ret(pdialog);
174
175 if (NULL != pdialog->shell) {
177 }
178}
179
180/*************************************************************************/
183static void luaconsole_dialog_create(struct luaconsole_data *pdialog)
184{
185 GtkWidget *entry, *box, *vbox, *sw, *text, *notebook;
186
187 fc_assert_ret(NULL != pdialog);
188
189 if (GUI_GTK_OPTION(message_chat_location) == GUI_GTK_MSGCHAT_SPLIT) {
190 notebook = right_notebook;
191 } else {
192 notebook = bottom_notebook;
193 }
194
195 gui_dialog_new(&pdialog->shell, GTK_NOTEBOOK(notebook), pdialog, TRUE);
196 gui_dialog_set_title(pdialog->shell, _("Client Lua Console"));
197
198 box = pdialog->shell->vbox;
199
200 vbox = gtk_grid_new();
201 gtk_orientable_set_orientation(GTK_ORIENTABLE(vbox),
202 GTK_ORIENTATION_VERTICAL);
203 gtk_container_add(GTK_CONTAINER(box), vbox);
204
205 sw = gtk_scrolled_window_new(NULL, NULL);
206 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw),
207 GTK_SHADOW_ETCHED_IN);
208 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
209 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
210 gtk_container_add(GTK_CONTAINER(vbox), sw);
211
212 text = gtk_text_view_new_with_buffer(pdialog->message_buffer);
213 gtk_widget_set_hexpand(text, TRUE);
214 gtk_widget_set_vexpand(text, TRUE);
216 gtk_text_view_set_editable(GTK_TEXT_VIEW(text), FALSE);
217 gtk_container_add(GTK_CONTAINER(sw), text);
218 g_signal_connect(text, "size-allocate",
219 G_CALLBACK(luaconsole_dialog_area_size_allocate), NULL);
220
221 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text), GTK_WRAP_WORD);
222 gtk_widget_realize(text);
223 gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text), 5);
224
225 pdialog->message_area = GTK_TEXT_VIEW(text);
226 g_signal_connect(text, "destroy", G_CALLBACK(gtk_widget_destroyed),
227 &pdialog->message_area);
228
229 /* The lua console input line. */
230 entry = gtk_entry_new();
231 g_object_set(entry, "margin", 2, NULL);
232 gtk_container_add(GTK_CONTAINER(vbox), entry);
233 g_signal_connect(entry, "activate", G_CALLBACK(luaconsole_input_return),
234 NULL);
235 g_signal_connect(entry, "key_press_event",
236 G_CALLBACK(luaconsole_input_handler), NULL);
237 pdialog->entry = entry;
238 g_signal_connect(entry, "destroy", G_CALLBACK(gtk_widget_destroyed),
239 &pdialog->entry);
240
241 /* Load lua script command button. */
242 gui_dialog_add_button(pdialog->shell, GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE);
243
244 gui_dialog_add_stockbutton(pdialog->shell, GTK_STOCK_OPEN,
245 _("Load Lua Script"), LUACONSOLE_RES_OPEN);
248
250 gui_dialog_show_all(pdialog->shell);
251}
252
253/*************************************************************************/
256static void luaconsole_input_return(GtkEntry *w, gpointer data)
257{
258 const char *theinput;
259 struct luaconsole_data *pdialog = luaconsole_dialog_get();
260
261 fc_assert_ret(pdialog);
262 fc_assert_ret(pdialog->history_list);
263
264 theinput = gtk_entry_get_text(w);
265
266 if (*theinput) {
267 luaconsole_printf(ftc_luaconsole_input, "(input)> %s", theinput);
268 script_client_do_string(theinput);
269
271 void *history_data;
272
273 history_data = genlist_get(pdialog->history_list, -1);
274 genlist_remove(pdialog->history_list, history_data);
275 free(history_data);
276 }
277
278 genlist_prepend(pdialog->history_list, fc_strdup(theinput));
279 pdialog->history_pos = -1;
280 }
281
282 gtk_entry_set_text(w, "");
283}
284
285/*************************************************************************/
288static void luaconsole_response_callback(struct gui_dialog *pgui_dialog,
289 int response, gpointer data)
290{
291 switch (response) {
293 break;
294 default:
295 gui_dialog_destroy(pgui_dialog);
296 return;
297 }
298
299 switch (response) {
302 break;
303 }
304}
305
306/*************************************************************************/
310{
311 GtkWidget *filesel;
312
313 /* Create the selector */
314 filesel = gtk_file_chooser_dialog_new("Load Lua file", GTK_WINDOW(toplevel),
315 GTK_FILE_CHOOSER_ACTION_OPEN,
316 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
317 GTK_STOCK_OPEN, GTK_RESPONSE_OK,
318 NULL);
319 setup_dialog(filesel, toplevel);
320 gtk_window_set_position(GTK_WINDOW(filesel), GTK_WIN_POS_MOUSE);
321
322 g_signal_connect(filesel, "response",
323 G_CALLBACK(luaconsole_load_file_callback), NULL);
324
325 /* Display that dialog */
326 gtk_window_present(GTK_WINDOW(filesel));
327}
328
329/*************************************************************************/
332static void luaconsole_load_file_callback(GtkWidget *widget, gint response,
333 gpointer data)
334{
335 if (response == GTK_RESPONSE_OK) {
336 gchar *filename = g_filename_to_utf8(gtk_file_chooser_get_filename
337 (GTK_FILE_CHOOSER(widget)),
338 -1, NULL, NULL, NULL);
339
340 if (NULL != filename) {
341 luaconsole_printf(ftc_luaconsole_input, "(file)> %s", filename);
342 script_client_do_file(filename);
343 g_free(filename);
344 }
345 }
346 gtk_widget_destroy(widget);
347}
348
349/*************************************************************************/
352static gboolean luaconsole_input_handler(GtkWidget *w, GdkEventKey *ev)
353{
354 struct luaconsole_data *pdialog = luaconsole_dialog_get();
355
356 fc_assert_ret_val(pdialog, FALSE);
358
359 switch (ev->keyval) {
360 case GDK_KEY_Up:
361 if (pdialog->history_pos < genlist_size(pdialog->history_list) - 1) {
362 gtk_entry_set_text(GTK_ENTRY(w), genlist_get(pdialog->history_list,
363 ++pdialog->history_pos));
364 gtk_editable_set_position(GTK_EDITABLE(w), -1);
365 }
366 return TRUE;
367
368 case GDK_KEY_Down:
369 if (pdialog->history_pos >= 0) {
370 pdialog->history_pos--;
371 }
372
373 if (pdialog->history_pos >= 0) {
374 gtk_entry_set_text(GTK_ENTRY(w), genlist_get(pdialog->history_list,
375 pdialog->history_pos));
376 } else {
377 gtk_entry_set_text(GTK_ENTRY(w), "");
378 }
379 gtk_editable_set_position(GTK_EDITABLE(w), -1);
380 return TRUE;
381
382 default:
383 break;
384 }
385
386 return FALSE;
387}
388
389/*************************************************************************/
395 GtkAllocation *allocation,
396 gpointer data)
397{
398 static int old_width = 0, old_height = 0;
399 if (allocation->width != old_width
400 || allocation->height != old_height) {
402 old_width = allocation->width;
403 old_height = allocation->height;
404 }
405}
406
407/*************************************************************************/
414{
415 struct luaconsole_data *pdialog = luaconsole_dialog_get();
416
417 fc_assert_ret(pdialog);
418
419 if (pdialog->shell) {
420 GtkTextIter end;
421
422 fc_assert_ret(NULL != pdialog->message_buffer);
423 fc_assert_ret(NULL != pdialog->message_area);
424
425 gtk_text_buffer_get_end_iter(pdialog->message_buffer, &end);
426 gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(pdialog->message_area),
427 &end, 0.0, TRUE, 1.0, 0.0);
428 }
429}
430
431/*************************************************************************/
434static void luaconsole_dialog_refresh(struct luaconsole_data *pdialog)
435{
436 fc_assert_ret(NULL != pdialog);
437}
438
439/*************************************************************************/
442static void luaconsole_dialog_destroy(struct luaconsole_data *pdialog)
443{
444 fc_assert_ret(NULL != pdialog);
445
446 if (pdialog->shell) {
447 gui_dialog_destroy(pdialog->shell);
448 fc_assert(NULL == pdialog->shell);
449 }
450 fc_assert(NULL == pdialog->message_area);
451 fc_assert(NULL == pdialog->entry);
452}
453
454/*************************************************************************/
459 const struct text_tag_list *tags)
460{
461 GtkTextBuffer *buf;
462 GtkTextIter iter;
463 GtkTextMark *mark;
464 ft_offset_t text_start_offset;
465 struct luaconsole_data *pdialog = luaconsole_dialog_get();
466
467 fc_assert_ret(pdialog);
468
469 buf = pdialog->message_buffer;
470 gtk_text_buffer_get_end_iter(buf, &iter);
471 gtk_text_buffer_insert(buf, &iter, "\n", -1);
472 mark = gtk_text_buffer_create_mark(buf, NULL, &iter, TRUE);
473
474 if (GUI_GTK_OPTION(show_chat_message_time)) {
475 char timebuf[64];
476 time_t now;
477 struct tm now_tm;
478
479 now = time(NULL);
480 fc_localtime(&now, &now_tm);
481 strftime(timebuf, sizeof(timebuf), "[%H:%M:%S] ", &now_tm);
482 gtk_text_buffer_insert(buf, &iter, timebuf, -1);
483 }
484
485 text_start_offset = gtk_text_iter_get_offset(&iter);
486 gtk_text_buffer_insert(buf, &iter, astring, -1);
487 text_tag_list_iterate(tags, ptag) {
488 apply_text_tag(ptag, buf, text_start_offset, astring);
490
491 if (pdialog->message_area) {
492 scroll_if_necessary(GTK_TEXT_VIEW(pdialog->message_area), mark);
493 }
494 gtk_text_buffer_delete_mark(buf, mark);
495}
#define _(String)
Definition fcintl.h:67
const struct ft_color ftc_luaconsole_input
#define text_tag_list_iterate_end
#define text_tag_list_iterate(tags, ptag)
int ft_offset_t
bool genlist_remove(struct genlist *pgenlist, const void *punlink)
Definition genlist.c:329
struct genlist * genlist_new(void)
Definition genlist.c:31
void * genlist_get(const struct genlist *pgenlist, int idx)
Definition genlist.c:224
void genlist_prepend(struct genlist *pgenlist, void *data)
Definition genlist.c:526
void genlist_destroy(struct genlist *pgenlist)
Definition genlist.c:57
int genlist_size(const struct genlist *pgenlist)
Definition genlist.c:192
void set_message_buffer_view_link_handlers(GtkWidget *view)
Definition chatline.c:744
void scroll_if_necessary(GtkTextView *textview, GtkTextMark *scroll_target)
Definition chatline.c:557
void apply_text_tag(const struct text_tag *ptag, GtkTextBuffer *buf, ft_offset_t text_start_offset, const char *text)
Definition chatline.c:755
GtkWidget * bottom_notebook
Definition gui_main.c:128
GtkWidget * toplevel
Definition gui_main.c:124
GtkWidget * right_notebook
Definition gui_main.c:128
#define GUI_GTK_OPTION(optname)
Definition gui_main.h:25
void gui_dialog_destroy(struct gui_dialog *dlg)
Definition gui_stuff.c:951
void gui_dialog_present(struct gui_dialog *dlg)
Definition gui_stuff.c:834
void gui_dialog_raise(struct gui_dialog *dlg)
Definition gui_stuff.c:864
void gui_dialog_new(struct gui_dialog **pdlg, GtkNotebook *notebook, gpointer user_data, bool check_top)
Definition gui_stuff.c:504
void gui_dialog_response_set_callback(struct gui_dialog *dlg, GUI_DIALOG_RESPONSE_FUN fun)
Definition gui_stuff.c:985
GtkWidget * gui_dialog_add_button(struct gui_dialog *dlg, const char *text, int response)
Definition gui_stuff.c:706
GtkWidget * gui_dialog_add_stockbutton(struct gui_dialog *dlg, const char *stock, const char *text, int response)
Definition gui_stuff.c:690
void gui_dialog_show_all(struct gui_dialog *dlg)
Definition gui_stuff.c:794
void gui_dialog_set_title(struct gui_dialog *dlg, const char *title)
Definition gui_stuff.c:932
void setup_dialog(GtkWidget *shell, GtkWidget *parent)
Definition gui_stuff.c:281
#define MAX_LUACONSOLE_HISTORY
Definition luaconsole.c:46
void luaconsole_dialog_popdown(void)
Definition luaconsole.c:144
static struct luaconsole_data * luaconsole_dialog_get(void)
Definition luaconsole.c:118
static void luaconsole_dialog_scroll_to_bottom(void)
Definition luaconsole.c:413
void luaconsole_dialog_init(void)
Definition luaconsole.c:83
bool luaconsole_dialog_is_open(void)
Definition luaconsole.c:157
static void luaconsole_load_file_callback(GtkWidget *widget, gint response, gpointer data)
Definition luaconsole.c:332
static void luaconsole_dialog_create(struct luaconsole_data *pdialog)
Definition luaconsole.c:183
static void luaconsole_response_callback(struct gui_dialog *pgui_dialog, int response, gpointer data)
Definition luaconsole.c:288
static struct luaconsole_data * luaconsole
Definition luaconsole.c:58
static void luaconsole_dialog_refresh(struct luaconsole_data *pdialog)
Definition luaconsole.c:434
luaconsole_res
Definition luaconsole.c:42
@ LUACONSOLE_RES_OPEN
Definition luaconsole.c:43
static void luaconsole_dialog_destroy(struct luaconsole_data *pdialog)
Definition luaconsole.c:442
static void luaconsole_input_return(GtkEntry *w, gpointer data)
Definition luaconsole.c:256
void real_luaconsole_append(const char *astring, const struct text_tag_list *tags)
Definition luaconsole.c:458
static void luaconsole_load_file_popup(void)
Definition luaconsole.c:309
void real_luaconsole_dialog_update(void)
Definition luaconsole.c:169
void luaconsole_dialog_popup(bool raise)
Definition luaconsole.c:126
static gboolean luaconsole_input_handler(GtkWidget *w, GdkEventKey *ev)
Definition luaconsole.c:352
void luaconsole_dialog_done(void)
Definition luaconsole.c:101
static void luaconsole_dialog_area_size_allocate(GtkWidget *widget, GtkAllocation *allocation, gpointer data)
Definition luaconsole.c:394
#define fc_assert_ret(condition)
Definition log.h:191
#define fc_assert(condition)
Definition log.h:176
#define fc_assert_ret_val(condition, val)
Definition log.h:194
void luaconsole_welcome_message(void)
void luaconsole_printf(const struct ft_color color, const char *format,...)
#define fc_calloc(n, esz)
Definition mem.h:38
#define fc_strdup(str)
Definition mem.h:43
@ GUI_GTK_MSGCHAT_SPLIT
Definition options.h:66
bool script_client_do_file(const char *filename)
bool script_client_do_string(const char *str)
GtkWidget * vbox
Definition gui_stuff.h:71
struct gui_dialog * shell
Definition luaconsole.c:49
struct genlist * history_list
Definition luaconsole.c:54
GtkWidget * entry
Definition luaconsole.c:52
GtkTextView * message_area
Definition luaconsole.c:51
GtkTextBuffer * message_buffer
Definition luaconsole.c:50
struct tm * fc_localtime(const time_t *timep, struct tm *result)
Definition support.c:1310
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47