~ubuntu-branches/ubuntu/feisty/irssi/feisty-backports

« back to all changes in this revision

Viewing changes to src/fe-text/statusbar-items.c

  • Committer: Bazaar Package Importer
  • Author(s): David Pashley
  • Date: 2005-12-10 21:25:51 UTC
  • Revision ID: james.westby@ubuntu.com-20051210212551-5qwm108g7inyu2f2
Tags: upstream-0.8.10
ImportĀ upstreamĀ versionĀ 0.8.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 statusbar-items.c : irssi
 
3
 
 
4
    Copyright (C) 1999-2001 Timo Sirainen
 
5
 
 
6
    This program is free software; you can redistribute it and/or modify
 
7
    it under the terms of the GNU General Public License as published by
 
8
    the Free Software Foundation; either version 2 of the License, or
 
9
    (at your option) any later version.
 
10
 
 
11
    This program is distributed in the hope that it will be useful,
 
12
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
    GNU General Public License for more details.
 
15
 
 
16
    You should have received a copy of the GNU General Public License
 
17
    along with this program; if not, write to the Free Software
 
18
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
19
*/
 
20
 
 
21
#include "module.h"
 
22
#include "signals.h"
 
23
#include "settings.h"
 
24
#include "servers.h"
 
25
 
 
26
#include "themes.h"
 
27
#include "statusbar.h"
 
28
#include "gui-entry.h"
 
29
#include "gui-windows.h"
 
30
 
 
31
/* how often to redraw lagging time (seconds) */
 
32
#define LAG_REFRESH_TIME 10
 
33
 
 
34
static GList *activity_list;
 
35
static GSList *more_visible; /* list of MAIN_WINDOW_RECs which have --more-- */
 
36
static GHashTable *input_entries;
 
37
static int last_lag, last_lag_unknown, lag_timeout_tag;
 
38
 
 
39
static void item_window_active(SBAR_ITEM_REC *item, int get_size_only)
 
40
{
 
41
        WINDOW_REC *window;
 
42
 
 
43
        window = active_win;
 
44
        if (item->bar->parent_window != NULL)
 
45
                window = item->bar->parent_window->active;
 
46
 
 
47
        if (window != NULL && window->active != NULL) {
 
48
                statusbar_item_default_handler(item, get_size_only,
 
49
                                               NULL, "", TRUE);
 
50
        } else if (get_size_only) {
 
51
                item->min_size = item->max_size = 0;
 
52
        }
 
53
}
 
54
 
 
55
static void item_window_empty(SBAR_ITEM_REC *item, int get_size_only)
 
56
{
 
57
        WINDOW_REC *window;
 
58
 
 
59
        window = active_win;
 
60
        if (item->bar->parent_window != NULL)
 
61
                window = item->bar->parent_window->active;
 
62
 
 
63
        if (window != NULL && window->active == NULL) {
 
64
                statusbar_item_default_handler(item, get_size_only,
 
65
                                               NULL, "", TRUE);
 
66
        } else if (get_size_only) {
 
67
                item->min_size = item->max_size = 0;
 
68
        }
 
69
}
 
70
 
 
71
static char *get_activity_list(MAIN_WINDOW_REC *window, int normal, int hilight)
 
