📄 rclock.c
字号:
/*--------------------------------*-C-*---------------------------------* * Copyright 1997 1998 Oezguer Kesim <kesim@math.fu-berlin.de> * Copyright 1992, 1993 Robert Nation <nation@rocket.sanders.lockheed.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *----------------------------------------------------------------------*/#ifdef HAVE_CONFIG_H# include <config.h>#else/* # define STDC_HEADERS */# define HAVE_UNISTD_H# define TIME_WITH_SYS_TIME# define HAVE_SYS_TIME_H# ifdef _AIX# define HAVE_SYS_SELECT_H# endif#endif#include "../src/version.h"#include "feature.h"#include <ctype.h>/* #ifdef STDC_HEADERS */# include <stdarg.h># include <stdio.h># include <stdlib.h># include <string.h>/* #endif */#ifdef HAVE_UNISTD_H# include <unistd.h>#endif#ifdef TIME_WITH_SYS_TIME# include <sys/time.h># include <time.h>#else# ifdef HAVE_SYS_TIME_H# include <sys/time.h># else# include <time.h># endif#endif#if defined (__svr4__)# include <sys/resource.h> /* for struct rlimit */#endif#ifdef HAVE_SYS_SELECT_H# include <sys/select.h>#endif#include <sys/stat.h>#ifdef MAIL#include <dirent.h>#endif#include <X11/Intrinsic.h> /* Xlib, Xutil, Xresource, Xfuncproto */#define APL_CLASS "Clock"#define APL_NAME "rclock"#define MSG_CLASS "Appointment"#define MSG_NAME "Appointment"#define CONFIG_FILE ".rclock"#ifndef EXIT_SUCCESS /* missed from <stdlib.h> ? */# define EXIT_SUCCESS 0# define EXIT_FAILURE 1#endif/*----------------------------------------------------------------------*/static Display* Xdisplay; /* X display */static int Xfd; /* file descriptor of server connection */static GC Xgc, Xrvgc; /* normal, reverse video GC */#define Xscreen DefaultScreen (Xdisplay)#define Xcmap DefaultColormap (Xdisplay, Xscreen)#define Xroot DefaultRootWindow (Xdisplay)/* windows and their sizes */typedef struct { Window win; int width, height;} mywindow_t;static mywindow_t Clock = {None, 80, 80}; /* parent window */#define fgColor 0#define bgColor 1static const char * rs_color [2] = { FG_COLOR_NAME, BG_COLOR_NAME };static Pixel PixColors [2];static const char * rs_geometry = NULL;#ifdef ICONWINstatic const char * rs_iconGeometry = NULL;static mywindow_t Icon = {None, 65, 65}; /* icon window */static int iconic_state = NormalState; /* iconic startup? */#endif#ifdef REMINDERSstatic mywindow_t Msg = {0, 0, 0}; /* message window */static struct { Window# ifndef NO_REMINDER_EXEC Start,# endif Dismiss, Defer; int width, height;} msgButton;static XFontStruct * Xfont;#define FontHeight() (Xfont->ascent + Xfont->descent)static int Msg_Mapped = 0; /* message window mapped? */static int reminderTime = -1;static char message [256] = "";#ifndef NO_REMINDER_EXECstatic char execPrgm [256] = "";#endifstatic const char * reminders_file = NULL; /* name of ~/.rclock file */#ifdef DATE_ON_CLOCK_FACEstatic int show_date = 1; /* show date on face of clock */#endif#endif#ifdef ADJUST_TIMEstatic int adjustTime = 0;#else# define adjustTime 0#endif#ifdef CENTURY# if (CENTURY < 1900)Error, Cenury incorrectly set.# endif#else# define CENTURY 1900#endifstatic int clockUpdate = CLOCKUPDATE;#ifdef MAILstatic int mailUpdate = MAILUPDATE;static char * mail_file = NULL;#ifndef MAIL_SPAWNstatic char * mail_spawn = NULL;#endifstatic int is_maildir = 0;#endifstatic XSizeHints szHint = { PMinSize | PResizeInc | PBaseSize | PWinGravity, 0, 0, 80, 80, /* x, y, width and height */ 1, 1, /* Min width and height */ 0, 0, /* Max width and height */ 1, 1, /* Width and height increments */ {1, 1}, /* x, y increments */ {1, 1}, /* Aspect ratio - not used */ 0, 0, /* base size */ NorthWestGravity /* gravity */};/* subroutine declarations */static void geometry2sizehint (mywindow_t * /* win */, const char * /* geom */);static void Create_Windows (int /* argc */, char * /* argv */ []);static void getXevent (void);static void print_error (const char * /* fmt */, ...);static void Draw_Window (mywindow_t * /* this_win */, int /* full_redraw */);static void Reminder (void);static void Next_Reminder (int /* update_only */);/* Arguments for Next_Reminder() */#define REPLACE 0#define UPDATE 1/*----------------------------------------------------------------------*/static voidusage (void){ int i; struct { const char * const opt; const char * const desc; } optList[] = {#define optList_size() (sizeof(optList)/sizeof(optList[0])) { "-display displayname", "X server to contact" }, { "-geometry geom", "size (in pixels) and position" }, { "-bg color", "background color" }, { "-fg color", "foreground color" },#ifdef REMINDERS { "-fn fontname", "normal font for messages" },#ifdef DATE_ON_CLOCK_FACE { "-nodate", "do not display date on the clock face" },#endif#endif#ifdef ICONWIN { "-iconic", "start iconic" },#endif#ifdef ADJUST_TIME { "-adjust +/-ddhhmm", "adjust clock time" },#endif { "-update seconds", "clock update interval" },#ifdef MAIL { "-mail seconds", "check $MAIL interval" }, { "-mailfile file", "file to use for mail checking" },#ifndef MAIL_SPAWN { "-mailspawn cmd", "execute `cmd` when clock is clicked" },#endif#endif { "#geom", "icon window geometry" } }; fprintf (stderr, "\nUsage v" VERSION ":\n " APL_NAME " [options]\n\n" "where options include:\n"); for (i = 0; i < optList_size(); i++) fprintf (stderr, " %-29s%s\n", optList[i].opt, optList[i].desc);}/**************** * Check out if we are using a maildir drop (qmail) * Note: this changes mail_dir to hold the "new" diretory */#ifdef MAILstatic voidCheckMaildir(){ struct stat st; char *buf, *p; if( !*mail_file || stat(mail_file, &st) || !S_ISDIR(st.st_mode) ) return; /* no */ if( !(buf = malloc(strlen(mail_file)+5)) ) { print_error ("malloc error"); exit( EXIT_FAILURE ); } strcpy(buf,mail_file); p = buf+strlen(buf); if( p[-1] != '/' ) *p++ = '/'; strcpy(p, "tmp" ); if( stat(buf, &st) || !S_ISDIR(st.st_mode ) ) goto leave; strcpy(p, "cur" ); if( stat(buf, &st) || !S_ISDIR(st.st_mode ) ) goto leave; strcpy(p, "new" ); if( stat(buf, &st) || !S_ISDIR(st.st_mode ) ) goto leave; mail_file = buf; is_maildir = 1; return; leave: free(buf);}#endif/*----------------------------------------------------------------------* * rclock - Rob's clock * simple X windows clock with appointment reminder *----------------------------------------------------------------------*/intmain (int argc, char * argv []){ int i; char * opt, * val; const char * display_name = NULL; XGCValues gcv;#ifdef REMINDERS const char * rs_font = FONT_NAME; /* find the ~/.rclock file */ if ((val = getenv ("HOME")) != NULL) { char * p = malloc (strlen (CONFIG_FILE) + strlen (val) + 2); if (p == NULL) goto Malloc_Error; strcpy (p, val); strcat (p, "/" CONFIG_FILE); reminders_file = p; }#endif#ifdef MAIL val = getenv ("MAIL"); /* get the mail spool file name */#ifdef MAIL_SPOOL if (val == NULL) /* csh doesn't set $MAIL */ { const char * spool = MAIL_SPOOL; char * user = getenv ("USER"); /* assume this works */ val = malloc (strlen (spool) + strlen (user) + 1); if (val == NULL) goto Malloc_Error; strcpy (val, spool); strcat (val, user); }#endif mail_file = val; if( mail_file ) CheckMaildir();#endif if ((display_name = getenv ("DISPLAY")) == NULL) display_name = ":0"; /* parse the command line */ for (i = 1; i < argc; i += 2) { opt = argv [i]; val = argv [i+1]; switch (*opt++) { case '-': break; case '#':#ifdef ICONWIN rs_iconGeometry = opt; /* drop */#endif default: continue; break; } if (*opt == 'd' && val) display_name = val; /* "d", "display" */ else if (*opt == 'g' && val) rs_geometry = val; /* "g", "geometry" */#ifdef ICONWIN else if (*opt == 'i') /* "ic", "iconic" */ { iconic_state = IconicState; i--; /* no argument */ }#endif else if (!strcmp (opt, "fg") && val) rs_color [fgColor] = val; else if (!strcmp (opt, "bg") && val) rs_color [bgColor] = val;#ifdef REMINDERS else if (!strcmp (opt, "fn") && val) rs_font = val;#ifdef DATE_ON_CLOCK_FACE else if (!strcmp (opt, "nodate")) { show_date = 0; i--; /* no argument */ }#endif#endif else if (!strcmp (opt, "update") && val) { int x = atoi (val); if (x < 1 || x > 60) print_error ("update: %d sec", clockUpdate); else clockUpdate = x; }#ifdef MAIL else if (!strcmp (opt, "mail") && val) { int x = atoi (val); if (x < 1) print_error ("mail update: %d sec", mailUpdate); else mailUpdate = x; } else if (!strcmp (opt, "mailfile") && val) { /* If the mail environment is not set, then mail_file was created * with a malloc. We need to free it. */ if( getenv ("MAIL") == NULL) free( mail_file); /* assume user knows what he's doing, don't check that file is valid...*/ mail_file = val; }#ifndef MAIL_SPAWN else if (!strcmp (opt, "mailspawn") && val) { mail_spawn = val; }#endif#endif /* MAIL */#ifdef ADJUST_TIME else if (!strcmp (opt, "adjust") && val) { /* convert ddhhmm to seconds, minimal error checking */ int x = atoi (val); adjustTime = ((((abs (x) / 10000) % 100) * 24 /* days */ + ((abs (x) / 100) % 100)) * 60 /* hours */ + (abs (x) % 100)) * 60; /* minutes */ if (x < 0) adjustTime = -adjustTime; }#endif /* ADJUST_TIME */ else { usage (); goto Abort; } } /* open display */ Xdisplay = XOpenDisplay (display_name); if (!Xdisplay) { print_error ("can't open display %s", display_name); goto Abort; } /* get display info */ Xfd = XConnectionNumber (Xdisplay); { const char * const color_msg = "can't load color \"%s\""; XColor xcol; /* allocate foreground/background colors */ if (!XParseColor (Xdisplay, Xcmap, rs_color [fgColor], &xcol) || !XAllocColor (Xdisplay, Xcmap, &xcol)) { print_error (color_msg, rs_color [fgColor]); goto Abort; } PixColors [fgColor] = xcol.pixel; if (!XParseColor (Xdisplay, Xcmap, rs_color [bgColor], &xcol) || !XAllocColor (Xdisplay, Xcmap, &xcol)) { print_error (color_msg, rs_color [bgColor]); goto Abort; } PixColors [bgColor] = xcol.pixel; }#ifdef REMINDERS /* load the font for messages */ if ((Xfont = XLoadQueryFont (Xdisplay, rs_font)) == NULL) { print_error ("can't load font \"%s\"", rs_font); goto Abort; } gcv.font = Xfont->fid;#endif Create_Windows (argc, argv); /* Create the graphics contexts */ gcv.foreground = PixColors [fgColor]; gcv.background = PixColors [bgColor]; Xgc = XCreateGC (Xdisplay, Clock.win,#ifdef REMINDERS GCFont |#endif GCForeground | GCBackground, &gcv); gcv.foreground = PixColors [bgColor]; gcv.background = PixColors [fgColor]; Xrvgc = XCreateGC (Xdisplay, Clock.win,#ifdef REMINDERS GCFont |#endif GCForeground | GCBackground, &gcv); getXevent (); return EXIT_SUCCESS; Malloc_Error: print_error ("malloc error"); Abort: print_error ("aborting"); return EXIT_FAILURE;}/* * translate geometry string to appropriate sizehint */static voidgeometry2sizehint (mywindow_t * win, const char * geom){ int x, y, flags; unsigned int width, height; /* copy in values */ szHint.width = win->width; szHint.height = win->height; if (geom == NULL) return; flags = XParseGeometry (geom, &x, &y, &width, &height); if (flags & WidthValue) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -