~ubuntu-branches/ubuntu/feisty/elinks/feisty-updates

« back to all changes in this revision

Viewing changes to src/dialogs/status.c

  • Committer: Bazaar Package Importer
  • Author(s): Peter Gervai
  • Date: 2004-01-21 22:13:45 UTC
  • Revision ID: james.westby@ubuntu.com-20040121221345-ju33hai1yhhqt6kn
Tags: upstream-0.9.1
ImportĀ upstreamĀ versionĀ 0.9.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Sessions status managment */
 
2
/* $Id: status.c,v 1.48 2004/01/06 06:28:15 witekfl Exp $ */
 
3
 
 
4
#ifdef HAVE_CONFIG_H
 
5
#include "config.h"
 
6
#endif
 
7
 
 
8
#include <string.h>
 
9
 
 
10
#include "elinks.h"
 
11
 
 
12
#include "bfu/leds.h"
 
13
#include "bfu/msgbox.h"
 
14
#include "bfu/style.h"
 
15
#include "config/options.h"
 
16
#include "cache/cache.h"
 
17
#include "dialogs/download.h"
 
18
#include "dialogs/status.h"
 
19
#include "document/document.h"
 
20
#include "document/renderer.h"
 
21
#include "document/view.h"
 
22
#include "intl/gettext/libintl.h"
 
23
#include "sched/connection.h"
 
24
#include "sched/error.h"
 
25
#include "sched/session.h"
 
26
#include "terminal/draw.h"
 
27
#include "terminal/screen.h"
 
28
#include "terminal/tab.h"
 
29
#include "terminal/terminal.h"
 
30
#include "terminal/window.h"
 
31
#include "util/color.h"
 
32
#include "util/conv.h"
 
33
#include "util/error.h"
 
34
#include "util/memory.h"
 
35
#include "util/snprintf.h"
 
36
#include "util/string.h"
 
37
#include "viewer/text/form.h"
 
38
#include "viewer/text/link.h"
 
39
#include "viewer/text/view.h"
 
40
 
 
41
 
 
42
#define average_speed(progress) \
 
43
        ((longlong) (progress)->loaded * 10 / ((progress)->elapsed / 100))
 
44
 
 
45
#define current_speed(progress) \
 
46
        ((progress)->cur_loaded / (CURRENT_SPD_SEC * SPD_DISP_TIME / 1000))
 
47
 
 
48
#define estimated_time(progress) \
 
49
        (((progress)->size - (progress)->pos) \
 
50
         / ((longlong) (progress)->loaded * 10 / ((progress)->elapsed / 100)) \
 
51
         * 1000)
 
52
 
 
53
unsigned char *
 
54
get_stat_msg(struct download *stat, struct terminal *term,
 
55
             int wide, int full, unsigned char *separator)
 
56
{
 
57
        struct string msg;
 
58
        int newlines = separator[strlen(separator) - 1] == '\n';
 
59
 
 
60
        if (!download_is_progressing(stat)) {
 
61
                /* DBG("%d -> %s", stat->state, _(get_err_msg(stat->state), term)); */
 
62
                return stracpy(get_err_msg(stat->state, term));
 
63
        }
 
64
 
 
65
        if (!init_string(&msg)) return NULL;
 
66
 
 
67
        /* FIXME: The following is a PITA from the l10n standpoint. A *big*
 
68
         * one, _("of")-like pearls are a nightmare. Format strings need to
 
69
         * be introduced to this fuggy corner of code as well. --pasky */
 
70
 
 
71
        add_to_string(&msg, _("Received", term));
 
72
        add_char_to_string(&msg, ' ');
 
73
        add_xnum_to_string(&msg, stat->prg->pos);
 
74
        if (stat->prg->size >= 0) {
 
75
                add_char_to_string(&msg, ' ');
 
76
                add_to_string(&msg, _("of", term));
 
77
                add_char_to_string(&msg, ' ');
 
78
                add_xnum_to_string(&msg, stat->prg->size);
 
79
        }
 
80
 
 
81
        add_to_string(&msg, separator);
 
82
 
 
83
        if (wide && stat->prg->elapsed >= CURRENT_SPD_AFTER * SPD_DISP_TIME) {
 
84
                add_to_string(&msg,
 
85
                              _(full ? (newlines ? N_("Average speed")
 
86
                                                 : N_("average speed"))
 
87
                                     : N_("avg"),
 
88
                                term));
 
89
        } else {
 
90
                add_to_string(&msg, _(newlines ? N_("Speed") : N_("speed"),
 
91
                                        term));
 
92
        }
 
93
 
 
94
        add_char_to_string(&msg, ' ');
 
95
        add_xnum_to_string(&msg, average_speed(stat->prg));
 
96
        add_to_string(&msg, "/s");
 
97
 
 
98
        if (wide && stat->prg->elapsed >= CURRENT_SPD_AFTER * SPD_DISP_TIME) {
 
99
                add_to_string(&msg, ", ");
 
100
                add_to_string(&msg,
 
101
                              _(full ? N_("current speed") : N_("cur"), term));
 
102
                add_char_to_string(&msg, ' '),
 
103
                add_xnum_to_string(&msg, current_speed(stat->prg));
 
104
                add_to_string(&msg, "/s");
 
105
        }
 
106
 
 
107
        if (wide) {
 
108
                /* Do the following only if there is room */
 
109
 
 
110
                add_to_string(&msg, separator);
 
111
 
 
112
                add_to_string(&msg, _(full ? (newlines ? N_("Elapsed time")
 
113
                                                       : N_("elapsed time"))
 
114
                                           : N_("ETT"),
 
115
                                   term));
 
116
                add_char_to_string(&msg, ' ');
 
117
                add_time_to_string(&msg, stat->prg->elapsed);
 
118
        }
 
119
 
 
120
        if (stat->prg->size >= 0 && stat->prg->loaded > 0) {
 
121
                if (wide) add_to_string(&msg, ", ");
 
122
                add_to_string(&msg, _(full ? N_("estimated time")
 
123
                                           : N_("ETA"),
 
124
                                      term));
 
125
                add_char_to_string(&msg, ' ');
 
126
                add_time_to_string(&msg, estimated_time(stat->prg));
 
127
        }
 
128
 
 
129
        return msg.source;
 
130
}
 
