aboutsummaryrefslogblamecommitdiffstats
path: root/src/screen_clock.c
blob: cba8acdb5fee767aaa622ddc3d13c846fbf46fe0 (plain) (tree)
1
2
3
4
5
6
7
8
9
  

       



                                                                        

                   
                             
                  
                      
                    


                         
                
 






                    




                        
                         



                                                



                                                              










                                              








                                                                  




             


















                                                                               





              



                                           

 




                                




















                                                  

 
           

                                         

                                 

 
                   
                                                         
 
                          

 
           
                                                                    














                                                                                         
         




































                                                                                                       
         
 
                    
                                         
      


                                                             
      




                                                                        

 
           
                                             
 



                                                                                

 

                                              


                               

                                 
 
      
/*
 * $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 <time.h>
#include <stdlib.h>
#include <string.h>
#include <glib.h>
#include <ncurses.h>


#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