486 lines
13 KiB
C
486 lines
13 KiB
C
|
/*------------------------------------------------------
|
||
|
*
|
||
|
* wmCalendar (c)2003 Matthias Laabs
|
||
|
*
|
||
|
* mattlaabs@users.sourceforge.net
|
||
|
*
|
||
|
* a calendar dockapp
|
||
|
-----------------------------------------------------*/
|
||
|
|
||
|
#include "wmCalendar.h"
|
||
|
|
||
|
/*------------------------------------------------------
|
||
|
* main
|
||
|
-----------------------------------------------------*/
|
||
|
int main(int argc, char *argv[])
|
||
|
{
|
||
|
int n = 0;
|
||
|
getSettings();
|
||
|
ParseCMDLine(argc, argv);
|
||
|
if(get_debug())printf("debugging mode:\nstarting wmCalendar version %s\n", getVersion());
|
||
|
if(get_debug())printf("using libical version %s\n", ICAL_VERSION);
|
||
|
dockapp_open_window("", "wmCalendar", 64, 64, argc, argv);
|
||
|
initValues();
|
||
|
gtk_init(&argc, &argv);
|
||
|
checkicalversion();
|
||
|
|
||
|
/* Loop until we die */
|
||
|
while(1) {
|
||
|
if(n == 0){ /* do updates only every COUNTERth time */
|
||
|
getTime();
|
||
|
calendar();
|
||
|
draw();
|
||
|
|
||
|
n = COUNTER;
|
||
|
}
|
||
|
/* check for events every time */
|
||
|
n--;
|
||
|
if(processXEvents())
|
||
|
n = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*------------------------------------------------------
|
||
|
* draw
|
||
|
-----------------------------------------------------*/
|
||
|
void draw()
|
||
|
{
|
||
|
|
||
|
blankScreen();
|
||
|
drawButtons();
|
||
|
drawDays();
|
||
|
drawMonthYear();
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*------------------------------------------------------
|
||
|
* initValues
|
||
|
-----------------------------------------------------*/
|
||
|
void initValues(){
|
||
|
XClassHint class_hints;
|
||
|
XpmColorSymbol colors[2];
|
||
|
int i, j;
|
||
|
monthOffset = 0;
|
||
|
class_hints.res_name="wmCalendar";
|
||
|
class_hints.res_class="wmCalendar";
|
||
|
/* Compute widths of months and digits */
|
||
|
for(i = 0; i < 12; ++i)
|
||
|
for( j = 0; j < 6; ++j)
|
||
|
xdMonth[j][i] = xeMonth[j][i] - xsMonth[j][i] + 1;
|
||
|
for(i = 0; i < 12; ++i)
|
||
|
for( j = 0; j < 2; ++j)
|
||
|
xdYear[j][i] = xeYear[j][i] - xsYear[j][i] + 1;
|
||
|
for(i = 0; i < MAXBUTTON; ++i)
|
||
|
xdButton[i] = xeButton[i] - xsButton[i] + 1;
|
||
|
|
||
|
dockapp_set_eventmask();
|
||
|
dockapp_xpm2pixmap( wmCalendar_master2_xpm, &bg[1], &mask, colors, 0);
|
||
|
dockapp_xpm2pixmap( wmCalendar_master_xpm, &bg[0], &mask, colors, 0);
|
||
|
pixmap = dockapp_XCreatePixmap(64, 64);
|
||
|
dockapp_setshape(mask, 0, 0);
|
||
|
if(mask)
|
||
|
XFreePixmap(display, mask);
|
||
|
dockapp_set_background(pixmap);
|
||
|
dockapp_show();
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*------------------------------------------------------
|
||
|
* read_stream
|
||
|
-----------------------------------------------------*/
|
||
|
char* read_stream(char *s, size_t size, void *d){
|
||
|
char *c = fgets(s, size, (FILE*)d);
|
||
|
return c;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*------------------------------------------------------
|
||
|
* getClickedDay
|
||
|
-----------------------------------------------------*/
|
||
|
int getClickedDay(int bx, int by)
|
||
|
{
|
||
|
int dayofweek, week, day;
|
||
|
dayofweek = bx / 9 + 1;
|
||
|
week = (by - 20) / 7;
|
||
|
tgr = get_civil(t, calendartype);
|
||
|
day = dayofweek + 7 * week - ((day_of_week(tgr) - t.day + 37 + get_start_of_week()) % 7);
|
||
|
if(day <= days_in_month(t.month, t.year, calendartype) && day > 0){
|
||
|
tgr.day = day;
|
||
|
tgr.month = t.month;
|
||
|
tgr.year = t.year;
|
||
|
tgr = get_civil(tgr, calendartype);
|
||
|
return 1;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*------------------------------------------------------
|
||
|
* getClickedButton
|
||
|
-----------------------------------------------------*/
|
||
|
int getClickedButton(int bx, int by)
|
||
|
{
|
||
|
if(bx < 12 && by < 12) /* arrow left : month back*/
|
||
|
return BT_BACK;
|
||
|
else if(bx > 50 && by < 12) /* arrow right : month forward*/
|
||
|
return BT_FORWARD;
|
||
|
else if(bx > 52 && by > 56) /* show/hide buttons */
|
||
|
return BT_OPENCLOSE;
|
||
|
else if(showbuttons){
|
||
|
if(bx < 46 && bx > 37 && by > 55) /* toggle gregorian/persian/... */
|
||
|
return BT_MOON ;
|
||
|
else if(bx < 52 && bx > 46 && by > 55) /* open settings dialog */
|
||
|
return BT_SETTINGS;
|
||
|
else if(bx < 37 && bx > 28 && by > 55) /* toggle moonphase on/off */
|
||
|
return BT_CALTYPE;
|
||
|
else if(bx < 28 && bx > 19 && by > 55) /* start calendar application */
|
||
|
return BT_APP;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*------------------------------------------------------
|
||
|
* ButtonPressEvent
|
||
|
-----------------------------------------------------*/
|
||
|
void buttonPress(int btype, int bx, int by, long etime){
|
||
|
char* applaunch;
|
||
|
if(get_debug() > 1) printf("push button %d\n", btype);
|
||
|
|
||
|
switch(btype){
|
||
|
case 1: /* leftmouse - button or mark */
|
||
|
switch ( getClickedButton(bx, by)){
|
||
|
case BT_BACK: /* arrow left : month back*/
|
||
|
monthOffset--;
|
||
|
break;
|
||
|
|
||
|
case BT_FORWARD: /* arrow right : month forward*/
|
||
|
monthOffset++;
|
||
|
break;
|
||
|
|
||
|
case BT_OPENCLOSE: /* show/hide buttons */
|
||
|
showbuttons = 1 - showbuttons;
|
||
|
break;
|
||
|
|
||
|
case BT_CALTYPE: /* toggle gregorian/persian/... */
|
||
|
calendartype = (calendartype + 1) % CALTYPES;
|
||
|
break;
|
||
|
|
||
|
case BT_MOON:/* toggle moonphase on/off */
|
||
|
showmoon = 1 - showmoon ;
|
||
|
break;
|
||
|
|
||
|
case BT_SETTINGS: /* open settings dialog */
|
||
|
openSettings();
|
||
|
break;
|
||
|
|
||
|
case BT_APP: /* start calendar application */
|
||
|
if(appDoubleClick && (etime - appClickTime < DBLCLKTIME)){
|
||
|
applaunch = malloc(250);
|
||
|
strcpy(applaunch, (const char*)get_application());
|
||
|
strcat(applaunch, " &");
|
||
|
system(applaunch);
|
||
|
appDoubleClick = 0;
|
||
|
free(applaunch);
|
||
|
}
|
||
|
else{
|
||
|
appDoubleClick = 1;
|
||
|
appClickTime = etime;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default: /* no button clicked check for marking days*/
|
||
|
if(getClickedDay(bx, by)){
|
||
|
if(!icaltime_is_null_time(mark))
|
||
|
mark = icaltime_null_time();
|
||
|
else
|
||
|
mark = tgr;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case 4: /* mousewheel up : month back*/
|
||
|
monthOffset--;
|
||
|
break;
|
||
|
|
||
|
case 5: /* mousewheel down : month forward*/
|
||
|
monthOffset++;
|
||
|
break;
|
||
|
|
||
|
case 2: /* Middlemouse click : go to actual month*/
|
||
|
monthOffset = 0;
|
||
|
break;
|
||
|
|
||
|
case 3: /* rightmouse click : show day entries*/
|
||
|
if(getClickedDay(bx, by))
|
||
|
showDay(tgr);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
told.month = 0; /* invalid month -> forces clearScreen at next draw*/
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*------------------------------------------------------
|
||
|
* ParseCMDLine
|
||
|
-----------------------------------------------------*/
|
||
|
void ParseCMDLine(int argc, char *argv[]){
|
||
|
int i;
|
||
|
|
||
|
for (i = 1; i < argc; i++){
|
||
|
if (!strcmp(argv[i], "--version") || !strcmp(argv[i], "-v")){
|
||
|
printf("wmCalendar %s\n", getVersion());
|
||
|
exit(1);
|
||
|
}
|
||
|
else if (!strcmp(argv[i], "--help") || !strcmp(argv[i], "-h")){
|
||
|
print_usage();
|
||
|
exit(1);
|
||
|
}
|
||
|
else if (!strcmp(argv[i], "--farsi") || !strcmp(argv[i], "-f"))
|
||
|
set_lang(1);
|
||
|
else if (!strcmp(argv[i], "--persian") || !strcmp(argv[i], "-p"))
|
||
|
calendartype = 1;
|
||
|
else if (!strcmp(argv[i], "--debug") || !strcmp(argv[i], "-d"))
|
||
|
set_debug( 1);
|
||
|
else{
|
||
|
print_usage();
|
||
|
exit(1);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*------------------------------------------------------
|
||
|
* print_usage
|
||
|
-----------------------------------------------------*/
|
||
|
void print_usage()
|
||
|
{
|
||
|
printf("wmCalendar %s (c) 2003 Matthias Laabs (mattlaabs@users.sourceforge.net)\n", getVersion());
|
||
|
printf("This is free software under GPL!\n");
|
||
|
printf("\nOptions:");
|
||
|
printf("\n -h --help\n Show summary of options.");
|
||
|
printf("\n -v --version\n Show version of program.");
|
||
|
printf("\n -d --debug\n Show debugging info.");
|
||
|
printf("\n -f --farsi\n Show months and numbers in farsi.");
|
||
|
printf("\n -p --persian\n Changes to persian calendar.");
|
||
|
printf("\n\nUsage: \nLeft and right arrow or mousewheel change month.\n");
|
||
|
printf("Middle mouseclick goes back to current month.\n");
|
||
|
printf("Right mouseclick opens dayview.\nClick on Moon to toggle moonphase-view on/off\n");
|
||
|
printf("Click on screwdriver to open settings menu\nClick on 'G' to toggle between Gregorian, Persian and Islamic calendar\n");
|
||
|
printf("Doubleclick evolution/mozilla icon to start application\nClick on blue arrow to show/hide buttons\n");
|
||
|
printf("Leftclick a day to highlight for converting between calendars\n");
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*------------------------------------------------------
|
||
|
* getTime
|
||
|
-----------------------------------------------------*/
|
||
|
void getTime(){
|
||
|
struct tm *Time;
|
||
|
long CurrentLocalTime;
|
||
|
|
||
|
/* get time */
|
||
|
CurrentLocalTime = time(CurrentTime);
|
||
|
Time = localtime(&CurrentLocalTime);
|
||
|
t.day = Time->tm_mday;
|
||
|
t.month = Time->tm_mon + 1;
|
||
|
t.year = Time->tm_year + 1900;
|
||
|
today = t;
|
||
|
|
||
|
/* change calendar*/
|
||
|
if(calendartype == 1)
|
||
|
t = civil_persian(t);
|
||
|
else if(calendartype == 2)
|
||
|
t = civil_islamic(t);
|
||
|
/* set t to currently shown month and year */
|
||
|
t.month += monthOffset;
|
||
|
while(t.month > 12){
|
||
|
t.month -= 12;
|
||
|
t.year += 1;
|
||
|
}
|
||
|
while(t.month < 1){
|
||
|
t.month += 12;
|
||
|
t.year -= 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*------------------------------------------------------
|
||
|
* drawMonthYear
|
||
|
-----------------------------------------------------*/
|
||
|
void drawMonthYear(){
|
||
|
int xoff, yoff;
|
||
|
int Year1, Year2, Year3, Year4;
|
||
|
int monthset;
|
||
|
yoff = 1;
|
||
|
monthset = calendartype + get_lang() * CALTYPES;
|
||
|
/* calculate digits of the year */
|
||
|
Year4 = t.year % 10;
|
||
|
Year3 = ((t.year - Year4) / 10) % 10;
|
||
|
Year2 = ((t.year - Year4 - 10 * Year3) / 100) % 10;
|
||
|
Year1 = (t.year - Year4 - 10 * Year3 - 100 * Year2) / 1000;
|
||
|
|
||
|
xoff = 30 - (xdMonth[monthset][t.month-1] + xdYear[get_lang()][Year3] + xdYear[get_lang()][Year4]) / 2;
|
||
|
|
||
|
/* draw Month */
|
||
|
dockapp_copyarea(bg[1], pixmap, xsMonth[monthset][t.month - 1], yMonth[monthset],
|
||
|
xdMonth[monthset][t.month - 1], ydMonth, xoff, yoff);
|
||
|
xoff += xdMonth[monthset][t.month - 1] + 3;
|
||
|
|
||
|
/* draw Year 3rd and 4th digit */
|
||
|
dockapp_copyarea(bg[1], pixmap,xsYear[get_lang()][Year3], yYear, xdYear[get_lang()][Year3], ydYear, xoff, yoff);
|
||
|
xoff += xdYear[get_lang()][Year3];
|
||
|
dockapp_copyarea(bg[1], pixmap,xsYear[get_lang()][Year4], yYear, xdYear[get_lang()][Year4], ydYear, xoff, yoff);
|
||
|
dockapp_copy2window(pixmap);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*------------------------------------------------------
|
||
|
* drawButtons
|
||
|
-----------------------------------------------------*/
|
||
|
void drawButtons(){
|
||
|
int xoff, yoff;
|
||
|
yoff = 56;
|
||
|
xoff = 56;
|
||
|
if(showbuttons){
|
||
|
xoff = drawButton(ARROW_CLOSE, xoff, yoff);
|
||
|
xoff = drawButton(SETTINGS, xoff, yoff);
|
||
|
xoff = drawButton(MOON + showmoon, xoff, yoff);
|
||
|
xoff = drawButton(CALENDAR + calendartype, xoff, yoff);
|
||
|
xoff = drawButton(APPLAUNCH + getAppicon(), xoff, yoff);
|
||
|
}
|
||
|
else
|
||
|
drawButton(ARROW_OPEN, xoff, yoff);
|
||
|
|
||
|
dockapp_copy2window(pixmap);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*------------------------------------------------------
|
||
|
* drawButton
|
||
|
-----------------------------------------------------*/
|
||
|
int drawButton(int btype, int xoff, int yoff){
|
||
|
xoff-= xdButton[btype];
|
||
|
dockapp_copyarea(bg[0], pixmap, xsButton[btype], yButton[btype], xdButton[btype],
|
||
|
ydButton, xoff, yoff);
|
||
|
return --xoff;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*------------------------------------------------------
|
||
|
* drawDays
|
||
|
-----------------------------------------------------*/
|
||
|
void drawDays()
|
||
|
{
|
||
|
int i, dayOfWeek;
|
||
|
int amount, startday;
|
||
|
int moonphase = 0;
|
||
|
int yoff = 20;
|
||
|
|
||
|
tgr = t;
|
||
|
tgr.day = 1;
|
||
|
|
||
|
tgr = get_civil(tgr, calendartype);
|
||
|
amount = days_in_month(t.month, t.year, calendartype);
|
||
|
startday = (day_of_week(tgr) + get_start_of_week()) % 7;
|
||
|
for(i = 1; i <= amount; i++){
|
||
|
dayOfWeek = (startday + i) % 7;
|
||
|
if((dayOfWeek == 0) && (i != 1))
|
||
|
yoff += 7; /* increase y-offset on Monday except it is day #1*/
|
||
|
|
||
|
tgr = t;
|
||
|
tgr.day = i;
|
||
|
tgr = get_civil(tgr, calendartype);
|
||
|
|
||
|
if(showmoon)
|
||
|
moonphase = moon(tgr);
|
||
|
|
||
|
if(daysEqual(tgr, mark))
|
||
|
drawNumber(i, yoff, dayOfWeek, 3, 0);
|
||
|
else if(moonphase == 0 || !showmoon) /* draw number */
|
||
|
drawNumber(i, yoff, dayOfWeek, getDayType(tgr), daysEqual(tgr, today));
|
||
|
else /* draw moonphase */
|
||
|
dockapp_copyarea(bg[0], pixmap, xsMoon[moonphase - 1], yMoon, xdMoon, ydMoon,
|
||
|
dayOfWeek * 9, yoff);
|
||
|
}
|
||
|
|
||
|
dockapp_copy2window(pixmap);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*------------------------------------------------------
|
||
|
* drawNumber
|
||
|
-----------------------------------------------------*/
|
||
|
void drawNumber(int number,int yoff, int dayOfWeek, int type, int today){
|
||
|
int digit1, digit2;
|
||
|
int offset;
|
||
|
offset = yNumbers + 20 * type + 10 * today;
|
||
|
if(number < 10){ /* draw single digit numbers*/
|
||
|
dockapp_copyarea(bg[0], pixmap, xeNumbers[get_lang()][1] - 5, offset, 2, ydNumbers,
|
||
|
dayOfWeek * 9, yoff);
|
||
|
dockapp_copyarea(bg[0], pixmap, xeNumbers[get_lang()][1] - 5, offset, 2, ydNumbers,
|
||
|
dayOfWeek * 9 + 7, yoff);
|
||
|
dockapp_copyarea(bg[0], pixmap, xeNumbers[get_lang()][number], offset, xdNumbers, ydNumbers,
|
||
|
dayOfWeek * 9 + 2, yoff);
|
||
|
}
|
||
|
else{ /* draw double digit numbers*/
|
||
|
digit2 = number % 10;
|
||
|
digit1 = (number - digit2) / 10;
|
||
|
dockapp_copyarea(bg[0], pixmap, xeNumbers[get_lang()][digit1], offset, xdNumbers, ydNumbers,
|
||
|
dayOfWeek * 9, yoff);
|
||
|
dockapp_copyarea(bg[0], pixmap, xeNumbers[get_lang()][digit2], offset, xdNumbers, ydNumbers,
|
||
|
dayOfWeek * 9 + 4, yoff);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*------------------------------------------------------
|
||
|
* processXEvents
|
||
|
-----------------------------------------------------*/
|
||
|
int processXEvents()
|
||
|
{
|
||
|
if(dockapp_nextevent_or_timeout(&event, 150)) {
|
||
|
/* Next Event */
|
||
|
switch (event.type) {
|
||
|
case ButtonPress:
|
||
|
buttonPress(event.xbutton.button,event.xbutton.x, event.xbutton.y, event.xbutton.time);
|
||
|
return 1;
|
||
|
default: break;
|
||
|
}
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*------------------------------------------------------
|
||
|
* blankScreen
|
||
|
-----------------------------------------------------*/
|
||
|
void blankScreen()
|
||
|
{
|
||
|
if(daysEqual(t, told))
|
||
|
return;
|
||
|
/* only neccessary if day has changed*/
|
||
|
dockapp_copyarea(bg[0], pixmap, 0, 0, 64, 64, 0, 0);
|
||
|
dockapp_copyarea(bg[0], pixmap, 9 * (7 - get_start_of_week()),70 + get_lang() * 12, 63, 8, 0, 12);
|
||
|
dockapp_copy2window(pixmap);
|
||
|
calendar(); /* reread calendardata */
|
||
|
told = t;
|
||
|
}
|