72
{
 
73
        THEME_REC *theme;
 
74
        GString *str;
 
75
        GList *tmp;
 
76
        char *ret, *name, *format, *value;
 
77
        int is_det;
 
78
 
 
79
        str = g_string_new(NULL);
 
80
 
 
81
        theme = window != NULL && window->active != NULL &&
 
82
                window->active->theme != NULL ?
 
83
                window->active->theme : current_theme;
 
84
 
 
85
        for (tmp = activity_list; tmp != NULL; tmp = tmp->next) {
 
86
                WINDOW_REC *window = tmp->data;
 
87
 
 
88
                is_det = window->data_level >= DATA_LEVEL_HILIGHT;
 
89
                if ((!is_det && !normal) || (is_det && !hilight))
 
90
                        continue;
 
91
 
 
92
                /* comma separator */
 
93
                if (str->len > 0) {
 
94
                        value = theme_format_expand(theme, "{sb_act_sep ,}");
 
95
                        g_string_append(str, value);
 
96
                        g_free(value);
 
97
                }
 
98
 
 
99
                switch (window->data_level) {
 
100
                case DATA_LEVEL_NONE:
 
101
                case DATA_LEVEL_TEXT:
 
102
                        name = "{sb_act_text %d}";
 
103
                        break;
 
104
                case DATA_LEVEL_MSG:
 
105
                        name = "{sb_act_msg %d}";
 
106
                        break;
 
107
                default:
 
108
                        if (window->hilight_color == NULL)
 
109
                                name = "{sb_act_hilight %d}";
 
110
                        else
 
111
                                name = NULL;
 
112
                        break;
 
113
                }
 
114
 
 
115
                if (name != NULL)
 
116
                        format = g_strdup_printf(name, window->refnum);
 
117
                else
 
118
                        format = g_strdup_printf("{sb_act_hilight_color %s %d}",
 
119
                                                 window->hilight_color,
 
120
                                                 window->refnum);
 
121
 
 
122
                value = theme_format_expand(theme, format);
 
123
                g_string_append(str, value);
 
124
                g_free(value);
 
125
 
 
126
                g_free(format);
 
127
        }
 
128
 
 
129
        ret = str->len == 0 ? NULL : str->str;
 
130
        g_string_free(str, ret == NULL);
 
131
        return ret;
 
132
}
 
133
 
 
134
/* redraw activity, FIXME: if we didn't get enough size, this gets buggy.
 
135
   At least "Det:" isn't printed properly. also we should rearrange the
 
136
   act list so that the highest priority items comes first. */
 
137
static void item_act(SBAR_ITEM_REC *item, int get_size_only)
 
138
{
 
139
        char *actlist;
 
140
 
 
141
        actlist = get_activity_list(item->bar->parent_window, TRUE, TRUE);
 
142
        if (actlist == NULL) {
 
143
                if (get_size_only)
 
144
                        item->min_size = item->max_size = 0;
 
145
                return;
 
146
        }
 
147
 
 
148
        statusbar_item_default_handler(item, get_size_only,
 
149
                                       NULL, actlist, FALSE);
 
150
 
 
151
        g_free_not_null(actlist);
 
152
}
 
153
 
 
154
static void sig_statusbar_activity_hilight(WINDOW_REC *window, gpointer oldlevel)
 
155
{
 
156
        GList *tmp;
 
157
        int inspos;
 
158
 
 
159
        g_return_if_fail(window != NULL);
 
160
 
 
161
        if (settings_get_bool("actlist_moves")) {
 
162
                /* Move the window to the first in the activity list */
 
163
                if (g_list_find(activity_list, window) != NULL)
 
164
                        activity_list = g_list_remove(activity_list, window);
 
165
                if (window->data_level != 0)
 
166
                        activity_list = g_list_prepend(activity_list, window);
 
167
                statusbar_items_redraw("act");
 
168
                return;
 
169
        }
 
170
 
 
171
        if (g_list_find(activity_list, window) != NULL) {
 
172
                /* already in activity list */
 
173
                if (window->data_level == 0) {
 
174
                        /* remove from activity list */
 
175
                        activity_list = g_list_remove(activity_list, window);
 
176
                        statusbar_items_redraw("act");
 
177
                } else if (window->data_level != GPOINTER_TO_INT(oldlevel) ||
 
178
                         window->hilight_color != 0) {
 
179
                        /* different level as last time (or maybe different
 
180
                           hilight color?), just redraw it. */
 
181
                        statusbar_items_redraw("act");
 
182
                }
 
183
                return;
 
184
        }
 
185
 
 
186
        if (window->data_level == 0)
 
187
                return;
 
188
 
 
189
        /* add window to activity list .. */
 
190
        inspos = 0;
 
191
        for (tmp = activity_list; tmp != NULL; tmp = tmp->next, inspos++) {
 
192
                WINDOW_REC *rec = tmp->data;
 
193
 
 
194
                if (window->refnum < rec->refnum) {
 
195
                        activity_list =
 
196
                                g_list_insert(activity_list, window, inspos);
 
197
                        break;
 
198
                }
 
199
        }
 
200
        if (tmp == NULL)
 
201
                activity_list = g_list_append(activity_list, window);
 
202
 
 
203
        statusbar_items_redraw("act");
 
204
}
 
