summary refs log tree commit diff stats
path: root/src/fe-gtk/xtext.h
blob: 8a4b26cf837d906f8da504f44b9518f240591f35 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
/* HexChat
 * Copyright (C) 1998-2010 Peter Zelezny.
 * Copyright (C) 2009-2013 Berke Viktor.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#ifndef HEXCHAT_XTEXT_H
#define HEXCHAT_XTEXT_H

#include <gtk/gtk.h>
#ifdef USE_XFT
#include <X11/Xft/Xft.h>
#endif

#ifdef USE_SHM
#include <X11/Xlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <X11/extensions/XShm.h>
#endif

#define GTK_TYPE_XTEXT              (gtk_xtext_get_type ())
#define GTK_XTEXT(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GTK_TYPE_XTEXT, GtkXText))
#define GTK_XTEXT_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_XTEXT, GtkXTextClass))
#define GTK_IS_XTEXT(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GTK_TYPE_XTEXT))
#define GTK_IS_XTEXT_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_XTEXT))
#define GTK_XTEXT_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_XTEXT, GtkXTextClass))

#define ATTR_BOLD			'\002'
#define ATTR_COLOR		'\003'
#define ATTR_BLINK		'\006'
#define ATTR_BEEP			'\007'
#define ATTR_HIDDEN		'\010'
#define ATTR_ITALICS2	'\011'
#define ATTR_RESET		'\017'
#define ATTR_REVERSE		'\026'
#define ATTR_ITALICS		'\035'
#define ATTR_UNDERLINE	'\037'

/* these match palette.h */
#define XTEXT_MIRC_COLS 32
#define XTEXT_COLS 37		/* 32 plus 5 for extra stuff below */
#define XTEXT_MARK_FG 32	/* for marking text */
#define XTEXT_MARK_BG 33
#define XTEXT_FG 34
#define XTEXT_BG 35
#define XTEXT_MARKER 36		/* for marker line */

typedef struct _GtkXText GtkXText;
typedef struct _GtkXTextClass GtkXTextClass;
typedef struct textentry textentry;

typedef struct {
	GtkXText *xtext;					/* attached to this widget */

	gfloat old_value;					/* last known adj->value */
	textentry *text_first;
	textentry *text_last;
	guint16 grid_offset[256];

	textentry *last_ent_start;	  /* this basically describes the last rendered */
	textentry *last_ent_end;	  /* selection. */
	int last_offset_start;
	int last_offset_end;

	int last_pixel_pos;

	int pagetop_line;
	int pagetop_subline;
	textentry *pagetop_ent;			/* what's at xtext->adj->value */

	int num_lines;
	int indent;						  /* position of separator (pixels) from left */

	textentry *marker_pos;

	int window_width;				/* window size when last rendered. */
	int window_height;

	unsigned int time_stamp:1;
	unsigned int scrollbar_down:1;
	unsigned int needs_recalc:1;
	unsigned int grid_dirty:1;
	unsigned int marker_seen:1;
	unsigned int reset_marker_pos:1;

	GList *search_found;		/* list of textentries where search found strings */
	gchar *search_text;		/* desired text to search for */
	gchar *search_nee;		/* prepared needle to look in haystack for */
	gint search_lnee;		/* its length */
	gtk_xtext_search_flags search_flags;	/* match, bwd, highlight */
	GList *cursearch;			/* GList whose 'data' pts to current textentry */
	GList *curmark;			/* current item in ent->marks */
	GRegex *search_re;		/* Compiled regular expression */
	textentry *hintsearch;	/* textentry found for last search */
} xtext_buffer;

struct _GtkXText
{
	GtkWidget widget;

	xtext_buffer *buffer;
	xtext_buffer *orig_buffer;
	xtext_buffer *selection_buffer;

#ifdef USE_SHM
	XShmSegmentInfo shminfo;
#endif

	GtkAdjustment *adj;
	GdkPixmap *pixmap;				/* 0 = use palette[19] */
	GdkDrawable *draw_buf;			/* points to ->window */
	GdkCursor *hand_cursor;
	GdkCursor *resize_cursor;