131
 
 
132
 
 
133
#define show_tabs(option, tabs) (((option) > 0) && !((option) == 1 && (tabs) < 2))
 
134
 
 
135
void
 
136
update_status(void)
 
137
{
 
138
        int show_title_bar = get_opt_int("ui.show_title_bar");
 
139
        int show_status_bar = get_opt_int("ui.show_status_bar");
 
140
        int show_tabs_bar = get_opt_int("ui.tabs.show_bar");
 
141
#ifdef CONFIG_LEDS
 
142
        int show_leds = get_opt_int("ui.leds.enable");
 
143
#endif
 
144
        int set_window_title = get_opt_bool("ui.window_title");
 
145
        struct session *ses;
 
146
        int tabs = 1;
 
147
        struct terminal *term = NULL;
 
148
 
 
149
        foreach (ses, sessions) {
 
150
                struct session_status *status = &ses->status;
 
151
                int dirty = 0;
 
152
 
 
153
                /* Try to descrease the number of tab calculation using that
 
154
                 * tab sessions share the same term. */
 
155
                if (ses->tab->term != term) {
 
156
                        term = ses->tab->term;
 
157
                        tabs = number_of_tabs(term);
 
158
                }
 
159
 
 
160
                if (status->show_title_bar != show_title_bar) {
 
161
                        status->show_title_bar = show_title_bar;
 
162
                        dirty = 1;
 
163
                }
 
164
 
 
165
                if (status->show_status_bar != show_status_bar) {
 
166
                        status->show_status_bar = show_status_bar;
 
167
                        dirty = 1;
 
168
                }
 
169
 
 
170
                if (show_tabs(show_tabs_bar, tabs) != status->show_tabs_bar) {
 
171
                        status->show_tabs_bar = show_tabs(show_tabs_bar, tabs);
 
172
                        /* Force the current document to be rerendered so the
 
173
                         * document view and document height is updated to fit
 
174
                         * into the new dimensions. Related to bug 87. */
 
175
                        render_document_frames(ses);
 
176
                        dirty = 1;
 
177
                }
 
178
#ifdef CONFIG_LEDS
 
179
                if (status->show_leds != show_leds) {
 
180
                        status->show_leds = show_leds;
 
181
                        dirty = 1;
 
182
                }
 
183
#endif
 
184
 
 
185
                status->set_window_title = set_window_title;
 
186
 
 
187
                if (!dirty) continue;
 
188
 
 
189
                set_screen_dirty(term->screen, 0, term->height);
 
190
        }
 
191
}
 
192
 
 
193
static inline void
 
194
display_status_bar(struct session *ses, struct terminal *term, int tabs_count)
 