205
 
 
206
static void sig_statusbar_activity_window_destroyed(WINDOW_REC *window)
 
207
{
 
208
        g_return_if_fail(window != NULL);
 
209
 
 
210
        if (g_list_find(activity_list, window) != NULL)
 
211
                activity_list = g_list_remove(activity_list, window);
 
212
        statusbar_items_redraw("act");
 
213
}
 
214
 
 
215
static void sig_statusbar_activity_updated(void)
 
216
{
 
217
        statusbar_items_redraw("act");
 
218
}
 
219
 
 
220
static void item_more(SBAR_ITEM_REC *item, int get_size_only)
 
221
{
 
222
        MAIN_WINDOW_REC *mainwin;
 
223
        int visible;
 
224
 
 
225
        if (active_win == NULL) {
 
226
                mainwin = NULL;
 
227
                visible = FALSE;
 
228
        } else {
 
229
                mainwin = WINDOW_MAIN(active_win);
 
230
                visible = WINDOW_GUI(active_win)->view->more_text;
 
231
        }
 
232
 
 
233
        if (!visible) {
 
234
                if (mainwin != NULL)
 
235
                        more_visible = g_slist_remove(more_visible, mainwin);
 
236
                if (get_size_only)
 
237
                        item->min_size = item->max_size = 0;
 
238
                return;
 
239
        }
 
240
 
 
241
        more_visible = g_slist_prepend(more_visible, mainwin);
 
242
        statusbar_item_default_handler(item, get_size_only, NULL, "", FALSE);
 
243
}
 
244
 
 
245
static void sig_statusbar_more_updated(void)
 
246
{
 
247
        int visible;
 
248
 
 
249
        visible = g_slist_find(more_visible, WINDOW_MAIN(active_win)) != NULL;
 
250
        if (WINDOW_GUI(active_win)->view->more_text != visible)
 
251
                statusbar_items_redraw("more");
 
252
}
 
253
 
 
254
/* Returns the lag in milliseconds. If we haven't been able to ask the lag
 
255
   for a while, unknown is set to TRUE. */
 
256
static int get_lag(SERVER_REC *server, int *unknown)
 
257
{
 
258
        long lag;
 
259
 
 
260
        *unknown = FALSE;
 
261
 
 
262
        if (server == NULL || server->lag_last_check == 0) {
 
263
                /* lag has not been asked even once yet */
 
264
                return 0;
 
265
        }
 
266
 
 
267
        if (server->lag_sent.tv_sec == 0) {
 
268
                /* no lag queries going on currently */
 
269
                return server->lag;
 
270
        }
 
271
 
 
272
        /* we're not sure about our current lag.. */
 
273
        *unknown = TRUE;
 
274
 
 
275
        lag = (long) (time(NULL)-server->lag_sent.tv_sec);
 
276
        if (server->lag/1000 > lag) {
 
277
                /* we've been waiting the lag reply less time than
 
278
                   what last known lag was -> use the last known lag */
 
279
                return server->lag;
 
280
        }
 
281
 
 
282
        /* return how long we have been waiting for lag reply */
 
283
        return lag*1000;
 
284
}
 
285
 
 
286
static void item_lag(SBAR_ITEM_REC *item, int get_size_only)
 
287
{
 
288
        SERVER_REC *server;
 
289
        char str[MAX_INT_STRLEN+10];
 
290
        int lag, lag_unknown;
 
291
 
 
292
        server = active_win == NULL ? NULL : active_win->active_server;
 
293
        lag = get_lag(server, &lag_unknown);
 
294
 
 
295
        if (lag <= 0 || lag < settings_get_time("lag_min_show")) {
 
296
                /* don't print the lag item */
 
297
                if (get_size_only)
 
298
                        item->min_size = item->max_size = 0;
 
299
                return;
 
300
        }
 
301
 
 
302
        lag /= 10;
 
303
        last_lag = lag;
 
304
        last_lag_unknown = lag_unknown;
 
305
 
 
306
        if (lag_unknown) {
 
307
                g_snprintf(str, sizeof(str), "%d (?""?)", lag/100);
 
308
        } else {
 
309
                g_snprintf(str, sizeof(str),
 
310
                           lag%100 == 0 ? "%d" : "%d.%02d", lag/100, lag%100);
 
311
        }
 
312
 
 
313
        statusbar_item_default_handler(item, get_size_only,
 
314
                                       NULL, str, TRUE);
 
315
}
 
316
 
 
317
static void lag_check_update(void)
 
318
{
 
319
        SERVER_REC *server;
 
320
        int lag, lag_unknown;
 
321
 
 
322
        server = active_win == NULL ? NULL : active_win->active_server;
 
323
        lag = get_lag(server, &lag_unknown)/10;
 
324
 
 
325
        if (lag < settings_get_time("lag_min_show"))
 
326
                lag = 0;
 
327
        else
 
328
                lag /= 10;
 
329
 
 
330
        if (lag != last_lag || (lag > 0 && lag_unknown != last_lag_unknown))
 
331
                statusbar_items_redraw("lag");
 
332
}
 
333
 
 
334
static void sig_server_lag_updated(SERVER_REC *server)
 
335
{
 
336
        if (active_win != NULL && active_win->active_server == server)
 
337
                lag_check_update();
 
338
}
 
339
 
 
340
static int sig_lag_timeout(void)
 
341
{
 
342
        lag_check_update();
 
343
        return 1;
 
344
}
 
345
 
 
346
static void item_input(SBAR_ITEM_REC *item, int get_size_only)
 
347
{
 
348
        GUI_ENTRY_REC *rec;
 
349
 
 
350
        rec = g_hash_table_lookup(input_entries, item->bar->config->name);
 
351
        if (rec == NULL) {
 
352
                rec = gui_entry_create(item->xpos, item->bar->real_ypos,
 
353
                                       item->size, term_type == TERM_TYPE_UTF8);
 
354
                gui_entry_set_active(rec);
 
355
                g_hash_table_insert(input_entries,
 
356
                                    g_strdup(item->bar->config->name), rec);
 
357
        }
 
358
 
 
359
        if (get_size_only) {
 
360
                item->min_size = 2+term_width/10;
 
361
                item->max_size = term_width;
 
362
                return;
 
363
        }
 
364
 
 
365
        gui_entry_move(rec, item->xpos, item->bar->real_ypos,
 
366
                       item->size);
 
367
        gui_entry_redraw(rec); /* FIXME: this is only necessary with ^L.. */
 
368
}
 
369
 
 
370
static void read_settings(void)
 
371
{
 
372
        if (active_entry != NULL)
 
373
                gui_entry_set_utf8(active_entry, term_type == TERM_TYPE_UTF8);
 
374
}
 
375
 
 
376
void statusbar_items_init(void)
 