	int pixel_offset;					/* amount of pixels the top line is chopped by */

	int last_win_x;
	int last_win_y;
	int last_win_h;
	int last_win_w;

	int tint_red;
	int tint_green;
	int tint_blue;

	GdkGC *bgc;						  /* backing pixmap */
	GdkGC *fgc;						  /* text foreground color */
	GdkGC *light_gc;				  /* sep bar */
	GdkGC *dark_gc;
	GdkGC *thin_gc;
	GdkGC *marker_gc;
	gulong palette[XTEXT_COLS];

	gint io_tag;					  /* for delayed refresh events */
	gint add_io_tag;				  /* "" when adding new text */
	gint scroll_tag;				  /* marking-scroll timeout */
	gulong vc_signal_tag;        /* signal handler for "value_changed" adj */

	int select_start_adj;		  /* the adj->value when the selection started */
	int select_start_x;
	int select_start_y;
	int select_end_x;
	int select_end_y;

	int max_lines;

	int col_fore;
	int col_back;

	int depth;						  /* gdk window depth */

	char num[8];					  /* for parsing mirc color */
	int nc;							  /* offset into xtext->num */

	textentry *hilight_ent;
	int hilight_start;
	int hilight_end;

	guint16 fontwidth[128];	  /* each char's width, only the ASCII ones */

#ifdef USE_XFT
	XftColor color[XTEXT_COLS];
	XftColor *xft_fg;
	XftColor *xft_bg;				/* both point into color[20] */
	XftDraw *xftdraw;
	XftFont *font;
	XftFont *ifont;				/* italics */
#else
	struct pangofont
	{
		PangoFontDescription *font;
		PangoFontDescription *ifont;	/* italics */
		int ascent;
		int descent;
	} *font, pango_font;
	PangoLayout *layout;
#endif

	int fontsize;
	int space_width;				  /* width (pixels) of the space " " character */
	int stamp_width;				  /* width of "[88:88:88]" */
	int max_auto_indent;

	unsigned char scratch_buffer[4096];

	void (*error_function) (int type);
	int (*urlcheck_function) (GtkWidget * xtext, char *word);

	int jump_out_offset;	/* point at which to stop rendering */
	int jump_in_offset;	/* "" start rendering */

	int ts_x;			/* ts origin for ->bgc GC */
	int ts_y;

	int clip_x;			/* clipping (x directions) */
	int clip_x2;		/* from x to x2 */

	int clip_y;			/* clipping (y directions) */
	int clip_y2;		/* from y to y2 */

	/* current text states */
	unsigned int bold:1;
	unsigned int underline:1;
	unsigned int italics:1;
	unsigned int hidden:1;

	/* text parsing states */
	unsigned int parsing_backcolor:1;
	unsigned int parsing_color:1;
	unsigned int backcolor:1;

	/* various state information */
	unsigned int moving_separator:1;
	unsigned int word_or_line_select:1;
	unsigned int button_down:1;
	unsigned int hilighting:1;
	unsigned int dont_render:1;
	unsigned int dont_render2:1;
	unsigned int cursor_hand:1;
	unsigned int cursor_resize:1;
	unsigned int skip_border_fills:1;
	unsigned int skip_stamp:1;
	unsigned int mark_stamp:1;	/* Cut&Paste with stamps? */
	unsigned int force_stamp:1;	/* force redrawing it */
	unsigned int render_hilights_only:1;
	unsigned int in_hilight:1;
	unsigned int un_hilight:1;
	unsigned int recycle:1;
	unsigned int avoid_trans:1;
	unsigned int force_render:1;
	unsigned int shm:1;
	unsigned int color_paste:1; /* CTRL was pressed when selection finished */

	/* settings/prefs */
	unsigned int auto_indent:1;
	unsigned int thinline:1;
	unsigned int transparent:1;
	unsigned int shaded:1;
	unsigned int marker:1;
	unsigned int separator:1;
	unsigned int wordwrap:1;
	unsigned int overdraw:1;
	unsigned int ignore_hidden:1;	/* rawlog uses this */
};

