xcb-2.4/0042750000000000040010000000000007570440621007740 5ustar rootxcb-2.4/cb.h0100640000000000040010000000202007570440621010463 0ustar root/* * xcb: Copyright (C) 1992,1993,1994 by Farrell McKay. * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, provided * that the above copyright notice appears in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation. This software is provided "as is" without express or * implied warranty. * * This header file contains the definitions and typedefs * for the custom cut buffer widget. */ #ifndef _cb_h #define _cb_h #include /* needed for CorePart et.al.*/ #define XtNatom "atom" #define XtCAtom "Atom" typedef struct _CbClassRec { CoreClassPart core_class; } CbClassRec, *CbWidgetClass; typedef struct _CbRec { CorePart core; Pixel fgnd; XFontSet fontset; int font_width; int font_ascent; int font_height; GC gc; GC gc_inv; Atom atom; } CbRec, *CbWidget; extern WidgetClass cbWidgetClass; extern CbClassRec cbClassRec; #endif xcb-2.4/xcb.c0100640000000000040010000010300007570440621010646 0ustar root/* * xcb: Copyright (C) 1992,1993,1994 by Farrell McKay. * XView modifications provided by Danny Vanderryn. * mb/utf8 support by Marc Lehmann . * * Simple X interface to the cut buffers in an X server. * The program creates a window subdivided into a number of subwindows, * one per cut buffer. The user may copy cut buffer contents around * using mouse buttons 1 and 2, or rotate the buffers using mouse * button 3. Buffers may be cleared by using Shift-button 2. * * Note that this program assumes the cut buffers contain textual * information, and displays buffer contents using the XDrawString * function. It is not suitable for use in any other environment. * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, provided * that the above copyright notice appears in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation. This software is provided "as is" without express or * implied warranty. */ /* * The Xutf8*-API seems to just add complexity for each and every code author * without providing any benefits (such as better font handling). To the * contrary, xfree86 seems to go into the (wrong) direction of "unicode fonts", * thereby forcing the user to accept their glyph style. Why. Why. Why??? */ #if !defined(ATHENA) && !defined(MOTIF) Bong ! Start again. You must define either the 'ATHENA' or 'MOTIF' symbol when compiling. #endif #include #include #include /* for strcmp() */ #include #include /* for exit()... */ #include /* for read(), write() */ #include /* for pre-defined atom names */ #include /* for XtNforeground et.al. */ #include #include #ifdef ATHENA #ifndef VMS #include #else #include #endif #endif #ifdef MOTIF #include #include #endif #include "cb.h" #include "patchlevel.h" #define eq(a,b) (strcmp((a),(b)) == 0) #define max(a,b) ((a) > (b)? (a): (b)) #define XtNbufferCount "bufferCount" /* Application resources */ #define XtCBufferCount "BufferCount" #define XtNlayout "layout" #define XtCLayout "Layout" #define PGM_NAME "xcb" #define PGM_CLASS "Xcb" #define BUFINC 2048 static Display *dpy; static Window root; static XtAppContext app; static Widget top, box, *wdg; static Atom xa_compound_text, xa_utf8_string, xa_text; static Atom delwin; static Atom *atom; static int natoms, nbuffs; static Window seln; static int use_utf8 = 0; static Atom convert_to; /* convert selection to this cut buffer */ #ifndef X_HAVE_UTF8_STRING #define Xutf8TextPropertyToTextList XmbTextPropertyToTextList #define Xutf8TextListToTextProperty XmbTextListToTextProperty #endif #define FONT_ELEMENT_SIZE 50 static const char * i_strstr (const char *str, const char *ptn) { const char *s2, *p2; for (; *str; str++) { for (s2 = str, p2 = ptn;; s2++, p2++) { if (!*p2) return str; if (toupper (*s2) != toupper (*p2)) break; } } return NULL; } static const char * Font_GetElement (const char *pattern, char *buf, int bufsiz, ...) { const char *p, *v; char *p2; va_list va; va_start (va, bufsiz); buf[bufsiz - 1] = 0; buf[bufsiz - 2] = '*'; while ((v = va_arg (va, char *)) != NULL) { p = i_strstr (pattern, v); if (p) { strncpy (buf, p + 1, bufsiz - 2); p2 = strchr (buf, '-'); if (p2) *p2 = 0; va_end (va); return p; } } va_end (va); strncpy (buf, "*", bufsiz); return NULL; } static const char * Font_GetSize (const char *pattern, int *size) { const char *p; const char *p2 = NULL; int n = 0; for (p = pattern; 1; p++) { if (!*p) { if (p2 != NULL && n > 1 && n < 72) { *size = n; return p2 + 1; } else { *size = 16; return NULL; } } else if (*p == '-') { if (n > 1 && n < 72 && p2 != NULL) { *size = n; return p2 + 1; } p2 = p; n = 0; } else if (*p >= '0' && *p <= '9' && p2 != NULL) { n *= 10; n += *p - '0'; } else { p2 = NULL; n = 0; } } } /* from http://www.debian.org/doc/manuals/intro-i18n/ */ static XFontSet XCreateFontSetWithGuess (Display * d, const char *pattern, char ***miss, int *n_miss, char **def) { XFontSet fs; char *pattern2; int pixel_size, bufsiz; char weight[FONT_ELEMENT_SIZE], slant[FONT_ELEMENT_SIZE]; /* No problem? or 'fs' for pattern analysis */ fs = XCreateFontSet (d, pattern, miss, n_miss, def); if (fs && !*n_miss) return fs; /* no need for font guessing */ /* for non-iso8859-1 language and iso8859-1 specification */ /* This 'fs' is only for pattern analysis. */ if (!fs) { if (*n_miss) XFreeStringList (*miss); setlocale (LC_CTYPE, "C"); fs = XCreateFontSet (d, pattern, miss, n_miss, def); setlocale (LC_CTYPE, ""); } /* make XLFD font name for pattern analysis */ if (fs) { XFontStruct **fontstructs; char **fontnames; XFontsOfFontSet (fs, &fontstructs, &fontnames); pattern = fontnames[0]; } /* read elements of font name */ Font_GetElement (pattern, weight, FONT_ELEMENT_SIZE, "-medium-", "-bold-", "-demibold-", "-regular-", NULL); Font_GetElement (pattern, slant, FONT_ELEMENT_SIZE, "-r-", "-i-", "-o-", "-ri-", "-ro-", NULL); Font_GetSize (pattern, &pixel_size); /* modify elements of font name to fit usual font names */ if (!strcmp (weight, "*")) strncpy (weight, "medium", FONT_ELEMENT_SIZE); if (!strcmp (slant, "*")) strncpy (slant, "r", FONT_ELEMENT_SIZE); if (pixel_size < 3) pixel_size = 3; else if (pixel_size > 97) pixel_size = 97; /* build font pattern for better matching for various charsets */ bufsiz = strlen (pattern) + FONT_ELEMENT_SIZE * 2 + 2 * 2 + 58; pattern2 = (char *) malloc (bufsiz); if (pattern2) { snprintf (pattern2, bufsiz - 1, "%s," "-*-*-%s-%s-*-*-%d-*-*-*-*-*-*-*," "-*-*-*-*-*-*-%d-*-*-*-*-*-*-*,*", pattern, weight, slant, pixel_size, pixel_size); pattern = pattern2; } if (*n_miss) XFreeStringList (*miss); if (fs) XFreeFontSet (d, fs); /* create fontset */ fs = XCreateFontSet (d, pattern, miss, n_miss, def); if (pattern2) free (pattern2); return fs; } static Boolean CvtStringToFontSet (dpy, args, num_args, fromVal, toVal, closure_ret) Display *dpy; XrmValuePtr args; Cardinal *num_args; XrmValuePtr fromVal; XrmValuePtr toVal; XtPointer *closure_ret; { XFontSet f; char **missing_charset_list; int missing_charset_count; char *def_string; f = XCreateFontSetWithGuess (dpy, (char *) fromVal->addr, &missing_charset_list, &missing_charset_count, &def_string); /* Free any returned missing charset list */ if (missing_charset_count) { fprintf (stderr, "Missing charsets in String to FontSet conversion (%s)\n", missing_charset_list[0]); XFreeStringList (missing_charset_list); } if (!f) { f = XCreateFontSetWithGuess (dpy, "-*-*-*-R-*-*-*-120-*-*-*-*", &missing_charset_list, &missing_charset_count, &def_string); } *(XFontSet *) (toVal->addr) = f; return f ? True : False; } /* * Fetch the contents of cut buffer n from the root window. */ static char * fetch_buffer (a, nb, force_mb) Atom a; int *nb; int force_mb; { unsigned long after; char **list; char *data; int count; XTextProperty pt; *nb = 0; if (XGetWindowProperty (dpy, root, a, 0L, 10000000L, False, AnyPropertyType, &pt.encoding, &pt.format, &pt.nitems, &after, &pt.value) != Success || !pt.nitems) return strdup (""); if (pt.nitems) { (force_mb ? XmbTextPropertyToTextList : Xutf8TextPropertyToTextList) (dpy, &pt, &list, &count); data = strdup (list[0]); *nb = strlen (data); XFreeStringList (list); XFree (pt.value); } else data = strdup (""); return data; } /* * Store the string p into cut buffer n on the root window. */ static void store_buffer (p, nb, atom, force_mb) char *p; int nb; Atom atom; int force_mb; { XTextProperty pt; (force_mb ? XmbTextListToTextProperty : Xutf8TextListToTextProperty) (dpy, &p, 1, XStdICCTextStyle, &pt); XChangeProperty (dpy, root, atom, pt.encoding, 8, PropModeReplace, pt.value, pt.nitems); XFree (pt.value); } /* * Add an atom to the program's atom cache. */ static Atom get_atom (n, ifexists) int n, ifexists; { char tmp[32]; if (n >= natoms) { atom = (Atom *) XtRealloc ((char *) atom, (n + 1) * sizeof (Atom)); while (natoms < n + 1) atom[natoms++] = 0; } if (!atom[n]) { sprintf (tmp, "CUT_BUFFER%d", n); atom[n] = XInternAtom (dpy, tmp, (Bool) ifexists); } return atom[n]; } static void initialize_properties (void) { int i; for (i = nbuffs - 1; i >= 0; i--) { Atom a; int nbytes; char *data; a = get_atom (i, False); data = fetch_buffer (a, &nbytes, 0); store_buffer (data, nbytes, a, 0); free (data); } } /* * Draw a string in the window with top-left corner justification. */ static void place_text (cb, str, len, y) CbWidget cb; char *str; int len, y; { int cols; GC gc; gc = (cb->core.window == seln) ? cb->gc_inv : cb->gc; if (y <= (int) cb->core.height) { /* we rely on clipping... */ /*cols = ((int) cb->core.width + cb->font_width - 1) / cb->font_width; */ /*len = min(len, cols); */ if (len > 0) { y -= cb->font_ascent; #if X_HAVE_UTF8_STRING Xutf8DrawImageString #else XmbDrawImageString #endif (dpy, cb->core.window, cb->fontset, gc, 0, y, str, len); } } } /* * ============================================================================ * The following collection of functions and data structures define * the cb widget. Each cb widget displays a single cut buffer value * in a window, and provides cut and paste access to that buffer. */ static void cb_initialize (req, wdg, args, nargs) /*ARGSUSED */ Widget req, wdg; ArgList args; Cardinal *nargs; { CbWidget cb = (CbWidget) wdg; XFontSetExtents *xfe = XExtentsOfFontSet (cb->fontset); cb->font_width = xfe->max_logical_extent.width; cb->font_height = xfe->max_logical_extent.height; cb->font_ascent = xfe->max_logical_extent.y; cb->gc = 0; cb->gc_inv = 0; } static void cb_realize (wdg, mask, attrs) Widget wdg; XtValueMask *mask; XSetWindowAttributes *attrs; { CbWidget cb = (CbWidget) wdg; XtGCMask v_mask = 0L; XGCValues values; XtCreateWindow (wdg, InputOutput, CopyFromParent, *mask, attrs); XStoreName (dpy, cb->core.window, cb->core.name); values.foreground = cb->fgnd; values.background = cb->core.background_pixel; values.plane_mask = AllPlanes; v_mask = GCForeground | GCBackground | GCPlaneMask; cb->gc = XtGetGC (wdg, v_mask, &values); values.foreground = cb->core.background_pixel; values.background = cb->fgnd; cb->gc_inv = XtGetGC (wdg, v_mask, &values); } /* * Redraw the contents of one of the subwindows. * The function assumes the cut buffer contains text data, and parses * it accordingly. The data is split into lines at each '\n' character. * Lines which extend beyond the subwindow's borders are clipped; no * wrap-around processing is done. * Keep it simple. */ static void cb_redisplay (wdg, event, region) /*ARGSUSED */ Widget wdg; XEvent *event; Region region; { CbWidget cb = (CbWidget) wdg; char *p, *pp, *base; int y, nbytes; y = 0; p = pp = base = fetch_buffer (cb->atom, &nbytes, 0); while (pp < base + nbytes) { if (*pp == '\n') { place_text (cb, p, pp - p, y); p = pp + 1; y += cb->font_height; } pp++; } place_text (cb, p, pp - p, y); XFree (base); } static void cb_destroy (wdg) Widget wdg; { CbWidget cb = (CbWidget) wdg; XtReleaseGC (wdg, cb->gc); XtReleaseGC (wdg, cb->gc_inv); } /* * Make this widget the owner of the PRIMARY selection. * The window contents are then redrawn with highlighting. * * It seems that if a XSetSelectionOwner is performed on a client's * window, no SelectionClear event is generated if another window * within the same client is already the selection owner. * This function originally attempted to avoid that problem and force * a SelectionClear event by firstly setting the selection ownership * to None and then setting it to this widget's window. Apparently * that didn't work for all X servers. * * Therefore the function must do the SelectionClear logic itself, * which means it must know when another xcb widget has selection * ownership, which brings about the need for the 'seln' global variable. * This breaks all the rules for object oriented widgets. Disgusting, no? */ static void cb_cut (wdg, event, parms, nparms) /*ARGSUSED */ Widget wdg; XEvent *event; String *parms; Cardinal *nparms; { CbWidget cb = (CbWidget) wdg; Window win = cb->core.window; Window w, tmp; if (win == seln) return; XSetSelectionOwner (dpy, XA_PRIMARY, win, event->xbutton.time); w = XGetSelectionOwner (dpy, XA_PRIMARY); if (seln && w != seln) { tmp = seln; seln = 0; XClearArea (dpy, tmp, 0, 0, 0, 0, False); cb_redisplay (XtWindowToWidget (dpy, tmp), (XEvent *) 0, (Region) 0); } if (w == win) { seln = win; XClearArea (dpy, win, 0, 0, 0, 0, False); cb_redisplay (wdg, (XEvent *) 0, (Region) 0); } } static void cb_paste (wdg, event, parms, nparms) /*ARGSUSED */ Widget wdg; XEvent *event; String *parms; Cardinal *nparms; { CbWidget cb = (CbWidget) wdg; Window w; char *ptr; int n; w = XGetSelectionOwner (dpy, XA_PRIMARY); if (w == None) { ptr = fetch_buffer (atom[0], &n, 0); /* copy from cb0 */ store_buffer (ptr, n, cb->atom, 0); XFree (ptr); } else if (w != cb->core.window) XConvertSelection (dpy, XA_PRIMARY, xa_utf8_string, convert_to = cb->atom, XtWindow (wdg), event->xbutton.time); } static void cb_clear (wdg, event, parms, nparms) /*ARGSUSED */ Widget wdg; XEvent *event; String *parms; Cardinal *nparms; { CbWidget cb = (CbWidget) wdg; Window win = cb->core.window; store_buffer ("", 0, cb->atom, 0); if (win == seln) { seln = 0; XSetSelectionOwner (dpy, XA_PRIMARY, None, event->xbutton.time); } } static void cb_rotate (wdg, event, parms, nparms) /*ARGSUSED */ Widget wdg; XEvent *event; String *parms; Cardinal *nparms; { int n = 0; if (*nparms > 0) n = atoi (parms[0]); if (n != 0) XRotateWindowProperties (dpy, root, atom, nbuffs, n); } static void cb_quit (wdg, event, parms, nparms) /*ARGSUSED */ Widget wdg; XEvent *event; String *parms; Cardinal *nparms; { exit (0); } /* * Clear and redraw the widget's window. */ static void cb_refresh (wdg, event, parms, nparms) /*ARGSUSED */ Widget wdg; XEvent *event; String *parms; Cardinal *nparms; { XClearArea (dpy, wdg->core.window, 0, 0, 0, 0, False); cb_redisplay (wdg, (XEvent *) 0, (Region) 0); } /* * Someone or something wants a copy of the current PRIMARY selection. * Such a request is only satisfied if the target type is STRING. * (No conversion facilities are provided by this program). * The selection request is met by copying the current contents * of the cut buffer to the target window+atom. */ static void cb_selreq (wdg, event, parms, nparms) /*ARGSUSED */ Widget wdg; XEvent *event; String *parms; Cardinal *nparms; { int nbytes; char *ptr; XSelectionEvent notify; XSelectionRequestEvent *rq; CbWidget cb = (CbWidget) wdg; Window win = cb->core.window; rq = (XSelectionRequestEvent *) event; notify.type = SelectionNotify; notify.display = rq->display; notify.requestor = rq->requestor; notify.selection = rq->selection; notify.target = rq->target; notify.property = None; notify.time = rq->time; if (win == seln) { XICCEncodingStyle style; Atom target = None; if (rq->target == XA_STRING) { target = XA_STRING; style = XStringStyle; } else if (rq->target == xa_text) { target = xa_compound_text; style = XStdICCTextStyle; } else if (rq->target == xa_compound_text) { target = xa_compound_text; style = XCompoundTextStyle; } #ifdef X_HAVE_UTF8_STRING else if (rq->target == xa_utf8_string) { target = xa_utf8_string; style = XUTF8StringStyle; } #endif if (target != None) { XTextProperty pt; char *fl; fl = fetch_buffer (cb->atom, &nbytes, 0); Xutf8TextListToTextProperty (dpy, &fl, 1, style, &pt); XFree (fl); XChangeProperty (dpy, rq->requestor, rq->property, pt.encoding, 8, PropModeReplace, pt.value, pt.nitems); notify.property = rq->property; XFree (pt.value); } } XSendEvent (dpy, rq->requestor, False, 0, (XEvent *) & notify); } /* * Boo hiss, someone has taken the PRIMARY selection ownership * away from this widget. The current window contents must * be redrawn without highlighting. */ static void cb_selclear (wdg, event, parms, nparms) /*ARGSUSED */ Widget wdg; XEvent *event; String *parms; Cardinal *nparms; { CbWidget cb = (CbWidget) wdg; if (event->xproperty.atom != XA_PRIMARY) return; seln = 0; XClearArea (dpy, cb->core.window, 0, 0, 0, 0, False); cb_redisplay (wdg, (XEvent *) 0, (Region) 0); } static XtResource resources[] = { #define offset(field) XtOffset(CbWidget, field) /* {name, class, type, size, offset, default_type, default_addr}, */ {XtNforeground, XtCForeground, XtRPixel, sizeof (Pixel), offset (fgnd), XtRString, (XtPointer) "XtDefaultForeground"}, {XtNfontSet, XtCFontSet, XtRFontSet, sizeof (XFontSet), offset (fontset), XtRString, (XtPointer) "XtDefaultFontSet"}, {XtNatom, XtCAtom, XtRAtom, sizeof (Atom), /* internal use */ offset (atom), XtRImmediate, (XtPointer) 0}, #undef offset }; static XtActionsRec actions[] = { {"cut", cb_cut}, {"paste", cb_paste}, {"clear", cb_clear}, {"rotate", cb_rotate}, {"quit", cb_quit}, {"refresh", cb_refresh}, {"selreq", cb_selreq}, {"selclear", cb_selclear}, }; static char cb_transl[] = "\ : cut() \n\ Shift : clear() \n\ : paste() \n\ Shift : rotate(-1) \n\ : rotate(1) \n\ Left: rotate(-1) \n\ Right: rotate(1) \n\ Up: rotate(-1) \n\ Down: rotate(1) \n\ q: quit() \n\ : selreq() \n\ : selclear() \n\ "; CbClassRec cbClassRec = { { (WidgetClass) & widgetClassRec, /* superclass */ "Buffer", /* class_name */ sizeof (CbRec), /* widget_size */ NULL, /* class_initialize */ NULL, /* class_part_initialize */ FALSE, /* class_inited */ cb_initialize, /* initialize */ NULL, /* initialize_hook */ cb_realize, /* realize */ actions, /* actions */ XtNumber (actions), /* num_actions */ resources, /* resources */ XtNumber (resources), /* num_resources */ NULLQUARK, /* xrm_class */ TRUE, /* compress_motion */ TRUE, /* compress_exposure */ TRUE, /* compress_enterleave */ FALSE, /* visible_interest */ cb_destroy, /* destroy */ NULL, /* resize */ cb_redisplay, /* expose */ NULL, /* set_values */ NULL, /* set_values_hook */ XtInheritSetValuesAlmost, /* set_values_almost */ NULL, /* get_values_hook */ NULL, /* accept_focus */ XtVersion, /* version */ NULL, /* callback_private */ cb_transl, /* tm_table */ XtInheritQueryGeometry, /* query_geometry */ XtInheritDisplayAccelerator, /* display_accelerator */ NULL /* extension */ }, }; WidgetClass cbWidgetClass = (WidgetClass) & cbClassRec; /* * Here endeth the section concerned with the cb widget. * Normal viewing shall now be resumed. * ============================================================================ */ static void usage () { fprintf (stderr, "Usage: %s [Xt option] [-l layout] [-n count] [-p|-s|-S list] [-r count]\n", PGM_NAME); exit (1); } /* * Gracefully exit after an XIO error, or after a "delete window" * directive from the window manager. * xioerror() avoids messy error messages sometimes seen from xterm * or in the xdm-errors file when forcibly destroying the client program. */ static int xioerror (d) /*ARGSUSED */ Display *d; { exit (1); /*NOTREACHED */ } static void wmdel (wdg, ptr, ep, cont) /*ARGSUSED */ Widget wdg; XtPointer ptr; XEvent *ep; Boolean *cont; { if (ep->type == ClientMessage && ep->xclient.data.l[0] == delwin) exit (0); } /* * Print the contents of a cut buffer on stdout. */ static void doprint (n, ptr, nb) int n; char *ptr; int nb; { Atom a; a = get_atom (n, True); if (a) { ptr = fetch_buffer (a, &nb, !use_utf8); if (write (1, ptr, nb) != nb) { fprintf (stderr, "Write error\n"); exit (1); } XFree (ptr); } } /* * Load a new value into one of the cut buffers. */ static void doset (n, ptr, nb) int n; char *ptr; int nb; { char *str = malloc (nb + 1); memcpy (str, ptr, nb); str[nb] = 0; store_buffer (str, nb, get_atom (n, False), !use_utf8); free (str); } static void timeout (arg, id) char *arg; XtIntervalId *id; { exit (2); } /* * Copy the PRIMARY selection into a cut buffer. */ static void dogetseln (n, ptr, nb) int n; char *ptr; int nb; { char *data; int nbytes; Atom atm; XEvent event; atm = get_atom (n, False); if (XGetSelectionOwner (dpy, XA_PRIMARY) == None) { if (n != 0) { data = fetch_buffer (atom[0], &nbytes, 0); store_buffer (data, nbytes, atm, 0); XFree (data); } return; } XSelectInput (dpy, root, PropertyChangeMask); XConvertSelection (dpy, XA_PRIMARY, xa_utf8_string, atm, root, CurrentTime); XtAppAddTimeOut (app, 3000, timeout, (char *) 0); for (;;) { XtAppNextEvent (app, &event); if (event.type == PropertyNotify && event.xproperty.window == root && event.xproperty.atom == atm && event.xproperty.state == PropertyNewValue) { return; } XtDispatchEvent (&event); /* This cannot happen. !!?? */ } } /* * Process an ASCII list of cut buffer numbers. * Lists must obey the form "buffno[,buffno...]" * where buffno is a non-negative integer or a range * of the form M-N. A processing function is called * for each buffer number in the list. Duplicates and * list ordering is significant. */ static void dolist (list, fn, data, nbytes) char *list; void (*fn) (); char *data; int nbytes; { int m, n, x; while (*list) { if (!isdigit (*list)) usage (); for (m = 0; isdigit (*list); list++) m = m * 10 + *list - '0'; (*fn) (m, data, nbytes); if (*list == '-') { list++; if (!isdigit (*list)) usage (); for (n = 0; isdigit (*list); list++) n = n * 10 + *list - '0'; x = (m > n) ? -1 : 1; while (m != n) { m += x; (*fn) (m, data, nbytes); } } if (*list == ',') list++; else if (*list) usage (); } } /* * Perform a task mode command, i.e. * do something to the cut buffers immediately, * without the need to create any X windows first. */ static void dotask (cmd, arg) int cmd; char *arg; { char *ptr; int i, n, nb; ptr = (char *) 0; n = nb = 0; switch (cmd) { case 'p': /* print one or more buffers */ dolist (arg, doprint, (char *) 0, 0); break; case 'r': /* rotate the buffer contents */ n = atoi (arg); if (n == 0) break; initialize_properties (); XRotateWindowProperties (dpy, root, atom, nbuffs, n); break; case 's': /* store data in one or more buffers */ do { ptr = XtRealloc (ptr, nb + BUFINC); i = BUFINC; do { n = read (0, ptr + nb, i); nb += n; i -= n; } while (n > 0 && i > 0); } while (n > 0); if (n == -1) { fprintf (stderr, "Read error\n"); exit (1); } dolist (arg, doset, ptr, nb); XtFree (ptr); break; case 'S': dolist (arg, dogetseln, (char *) 0, 0); break; } } typedef struct { int nbuffs; char *layout; } ares_t, *ares_ptr; static ares_t ares; static XtResource res[] = { #define offset(field) XtOffset(ares_ptr, field) {XtNbufferCount, XtCBufferCount, XtRInt, sizeof (int), offset (nbuffs), XtRImmediate, (XtPointer) 8}, {XtNlayout, XtCLayout, XtRString, sizeof (char *), offset (layout), XtRImmediate, "horiz"}, #undef offset }; static char *def[] = { /* default resource values */ ".bufferCount: 8", ".layout: horizontal", "*fontSet: XtDefaultFontSet", "*Buffer.width: 60", "*Buffer.height: 60", 0, }; static XrmOptionDescRec opt[] = { {"-n", ".bufferCount", XrmoptionSepArg, (caddr_t) 8}, {"-l", ".layout", XrmoptionSepArg, (caddr_t) "horiz"}, }; /* * Parse the command line options, and * perform all the windows initializations. */ static void init (argc, argv) int argc; char **argv; { int i, n; char **p; char name[16]; Arg args[3]; /* * Set up the atoms that we already know about. */ natoms = 8; atom = (Atom *) XtMalloc (natoms * sizeof (Atom)); atom[0] = XA_CUT_BUFFER0; atom[1] = XA_CUT_BUFFER1; atom[2] = XA_CUT_BUFFER2; atom[3] = XA_CUT_BUFFER3; atom[4] = XA_CUT_BUFFER4; atom[5] = XA_CUT_BUFFER5; atom[6] = XA_CUT_BUFFER6; atom[7] = XA_CUT_BUFFER7; /* * Initialize the toolkit, parse the command line, * initialize the resources database, and find out * how many buffers to deal with. */ XtSetLanguageProc (0, 0, 0); top = XtAppInitialize (&app, PGM_CLASS, opt, 2, &argc, argv, def, 0, 0); dpy = XtDisplay (top); root = RootWindow (dpy, DefaultScreen (dpy)); XtSetTypeConverter(XtRString, /* source type */ XtRFontSet, /* target type */ CvtStringToFontSet, /* converter routine */ (XtConvertArgList) NULL, /* args for converter routine */ 0, /*# args for converter routine */ XtCacheAll, /* caching instructions */ NULL); /* destructor function */ XtGetApplicationResources (top, &ares, res, XtNumber (res), 0, 0); nbuffs = max (ares.nbuffs, 1); /* search for the -u and -v switches first */ for (p = argv + 1; p < argv + argc; p++) { if (eq (*p, "-u")) use_utf8 = 1; else if (eq (*p, "-V")) { printf ("xcb version %s\n", version); exit (0); } } /* * If the command line contains one of the task mode * switches (print, set, rotate), it is processed here. * If there are multiple task mode args, only the first * one is processed. */ for (p = argv + 1; p < argv + argc; p++) { if (eq (*p, "-p") || eq (*p, "-r") || eq (*p, "-s") || eq (*p, "-S")) { if (p == argv + argc - 1) usage (); dotask (p[0][1], p[1]); XCloseDisplay (dpy); exit (0); } } /* * If no task mode request has been made of us, this code * proceeds with the rest of the windows initialization. * The container widget is created, the sub-widgets are * created and then everything is realized. */ if (argc > 1) usage (); wdg = (Widget *) XtMalloc (nbuffs * sizeof (Widget)); #ifdef ATHENA box = XtCreateWidget ("container", formWidgetClass, top, 0, 0); XtManageChild (box); for (i = 0; i < nbuffs; i++) { XtSetArg (args[0], XtNatom, get_atom (i, False)); n = 1; if (i > 0) { if (ares.layout[0] == 'h') { XtSetArg (args[1], XtNfromHoriz, wdg[i - 1]); XtSetArg (args[2], XtNfromVert, 0); n = 3; } if (ares.layout[0] == 'v') { XtSetArg (args[1], XtNfromVert, wdg[i - 1]); XtSetArg (args[2], XtNfromHoriz, 0); n = 3; } } sprintf (name, "buffer%d", i); wdg[i] = XtCreateWidget (name, cbWidgetClass, box, args, n); XtManageChild (wdg[i]); } #endif #ifdef MOTIF n = 0; if (ares.layout[0] == 'h') { XtSetArg (args[0], XmNorientation, XmHORIZONTAL); n = 1; } if (ares.layout[0] == 'v') { XtSetArg (args[0], XmNorientation, XmVERTICAL); n = 1; } box = XtCreateWidget ("container", xmRowColumnWidgetClass, top, args, n); XtManageChild (box); for (i = 0; i < nbuffs; i++) { Widget frame; XtSetArg (args[0], XtNatom, get_atom (i, False)); n = 1; sprintf (name, "frame%d", i); frame = XmCreateFrame (box, name, 0, 0); XtManageChild (frame); sprintf (name, "buffer%d", i); wdg[i] = XtCreateWidget (name, cbWidgetClass, frame, args, n); XtManageChild (wdg[i]); } #endif XSelectInput (dpy, root, PropertyChangeMask); XSetIOErrorHandler (xioerror); XtRealizeWidget (top); delwin = XInternAtom (dpy, "WM_DELETE_WINDOW", False); XSetWMProtocols (dpy, XtWindow (top), &delwin, 1); XtAddEventHandler (top, 0, True, wmdel, (XtPointer) 0); xa_compound_text = XInternAtom (dpy, "COMPOUND_TEXT", False); xa_utf8_string = XInternAtom (dpy, "UTF8_STRING", False); xa_text = XInternAtom (dpy, "TEXT", False); if (!xa_utf8_string) xa_utf8_string = xa_compound_text; initialize_properties (); } /* * Process incoming events. * The program needs to know when a cut buffer value changes. * We achieve this by eavesdropping on PropertyNotify events arising * on the root window. If such an event is delivered to us, the * function immediately clears the window displaying that property * and causes an Expose event to be generated for the window. * This is horrible nasty stuff. */ static void xevents () { XEvent event; int i; for (;;) { XtAppNextEvent (app, &event); if (event.type == PropertyNotify) { for (i = 0; i < nbuffs; i++) if (event.xproperty.atom == atom[i]) XClearArea (dpy, XtWindow (wdg[i]), 0, 0, 0, 0, True); } else if (event.type == SelectionNotify) { if (event.xselection.property) { /* horribly inefficient... */ XConvertSelection (dpy, XA_PRIMARY, event.xselection.target, convert_to, root, event.xselection.time); } else { Atom target; if (event.xselection.target == xa_text) target = XA_STRING; else if (event.xselection.target == xa_compound_text) target = xa_text; else if (event.xselection.target == xa_utf8_string) target = xa_compound_text; else target = None; if (target != None) XConvertSelection (dpy, XA_PRIMARY, target, convert_to, event.xselection.requestor, event.xselection.time); } } else (void) XtDispatchEvent (&event); } } main (argc, argv) int argc; char **argv; { init (argc, argv); xevents (); return 0; } xcb-2.4/README0100640000000000040010000001227707570440621010625 0ustar root What is xcb? ============ Do you ever wish you could cut two or more separate pieces of text at once from a window? Do you ever need to save the output from one command for reuse in several subsequent tasks? Do you ever find yourself wanting some easy means of globally exporting data, e.g. to a parent shell, to another xterm or application, or to another machine or user? If you answer yes to any of these questions, then xcb is for you. Xcb provides access to the cut buffers built into every X server. It allows the buffers to be manipulated either via the command line, or with the mouse in a point and click manner. The buffers can be used as holding pens to store and retrieve arbitrary data fragments, so any number of different pieces of data can be saved and recalled later. The program is designed primarily for use with textual data. What is so good about this release? =================================== Release 2.3i add I18n and Unicode support to the base xcb. It also supports more formats, so applications requiring compound text for example work. You cna also paste utf-8 and japanese text... Release 2.3 fixes a bug found in the XView code that prevented data from being pasted from xcb to XView applications such as cmdtool. The release also adds a Motif GUI, selectable as a compile-time option. Now you can choose between the Athena or the Motif look and feel. Yes, but has it been ported to WHIZ-IX 12.1A.00x, on SRS-80 27-bit CPUs? ======================================================================== Xcb has been ported to a wide variety of sites and systems. In no particular order, the machines and operating systems known to be running xcb include:- o OSx (5.1a) - Pyramid MIS-2/02 o DC/OSx (1.0) - Pyramid MIServer-S 1/32 r3000 o AT&T SYSV (SVR3.2, SVR4) - i386, DG Aviion 5200 o HP-UX (lots of versions) - HP 9000s o SunOS (4.1) - Sun3, Sun4, Solbourne Series5, SPARCstations o SPARC/OS (1.1) o Solaris (2.1) - SPARCstations o Irix (4.0, 5.2) - SGI o ULTRIX (4.2) - DECstations o UNICOS (6.1) - Cray Y-MP o ConvexOS (10.0.2) - Convex 3100 o DYNIX (V3.0.17.10) - Sequent Symmetry S81 o AIX (3.2) - RS6000 o RISC/os (4.52) - MIPS o Domain/OS (10.4) - Apollo DN3000, 3500, 4500, 5500 o Linux (lots of versions) - i486 o VMS (5.5) o DGUX (5.4.2) - AViiON mc88100 o Dynix/ptx (1.3) - i386 Xcb has been written to compile using both ANSI and non-ANSI compilers. It is in use in X11 R3, R4, R5 and R6 environments. The current version uses either the Athena widgets (libXaw.a) or the Motif widgets (libXm.a), plus the X Toolkit library (libXt.a). Ok, where is it available? ========================== This version is a branch of the original xcb sources. It's homepage can be found at http://xcb.plan9.de/ So, it will compile, will it? ============================= Yes! The makefiles will, by default, build the Athena widgets version of xcb. If you prefer Motif, you should adjust the $(GUI) definition to be -DMOTIF. In addition, if you wish to cut and paste text between xcb and XView applications, you should also add the -DXVIEW flag. AT&T SVR4 sites need libnsl.a during linking. If you are using SVR4, and you don't like Imakefiles, you will need to add -lnsl to the LIBS in Makefile.std. HP-UX users may find that the Athena widgets are not installed on their machine, even though the components are freely available as part of the MIT X11 distribution. There is an HP maintained, but unsupported, set of X11R4 libraries and utilities (including the Athena widgets) for the HP 9000 Series 300, 400, 700, and 800. You can get the libraries, include files, and config files (imake) via anonymous FTP from hpcvaaz.cv.hp.com (15.255.72.15) - look for pub/MitX11R4/libs.s*00.tar.Z AIX 3.2 users may find their Athena components are installed in a non-standard place. Check the directory /usr/lpp/X11/Xamples/lib/Xaw. VMS and ULTRIX users may find their Athena components are installed in a non-standard place too. Check the directory /usr/include/mit for the Athena include files. And how do I set the thing up? ============================== That is pretty easy too. Once you have compiled the program, you can start using it straight away - just put it in your favourite bin directory. The program contains a minimal set of fallback resources so that it will behave itself even if there are no X resource specifications for it to feed on. To install the program, plus its application defaults file, and the man page, simply type 'make install install.man', after checking the target directories for the install in the Imakefile/Makefile.std. Who is to blame? Where do I send complaints? ============================================= Blame me. If you have any bug reports, porting problems, comments, more comments, suggestions, patches, unwanted cash etc. please tell me. I can be reached at the email address below. Marc Lehmann Feb 2001 ;) I couldn't reach the original author, who wrote most of xcb, but your mileage may vary. Xcb was originally brought to you by: Better still, if you really like xcb, send me a postcard! (to P.O. Box 213, Belgrave, Victoria, Australia. 3160). Enjoy. Farrell McKay (Farrell.McKay@mpx.com.au) Nov 1994 xcb-2.4/Imakefile0100640000000000040010000000120307570440621011541 0ustar root # Add your favourite compiler flags here, and select either the # Athena or Motif GUI interface. # DEFINES = $(GUI) # -DXVIEW GUI = -DATHENA #GUI = -DMOTIF # These are the libraries required for linking. Select one. # DEPLIBS = $(DEPXALIB) $(DEPXMULIB) $(DEPXTOOLLIB) $(DEPXLIB) LOCAL_LIBRARIES = $(XAWLIB) $(XMULIB) $(XTOOLLIB) $(XLIB) #DEPLIBS = $(DEPMOTIFLIB) $(DEPXTOOLLIB) $(DEPXLIB) #LOCAL_LIBRARIES = $(MOTIFLIB) $(XTOOLLIB) $(XLIB) SYS_LIBRARIES = SRCS = xcb.c OBJS = xcb.o ComplexProgramTarget(xcb) Xcb.ad: Xcb.ad.base $(CPP) -P Xcb.ad.base $(GUI) > $@ # -P removes line directives. InstallAppDefaults(Xcb) xcb-2.4/Changes0100640000000000040010000000724507570440621011237 0ustar root(this fork is maintained by Marc Lehmann ) 2.4 Mon Nov 25 16:15:55 CET 2002 - much better i18n, slightly inefficient and probably not perfect, but cna be used to convert between a lot of apps who have their own problems (mozilla, netscape, lyx...) 2.32 Wed Mar 28 12:04:26 CEST 2001 - properties are now being initialized properly. 2.3i (branch maintained by Marc Lehmann ) - Forked version because the original maintainer was unreachable. - Internal representation has now changed to utf-8 (XFree) or locale-dependent multibyte (X). - Font ressource is now .fontSet instead of .font. - I/O is done using the current locale unless the -u (utf8) switch is in effect. Version 2.3 (patchlevel 3): o Bug fix: XVIEW code was broken when pasting from xcb to some XView applications (cmdtool, mailtool, ....) o Added alternative Motif(tm) GUI for that special warm 3D look-and-feel that we all love. Version 2.2 (patchlevel 2): o Added -S task mode option for copying the current PRIMARY selection into a cut buffer. Use this if you need to grab a copy of the current PRIMARY selection. o Added WM_NAME hints to each of the individual buffer windows. This helps you to set the PRIMARY selection from a program or shell script - send a event to one of the windows. o Bug fix: needed to explicitly specify all form widget attachments for the -h and -v layout schemes. o Bug fix: Xcb.ad multi-row example resources were wrong. Version 2.1 (patchlevel 1): o Added the WM_DELETE_WINDOW protocol. o Bug fix: on some platforms (SunOS, ULTRIX and VMS) xcb could not hand off the PRIMARY selection between its own windows, so windows remained highlighted, and could not be re-selected. o Bug fix: rotating the buffers when using fewer than 8 cut buffer windows, either via mouse button 3 or via the arrow keys, caused the program to dump core. Version 2.0 (patchlevel 0): o Went to an Xaw and Xt based implementation. Many pros and cons to this decision. Some of the pros: standardized support for Toolkit command line switches, support for resource specifications .Xdefaults app-defaults files etc., control over individual subwindow sizes, placement, translations etc. Some of the cons: program is noticeably fatter and slower (Booo, hiss). o User selectable number of cut buffers - any number from 1 upwards; no longer limited to 8. o Added code for compatibility with XView 2.0 and 3.0 applications (code provided Danny Vanderryn; thanks Danny!). o Added XIO error handler for graceful shutdown when killed. o Changed list processing for '-p' and '-s' options so that list order and duplicates are significant. Version 1.1 (patchlevel 1): o Added WM_CLASS hints to the client properties. This fixed failures by some window managers (e.g. mwm, olwm) to honour client decoration directives. o Removed 9x15bold default font specification (sigh, reluctantly). o #include directive is now conditional upon __STDC__. o Added another example to the man page. o Several porting changes to Imakefile and Makefile.std o Fallback geometry in vertical mode altered to give a tall, thin window size. o Support for non-standard implementations of realloc() added, i.e. '-s' option never passes a NULL pointer value to realloc() now. o Function declarations rewritten for compilation in both ANSI and non-ANSI environments. o usage() string concatenated. o Warnings/complaints from some compilers re parameter type mismatch in XChangeProperty() calls fixed. Version 1.0: o Initial version xcb-2.4/Makefile.std0100640000000000040010000000241507570440621012167 0ustar root# # $Header: /cvsroot/xcb/Makefile.std,v 1.1 2002/10/10 10:07:02 root Exp $ CPP = /lib/cpp INCS = HDRS = cb.h patchlevel.h SRCS = xcb.c OBJS = xcb.o MISC = README Changes xcb.man Xcb.ad.base Imakefile Makefile.std DISTN = $(MISC) $(SRCS) $(HDRS) # Add your favourite compiler flags here, and select either the # Athena or Motif GUI interface. # CFLAGS = $(INCS) -O $(GUI) # -DXVIEW LDFLAGS = GUI = -DATHENA #GUI = -DMOTIF # These are the libraries required for linking. Select one. # LIBS = -lXaw -lXt -lXext -lX11 # Athena libraries #LIBS = -lXm -lXt -lX11 # Motif libraries all: xcb xcb: $(OBJS) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) Xcb.ad: Xcb.ad.base $(CPP) -P Xcb.ad.base $(GUI) > $@ # -P removes line directives. # You will need to check and possibly adjust the target # directories for these install rules. # install: xcb Xcb.ad install -c xcb /usr/bin/X11 install -c -m 0644 -o bin -g bin Xcb.ad /usr/lib/X11/app-defaults/Xcb install.man: install -c -m 0644 -o bin -g bin xcb.man /usr/share/man/mrd/man1/xcb.1 clean clobber: rm -f *.o xcb tags ctags: $(HDRS) $(SRCS) ctags -tw $(HDRS) $(SRCS) shar: shar -c -f part -p -x X $(DISTN) tar: mkdir xcb-2.4 cp $(DISTN) xcb-2.4 tar -cf xcb-2.4.tar xcb-2.4 gzip -9 xcb-2.4.tar rm -rf xcb-2.4 xcb-2.4/patchlevel.h0100640000000000040010000000007107570440621012232 0ustar root /* PATCHLEVEL: 3 */ static char version[] = "Xcb 2.4"; xcb-2.4/Xcb.ad.base0100640000000000040010000000557707570440621011705 0ustar root ! Xcb application defaults resource file. ! ====================================================================== #ifdef ATHENA ! The xcb widget hierarchy consists of a number of custom buffer ! widgets contained within a single Athena form widget. ! The widget names and classes are as follows: ! ! buffer widgets name = "buffer" class = "Buffer" ! form widget name = "container" class = "Form" #endif #ifdef MOTIF ! The xcb widget hierarchy consists of a number of custom buffer ! widgets each enclosed by its own Motif frame widget. The frame ! widgets are all contained within a single Motif RowColumn widget. ! The widget names and classes are as follows: ! ! buffer widgets name = "buffer" class = "Buffer" ! frame widgets name = "frame" class = "XmFrame" ! rowcolumn widget name = "container" class = "XmRowColumn" #endif ! Buffer widgets are numbered from 0... onwards, and are named accordingly. ! As well as the standard core resources, each buffer widget supports ! resources for "foreground" and "fontSet". ! Application wide resources are as follows: ! ! "bufferCount" (default value 8) ! This is the number of buffer widgets to create. ! Any number of widgets (greater than zero) can be created. ! ! "layout" (default value "h") ! Only the first character of the resource value is significant. ! This is the geometry arrangement to apply in the container widget. ! The layout can be "h" (horizontal), "v" (vertical), or some ! other value to disable the inbuilt geometry code and specify ! the layout via your X resources. Xcb.bufferCount: 8 Xcb.layout: horizontal Xcb*fontSet: fixed Xcb*borderWidth: 1 Xcb*Buffer.width: 60 Xcb*Buffer.height: 60 #ifdef ATHENA Xcb*container.defaultDistance: 0 #endif #ifdef MOTIF !Xcb*XmFrame*shadowType: SHADOW_ETCHED_IN Xcb*XmFrame*shadowType: SHADOW_IN ! The Motif RowColumn widget permits many layout schemes. ! For example, vary the '*numColumns' value for multiple rows/columns. ! Refer to the "Motif Programmers Reference Guide" for full details. ! !Xcb.container*orientation: HORIZONTAL Xcb.container*packing: PACK_COLUMN Xcb.container*numColumns: 1 Xcb.container.marginWidth: 1 Xcb.container.marginHeight: 1 Xcb.container.spacing: 2 #endif #ifdef ATHENA ! Below is an example of a layout scheme which arranges ! 10 cut buffer widgets in two rows of 5 windows. ! Refer to the "Athena Widget Set" manual for full details. ! !Xcb.bufferCount: 10 !Xcb.layout: custom !Xcb*buffer1.fromHoriz: buffer0 !Xcb*buffer2.fromHoriz: buffer1 !Xcb*buffer3.fromHoriz: buffer2 !Xcb*buffer4.fromHoriz: buffer3 !Xcb*buffer5.fromVert: buffer0 !Xcb*buffer6.fromHoriz: buffer5 !Xcb*buffer6.fromVert: buffer1 !Xcb*buffer7.fromHoriz: buffer6 !Xcb*buffer7.fromVert: buffer2 !Xcb*buffer8.fromHoriz: buffer7 !Xcb*buffer8.fromVert: buffer3 !Xcb*buffer9.fromHoriz: buffer8 !Xcb*buffer9.fromVert: buffer4 #endif xcb-2.4/xcb.man0100640000000000040010000002375307570440621011217 0ustar root.TH XCB 1 "Oct 6 1994" "X Version 11" .SH NAME xcb \- X Cut Buffers \- Pigeon holes for your cut and paste selections. .SH SYNOPSIS .B xcb [\fIXt option\fP] [\fB\-l\fP \fIlayout\fP] [\fB\-n\fP \fIcount\fP] [\fB\-p\fP|\fB\-s\fP|\fB\-S\fP \fIlist\fP] [\fB\-r\fP \fIcount\fP] .SH DESCRIPTION \fIXcb\fP provides easy access to the cut buffers built into every X server. It allows the buffers to be manipulated either via the command line, or with the mouse in a point and click manner. The buffers can be used as holding pens to store and retrieve arbitrary data fragments. Any number of cut buffers may be created, so any number of different pieces of data can be saved and recalled later. By default, 8 cut buffers are created. The program is designed primarily for use with textual data. .LP \fIXcb\fP has two modes of operation. Normally \fIxcb\fP provides an array of windows on your display, one per cut buffer, tiled horizontally, vertically, or in some user specified layout. Each window displays the contents of its respective cut buffer. Data can be cut from and pasted to the windows in a similar manner to xterm. The buffers can also be rotated. .LP In task mode, \fIxcb\fP lets you access the cut buffers from the command line. Cut buffers can be loaded from stdin, copied or concatenated to stdout, loaded using the current PRIMARY selection, or rotated an arbitrary number of positions. In this mode of operation, \fIxcb\fP performs the requested task and then exits. It does not create any windows and has no interaction with the mouse or keyboard. .SH OPTIONS \fIXcb\fP supports the full set of X Toolkit Intrinsics options, as well as those listed below. \fIXcb\fP options can appear in any order. The presence of the \fB\-p\fP, \fB\-r\fP, \fB\-s\fP or \fB\-S\fP options causes \fIxcb\fP to execute in task mode, described above. .IP "\fB\-l\fP \fIlayout\fP" This option controls the geometry arrangement of \fIxcb's\fP subwindows. It is the command line equivalent of the \fB.layout\fP resource, described below. .LP .IP "\fB\-n\fP \fIcount\fP" Create \fIcount\fP cut buffers. \fICount\fP can be any integer greater than zero. This option is the command line equivalent of the \fB.bufferCount\fP resource, described below. .LP .IP "\fB\-u\fP" Use utf-8 instead of the current locale settings when executing in task mode and doing I/O. .LP .IP "\fB\-V\fP" Print the xcb release version number and exit immediately. .LP .IP "\fB\-p\fP \fIlist\fP" Print the contents of the listed buffer(s) on stdout. The buffered data is printed exactly as it is stored in the server. Selecting two or more buffers has the effect of concatenating the data on stdout. The cut buffers are numbered from 0... onwards. The list can be either a single digit, a comma separated list of digits, a range of the form m\-n, or some combination of lists and ranges. The buffers are printed in listed order, so repeated numbers in the list can be used to duplicate buffer contents. .LP .IP "\fB\-r\fP \fIcount\fP" Rotate the buffers by \fIcount\fP positions. \fICount\fP can be any integer, positive or negative. This option may be used in conjunction with the \fB\-n\fP \fIcount\fP option to rotate a specific number of buffers. If the \fB\-n\fP option is not used, \fIxcb\fP will rotate the number of buffers given by the \fB.bufferCount\fP resource. .LP .IP "\fB\-s\fP \fIlist\fP" Store the data from stdin in the listed buffer(s). If the list refers to two or more buffers, the input data is duplicated in each buffer. Refer to the \fB\-p\fP option for the definition of a list. .LP .IP "\fB\-S\fP \fIlist\fP" Store the current PRIMARY selection data in the listed buffer(s). The data is converted to a string representation. If the list refers to two or more buffers, the PRIMARY selection is duplicated in each buffer. Refer to the \fB\-p\fP option for the definition of a list. Under the \-S option xcb waits for the nominated cut buffer's contents to change before exiting. If no change is detected within 3 seconds, xcb exits with a non-zero return code. .SH WIDGETS and RESOURCES The \fIxcb\fP widget hierarchy consists of a collection of custom buffer widgets, one per cut buffer. In the Athena version of the program, these buffer widgets are all contained within a single Athena form widget. In the Motif version of the program, they are each enclosed by Motif frame widgets, and the frame widgets are all contained within a single Motif RowColumn widget. .LP The names of the buffer widgets are "buffer0", "buffer1", "buffer2", .... etc., and their class name is "Buffer". Each buffer widget supports all the standard core widget resources, plus the \fB\.foreground\fP and \fB\.fontSet\fP resources. .LP Application wide resources are as follows: .br .sp 1 .nf \fB\.bufferCount\fP (default value 8) .in +8 This is the number of buffer widgets to create. Any number of widgets (greater than zero) can be created. .in -8 .sp 1 \fB\.layout\fP (default value "h") .in +8 Only the first character of the resource value is significant. This is the geometry arrangement to apply in the container widget. The layout can be "h" (horizontal), "v" (vertical), or some other value to disable the inbuilt geometry code and specify the layout via your X resources. An example is provided in the application default resources file. .in -8 .fi .SH EVENTS and TRANSLATIONS \fIXcb's\fP input semantics are coded into a Toolkit translation table. The default bindings have been chosen to conform with the default configuration of other cut and paste clients, such as xterm. The bindings may be altered or overridden according to your needs. The actions functions provided by \fIxcb\fP are:\- .br .sp 1 .ns .ta 16n .nf cut() causes the contents of the chosen cut buffer to become the PRIMARY selection. The window contents, if any, are highlighted, and can then be pasted into other cut buffers or applications. .sp 1 paste() causes the value of the PRIMARY selection to be converted into text and pasted into the chosen cut buffer, overwriting any previous buffer contents. If no PRIMARY selection is present, \fIxcb\fP pastes the contents of cut buffer zero into the chosen buffer. .sp 1 clear() clears the chosen cut buffer. .sp 1 rotate(NN) rotates the cut buffers by NN positions. NN may be any positive or negative number. .sp 1 refresh() causes the cut buffer window to be cleared and redrawn. .sp 1 selreq() this action function handles paste requests from other clients, or other \fIxcb\fP windows. It should always be bound to SelectionRequest events. .sp 1 selclear() this action function responds to the loss of ownership of the PRIMARY selection property. It should always be bound to SelectionClear events. .sp 1 quit() causes \fIxcb\fP to terminate. .fi .ta 8n .sp 1 The default bindings are as follows:\- .sp 1 .ta 20n .nf : cut() \\n\\ Shift : clear() \\n\\ : paste() \\n\\ Shift : rotate(-1) \\n\\ : rotate(1) \\n\\ Left: rotate(-1) \\n\\ Right: rotate(1) \\n\\ Up: rotate(-1) \\n\\ Down: rotate(1) \\n\\ q: quit() \\n\\ : selreq() \\n\\ : selclear() .fi .ta 8n .sp 1 .SH EXAMPLES The following are some examples of \fIxcb\fP task mode usage:\- .sp 1 xcb \-s 0\-7 < /dev/null .br This clears the first 8 cut buffers in your server. .sp 1 echo "G'day." | xcb \-display bigears:0.0 \-s 1,3,5,7 .br This loads the string "G'day." into four of the cut buffers on the display "bigears". .sp 1 xsendevent -win buffer5 '' .br This uses the program xsendevent to send a synthetic mouse click event to an xcb subwindow, thereby making that window the owner of the PRIMARY selection. .sp 1 ls \`xcb \-p 2,3\` .br This produces a listing of all the files named in cut buffers 2 and 3. .br .sp 1 xcb \-p 0\-7 | xcb \-s 0 .br This concatenates the values in the first 8 cut buffers, and places the result back in cut buffer zero. .sp 1 xcb -S 0 && xcb -p 0 .br The first command copies the current PRIMARY selection into the first cut buffer. If the copy succeeds, then the second command prints that data on stdout. .br .sp 1 .nf for i in 0 1 2 3 4 5 6 7 do xcb \-p $i > $HOME/.xcb/$i done for i in 0 1 2 3 4 5 6 7 do xcb \-s $i < $HOME/.xcb/$i done .fi This first loop saves the contents of each of the cut buffers in a separate file under your home directory. The second loop restores the cut buffer contents from those files. When placed in your .logout and .login scripts respectively, the commands are a simple method of preserving your cut buffers across login sessions. .sp 1 .nf function g { echo "$1\\\\c" | xcb \-s 7 grep "$@" } function vg { vi +/\`xcb \-p 7\` "$@" } .fi These two shell functions exemplify a simple mechanism for saving and reusing regular expressions. The first function saves the regex used for grep\-ing into cut buffer 7. The second function reuses the most recent grep regex as a search command in vi. There is considerable scope for expanding and improving these ideas. .SH SEE ALSO xterm(1), xcutsel(1), xclipboard(1), xprop(1) .br Athena Widget Set \- C Language Interface .br Motif Programmers Reference Guide .SH AUTHORS Current Maintainer (I18n version) .br Marc Lehmann .br E\-mail: pcg\@goof.com .br .sp 1 Original Author .br Farrell McKay .br E\-mail: Farrell.McKay\@mpx.com.au .br .sp 1 XView modifications provided by Danny Vanderryn .br E\-mail: dvanderr\@us.oracle.com .SH COPYRIGHT Copyright (C) 1992,1993,1994 by Farrell McKay. .br .sp 1 Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appears in all copies and that both that copyright notice and this permission notice appear in supporting documentation. This software is provided "as is" without express or implied warranty. .SH "BUGS :\-)" Xlib's underlying protocol for moving selection data between client and server can sometimes be slow, depending on the amount of data involved. Do not expect fast performance if your selections are big or you want to store big files in your cut buffers! ("big" means, say, over 10k bytes \- but your mileage may vary).