/***************************************************************************** XREMIND: Opens a full screen window with a vector graphics text reminder message at the given time. The time can either be at a certain time or after a certain time and can be repeated. Written by Neil Robertson, January 2004. Last update: October 2005 *****************************************************************************/ #include #include #include #include #include #include #include #include #define SEP 13 #define DEGS_PER_RADIAN 57.29578 #define LEFT_SCR_X 10 #define SPIRAL_MULT 3 /*** Function prototypes ***/ void parse_command_line(int argc, char **argv); void set_trigger_time(char *tstr); void wait_and_init(); void do_text_animation(); void move(); void charcalc(int pos); void draw(GC gc, int pos, char ascii); /*** Global vars ***/ enum { TRIG_NOTSET, TRIG_AT, TRIG_AFTER }; Display *display; Window win; GC gcw,gcb; time_t trigtime; time_t timeadd; char *disp; char *text; char *fgcol; char *bgcol; int starting; int repeat; int trigtype; int dwidth; int dheight; int dwidth2; int dheight2; int dwidth3; int hx,hy; int movement; int movestart; int moveang; int delay; int scroll; int scale; int lwidth; int sep; int charsize; int hr,min,sec; int timeout; /*** Movement states ***/ enum { MOVE_LEFT, MOVE_RIGHT, MOVE_CLOCKWISE, MOVE_ANTICLOCKWISE, MOVE_WAVE, MOVE_ROTATE, MOVE_SPIRAL }; /*** Co-ord and template structs ***/ struct xy { int x,y; }; struct char_template { int cnt; struct xy data[1]; } *trans[256]; /*** CHARACTER DATA ***/ struct { int cnt; } char_space = { 0 }; struct { int cnt; struct xy data[6]; } char_a = { 6, {{ 0,10 }, { 5,0 }, { 5,0 }, { 10,10 }, { 2,6 }, {8,6 }} }; struct { int cnt; struct xy data[20]; } char_b = { 20, {{ 0,0 }, { 8,0 }, { 8,0 }, { 10,1 }, { 10,1 }, { 10,4 }, { 10,4 }, { 5,5 }, { 5,5 }, { 10,6 }, { 10,6 }, { 10,9 }, { 10,9 }, { 8,10 }, { 8,10 }, { 0,10 }, { 0,10 }, { 0,0 }, { 0,5 }, { 5,5 }} }; struct { int cnt; struct xy data[14]; } char_c = { 14, {{10,1 } , { 9,0 }, { 9,0 } , { 2,0 }, { 2,0 }, { 0,2 }, { 0,2 }, { 0,8 }, { 0,8 }, { 2,10 }, { 2,10 }, { 9,10 }, { 9,10 }, { 10,9 }} }; struct { int cnt; struct xy data[12]; } char_d = { 12, {{ 0,0 }, { 7,0 }, { 7,0 }, { 10,2 }, { 10,2 }, { 10,8 }, { 10,8 }, { 7,10 }, { 7,10 }, { 0,10 }, { 0,10 }, { 0,0 }} }; struct { int cnt; struct xy data[8]; } char_e = { 8, {{ 0,0 }, { 10,0 }, { 0,0 } , { 0,10 }, { 0,5 }, { 7,5 }, { 0,10 }, { 10,10 }} }; struct { int cnt; struct xy data[6]; } char_f = { 6, {{ 0,0 } , { 10,0 }, { 0,0 }, { 0,10 }, { 0,5 }, { 7,5 }} }; struct { int cnt; struct xy data[18]; } char_g = { 18, {{ 10,2 } , { 7,0 }, { 7,0 }, { 2,0 }, { 2,0 }, { 0,2 }, { 0,2 }, { 0,8 }, { 0,8 }, { 2,10 }, { 2,10 }, { 7,10 }, { 7,10 }, { 10,7 }, { 10,7 }, { 10,5 }, { 10,5 }, { 5,5 }} }; struct { int cnt; struct xy data[6]; } char_h = { 6, {{ 0,0 }, { 0,10 }, { 0,5 }, { 10,5 }, { 10,0 }, { 10,10 }} }; struct { int cnt; struct xy data[6]; } char_i = { 6, {{ 0,0 }, { 10,0 }, { 5,0 }, { 5,10 }, { 0,10 }, { 10,10 }} }; struct { int cnt; struct xy data[12]; } char_j = { 12, {{ 0,0 }, { 10,0 }, { 7,0 }, { 7,7 }, { 7,7 }, { 5,10 }, { 5,10 }, { 2,10 }, { 2,10 }, { 1,8 }, { 1,8 }, { 1,6 }} }; struct { int cnt; struct xy data[6]; } char_k = { 6, {{ 0,0 }, { 0,10 }, { 0,7 }, { 10,0 }, { 3,5 }, { 10,10 }} }; struct { int cnt; struct xy data[4]; } char_l = { 4, {{ 0,0 }, { 0,10 }, { 0,10 }, { 10,10 }} }; struct { int cnt; struct xy data[8]; } char_m = { 8, {{ 0,0 } , { 0,10 }, { 0,0 }, { 5,5 }, { 5,5 }, { 10,0 }, { 10,0 }, { 10,10 }} }; struct { int cnt; struct xy data[6]; } char_n = { 6, {{ 0,0 }, { 0,10 }, { 0,0 }, { 10,10 }, { 10,10 }, { 10,0 }} }; struct { int cnt; struct xy data[16]; } char_o = { 16, {{ 3,0 }, { 7,0 }, { 7,0 }, { 10,3 }, { 10,3 }, { 10,7 }, { 10,7 }, { 7,10 }, { 7,10 }, { 3,10 }, { 3,10 }, { 0,7 }, { 0,7 }, { 0,3 }, { 0,3 }, { 3,0 }} }; struct { int cnt; struct xy data[12]; } char_p = { 12, {{ 0,0 }, { 7,0 }, { 7,0 }, { 10,2 }, { 10,2 }, { 10,4 }, { 10,4 }, { 7,6 }, { 7,6 }, { 0,6 }, { 0,0 }, { 0,10 }} }; struct { int cnt; struct xy data[18]; } char_q = { 18, {{ 3,0 }, { 7,0 }, { 7,0 }, { 10,3 }, { 10,3 }, { 10,7 }, { 10,7 }, { 7,10 }, { 7,10 }, { 3,10 }, { 3,10 }, { 0,7 }, { 0,7 }, { 0,3 }, { 0,3 }, { 3,0 }, { 0,10 }, { 4,6 }} }; struct { int cnt; struct xy data[14]; } char_r = { 14, {{ 0,0 }, { 7,0 }, { 7,0 }, { 10,2 }, { 10,2 }, { 10,4 }, { 10,4 }, { 7,6 }, { 7,6 }, { 0,6 }, { 0,0 }, { 0,10 }, { 3,6 }, { 9,10 }} }; struct { int cnt; struct xy data[22]; } char_s = { 22, {{ 10,1 }, { 9,0 }, { 9,0 }, { 1,0 }, { 1,0 }, { 0,1 }, { 0,1 }, { 0,4 }, { 0,4 }, { 1,5 }, { 1,5 }, { 9,5 }, { 9,5 }, { 10,6 }, { 10,6 }, { 10,9 }, { 10,9 }, { 9,10 }, { 9,10 }, { 1,10 }, { 1,10 }, { 0,9 }} }; struct { int cnt; struct xy data[4]; } char_t = { 4, {{ 0,0 }, { 10,0 }, { 5,0 }, { 5,10 }} }; struct { int cnt; struct xy data[10]; } char_u = { 10, {{ 0,0 } , { 0,8 }, { 0,8 }, { 2,10 }, { 2,10 }, { 8,10 }, { 8,10 }, { 10,8 }, { 10,8 }, { 10,0 }} }; struct { int cnt; struct xy data[4]; } char_v = { 4, {{ 0,0 }, { 5,10 }, { 5,10 }, { 10,0 }} }; struct { int cnt; struct xy data[8]; } char_w = { 8, {{ 0,0 }, { 2,10 }, { 2,10 }, { 5,4 }, { 5,4 }, { 8,10 }, { 8,10 }, { 10,0 }} }; struct { int cnt; struct xy data[4]; } char_x = { 4, {{ 0,0 }, { 10,10 }, { 10,0 }, { 0,10 }} }; struct { int cnt; struct xy data[4]; } char_y = { 4, {{ 0,0 }, { 6,4 }, { 10,0 }, { 2,10 }} }; struct { int cnt; struct xy data[6]; } char_z = { 6, {{ 0,0 }, { 10,0 }, { 10,0 }, { 0,10 }, { 0,10 }, { 10,10 }} }; struct { int cnt; struct xy data[6]; } char_1 = { 6, {{ 2,3 }, { 5,0 }, { 5,0 }, { 5,10 }, { 0,10 }, { 10,10 }} }; struct { int cnt; struct xy data[12]; } char_2 = { 12, {{ 0,2 }, { 2,0 }, { 2,0 }, { 8,0 }, { 8,0 }, { 10,2 }, { 10,2 }, { 10,4 }, { 10,4 }, { 0,10 }, { 0,10 }, { 10,10 }} }; struct { int cnt; struct xy data[16]; } char_3 = { 16, {{ 0,1 }, { 1,0 }, { 1,0 }, { 9,0 }, { 9,0 }, { 10,1 }, { 10,1 }, { 10,9 }, { 10,9 }, { 9,10 }, { 9,10 }, { 1,10 }, { 1,10 }, { 0,9 }, { 3,5 }, { 10,5 }} }; struct { int cnt; struct xy data[6]; } char_4 = { 6, {{ 10,5 }, { 0,5 }, { 0,5 }, { 5,0 }, { 5,0 }, { 5,10 }} }; struct { int cnt; struct xy data[14]; } char_5 = { 14, {{ 10,0 }, { 0,0 }, { 0,0 }, { 0,5 }, { 0,5 }, { 9,5 }, { 9,5 }, { 10,6 }, { 10,6 }, { 10,9 }, { 10,9 }, { 9,10 }, { 9,10 }, { 0,10 }} }; struct { int cnt; struct xy data[18]; } char_6 = { 18, {{ 10,0 }, { 1,0 }, { 1,0 }, { 0,1 }, { 0,1 }, { 0,9 }, { 0,9 }, { 1,10 }, { 1,10 }, { 9,10 }, { 9,10 }, { 10,9 }, { 10,9 }, { 10,6 }, { 10,6 }, { 9,5 }, { 9,5 }, { 0,5 }} }; struct { int cnt; struct xy data[4]; } char_7 = { 4, {{ 0,0 }, { 10,0 }, { 10,0 }, { 2,10 }} }; struct { int cnt; struct xy data[30]; } char_8 = { 30, {{ 1,0 }, { 9,0 }, { 9,0 }, { 10,1 }, { 10,1 }, { 10,4 }, { 10,4 }, { 9,5 }, { 9,5 }, { 10,6 }, { 10,6 }, { 10,9 }, { 10,9 }, { 9,10 }, { 9,10 }, { 1,10 }, { 1,10 }, { 0,9 }, { 0,9 }, { 0,6 }, { 0,6 }, { 1,5 }, { 1,5 }, { 0,4 }, { 0,4 }, { 0,1 }, { 0,1 }, { 1,0 }, { 1,5 }, { 9,5 }} }; struct { int cnt; struct xy data[18]; } char_9 = { 18, {{ 1,10 }, { 9,10 }, { 9,10 }, { 10,9 }, { 10,9 }, { 10,1 }, { 10,1 }, { 9,0 }, { 9,0 }, { 1,0 }, { 1,0 }, { 0,1 }, { 0,1 }, { 0,4 }, { 0,4 }, { 1,5 }, { 1,5 }, { 10,5 }} }; struct { int cnt; struct xy data[18]; } char_0 = { 18, {{ 3,0 }, { 7,0 }, { 7,0 }, { 10,3 }, { 10,3 }, { 10,7 }, { 10,7 }, { 7,10 }, { 7,10 }, { 3,10 }, { 3,10 }, { 0,7 }, { 0,7 }, { 0,3 }, { 0,3 }, { 3,0 }, { 3,10 }, { 7.0 }} }; struct { int cnt; struct xy data[16]; } char_qmark = { 16, {{ 0,2 }, { 2,0 }, { 2,0 }, { 9,0 }, { 9,0 }, { 10,1 }, { 10,1 }, { 10,4 }, { 10,4 }, { 9,5 }, { 9,5 }, { 5,5 }, { 5,5 }, { 5,7 }, { 5,9 }, { 5,10 }} }; struct { int cnt; struct xy data[8]; } char_exmark = { 8, {{ 4,0 }, { 6,0 }, { 6,0 }, { 5,7 }, { 5,7 }, { 4,0 }, { 5,9 }, { 5,10 }} }; struct { int cnt; struct xy data[4]; } char_plus = { 4, {{ 5,0 }, { 5,10 }, { 0,5 }, { 10,5 }} }; struct { int cnt; struct xy data[2]; } char_minus = { 2, {{ 0,5 }, { 10,5 }} }; struct { int cnt; struct xy data[8]; } char_star = { 8, {{ 0,5 }, { 10,5 }, { 5,0 }, { 5,10 }, { 1,1 }, { 9,9 }, { 1,9 }, { 9,1 }} }; struct { int cnt; struct xy data[4]; } char_equals = { 4, {{ 0,3 }, { 10,3 }, { 0,7 }, { 10,7 }} }; struct { int cnt; struct xy data[10]; } char_dot = { 8, {{ 4,8 }, { 6,8 }, { 6,8 }, { 6,10 }, { 6,10 }, { 4,10 }, { 4,10 }, { 4,8 }} }; struct { int cnt; struct xy data[4]; } char_comma = { 4, {{ 7,6 }, { 6,9 }, { 6,9 }, { 4,10 }} }; struct { int cnt; struct xy data[10]; } char_lrbracket = { 10, {{ 6,0 }, { 5,0 }, { 5,0 }, { 3,2 }, { 3,2 }, { 3,8 }, { 3,8 }, { 5,10 }, { 5,10 }, { 6,10 }} }; struct { int cnt; struct xy data[10]; } char_rrbracket = { 10, {{ 3,0 }, { 4,0 }, { 4,0 }, { 6,2 }, { 6,2 }, { 6,8 }, { 6,8 }, { 4,10 }, { 4,10 }, { 3,10 }} }; struct { int cnt; struct xy data[12]; } char_lcbracket = { 12, {{ 6,0 }, { 4,1 }, { 4,1 }, { 4,4 }, { 4,4 }, { 2,5 }, { 2,5 }, { 4,6 }, { 4,6 }, { 4,9 }, { 4,9 }, { 6,10 }} }; struct { int cnt; struct xy data[12]; } char_rcbracket = { 12, {{ 4,0 }, { 6,1 }, { 6,1 }, { 6,4 }, { 6,4 }, { 8,5 }, { 8,5 }, { 6,6 }, { 6,6 }, { 6,9 }, { 6,9 }, { 4,10 }} }; struct { int cnt; struct xy data[6]; } char_lsbracket = { 6, {{ 7,0 }, { 3,0 }, { 3,0 }, { 3,10 }, { 3,10 }, { 7,10 }} }; struct { int cnt; struct xy data[6]; } char_rsbracket = { 6, {{ 3,0 }, { 7,0 }, { 7,0 }, { 7,10 }, { 7,10 }, { 3,10 }} }; struct { int cnt; struct xy data[26]; } char_dollar = { 26, {{ 10,2 }, { 9,1 }, { 9,1 }, { 1,1 }, { 1,1 }, { 0,2 }, { 0,2 }, { 0,4 }, { 0,4 }, { 1,5 }, { 1,5 }, { 9,5 }, { 9,5 }, { 10,6 }, { 10,6 }, { 10,8 }, { 10,8 }, { 9,9 }, { 9,9 }, { 1,9 }, { 1,9 }, { 0,8 }, { 4,0 }, { 4,10 }, { 6,0 }, { 6,10 }} }; struct { int cnt; struct xy data[8]; } char_hash = { 8, {{ 0,3 }, { 10,3 }, { 0,7 }, { 10,7 }, { 3,0 }, { 3,10 }, { 7,0 }, { 7,10 }} }; struct { int cnt; struct xy data[4]; } char_fslash = { 4, {{ 10,0 }, { 0,10 }} }; struct { int cnt; struct xy data[4]; } char_bslash = { 4, {{ 0,0 }, { 10,10 }} }; struct { int cnt; struct xy data[4]; } char_greater = { 4, {{ 10,0 }, { 0,5 }, { 0,5 }, { 10,10 }} }; struct { int cnt; struct xy data[4]; } char_less = { 4, {{ 0,0 }, { 10,5 }, { 10,5 }, { 0,10 }} }; struct { int cnt; struct xy data[2]; } char_underscore = { 2, {{ 0,10 }, { 10,10 }} }; struct { int cnt; struct xy data[2]; } char_bar = { 2, {{ 5,0 }, { 5,10 }} }; struct { int cnt; struct xy data[2]; } char_squote = { 2, {{ 6,0 }, { 4,3 }} }; struct { int cnt; struct xy data[4]; } char_dquote = { 4, {{ 3,0 }, { 3,2 }, { 7,0 }, { 7,2 }} }; struct { int cnt; struct xy data[2]; } char_bquote = { 2, {{ 4,0 }, { 6,3 }} }; struct { int cnt; struct xy data[16]; } char_colon = { 16, {{ 4,1 }, { 6,1 }, { 6,1 }, { 6,3 }, { 6,3 }, { 4,3 }, { 4,3 }, { 4,1 }, { 4,7 }, { 6,7 }, { 6,7 }, { 6,9 }, { 6,9 }, { 4,9 }, { 4,9 }, { 4,7 }} }; struct { int cnt; struct xy data[12]; } char_semicolon = { 12, {{ 4,1 }, { 6,1 }, { 6,1 }, { 6,3 }, { 6,3 }, { 4,3 }, { 4,3 }, { 4,1 }, { 6,6 }, { 6,8 }, { 6,8 }, { 4,10 }} }; struct { int cnt; struct xy data[36]; } char_at = { 36, {{ 7,6 }, { 7,4 }, { 7,4 }, { 6,3 }, { 6,3 }, { 4,3 }, { 4,3 }, { 3,4 }, { 3,4 }, { 3,6 }, { 3,6 }, { 4,7 }, { 4,7 }, { 6,7 }, { 6,7 }, { 7,6 }, { 7,6 }, { 8,7 }, { 8,7 }, { 9,6 }, { 9,6 }, { 9,2 }, { 9,2 }, { 7,0 }, { 7,0 }, { 2,0 }, { 2,0 }, { 0,2 }, { 0,2 }, { 0,8 }, { 0,8 }, { 2,10 }, { 2,10 }, { 8,10 }, { 8,10 }, { 10,8 }} }; struct { int cnt; struct xy data[4]; } char_hat = { 4, {{ 5,0 }, { 1,5 }, { 5,0 }, { 9,5 }} }; struct { int cnt; struct xy data[6]; } char_tilda = { 6, {{ 1,2 }, { 3,0 }, { 3,0 }, { 5,2 }, { 5,2 }, { 7,0 }} }; struct { int cnt; struct xy data[26]; } char_ampersand = { 26, {{ 9,9 }, { 8,10 }, { 8,10 }, { 1,3 }, { 1,3 }, { 1,1 }, { 1,1 }, { 2,0 }, { 2,0 }, { 5,0 }, { 5,0 }, { 6,1 }, { 6,1 }, { 6,3 }, { 6,3 }, { 0,7 }, { 0,7 }, { 0,9 }, { 0,9 }, { 1,10 }, { 1,10 }, { 6,10 }, { 6,10 }, { 8,8 }, { 8,8 }, { 8,7 }} }; /*** Character drawing struct ***/ struct st_char { int x; int y; int pos; int rotang; int rotangadd; double ang; } *charobj; /*** Start here ***/ int main(int argc, char **argv) { parse_command_line(argc,argv); do { wait_and_init(); do_text_animation(); } while(repeat); // Keeps compilers happy return 0; } /*** Parse command line args ***/ void parse_command_line(int argc, char **argv) { char *opt[] = { "t", "at", "af", "u", "d", "sc", "lw", "sr", "r", "fg", "bg", "to", "dm" }; enum { OPT_TEXT, OPT_AT, OPT_AFTER, OPT_DELAY, OPT_DISP, OPT_SCALE, OPT_LWIDTH, OPT_SCROLL, OPT_REPEAT, OPT_FG, OPT_BG, OPT_TIMEOUT, OPT_DAEMON, OPT_END }; char *usage = "Usage: %s\n" " -t \"\"\n" " [-at [YYYYMMDD:]HHMM[SS] | -af HHMM[SS]]\n" " [-r] (Repeat at/after same time continuously)\n" " [-d ] (X display)\n" " [-sc ] (size of characters)\n" " [-u ] (animation frame delay)\n" " [-lw ]\n" " [-bg ]\n" " [-to ]\n" " [-dm] (be daemon)\n"; int daemon = 0; int i,o; /* Parse command line */ trigtype = TRIG_NOTSET; trigtime = time(0); // Default to now for demo mode if no time arg given repeat = 0; timeadd = 0; text = NULL; disp = NULL; delay = 30000; scroll = 0; scale = 3; lwidth = 1; fgcol = "white"; bgcol = "black"; timeout = 120; for(i=1;i < argc;++i) { if (argv[i][0] != '-') { printf(usage,argv[0]); exit(1); } for(o=0;o != OPT_END;++o) if (!strcasecmp(opt[o],argv[i]+1)) break; switch(o) { case OPT_TEXT: if (i == argc-1) goto USAGE; text = argv[++i]; break; case OPT_AT: if (i == argc-1 || trigtype == TRIG_AFTER) goto USAGE; trigtype = TRIG_AT; set_trigger_time(argv[++i]); break; case OPT_AFTER: if (i == argc-1 || trigtype == TRIG_AT) goto USAGE; trigtype = TRIG_AFTER; set_trigger_time(argv[++i]); break; case OPT_REPEAT: repeat = 1; break; case OPT_DELAY: if (i == argc-1) goto USAGE; delay = atoi(argv[++i]); break; case OPT_DISP: if (i == argc-1) goto USAGE; disp = argv[++i]; break; case OPT_SCALE: if (i == argc-1) goto USAGE; scale = atoi(argv[++i]); break; case OPT_LWIDTH: if (i == argc-1) goto USAGE; lwidth = atoi(argv[++i]); break; case OPT_SCROLL: scroll = 1; break; case OPT_FG: if (i == argc-1) goto USAGE; fgcol = argv[++i]; break; case OPT_BG: if (i == argc-1) goto USAGE; bgcol = argv[++i]; break; case OPT_TIMEOUT: if (i == argc-1) goto USAGE; timeout = atoi(argv[++i]); break; case OPT_DAEMON: daemon = 1; break; USAGE: default: printf(usage,argv[0]); exit(1); } } if (!text) { printf(usage,argv[0]); exit(1); } if (trigtype == TRIG_NOTSET) trigtype = TRIG_AFTER; /* Fork and dissociate from tty if to be daemon. */ if (daemon) { switch(fork()) { case -1: perror("fork()"); exit(1); case 0: break; default: exit(0); } #ifdef TIOCNOTTY ioctl(fileno(stdin),TIOCNOTTY,NULL); ioctl(fileno(stdout),TIOCNOTTY,NULL); ioctl(fileno(stderr),TIOCNOTTY,NULL); #endif setsid(); } if (repeat) timeadd = (trigtype == TRIG_AFTER) ? hr * 3600 + min * 60 + sec : 86400; } /*** Parse at time. Format is [YYYYMMDD:]HHMM[SS] where the date part (including the colon) and the second are optional ***/ void set_trigger_time(char *tstr) { struct tm trigtms; time_t tt; char *s,c; int len,have_date; int yr,mon,day; /* Set up time struct to current date/time */ bzero(&trigtms,sizeof(trigtms)); time(&tt); memcpy(&trigtms,localtime(&tt),sizeof(trigtms)); trigtime = 0; yr = 0; mon = 0; day = 0; have_date = 0; /* Look for date */ if ((s = strchr(tstr,':'))) { if (s - tstr != 8) goto ERROR; c = tstr[4]; tstr[4] = '\0'; if ((yr = atoi(tstr)) < trigtms.tm_year + 1900) goto ERROR; tstr[4] = c; c = tstr[6]; tstr[6] = '\0'; if ((mon =atoi(tstr+4)) < 1 || mon > 12) goto ERROR; tstr[6] = c; tstr[8] = '\0'; if ((day = atoi(tstr+6)) < 1 || day > 31) goto ERROR; ++s; have_date = 1; } else s = tstr; /* Get time. If its TRIG_AT then set the time , else add to it */ if ((len = strlen(s)) < 4 || len == 5 || len > 6) goto ERROR; c = s[2]; s[2] = '\0'; if ((hr = atoi(s)) < 0 || hr > 23) goto ERROR; s[2] = c; c = s[4]; s[4] = '\0'; if ((min = atoi(s+2)) < 0 || min > 59) goto ERROR; s[4] = c; if (len == 4) sec = 0; else if ((sec = atoi(s+4)) < 0 || sec > 59) goto ERROR; if (trigtype == TRIG_AT) { if (have_date) { trigtms.tm_year = yr - 1900; trigtms.tm_mon = mon - 1; trigtms.tm_mday = day; } trigtms.tm_hour = hr; trigtms.tm_min = min; trigtms.tm_sec = sec; } else { trigtms.tm_year += yr; trigtms.tm_mon += mon; trigtms.tm_mday += day; trigtms.tm_hour += hr; trigtms.tm_min += min; trigtms.tm_sec += sec; } trigtime = mktime(&trigtms); return; ERROR: puts("Invalid date/time string."); exit(1); } /*** Wait and then init code ***/ void wait_and_init() { XSetWindowAttributes attrib; XGCValues gcvals; XEvent event; Colormap cmap; XColor fgc,bgc,acol; int screen,i; /* Wait until its time */ WAIT: while(time(0) < trigtime) sleep(1); /* Set up X */ if (!(display = XOpenDisplay(disp))) { printf("XOpenDisplay(): Can't connect to: %s\n",XDisplayName(disp)); /* If we're repeating don't just die, maybe it'll work next time */ if (repeat) { trigtime += timeadd; goto WAIT; } exit(1); } screen = DefaultScreen(display); cmap = DefaultColormap(display,screen); /* Get colours. If we can't just use black & white. */ if (!XAllocNamedColor(display,cmap,fgcol,&fgc,&acol)) fgc.pixel = WhitePixel(display,screen); if (!XAllocNamedColor(display,cmap,bgcol,&bgc,&acol)) bgc.pixel = BlackPixel(display,screen); /* Create non managed transparent window the same size as the screen */ dwidth = DisplayWidth(display,screen); dheight = DisplayHeight(display,screen); dwidth2 = dwidth / 2; dheight2 = dheight / 2; attrib.override_redirect = True; attrib.background_pixel = bgc.pixel; win = XCreateWindow( display, RootWindow(display,screen), 0,0,dwidth,dheight, 0, DefaultDepth(display,screen), InputOutput, CopyFromParent, CWOverrideRedirect | CWBackPixel, &attrib); /* Set up GCs */ gcvals.line_width = lwidth; gcvals.foreground = fgc.pixel; gcw = XCreateGC(display,win,GCLineWidth | GCForeground, &gcvals); gcvals.line_width = lwidth; gcvals.foreground = bgc.pixel; gcb = XCreateGC(display,win,GCLineWidth | GCForeground, &gcvals); /* Select input , map and wait for exposure */ XSelectInput(display,win,ExposureMask | ButtonPressMask | ButtonReleaseMask); XMapRaised(display,win); XNextEvent(display,&event); /* Setup character translation tables */ for(i=0;i < 256;++i) trans[i] = (struct char_template *)&char_qmark; /* Set up alphabet , numbers and various symbols */ trans['a'] = (struct char_template *)&char_a; trans['b'] = (struct char_template *)&char_b; trans['c'] = (struct char_template *)&char_c; trans['d'] = (struct char_template *)&char_d; trans['e'] = (struct char_template *)&char_e; trans['f'] = (struct char_template *)&char_f; trans['g'] = (struct char_template *)&char_g; trans['h'] = (struct char_template *)&char_h; trans['i'] = (struct char_template *)&char_i; trans['j'] = (struct char_template *)&char_j; trans['k'] = (struct char_template *)&char_k; trans['l'] = (struct char_template *)&char_l; trans['m'] = (struct char_template *)&char_m; trans['n'] = (struct char_template *)&char_n; trans['o'] = (struct char_template *)&char_o; trans['p'] = (struct char_template *)&char_p; trans['q'] = (struct char_template *)&char_q; trans['r'] = (struct char_template *)&char_r; trans['s'] = (struct char_template *)&char_s; trans['t'] = (struct char_template *)&char_t; trans['u'] = (struct char_template *)&char_u; trans['v'] = (struct char_template *)&char_v; trans['w'] = (struct char_template *)&char_w; trans['x'] = (struct char_template *)&char_x; trans['y'] = (struct char_template *)&char_y; trans['z'] = (struct char_template *)&char_z; trans['A'] = (struct char_template *)&char_a; trans['B'] = (struct char_template *)&char_b; trans['C'] = (struct char_template *)&char_c; trans['D'] = (struct char_template *)&char_d; trans['E'] = (struct char_template *)&char_e; trans['F'] = (struct char_template *)&char_f; trans['G'] = (struct char_template *)&char_g; trans['H'] = (struct char_template *)&char_h; trans['I'] = (struct char_template *)&char_i; trans['J'] = (struct char_template *)&char_j; trans['K'] = (struct char_template *)&char_k; trans['L'] = (struct char_template *)&char_l; trans['M'] = (struct char_template *)&char_m; trans['N'] = (struct char_template *)&char_n; trans['O'] = (struct char_template *)&char_o; trans['P'] = (struct char_template *)&char_p; trans['Q'] = (struct char_template *)&char_q; trans['R'] = (struct char_template *)&char_r; trans['S'] = (struct char_template *)&char_s; trans['T'] = (struct char_template *)&char_t; trans['U'] = (struct char_template *)&char_u; trans['V'] = (struct char_template *)&char_v; trans['W'] = (struct char_template *)&char_w; trans['X'] = (struct char_template *)&char_x; trans['Y'] = (struct char_template *)&char_y; trans['Z'] = (struct char_template *)&char_z; trans['0'] = (struct char_template *)&char_0; trans['1'] = (struct char_template *)&char_1; trans['2'] = (struct char_template *)&char_2; trans['3'] = (struct char_template *)&char_3; trans['4'] = (struct char_template *)&char_4; trans['5'] = (struct char_template *)&char_5; trans['6'] = (struct char_template *)&char_6; trans['7'] = (struct char_template *)&char_7; trans['8'] = (struct char_template *)&char_8; trans['9'] = (struct char_template *)&char_9; trans[' '] = (struct char_template *)&char_space; trans['!'] = (struct char_template *)&char_exmark; trans['+'] = (struct char_template *)&char_plus; trans['-'] = (struct char_template *)&char_minus; trans['*'] = (struct char_template *)&char_star; trans['='] = (struct char_template *)&char_equals; trans['.'] = (struct char_template *)&char_dot; trans[','] = (struct char_template *)&char_comma; trans['('] = (struct char_template *)&char_lrbracket; trans[')'] = (struct char_template *)&char_rrbracket; trans['{'] = (struct char_template *)&char_lcbracket; trans['}'] = (struct char_template *)&char_rcbracket; trans['['] = (struct char_template *)&char_lsbracket; trans[']'] = (struct char_template *)&char_rsbracket; trans['$'] = (struct char_template *)&char_dollar; trans['#'] = (struct char_template *)&char_hash; trans['/'] = (struct char_template *)&char_fslash; trans['\\'] = (struct char_template *)&char_bslash; trans['>'] = (struct char_template *)&char_greater; trans['<'] = (struct char_template *)&char_less; trans['_'] = (struct char_template *)&char_underscore; trans['|'] = (struct char_template *)&char_bar; trans['\''] = (struct char_template *)&char_squote; trans['"'] = (struct char_template *)&char_dquote; trans['`'] = (struct char_template *)&char_bquote; trans[':'] = (struct char_template *)&char_colon; trans[';'] = (struct char_template *)&char_semicolon; trans['@'] = (struct char_template *)&char_at; trans['^'] = (struct char_template *)&char_hat; trans['~'] = (struct char_template *)&char_tilda; trans['&'] = (struct char_template *)&char_ampersand; starting = 1; movement = MOVE_LEFT; movestart = 1; sep = SEP * scale; charsize = 11 * scale; dwidth3 = dwidth - charsize * 2; } /*** It all happens here ***/ void do_text_animation() { XEvent event; int len,i; int phx,phy; int scrpos,scrticker; /* Init local vars */ scrticker = 0; scrpos = 0; /* Set up character structures */ len = strlen(text); charobj = (struct st_char *)malloc(sizeof(struct st_char) * len); for(i=0;i < len;++i) { charobj[i].x = -100; /* Make sure start positions are out of sight */ charobj[i].y = 0; charobj[i].ang = 0; charobj[i].rotang = 0; charobj[i].pos = i; } hx = dwidth; hy = dheight2; /* Main loop */ for(phx=0,phy=0;;phx=hx,phy=hy) { /* See if we've passed timeout */ if (time(0) - trigtime >= timeout) break; /* If user has pressed mouse button 3 then collect release event (so it doesn't get passed to any windows underneath when our window is destroyed) and then exit loop */ if (XCheckTypedEvent(display,ButtonPress,&event) && event.xbutton.button == 3) { XNextEvent(display,&event); break; } /* Draw */ for(i=len-1;i >= 0;--i) draw(gcw,i,text[(i+scrpos) % len]); XFlush(display); usleep(delay); /* Undraw */ for(i=len-1;i >= 0;--i) draw(gcb,i,text[(i+scrpos) % len]); /* Calculate new positions and rotations */ move(); if (scroll && ++scrticker == 3) { scrticker = 0; scrpos--; if (scrpos < 0) scrpos = len-1; } for(i=len-1;i > 0;--i) charcalc(i); charobj[0].x = hx + 10; charobj[0].y = hy - 6 * scale; } if (!repeat) exit(0); /* Free up stuff for next iteration */ free(charobj); XDestroyWindow(display,win); XCloseDisplay(display); trigtime += timeadd; } /*** Move the head of the string ***/ void move() { double ang; static int w,h,cnt,addstart; static float wmult,hmult; static int cw_next = 1; switch(movement) { case MOVE_LEFT: if (movestart) { hx = dwidth - charsize * (!starting * 2); hy = dheight2; starting = 0; movestart = 0; } else hx -= sep; if (hx <= 0) { movement = MOVE_ROTATE; movestart = 1; } break; case MOVE_RIGHT: if (movestart) { /* hx set by caller */ hy = dheight2; movestart = 0; } else hx += sep; if (hx >= dwidth3) { hx = dwidth3; movement = MOVE_ANTICLOCKWISE; movestart = 1; } break; case MOVE_SPIRAL: case MOVE_CLOCKWISE: case MOVE_ANTICLOCKWISE: if (movestart) { moveang = (movement == MOVE_ANTICLOCKWISE ? 90 : 270); movestart = 0; addstart = 0; w = wmult = dwidth2 - charsize; h = dheight2; hmult = dheight2 - charsize; } ang = moveang / DEGS_PER_RADIAN; hx = w + sin(ang) * wmult; hy = h + cos(ang) * hmult; switch(movement) { case MOVE_CLOCKWISE: if (abs(270 - moveang) <= scale && addstart) { movement = MOVE_RIGHT; movestart = 1; hx = 0; break; } moveang -= 2 * scale; if (moveang < 0) moveang += 360; addstart = 1; break; case MOVE_ANTICLOCKWISE: if (abs(90 - moveang) <= scale && addstart) { movement = MOVE_LEFT; movestart = 1; break; } moveang = (moveang + 2 * scale) % 360; addstart = 1; break; case MOVE_SPIRAL: if (hmult <= 0 || wmult <= 0) { movement = MOVE_RIGHT; movestart = 1; break; } moveang = (moveang + 2 * scale) % 360; wmult -= ((float)dwidth / (float)dheight) * SPIRAL_MULT; hmult -= SPIRAL_MULT; } break; case MOVE_WAVE: if (movestart) { hx = LEFT_SCR_X; movestart = 0; moveang = 0; cnt = 0; } ang = moveang / DEGS_PER_RADIAN; hy = dheight2 + sin(ang) * (dheight2/4); moveang = (moveang + 20) % 360; if (++cnt == (cw_next ? 81 : 72)) { movement = (cw_next ? MOVE_CLOCKWISE : MOVE_SPIRAL); cw_next = !cw_next; movestart = 1; } break; case MOVE_ROTATE: if (movestart) { hx = LEFT_SCR_X; cnt = 0; movestart = 0; } if (++cnt == 36) { movement = MOVE_WAVE; movestart = 1; } } } /*** Calculate new centre positions ***/ void charcalc(int pos) { switch(movement) { case MOVE_WAVE: charobj[pos].x = charobj[pos-1].x + sep; break; case MOVE_LEFT: case MOVE_SPIRAL: case MOVE_CLOCKWISE: case MOVE_ANTICLOCKWISE: case MOVE_RIGHT: charobj[pos].x = charobj[pos-1].x; break; case MOVE_ROTATE: charobj[pos].x = charobj[pos-1].x + sep; charobj[pos].rotang = (charobj[pos].rotang + 10) % 360; } charobj[pos].y = charobj[pos-1].y; } /*** Draw the character at position pos including its trails ***/ void draw(GC gc, int pos, char ascii) { struct char_template *td; double xb,x1,y1,x2,y2; double xd,yd,cpnt,ang; int i; /* Calculate new rotation angle if not position 0 */ if (pos) { xd = charobj[pos].x - charobj[pos-1].x; yd = charobj[pos].y - charobj[pos-1].y; if (!yd) ang = (xd > 0 ? 0 : 180); else if (!xd) ang = (yd > 0 ? 90 : 270); else { ang = atan(yd/xd) * DEGS_PER_RADIAN; if (xd < 0) ang += 180; else if (yd < 0) ang += 360; } ang += charobj[pos].rotang; ang /= DEGS_PER_RADIAN; } else ang = charobj[1].ang; /* Cheat, but looks ok. */ td = trans[ascii]; cpnt = charsize / 2; /* Centrepoint of character */ /* Draw character */ for(i=0;i < td->cnt;i+=2) { x1 = td->data[i].x * scale; y1 = td->data[i].y * scale; x2 = td->data[i+1].x * scale; y2 = td->data[i+1].y * scale; xb = x1; x1 = ((x1 - cpnt) * cos(ang) - (y1 - cpnt) * sin(ang)) + cpnt; y1 = ((y1 - cpnt) * cos(ang) + (xb - cpnt) * sin(ang)) + cpnt; xb = x2; x2 = ((x2 - cpnt) * cos(ang) - (y2 - cpnt) * sin(ang)) + cpnt; y2 = ((y2 - cpnt) * cos(ang) + (xb - cpnt) * sin(ang)) + cpnt; XDrawLine( display,win,gc, (int)(charobj[pos].x + x1), (int)(charobj[pos].y + y1), (int)(charobj[pos].x + x2), (int)(charobj[pos].y + y2)); } charobj[pos].ang = ang; }