struct _GtkXTextClass
{
	GtkWidgetClass parent_class;
	void (*word_click) (GtkXText * xtext, char *word, GdkEventButton * event);
};

GtkWidget *gtk_xtext_new (GdkColor palette[], int separator);
void gtk_xtext_append (xtext_buffer *buf, unsigned char *text, int len);
void gtk_xtext_append_indent (xtext_buffer *buf,
										unsigned char *left_text, int left_len,
										unsigned char *right_text, int right_len,
										time_t stamp);
int gtk_xtext_set_font (GtkXText *xtext, char *name);
void gtk_xtext_set_background (GtkXText * xtext, GdkPixmap * pixmap, gboolean trans);
void gtk_xtext_set_palette (GtkXText * xtext, GdkColor palette[]);
void gtk_xtext_clear (xtext_buffer *buf, int lines);
void gtk_xtext_save (GtkXText * xtext, int fh);
void gtk_xtext_refresh (GtkXText * xtext, int do_trans);
int gtk_xtext_lastlog (xtext_buffer *out, xtext_buffer *search_area);
textentry *gtk_xtext_search (GtkXText * xtext, const gchar *text, gtk_xtext_search_flags flags, GError **err);
void gtk_xtext_reset_marker_pos (GtkXText *xtext);
void gtk_xtext_check_marker_visibility(GtkXText *xtext);

gboolean gtk_xtext_is_empty (xtext_buffer *buf);
typedef void (*GtkXTextForeach) (GtkXText *xtext, unsigned char *text, void *data);
void gtk_xtext_foreach (xtext_buffer *buf, GtkXTextForeach func, void *data);

void gtk_xtext_set_error_function (GtkXText *xtext, void (*error_function) (int));
void gtk_xtext_set_indent (GtkXText *xtext, gboolean indent);
void gtk_xtext_set_max_indent (GtkXText *xtext, int max_auto_indent);
void gtk_xtext_set_max_lines (GtkXText *xtext, int max_lines);
void gtk_xtext_set_show_marker (GtkXText *xtext, gboolean show_marker);
void gtk_xtext_set_show_separator (GtkXText *xtext, gboolean show_separator);
void gtk_xtext_set_thin_separator (GtkXText *xtext, gboolean thin_separator);
void gtk_xtext_set_time_stamp (xtext_buffer *buf, gboolean timestamp);
void gtk_xtext_set_tint (GtkXText *xtext, int tint_red, int tint_green, int tint_blue);
void gtk_xtext_set_urlcheck_function (GtkXText *xtext, int (*urlcheck_function) (GtkWidget *, char *));
void gtk_xtext_set_wordwrap (GtkXText *xtext, gboolean word_wrap);

xtext_buffer *gtk_xtext_buffer_new (GtkXText *xtext);
void gtk_xtext_buffer_free (xtext_buffer *buf);
void gtk_xtext_buffer_show (GtkXText *xtext, xtext_buffer *buf, int render);
void gtk_xtext_copy_selection (GtkXText *xtext);
GType gtk_xtext_get_type (void);

