array_t *array_init(int size) { array_t *array = xcmalloc(sizeof(array_t)); array->a_data = xmalloc(sizeof(void *) * size); array->a_count = size; return array; }
/* a strdup() implementation since ANSI C doesn't include strdup() */ void * xcstrdup(const char *string) { void *mem; /* allocate a buffer big enough to hold the characters and the * null terminator, then copy the string into the buffer */ mem = xcmalloc(strlen(string) + sizeof(char)); strcpy(mem, string); return (mem); }
/* Use XrmParseCommand to parse command line options to option variable */ static void doOptMain (int argc, char *argv[]) { /* Initialise resource manager and parse options into database */ XrmInitialize(); XrmParseCommand( &opt_db, opt_tab, sizeof(opt_tab) / sizeof(opt_tab[0]), XC_NAME, &argc, argv ); /* set output level */ if ( XrmGetResource( opt_db, "xclip.olevel", "Xclip.Olevel", &rec_typ, &rec_val ) ) { /* set verbose flag according to option */ if (strcmp(rec_val.addr, "S") == 0) fverb = OSILENT; if (strcmp(rec_val.addr, "Q") == 0) fverb = OQUIET; if (strcmp(rec_val.addr, "V") == 0) fverb = OVERBOSE; } /* set direction flag (in or out) */ if ( XrmGetResource( opt_db, "xclip.direction", "Xclip.Direction", &rec_typ, &rec_val ) ) { if (strcmp(rec_val.addr, "I") == 0) fdiri = T; if (strcmp(rec_val.addr, "O") == 0) fdiri = F; } /* set filter mode */ if ( XrmGetResource( opt_db, "xclip.filter", "Xclip.Filter", &rec_typ, &rec_val ) ) { /* filter mode only allowed in silent mode */ if (fverb == OSILENT) ffilt = T; } /* check for -help and -version */ if ( XrmGetResource( opt_db, "xclip.print", "Xclip.Print", &rec_typ, &rec_val ) ) { if (strcmp(rec_val.addr, "H") == 0) prhelp(argv[0]); if (strcmp(rec_val.addr, "V") == 0) prversion(); } /* check for -display */ if ( XrmGetResource( opt_db, "xclip.display", "Xclip.Display", &rec_typ, &rec_val ) ) { sdisp = rec_val.addr; if (fverb == OVERBOSE) /* print in verbose mode only */ fprintf(stderr, "Display: %s\n", sdisp); } /* check for -loops */ if ( XrmGetResource( opt_db, "xclip.loops", "Xclip.Loops", &rec_typ, &rec_val ) ) { sloop = atoi(rec_val.addr); if (fverb == OVERBOSE) /* print in verbose mode only */ fprintf(stderr, "Loops: %i\n", sloop); } /* Read remaining options (filenames) */ while ( (fil_number + 1) < argc ) { if (fil_number > 0) { fil_names = xcrealloc( fil_names, (fil_number + 1) * sizeof(char*) ); } else { fil_names = xcmalloc(sizeof(char*)); } fil_names[fil_number] = argv[fil_number + 1]; fil_number++; } }
int main (int argc, char *argv[]) { /* Declare variables */ unsigned char *sel_buf; /* buffer for selection data */ unsigned long sel_len = 0; /* length of sel_buf */ unsigned long sel_all = 0; /* allocated size of sel_buf */ Window win; /* Window */ XEvent evt; /* X Event Structures */ int dloop = 0; /* done loops counter */ pid_t pid; /* child pid if forking */ /* set up option table. I can't figure out a better way than this to * do it while sticking to pure ANSI C. The option and specifier * members have a type of volatile char *, so they need to be allocated * by strdup or malloc, you can't set them to a string constant at * declare time, this is note pure ANSI C apparently, although it does * work with gcc */ /* loop option entry */ opt_tab[0].option = xcstrdup("-loops"); opt_tab[0].specifier = xcstrdup(".loops"); opt_tab[0].argKind = XrmoptionSepArg; opt_tab[0].value = (XPointer) NULL; /* display option entry */ opt_tab[1].option = xcstrdup("-display"); opt_tab[1].specifier = xcstrdup(".display"); opt_tab[1].argKind = XrmoptionSepArg; opt_tab[1].value = (XPointer) NULL; /* selection option entry */ opt_tab[2].option = xcstrdup("-selection"); opt_tab[2].specifier = xcstrdup(".selection"); opt_tab[2].argKind = XrmoptionSepArg; opt_tab[2].value = (XPointer) NULL; /* filter option entry */ opt_tab[3].option = xcstrdup("-filter"); opt_tab[3].specifier = xcstrdup(".filter"); opt_tab[3].argKind = XrmoptionNoArg; opt_tab[3].value = (XPointer) xcstrdup(ST); /* in option entry */ opt_tab[4].option = xcstrdup("-in"); opt_tab[4].specifier = xcstrdup(".direction"); opt_tab[4].argKind = XrmoptionNoArg; opt_tab[4].value = (XPointer) xcstrdup("I"); /* out option entry */ opt_tab[5].option = xcstrdup("-out"); opt_tab[5].specifier = xcstrdup(".direction"); opt_tab[5].argKind = XrmoptionNoArg; opt_tab[5].value = (XPointer) xcstrdup("O"); /* version option entry */ opt_tab[6].option = xcstrdup("-version"); opt_tab[6].specifier = xcstrdup(".print"); opt_tab[6].argKind = XrmoptionNoArg; opt_tab[6].value = (XPointer) xcstrdup("V"); /* help option entry */ opt_tab[7].option = xcstrdup("-help"); opt_tab[7].specifier = xcstrdup(".print"); opt_tab[7].argKind = XrmoptionNoArg; opt_tab[7].value = (XPointer) xcstrdup("H"); /* silent option entry */ opt_tab[8].option = xcstrdup("-silent"); opt_tab[8].specifier = xcstrdup(".olevel"); opt_tab[8].argKind = XrmoptionNoArg; opt_tab[8].value = (XPointer) xcstrdup("S"); /* quiet option entry */ opt_tab[9].option = xcstrdup("-quiet"); opt_tab[9].specifier = xcstrdup(".olevel"); opt_tab[9].argKind = XrmoptionNoArg; opt_tab[9].value = (XPointer) xcstrdup("Q"); /* verbose option entry */ opt_tab[10].option = xcstrdup("-verbose"); opt_tab[10].specifier = xcstrdup(".olevel"); opt_tab[10].argKind = XrmoptionNoArg; opt_tab[10].value = (XPointer) xcstrdup("V"); /* parse command line options */ doOptMain(argc, argv); /* Connect to the X server. */ if ( (dpy = XOpenDisplay(sdisp)) ) { /* successful */ if (fverb == OVERBOSE) fprintf(stderr, "Connected to X server.\n"); } else { /* couldn't connect to X server. Print error and exit */ errxdisplay(sdisp); } /* parse selection command line option */ doOptSel(); /* Create a window to trap events */ win = XCreateSimpleWindow( dpy, DefaultRootWindow(dpy), 0, 0, 1, 1, 0, 0, 0 ); /* get events about property changes */ XSelectInput(dpy, win, PropertyChangeMask); if (fdiri) { /* in mode */ sel_all = 16; /* Reasonable ballpark figure */ sel_buf = xcmalloc(sel_all * sizeof(char)); /* Put chars into inc from stdin or files until we hit EOF */ do { if (fil_number == 0) { /* read from stdin if no files specified */ fil_handle = stdin; } else { if ( (fil_handle = fopen( fil_names[fil_current], "r" )) == NULL ) { errperror( 3, argv[0], ": ", fil_names[fil_current] ); exit(EXIT_FAILURE); } else { /* file opened successfully. Print * message (verbose mode only). */ if (fverb == OVERBOSE) fprintf( stderr, "Reading %s...\n", fil_names[fil_current] ); } } fil_current++; while (!feof(fil_handle)) { /* If sel_buf is full (used elems = * allocated elems) */ if (sel_len == sel_all) { /* double the number of * allocated elements */ sel_all *= 2; sel_buf = (unsigned char *)xcrealloc( sel_buf, sel_all * sizeof(char) ); } sel_len += fread( sel_buf + sel_len, sizeof(char), sel_all - sel_len, fil_handle ); } } while (fil_current < fil_number); /* if there are no files being read from (i.e., input * is from stdin not files, and we are in filter mode, * spit all the input back out to stdout */ if ((fil_number == 0) && ffilt) fwrite(sel_buf, sizeof(char), sel_len, stdout); /* take control of the selection so that we receive * SelectionRequest events from other windows */ XSetSelectionOwner(dpy, sseln, win, CurrentTime); /* fork into the background, exit parent process if we * are in silent mode */ if (fverb == OSILENT) { pid = fork(); /* exit the parent process; */ if (pid) exit(EXIT_SUCCESS); } /* print a message saying what we're waiting for */ if (fverb > OSILENT) { if (sloop == 1) fprintf( stderr, "Waiting for one selection request.\n" ); if (sloop < 1) fprintf( stderr, "Waiting for selection requests, Control-C to quit\n" ); if (sloop > 1) fprintf( stderr, "Waiting for %i selection requests, Control-C to quit\n", sloop ); } /* loop and wait for the expected number of * SelectionRequest events */ while (dloop < sloop || sloop < 1) { /* print messages about what we're waiting for * if not in silent mode */ if (fverb > OSILENT) { if (sloop > 1) fprintf( stderr, " Waiting for selection request %i of %i.\n", dloop + 1, sloop ); if (sloop == 1) fprintf( stderr, " Waiting for a selection request.\n" ); if (sloop < 1) fprintf( stderr, " Waiting for selection request number %i\n", dloop + 1 ); } /* wait for a SelectionRequest event */ while (1) { XNextEvent(dpy, &evt); /* request for selection, process * with xcin() */ if (evt.type == SelectionRequest) break; /* lost ownership of selection, exit */ if (evt.type == SelectionClear) exit(EXIT_SUCCESS); } /* recieved request, send response with xcin(). * xcin() will return a true value if it * received a SelectionClear, in which case * xclip should exit */ if (xcin(dpy, evt, sel_buf, sel_len)) exit(EXIT_SUCCESS); dloop++; /* increment loop counter */ } } else { /* out mode - get selection, print it, free the memory */ xcout(dpy, win, sseln, &sel_buf, &sel_len); if (sel_len) { /* only print the buffer out, and free it, if it's not * empty */ fwrite(sel_buf, sizeof(char), sel_len, stdout); free(sel_buf); } } /* Disconnect from the X server */ XCloseDisplay(dpy); /* exit */ return(EXIT_SUCCESS); }
/* Retrieves the contents of a selections. Arguments are: * * A display that has been opened. * * A window * * An event to process * * The selection to return * * The target(UTF8_STRING or XA_STRING) to return * * A pointer to a char array to put the selection into. * * A pointer to a long to record the length of the char array * * A pointer to an int to record the context in which to process the event * * Return value is 1 if the retrieval of the selection data is complete, * otherwise it's 0. */ int xcout(Display * dpy, Window win, XEvent evt, Atom sel, Atom target, unsigned char **txt, unsigned long *len, unsigned int *context) { /* a property for other windows to put their selection into */ static Atom pty; static Atom inc; Atom pty_type; Atom atomUTF8String; int pty_format; /* buffer for XGetWindowProperty to dump data into */ unsigned char *buffer; unsigned long pty_size, pty_items; /* local buffer of text to return */ unsigned char *ltxt = *txt; if (!pty) { pty = XInternAtom(dpy, "XCLIP_OUT", False); } if (!inc) { inc = XInternAtom(dpy, "INCR", False); } switch (*context) { /* there is no context, do an XConvertSelection() */ case XCLIB_XCOUT_NONE: /* initialise return length to 0 */ if (*len > 0) { free(*txt); *len = 0; } /* send a selection request */ XConvertSelection(dpy, sel, target, pty, win, CurrentTime); *context = XCLIB_XCOUT_SENTCONVSEL; return (0); case XCLIB_XCOUT_SENTCONVSEL: atomUTF8String = XInternAtom(dpy, "UTF8_STRING", False); if (evt.type != SelectionNotify) return (0); /* fallback to XA_STRING when UTF8_STRING failed */ if (target == atomUTF8String && evt.xselection.property == None) { *context = XCLIB_XCOUT_FALLBACK; return (0); } /* find the size and format of the data in property */ XGetWindowProperty(dpy, win, pty, 0, 0, False, AnyPropertyType, &pty_type, &pty_format, &pty_items, &pty_size, &buffer); XFree(buffer); if (pty_type == inc) { /* start INCR mechanism by deleting property */ XDeleteProperty(dpy, win, pty); XFlush(dpy); *context = XCLIB_XCOUT_INCR; return (0); } /* if it's not incr, and not format == 8, then there's * nothing in the selection (that xclip understands, * anyway) */ if (pty_format != 8) { *context = XCLIB_XCOUT_NONE; return (0); } /* not using INCR mechanism, just read the property */ XGetWindowProperty(dpy, win, pty, 0, (long) pty_size, False, AnyPropertyType, &pty_type, &pty_format, &pty_items, &pty_size, &buffer); /* finished with property, delete it */ XDeleteProperty(dpy, win, pty); /* copy the buffer to the pointer for returned data */ ltxt = (unsigned char *) xcmalloc(pty_items); memcpy(ltxt, buffer, pty_items); /* set the length of the returned data */ *len = pty_items; *txt = ltxt; /* free the buffer */ XFree(buffer); *context = XCLIB_XCOUT_NONE; /* complete contents of selection fetched, return 1 */ return (1); case XCLIB_XCOUT_INCR: /* To use the INCR method, we basically delete the * property with the selection in it, wait for an * event indicating that the property has been created, * then read it, delete it, etc. */ /* make sure that the event is relevant */ if (evt.type != PropertyNotify) return (0); /* skip unless the property has a new value */ if (evt.xproperty.state != PropertyNewValue) return (0); /* check size and format of the property */ XGetWindowProperty(dpy, win, pty, 0, 0, False, AnyPropertyType, &pty_type, &pty_format, &pty_items, &pty_size, (unsigned char **) &buffer); if (pty_format != 8) { /* property does not contain text, delete it * to tell the other X client that we have read * it and to send the next property */ XFree(buffer); XDeleteProperty(dpy, win, pty); return (0); } if (pty_size == 0) { /* no more data, exit from loop */ XFree(buffer); XDeleteProperty(dpy, win, pty); *context = XCLIB_XCOUT_NONE; /* this means that an INCR transfer is now * complete, return 1 */ return (1); } XFree(buffer); /* if we have come this far, the propery contains * text, we know the size. */ XGetWindowProperty(dpy, win, pty, 0, (long) pty_size, False, AnyPropertyType, &pty_type, &pty_format, &pty_items, &pty_size, (unsigned char **) &buffer); /* allocate memory to accommodate data in *txt */ if (*len == 0) { *len = pty_items; ltxt = (unsigned char *) xcmalloc(*len); } else { *len += pty_items; ltxt = (unsigned char *) xcrealloc(ltxt, *len); } /* add data to ltxt */ memcpy(<xt[*len - pty_items], buffer, pty_items); *txt = ltxt; XFree(buffer); /* delete property to get the next item */ XDeleteProperty(dpy, win, pty); XFlush(dpy); return (0); } return (0); }
int main (int argc, char *argv[]) { /* Declare variables */ char *seltxt; /* selection text string */ unsigned long stelems = 0; /* number of used elements in seltxt */ unsigned long stalloc = 0; /* size of seltxt */ Window win; /* Window */ XEvent evt; /* X Event Structures */ int dloop = 0; /* done loops counter */ pid_t pid; /* child pid if forking */ /* parse command line options */ doOptMain(argc, argv); /* Connect to the X server. */ if ( (dpy = XOpenDisplay(sdisp)) ) { /* successful */ if (fverb == OVERBOSE) fprintf(stderr, "Connected to X server.\n"); } else { /* couldn't connect to X server. Print error and exit */ errxdisplay(sdisp); } /* parse selection command line option */ doOptSel(argc, argv); /* Create a window to trap events */ win = XCreateSimpleWindow( dpy, DefaultRootWindow(dpy), 0, 0, 1, 1, 0, 0, 0 ); /* get events about property changes */ XSelectInput(dpy, win, PropertyChangeMask); if (fdiri) { /* in mode */ stalloc = 16; /* Reasonable ballpark figure */ seltxt = xcmalloc(stalloc); /* Put chars into inc from stdin or files until we hit EOF */ do { if (fil_number == 0) { /* read from stdin if no files specified */ fil_handle = stdin; } else { /* open the current file for reading */ if ( (fil_handle = fopen( fil_names[fil_current], "r" )) == NULL ) { errperror( argv[0], ": ", fil_names[fil_current] ); exit(EXIT_FAILURE); } else { /* file opened successfully. Print * message (verbose mode only). */ if (fverb == OVERBOSE) fprintf( stderr, "Reading %s...\n", fil_names[fil_current] ); } } fil_current++; while (!feof(fil_handle)) { int n = 0; /* If in is full (used elems = * allocated elems) */ if (stelems == stalloc) { /* double the number of * allocated elements */ stalloc *= 2 + 1; seltxt = (char *)xcrealloc( seltxt, stalloc * sizeof(char) ); } n = fread( seltxt + stelems, 1, stalloc - stelems, fil_handle ); stelems += n; seltxt[stelems] = '\0'; } } while (fil_current < fil_number); /* if there are no files being read from (i.e., input * is from stdin not files, and we are in filter mode, * spit all the input back out to stdout */ if ((fil_number == 0) && ffilt) printf(seltxt); /* take control of the selection so that we receive * SelectionRequest events from other windows */ XSetSelectionOwner(dpy, sseln, win, CurrentTime); /* fork into the background, exit parent process if we * are in silent mode */ if (fverb == OSILENT) { pid = fork(); /* exit the parent process; */ if (pid) exit(EXIT_SUCCESS); } /* print a message saying what we're waiting for */ if (fverb > OSILENT) { if (sloop == 1) fprintf( stderr, "Waiting for one selection request.\n" ); if (sloop < 1) fprintf( stderr, "Waiting for selection requests, Control-C to quit\n" ); if (sloop > 1) fprintf( stderr, "Waiting for %i selection requests, Control-C to quit\n", sloop ); } /* loop and wait for the expected number of * SelectionRequest events */ while (dloop < sloop || sloop < 1) { /* print messages about what we're waiting for * if not in silent mode */ if (fverb > OSILENT) { if (sloop > 1) fprintf( stderr, " Waiting for selection request %i of %i.\n", dloop + 1, sloop ); if (sloop == 1) fprintf( stderr, " Waiting for a selection request.\n" ); if (sloop < 1) fprintf( stderr, " Waiting for selection request number %i\n", dloop + 1 ); } /* wait for a SelectionRequest event */ while (1) { XNextEvent(dpy, &evt); /* request for selection, process * with xcin() */ if (evt.type == SelectionRequest) break; /* lost ownership of selection, exit */ if (evt.type == SelectionClear) exit(EXIT_SUCCESS); } /* recieved request, send response with xcin(). * xcin() will return a true value if it * received a SelectionClear, in which case * xclip should exit */ if (xcin(dpy, win, evt, seltxt)) exit(EXIT_SUCCESS); dloop++; /* increment loop counter */ } } else { /* out mode - get selection, print it, free the memory */ seltxt = xcout(dpy, win, sseln); printf(seltxt); free(seltxt); } /* Disconnect from the X server */ XCloseDisplay(dpy); /* exit */ return(EXIT_SUCCESS); }
/* return selection data */ char *xcout (Display *dpy, Window win, Atom sel) { Atom pty, inc, pty_type; int pty_format; XEvent evt; char *txt; char *rtn_str; unsigned int rtn_siz = 0; unsigned char *data; unsigned long pty_items, pty_size; /* Two new window properties for transferring the selection */ pty = XInternAtom(dpy, "XCLIP_OUT", False); inc = XInternAtom(dpy, "INCR", False); /* send a selection request */ XConvertSelection( dpy, sel, XA_STRING, pty, win, CurrentTime ); /* wait for a SelectionNotify in response to our request */ while (1) { XNextEvent(dpy, &evt); if (evt.type == SelectionNotify || evt.type == None ) break; } /* quit if there is nothing in the selection */ if (evt.type == None) return(rtn_str); /* find out the size and format of the data in property */ XGetWindowProperty( dpy, win, pty, 0, 0, False, AnyPropertyType, &pty_type, &pty_format, &pty_items, &pty_size, &data ); if (pty_format == 8) { /* not using INCR mechanism, just read and print the property */ XGetWindowProperty( dpy, win, pty, 0, pty_size, False, AnyPropertyType, &pty_type, &pty_format, &pty_items, &pty_size, (unsigned char **)&txt ); /* finished with property, delete it */ XDeleteProperty(dpy, win, pty); /* make a copy of the selection string, then free it */ rtn_str = strdup(txt); XFree(txt); } else if (pty_type == inc) { /* Using INCR mechanism, start by deleting the property */ XDeleteProperty(dpy, win, pty); while (1) { /* To use the INCR method, we basically delete the * property with the selection in it, wait for an * event indicating that the property has been created, * then read it, delete it, etc. */ /* flush to force any pending XDeleteProperty calls * from the previous running of the loop, get the next * event in the event queue */ XFlush(dpy); XNextEvent(dpy, &evt); /* skip unless is a property event */ if (evt.type != PropertyNotify) continue; /* skip unless the property has a new value */ if (evt.xproperty.state != PropertyNewValue) continue; /* check size and format of the property */ XGetWindowProperty( dpy, win, pty, 0, 0, False, AnyPropertyType, &pty_type, &pty_format, &pty_items, &pty_size, (unsigned char **)&txt ); if (pty_format != 8){ /* property does not contain text, delete it * to tell the other X client that we have read * it and to send the next property */ XDeleteProperty(dpy, win, pty); continue; } if (pty_size == 0){ /* no more data, exit from loop */ XDeleteProperty(dpy, win, pty); break; } /* if we have come this far, the propery contains * text, we know the size. */ XGetWindowProperty( dpy, win, pty, 0, pty_size, False, AnyPropertyType, &pty_type, &pty_format, &pty_items, &pty_size, (unsigned char **)&txt ); /* allocate memory to ammodate date in rtn_str */ if (rtn_siz == 0) { rtn_siz = pty_items; rtn_str = (char *)xcmalloc(rtn_siz); } else { rtn_siz += pty_items; rtn_str = (char *)xcrealloc(rtn_str, rtn_siz); } /* add data to return_str */ strncat(rtn_str, txt, pty_items); /* delete property to get the next item */ XDeleteProperty(dpy, win, pty); } } return(rtn_str); }
/* send selection data in response to a request returns 0 */ int xcin (Display *dpy, Window win, XEvent rev, char *txt) { unsigned int incr = F; /* incr mode flag */ XEvent res; /* response to event */ Atom inc; unsigned int selc = F; /* SelClear event */ if (rev.type == SelectionClear) return(1); /* send only continue if this is a SelectionRequest event */ if (rev.type != SelectionRequest) return(0); /* test whether to use INCR or not */ if ( strlen(txt) > XC_CHUNK ) { incr = T; inc = XInternAtom(dpy, "INCR", False); } /* put the data into an property */ if (incr) { /* send INCR response */ XChangeProperty( dpy, rev.xselectionrequest.requestor, rev.xselectionrequest.property, inc, 32, PropModeReplace, 0, 0 ); /* With the INCR mechanism, we need to know when the * requestor window changes (deletes) its properties */ XSelectInput( dpy, rev.xselectionrequest.requestor, PropertyChangeMask ); } else { /* send data all at once (not using INCR) */ XChangeProperty( dpy, rev.xselectionrequest.requestor, rev.xselectionrequest.property, XA_STRING, 8, PropModeReplace, (unsigned char*) txt, strlen(txt) ); } /* set values for the response event */ res.xselection.property = rev.xselectionrequest.property; res.xselection.type = SelectionNotify; res.xselection.display = rev.xselectionrequest.display; res.xselection.requestor = rev.xselectionrequest.requestor; res.xselection.selection = rev.xselectionrequest.selection; res.xselection.target = rev.xselectionrequest.target; res.xselection.time = rev.xselectionrequest.time; /* send the response event */ XSendEvent(dpy, rev.xselectionrequest.requestor, 0, 0, &res); XFlush(dpy); if (incr) { unsigned int sel_pos = 0; /* position in sel_str */ unsigned int sel_end = 0; char *chk_str; chk_str = (char *)xcmalloc(XC_CHUNK); while (1) { unsigned int chk_pos = 0; while (1) { XEvent spe; XNextEvent(dpy, &spe); if (spe.type == SelectionClear) { selc = T; continue; } if (spe.type != PropertyNotify) continue; if (spe.xproperty.state == PropertyDelete) break; } if (!sel_end) { for (chk_pos=0; chk_pos<=XC_CHUNK; chk_pos++) { if (txt[sel_pos] == (char)NULL) { sel_end = 1; break; } chk_str[chk_pos] = txt[sel_pos]; sel_pos++; } } if (chk_pos) { XChangeProperty( dpy, rev.xselectionrequest.requestor, rev.xselectionrequest.property, XA_STRING, 8, PropModeReplace, chk_str, chk_pos ); } else { XChangeProperty( dpy, rev.xselectionrequest.requestor, rev.xselectionrequest.property, XA_STRING, 8, PropModeReplace, 0, 0 ); } XFlush(dpy); /* no more chars to send, break out of the loop */ if (!chk_pos) break; } } return(selc); }
hash_t *hash_init() { hash_t *hash = xcmalloc(sizeof(hash_t)); return hash; }
static int doIn(Window win, const char *progname) { unsigned char *sel_buf; /* buffer for selection data */ unsigned long sel_len = 0; /* length of sel_buf */ unsigned long sel_all = 0; /* allocated size of sel_buf */ XEvent evt; /* X Event Structures */ int dloop = 0; /* done loops counter */ /* in mode */ sel_all = 16; /* Reasonable ballpark figure */ sel_buf = xcmalloc(sel_all * sizeof(char)); /* Put chars into inc from stdin or files until we hit EOF */ do { if (fil_number == 0) { /* read from stdin if no files specified */ fil_handle = stdin; } else { if ((fil_handle = fopen(fil_names[fil_current], "r")) == NULL) { errperror(3, progname, ": ", fil_names[fil_current] ); return EXIT_FAILURE; } else { /* file opened successfully. Print * message (verbose mode only). */ if (fverb == OVERBOSE) fprintf(stderr, "Reading %s...\n", fil_names[fil_current] ); } } fil_current++; while (!feof(fil_handle)) { /* If sel_buf is full (used elems = * allocated elems) */ if (sel_len == sel_all) { /* double the number of * allocated elements */ sel_all *= 2; sel_buf = (unsigned char *) xcrealloc(sel_buf, sel_all * sizeof(char) ); } sel_len += fread(sel_buf + sel_len, sizeof(char), sel_all - sel_len, fil_handle); } } while (fil_current < fil_number); /* if there are no files being read from (i.e., input * is from stdin not files, and we are in filter mode, * spit all the input back out to stdout */ if ((fil_number == 0) && ffilt) { fwrite(sel_buf, sizeof(char), sel_len, stdout); fclose(stdout); } /* Handle cut buffer if needed */ if (sseln == XA_STRING) { XStoreBuffer(dpy, (char *) sel_buf, (int) sel_len, 0); return EXIT_SUCCESS; } /* take control of the selection so that we receive * SelectionRequest events from other windows */ /* FIXME: Should not use CurrentTime, according to ICCCM section 2.1 */ XSetSelectionOwner(dpy, sseln, win, CurrentTime); /* fork into the background, exit parent process if we * are in silent mode */ if (fverb == OSILENT) { pid_t pid; pid = fork(); /* exit the parent process; */ if (pid) exit(EXIT_SUCCESS); } /* print a message saying what we're waiting for */ if (fverb > OSILENT) { if (sloop == 1) fprintf(stderr, "Waiting for one selection request.\n"); if (sloop < 1) fprintf(stderr, "Waiting for selection requests, Control-C to quit\n"); if (sloop > 1) fprintf(stderr, "Waiting for %i selection requests, Control-C to quit\n", sloop); } /* Avoid making the current directory in use, in case it will need to be umounted */ chdir("/"); /* loop and wait for the expected number of * SelectionRequest events */ while (dloop < sloop || sloop < 1) { /* print messages about what we're waiting for * if not in silent mode */ if (fverb > OSILENT) { if (sloop > 1) fprintf(stderr, " Waiting for selection request %i of %i.\n", dloop + 1, sloop); if (sloop == 1) fprintf(stderr, " Waiting for a selection request.\n"); if (sloop < 1) fprintf(stderr, " Waiting for selection request number %i\n", dloop + 1); } /* wait for a SelectionRequest event */ while (1) { static unsigned int clear = 0; static unsigned int context = XCLIB_XCIN_NONE; static unsigned long sel_pos = 0; static Window cwin; static Atom pty; int finished; XNextEvent(dpy, &evt); finished = xcin(dpy, &cwin, evt, &pty, target, sel_buf, sel_len, &sel_pos, &context); if (evt.type == SelectionClear) clear = 1; if ((context == XCLIB_XCIN_NONE) && clear) return EXIT_SUCCESS; if (finished) break; } dloop++; /* increment loop counter */ } return EXIT_SUCCESS; }