195
{
 
196
        static int last_current_link;
 
197
        unsigned char *msg = NULL;
 
198
        unsigned int tab_info_len = 0;
 
199
        struct download *stat = get_current_download(ses);
 
200
        struct session_status *status = &ses->status;
 
201
        struct color_pair *text_color = NULL;
 
202
        int msglen;
 
203
 
 
204
        if (ses->kbdprefix.typeahead) {
 
205
                unsigned char *uri = print_current_link(ses);
 
206
                struct string msgstr;
 
207
 
 
208
                if (!init_string(&msgstr)) return;
 
209
 
 
210
                string_concat(&msgstr, _("Typeahead", term), ": ",
 
211
                              ses->kbdprefix.typeahead, NULL);
 
212
                set_cursor(term, msgstr.length, term->height - 1, 0);
 
213
                string_concat(&msgstr, "  [", empty_string_or_(uri), "]", NULL);
 
214
 
 
215
                if (uri) mem_free(uri);
 
216
                msg = msgstr.source;
 
217
 
 
218
        } else if (stat) {
 
219
                /* Show S_INTERRUPTED message *once* but then show links
 
220
                 * again as usual. */
 
221
                if (current_frame(ses)) {
 
222
                        int ncl = current_frame(ses)->vs->current_link;
 
223
 
 
224
                        if (stat->state == S_INTERRUPTED
 
225
                                && ncl != last_current_link)
 
226
                                stat->state = S_OK;
 
227
                        last_current_link = ncl;
 
228
 
 
229
                        if (stat->state == S_OK)
 
230
                                msg = print_current_link(ses);
 
231
                }
 
232
 
 
233
                if (!msg) {
 
234
                        int full = term->width > 130;
 
235
                        int wide = term->width > 80;
 
236
 
 
237
                        msg = get_stat_msg(stat, term, wide, full, ", ");
 
238
                }
 
239
        }
 
240
 
 
241
        draw_area(term, 0, term->height - 1, term->width, 1, ' ', 0,
 
242
                get_bfu_color(term, "status.status-bar"));
 
243
 
 
244
        if (!status->show_tabs_bar && tabs_count > 1) {
 
245
                unsigned char tab_info[8];
 
246
 
 
247
                tab_info[tab_info_len++] = '[';
 
248
                ulongcat(tab_info, &tab_info_len, term->current_tab + 1, 4, 0);
 
249
                tab_info[tab_info_len++] = ']';
 
250
                tab_info[tab_info_len++] = ' ';
 
251
                tab_info[tab_info_len] = '\0';
 
252
 
 
253
                text_color = get_bfu_color(term, "status.status-text");
 
254
                draw_text(term, 0, term->height - 1, tab_info, tab_info_len,
 
255
                        0, text_color);
 
256
        }
 
257
 
 
258
        if (!msg) return;
 
259
 
 
260
        if (!text_color)
 
261
                text_color = get_bfu_color(term, "status.status-text");
 
262
 
 
263
        msglen = strlen(msg);
 
264
        draw_text(term, 0 + tab_info_len, term->height - 1,
 
265
                  msg, msglen, 0, text_color);
 
266
        mem_free(msg);
 
267
 
 
268
        if (download_is_progressing(stat) && stat->prg->size > 0) {
 
269
                int xend = term->width - 1;
 
270
                int width;
 
271
 
 
272
#ifdef CONFIG_LEDS
 
273
                if (ses->status.show_leds)
 
274
                        xend -= LEDS_COUNT + 2;
 
275
#endif
 
276
 
 
277
                if (xend - msglen < 6) return;
 
278
                width = int_min(20, xend - msglen - 1);
 
279
 
 
280
                download_progress_bar(term, xend - width, term->height - 1,
 
281
                                      width, NULL, NULL,
 
282
                                      stat->prg->pos, stat->prg->size);
 
283
        }
 
284
}
 
285
 
 
286
static inline void
 
287
display_tab_bar(struct session *ses, struct terminal *term, int tabs_count)
 
