/***************************************************************************** TEXTAIL: Makes a piece of text follow the mouse cursor wherever it goes. Idea borrowed from some javascript seen somewhere except original one didn't support scrolling text. Written by Neil, last update Nov 2003 *****************************************************************************/ #include #include #define SCROLL_CNT 3 main(int argc, char **argv) { Display *display; Window rootwin,rw,cw; GC gc; XGCValues gcvals; XFontStruct *font; char *disp; char **fonts; int font_cnt,screen,delay; int len,mx,my,i,wx,wy; int scroll,scrpos,scrflag,prvscrpos,nl,ol; u_int pmask; int *xpos,*ypos; char *text; char *usage = "Usage: %s -t \"\" [-u ] [-d ] -s\n"; /* Parse command line */ text = NULL; disp = NULL; delay = 20000; scroll = 0; scrflag = 0; for(i=1;i < argc;++i) { if (argv[i][0] != '-') { printf(usage,argv[0]); exit(1); } switch(argv[i][1]) { case 's': case 'S': scroll = 1; break; case 't': case 'T': if (i == argc-1) goto USAGE; text = argv[++i]; break; case 'd': case 'D': if (i == argc-1) goto USAGE; disp = argv[++i]; break; case 'u': case 'U': if (i == argc-1) goto USAGE; delay = atoi(argv[++i]); break; USAGE: default : printf(usage,argv[0]); exit(1); } } if (!text) { printf(usage,argv[0]); exit(1); } /* Set up X */ if (!(display=XOpenDisplay(disp))) { fprintf(stderr,"XOpenDisplay(): Can't connect to: %s\n", XDisplayName(disp)); exit(1); } screen=DefaultScreen(display); rootwin=RootWindow(display,screen); fonts=XListFonts(display,"*9x15*",100,&font_cnt); font=XLoadQueryFont(display,fonts[0]); XFreeFontNames(fonts); /* Create GC. IncludeInferiors means that when we draw to root window it will draw over the top of any child windows in it. */ gcvals.font=font->fid; gcvals.function = GXinvert; gcvals.subwindow_mode = IncludeInferiors; gc=XCreateGC(display,rootwin,GCFont | GCFunction | GCSubwindowMode, &gcvals); XSelectInput(display,rootwin,ExposureMask); mx = 10; my = 10; len = strlen(text); scrpos = prvscrpos = len - 1; xpos = (int *)malloc(len * sizeof(int *)); ypos = (int *)malloc(len * sizeof(int *)); /* Mainloop */ while(1) { XQueryPointer(display,rootwin,&rw,&cw,&mx,&my,&wx,&wy,&pmask); /* Set new positions and draw characters. We go from the end of the string to the start so position changes ripple down */ for(i=len-1,nl=scrpos,ol=prvscrpos;i >= 0;--i,--nl,--ol) { if (nl < 0) nl = len-1; if (ol < 0) ol = len-1; /* Undraw old position */ XDrawString(display,rootwin,gc,xpos[i],ypos[i],&text[ol],1); /* Draw new one */ if (i) { xpos[i] = xpos[i-1] + font->max_bounds.width; ypos[i] = ypos[i-1]; } else { /* 1st character (char 0) has to move with mouse pointer */ xpos[0] = mx + font->max_bounds.width; ypos[0] = my; } XDrawString(display,rootwin,gc,xpos[i],ypos[i],&text[nl],1); } XFlush(display); usleep(delay); prvscrpos = scrpos; if (scroll && ++scrflag == SCROLL_CNT) { scrflag = 0; scrpos--; if (scrpos < 0) scrpos = len-1; } } }