1 /*
2 * This file is based on the 'Grand digital clock' (gdc.c) shipped with
3 * ncurses.
4 */
6 #include <time.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <glib.h>
10 #include <ncurses.h>
12 #include "config.h"
14 #ifdef ENABLE_CLOCK_SCREEN
15 #include "ncmpc.h"
16 #include "libmpdclient.h"
17 #include "options.h"
18 #include "mpc.h"
19 #include "command.h"
20 #include "screen.h"
21 #include "screen_utils.h"
23 #define YDEPTH 5
24 #define BUFSIZE 64
26 #define ENABLE_SECONDS 0
28 static window_t win = { NULL, 0, 0 };
29 static gboolean enable_seconds = ENABLE_SECONDS;
31 /* orginal variables from gdc.c */
32 static short disp[11] =
33 {
34 075557, 011111, 071747, 071717, 055711,
35 074717, 074757, 071111, 075757, 075717, 002020
36 };
38 static long older[6], next[6], newer[6], mask;
40 static int YBASE = 10;
41 static int XBASE = 10;
42 static int XLENGTH = 54;
44 /* orginal functions */
45 static void
46 set(int t, int n)
47 {
48 int i, m;
50 m = 7 << n;
51 for (i = 0; i < 5; i++) {
52 next[i] |= ((disp[t] >> ((4 - i) * 3)) & 07) << n;
53 mask |= (next[i] ^ older[i]) & m;
54 }
55 if (mask & m)
56 mask |= m;
57 }
59 static void
60 drawbox(void)
61 {
62 chtype bottom[XLENGTH + 1];
63 int n;
65 mvwaddch(win.w, YBASE - 1, XBASE - 1, ACS_ULCORNER);
66 whline(win.w, ACS_HLINE, XLENGTH);
67 mvwaddch(win.w, YBASE - 1, XBASE + XLENGTH, ACS_URCORNER);
69 mvwaddch(win.w, YBASE + YDEPTH, XBASE - 1, ACS_LLCORNER);
70 mvwinchnstr(win.w, YBASE + YDEPTH, XBASE, bottom, XLENGTH);
71 for (n = 0; n < XLENGTH; n++)
72 bottom[n] = ACS_HLINE | (bottom[n] & (A_ATTRIBUTES | A_COLOR));
73 mvwaddchnstr(win.w, YBASE + YDEPTH, XBASE, bottom, XLENGTH);
74 mvwaddch(win.w, YBASE + YDEPTH, XBASE + XLENGTH, ACS_LRCORNER);
76 wmove(win.w, YBASE, XBASE - 1);
77 wvline(win.w, ACS_VLINE, YDEPTH);
79 wmove(win.w, YBASE, XBASE + XLENGTH);
80 wvline(win.w, ACS_VLINE, YDEPTH);
81 }
84 static void
85 standt(int on)
86 {
87 if(on)
88 wattron(win.w, A_REVERSE);
89 else
90 wattroff(win.w, A_REVERSE);
91 }
95 /* ncmpc screen functions */
97 static void
98 clock_resize(int cols, int rows)
99 {
100 int j;
102 for (j = 0; j < 5; j++)
103 older[j] = newer[j] = next[j] = 0;
105 win.cols = cols;
106 win.rows = rows;
108 if( cols<60 )
109 enable_seconds = FALSE;
110 else
111 enable_seconds = ENABLE_SECONDS;
113 if( enable_seconds )
114 XLENGTH = 54;
115 else
116 XLENGTH = 54-18;
119 XBASE = (cols-XLENGTH)/2;
120 YBASE = (rows-YDEPTH)/2-(YDEPTH/2)+2;
121 }
123 static void
124 clock_init(WINDOW *w, int cols, int rows)
125 {
126 win.w = w;
127 clock_resize(cols, rows);
128 }
130 static void
131 clock_exit(void)
132 {
133 }
135 static void
136 clock_open(screen_t *screen, mpd_client_t *c)
137 {
138 int j;
140 for (j = 0; j < 5; j++)
141 older[j] = newer[j] = next[j] = 0;
143 }
145 static void
146 clock_close(void)
147 {
148 }
150 static char *
151 clock_title(char *str, size_t size)
152 {
153 return _("Clock");
154 }
156 static void
157 clock_update(screen_t *screen, mpd_client_t *c)
158 {
159 time_t now;
160 struct tm *tm;
161 long t, a;
162 int i, j, s, k;
163 char buf[BUFSIZE];
165 time(&now);
166 tm = localtime(&now);
168 if( win.rows<=YDEPTH+1 || win.cols<=XLENGTH+1 )
169 {
170 strftime(buf, BUFSIZE, "%X ",tm);
171 mvwaddstr(win.w, win.rows ? win.rows/2:0, (win.cols-strlen(buf))/2, buf);
172 wrefresh(win.w);
173 return;
174 }
178 mask = 0;
179 set(tm->tm_sec % 10, 0);
180 set(tm->tm_sec / 10, 4);
181 set(tm->tm_min % 10, 10);
182 set(tm->tm_min / 10, 14);
183 set(tm->tm_hour % 10, 20);
184 set(tm->tm_hour / 10, 24);
185 set(10, 7);
186 set(10, 17);
188 for (k = 0; k < 6; k++) {
189 newer[k] = (newer[k] & ~mask) | (next[k] & mask);
190 next[k] = 0;
191 for (s = 1; s >= 0; s--) {
192 standt(s);
193 for (i = 0; i < 6; i++) {
194 if ((a = (newer[i] ^ older[i]) & (s ? newer : older)[i])
195 != 0) {
196 for (j = 0, t = 1 << 26; t; t >>= 1, j++) {
197 if (a & t) {
198 if (!(a & (t << 1))) {
199 wmove(win.w, YBASE + i, XBASE + 2 * j);
200 }
201 if( enable_seconds || j<18 )
202 waddstr(win.w, " ");
203 }
204 }
205 }
206 if (!s) {
207 older[i] = newer[i];
208 }
209 }
210 if (!s) {
211 wrefresh(win.w);
212 }
213 }
214 }
216 #ifdef HAVE_LOCALE_H
217 strftime(buf, BUFSIZE, "%x", tm);
218 # else
219 /* this depends on the detailed format of ctime(3) */
220 strcpy(buf, ctime(&now));
221 strcpy(buf + 10, buf + 19);
222 #endif
223 mvwaddstr(win.w, YBASE+YDEPTH+1, (win.cols-strlen(buf))/2, buf);
225 wmove(win.w, 6, 0);
226 drawbox();
227 wrefresh(win.w);
228 }
230 static void
231 clock_paint(screen_t *screen, mpd_client_t *c)
232 {
233 /* this seems to be a better way to clear the window than wclear() ?! */
234 wmove(win.w, 0, 0);
235 wclrtobot(win.w);
236 clock_update(screen, c);
237 }
241 static int
242 clock_cmd(screen_t *screen, mpd_client_t *c, command_t cmd)
243 {
244 return 0;
245 }
248 screen_functions_t *
249 get_screen_clock(void)
250 {
251 static screen_functions_t functions;
253 memset(&functions, 0, sizeof(screen_functions_t));
254 functions.init = clock_init;
255 functions.exit = clock_exit;
256 functions.open = clock_open;
257 functions.close = clock_close;
258 functions.resize = clock_resize;
259 functions.paint = clock_paint;
260 functions.update = clock_update;
261 functions.cmd = clock_cmd;
262 functions.get_lw = NULL;
263 functions.get_title = clock_title;
265 return &functions;
266 }
269 #endif