From 88ab74ac20ad96771a9f06667da666bf85cd3f23 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Sat, 10 Jan 2009 19:35:40 +0000 Subject: [PATCH] Clock mode. --- CHANGES | 5 +- Makefile | 8 +- TODO | 4 +- cmd-clock-mode.c | 55 ++++++++++ cmd-set-window-option.c | 8 +- cmd.c | 3 +- key-bindings.c | 3 +- server.c | 28 ++++- tmux.c | 5 +- tmux.h | 11 +- window-clock.c | 235 ++++++++++++++++++++++++++++++++++++++++ window-copy.c | 5 +- window-more.c | 5 +- window-scroll.c | 5 +- 14 files changed, 361 insertions(+), 19 deletions(-) create mode 100644 cmd-clock-mode.c create mode 100644 window-clock.c diff --git a/CHANGES b/CHANGES index 907808fa..2e68b029 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,8 @@ 10 January 2009 +* New mode to display a large clock. Entered with clock-mode command (bound to + C-b t by default); two window options: clock-mode-colour and clock-mode-style + (12 or 24). This will probably be used as the basis for window locking. * New command, server-info, to show some server information and terminal details. @@ -838,7 +841,7 @@ (including mutt, emacs). No status bar yet and no key remapping or other customisation. -$Id: CHANGES,v 1.187 2009-01-10 01:51:21 nicm Exp $ +$Id: CHANGES,v 1.188 2009-01-10 19:35:39 nicm Exp $ LocalWords: showw utf UTF fulvio ciriaco joshe OSC APC gettime abc DEF OA clr LocalWords: rivo nurges lscm Erdely eol smysession mysession ek dstname RB diff --git a/Makefile b/Makefile index 46f0f212..a323334f 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.84 2009-01-10 15:21:31 nicm Exp $ +# $Id: Makefile,v 1.85 2009-01-10 19:35:39 nicm Exp $ .SUFFIXES: .c .o .y .h .PHONY: clean update-index.html upload-index.html @@ -36,8 +36,10 @@ SRCS= tmux.c server.c server-msg.c server-fn.c buffer.c buffer-poll.c status.c \ cmd-show-buffer.c cmd-list-buffers.c cmd-delete-buffer.c \ cmd-list-commands.c cmd-move-window.c cmd-select-prompt.c \ cmd-respawn-window.c cmd-source-file.c cmd-server-info.c \ - window-scroll.c window-more.c window-copy.c options.c paste.c \ - tty.c tty-term.c tty-keys.c tty-write.c colour.c utf8.c options-cmd.c + cmd-clock-mode.c \ + window-clock.c window-scroll.c window-more.c window-copy.c \ + options.c options-cmd.c paste.c colour.c utf8.c \ + tty.c tty-term.c tty-keys.c tty-write.c CC?= cc INCDIRS+= -I. -I- -I/usr/local/include diff --git a/TODO b/TODO index 0116e565..a7dde8c4 100644 --- a/TODO +++ b/TODO @@ -62,7 +62,9 @@ - document xterm-keys - document server-info - document window options changes -- a window mode to show a clock +- document clock-mode +- automatic lock/screensaver after $time inactivity (switch all windows into + clock mode/blank) - a key binding to display the status line when it is turned off - FAQ "Can I have some examples of cool things I can do with tmux?" -- linkw - clone session command diff --git a/cmd-clock-mode.c b/cmd-clock-mode.c new file mode 100644 index 00000000..0e76135c --- /dev/null +++ b/cmd-clock-mode.c @@ -0,0 +1,55 @@ +/* $Id: cmd-clock-mode.c,v 1.1 2009-01-10 19:35:39 nicm Exp $ */ + +/* + * Copyright (c) 2009 Nicholas Marriott + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include "tmux.h" + +/* + * Enter clock mode. + */ + +void cmd_clock_mode_exec(struct cmd *, struct cmd_ctx *); + +const struct cmd_entry cmd_clock_mode_entry = { + "clock-mode", NULL, + CMD_TARGET_WINDOW_USAGE, + 0, + cmd_target_init, + cmd_target_parse, + cmd_clock_mode_exec, + cmd_target_send, + cmd_target_recv, + cmd_target_free, + cmd_target_print +}; + +void +cmd_clock_mode_exec(struct cmd *self, struct cmd_ctx *ctx) +{ + struct cmd_target_data *data = self->data; + struct winlink *wl; + + if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) + return; + + window_set_mode(wl->window, &window_clock_mode); + + if (ctx->cmdclient != NULL) + server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); +} diff --git a/cmd-set-window-option.c b/cmd-set-window-option.c index 69dc2248..e0fe02cc 100644 --- a/cmd-set-window-option.c +++ b/cmd-set-window-option.c @@ -1,4 +1,4 @@ -/* $Id: cmd-set-window-option.c,v 1.18 2009-01-10 01:51:21 nicm Exp $ */ +/* $Id: cmd-set-window-option.c,v 1.19 2009-01-10 19:35:39 nicm Exp $ */ /* * Copyright (c) 2008 Nicholas Marriott @@ -50,8 +50,14 @@ const struct cmd_entry cmd_set_window_option_entry = { const char *set_option_mode_keys_list[] = { "emacs", "vi", NULL }; +const char *set_option_clock_mode_style_list[] = { + "12", "24", NULL +}; const struct set_option_entry set_window_option_table[NSETWINDOWOPTION] = { { "aggressive-resize", SET_OPTION_FLAG, 0, 0, NULL }, + { "clock-mode-colour", SET_OPTION_COLOUR, 0, 0, NULL }, + { "clock-mode-style", + SET_OPTION_CHOICE, 0, 0, set_option_clock_mode_style_list }, { "force-height", SET_OPTION_NUMBER, 0, INT_MAX, NULL }, { "force-width", SET_OPTION_NUMBER, 0, INT_MAX, NULL }, { "mode-bg", SET_OPTION_COLOUR, 0, 0, NULL }, diff --git a/cmd.c b/cmd.c index f5e11324..f73ab7d3 100644 --- a/cmd.c +++ b/cmd.c @@ -1,4 +1,4 @@ -/* $Id: cmd.c,v 1.70 2009-01-10 01:51:21 nicm Exp $ */ +/* $Id: cmd.c,v 1.71 2009-01-10 19:35:39 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -28,6 +28,7 @@ const struct cmd_entry *cmd_table[] = { &cmd_attach_session_entry, &cmd_bind_key_entry, + &cmd_clock_mode_entry, &cmd_command_prompt_entry, &cmd_copy_mode_entry, &cmd_delete_buffer_entry, diff --git a/key-bindings.c b/key-bindings.c index 3ffd5a6b..f7b8e75e 100644 --- a/key-bindings.c +++ b/key-bindings.c @@ -1,4 +1,4 @@ -/* $Id: key-bindings.c,v 1.41 2009-01-07 22:52:33 nicm Exp $ */ +/* $Id: key-bindings.c,v 1.42 2009-01-10 19:35:39 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -102,6 +102,7 @@ key_bindings_init(void) { 'p', &cmd_previous_window_entry }, { 'r', &cmd_refresh_client_entry }, { 's', &cmd_list_sessions_entry }, + { 't', &cmd_clock_mode_entry }, { 'w', &cmd_list_windows_entry }, { '\'', &cmd_select_prompt_entry }, { META, &cmd_send_prefix_entry }, diff --git a/server.c b/server.c index abf38278..f0651f07 100644 --- a/server.c +++ b/server.c @@ -1,4 +1,4 @@ -/* $Id: server.c,v 1.91 2009-01-10 01:51:22 nicm Exp $ */ +/* $Id: server.c,v 1.92 2009-01-10 19:35:40 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -54,6 +54,7 @@ void server_lost_client(struct client *); void server_lost_window(struct window *); void server_check_redraw(struct client *); void server_check_timers(struct client *); +void server_second_timers(void); int server_update_socket(const char *); /* Fork new server. */ @@ -168,9 +169,12 @@ server_main(const char *srv_path, int srv_fd) struct pollfd *pfds, *pfd; int nfds, xtimeout; u_int i, n; + time_t now, last; siginit(); + last = time(NULL); + pfds = NULL; while (!sigterm) { /* Initialise pollfd array. */ @@ -211,6 +215,13 @@ server_main(const char *srv_path, int srv_fd) } pfd++; + /* Call seconds-based timers. */ + now = time(NULL); + if (now != last) { + last = now; + server_second_timers(); + } + /* * Handle window and client sockets. Clients can create * windows, so windows must come first to avoid messing up by @@ -688,6 +699,21 @@ server_lost_window(struct window *w) recalculate_sizes(); } +/* Call any once-per-second timers. */ +void +server_second_timers(void) +{ + struct window *w; + u_int i; + + for (i = 0; i < ARRAY_LENGTH(&windows); i++) { + w = ARRAY_ITEM(&windows, i); + if (w->mode != NULL && w->mode->timer != NULL) + w->mode->timer(w); + } +} + +/* Update socket execute permissions based on whether sessions are attached. */ int server_update_socket(const char *path) { diff --git a/tmux.c b/tmux.c index 02016d57..ada0bb4a 100644 --- a/tmux.c +++ b/tmux.c @@ -1,4 +1,4 @@ -/* $Id: tmux.c,v 1.89 2009-01-10 14:43:43 nicm Exp $ */ +/* $Id: tmux.c,v 1.90 2009-01-10 19:35:40 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -248,6 +248,8 @@ main(int argc, char **argv) options_set_number(&global_window_options, "mode-keys", MODEKEY_EMACS); options_set_number(&global_window_options, "force-width", 0); options_set_number(&global_window_options, "force-height", 0); + options_set_number(&global_window_options, "clock-mode-colour", 4); + options_set_number(&global_window_options, "clock-mode-style", 1); if (cfg_file == NULL) { home = getenv("HOME"); @@ -301,6 +303,7 @@ main(int argc, char **argv) } options_set_string( &global_options, "default-command", "exec %s", shell); + if (argc == 0) { cmd = xmalloc(sizeof *cmd); diff --git a/tmux.h b/tmux.h index 8d1006ef..d5541bfe 100644 --- a/tmux.h +++ b/tmux.h @@ -1,4 +1,4 @@ -/* $Id: tmux.h,v 1.217 2009-01-10 18:37:08 nicm Exp $ */ +/* $Id: tmux.h,v 1.218 2009-01-10 19:35:40 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -260,7 +260,7 @@ enum tty_code_code { TTYC_IS1, /* init_1string, i1 */ TTYC_IS2, /* init_2string, i2 */ TTYC_IS3, /* init_3string, i3 */ - TTYC_KCBT, /* key_btab, kB */ + TTYC_KCBT, /* key_btab, kB */ TTYC_KCUB1, /* key_left, kl */ TTYC_KCUD1, /* key_down, kd */ TTYC_KCUF1, /* key_right, kr */ @@ -584,6 +584,7 @@ struct window_mode { void (*free)(struct window *); void (*resize)(struct window *, u_int, u_int); void (*key)(struct window *, struct client *, int); + void (*timer)(struct window *); }; /* Window structure. */ @@ -866,7 +867,7 @@ struct set_option_entry { extern const struct set_option_entry set_option_table[]; extern const struct set_option_entry set_window_option_table[]; #define NSETOPTION 17 -#define NSETWINDOWOPTION 10 +#define NSETWINDOWOPTION 12 /* Edit keys. */ enum mode_key { @@ -1043,6 +1044,7 @@ struct winlink *cmd_find_window( extern const struct cmd_entry *cmd_table[]; extern const struct cmd_entry cmd_attach_session_entry; extern const struct cmd_entry cmd_bind_key_entry; +extern const struct cmd_entry cmd_clock_mode_entry; extern const struct cmd_entry cmd_command_prompt_entry; extern const struct cmd_entry cmd_copy_mode_entry; extern const struct cmd_entry cmd_delete_buffer_entry; @@ -1350,6 +1352,9 @@ void window_reset_mode(struct window *); void window_parse(struct window *); void window_key(struct window *, struct client *, int); +/* window-clock.c */ +extern const struct window_mode window_clock_mode; + /* window-copy.c */ extern const struct window_mode window_copy_mode; diff --git a/window-clock.c b/window-clock.c new file mode 100644 index 00000000..ef231db2 --- /dev/null +++ b/window-clock.c @@ -0,0 +1,235 @@ +/* $Id: window-clock.c,v 1.1 2009-01-10 19:35:40 nicm Exp $ */ + +/* + * Copyright (c) 2009 Nicholas Marriott + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include + +#include "tmux.h" + +struct screen *window_clock_init(struct window *); +void window_clock_free(struct window *); +void window_clock_resize(struct window *, u_int, u_int); +void window_clock_key(struct window *, struct client *, int); +void window_clock_timer(struct window *); + +void window_clock_draw_screen(struct window *); + +const struct window_mode window_clock_mode = { + window_clock_init, + window_clock_free, + window_clock_resize, + window_clock_key, + window_clock_timer +}; + +struct window_clock_mode_data { + struct screen screen; +}; + +struct screen * +window_clock_init(struct window *w) +{ + struct window_clock_mode_data *data; + struct screen *s; + + w->modedata = data = xmalloc(sizeof *data); + + s = &data->screen; + screen_init(s, screen_size_x(&w->base), screen_size_y(&w->base), 0); + s->mode &= ~MODE_CURSOR; + + window_clock_draw_screen(w); + + return (s); +} + +void +window_clock_free(struct window *w) +{ + struct window_clock_mode_data *data = w->modedata; + + screen_free(&data->screen); + xfree(data); +} + +void +window_clock_resize(struct window *w, u_int sx, u_int sy) +{ + struct window_clock_mode_data *data = w->modedata; + struct screen *s = &data->screen; + + screen_resize(s, sx, sy); + window_clock_draw_screen(w); +} + +void +window_clock_key(struct window *w, unused struct client *c, unused int key) +{ + window_reset_mode(w); +} + +void +window_clock_timer(struct window *w) +{ + window_clock_draw_screen(w); + server_redraw_window(w); +} + +void +window_clock_draw_screen(struct window *w) +{ + struct window_clock_mode_data *data = w->modedata; + struct screen *s = &data->screen; + struct screen_write_ctx ctx; + struct grid_cell gc; + char tim[64], *ptr; + time_t t; + u_int colour, i, j, x, y, idx; + char table[14][5][5] = { + { { 1,1,1,1,1 }, /* 0 */ + { 1,0,0,0,1 }, + { 1,0,0,0,1 }, + { 1,0,0,0,1 }, + { 1,1,1,1,1 } }, + { { 0,0,0,0,1 }, /* 1 */ + { 0,0,0,0,1 }, + { 0,0,0,0,1 }, + { 0,0,0,0,1 }, + { 0,0,0,0,1 } }, + { { 1,1,1,1,1 }, /* 2 */ + { 0,0,0,0,1 }, + { 1,1,1,1,1 }, + { 1,0,0,0,0 }, + { 1,1,1,1,1 } }, + { { 1,1,1,1,1 }, /* 3 */ + { 0,0,0,0,1 }, + { 1,1,1,1,1 }, + { 0,0,0,0,1 }, + { 1,1,1,1,1 } }, + { { 1,0,0,0,1 }, /* 4 */ + { 1,0,0,0,1 }, + { 1,1,1,1,1 }, + { 0,0,0,0,1 }, + { 0,0,0,0,1 } }, + { { 1,1,1,1,1 }, /* 5 */ + { 1,0,0,0,0 }, + { 1,1,1,1,1 }, + { 0,0,0,0,1 }, + { 1,1,1,1,1 } }, + { { 1,1,1,1,1 }, /* 6 */ + { 1,0,0,0,0 }, + { 1,1,1,1,1 }, + { 1,0,0,0,1 }, + { 1,1,1,1,1 } }, + { { 1,1,1,1,1 }, /* 7 */ + { 0,0,0,0,1 }, + { 0,0,0,0,1 }, + { 0,0,0,0,1 }, + { 0,0,0,0,1 } }, + { { 1,1,1,1,1 }, /* 8 */ + { 1,0,0,0,1 }, + { 1,1,1,1,1 }, + { 1,0,0,0,1 }, + { 1,1,1,1,1 } }, + { { 1,1,1,1,1 }, /* 9 */ + { 1,0,0,0,1 }, + { 1,1,1,1,1 }, + { 0,0,0,0,1 }, + { 1,1,1,1,1 } }, + { { 0,0,0,0,0 }, /* : */ + { 0,0,1,0,0 }, + { 0,0,0,0,0 }, + { 0,0,1,0,0 }, + { 0,0,0,0,0 } }, + { { 1,1,1,1,1 }, /* A */ + { 1,0,0,0,1 }, + { 1,1,1,1,1 }, + { 1,0,0,0,1 }, + { 1,0,0,0,1 } }, + { { 1,1,1,1,1 }, /* P */ + { 1,0,0,0,1 }, + { 1,1,1,1,1 }, + { 1,0,0,0,0 }, + { 1,0,0,0,0 } }, + { { 1,0,0,0,1 }, /* M */ + { 1,1,0,1,1 }, + { 1,0,1,0,1 }, + { 1,0,0,0,1 }, + { 1,0,0,0,1 } }, + }; + + colour = options_get_number(&w->options, "clock-mode-colour"); + + t = time(NULL); + if (options_get_number(&w->options, "clock-mode-style") == 0) + strftime(tim, sizeof tim, "%l:%M %p", localtime(&t)); + else + strftime(tim, sizeof tim, "%H:%M", localtime(&t)); + + screen_write_start(&ctx, s, NULL, NULL); + screen_write_clearscreen(&ctx); + memcpy(&gc, &grid_default_cell, sizeof gc); + + if (screen_size_x(s) < 6 * strlen(tim) || screen_size_y(s) < 6) { + if (screen_size_x(s) >= strlen(tim) && screen_size_y(s) != 0) { + x = (screen_size_x(s) / 2) - (strlen(tim) / 2); + y = screen_size_y(s) / 2; + screen_write_cursormove(&ctx, x, y); + + gc.fg = colour; + screen_write_puts(&ctx, &gc, "%s", tim); + } + screen_write_stop(&ctx); + return; + } + + x = (screen_size_x(s) / 2) - 3 * strlen(tim); + y = (screen_size_y(s) / 2) - 3; + + for (ptr = tim; *ptr != '\0'; ptr++) { + if (*ptr >= '0' && *ptr <= '9') + idx = *ptr - '0'; + else if (*ptr == ':') + idx = 10; + else if (*ptr == 'A') + idx = 11; + else if (*ptr == 'P') + idx = 12; + else if (*ptr == 'M') + idx = 13; + else { + x += 6; + continue; + } + + for (j = 0; j < 5; j++) { + screen_write_cursormove(&ctx, x, y + j); + for (i = 0; i < 5; i++) { + if (table[idx][j][i]) + gc.bg = colour; + else + gc.bg = 0; + screen_write_putc(&ctx, &gc, ' '); + } + } + x += 6; + } + + screen_write_stop(&ctx); +} diff --git a/window-copy.c b/window-copy.c index 7b8b0b8a..c23ca07e 100644 --- a/window-copy.c +++ b/window-copy.c @@ -1,4 +1,4 @@ -/* $Id: window-copy.c,v 1.36 2009-01-10 01:51:22 nicm Exp $ */ +/* $Id: window-copy.c,v 1.37 2009-01-10 19:35:40 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -63,7 +63,8 @@ const struct window_mode window_copy_mode = { window_copy_init, window_copy_free, window_copy_resize, - window_copy_key + window_copy_key, + NULL }; struct window_copy_mode_data { diff --git a/window-more.c b/window-more.c index dde3e7f3..25eeca4b 100644 --- a/window-more.c +++ b/window-more.c @@ -1,4 +1,4 @@ -/* $Id: window-more.c,v 1.22 2009-01-10 01:41:32 nicm Exp $ */ +/* $Id: window-more.c,v 1.23 2009-01-10 19:35:40 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -38,7 +38,8 @@ const struct window_mode window_more_mode = { window_more_init, window_more_free, window_more_resize, - window_more_key + window_more_key, + NULL }; struct window_more_mode_data { diff --git a/window-scroll.c b/window-scroll.c index a529a82a..7d49036c 100644 --- a/window-scroll.c +++ b/window-scroll.c @@ -1,4 +1,4 @@ -/* $Id: window-scroll.c,v 1.25 2008-12-08 16:19:51 nicm Exp $ */ +/* $Id: window-scroll.c,v 1.26 2009-01-10 19:35:40 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -42,7 +42,8 @@ const struct window_mode window_scroll_mode = { window_scroll_init, window_scroll_free, window_scroll_resize, - window_scroll_key + window_scroll_key, + NULL }; struct window_scroll_mode_data {