Coverage Report

Created: 2025-04-11 06:41

/src/tmux/window-clock.c
Line
Count
Source (jump to first uncovered line)
1
/* $OpenBSD$ */
2
3
/*
4
 * Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16
 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <sys/types.h>
20
21
#include <stdlib.h>
22
#include <string.h>
23
#include <time.h>
24
25
#include "tmux.h"
26
27
static struct screen *window_clock_init(struct window_mode_entry *,
28
        struct cmd_find_state *, struct args *);
29
static void window_clock_free(struct window_mode_entry *);
30
static void window_clock_resize(struct window_mode_entry *, u_int, u_int);
31
static void window_clock_key(struct window_mode_entry *, struct client *,
32
         struct session *, struct winlink *, key_code,
33
         struct mouse_event *);
34
35
static void window_clock_timer_callback(int, short, void *);
36
static void window_clock_draw_screen(struct window_mode_entry *);
37
38
const struct window_mode window_clock_mode = {
39
  .name = "clock-mode",
40
41
  .init = window_clock_init,
42
  .free = window_clock_free,
43
  .resize = window_clock_resize,
44
  .key = window_clock_key,
45
};
46
47
struct window_clock_mode_data {
48
  struct screen         screen;
49
  time_t      tim;
50
  struct event    timer;
51
};
52
53
const char window_clock_table[14][5][5] = {
54
  { { 1,1,1,1,1 }, /* 0 */
55
    { 1,0,0,0,1 },
56
    { 1,0,0,0,1 },
57
    { 1,0,0,0,1 },
58
    { 1,1,1,1,1 } },
59
  { { 0,0,0,0,1 }, /* 1 */
60
    { 0,0,0,0,1 },
61
    { 0,0,0,0,1 },
62
    { 0,0,0,0,1 },
63
    { 0,0,0,0,1 } },
64
  { { 1,1,1,1,1 }, /* 2 */
65
    { 0,0,0,0,1 },
66
    { 1,1,1,1,1 },
67
    { 1,0,0,0,0 },
68
    { 1,1,1,1,1 } },
69
  { { 1,1,1,1,1 }, /* 3 */
70
    { 0,0,0,0,1 },
71
    { 1,1,1,1,1 },
72
    { 0,0,0,0,1 },
73
    { 1,1,1,1,1 } },
74
  { { 1,0,0,0,1 }, /* 4 */
75
    { 1,0,0,0,1 },
76
    { 1,1,1,1,1 },
77
    { 0,0,0,0,1 },
78
    { 0,0,0,0,1 } },
79
  { { 1,1,1,1,1 }, /* 5 */
80
    { 1,0,0,0,0 },
81
    { 1,1,1,1,1 },
82
    { 0,0,0,0,1 },
83
    { 1,1,1,1,1 } },
84
  { { 1,1,1,1,1 }, /* 6 */
85
    { 1,0,0,0,0 },
86
    { 1,1,1,1,1 },
87
    { 1,0,0,0,1 },
88
    { 1,1,1,1,1 } },
89
  { { 1,1,1,1,1 }, /* 7 */
90
    { 0,0,0,0,1 },
91
    { 0,0,0,0,1 },
92
    { 0,0,0,0,1 },
93
    { 0,0,0,0,1 } },
94
  { { 1,1,1,1,1 }, /* 8 */
95
    { 1,0,0,0,1 },
96
    { 1,1,1,1,1 },
97
    { 1,0,0,0,1 },
98
    { 1,1,1,1,1 } },
99
  { { 1,1,1,1,1 }, /* 9 */
100
    { 1,0,0,0,1 },
101
    { 1,1,1,1,1 },
102
    { 0,0,0,0,1 },
103
    { 1,1,1,1,1 } },
104
  { { 0,0,0,0,0 }, /* : */
105
    { 0,0,1,0,0 },
106
    { 0,0,0,0,0 },
107
    { 0,0,1,0,0 },
108
    { 0,0,0,0,0 } },
109
  { { 1,1,1,1,1 }, /* A */
110
    { 1,0,0,0,1 },
111
    { 1,1,1,1,1 },
112
    { 1,0,0,0,1 },
113
    { 1,0,0,0,1 } },
114
  { { 1,1,1,1,1 }, /* P */
115
    { 1,0,0,0,1 },
116
    { 1,1,1,1,1 },
117
    { 1,0,0,0,0 },
118
    { 1,0,0,0,0 } },
119
  { { 1,0,0,0,1 }, /* M */
120
    { 1,1,0,1,1 },
121
    { 1,0,1,0,1 },
122
    { 1,0,0,0,1 },
123
    { 1,0,0,0,1 } },
124
};
125
126
static void
127
window_clock_timer_callback(__unused int fd, __unused short events, void *arg)
128
0
{
129
0
  struct window_mode_entry  *wme = arg;
130
0
  struct window_pane    *wp = wme->wp;
131
0
  struct window_clock_mode_data *data = wme->data;
132
0
  struct tm      now, then;
133
0
  time_t         t;
134
0
  struct timeval       tv = { .tv_sec = 1 };
135
136
0
  evtimer_del(&data->timer);
137
0
  evtimer_add(&data->timer, &tv);
138
139
0
  if (TAILQ_FIRST(&wp->modes) != wme)
140
0
    return;
141
142
0
  t = time(NULL);
143
0
  gmtime_r(&t, &now);
144
0
  gmtime_r(&data->tim, &then);
145
0
  if (now.tm_min == then.tm_min)
146
0
    return;
147
0
  data->tim = t;
148
149
0
  window_clock_draw_screen(wme);
150
0
  wp->flags |= PANE_REDRAW;
151
0
}
152
153
static struct screen *
154
window_clock_init(struct window_mode_entry *wme,
155
    __unused struct cmd_find_state *fs, __unused struct args *args)
