Crossfire Client, Branches  R11627
info.c
Go to the documentation of this file.
1 const char * const rcsid_gtk2_info_c =
2  "$Id: info.c 11116 2008-12-30 06:57:53Z mwedel $";
3 /*
4  Crossfire client, a client program for the crossfire program.
5 
6  Copyright (C) 2005-2008 Mark Wedel & Crossfire Development Team
7 
8  This program is free software; you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 2 of the License, or
11  (at your option) any later version.
12 
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 
22  The author can be reached via e-mail to crossfire@metalforge.org
23 */
24 
30 #ifdef HAVE_CONFIG_H
31 # include <config.h>
32 #endif
33 
34 #include <gtk/gtk.h>
35 #include <glade/glade.h>
36 
37 #include "client.h"
38 
39 #include "image.h"
40 #include "gtk2proto.h"
41 
42 #include "main.h"
43 
51 #define FONT_NORMAL 0
52 #define FONT_ARCANE 1
53 #define FONT_STRANGE 2
54 #define FONT_FIXED 3
55 #define FONT_HAND 4
56 #define NUM_FONTS 5
57 
61 static char *font_style_names[NUM_FONTS] = {
62  "info_font_normal",
63  "info_font_arcane",
64  "info_font_strange",
65  "info_font_fixed",
66  "info_font_hand"
67 };
79 #define NUM_TEXT_VIEWS 2
80 
81 extern const char * const usercolorname[NUM_COLORS];
82 
83 struct Info_Pane
84 {
85  GtkWidget *textview;
86  GtkWidget *scrolled_window;
87  GtkTextBuffer *textbuffer;
88  GtkTextMark *textmark;
89  GtkAdjustment *adjustment;
90  GtkTextTag *color_tags[NUM_COLORS];
91  GtkTextTag *font_tags[NUM_FONTS];
95 
96 static void message_callback(int flag, int type, int subtype, char *message);
97 
98 extern const char * const colorname[NUM_COLORS];
99 
100 /*
101  * The idea behind the msg_type_names is to provide meaningful names that the
102  * client can use to load/save these values, in particular, the gtk2 client
103  * uses these to find styles on how to draw the different msg types. We could
104  * set this up as a two dimension array instead - that probably isn't as
105  * efficient as the number of subtypes varies wildly. The 0 subtypes are used
106  * for general cases (describe the entire class of those message types). Note
107  * also that the names here are verbose - the actual code that uses these will
108  * expand it further. In practice, there should never be entries with both the
109  * same type/subtype (each subtype should be unique) - if so, the results are
110  * probably unpredictable on which one the code would use.
111  */
112 #include "msgtypes.h"
113 
114 static int max_subtype=0, has_style=0;
115 
133 void set_text_tag_from_style(GtkTextTag *tag, GtkStyle *style, GtkStyle *base_style)
134 {
135  g_object_set(tag, "foreground-set", FALSE, NULL);
136  g_object_set(tag, "background-set", FALSE, NULL);
137  g_object_set(tag, "font-desc", NULL, NULL);
138 
139  if (memcmp(
140  &style->fg[GTK_STATE_NORMAL],
141  &base_style->fg[GTK_STATE_NORMAL],
142  sizeof(GdkColor)))
143 
144  g_object_set(tag, "foreground-gdk", &style->fg[GTK_STATE_NORMAL], NULL);
145 
146  if (memcmp(
147  &style->bg[GTK_STATE_NORMAL],
148  &base_style->bg[GTK_STATE_NORMAL],
149  sizeof(GdkColor)))
150 
151  g_object_set(tag, "background-gdk", &style->bg[GTK_STATE_NORMAL], NULL);
152 
153  if (style->font_desc != base_style->font_desc)
154  g_object_set(tag, "font-desc", style->font_desc, NULL);
155 }
156 
165 void info_get_styles(void)
166 {
167  int i, j;
168  static int has_init=0;
169  GtkStyle *tmp_style, *base_style[2];
170  char style_name[MAX_BUF];
171 
172  if (!has_init) {
173  /*
174  * We want to set up a 2 dimensional array of msg_type_tags to
175  * correspond to all the types/subtypes, so looking up any value is
176  * really easy. We know the size of the types, but don't know the
177  * number of subtypes - no single declared value. So we just parse the
178  * msg_type_names to find that, then know how big to make the other
179  * dimension. We could allocate different number of entries for each
180  * type, but that makes processing a bit harder (no single value on the
181  * number of subtypes), and this extra memory usage shouldn't really be
182  * at all significant.
183  */
184  for (i = 0; i < sizeof(msg_type_names) / sizeof(Msg_Type_Names); i++) {
185  if (msg_type_names[i].subtype > max_subtype)
187  }
188  for (j = 0; j < NUM_TEXT_VIEWS; j++) {
189  for (i = 0; i < MSG_TYPE_LAST; i++)
190  info_pane[j].msg_type_tags[i] =
191  calloc(max_subtype + 1, sizeof(GtkTextTag*));
192 
193  for (i = 0; i < NUM_FONTS; i++)
194  info_pane[j].font_tags[i] = NULL;
195 
196  for (i = 0; i < NUM_COLORS; i++)
197  info_pane[j].color_tags[i] = NULL;
198  /*
199  * These tag definitions never change - we don't get them from the
200  * settings file (maybe we should), so we only need to allocate
201  * them once.
202  */
203  info_pane[j].bold_tag =
204  gtk_text_buffer_create_tag(info_pane[j].textbuffer,
205  "bold", "weight", PANGO_WEIGHT_BOLD, NULL);
206 
207  info_pane[j].italic_tag =
208  gtk_text_buffer_create_tag(info_pane[j].textbuffer,
209  "italic", "style", PANGO_STYLE_ITALIC, NULL);
210 
212  gtk_text_buffer_create_tag(info_pane[j].textbuffer,
213  "underline", "underline", PANGO_UNDERLINE_SINGLE, NULL);
214  /*
215  * This is really a convenience - we can pass multiple tags in when
216  * drawing text, but once we pass in a NULL tag, that signifies no
217  * more tags. Rather than having to set up an array we pass in,
218  * instead, we have this empty tag that we can pass is so that we
219  * always have the same calling semantics, just differ what tags we
220  * pass in.
221  */
222  if (!info_pane[j].default_tag)
224  gtk_text_buffer_create_tag(info_pane[j].textbuffer,
225  "default", NULL);
226  }
227  has_init = 1;
228  }
229  for (i = 0; i < NUM_TEXT_VIEWS; i++) {
230  base_style[i] =
231  gtk_rc_get_style_by_paths(
232  gtk_settings_get_default(),
233  NULL, "info_default", G_TYPE_NONE);
234  }
235  if (!base_style[0]) {
236  LOG(LOG_INFO, "info.c::info_get_styles",
237  "Unable to find base style info_default"
238  " - will not process most info tag styles!");
239  }
240 
241  has_style = 0;
242 
243  /*
244  * If we don't have a base style tag, we can't process these other tags, as
245  * we need to be able to do a difference, and doing a difference from
246  * nothing (meaning, taking everything in style) still doesn't work really
247  * well.
248  */
249  if (base_style[0]) {
250  /*
251  * This processes the type/subtype styles. We look up the names in the
252  * array to find what name goes to what number.
253  */
254  for (i = 0; i < sizeof(msg_type_names) / sizeof(Msg_Type_Names); i++) {
255  int type, subtype;
256 
257  snprintf(style_name, sizeof(style_name), "msg_%s", msg_type_names[i].style_name);
258  type = msg_type_names[i].type;
259  subtype = msg_type_names[i].subtype;
260 
261  tmp_style =
262  gtk_rc_get_style_by_paths(
263  gtk_settings_get_default(), NULL, style_name, G_TYPE_NONE);
264 
265  for (j = 0; j < NUM_TEXT_VIEWS; j++) {
266  /*
267  * If we have a style for this, update the tag that goes along
268  * with this. If we don't have a tag for this style, create
269  * it.
270  */
271  if (tmp_style) {
272  if (!info_pane[j].msg_type_tags[type][subtype]) {
273  info_pane[j].msg_type_tags[type][subtype] =
274  gtk_text_buffer_create_tag(
275  info_pane[j].textbuffer, NULL, NULL);
276  }
278  info_pane[j].msg_type_tags[type][subtype],
279  tmp_style, base_style[j]);
280  has_style = 1;
281  } else {
282  /*
283  * No setting for this type/subtype, so remove tag if there
284  * is one.
285  */
286  if (info_pane[j].msg_type_tags[type][subtype]) {
287  gtk_text_tag_table_remove(
288  gtk_text_buffer_get_tag_table(
289  info_pane[j].textbuffer),
290  info_pane[j].msg_type_tags[type][subtype]);
291  info_pane[j].msg_type_tags[type][subtype] = NULL;
292  }
293  }
294  }
295  }
296 
297  /*
298  * Old message/color support.
299  */
300  for (i = 0; i < NUM_COLORS; i++) {
301  snprintf(style_name, MAX_BUF, "info_%s", usercolorname[i]);
302 
303  tmp_style =
304  gtk_rc_get_style_by_paths(
305  gtk_settings_get_default(), NULL, style_name, G_TYPE_NONE);
306 
307  for (j = 0; j < NUM_TEXT_VIEWS; j++) {
308  if (tmp_style) {
309  if (!info_pane[j].color_tags[i]) {
310  info_pane[j].color_tags[i] =
311  gtk_text_buffer_create_tag(
312  info_pane[j].textbuffer, NULL, NULL);
313  }
315  info_pane[j].color_tags[i],
316  tmp_style, base_style[j]);
317  } else {
318  if (info_pane[j].color_tags[i]) {
319  gtk_text_tag_table_remove(
320  gtk_text_buffer_get_tag_table(
321  info_pane[j].textbuffer),
322  info_pane[j].color_tags[i]);
323  info_pane[j].color_tags[i] = NULL;
324  }
325  }
326  }
327  }
328 
329  /* Font type support */
330  for (i = 0; i < NUM_FONTS; i++) {
331  tmp_style =
332  gtk_rc_get_style_by_paths(
333  gtk_settings_get_default(),
334  NULL, font_style_names[i], G_TYPE_NONE);
335 
336  for (j = 0; j < NUM_TEXT_VIEWS; j++) {
337  if (tmp_style) {
338  if (!info_pane[j].font_tags[i]) {
339  info_pane[j].font_tags[i] =
340  gtk_text_buffer_create_tag(
341  info_pane[j].textbuffer, NULL, NULL);
342  }
344  info_pane[j].font_tags[i], tmp_style, base_style[j]);
345  } else {
346  if (info_pane[j].font_tags[i]) {
347  gtk_text_tag_table_remove(
348  gtk_text_buffer_get_tag_table(
349  info_pane[j].textbuffer),
350  info_pane[j].font_tags[i]);
351  info_pane[j].font_tags[i] = NULL;
352  }
353  }
354  }
355  }
356  } else {
357  /*
358  * There is no base style - this should not normally be the case
359  * with any real setting files, but certainly can be the case if the
360  * user selected the 'None' setting. So in this case, we just free all
361  * the text tags.
362  */
363  has_style = 0;
364  for (i = 0; i < sizeof(msg_type_names) / sizeof(Msg_Type_Names); i++) {
365  int type, subtype;
366 
367  type = msg_type_names[i].type;
368  subtype = msg_type_names[i].subtype;
369 
370  for (j = 0; j < NUM_TEXT_VIEWS; j++) {
371  if (info_pane[j].msg_type_tags[type][subtype]) {
372  gtk_text_tag_table_remove(
373  gtk_text_buffer_get_tag_table(
374  info_pane[j].textbuffer),
375  info_pane[j].msg_type_tags[type][subtype]);
376  info_pane[j].msg_type_tags[type][subtype] = NULL;
377  }
378  }
379  }
380  for (i = 0; i < NUM_COLORS; i++) {
381  for (j = 0; j < NUM_TEXT_VIEWS; j++) {
382  if (info_pane[j].color_tags[i]) {
383  gtk_text_tag_table_remove(
384  gtk_text_buffer_get_tag_table(
385  info_pane[j].textbuffer),
386  info_pane[j].color_tags[i]);
387  info_pane[j].color_tags[i] = NULL;
388  }
389  }
390  }
391  /* Font type support */
392  for (i = 0; i < NUM_FONTS; i++) {
393  for (j = 0; j < NUM_TEXT_VIEWS; j++) {
394  if (info_pane[j].font_tags[i]) {
395  gtk_text_tag_table_remove(
396  gtk_text_buffer_get_tag_table(
397  info_pane[j].textbuffer),
398  info_pane[j].font_tags[i]);
399  info_pane[j].font_tags[i] = NULL;
400  }
401  }
402  }
403  }
404 }
405 
413 void info_init(GtkWidget *window_root)
414 {
415  int i;
416  GtkTextIter end;
417  char widget_name[MAX_BUF];
418  GladeXML *xml_tree;
419 
420  xml_tree = glade_get_widget_tree(GTK_WIDGET(window_root));
421  for (i = 0; i < NUM_TEXT_VIEWS; i++) {
422  snprintf(widget_name, MAX_BUF, "textview_info%d", i+1);
423  info_pane[i].textview = glade_xml_get_widget(xml_tree, widget_name);
424 
425  snprintf(widget_name, MAX_BUF, "scrolledwindow_textview%d", i+1);
426 
428  glade_xml_get_widget(xml_tree, widget_name);
429 
430  gtk_text_view_set_wrap_mode(
431  GTK_TEXT_VIEW(info_pane[i].textview), GTK_WRAP_WORD);
432 
433  info_pane[i].textbuffer =
434  gtk_text_view_get_buffer(GTK_TEXT_VIEW(info_pane[i].textview));
435 
436  info_pane[i].adjustment =
437  gtk_scrolled_window_get_vadjustment(
438  GTK_SCROLLED_WINDOW(info_pane[i].scrolled_window));
439 
440  gtk_text_buffer_get_end_iter(info_pane[i].textbuffer, &end);
441 
442  info_pane[i].textmark =
443  gtk_text_buffer_create_mark(
444  info_pane[i].textbuffer, NULL, &end, FALSE);
445 
446  gtk_widget_realize(info_pane[i].textview);
447  }
448 
449  info_get_styles();
450 
451  /* Register callbacks for all message types */
452  for (i = 0; i < MSG_TYPE_LAST; i++)
454 }
455 
481 static void add_to_textbuf(int pane, char *message,
482  int type, int subtype,
483  int bold, int italic,
484  int font, char *color, int underline)
485 {
486  GtkTextIter end;
487  GdkRectangle rect;
488  int scroll_to_end=0, color_num;
489  GtkTextTag *color_tag=NULL, *type_tag=NULL;
490 
491  /*
492  * Lets see if the defined color matches any of our defined colors. If we
493  * get a match, set color_tag. If color_tag is null, we either don't have
494  * a match, we don't have a defined tag for the color, or we don't have a
495  * color, use the default tag. It would be nice to know if color is a sub
496  * value set with [color] tag, or is part of the message itself - if we're
497  * just being passed NDI_RED in the draw_ext_info from the server, we
498  * really don't care about that - the type/subtype styles should really be
499  * what determines what color to use.
500  */
501  if (color) {
502  for (color_num = 0; color_num < NUM_COLORS; color_num++)
503  if (!strcasecmp(usercolorname[color_num], color))
504  break;
505  if (color_num < NUM_COLORS)
506  color_tag = info_pane[pane].color_tags[color_num];
507  }
508  if (!color_tag)
509  color_tag = info_pane[pane].default_tag;
510 
511  /*
512  * Following block of code deals with the type/subtype. First, we check
513  * and make sure the passed in values are legal. If so, first see if there
514  * is a particular style for the type/subtype combo, if not, fall back to
515  * one just for the type.
516  */
517  type_tag = info_pane[pane].default_tag;
518 
519  if (type >= MSG_TYPE_LAST
520  || subtype >= max_subtype
521  || type < 0 || subtype < 0 ) {
522  LOG(LOG_ERROR, "info.c::add_to_textbuf",
523  "type (%d) >= MSG_TYPE_LAST (%d) or "
524  "subtype (%d) >= max_subtype (%d)\n",
525  type, MSG_TYPE_LAST, subtype, max_subtype);
526  } else {
527  if (info_pane[pane].msg_type_tags[type][subtype])
528  type_tag = info_pane[pane].msg_type_tags[type][subtype];
529  else if (info_pane[pane].msg_type_tags[type][0])
530  type_tag = info_pane[pane].msg_type_tags[type][0];
531  }
532 
533  gtk_text_view_get_visible_rect(
534  GTK_TEXT_VIEW(info_pane[pane].textview), &rect);
535 
536  if ((info_pane[pane].adjustment->value + rect.height)
537  >= info_pane[pane].adjustment->upper)
538  scroll_to_end = 1;
539 
540  gtk_text_buffer_get_end_iter(info_pane[pane].textbuffer, &end);
541 
542  gtk_text_buffer_insert_with_tags(
543  info_pane[pane].textbuffer, &end, message, strlen(message),
544  bold ? info_pane[pane].bold_tag : info_pane[pane].default_tag,
545  italic ? info_pane[pane].italic_tag : info_pane[pane].default_tag,
546  underline ? info_pane[pane].underline_tag : info_pane[pane].default_tag,
547  info_pane[pane].font_tags[font] ?
548  info_pane[pane].font_tags[font] : info_pane[pane].default_tag,
549  color_tag, type_tag, NULL);
550 
551  if (scroll_to_end)
552  gtk_text_view_scroll_mark_onscreen(
553  GTK_TEXT_VIEW(info_pane[pane].textview), info_pane[pane].textmark);
554 }
555 
573 static void message_callback(int orig_color, int type, int subtype, char *message) {
574  char *marker, *current, *original;
575  int bold=0, italic=0, font=0, underline=0;
576  int pane=0;
578  char *color=NULL;
583  current = strdup(message);
584  original = current; /* Just so we know what to free */
585 
586  if (!has_style) {
587  if (orig_color <0 || orig_color>NUM_COLORS) {
588  LOG(LOG_ERROR, "info.c::message_callback",
589  "Passed invalid color from server: %d, max allowed is %d\n",
590  orig_color, NUM_COLORS);
591  orig_color = 0;
592  } else {
593  /*
594  * Not efficient - we have a number, but convert it to a string, at
595  * which point add_to_textbuf() converts it back to a number :(
596  */
597  color = (char*)usercolorname[orig_color];
598  }
599  }
600 
601  while ((marker = strchr(current, '[')) != NULL) {
602  *marker = 0;
603 
604  if (strlen(current) > 0)
605  add_to_textbuf(pane,
606  current, type, subtype, bold, italic, font, color, underline);
607 
608  current = marker + 1;
609 
610  if ((marker = strchr(current, ']')) == NULL) {
611  free(original);
612  return;
613  }
614 
615  *marker = 0;
616  if (!strcmp(current, "b")) bold = TRUE;
617  else if (!strcmp(current, "/b")) bold = FALSE;
618  else if (!strcmp(current, "i")) italic = TRUE;
619  else if (!strcmp(current, "/i")) italic = FALSE;
620  else if (!strcmp(current, "ul")) underline = TRUE;
621  else if (!strcmp(current, "/ul")) underline = FALSE;
622  else if (!strcmp(current, "fixed")) font = FONT_FIXED;
623  else if (!strcmp(current, "arcane")) font = FONT_ARCANE;
624  else if (!strcmp(current, "hand")) font = FONT_HAND;
625  else if (!strcmp(current, "strange")) font = FONT_STRANGE;
626  else if (!strcmp(current, "print")) font = FONT_NORMAL;
627  else if (!strcmp(current, "/color")) color = NULL;
628  else if (!strncmp(current, "color=", 6)) color = current + 6;
629  else
630  LOG(LOG_INFO, "info.c::message_callback",
631  "unrecognized tag: [%s]\n", current);
632 
633  current = marker + 1;
634  }
635 
637  pane, current, type, subtype, bold, italic, font, color, underline);
638 
640  pane, "\n", type, subtype, bold, italic, font, color, underline);
641 
642  free(original);
643 }
644 
662 void draw_info(const char *str, int color) {
663  int ncolor = color;
664  GtkTextIter end;
665  GdkRectangle rect;
666  int scroll_to_end=0;
667 
668  if (ncolor == NDI_WHITE) {
669  ncolor = NDI_BLACK;
670  }
671 
672  /*
673  * This seems more complicated than it should be, but we need to see if the
674  * window is scrolled at the end. If it is, we want to keep scrolling it
675  * down with new info. If not, we don't want to change position -
676  * otherwise, it makes it very difficult to look back at the old info (like
677  * old messages missed during combat, looking at the shop listing while
678  * people are chatting, etc) We need to find out the position before
679  * putting in new text - otherwise, that operation will mess up our
680  * position, and not give us right info.
681  */
682  gtk_text_view_get_visible_rect(
683  GTK_TEXT_VIEW(info_pane[0].textview), &rect);
684 
685  if ((info_pane[0].adjustment->value + rect.height)
686  >= info_pane[0].adjustment->upper)
687  scroll_to_end = 1;
688 
689  gtk_text_buffer_get_end_iter(info_pane[0].textbuffer, &end);
690 
691  gtk_text_buffer_insert_with_tags(
692  info_pane[0].textbuffer, &end, str, strlen(str),
693  info_pane[0].color_tags[ncolor], NULL);
694 
695  gtk_text_buffer_insert(info_pane[0].textbuffer, &end, "\n" , 1);
696 
697  if (scroll_to_end)
698  gtk_text_view_scroll_mark_onscreen(
699  GTK_TEXT_VIEW(info_pane[0].textview), info_pane[0].textmark);
700 
701  /*
702  * Non-black text is also copied to the critical message panel. Why
703  * does/should color alone determine the message is critical?
704  */
705  if (color != NDI_BLACK) {
706 
707  gtk_text_view_get_visible_rect(
708  GTK_TEXT_VIEW(info_pane[1].textview), &rect);
709 
710  if ((info_pane[1].adjustment->value + rect.height)
711  >= info_pane[1].adjustment->upper)
712  scroll_to_end = 1;
713  else
714  scroll_to_end = 0;
715 
716  gtk_text_buffer_get_end_iter(info_pane[1].textbuffer, &end);
717 
718  gtk_text_buffer_insert_with_tags(
719  info_pane[1].textbuffer, &end, str, strlen(str),
720  info_pane[1].color_tags[ncolor], NULL);
721 
722  gtk_text_buffer_insert(info_pane[1].textbuffer, &end, "\n" , 1);
723 
724  if (scroll_to_end)
725  gtk_text_view_scroll_mark_onscreen(
726  GTK_TEXT_VIEW(info_pane[1].textview), info_pane[1].textmark);
727  }
728 }
729 
742 void draw_color_info(int colr, const char *buf) {
743  draw_info(buf,colr);
744 }
745 
750 void menu_clear(void) {
751  int i;
752 
753  for (i=0; i < NUM_TEXT_VIEWS; i++) {
754  gtk_text_buffer_set_text(info_pane[i].textbuffer, "", 0);
755  }
756 }
757 
767 void set_scroll(const char *s)
768 {
769 }
770 
780 void set_autorepeat(const char *s)
781 {
782 }
783 
795 int get_info_width(void)
796 {
797  return 40;
798 }
GtkWidget * textview
Definition: info.c:85
static XFontStruct * font
Definition: x11.c:192
static int max_subtype
Definition: info.c:114
const Msg_Type_Names msg_type_names[]
Definition: msgtypes.h:5
static void add_to_textbuf(int pane, char *message, int type, int subtype, int bold, int italic, int font, char *color, int underline)
Definition: info.c:481
void setTextManager(int type, ExtTextManager callback)
Definition: commands.c:497
GtkTextTag * bold_tag
Definition: info.c:92
struct Info_Pane info_pane[NUM_TEXT_VIEWS]
static char * font_style_names[NUM_FONTS]
Definition: info.c:61
void draw_color_info(int colr, const char *buf)
Definition: info.c:742
void menu_clear(void)
Definition: info.c:750
const char *const usercolorname[NUM_COLORS]
Definition: main.c:80
void set_text_tag_from_style(GtkTextTag *tag, GtkStyle *style, GtkStyle *base_style)
Definition: info.c:133
void LOG(LogLevel level, const char *origin, const char *format,...)
Definition: misc.c:178
#define TRUE
Definition: client-types.h:71
#define FONT_HAND
Definition: info.c:55
GtkTextTag ** msg_type_tags[MSG_TYPE_LAST]
Definition: info.c:93
GtkWidget * window_root
Definition: main.c:56
const char *const colorname[NUM_COLORS]
Definition: main.c:60
void info_get_styles(void)
Definition: info.c:165
#define FONT_STRANGE
Definition: info.c:53
#define FONT_FIXED
Definition: info.c:54
#define MSG_TYPE_LAST
Definition: newclient.h:335
GtkTextTag * color_tags[NUM_COLORS]
Definition: info.c:90
GtkTextMark * textmark
Definition: info.c:88
GtkTextTag * italic_tag
Definition: info.c:92
void draw_info(const char *str, int color)
Definition: info.c:662
GtkTextTag * default_tag
Definition: info.c:92
#define NUM_COLORS
Definition: main.h:32
#define FONT_ARCANE
Definition: info.c:52
#define NDI_WHITE
Definition: newclient.h:202
#define MAX_BUF
Definition: client-types.h:128
#define NUM_FONTS
Definition: info.c:56
Definition: info.c:83
static int has_style
Definition: info.c:114
GtkTextBuffer * textbuffer
Definition: info.c:87
GtkWidget * scrolled_window
Definition: info.c:86
const char *const rcsid_gtk2_info_c
Definition: info.c:1
GtkTextTag * font_tags[NUM_FONTS]
Definition: info.c:91
#define FONT_NORMAL
Definition: info.c:51
static int has_init
Definition: spells.c:63
void set_scroll(const char *s)
Definition: info.c:767
GtkTextTag * underline_tag
Definition: info.c:92
int get_info_width(void)
Definition: info.c:795
void set_autorepeat(const char *s)
Definition: info.c:780
GtkAdjustment * adjustment
Definition: info.c:89
#define NDI_BLACK
Definition: newclient.h:201
#define FALSE
Definition: client-types.h:68
void info_init(GtkWidget *window_root)
Definition: info.c:413
static void message_callback(int flag, int type, int subtype, char *message)
Definition: info.c:573
#define NUM_TEXT_VIEWS
Definition: info.c:79