377
{
 
378
        settings_add_time("misc", "lag_min_show", "1sec");
 
379
        settings_add_bool("lookandfeel", "actlist_moves", FALSE);
 
380
 
 
381
        statusbar_item_register("window", NULL, item_window_active);
 
382
        statusbar_item_register("window_empty", NULL, item_window_empty);
 
383
        statusbar_item_register("prompt", NULL, item_window_active);
 
384
        statusbar_item_register("prompt_empty", NULL, item_window_empty);
 
385
        statusbar_item_register("topic", NULL, item_window_active);
 
386
        statusbar_item_register("topic_empty", NULL, item_window_empty);
 
387
        statusbar_item_register("lag", NULL, item_lag);
 
388
        statusbar_item_register("act", NULL, item_act);
 
389
        statusbar_item_register("more", NULL, item_more);
 
390
        statusbar_item_register("input", NULL, item_input);
 
391
 
 
392
        /* activity */
 
393
        activity_list = NULL;
 
394
        signal_add("window activity", (SIGNAL_FUNC) sig_statusbar_activity_hilight);
 
395
        signal_add("window destroyed", (SIGNAL_FUNC) sig_statusbar_activity_window_destroyed);
 
396
        signal_add("window refnum changed", (SIGNAL_FUNC) sig_statusbar_activity_updated);
 
397
 
 
398
        /* more */
 
399
        more_visible = NULL;
 
400
        signal_add("gui page scrolled", (SIGNAL_FUNC) sig_statusbar_more_updated);
 
401
        signal_add("window changed", (SIGNAL_FUNC) sig_statusbar_more_updated);
 
402
        signal_add_last("gui print text finished", (SIGNAL_FUNC) sig_statusbar_more_updated);
 
403
        signal_add_last("command clear", (SIGNAL_FUNC) sig_statusbar_more_updated);
 
404
        signal_add_last("command scrollback", (SIGNAL_FUNC) sig_statusbar_more_updated);
 
405
 
 
406
        /* lag */
 
407
        last_lag = 0; last_lag_unknown = FALSE;
 
408
        signal_add("server lag", (SIGNAL_FUNC) sig_server_lag_updated);
 
409
        signal_add("window changed", (SIGNAL_FUNC) lag_check_update);
 
410
        signal_add("window server changed", (SIGNAL_FUNC) lag_check_update);
 
411
        lag_timeout_tag = g_timeout_add(5000, (GSourceFunc) sig_lag_timeout, NULL);
 
412
 
 
413
        /* input */
 
414
        input_entries = g_hash_table_new((GHashFunc) g_str_hash,
 
415
                                         (GCompareFunc) g_str_equal);
 
416
 
 
417
        read_settings();
 
418
        signal_add_last("setup changed", (SIGNAL_FUNC) read_settings);
 
419
}
 
420
 
 
421
void statusbar_items_deinit(void)
 
422
{
 
423
        /* activity */
 
424
        signal_remove("window activity", (SIGNAL_FUNC) sig_statusbar_activity_hilight);
 
425
        signal_remove("window destroyed", (SIGNAL_FUNC) sig_statusbar_activity_window_destroyed);
 
426
        signal_remove("window refnum changed", (SIGNAL_FUNC) sig_statusbar_activity_updated);
 
427
        g_list_free(activity_list);
 
428
        activity_list = NULL;
 
429
 
 
430
        /* more */
 
431
        g_slist_free(more_visible);
 
432
        signal_remove("gui page scrolled", (SIGNAL_FUNC) sig_statusbar_more_updated);
 
433
        signal_remove("window changed", (SIGNAL_FUNC) sig_statusbar_more_updated);
 
434
        signal_remove("gui print text finished", (SIGNAL_FUNC) sig_statusbar_more_updated);
 
435
        signal_remove("command clear", (SIGNAL_FUNC) sig_statusbar_more_updated);
 
436
        signal_remove("command scrollback", (SIGNAL_FUNC) sig_statusbar_more_updated);
 
437
 
 
438
        /* lag */
 
439
        signal_remove("server lag", (SIGNAL_FUNC) sig_server_lag_updated);
 
440
        signal_remove("window changed", (SIGNAL_FUNC) lag_check_update);
 
441
        signal_remove("window server changed", (SIGNAL_FUNC) lag_check_update);
 
442
        g_source_remove(lag_timeout_tag);
 
443
 
 
444
        /* input */
 
445
        g_hash_table_foreach(input_entries, (GHFunc) g_free, NULL);
 
446
        g_hash_table_destroy(input_entries);
 
447
 
 
448
        signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
 
449
}