/* This is free software. See LICENSE for terms.
* Copyright 2004 - 2015, Patricia Kirk.
*/
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#if defined (__linux__)
#define __USE_XOPEN
#include <time.h>
#undef __USE_XOPEN
#endif
#include "proto.h"
extern struct global g;
extern struct data fresh;
extern struct lineopts *linelist;
extern Display *maindisplay;
extern Atom wmdeletewindow, wmprotocols;
char smalbuf[SMALBUF];
struct keyval {
int key;
int value;
};
int keyCheck(int key) {
struct keyval keys[] = {
/* Esc */
{9, 99},
/* Top row */
{10, 1}, {11, 2}, {12, 3},
{13, 4}, {14, 5}, {15, 6},
{16, 7}, {17, 8}, {18, 9},
{19, 0},
/* Back space, Enter, Space */
{22, 22}, {36, 36}, {65, 65},
/* Key pad */
{79, 7}, {80, 8}, {81, 9},
{83, 4}, {84, 5}, {85, 6},
{87, 1}, {88, 2}, {89, 3},
{90, 0},
/* Up, Left, Right */
{98, 98}, {100, 100}, {102, 102},
/* Return */
{108, 36},
{0, -1}
};
int i=0;
for (;; i++) {
if (!keys[i].key || (keys[i].key == key))
break;
}
return keys[i].value;
}
void runLines(int key, int button, int x, int y) {
struct lineopts *line;
for (line = linelist; line; line = line->next) {
if (line->left <= x && line->right >= x &&
line->upper <= y && line->lower >= y) {
#if WITH_DETACH
if (disMount(line)) {
break;
} else
#endif /* WITH_DETACH */
if (itsaTalker(line)) {
break;
} else if (itsCalendar(line)) {
break;
} else if (itsaTimer(line, key, button, x)) {
break;
} else if (itsElapsed(line, key, button, x)) {
break;
} else if (itsVolume(line, key, button, x, y)) {
break;
}
#if WITH_COMMANDS || WITH_STEPEXEC
else if (line->command) { /* Any key or button */
execComm(line->command);
break;
}
#endif /* WITH_COMMANDS || WITH_STEPEXEC */
break; /* from linelist */
}
}
}
void reFresh(int function) {
int refresh;
refresh = g.refresh;
g.refresh = 0;
if (function) {
checkLines();
g.updaterequest = 1;
} else {
getVolume();
}
g.refresh = refresh;
}
XEvent event;
void checkEvents() {
int key;
#if WITH_SUID
static int shutdown=0;
#endif /* WITH_SUID */
while (XPending(maindisplay)) {
XNextEvent(maindisplay, &event);
switch (event.type) {
case KeyPress:
key = event.xkey.keycode;
if ((key == 31 || key == 53 || key == 59) &&
(event.xkey.state & ControlMask)) {
/* ^q(uit) || ^w(indow) */
gdayMate(NULL, NULL);
} else if (event.xkey.state & ShiftMask) {
smalbuf[0] = '\0';
if (key == 10 || key == 87) { /* 1 */
key = (g.powerlog = !g.powerlog);
snprintf(smalbuf, sizeof(smalbuf), "power state");
} else if (key == 11 || key == 88) { /* 2 */
key = (g.timelog = !g.timelog);
snprintf(smalbuf, sizeof(smalbuf), "time sync");
} else if (key == 12 || key == 89) { /* 3 */
key = (g.thermlog = !g.thermlog);
snprintf(smalbuf, sizeof(smalbuf), "thermal zone");
} else if (key == 13 || key == 83) { /* 4 */
key = (g.execlog = !g.execlog);
snprintf(smalbuf, sizeof(smalbuf), "remote execute");
}
if (key == 1)
stringcat(smalbuf, " logging is on", sizeof(smalbuf));
else if (!key)
stringcat(smalbuf, " logging is off", sizeof(smalbuf));
if (strlen(smalbuf))
logMessage(smalbuf);
#if WITH_SUID
} else if (g.clickoff) {
/* Don`t respond to other keys. */
break;
#endif /* WITH_SUID */
} else if (key == 65 && g.refresh > 1) {
/* Space in top. */
reFresh(1);
break;
} else if ((key = keyCheck(key)) >= 0) {
/* Key entry for line manipulation. */
if (!calcPhase(key, -1, event.xkey.x, event.xkey.y))
runLines(key, -1, event.xkey.x, event.xkey.y);
}
break; /* from key press */
case ButtonPress:
#if WITH_SUID
if (g.clickoff) {
/* Click anywhere for shutdown.
* Click again to kill shutdown.
*/
if (!shutdown) {
shutdown = execShutdown(g.clicktime);
makeNoise(g.clicksound);
} else {
shutdown = execShutdown(-1);
}
break;
}
#endif /* WITH_SUID */
if (!calcPhase(-1, event.xbutton.button, event.xbutton.x, event.xbutton.y))
runLines(-1, event.xbutton.button, event.xbutton.x, event.xbutton.y);
break; /* from button press */
case Expose:
if (event.xexpose.count == 0)
g.updaterequest = 1;
break;
case ClientMessage:
/* Respond to click on close window button. */
if ((event.xclient.message_type == wmprotocols) &&
(event.xclient.data.l[0] == wmdeletewindow))
gdayMate(NULL, NULL);
break;
}
}
}
#if WITH_DETACH
int disMount(struct lineopts *line) {
char *buffer, *ptr;
FILE *fd;
int yes=0;
if (line->command && !strcmp(line->command, "detach")) {
yes = 1;
if (!g.localhost || !(buffer = calloc(BUFSIZE, sizeof(char))))
return yes;
buffer[0] = '\0';
if (g.effectiveuid) {
snprintf(buffer, BUFSIZE,
"echo Salmon must be run SUID to implement the detach function");
} else if (!strcmp(line->type, "mount")) {
/* This is an absolute address to an alleged file system. */
if (!strcmp(line->argument, "/")) {
snprintf(buffer, BUFSIZE,
"echo Salmon will not un/mount root");
} else if (!strcmp(line->status, "0")) {
snprintf(buffer, BUFSIZE,
"echo File system %s is not in /etc/fstab",
line->argument);
} else if (!strcmp(line->status, "1")) {
/* The file system is found but not mounted.
* line->value has been set with fs_mntops etc.
* by mntPoint() in refresh.c
*/
snprintf(buffer, BUFSIZE, "/sbin/mount %s",
line->value);
} else if (!strcmp(line->status, "2")) {
snprintf(buffer, BUFSIZE, "/sbin/umount -f %s",
line->argument);
}
} else if (!strcmp(line->type, "interface")) {
/* This is a network interface. */
if (!strncmp(line->argument, "wlan", 4)) {
snprintf(buffer, BUFSIZE,
"echo Salmon does not support detaching %s",
line->argument);
} else if (!strcmp(line->status, "0")) {
snprintf(buffer, BUFSIZE, "/sbin/ifconfig %s up",
line->argument);
} else {
snprintf(buffer, BUFSIZE, "/sbin/ifconfig %s down",
line->argument);
}
}
if (strlen(buffer)) {
if (line->value && strstr(line->value, "nfs")) {
/* line->next was spliced into the linelist at the
* first pass through mntPoint() and set to type
* remoteHost. The status of the host is kept
* updated by checkLines() and the icmp echo
* reply code. Don`t attempt to toggle the
* state if the host is not responding.
*/
if (parseStrtol(line->next->value, TRUE, "disMount") >= 5)
snprintf(buffer, BUFSIZE,
"echo Host %s for file system %s is not responding",
line->next->argument, line->argument);
}
seteuid(g.effectiveuid);
if ((fd = popen(buffer, "r"))) {
if (!strncmp(buffer, "echo ", 5)) {
buffer[fread(buffer, sizeof(char), BUFSIZE, fd)] = '\0';
if ((ptr = strchr(buffer, '\n')))
*ptr = '\0';
logMessage(buffer);
}
pclose(fd);
}
seteuid(g.realuid);
}
FREE(buffer);
}
return yes;
}
#endif /* WITH_DETACH */
#if defined(__NetBSD__) || defined(__OpenBSD__)
int pointless[]={0, 0, 7, 7, 7,
15, 15, 15, 23, 23, 23, 31, 31, 31,
39, 39, 39, 47, 47, 47, 55, 55, 55,
63, 63, 63, 71, 71, 71, 79, 79, 79,
87, 87, 87, 95, 95, 95, 103, 103, 103,
111, 111, 111, 119, 119, 119, 127, 127, 127,
135, 135, 135, 143, 143, 143, 151, 151, 151,
159, 159, 159, 167, 167, 167, 175, 175, 175,
183, 183, 183, 191, 191, 191, 199, 199, 199,
207, 207, 207, 215, 215, 215, 223, 223, 223,
231, 231, 231, 239, 239, 239, 247, 247, 247,
247, 255, 255, 255, 255, 255
};
#endif
int itsVolume(struct lineopts *line, int key, int button, int x, int y) {
static time_t lasttime=0;
time_t timenow=time(NULL);
static int step=0, sleep=0;
int yes=0, channel, volume[2];
FILE *fd;
if ((yes = (line->index == getIndex("volume")))) {
if (!step) {
#if defined(__NetBSD__) || defined(__OpenBSD__)
step = 3;
#else
step = 1;
#endif
}
if (!strcmp(line->status, "connect")) {
#if !defined(__linux__)
g.volconn = !g.volconn;
#endif
return yes;
}
if (timenow >= (lasttime + 1))
sleep = 0;
if (sleep)
/* Update the current values.
* This is necessary for the
* left & right press & hold
* action to work.
*/
reFresh(0);
volume[0] = fresh.volume[0];
volume[1] = fresh.volume[1];
channel = parseStrtol(line->value, TRUE, "itsVolume");
if (x <= line->left + (6 * g.xmag)) {
#if defined(__NetBSD__) || defined(__OpenBSD__)
if (volume[channel] > 95)
volume[channel] = 95;
#endif
volume[channel] -= step;
goto sleep;
} else if (x >= line->left + (58 * g.xmag)) {
#if defined(__NetBSD__) || defined(__OpenBSD__)
if (volume[channel] < 3)
volume[channel] = 3;
#endif
volume[channel] += step;
#if defined(__NetBSD__) || defined(__OpenBSD__)
if (volume[channel] > 95)
volume[channel] = 100;
#endif
sleep:
if (!sleep)
sleep = 100000;
else
sleep = 20000;
} else {
volume[channel] = (((x - line->left) / g.xmag) - 6) * 2;
sleep = 0;
}
if (volume[channel] < 0)
volume[channel] = 0;
else if (volume[channel] > 100)
volume[channel] = 100;
#if defined(__NetBSD__) || defined(__OpenBSD__)
volume[channel] = pointless[volume[channel] +
((sleep != 0) && (volume[channel] != 100))];
#endif
if (g.volconn) {
if (channel)
volume[0] = volume[1];
else
volume[1] = volume[0];
}
#if defined(__FreeBSD__)
snprintf(smalbuf, SMALBUF, "%s vol %d:%d",
g.mixer, volume[0], volume[1]);
#elif defined(__linux__)
snprintf(smalbuf, SMALBUF, "%s -v %d",
g.mixer, volume[0]);
#else
snprintf(smalbuf, SMALBUF, "%s -w outputs.master=%d,%d",
g.mixer, volume[0], volume[1]);
#endif
if (strlen(smalbuf) && (fd = popen(smalbuf, "r")))
/* execComm() prints scruff to stdout. */
pclose(fd);
if (XPending(maindisplay)) {
sleep = 0;
} else if (sleep) {
usleep(sleep);
if (!XPending(maindisplay))
XPutBackEvent(maindisplay, &event);
}
}
lasttime = timenow;
return yes;
}
/* Toggle talking clock on and off.
* Don`t set yes unless line->setting
* is defined.
*/
int itsaTalker(struct lineopts *line) {
int yes=0;
if (!strcmp(line->type, "format")) {
if (line->setting) {
STRDUP(line->buffer, line->setting);
FREE(line->setting);
yes = 1;
} else if (line->buffer) {
STRDUP(line->setting, line->buffer);
FREE(line->buffer);
yes = 1;
}
}
return yes;
}
/* Move current date to line
* on key/pointer event.
*/
int itsCalendar(struct lineopts *line) {
int yes=0, color=0, setting=1, dir=-1;
struct lineopts *l1, *ln;
if ((yes = (line->index == getIndex("calendar")))) {
for (l1 = linelist; l1; l1 = l1->next) {
if (l1->index == getIndex("calendar"))
break;
}
for (ln = l1; ln; ln = ln->next) {
if (ln->index != getIndex("calendar"))
break;
setting += dir;
if (ln->color)
color = ln->color;
if (ln == line)
dir = 0;
}
while (l1 && l1->index == getIndex("calendar")) {
snprintf(smalbuf, SMALBUF, "%d", setting);
STRDUP(l1->setting, smalbuf);
if (setting && l1->color)
l1->color = 0;
else if (!setting)
l1->color = color;
l1 = l1->next;
setting++;
}
reFresh(1);
}
return yes;
}
int itsaTimer(struct lineopts *line, int key, int button, int x) {
char showbuf[SHOWBUF];
int yes=0;
if ((yes = (line->index >= getIndex("timer") && line->index <= getIndex("reset")))) {
if (!line->status) {
if (key == 102 || button == 3) { /* Right arrow or right click, start count */
if (line->value) { /* argument value */
STRDUP(line->buffer, line->value);
} else if (line->setting) { /* setting value */
STRDUP(line->buffer, line->setting);
} else {
return yes;
}
if (!strcmp(line->type, "timer")) {
snprintf(showbuf, sizeof(showbuf), "%d",
(int)(parseStrtol(line->buffer, TRUE, "itsaTimer") + time(NULL)));
STRDUP(line->buffer, showbuf);
}
STRDUP(line->status, "running");
} else if (key == 99 || key == 98 || button == 2) { /* ESC, up arrow, middle click, edit setting */
if (!line->setting) {
STRDUP(line->setting, "0");
}
STRDUP(line->buffer, line->setting);
STRDUP(line->status, "setting");
if (!strcmp(line->type, "timer"))
adjTimer(line, -1, 0, x);
else
adjAlarm(line, -1, 0, x);
} else if (key == 22 || key == 100 || button == 1) { /* Backspace, left arrow, left click, edit value */
if (!line->value) {
STRDUP(line->value, "0");
}
STRDUP(line->buffer, line->value);
STRDUP(line->status, "value");
if (!strcmp(line->type, "timer"))
adjTimer(line, -1, 0, x);
else
adjAlarm(line, -1, 0, x);
}
} else if (!strcmp(line->status, "value") ||
!strcmp(line->status, "setting")) { /* In edit mode. */
if (key == 98 || button == 2) { /* Up arrow, start count. */
if (!strcmp(line->type, "timer")) {
snprintf(showbuf, sizeof(showbuf), "%d",
(int)(parseStrtol(line->buffer, TRUE, "itsaTimer") + time(NULL)));
STRDUP(line->buffer, showbuf);
}
if (!strcmp(line->type, "reset") &&
!strcmp(line->status, "setting")) {
FREE(line->status);
} else {
STRDUP(line->status, "running");
}
} else {
if (!strcmp(line->type, "timer"))
adjTimer(line, key, button, x);
else
adjAlarm(line, key, button, x);
}
} else if (!strcmp(line->status, "running") &&
(key == 100 || button == 1)) { /* Left arrow or left click, stop count. */
FREE(line->status);
}
}
return yes;
}
int itsElapsed(struct lineopts *line, int key, int button, int x) {
time_t timeval=0, timenow=time(NULL);
char showbuf[SHOWBUF];
int yes=0;
if ((yes = (!strcmp(line->type, "elapsed")))) {
if (!line->status) { /* Any key or button starts. */
snprintf(showbuf, sizeof(showbuf), "%d", (int)timenow);
STRDUP(line->value, showbuf);
STRDUP(line->status, "running");
} else if (!strcmp(line->status, "running")) {
if (key == 98 || button == 2) { /* Up */
STRDUP(line->status, "stopped");
snprintf(showbuf, sizeof(showbuf), "%d", (int)timenow);
STRDUP(line->buffer, showbuf);
}
} else if (!strcmp(line->status, "stopped") || !strcmp(line->status, "clear")) {
if (key == 100 || button == 1) { /* Left */
/* Run time. */
timeval = timenow - parseStrtol(line->buffer, TRUE, "itsElapsed");
snprintf(showbuf, sizeof(showbuf), "%d",
parseStrtol(line->value, TRUE, "itsElapsed") + (int)timeval);
STRDUP(line->value, showbuf);
STRDUP(line->status, "running");
} else if (key == 102 || button == 3) { /* Right */
/* Lap time. */
STRDUP(line->status, "running");
FREE(line->buffer);
} else if (key == 98 || button == 2) { /* Up */
if (!strcmp(line->status, "stopped")) {
STRDUP(line->status, "clear");
} else if (!strcmp(line->status, "clear")) {
FREE(line->status);
}
}
}
}
return yes;
}
/* This only responds to up, left or right arrow
* keys or button clicks. Click on any part of
* the window or panel for function.
*/
int calcPhase(int key, int button, int x, int y) {
time_t timenow=time(NULL);
struct lineopts *line;
int yes=0;
if (g.phasecalc) {
for (line = linelist; line; line = line->next) {
if (line->status && !strcmp(line->type, "display") &&
x >= line->left && x <= line->right &&
y >= ((line->panel > 2) * g.psize) &&
y <= ((line->panel > 2) * g.psize) + g.psize &&
(key >= 98 || button > 0)) {
yes = 1;
if (!g.phasetime)
g.phasetime = timenow;
if (key == 100 || button == 1)
/* Previous quarter, static display. */
getNext(g.phasetime, -1);
else if (key == 102 || button == 3)
/* Next quarter, static display. */
getNext(g.phasetime, 1);
else if (key == 98 || button == 2)
/* Current status, running display. */
g.phasetime = 0;
checkLines(); /* Update the data. */
g.updaterequest = 1; /* Update the display. */
}
}
}
return yes;
}
/* Convert user date and time into seconds for alarms.
* Enter with line->buffer as HH:MM [yy/mm/dd].
* Returns expiration time in seconds.
*/
time_t getExpiration(struct lineopts *line) {
struct tm *timeptr;
time_t timenow=time(NULL);
int hour=0, minute=0, year=0, month=0, day=0, count;
timeptr = localtime(&timenow);
timeptr->tm_sec = 0;
count = sscanf(line->buffer, "%d:%d %d/%d/%d", &hour, &minute, &year, &month, &day);
if (count == 5) {
timeptr->tm_hour = hour;
timeptr->tm_min = minute;
timeptr->tm_year = year + 100;
timeptr->tm_mon = month - 1;
timeptr->tm_mday = day;
} else if (count == 2) {
timeptr->tm_hour = hour;
timeptr->tm_min = minute;
} else {
gdayMate("getExpiration() alarm/reset setting", strerror(EINVAL));
}
return mktime(timeptr);
}
/* Convert user time into seconds for timers.
* Enter with line->buffer as ddd HH:MM:SS.
* Returns duration in seconds.
*/
time_t getDuration(struct lineopts *line) {
int days=0, hours, minutes, seconds;
if ((sscanf(line->buffer, "%d:%d:%d",
&hours, &minutes, &seconds) == 3) ||
(sscanf(line->buffer, "%d %d:%d:%d",
&days, &hours, &minutes, &seconds) == 4) ||
(sscanf(line->buffer, "T||%d||%d:%d:%d",
&days, &hours, &minutes, &seconds) == 4)) {
if (days > 999)
days = 999;
if (hours > 23)
hours = 23;
if (minutes > 59)
minutes = 59;
if (seconds > 59)
seconds = 59;
} else {
gdayMate("getDuration() timer preset", strerror(EINVAL));
}
return ((days * 86400) + (hours * 3600) + (minutes * 60) + seconds);
}
/* Translate key and button events
* for adjTimer() and adjAlarm().
*/
int transKey(int *key, int *button, int *iskey) {
int yes=0;
/* Use left and right arrow keys as button events. */
if (*key == 100) {
*key = -1;
*button = 1;
} else if (*key == 102) {
*key = -1;
*button = 3;
}
if (*key >= 0 && *key <= 9) {
*key += AZERO;
*iskey = 1;
yes = 1;
} else if (*button > 0) {
if (*button == 1)
*button = -1;
else if (*button == 3)
*button = 1;
yes = 1;
} else if (*key == 99) {
yes = 1;
}
return yes;
}
/* Used for key or button setting timers.
*/
void adjTimer(struct lineopts *line, int key, int button, int x) {
int days, hours, minutes, seconds, mx, space=0, iskey=0;
char showbuf[SHOWBUF];
mx = (x - line->left) / g.xmag;
splitSeconds(&days, &hours, &minutes, &seconds, parseStrtol(line->buffer, TRUE, "edjTimer"));
snprintf(showbuf, sizeof(showbuf), "T||%03d||%02d:%02d:%02d",
days, hours, minutes, seconds);
if (transKey(&key, &button, &iskey)) {
if (mx >= 55) {
/* Seconds. */
space = 15;
} else if (mx >= 50 && mx < 55) {
/* Ten seconds. */
space = 14;
} else if (mx >= 43 && mx < 48) {
/* Minutes. */
space = 12;
} else if (mx >= 38 && mx < 43) {
/* Ten minutes. */
space = 11;
} else if (mx >= 32 && mx < 37) {
/* Hours. */
space = 9;
} else if (mx >= 26 && mx < 31) {
/* Ten hours. */
space = 8;
} else if (mx >= 19 && mx < 24) {
/* Days. */
space = 5;
} else if (mx >= 14 && mx < 19) {
/* Ten days. */
space = 4;
} else if (mx >= 9 && mx < 14) {
/* One hundred days. */
space = 3;
} else if (mx < 8 && button == -1) {
FREE(line->status);
}
if (space) {
if (iskey) {
showbuf[space] = key;
} else {
showbuf[space] += button;
if (showbuf[space] > ANINE)
showbuf[space] = ANINE;
else if (showbuf[space] < AZERO)
showbuf[space] = AZERO;
}
}
}
STRDUP(line->buffer, showbuf);
snprintf(showbuf, sizeof(showbuf), "%d", (int)getDuration(line));
STRDUP(line->buffer, showbuf);
if (key == 36 && mx < 8) {
if (!strcmp(line->status, "setting")) {
STRDUP(line->setting, showbuf);
} else {
STRDUP(line->value, showbuf);
}
snprintf(showbuf, sizeof(showbuf), "%d",
(int)(parseStrtol(line->buffer, TRUE, "adjTimer") + time(NULL)));
STRDUP(line->buffer, showbuf);
STRDUP(line->status, "running");
}
}
/* Change the reset interval from the default 24
* hours or user preset on line->type "reset".
*/
void adjInterval(struct lineopts *line, int key, int button, int x) {
char showbuf[SHOWBUF];
time_t timeval=0;
int mx, space=0, top=ANINE, iskey=0;
int days, hours, minutes;
mx = (x - line->left) / g.xmag;
timeval = parseStrtol(line->buffer, TRUE, "adjInterval");
splitSeconds(&days, &hours, &minutes, NULL, timeval);
snprintf(showbuf, sizeof(showbuf), "Interval|%02d:%02d",
hours + (days * 24), minutes);
if (transKey(&key, &button, &iskey)) {
if (mx >= 58) {
/* Minutes */
space = 13;
} else if (mx >= 53 && mx < 58) {
/* Ten minutes */
space = 12;
top = 53; /* 5 */
} else if (mx >= 46 && mx < 51) {
/* Hours */
space = 10;
} else if (mx >= 41 && mx < 46) {
/* Ten hours */
space = 9;
} else if (mx < 8) {
if (button == -1) {
FREE(line->status);
}
}
if (space) {
if (iskey)
showbuf[space] = key;
else
showbuf[space] += button;
if (showbuf[space] > top)
showbuf[space] = top;
else if (showbuf[space] < AZERO)
showbuf[space] = AZERO;
}
}
sscanf(showbuf, "Interval|%d:%d", &hours, &minutes);
timeval = (hours * 3600) + (minutes * 60);
snprintf(showbuf, sizeof(showbuf), "%d", (int)timeval);
STRDUP(line->buffer, showbuf);
if (key == 36 && mx < 8) { /* Enter, set new interval */
if (!timeval) {
FREE(line->setting); /* Restore default 24 hours */
} else {
STRDUP(line->setting, showbuf);
}
FREE(line->status);
}
}
void adjAlarm(struct lineopts *line, int key, int button, int x) {
struct tm *timeptr=NULL;
time_t timeval=0, timenow=time(NULL);
char showbuf[SHOWBUF], *ptr;
int mx, space=0, top=ANINE, iskey=0;
if (!strcmp(line->type, "reset") && !strcmp(line->status, "setting")) {
adjInterval(line, key, button, x);
return;
}
mx = (x - line->left) / g.xmag;
timeval = parseStrtol(line->buffer, TRUE, "adjAlarm");
if (!timeval)
timeval = timenow;
timeptr = localtime(&timeval);
timeptr->tm_sec = 0;
strftime(showbuf, sizeof(showbuf), "A||%m/%d||%H:%M", timeptr);
if (!strcmp(line->type, "reset"))
showbuf[0] = 'R';
if (key == 99) /* ESC, set to now plus one hour. */
button = 0; /* So it won`t change values. */
if (transKey(&key, &button, &iskey)) {
if (mx >= 55) {
/* Minutes */
space = 14;
} else if (mx >= 50 && mx < 55) {
/* Ten minutes */
space = 13;
top = 53; /* 5 */
} else if (mx >= 43 && mx < 48) {
/* Hours */
space = 11;
} else if (mx >= 38 && mx < 43) {
/* Ten hours */
space = 10;
top = 50; /* 2 */
} else if (mx >= 31 && mx < 36) {
/* Days */
space = 7;
} else if (mx >= 26 && mx < 31) {
/* Ten days */
space = 6;
top = 51; /* 3 */
} else if (mx >= 15 && mx < 20) {
/* Months */
space = 4;
} else if (mx >= 10 && mx < 15) {
/* Ten months */
space = 3;
top = 49; /* 1 */
} else if (mx < 8) {
if (key == 99) { /* ESC */
timeval = timenow + 3600;
timeptr = localtime(&timeval);
strftime(showbuf, sizeof(showbuf), " ||%m/%d||%H:%M", timeptr);
} else if (button == -1) {
FREE(line->status);
}
}
if (space) {
if (iskey)
showbuf[space] = key;
else
showbuf[space] += button;
if (showbuf[space] > top)
showbuf[space] = top;
else if (showbuf[space] < AZERO)
showbuf[space] = AZERO;
}
}
timeptr = localtime(&timenow);
timeptr->tm_sec = 0;
ptr = showbuf;
ptr++; /* Past the A or D */
strptime(ptr, "||%m/%d||%H:%M", timeptr);
timeval = mktime(timeptr);
snprintf(showbuf, sizeof(showbuf), "%d", (int)timeval);
STRDUP(line->buffer, showbuf);
if (key == 36 && mx < 8) {
if (!strcmp(line->status, "setting")) {
STRDUP(line->setting, showbuf);
} else {
STRDUP(line->value, showbuf);
}
STRDUP(line->status, "running");
}
}