1
0
mirror of https://github.com/rkd77/elinks.git synced 2024-06-25 01:05:37 +00:00
elinks/src/bfu/leds.c
Kalle Olavi Niemitalo 5a43c55c9e Rewrap lines in option documentation.
Documentation strings of most options used to contain a "\n" at the
end of each source line.  When the option manager displayed these
strings, it treated each "\n" as a hard newline.  On 80x24 terminals
however, the option description window has only 60 columes available
for the text (with the default setup.h), and the hard newlines were
further apart, so the option manager wrapped the text a second time,
resulting in rather ugly output where long lones are interleaved with
short ones.  This could also cause the text to take up too much
vertical space and not fit in the window.

Replace most of those hard newlines with spaces so that the option
manager (or perhaps BFU) will take care of the wrapping.  At the same
time, rewrap the strings in source code so that the source lines are
at most 79 columns wide.

In some options though, there is a list of possible values and their
meanings.  In those lists, if the description of one value does not
fit in one line, then continuation lines should be indented.  The
option manager and BFU are not currently able to do that.  So, keep
the hard newlines in those lists, but rewrap them to 60 columns so
that they are less likely to require further wrapping at runtime.
2009-03-08 15:18:10 +02:00

355 lines
8.2 KiB
C

/* These cute LightEmittingDiode-like indicators. */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef HAVE_TIME_H
#include <time.h>
#endif
#include "elinks.h"
#include "bfu/leds.h"
#include "config/options.h"
#include "intl/gettext/libintl.h"
#include "main/module.h"
#include "main/timer.h"
#include "session/session.h"
#include "terminal/draw.h"
#include "terminal/terminal.h"
#include "terminal/window.h"
#include "util/color.h"
#include "util/error.h"
#include "util/time.h"
#include "viewer/timer.h"
#define LEDS_REFRESH_DELAY ((milliseconds_T) 100)
/* Current leds allocation:
* 0 - SSL connection indicator
* 1 - Insert-mode indicator
* 2 - JavaScript Error indicator
* 3 - JavaScript pop-up blocking indicator
* 4 - unused, reserved for Lua
* 5 - unused */
/* XXX: Currently, the leds toggling is quite hackish, some more work should go
* to it (ie. some led hooks called in sync_leds() to light the leds
* dynamically. --pasky */
/* Always reset led to '-' when not used anymore. */
/* If we would do real protection, we would do this as array of pointers. This
* way someone can just get any struct led and add/subscribe appropriate struct
* led for his control; however, I bet on programmers' responsibility rather,
* and hope that everyone will abide the "rules". */
static int timer_duration_backup = 0;
static timer_id_T redraw_timer = TIMER_ID_UNDEF;
static int drawing = 0;
static void redraw_leds(void *);
enum led_option {
LEDS_CLOCK_TREE,
LEDS_CLOCK_ENABLE,
LEDS_CLOCK_FORMAT,
LEDS_CLOCK_ALIAS,
LEDS_PANEL_TREE,
LEDS_PANEL_ENABLE,
LEDS_OPTIONS,
};
static struct option_info led_options[] = {
INIT_OPT_TREE("ui", N_("Clock"),
"clock", 0, N_("Digital clock in the status bar.")),
INIT_OPT_BOOL("ui.clock", N_("Enable"),
"enable", 0, 0,
N_("Whether to display a digital clock in the status bar.")),
INIT_OPT_STRING("ui.clock", N_("Format"),
"format", 0, "[%H:%M]",
N_("Format string for the digital clock. See the strftime(3) "
"manpage for details.")),
/* Compatibility alias. Added: 2004-04-22, 0.9.CVS. */
INIT_OPT_ALIAS("ui.timer", "clock", 0, "ui.clock"),
INIT_OPT_TREE("ui", N_("LEDs"),
"leds", 0,
N_("LEDs (visual indicators) options.")),
INIT_OPT_BOOL("ui.leds", N_("Enable"),
"enable", 0, 1,
N_("Enable LEDs. These visual indicators will inform you "
"about various states.")),
NULL_OPTION_INFO,
};
#define get_opt_leds(which) led_options[(which)].option.value
#define get_leds_clock_enable() get_opt_leds(LEDS_CLOCK_ENABLE).number
#define get_leds_clock_format() get_opt_leds(LEDS_CLOCK_FORMAT).string
#define get_leds_panel_enable() get_opt_leds(LEDS_PANEL_ENABLE).number
void
init_leds(struct module *module)
{
timer_duration_backup = 0;
/* We can't setup timer here, because we may not manage to startup in
* 100ms and we will get to problems when we will call draw_leds() on
* uninitialized terminal. So, we will wait for draw_leds(). */
}
void
done_leds(struct module *module)
{
kill_timer(&redraw_timer);
}
void
set_led_value(struct led *led, unsigned char value)
{
if (value != led->value__) {
led->value__ = value;
led->value_changed__ = 1;
}
}
void
unset_led_value(struct led *led)
{
set_led_value(led, '-');
}
void
init_led_panel(struct led_panel *leds)
{
int i;
for (i = 0; i < LEDS_COUNT; i++) {
leds->leds[i].used__ = 0;
unset_led_value(&leds->leds[i]);
}
}
static int
draw_timer(struct terminal *term, int xpos, int ypos, struct color_pair *color)
{
unsigned char s[64];
int i, length;
snprintf(s, sizeof(s), "[%d]", get_timer_duration());
length = strlen(s);
for (i = length - 1; i >= 0; i--)
draw_char(term, xpos - (length - i), ypos, s[i], 0, color);
return length;
}
#ifdef HAVE_STRFTIME
static int
draw_clock(struct terminal *term, int xpos, int ypos, struct color_pair *color)
{
unsigned char s[64];
time_t curtime = time(NULL);
struct tm *loctime = localtime(&curtime);
int i, length;
length = strftime(s, sizeof(s), get_leds_clock_format(), loctime);
s[length] = '\0';
for (i = length - 1; i >= 0; i--)
draw_char(term, xpos - (length - i), ypos, s[i], 0, color);
return length;
}
#endif
void
draw_leds(struct session *ses)
{
struct terminal *term = ses->tab->term;
struct color_pair *led_color = NULL;
int i;
int xpos = term->width - LEDS_COUNT - 3;
int ypos = term->height - 1;
term->leds_length = 0;
/* This should be done elsewhere, but this is very nice place where we
* could do that easily. */
if (get_opt_int("ui.timer.enable") == 2) {
led_color = get_bfu_color(term, "status.status-text");
if (!led_color) goto end;
term->leds_length += draw_timer(term, xpos, ypos, led_color);
}
if (!get_leds_panel_enable()) return;
if (!led_color) {
led_color = get_bfu_color(term, "status.status-text");
if (!led_color) goto end;
}
#ifdef HAVE_STRFTIME
if (get_leds_clock_enable()) {
term->leds_length += draw_clock(term, xpos - term->leds_length, ypos, led_color);
}
#endif
/* We must shift the whole thing by one char to left, because we don't
* draft the char in the right-down corner :(. */
draw_char(term, xpos, ypos, '[', 0, led_color);
for (i = 0; i < LEDS_COUNT; i++) {
struct led *led = &ses->status.leds.leds[i];
draw_char(term, xpos + i + 1, ypos, led->value__, 0, led_color);
led->value_changed__ = 0;
}
draw_char(term, xpos + LEDS_COUNT + 1, ypos, ']', 0, led_color);
term->leds_length += LEDS_COUNT + 2;
end:
/* Redraw each 100ms. */
if (!drawing && redraw_timer == TIMER_ID_UNDEF)
install_timer(&redraw_timer, LEDS_REFRESH_DELAY, redraw_leds, NULL);
}
/* Determine if leds redrawing is necessary. Returns non-zero if so. */
static int
sync_leds(struct session *ses)
{
int i;
int timer_duration;
#ifdef HAVE_STRFTIME
/* Check if clock was enabled and update if needed. */
if (get_leds_clock_enable()) {
/* We _always_ update when clock is enabled
* Not perfect. --Zas */
return 1;
}
#endif
for (i = 0; i < LEDS_COUNT; i++) {
struct led *led = &ses->status.leds.leds[i];
if (led->value_changed__)
return 1;
}
/* Check if timer was updated. */
timer_duration = get_timer_duration();
if (timer_duration_backup != timer_duration) {
timer_duration_backup = timer_duration;
return 1;
}
return 0;
}
/* Timer callback for @redraw_timer. As explained in @install_timer,
* this function must erase the expired timer ID from all variables. */
static void
redraw_leds(void *xxx)
{
struct session *ses;
if (!get_leds_panel_enable()
&& get_opt_int("ui.timer.enable") != 2) {
redraw_timer = TIMER_ID_UNDEF;
return;
}
install_timer(&redraw_timer, LEDS_REFRESH_DELAY, redraw_leds, NULL);
/* The expired timer ID has now been erased. */
if (drawing) return;
drawing = 1;
foreach (ses, sessions) {
if (!sync_leds(ses))
continue;
redraw_terminal(ses->tab->term);
draw_leds(ses);
}
drawing = 0;
}
void
menu_leds_info(struct terminal *term, void *xxx, void *xxxx)
{
/* If LEDs ever get more dynamic we might have to change this, but it
* should do for now. --jonas */
info_box(term, MSGBOX_FREE_TEXT | MSGBOX_SCROLLABLE,
N_("LED indicators"), ALIGN_LEFT,
msg_text(term, N_("What the different LEDs indicate:\n"
"\n"
"[SIJP--]\n"
" |||||`- Unused\n"
" ||||`-- Unused\n"
" |||`--- A JavaScript pop-up window was blocked\n"
" ||`---- A JavaScript error has occurred\n"
" |`----- The state of insert mode for text-input form-fields\n"
" | 'i' means modeless, 'I' means insert mode is on\n"
" `------ Whether an SSL connection was used\n"
"\n"
"'-' generally indicates that the LED is off.")));
}
struct led *
register_led(struct session *ses, int number)
{
struct led *led;
if (number >= LEDS_COUNT || number < 0)
return NULL;
led = &ses->status.leds.leds[number];
if (led->used__)
return NULL;
led->used__ = 1;
return led;
}
void
unregister_led(struct led *led)
{
assertm(led->used__, "Attempted to unregister unused led!");
led->used__ = 0;
unset_led_value(led);
}
struct module leds_module = struct_module(
/* name: */ N_("LED indicators"),
/* options: */ led_options,
/* events: */ NULL,
/* submodules: */ NULL,
/* data: */ NULL,
/* init: */ init_leds,
/* done: */ done_leds
);