288
{
 
289
        struct color_pair *normal_color = get_bfu_color(term, "tabs.normal");
 
290
        struct color_pair *selected_color = get_bfu_color(term, "tabs.selected");
 
291
        struct color_pair *loading_color = get_bfu_color(term, "tabs.loading");
 
292
        struct color_pair *fresh_color = get_bfu_color(term, "tabs.unvisited");
 
293
        struct color_pair *tabsep_color = get_bfu_color(term, "tabs.separator");
 
294
        struct session_status *status = &ses->status;
 
295
        int tab_width = int_max(1, term->width / tabs_count);
 
296
        int tab_total_width = tab_width * tabs_count;
 
297
        int tab_remain_width = int_max(0, term->width - tab_total_width);
 
298
        int tab_add = int_max(1, (tab_remain_width / tabs_count));
 
299
        int tab_num;
 
300
        int ypos = term->height - (status->show_status_bar ? 2 : 1);
 
301
        int xpos = 0;
 
302
 
 
303
        for (tab_num = 0; tab_num < tabs_count; tab_num++) {
 
304
                struct download *stat = NULL;
 
305
                struct color_pair *color = normal_color;
 
306
                struct window *tab = get_tab_by_number(term, tab_num);
 
307
                struct document_view *doc_view;
 
308
                struct session *tab_ses = tab->data;
 
309
                int actual_tab_width = tab_width;
 
310
                unsigned char *msg;
 
311
 
 
312
                /* Adjust tab size to use full term width. */
 
313
                if (tab_remain_width) {
 
314
                        actual_tab_width += tab_add;
 
315
                        tab_remain_width -= tab_add;
 
316
                }
 
317
 
 
318
                doc_view = tab_ses ? current_frame(tab_ses) : NULL;
 
319
 
 
320
                if (doc_view) {
 
321
                        if (doc_view->document->title
 
322
                            && *(doc_view->document->title))
 
323
                                msg = doc_view->document->title;
 
324
                        else
 
325
                                msg = _("Untitled", term);
 
326
                } else {
 
327
                        msg = _("No document", term);
 
328
                }
 
329
 
 
330
                if (tab_num) {
 
331
                        draw_char(term, xpos, ypos, BORDER_SVLINE,
 
332
                                  SCREEN_ATTR_FRAME, tabsep_color);
 
333
                        xpos += 1;
 
334
                }
 
335
 
 
336
                if (tab_num == term->current_tab) {
 
337
                        color = selected_color;
 
338
 
 
339
                } else {
 
340
                        stat = get_current_download(tab->data);
 
341
 
 
342
                        if (stat && stat->state != S_OK) {
 
343
                                color = loading_color;
 
344
                                /* Set incomplete download to unvisited */
 
345
                                if (tab_ses && tab_ses->status.visited)
 
346
                                        tab_ses->status.visited = 0;
 
347
 
 
348
                        } else if (!tab_ses || !tab_ses->status.visited) {
 
349
                                color = fresh_color;
 
350
                        }
 
351
 
 
352
                        if (!download_is_progressing(stat)
 
353
                            || stat->prg->size <= 0)
 
354
                                stat = NULL;
 
355
                }
 
356
 
 
357
                draw_area(term, xpos, ypos, actual_tab_width, 1, ' ', 0, color);
 
358
 
 
359
                if (stat) {
 
360
                        download_progress_bar(term, xpos, ypos,
 
361
                                              actual_tab_width - 1, msg, NULL,
 
362
                                              stat->prg->pos, stat->prg->size);
 
363
                } else {
 
364
                        int msglen = int_min(strlen(msg), actual_tab_width - 1);
 
365
 
 
366
                        draw_text(term, xpos, ypos, msg, msglen, 0, color);
 
367
                }
 
368
 
 
369
                tab->xpos = xpos;
 
370
                tab->width = actual_tab_width;
 
371
                xpos += actual_tab_width - 1;
 
372
        }
 
373
}
 
374
 
 
375
/* Print page's title and numbering at window top. */
 
376
static inline void
 
377
display_title_bar(struct session *ses, struct terminal *term)
 
378
{
 
379
        struct document_view *doc_view;
 
380
        struct document *document;
 
381
        struct string title;
 
382
        unsigned char buf[80];
 
383
        int buflen = 0;
 
384
 
 
385
        /* Clear the old title */
 
386
        draw_area(term, 0, 0, term->width, 1, ' ', 0,
 
387
                  get_bfu_color(term, "title.title-bar"));
 
388
 
 
389
        doc_view = current_frame(ses);
 
390
        if (!doc_view || !doc_view->document) return;
 
391
 
 
392
        if (!init_string(&title)) return;
 
393
 
 
394
        document = doc_view->document;
 
395
 
 
396
        /* Set up the document page info string: '(' %page '/' %pages ')' */
 
397
        if (doc_view->height < document->height) {
 
398
                int pos = doc_view->vs->y + doc_view->height;
 
399
                int page = 1;
 
400
                int pages = doc_view->height
 
401
                            ? (document->height + doc_view->height - 1) / doc_view->height
 
402
                            : 1;
 
403
 
 
404
                /* Check if at the end else calculate the page. */
 
405
                if (pos >= document->height) {
 
406
                        page = pages;
 
407
                } else if (doc_view->height) {
 
408
                        page = int_min((pos - doc_view->height / 2) / doc_view->height + 1,
 
409
                                       pages);
 
410
                }
 
411
 
 
412
                buflen = snprintf(buf, sizeof(buf), " (%d/%d)", page, pages);
 
413
                if (buflen < 0) buflen = 0;
 
414
        }
 
415
 
 
416
        if (document->title) {
 
417
                int maxlen = int_max(term->width - 4 - buflen, 0);
 
418
                int titlelen = int_min(strlen(document->title), maxlen);
 
419
 
 
420
                add_bytes_to_string(&title, document->title, titlelen);
 
421
 
 
422
                if (titlelen == maxlen)
 
423
                        add_bytes_to_string(&title, "...", 3);
 
424
        }
 
425
 
 
426
        if (buflen > 0)
 
427
                add_bytes_to_string(&title, buf, buflen);
 
428
 
 
429
        if (title.length) {
 
430
                int x = int_max(term->width - 1 - title.length, 0);
 
431
 
 
432
                draw_text(term, x, 0, title.source, title.length, 0,
 
433
                          get_bfu_color(term, "title.title-text"));
 
434
        }
 
435
 
 
436
        done_string(&title);
 
437
}
 