156
0
{
157
0
  struct window_pane    *wp = wme->wp;
158
0
  struct window_clock_mode_data *data;
159
0
  struct screen     *s;
160
0
  struct timeval       tv = { .tv_sec = 1 };
161
162
0
  wme->data = data = xmalloc(sizeof *data);
163
0
  data->tim = time(NULL);
164
165
0
  evtimer_set(&data->timer, window_clock_timer_callback, wme);
166
0
  evtimer_add(&data->timer, &tv);
167
168
0
  s = &data->screen;
169
0
  screen_init(s, screen_size_x(&wp->base), screen_size_y(&wp->base), 0);
170
0
  s->mode &= ~MODE_CURSOR;
171
172
0
  window_clock_draw_screen(wme);
173
174
0
  return (s);
175
0
}
176
177
static void
178
window_clock_free(struct window_mode_entry *wme)
179
0
{
180
0
  struct window_clock_mode_data *data = wme->data;
181
182
0
  evtimer_del(&data->timer);
183
0
  screen_free(&data->screen);
184
0
  free(data);
185
0
}
186
187
static void
188
window_clock_resize(struct window_mode_entry *wme, u_int sx, u_int sy)
189
0
{
190
0
  struct window_clock_mode_data *data = wme->data;
191
0
  struct screen     *s = &data->screen;
192
193
0
  screen_resize(s, sx, sy, 0);
194
0
  window_clock_draw_screen(wme);
195
0
}
196
197
static void
198
window_clock_key(struct window_mode_entry *wme, __unused struct client *c,
199
    __unused struct session *s, __unused struct winlink *wl,
200
    __unused key_code key, __unused struct mouse_event *m)
201
0
{
202
0
  window_pane_reset_mode(wme->wp);
203
0
}
204
205
static void
206
window_clock_draw_screen(struct window_mode_entry *wme)
207
0
{
208
0
  struct window_pane    *wp = wme->wp;
209
0
  struct window_clock_mode_data *data = wme->data;
210
0
  struct screen_write_ctx    ctx;
211
0
  int        colour, style;
212
0
  struct screen     *s = &data->screen;
213
0
  struct grid_cell     gc;
214
0
  char         tim[64], *ptr;
215
0
  time_t         t;
216
0
  struct tm     *tm;
217
0
  u_int        i, j, x, y, idx;
218
219
0
  colour = options_get_number(wp->window->options, "clock-mode-colour");
220
0
  style = options_get_number(wp->window->options, "clock-mode-style");
221
222
0
  screen_write_start(&ctx, s);
223
224
0
  t = time(NULL);
225
0
  tm = localtime(&t);
226
0
  if (style == 0) {
227
0
    strftime(tim, sizeof tim, "%l:%M ", localtime(&t));
228
0
    if (tm->tm_hour >= 12)
229
0
      strlcat(tim, "PM", sizeof tim);
230
0
    else
231
0
      strlcat(tim, "AM", sizeof tim);
232
0
  } else
233
0
    strftime(tim, sizeof tim, "%H:%M", tm);
234
235
0
  screen_write_clearscreen(&ctx, 8);
236
237
0
  if (screen_size_x(s) < 6 * strlen(tim) || screen_size_y(s) < 6) {
238
0
    if (screen_size_x(s) >= strlen(tim) && screen_size_y(s) != 0) {
239
0
      x = (screen_size_x(s) / 2) - (strlen(tim) / 2);
240
0
      y = screen_size_y(s) / 2;
241
0
      screen_write_cursormove(&ctx, x, y, 0);
242
243
0
      memcpy(&gc, &grid_default_cell, sizeof gc);
244
0
      gc.flags |= GRID_FLAG_NOPALETTE;
245
0
      gc.fg = colour;
246
0
      screen_write_puts(&ctx, &gc, "%s", tim);
247
0
    }
248
249
0
    screen_write_stop(&ctx);
250
0
    return;
251
0
  }
252
253
0
  x = (screen_size_x(s) / 2) - 3 * strlen(tim);
254
0
  y = (screen_size_y(s) / 2) - 3;
255
256
0
  memcpy(&gc, &grid_default_cell, sizeof gc);
257
0
  gc.flags |= GRID_FLAG_NOPALETTE;
258
0
  gc.bg = colour;
259
0
  for (ptr = tim; *ptr != '\0'; ptr++) {
260
0
    if (*ptr >= '0' && *ptr <= '9')
261
0
      idx = *ptr - '0';
262
0
    else if (*ptr == ':')
263
0
      idx = 10;
264
0
    else if (*ptr == 'A')
265
0
      idx = 11;
266
0
    else if (*ptr == 'P')
267
0
      idx = 12;
268
0
    else if (*ptr == 'M')
269
0
      idx = 13;
270
0
    else {
271
0
      x += 6;
272
0
      continue;
273
0
    }
274
275
0
    for (j = 0; j < 5; j++) {
276
0
      for (i = 0; i < 5; i++) {
277
0
        screen_write_cursormove(&ctx, x + i, y + j, 0);
278
0
        if (window_clock_table[idx][j][i])
279
0
          screen_write_putc(&ctx, &gc, ' ');
280
0
      }
281
0
    }
282
0
    x += 6;
283
0
  }
284
285
0
  screen_write_stop(&ctx);
286
0
}