1 /* These cute LightEmittingDiode-like indicators. */
10 #ifdef HAVE_SYS_TIME_H
20 #include "config/options.h"
21 #include "intl/gettext/libintl.h"
22 #include "main/module.h"
23 #include "main/timer.h"
24 #include "session/session.h"
25 #include "terminal/draw.h"
26 #include "terminal/terminal.h"
27 #include "terminal/window.h"
28 #include "util/color.h"
29 #include "util/error.h"
30 #include "util/time.h"
31 #include "viewer/timer.h"
33 #define LEDS_REFRESH_DELAY ((milliseconds_T) 100)
35 /* Current leds allocation:
36 * 0 - SSL connection indicator
37 * 1 - Insert-mode indicator
38 * 2 - JavaScript Error indicator
39 * 3 - JavaScript pop-up blocking indicator
40 * 4 - unused, reserved for Lua
43 /* XXX: Currently, the leds toggling is quite hackish, some more work should go
44 * to it (ie. some led hooks called in sync_leds() to light the leds
45 * dynamically. --pasky */
47 /* Always reset led to '-' when not used anymore. */
49 /* If we would do real protection, we would do this as array of pointers. This
50 * way someone can just get any struct led and add/subscribe appropriate struct
51 * led for his control; however, I bet on programmers' responsibility rather,
52 * and hope that everyone will abide the "rules". */
54 static int timer_duration_backup
= 0;
56 static timer_id_T redraw_timer
= TIMER_ID_UNDEF
;
57 static int drawing
= 0;
59 static void redraw_leds(void *);
73 static struct option_info led_options
[] = {
74 INIT_OPT_TREE("ui", N_("Clock"),
75 "clock", 0, N_("Digital clock in the status bar.")),
77 INIT_OPT_BOOL("ui.clock", N_("Enable"),
79 N_("Whether to display a digital clock in the status bar.")),
81 INIT_OPT_STRING("ui.clock", N_("Format"),
82 "format", 0, "[%H:%M]",
83 N_("Format string for the digital clock. See the strftime(3)\n"
84 "manpage for details.")),
86 /* Compatibility alias. Added: 2004-04-22, 0.9.CVS. */
87 INIT_OPT_ALIAS("ui.timer", "clock", 0, "ui.clock"),
90 INIT_OPT_TREE("ui", N_("LEDs"),
92 N_("LEDs (visual indicators) options.")),
94 INIT_OPT_BOOL("ui.leds", N_("Enable"),
97 "These visual indicators will inform you about various states.")),
102 #define get_opt_leds(which) led_options[(which)].option.value
103 #define get_leds_clock_enable() get_opt_leds(LEDS_CLOCK_ENABLE).number
104 #define get_leds_clock_format() get_opt_leds(LEDS_CLOCK_FORMAT).string
105 #define get_leds_panel_enable() get_opt_leds(LEDS_PANEL_ENABLE).number
108 init_leds(struct module
*module
)
110 timer_duration_backup
= 0;
112 /* We can't setup timer here, because we may not manage to startup in
113 * 100ms and we will get to problems when we will call draw_leds() on
114 * uninitialized terminal. So, we will wait for draw_leds(). */
118 done_leds(struct module
*module
)
120 kill_timer(&redraw_timer
);
124 set_led_value(struct led
*led
, unsigned char value
)
126 if (value
!= led
->value__
) {
127 led
->value__
= value
;
128 led
->value_changed__
= 1;
133 unset_led_value(struct led
*led
)
135 set_led_value(led
, '-');
140 init_led_panel(struct led_panel
*leds
)
144 for (i
= 0; i
< LEDS_COUNT
; i
++) {
145 leds
->leds
[i
].used__
= 0;
146 unset_led_value(&leds
->leds
[i
]);
151 draw_timer(struct terminal
*term
, int xpos
, int ypos
, struct color_pair
*color
)
156 snprintf(s
, sizeof(s
), "[%d]", get_timer_duration());
159 for (i
= length
- 1; i
>= 0; i
--)
160 draw_char(term
, xpos
- (length
- i
), ypos
, s
[i
], 0, color
);
167 draw_clock(struct terminal
*term
, int xpos
, int ypos
, struct color_pair
*color
)
170 time_t curtime
= time(NULL
);
171 struct tm
*loctime
= localtime(&curtime
);
174 length
= strftime(s
, sizeof(s
), get_leds_clock_format(), loctime
);
176 for (i
= length
- 1; i
>= 0; i
--)
177 draw_char(term
, xpos
- (length
- i
), ypos
, s
[i
], 0, color
);
184 draw_leds(struct session
*ses
)
186 struct terminal
*term
= ses
->tab
->term
;
187 struct color_pair
*led_color
= NULL
;
189 int xpos
= term
->width
- LEDS_COUNT
- 3;
190 int ypos
= term
->height
- 1;
192 term
->leds_length
= 0;
194 /* This should be done elsewhere, but this is very nice place where we
195 * could do that easily. */
196 if (get_opt_int("ui.timer.enable") == 2) {
197 led_color
= get_bfu_color(term
, "status.status-text");
198 if (!led_color
) goto end
;
200 term
->leds_length
+= draw_timer(term
, xpos
, ypos
, led_color
);
203 if (!get_leds_panel_enable()) return;
206 led_color
= get_bfu_color(term
, "status.status-text");
207 if (!led_color
) goto end
;
211 if (get_leds_clock_enable()) {
212 term
->leds_length
+= draw_clock(term
, xpos
- term
->leds_length
, ypos
, led_color
);
216 /* We must shift the whole thing by one char to left, because we don't
217 * draft the char in the right-down corner :(. */
219 draw_char(term
, xpos
, ypos
, '[', 0, led_color
);
221 for (i
= 0; i
< LEDS_COUNT
; i
++) {
222 struct led
*led
= &ses
->status
.leds
.leds
[i
];
224 draw_char(term
, xpos
+ i
+ 1, ypos
, led
->value__
, 0, led_color
);
225 led
->value_changed__
= 0;
228 draw_char(term
, xpos
+ LEDS_COUNT
+ 1, ypos
, ']', 0, led_color
);
230 term
->leds_length
+= LEDS_COUNT
+ 2;
233 /* Redraw each 100ms. */
234 if (!drawing
&& redraw_timer
== TIMER_ID_UNDEF
)
235 install_timer(&redraw_timer
, LEDS_REFRESH_DELAY
, redraw_leds
, NULL
);
238 /* Determine if leds redrawing is necessary. Returns non-zero if so. */
240 sync_leds(struct session
*ses
)
246 /* Check if clock was enabled and update if needed. */
247 if (get_leds_clock_enable()) {
248 /* We _always_ update when clock is enabled
249 * Not perfect. --Zas */
254 for (i
= 0; i
< LEDS_COUNT
; i
++) {
255 struct led
*led
= &ses
->status
.leds
.leds
[i
];
257 if (led
->value_changed__
)
261 /* Check if timer was updated. */
262 timer_duration
= get_timer_duration();
263 if (timer_duration_backup
!= timer_duration
) {
264 timer_duration_backup
= timer_duration
;
272 redraw_leds(void *xxx
)
276 if (!get_leds_panel_enable()
277 && get_opt_int("ui.timer.enable") != 2) {
278 redraw_timer
= TIMER_ID_UNDEF
;
282 install_timer(&redraw_timer
, LEDS_REFRESH_DELAY
, redraw_leds
, NULL
);
287 foreach (ses
, sessions
) {
290 redraw_terminal(ses
->tab
->term
);
297 menu_leds_info(struct terminal
*term
, void *xxx
, void *xxxx
)
299 /* If LEDs ever get more dynamic we might have to change this, but it
300 * should do for now. --jonas */
301 info_box(term
, MSGBOX_FREE_TEXT
| MSGBOX_SCROLLABLE
,
302 N_("LED indicators"), ALIGN_LEFT
,
303 msg_text(term
, N_("What the different LEDs indicate:\n"
308 " |||`--- A JavaScript pop-up window was blocked\n"
309 " ||`---- A JavaScript error has occurred\n"
310 " |`----- The state of insert mode for text-input form-fields\n"
311 " | 'i' means modeless, 'I' means insert mode is on\n"
312 " `------ Whether an SSL connection was used\n"
314 "'-' generally indicates that the LED is off.")));
319 register_led(struct session
*ses
, int number
)
323 if (number
>= LEDS_COUNT
|| number
< 0)
326 led
= &ses
->status
.leds
.leds
[number
];
336 unregister_led(struct led
*led
)
338 assertm(led
->used__
, "Attempted to unregister unused led!");
340 unset_led_value(led
);
343 struct module leds_module
= struct_module(
344 /* name: */ N_("LED indicators"),
345 /* options: */ led_options
,
347 /* submodules: */ NULL
,
349 /* init: */ init_leds
,
350 /* done: */ done_leds