438
 
 
439
static inline void
 
440
display_window_title(struct session *ses, struct terminal *term)
 
441
{
 
442
        static struct session *last_ses;
 
443
        struct session_status *status = &ses->status;
 
444
        unsigned char *doc_title = NULL;
 
445
        unsigned char *title;
 
446
        int titlelen;
 
447
 
 
448
        if (ses->doc_view
 
449
            && ses->doc_view->document
 
450
            && ses->doc_view->document->title
 
451
            && ses->doc_view->document->title[0])
 
452
                doc_title = ses->doc_view->document->title;
 
453
 
 
454
        title = straconcat("ELinks",
 
455
                           doc_title ? " - " : NULL,
 
456
                           doc_title,
 
457
                           NULL);
 
458
        if (!title) return;
 
459
 
 
460
        titlelen = strlen(title);
 
461
        if (last_ses != ses
 
462
            || !status->last_title
 
463
            || strlen(status->last_title) != titlelen
 
464
            || memcmp(status->last_title, title, titlelen)) {
 
465
                if (status->last_title) mem_free(status->last_title);
 
466
                status->last_title = title;
 
467
                set_terminal_title(term, title);
 
468
                last_ses = ses;
 
469
        } else {
 
470
                mem_free(title);
 
471
        }
 
472
}
 
473
 
 
474
#ifdef CONFIG_LEDS
 
475
static inline void
 
476
display_leds(struct session *ses, struct session_status *status)
 
477
{
 
478
        if (ses->doc_view && ses->doc_view->document
 
479
            && ses->doc_view->document->url) {
 
480
                struct cache_entry *cache_entry =
 
481
                        find_in_cache(ses->doc_view->document->url);
 
482
 
 
483
                if (cache_entry) {
 
484
                        status->ssl_led->value = (cache_entry->ssl_info)
 
485
                                            ? 'S' : '-';
 
486
                } else {
 
487
                        /* FIXME: We should do this thing better. */
 
488
                        status->ssl_led->value = '?';
 
489
                }
 
490
        }
 
491
 
 
492
        draw_leds(ses);
 
493
}
 
494
#endif /* CONFIG_LEDS */
 
495
 
 
496
/* Print statusbar and titlebar, set terminal title. */
 
497
void
 
498
print_screen_status(struct session *ses)
 
499
{
 
500
        struct terminal *term = ses->tab->term;
 
501
        struct session_status *status = &ses->status;
 
502
        int tabs_count = number_of_tabs(term);
 
503
        int ses_tab_is_current = (ses->tab == get_current_tab(term));
 
504
 
 
505
        if (ses_tab_is_current) {
 
506
                if (status->set_window_title)
 
507
                        display_window_title(ses, term);
 
508
 
 
509
                if (status->show_title_bar)
 
510
                        display_title_bar(ses, term);
 
511
 
 
512
                if (status->show_status_bar)
 
513
                        display_status_bar(ses, term, tabs_count);
 
514
#ifdef CONFIG_LEDS
 
515
                if (status->show_leds)
 
516
                        display_leds(ses, status);
 
517
#endif
 
518
 
 
519
                if (!ses->status.visited)
 
520
                        ses->status.visited = 1;
 
521
        }
 
522
 
 
523
        if (status->show_tabs_bar) {
 
524
                display_tab_bar(ses, term, tabs_count);
 
525
        }
 
526
 
 
527
        redraw_from_window(ses->tab);
 
528
}