#endif
s="p">; else col = 30; mirc = atoi (num); mirc = colconv[mirc]; if (mirc > 9) { mirc += 50; sprintf ((char *) &newtext[j], "%dm", mirc + col); } else { sprintf ((char *) &newtext[j], "%dm", mirc + col); } j = strlen (newtext); } switch (text[i]) { case ',': comma = TRUE; break; default: goto endloop; } k = 0; } i++; } break; /* don't actually want hidden text */ case '\010': /* hidden */ break; case '\026': /* REVERSE */ if (reverse) { reverse = FALSE; strcpy (&newtext[j], "\033[27m"); } else { reverse = TRUE; strcpy (&newtext[j], "\033[7m"); } j = strlen (newtext); break; case '\037': /* underline */ if (under) { under = FALSE; strcpy (&newtext[j], "\033[24m"); } else { under = TRUE; strcpy (&newtext[j], "\033[4m"); } j = strlen (newtext); break; case '\002': /* bold */ if (bold) { bold = FALSE; strcpy (&newtext[j], "\033[22m"); } else { bold = TRUE; strcpy (&newtext[j], "\033[1m"); } j = strlen (newtext); break; case '\007': if (!prefs.filterbeep) { newtext[j] = text[i]; j++; } break; case '\017': /* reset all */ strcpy (&newtext[j], "\033[m"); j += 3; reverse = FALSE; bold = FALSE; under = FALSE; break; case '\t': newtext[j] = ' '; j++; break; case '\n': newtext[j] = '\r'; j++; if (prefs.timestamp) dotime = TRUE; default: newtext[j] = text[i]; j++; } i++; endloop: ; } /* make sure last character is a new line */ if (text[i-1] != '\n') newtext[j++] = '\n'; newtext[j] = 0; write (STDOUT_FILENO, newtext, j); free (newtext); } #else /* The win32 version for cmd.exe */ void fe_print_text (struct session *sess, char *text, time_t stamp) { int dotime = FALSE; int comma, k, i = 0, j = 0, len = strlen (text); unsigned char *newtext = malloc (len + 1024); if (prefs.timestamp) { newtext[0] = 0; j += timecat (newtext, stamp); } while (i < len) { if (dotime && text[i] != 0) { dotime = FALSE; newtext[j] = 0; j += timecat (newtext, stamp); } switch (text[i]) { case 3: i++; if (!isdigit (text[i])) { goto endloop; } k = 0; comma = FALSE; while (i < len) { if (text[i] >= '0' && text[i] <= '9' && k < 2) { k++; } else { switch (text[i]) { case ',': comma = TRUE; break; default: goto endloop; } k = 0; } i++; } break; /* don't actually want hidden text */ case '\010': /* hidden */ case '\026': /* REVERSE */ case '\037': /* underline */ case '\002': /* bold */ case '\017': /* reset all */ break; case '\007': if (!prefs.filterbeep) { newtext[j] = text[i]; j++; } break; case '\t': newtext[j] = ' '; j++; break; case '\n': newtext[j] = '\r'; j++; if (prefs.timestamp) dotime = TRUE; default: newtext[j] = text[i]; j++; } i++; endloop: ; } /* make sure last character is a new line */ if (text[i-1] != '\n') newtext[j++] = '\n'; newtext[j] = 0; write (STDOUT_FILENO, newtext, j); free (newtext); } #endif void fe_timeout_remove (int tag) { g_source_remove (tag); } int fe_timeout_add (int interval, void *callback, void *userdata) { return g_timeout_add (interval, (GSourceFunc) callback, userdata); } void fe_input_remove (int tag) { g_source_remove (tag); } int fe_input_add (int sok, int flags, void *func, void *data) { int tag, type = 0; GIOChannel *channel; channel = g_io_channel_unix_new (sok); if (flags & FIA_READ) type |= G_IO_IN | G_IO_HUP | G_IO_ERR; if (flags & FIA_WRITE) type |= G_IO_OUT | G_IO_ERR; if (flags & FIA_EX) type |= G_IO_PRI; tag = g_io_add_watch (channel, type, (GIOFunc) func, data); g_io_channel_unref (channel); return tag; } /* === command-line parameter parsing : requires glib 2.6 === */ static char *arg_cfgdir = NULL; static gint arg_show_autoload = 0; static gint arg_show_config = 0; static gint arg_show_version = 0; static const GOptionEntry gopt_entries[] = { {"no-auto", 'a', 0, G_OPTION_ARG_NONE, &arg_dont_autoconnect, N_("Don't auto connect to servers"), NULL}, {"cfgdir", 'd', 0, G_OPTION_ARG_STRING, &arg_cfgdir, N_("Use a different config directory"), "PATH"}, {"no-plugins", 'n', 0, G_OPTION_ARG_NONE, &arg_skip_plugins, N_("Don't auto load any plugins"), NULL}, {"plugindir", 'p', 0, G_OPTION_ARG_NONE, &arg_show_autoload, N_("Show plugin auto-load directory"), NULL}, {"configdir", 'u', 0, G_OPTION_ARG_NONE, &arg_show_config, N_("Show user config directory"), NULL}, {"url", 0, 0, G_OPTION_ARG_STRING, &arg_url, N_("Open an irc://server:port/channel URL"), "URL"}, {"version", 'v', 0, G_OPTION_ARG_NONE, &arg_show_version, N_("Show version information"), NULL}, {NULL} }; int fe_args (int argc, char *argv[]) { GError *error = NULL; GOptionContext *context; #ifdef ENABLE_NLS bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); textdomain (GETTEXT_PACKAGE); #endif context = g_option_context_new (NULL); g_option_context_add_main_entries (context, gopt_entries, GETTEXT_PACKAGE); g_option_context_parse (context, &argc, &argv, &error); if (error) { if (error->message) printf ("%s\n", error->message); return 1; } g_option_context_free (context); if (arg_show_version) { printf (PACKAGE_TARNAME" "PACKAGE_VERSION"\n"); return 0; } if (arg_show_autoload) { #ifdef WIN32 /* see the chdir() below */ char *sl, *exe = strdup (argv[0]); sl = strrchr (exe, '\\'); if (sl) { *sl = 0; printf ("%s\\plugins\n", exe); } #else printf ("%s\n", HEXCHATLIBDIR"/plugins"); #endif return 0; } if (arg_show_config) { printf ("%s\n", get_xdir_fs ()); return 0; } if (arg_cfgdir) /* we want filesystem encoding */ { xdir_fs = strdup (arg_cfgdir); if (xdir_fs[strlen (xdir_fs) - 1] == '/') xdir_fs[strlen (xdir_fs) - 1] = 0; g_free (arg_cfgdir); } return -1; } void fe_init (void) { /* the following should be default generated, not enfoced in binary */ prefs.autosave = 0; prefs.use_server_tab = 0; prefs.autodialog = 0; /* except for these, there is no lag meter, there is no server list */ prefs.lagometer = 0; prefs.slist_skip = 1; } void fe_main (void) { GIOChannel *keyboard_input; main_loop = g_main_loop_new(NULL, FALSE); /* Keyboard Entry Setup */ #ifdef G_OS_WIN32 keyboard_input = g_io_channel_win32_new_fd(STDIN_FILENO); #else keyboard_input = g_io_channel_unix_new(STDIN_FILENO); #endif g_io_add_watch(keyboard_input, G_IO_IN, handle_line, NULL); g_main_loop_run(main_loop); return; } void fe_exit (void) { done = TRUE; g_main_loop_quit(main_loop); } void fe_new_server (struct server *serv) { serv->gui = malloc (4); } void fe_message (char *msg, int flags) { puts (msg); } void fe_close_window (struct session *sess) { session_free (sess); done = TRUE; } void fe_beep (void) { putchar (7); } void fe_add_rawlog (struct server *serv, char *text, int len, int outbound) { } void fe_set_topic (struct session *sess, char *topic, char *stripped_topic) { } void fe_cleanup (void) { } void fe_set_hilight (struct session *sess) { } void fe_set_tab_color (struct session *sess, int col) { } void fe_update_mode_buttons (struct session *sess, char mode, char sign) { } void fe_update_channel_key (struct session *sess) { } void fe_update_channel_limit (struct session *sess) { } int fe_is_chanwindow (struct server *serv) { return 0; } void fe_add_chan_list (struct server *serv, char *chan, char *users, char *topic) { } void fe_chan_list_end (struct server *serv) { } int fe_is_banwindow (struct session *sess) { return 0; } void fe_add_ban_list (struct session *sess, char *mask, char *who, char *when, int is_exemption) { } void fe_ban_list_end (struct session *sess, int is_exemption) { } void fe_notify_update (char *name) { } void fe_notify_ask (char *name, char *networks) { } void fe_text_clear (struct session *sess, int lines) { } void fe_progressbar_start (struct session *sess) { } void fe_progressbar_end (struct server *serv) { } void fe_userlist_insert (struct session *sess, struct User *newuser, int row, int sel) { } int fe_userlist_remove (struct session *sess, struct User *user) { return 0; } void fe_userlist_rehash (struct session *sess, struct User *user) { } void fe_userlist_move (struct session *sess, struct User *user, int new_row) { } void fe_userlist_numbers (struct session *sess) { } void fe_userlist_clear (struct session *sess) { } void fe_userlist_set_selected (struct session *sess) { } void fe_dcc_add (struct DCC *dcc) { } void fe_dcc_update (struct DCC *dcc) { } void fe_dcc_remove (struct DCC *dcc) { } void fe_clear_channel (struct session *sess) { } void fe_session_callback (struct session *sess) { } void fe_server_callback (struct server *serv) { } void fe_url_add (const char *text) { } void fe_pluginlist_update (void) { } void fe_buttons_update (struct session *sess) { } void fe_dlgbuttons_update (struct session *sess) { } void fe_dcc_send_filereq (struct session *sess, char *nick, int maxcps, int passive) { } void fe_set_channel (struct session *sess) { } void fe_set_title (struct session *sess) { } void fe_set_nonchannel (struct session *sess, int state) { } void fe_set_nick (struct server *serv, char *newnick) { } void fe_change_nick (struct server *serv, char *nick, char *newnick) { } void fe_ignore_update (int level) { } int fe_dcc_open_recv_win (int passive) { return FALSE; } int fe_dcc_open_send_win (int passive) { return FALSE; } int fe_dcc_open_chat_win (int passive) { return FALSE; } void fe_userlist_hide (session * sess) { } void fe_lastlog (session * sess, session * lastlog_sess, char *sstr, gboolean regexp) { } void fe_set_lag (server * serv, int lag) { } void fe_set_throttle (server * serv) { } void fe_set_away (server *serv) { } void fe_serverlist_open (session *sess) { } void fe_get_str (char *prompt, char *def, void *callback, void *ud) { } void fe_get_int (char *prompt, int def, void *callback, void *ud) { } void fe_idle_add (void *func, void *data) { g_idle_add (func, data); } void fe_ctrl_gui (session *sess, fe_gui_action action, int arg) { /* only one action type handled for now, but could add more */ switch (action) { /* gui focus is really the only case xchat-text needs to wory about */ case FE_GUI_FOCUS: current_sess = sess; current_tab = sess; sess->server->front_session = sess; break; default: break; } } int fe_gui_info (session *sess, int info_type) { return -1; } void * fe_gui_info_ptr (session *sess, int info_type) { return NULL; } void fe_confirm (const char *message, void (*yesproc)(void *), void (*noproc)(void *), void *ud) { } char *fe_get_inputbox_contents (struct session *sess) { return NULL; } void fe_set_inputbox_contents (struct session *sess, char *text) { } int fe_get_inputbox_cursor (struct session *sess) { return 0; } void fe_set_inputbox_cursor (struct session *sess, int delta, int pos) { } void fe_open_url (const char *url) { } void fe_menu_del (menu_entry *me) { } char *fe_menu_add (menu_entry *me) { return NULL; } void fe_menu_update (menu_entry *me) { } void fe_uselect (struct session *sess, char *word[], int do_clear, int scroll_to) { } void fe_server_event (server *serv, int type, int arg) { } void fe_flash_window (struct session *sess) { } void fe_get_file (const char *title, char *initial, void (*callback) (void *userdata, char *file), void *userdata, int flags) { } void fe_tray_set_flash (const char *filename1, const char *filename2, int timeout){} void fe_tray_set_file (const char *filename){} void fe_tray_set_icon (feicon icon){} void fe_tray_set_tooltip (const char *text){} void fe_tray_set_balloon (const char *title, const char *text){} void fe_userlist_update (session *sess, struct User *user){}