Code

493150bb056fffd185049476ae4e5b516a8b3ecd
[ncmpc.git] / src / screen_clock.c
1 /*
2  * $Id$
3  *
4  * This file is based on the 'Grand digital clock' (gdc.c) shipped with 
5  * ncurses. 
6  */
8 #include "config.h"
10 #ifndef  DISABLE_CLOCK_SCREEN
11 #include "ncmpc.h"
12 #include "mpdclient.h"
13 #include "options.h"
14 #include "command.h"
15 #include "screen.h"
16 #include "screen_utils.h"
17 #include "gcc.h"
19 #include <time.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <glib.h>
23 #include <ncurses.h>
26 #define YDEPTH  5
27 #define BUFSIZE 64
29 #define ENABLE_SECONDS 0
31 static struct window win;
32 static gboolean enable_seconds = ENABLE_SECONDS;
34 /* orginal variables from gdc.c */
35 static short disp[11] =
36         {
37                 075557, 011111, 071747, 071717, 055711,
38                 074717, 074757, 071111, 075757, 075717, 002020
39         };
41 static long older[6], next[6], newer[6], mask;
43 static int YBASE = 10;
44 static int XBASE = 10;
45 static int XLENGTH = 54;
47 /* orginal functions */
48 static void
49 set(int t, int n)
50 {
51         int i, m;
53         m = 7 << n;
54         for (i = 0; i < 5; i++) {
55                 next[i] |= ((disp[t] >> ((4 - i) * 3)) & 07) << n;
56                 mask |= (next[i] ^ older[i]) & m;
57         }
58         if (mask & m)
59                 mask |= m;
60 }
62 static void
63 drawbox(void)
64 {
65         chtype bottom[XLENGTH + 1];
66         int n;
68         mvwaddch(win.w, YBASE - 1, XBASE - 1, ACS_ULCORNER);
69         whline(win.w, ACS_HLINE, XLENGTH);
70         mvwaddch(win.w, YBASE - 1, XBASE + XLENGTH, ACS_URCORNER);
72         mvwaddch(win.w, YBASE + YDEPTH, XBASE - 1, ACS_LLCORNER);
73         mvwinchnstr(win.w, YBASE + YDEPTH, XBASE, bottom, XLENGTH);
74         for (n = 0; n < XLENGTH; n++)
75                 bottom[n] = ACS_HLINE | (bottom[n] & (A_ATTRIBUTES | A_COLOR));
76         mvwaddchnstr(win.w, YBASE + YDEPTH, XBASE, bottom, XLENGTH);
77         mvwaddch(win.w, YBASE + YDEPTH, XBASE + XLENGTH, ACS_LRCORNER);
79         wmove(win.w, YBASE, XBASE - 1);
80         wvline(win.w, ACS_VLINE, YDEPTH);
82         wmove(win.w, YBASE, XBASE + XLENGTH);
83         wvline(win.w, ACS_VLINE, YDEPTH);
84 }
87 static void
88 standt(int on)
89 {
90         if (on)
91                 wattron(win.w, A_REVERSE);
92         else
93                 wattroff(win.w, A_REVERSE);
94 }
96 /* ncmpc screen functions */
98 static void
99 clock_resize(int cols, int rows)
101         int j;
103         for (j = 0; j < 5; j++)
104                 older[j] = newer[j] = next[j] = 0;
106         win.cols = cols;
107         win.rows = rows;
109         if (cols < 60)
110                 enable_seconds = FALSE;
111         else
112                 enable_seconds = ENABLE_SECONDS;
114         if (enable_seconds)
115                 XLENGTH = 54;
116         else
117                 XLENGTH = 54-18;
120         XBASE = (cols-XLENGTH)/2;
121         YBASE = (rows-YDEPTH)/2-(YDEPTH/2)+2;
124 static void
125 clock_init(WINDOW *w, int cols, int rows)
127         win.w = w;
128         clock_resize(cols, rows);
131 static void
132 clock_exit(void)
136 static void
137 clock_open(mpd_unused screen_t *screen, mpd_unused mpdclient_t *c)
139         int j;
141         for (j = 0; j < 5; j++)
142                 older[j] = newer[j] = next[j] = 0;
146 static void
147 clock_close(void)
151 static const char *
152 clock_title(mpd_unused char *str, mpd_unused size_t size)
154         return _("Clock");
157 static void
158 clock_update(mpd_unused screen_t *screen, mpd_unused mpdclient_t *c)
160         time_t now;
161         struct tm *tm;
162         long t, a;
163         int i, j, s, k;
164         char buf[BUFSIZE];
166         time(&now);
167         tm = localtime(&now);
169         if (win.rows<=YDEPTH+1 || win.cols<=XLENGTH+1) {
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         }
176         mask = 0;
177         set(tm->tm_sec % 10, 0);
178         set(tm->tm_sec / 10, 4);
179         set(tm->tm_min % 10, 10);
180         set(tm->tm_min / 10, 14);
181         set(tm->tm_hour % 10, 20);
182         set(tm->tm_hour / 10, 24);
183         set(10, 7);
184         set(10, 17);
186         for (k = 0; k < 6; k++) {
187                 newer[k] = (newer[k] & ~mask) | (next[k] & mask);
188                 next[k] = 0;
189                 for (s = 1; s >= 0; s--) {
190                         standt(s);
191                         for (i = 0; i < 6; i++) {
192                                 if ((a = (newer[i] ^ older[i]) & (s ? newer : older)[i])
193                                     != 0) {
194                                         for (j = 0, t = 1 << 26; t; t >>= 1, j++) {
195                                                 if (a & t) {
196                                                         if (!(a & (t << 1))) {
197                                                                 wmove(win.w, YBASE + i, XBASE + 2 * j);
198                                                         }
199                                                         if( enable_seconds || j<18 )
200                                                                 waddstr(win.w, "  ");
201                                                 }
202                                         }
203                                 }
204                                 if (!s) {
205                                         older[i] = newer[i];
206                                 }
207                         }
208                         if (!s) {
209                                 wrefresh(win.w);
210                         }
211                 }
212         }
214 #ifdef HAVE_LOCALE_H
215         strftime(buf, BUFSIZE, "%x", tm);
216 # else
217         /* this depends on the detailed format of ctime(3) */
218         strcpy(buf, ctime(&now));
219         strcpy(buf + 10, buf + 19);
220 #endif
221         mvwaddstr(win.w, YBASE+YDEPTH+1, (win.cols-strlen(buf))/2, buf);
223         wmove(win.w, 6, 0);
224         drawbox();
225         wrefresh(win.w);
228 static void
229 clock_paint(screen_t *screen, mpdclient_t *c)
231         /* this seems to be a better way to clear the window than wclear() ?! */
232         wmove(win.w, 0, 0);
233         wclrtobot(win.w);
234         clock_update(screen, c);
237 static int
238 clock_cmd(mpd_unused screen_t *screen, mpd_unused mpdclient_t *c,
239           mpd_unused command_t cmd)
241         return 0;
244 screen_functions_t *
245 get_screen_clock(void)
247         static screen_functions_t functions;
249         memset(&functions, 0, sizeof(screen_functions_t));
250         functions.init = clock_init;
251         functions.exit = clock_exit;
252         functions.open = clock_open;
253         functions.close = clock_close;
254         functions.resize = clock_resize;
255         functions.paint = clock_paint;
256         functions.update = clock_update;
257         functions.cmd = clock_cmd;
258         functions.get_lw = NULL;
259         functions.get_title = clock_title;
261         return &functions;
264 #endif