1 /*
2 $Id: gtkmessage.c,v 1.10 2003/08/02 14:27:26 j_ali Exp $
3 */
4 /*
5 GTK+ NetHack Copyright (c) Issei Numata 1999-2000
6 GTK+ NetHack Copyright (c) Slash'EM Development Team 2000-2003
7 GTK+ NetHack may be freely redistributed. See license for details.
8 */
9
10 #include <sys/types.h>
11 #include <signal.h>
12 #include "winGTK.h"
13 #include <gtk/gtk.h>
14 #include <gdk/gdkkeysyms.h>
15
16 static GtkWidget *message_text;
17
18 extern int root_width;
19 extern int root_height;
20
21 #if GTK_CHECK_VERSION(2,0,0)
22 # define USE_TEXTVIEW
23 #else /* GTK_CHECK_VERSION */
24 # ifdef WIN32
25 /* ALI: Switching this on avoids strange scrolling effects (see bug 124233).
26 */
27 # define FROZEN_INSERT
28 # endif
29 #endif /* GTK_CHECK_VERSION */
30
31 #ifdef USE_TEXTVIEW
32 GtkWidget *
nh_message_new()33 nh_message_new()
34 {
35 GtkWidget *message_h;
36 GtkWidget *sw;
37 GtkTextIter iter;
38 GtkTextBuffer *t;
39
40 message_h = gtk_handle_box_new();
41 GTK_HANDLE_BOX(message_h)->shrink_on_detach = 1;
42
43 message_text = gtk_text_view_new();
44 gtk_widget_show(message_text);
45 GTK_WIDGET_UNSET_FLAGS(message_text, GTK_CAN_FOCUS);
46 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(message_text), GTK_WRAP_WORD);
47 t = gtk_text_view_get_buffer(GTK_TEXT_VIEW(message_text));
48 gtk_text_buffer_create_tag(t, "warning", "foreground", "red", NULL);
49 gtk_text_buffer_get_end_iter(t, &iter);
50 gtk_text_buffer_create_mark(t, "nh_end", &iter, FALSE);
51
52 sw = nh_gtk_new_and_add(gtk_scrolled_window_new(NULL, NULL), message_h, "");
53 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
54 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
55 gtk_container_add(GTK_CONTAINER(sw), message_text);
56
57 return message_h;
58 }
59
60 void
nh_message_putstr(const char * str)61 nh_message_putstr(const char *str)
62 {
63 int len;
64 char *buf;
65 GtkTextIter iter, iter2;
66 GtkTextBuffer *t;
67
68 if (!message_text)
69 return;
70
71 t = gtk_text_view_get_buffer(GTK_TEXT_VIEW(message_text));
72 gtk_text_buffer_get_end_iter(t, &iter);
73
74 len = strlen(str);
75 buf = (char *)alloc(len + 2);
76
77 sprintf(buf, "\n%s", str);
78
79 if (nh_status_in_trouble())
80 gtk_text_buffer_insert_with_tags_by_name(t, &iter, buf, len + 1,
81 "warning", NULL);
82 else
83 gtk_text_buffer_insert(t, &iter, buf, len + 1);
84 free(buf);
85
86 len = gtk_text_buffer_get_char_count(t);
87 if (len > NH_TEXT_REMEMBER) {
88 gtk_text_buffer_get_iter_at_offset(t, &iter, len - NH_TEXT_REMEMBER);
89 gtk_text_buffer_get_iter_at_line(t, &iter2,
90 gtk_text_iter_get_line(&iter) + 1);
91 gtk_text_buffer_get_start_iter(t, &iter);
92 gtk_text_buffer_delete(t, &iter, &iter2);
93 }
94
95 gtk_text_view_scroll_mark_onscreen(GTK_TEXT_VIEW(message_text),
96 gtk_text_buffer_get_mark(t, "nh_end"));
97 }
98
99 #else /* USE_TEXTVIEW */
100
101 GtkWidget *
nh_message_new()102 nh_message_new()
103 {
104 GtkWidget *message_h;
105 GtkWidget *message_hbox;
106
107 message_h = gtk_handle_box_new();
108 GTK_HANDLE_BOX(message_h)->shrink_on_detach = 1;
109
110 message_hbox = nh_gtk_new_and_add(gtk_hbox_new(FALSE, 0), message_h, "");
111
112 message_text = nh_gtk_new_and_pack(gtk_text_new(NULL, NULL),
113 message_hbox, "", TRUE, TRUE, NH_PAD);
114
115 GTK_WIDGET_UNSET_FLAGS(message_text, GTK_CAN_FOCUS);
116 gtk_text_set_word_wrap((GtkText *) message_text, TRUE);
117
118 (void)nh_gtk_new_and_pack(gtk_vscrollbar_new(GTK_TEXT(message_text)->vadj),
119 message_hbox, "", FALSE, FALSE, NH_PAD);
120
121 return message_h;
122 }
123
124 void
nh_message_putstr(const char * str)125 nh_message_putstr(const char *str)
126 {
127 int i;
128 int len;
129 char *buf;
130 GtkText *t;
131 #ifdef FROZEN_INSERT
132 static int freeze_count=0;
133 #endif
134
135 if (!message_text)
136 return;
137
138 t = GTK_TEXT(message_text);
139
140 len = strlen(str);
141 buf = (char *)alloc(len + 2);
142
143 sprintf(buf, "\n%s", str);
144
145 #ifdef FROZEN_INSERT
146 /* ALI: gimpwin 20001226 looks very bad if you update a text widget without
147 * freezing it (the text is displayed half-scrolled, with lines overlapping
148 * each other). This is not ideal (the text is redrawn each thaw), but it
149 * is an improvement. Due to a bug in gimpwin we can't trim text if we've
150 * frozen the widget, thus every so often we don't freeze but trim instead.
151 */
152 if (++freeze_count >= 50) /* Trim text every 50 inserts */
153 freeze_count = 0;
154 else
155 gtk_text_freeze(t);
156 #endif
157
158 if (nh_status_in_trouble())
159 i = CLR_RED;
160 else
161 i = MAP_BLACK;
162 gtk_text_insert(t, NULL, &nh_color[i], &nh_color[MAP_WHITE], buf, len + 1);
163
164 len = gtk_text_get_length(t);
165 #ifdef FROZEN_INSERT
166 if (!freeze_count && len > NH_TEXT_REMEMBER) {
167 #else
168 if (len > NH_TEXT_REMEMBER) {
169 #endif
170 gtk_text_freeze(t);
171 for(i = 0; i < len && len > NH_TEXT_REMEMBER; i++)
172 if (GTK_TEXT_INDEX(t, i) == '\n') {
173 i++;
174 gtk_text_set_point(t, i);
175 gtk_text_backward_delete(t, i);
176 len -= i;
177 }
178 gtk_text_set_point(t, len);
179 gtk_text_thaw(t);
180 }
181 #ifdef FROZEN_INSERT
182 /* ALI: t->vadj->upper would be more correct, but causes gimpwin to crash */
183 if (freeze_count) {
184 gtk_adjustment_set_value(t->vadj, t->vadj->upper - 1);
185 gtk_text_thaw(t);
186 }
187 #endif
188
189 free(buf);
190 }
191
192 #endif /* USE_TEXTVIEW */
193
194 int
195 GTK_doprev_message()
196 {
197 return 0;
198 }
199
200 void
201 nh_message_destroy(void)
202 {
203 message_text = NULL;
204 }
205