You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

434 lines
12 KiB

/*
* TTY-CLOCK Main file.
* Copyright © 2008 Martin Duquesnoy <xorg62@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of the nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "ttyclock.h"
void
init(void)
{
struct sigaction sig;
int bg = COLOR_BLACK;
/* Init ncurses */
initscr();
noecho();
keypad(stdscr, True);
start_color();
curs_set(False);
clear();
/* Init default terminal color */
if(use_default_colors() == OK)
bg = -1;
/* Init color pair */
init_pair(0, bg, bg);
init_pair(1, bg, COLOR_GREEN);
init_pair(2, COLOR_GREEN, bg);
refresh();
/* Init signal handler */
sig.sa_handler = signal_handler;
sig.sa_flags = 0;
sigaction(SIGWINCH, &sig, NULL);
sigaction(SIGTERM, &sig, NULL);
sigaction(SIGINT, &sig, NULL);
sigaction(SIGSEGV, &sig, NULL);
/* Init global struct */
ttyclock->running = True;
ttyclock->geo.x = 0;
ttyclock->geo.y = 0;
ttyclock->geo.w = (ttyclock->option.second) ? SECFRAMEW : NORMFRAMEW;
ttyclock->geo.h = 7;
ttyclock->tm = localtime(&(ttyclock->lt));
ttyclock->lt = time(NULL);
update_hour();
/* Create clock win */
ttyclock->framewin = newwin(ttyclock->geo.h,
ttyclock->geo.w,
ttyclock->geo.x,
ttyclock->geo.y);
box(ttyclock->framewin, 0, 0);
/* Create the date win */
ttyclock->datewin = newwin(DATEWINH, strlen(ttyclock->date.datestr) + 2,
ttyclock->geo.x + ttyclock->geo.h - 1,
ttyclock->geo.y + (ttyclock->geo.w / 2) -
(strlen(ttyclock->date.datestr) / 2) - 1);
box(ttyclock->datewin, 0, 0);
clearok(ttyclock->datewin, True);
set_center(ttyclock->option.center);
wrefresh(ttyclock->datewin);
wrefresh(ttyclock->framewin);
return;
}
void
signal_handler(int signal)
{
switch(signal)
{
case SIGWINCH:
/* If the terminal is resizing */
if(ttyclock->option.center)
{
endwin();
init();
}
break;
/* Interruption signal */
case SIGINT:
case SIGTERM:
ttyclock->running = False;
/* Segmentation fault signal */
break;
case SIGSEGV:
endwin();
fprintf(stderr, "Segmentation fault.\n");
exit(EXIT_FAILURE);
break;
}
return;
}
void
update_hour(void)
{
int ihour;
ttyclock->tm = localtime(&(ttyclock->lt));
ttyclock->lt = time(NULL);
ihour = ttyclock->tm->tm_hour;
if(ttyclock->option.twelve)
ttyclock->meridiem = (ihour > 12) ? " [PM]" : " [AM]";
else
ttyclock->meridiem = "";
/* Manage hour for twelve mode */
ihour = ((ttyclock->option.twelve && ihour > 12) ? (ihour - 12) : ihour);
ihour = ((ttyclock->option.twelve && !ihour) ? 12 : ihour);
/* Set hour */
ttyclock->date.hour[0] = ihour / 10;
ttyclock->date.hour[1] = ihour % 10;
/* Set minutes */
ttyclock->date.minute[0] = ttyclock->tm->tm_min / 10;
ttyclock->date.minute[1] = ttyclock->tm->tm_min % 10;
/* Set date string */
sprintf(ttyclock->date.datestr,
"%.2d/%.2d/%d%s",
ttyclock->tm->tm_mday,
ttyclock->tm->tm_mon + 1,
ttyclock->tm->tm_year + 1900,
ttyclock->meridiem);
/* Set seconds */
ttyclock->date.second[0] = ttyclock->tm->tm_sec / 10;
ttyclock->date.second[1] = ttyclock->tm->tm_sec % 10;
return;
}
void
draw_number(int n, int x, int y)
{
int i, sy = y;
for(i = 0; i < 30; ++i, ++sy)
{
if(sy == y + 6)
{
sy = y;
++x;
}
wbkgdset(ttyclock->framewin, COLOR_PAIR(number[n][i/2]));
mvwaddch(ttyclock->framewin, x, sy, ' ');
}
wrefresh(ttyclock->framewin);
return;
}
void
draw_clock(void)
{
/* Draw hour numbers */
draw_number(ttyclock->date.hour[0], 1, 1);
draw_number(ttyclock->date.hour[1], 1, 8);
/* 2 dot for number separation */
wbkgdset(ttyclock->framewin, COLOR_PAIR(1));
mvwaddstr(ttyclock->framewin, 2, 16, " ");
mvwaddstr(ttyclock->framewin, 4, 16, " ");
/* Draw minute numbers */
draw_number(ttyclock->date.minute[0], 1, 20);
draw_number(ttyclock->date.minute[1], 1, 27);
/* Draw the date */
wbkgdset(ttyclock->datewin, (COLOR_PAIR(2)));
mvwprintw(ttyclock->datewin, (DATEWINH - (DATEWINH / 2) - 1), 1, ttyclock->date.datestr);
wrefresh(ttyclock->datewin);
/* Draw second if the option is enable */
if(ttyclock->option.second)
{
/* Again 2 dot for number separation */
wbkgdset(ttyclock->framewin, COLOR_PAIR(1));
mvwaddstr(ttyclock->framewin, 2, NORMFRAMEW, " ");
mvwaddstr(ttyclock->framewin, 4, NORMFRAMEW, " ");
/* Draw second numbers */
draw_number(ttyclock->date.second[0], 1, 39);
draw_number(ttyclock->date.second[1], 1, 46);
}
return;
}
void
clock_move(int x, int y, int w, int h)
{
/* Erase border for a clean move */
wbkgdset(ttyclock->framewin, COLOR_PAIR(0));
wborder(ttyclock->framewin, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ');
wbkgdset(ttyclock->datewin, COLOR_PAIR(0));
wborder(ttyclock->datewin, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ');
/* Clean windows */
werase(ttyclock->framewin);
werase(ttyclock->datewin);
wrefresh(ttyclock->framewin);
wrefresh(ttyclock->datewin);
/* Make new property */
ttyclock->framewin = newwin((ttyclock->geo.h = h),
(ttyclock->geo.w = w),
(ttyclock->geo.x = x),
(ttyclock->geo.y = y));
ttyclock->datewin = newwin(DATEWINH,
strlen(ttyclock->date.datestr) + 2,
ttyclock->geo.x + ttyclock->geo.h - 1,
ttyclock->geo.y + (ttyclock->geo.w / 2) - (strlen(ttyclock->date.datestr) / 2) - 1);
box(ttyclock->framewin, 0, 0);
box(ttyclock->datewin, 0, 0);
wrefresh(ttyclock->datewin);
wrefresh(ttyclock->framewin);
return;
}
void
set_second(void)
{
/* Reverse option value */
if((ttyclock->option.second = !ttyclock->option.second))
clock_move(ttyclock->geo.x, ttyclock->geo.y, (ttyclock->geo.w = SECFRAMEW), ttyclock->geo.h);
else
clock_move(ttyclock->geo.x, ttyclock->geo.y, (ttyclock->geo.w = NORMFRAMEW), ttyclock->geo.h);
set_center(ttyclock->option.center);
return;
}
void
set_center(Bool b)
{
if((ttyclock->option.center = b))
clock_move((ttyclock->geo.x = (LINES / 2 - (ttyclock->geo.h / 2))),
(ttyclock->geo.y = (COLS / 2 - (ttyclock->geo.w / 2))),
ttyclock->geo.w,
ttyclock->geo.h);
return;
}
void
key_event(void)
{
if(ttyclock->option.keylock)
return;
halfdelay(1);
switch(getch())
{
case KEY_UP:
case 'k':
case 'K':
if(ttyclock->geo.x >= 1
&& !ttyclock->option.center)
clock_move(ttyclock->geo.x - 1, ttyclock->geo.y, ttyclock->geo.w, ttyclock->geo.h);
break;
case KEY_DOWN:
case 'j':
case 'J':
if(ttyclock->geo.x <= (LINES - ttyclock->geo.h - DATEWINH)
&& !ttyclock->option.center)
clock_move(ttyclock->geo.x + 1, ttyclock->geo.y, ttyclock->geo.w, ttyclock->geo.h);
break;
case KEY_LEFT:
case 'h':
case 'H':
if(ttyclock->geo.y >= 1
&& !ttyclock->option.center)
clock_move(ttyclock->geo.x, ttyclock->geo.y - 1, ttyclock->geo.w, ttyclock->geo.h);
break;
case KEY_RIGHT:
case 'l':
case 'L':
if(ttyclock->geo.y <= (COLS - ttyclock->geo.w - 1)
&& !ttyclock->option.center)
clock_move(ttyclock->geo.x, ttyclock->geo.y + 1, ttyclock->geo.w, ttyclock->geo.h);
break;
case 'q':
case 'Q':
ttyclock->running = False;
break;
case 's':
case 'S':
set_second();
break;
case 't':
case 'T':
ttyclock->option.twelve = !ttyclock->option.twelve;
/* Set the new ttyclock->date.datestr for resize date window */
update_hour();
clock_move(ttyclock->geo.x, ttyclock->geo.y, ttyclock->geo.w, ttyclock->geo.h);
break;
case 'c':
case 'C':
set_center(!ttyclock->option.center);
break;
}
return;
}
int
main(int argc, char **argv)
{
int c;
struct option long_options[] =
{
{"help", 0, NULL, 'h'},
{"version", 0, NULL, 'v'},
{"info", 0, NULL, 'i'},
{"second", 0, NULL, 's'},
{"twelve", 0, NULL, 't'},
{"lock", 0, NULL, 'l'},
{"center", 0, NULL, 'c'},
{NULL, 0, NULL, 0}
};
/* Alloc ttyclock */
ttyclock = malloc(sizeof(ttyclock_t));
while ((c = getopt_long(argc,argv,"tvslcih",
long_options, NULL)) != -1)
{
switch(c)
{
case 'h':
default:
puts(HELPSTR);
free(ttyclock);
exit(EXIT_SUCCESS);
break;
case 'i':
puts("TTY-Clock 2 © by Martin Duquesnoy (xorg62@gmail.com)");
free(ttyclock);
exit(EXIT_SUCCESS);
break;
case 'v':
puts("TTY-Clock 2 © devel version");
free(ttyclock);
exit(EXIT_SUCCESS);
break;
case 's':
ttyclock->option.second = True;
break;
case 'c':
ttyclock->option.center = True;
break;
case 't':
ttyclock->option.twelve = True;
break;
case 'l':
ttyclock->option.keylock = True;
break;
}
}
init();
while(ttyclock->running)
{
update_hour();
draw_clock();
key_event();
usleep(UPDATETIME);
}
free(ttyclock);
endwin();
return 0;
}