1 /* These cute LightEmittingDiode-like indicators. */
2 /* $Id: leds.c,v 1.88 2005/08/25 15:08:00 zas Exp $ */
11 #ifdef HAVE_SYS_TIME_H
21 #include "config/options.h"
22 #include "intl/gettext/libintl.h"
23 #include "main/module.h"
24 #include "main/timer.h"
25 #include "session/session.h"
26 #include "terminal/draw.h"
27 #include "terminal/terminal.h"
28 #include "terminal/window.h"
29 #include "util/color.h"
30 #include "util/error.h"
31 #include "util/time.h"
32 #include "viewer/timer.h"
34 #define LEDS_REFRESH_DELAY ((milliseconds_T) 100)
36 /* Current leds allocation:
37 * 0 - SSL connection indicator
38 * 1 - Insert-mode indicator
39 * 2 - JavaScript Error indicator
40 * 3 - JavaScript pop-up blocking indicator
41 * 4 - unused, reserved for Lua
44 /* XXX: Currently, the leds toggling is quite hackish, some more work should go
45 * to it (ie. some led hooks called in sync_leds() to light the leds
46 * dynamically. --pasky */
48 /* Always reset led to '-' when not used anymore. */
50 /* If we would do real protection, we would do this as array of pointers. This
51 * way someone can just get any struct led and add/subscribe appropriate struct
52 * led for his control; however, I bet on programmers' responsibility rather,
53 * and hope that everyone will abide the "rules". */
55 static int timer_duration_backup
= 0;
57 static timer_id_T redraw_timer
= TIMER_ID_UNDEF
;
58 static int drawing
= 0;
60 static void redraw_leds(void *);
74 static struct option_info led_options
[] = {
75 INIT_OPT_TREE("ui", N_("Clock"),
76 "clock", 0, N_("Digital clock in the status bar.")),
78 INIT_OPT_BOOL("ui.clock", N_("Enable"),
80 N_("Whether to display a digital clock in the status bar.")),
82 INIT_OPT_STRING("ui.clock", N_("Format"),
83 "format", 0, "[%H:%M]",
84 N_("Format string for the digital clock. See the strftime(3)\n"
85 "manpage for details.")),
87 /* Compatibility alias. Added: 2004-04-22, 0.9.CVS. */
88 INIT_OPT_ALIAS("ui.timer", "clock", 0, "ui.clock"),
91 INIT_OPT_TREE("ui", N_("LEDs"),
93 N_("LEDs (visual indicators) options.")),
95 INIT_OPT_BOOL("ui.leds", N_("Enable"),
98 "These visual indicators will inform you about various states.")),
103 #define get_opt_leds(which) led_options[(which)].option.value
104 #define get_leds_clock_enable() get_opt_leds(LEDS_CLOCK_ENABLE).number
105 #define get_leds_clock_format() get_opt_leds(LEDS_CLOCK_FORMAT).string
106 #define get_leds_panel_enable() get_opt_leds(LEDS_PANEL_ENABLE).number
109 init_leds(struct module
*module
)
111 timer_duration_backup
= 0;
113 /* We can't setup timer here, because we may not manage to startup in
114 * 100ms and we will get to problems when we will call draw_leds() on
115 * uninitialized terminal. So, we will wait for draw_leds(). */
119 done_leds(struct module
*module
)
121 kill_timer(&redraw_timer
);
125 set_led_value(struct led
*led
, unsigned char value
)
127 if (value
!= led
->value__
) {
128 led
->value__
= value
;
129 led
->value_changed__
= 1;
134 unset_led_value(struct led
*led
)
136 set_led_value(led
, '-');
141 init_led_panel(struct led_panel
*leds
)
145 for (i
= 0; i
< LEDS_COUNT
; i
++) {
146 leds
->leds
[i
].used__
= 0;
147 unset_led_value(&leds
->leds
[i
]);
152 draw_timer(struct terminal
*term
, int xpos
, int ypos
, struct color_pair
*color
)
157 snprintf(s
, sizeof(s
), "[%d]", get_timer_duration());
160 for (i
= length
- 1; i
>= 0; i
--)
161 draw_char(term
, xpos
- (length
- i
), ypos
, s
[i
], 0, color
);
168 draw_clock(struct terminal
*term
, int xpos
, int ypos
, struct color_pair
*color
)
171 time_t curtime
= time(NULL
);
172 struct tm
*loctime
= localtime(&curtime
);
175 length
= strftime(s
, sizeof(s
), get_leds_clock_format(), loctime
);
177 for (i
= length
- 1; i
>= 0; i
--)
178 draw_char(term
, xpos
- (length
- i
), ypos
, s
[i
], 0, color
);
185 draw_leds(struct session
*ses
)
187 struct terminal
*term
= ses
->tab
->term
;
188 struct color_pair
*led_color
= NULL
;
190 int xpos
= term
->width
- LEDS_COUNT
- 3;
191 int ypos
= term
->height
- 1;
193 term
->leds_length
= 0;
195 /* This should be done elsewhere, but this is very nice place where we
196 * could do that easily. */
197 if (get_opt_int("ui.timer.enable") == 2) {
198 led_color
= get_bfu_color(term
, "status.status-text");
199 if (!led_color
) goto end
;
201 term
->leds_length
+= draw_timer(term
, xpos
, ypos
, led_color
);
204 if (!get_leds_panel_enable()) return;
207 led_color
= get_bfu_color(term
, "status.status-text");
208 if (!led_color
) goto end
;
212 if (get_leds_clock_enable()) {
213 term
->leds_length
+= draw_clock(term
, xpos
- term
->leds_length
, ypos
, led_color
);
217 /* We must shift the whole thing by one char to left, because we don't
218 * draft the char in the right-down corner :(. */
220 draw_char(term
, xpos
, ypos
, '[', 0, led_color
);
222 for (i
= 0; i
< LEDS_COUNT
; i
++) {
223 struct led
*led
= &ses
->status
.leds
.leds
[i
];
225 draw_char(term
, xpos
+ i
+ 1, ypos
, led
->value__
, 0, led_color
);
226 led
->value_changed__
= 0;
229 draw_char(term
, xpos
+ LEDS_COUNT
+ 1, ypos
, ']', 0, led_color
);
231 term
->leds_length
+= LEDS_COUNT
+ 2;
234 /* Redraw each 100ms. */
235 if (!drawing
&& redraw_timer
== TIMER_ID_UNDEF
)
236 install_timer(&redraw_timer
, LEDS_REFRESH_DELAY
, redraw_leds
, NULL
);
239 /* Determine if leds redrawing is necessary. Returns non-zero if so. */
241 sync_leds(struct session
*ses
)
247 /* Check if clock was enabled and update if needed. */
248 if (get_leds_clock_enable()) {
249 /* We _always_ update when clock is enabled
250 * Not perfect. --Zas */
255 for (i
= 0; i
< LEDS_COUNT
; i
++) {
256 struct led
*led
= &ses
->status
.leds
.leds
[i
];
258 if (led
->value_changed__
)
262 /* Check if timer was updated. */
263 timer_duration
= get_timer_duration();
264 if (timer_duration_backup
!= timer_duration
) {
265 timer_duration_backup
= timer_duration
;
273 redraw_leds(void *xxx
)
277 if (!get_leds_panel_enable()
278 && get_opt_int("ui.timer.enable") != 2) {
279 redraw_timer
= TIMER_ID_UNDEF
;
283 install_timer(&redraw_timer
, LEDS_REFRESH_DELAY
, redraw_leds
, NULL
);
288 foreach (ses
, sessions
) {
291 redraw_terminal(ses
->tab
->term
);
298 menu_leds_info(struct terminal
*term
, void *xxx
, void *xxxx
)
300 /* If LEDs ever get more dynamic we might have to change this, but it
301 * should do for now. --jonas */
302 info_box(term
, MSGBOX_FREE_TEXT
| MSGBOX_SCROLLABLE
,
303 N_("LED indicators"), ALIGN_LEFT
,
304 msg_text(term
, N_("What the different LEDs indicate:\n"
309 " |||`--- A JavaScript pop-up window was blocked\n"
310 " ||`---- A JavaScript error has occured\n"
311 " |`----- The state of insert mode for text-input form-fields\n"
312 " | 'i' means modeless, 'I' means insert mode is on\n"
313 " `------ Whether an SSL connection was used\n"
315 "'-' generally indicates that the LED is off.")));
320 register_led(struct session
*ses
, int number
)
324 if (number
>= LEDS_COUNT
|| number
< 0)
327 led
= &ses
->status
.leds
.leds
[number
];
337 unregister_led(struct led
*led
)
339 assertm(led
->used__
, "Attempted to unregister unused led!");
341 unset_led_value(led
);
344 struct module leds_module
= struct_module(
345 /* name: */ N_("LED indicators"),
346 /* options: */ led_options
,
348 /* submodules: */ NULL
,
350 /* init: */ init_leds
,
351 /* done: */ done_leds