/* * $Id$ * * This file is based on the 'Grand digital clock' (gdc.c) shipped with * ncurses. */ #include "config.h" #ifndef DISABLE_CLOCK_SCREEN #include "ncmpc.h" #include "mpdclient.h" #include "options.h" #include "command.h" #include "screen.h" #include "screen_utils.h" #include "gcc.h" #include #include #include #include #include #define YDEPTH 5 #define BUFSIZE 64 #define ENABLE_SECONDS 0 static struct window win; static gboolean enable_seconds = ENABLE_SECONDS; /* orginal variables from gdc.c */ static short disp[11] = { 075557, 011111, 071747, 071717, 055711, 074717, 074757, 071111, 075757, 075717, 002020 }; static long older[6], next[6], newer[6], mask; static int YBASE = 10; static int XBASE = 10; static int XLENGTH = 54; /* orginal functions */ static void set(int t, int n) { int i, m; m = 7 << n; for (i = 0; i < 5; i++) { next[i] |= ((disp[t] >> ((4 - i) * 3)) & 07) << n; mask |= (next[i] ^ older[i]) & m; } if (mask & m) mask |= m; } static void drawbox(void) { chtype bottom[XLENGTH + 1]; int n; mvwaddch(win.w, YBASE - 1, XBASE - 1, ACS_ULCORNER); whline(win.w, ACS_HLINE, XLENGTH); mvwaddch(win.w, YBASE - 1, XBASE + XLENGTH, ACS_URCORNER); mvwaddch(win.w, YBASE + YDEPTH, XBASE - 1, ACS_LLCORNER); mvwinchnstr(win.w, YBASE + YDEPTH, XBASE, bottom, XLENGTH); for (n = 0; n < XLENGTH; n++) bottom[n] = ACS_HLINE | (bottom[n] & (A_ATTRIBUTES | A_COLOR)); mvwaddchnstr(win.w, YBASE + YDEPTH, XBASE, bottom, XLENGTH); mvwaddch(win.w, YBASE + YDEPTH, XBASE + XLENGTH, ACS_LRCORNER); wmove(win.w, YBASE, XBASE - 1); wvline(win.w, ACS_VLINE, YDEPTH); wmove(win.w, YBASE, XBASE + XLENGTH); wvline(win.w, ACS_VLINE, YDEPTH); } static void standt(int on) { if (on) wattron(win.w, A_REVERSE); else wattroff(win.w, A_REVERSE); } /* ncmpc screen functions */ static void clock_resize(int cols, int rows) { int j; for (j = 0; j < 5; j++) older[j] = newer[j] = next[j] = 0; win.cols = cols; win.rows = rows; if (cols < 60) enable_seconds = FALSE; else enable_seconds = ENABLE_SECONDS; if (enable_seconds) XLENGTH = 54; else XLENGTH = 54-18; XBASE = (cols-XLENGTH)/2; YBASE = (rows-YDEPTH)/2-(YDEPTH/2)+2; } static void clock_init(WINDOW *w, int cols, int rows) { win.w = w; clock_resize(cols, rows); } static const char * clock_title(mpd_unused char *str, mpd_unused size_t size) { return _("Clock"); } static void clock_update(mpd_unused screen_t *screen, mpd_unused mpdclient_t *c) { time_t now; struct tm *tm; long t, a; int i, j, s, k; char buf[BUFSIZE]; time(&now); tm = localtime(&now); if (win.rows<=YDEPTH+1 || win.cols<=XLENGTH+1) { strftime(buf, BUFSIZE, "%X ",tm); mvwaddstr(win.w, win.rows ? win.rows/2:0, (win.cols-strlen(buf))/2, buf); wrefresh(win.w); return; } mask = 0; set(tm->tm_sec % 10, 0); set(tm->tm_sec / 10, 4); set(tm->tm_min % 10, 10); set(tm->tm_min / 10, 14); set(tm->tm_hour % 10, 20); set(tm->tm_hour / 10, 24); set(10, 7); set(10, 17); for (k = 0; k < 6; k++) { newer[k] = (newer[k] & ~mask) | (next[k] & mask); next[k] = 0; for (s = 1; s >= 0; s--) { standt(s); for (i = 0; i < 6; i++) { if ((a = (newer[i] ^ older[i]) & (s ? newer : older)[i]) != 0) { for (j = 0, t = 1 << 26; t; t >>= 1, j++) { if (a & t) { if (!(a & (t << 1))) { wmove(win.w, YBASE + i, XBASE + 2 * j); } if( enable_seconds || j<18 ) waddstr(win.w, " "); } } } if (!s) { older[i] = newer[i]; } } if (!s) { wrefresh(win.w); } } } #ifdef HAVE_LOCALE_H strftime(buf, BUFSIZE, "%x", tm); # else /* this depends on the detailed format of ctime(3) */ strcpy(buf, ctime(&now)); strcpy(buf + 10, buf + 19); #endif mvwaddstr(win.w, YBASE+YDEPTH+1, (win.cols-strlen(buf))/2, buf); wmove(win.w, 6, 0); drawbox(); wrefresh(win.w); } static void clock_paint(screen_t *screen, mpdclient_t *c) { /* this seems to be a better way to clear the window than wclear() ?! */ wmove(win.w, 0, 0); wclrtobot(win.w); clock_update(screen, c); } const struct screen_functions screen_clock = { .init = clock_init, .resize = clock_resize, .paint = clock_paint, .update = clock_update, .get_title = clock_title, }; #endif