cba8acdb5fee767aaa622ddc3d13c846fbf46fe0
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)
100 {
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;
122 }
124 static void
125 clock_init(WINDOW *w, int cols, int rows)
126 {
127 win.w = w;
128 clock_resize(cols, rows);
129 }
131 static const char *
132 clock_title(mpd_unused char *str, mpd_unused size_t size)
133 {
134 return _("Clock");
135 }
137 static void
138 clock_update(mpd_unused screen_t *screen, mpd_unused mpdclient_t *c)
139 {
140 time_t now;
141 struct tm *tm;
142 long t, a;
143 int i, j, s, k;
144 char buf[BUFSIZE];
146 time(&now);
147 tm = localtime(&now);
149 if (win.rows<=YDEPTH+1 || win.cols<=XLENGTH+1) {
150 strftime(buf, BUFSIZE, "%X ",tm);
151 mvwaddstr(win.w, win.rows ? win.rows/2:0, (win.cols-strlen(buf))/2, buf);
152 wrefresh(win.w);
153 return;
154 }
156 mask = 0;
157 set(tm->tm_sec % 10, 0);
158 set(tm->tm_sec / 10, 4);
159 set(tm->tm_min % 10, 10);
160 set(tm->tm_min / 10, 14);
161 set(tm->tm_hour % 10, 20);
162 set(tm->tm_hour / 10, 24);
163 set(10, 7);
164 set(10, 17);
166 for (k = 0; k < 6; k++) {
167 newer[k] = (newer[k] & ~mask) | (next[k] & mask);
168 next[k] = 0;
169 for (s = 1; s >= 0; s--) {
170 standt(s);
171 for (i = 0; i < 6; i++) {
172 if ((a = (newer[i] ^ older[i]) & (s ? newer : older)[i])
173 != 0) {
174 for (j = 0, t = 1 << 26; t; t >>= 1, j++) {
175 if (a & t) {
176 if (!(a & (t << 1))) {
177 wmove(win.w, YBASE + i, XBASE + 2 * j);
178 }
179 if( enable_seconds || j<18 )
180 waddstr(win.w, " ");
181 }
182 }
183 }
184 if (!s) {
185 older[i] = newer[i];
186 }
187 }
188 if (!s) {
189 wrefresh(win.w);
190 }
191 }
192 }
194 #ifdef HAVE_LOCALE_H
195 strftime(buf, BUFSIZE, "%x", tm);
196 # else
197 /* this depends on the detailed format of ctime(3) */
198 strcpy(buf, ctime(&now));
199 strcpy(buf + 10, buf + 19);
200 #endif
201 mvwaddstr(win.w, YBASE+YDEPTH+1, (win.cols-strlen(buf))/2, buf);
203 wmove(win.w, 6, 0);
204 drawbox();
205 wrefresh(win.w);
206 }
208 static void
209 clock_paint(screen_t *screen, mpdclient_t *c)
210 {
211 /* this seems to be a better way to clear the window than wclear() ?! */
212 wmove(win.w, 0, 0);
213 wclrtobot(win.w);
214 clock_update(screen, c);
215 }
217 const struct screen_functions screen_clock = {
218 .init = clock_init,
219 .resize = clock_resize,
220 .paint = clock_paint,
221 .update = clock_update,
222 .get_title = clock_title,
223 };
225 #endif