home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #27 / NN_1992_27.iso / spool / comp / sources / misc / 4097 < prev    next >
Encoding:
Text File  |  1992-11-19  |  50.5 KB  |  1,740 lines

  1. Newsgroups: comp.sources.misc
  2. Path: sparky!kent
  3. From: fbm@ptcburp.ptcbu.oz.au (Farrell McKay)
  4. Subject:  v33i092:  xcb-2.1 - X cut buffers, v2.1, Part01/01
  5. Message-ID: <1992Nov20.045437.12496@sparky.imd.sterling.com>
  6. Followup-To: comp.sources.d
  7. X-Md4-Signature: 7eb82da8ae07d187ea3e56a97db6fa70
  8. Keywords: X, cut and paste, cut buffers, pigeon holes
  9. Sender: kent@sparky.imd.sterling.com (Kent Landfield)
  10. Organization: Pyramid Technology Corporation
  11. Date: Fri, 20 Nov 1992 04:54:37 GMT
  12. Approved: kent@sparky.imd.sterling.com
  13. Lines: 1725
  14.  
  15. Submitted-by: fbm@ptcburp.ptcbu.oz.au (Farrell McKay)
  16. Posting-number: Volume 33, Issue 92
  17. Archive-name: xcb-2.1/part01
  18. Environment: X11
  19.  
  20. This is to announce the fourth release of xcb, an X11 program for
  21. providing easy access to your X server cut buffers.
  22.  
  23. This release fixes two (all) bugs reported in version 2.0 and provides
  24. a few minor enhancements.  The bug fixes are relevant to everyone
  25. who is already using xcb.  You can obtain xcb in any one of a number
  26. of ways.  See the README file below for full details.
  27.  
  28. Many thanks go to all those people who took the time to send
  29. back their comments/suggestions/patches after the last release.
  30. Keep that feedback rolling in!
  31.  
  32. And once again, *be warned*, using this program can be addictive.  :-)
  33.  
  34. Enjoy.
  35. Farrell.
  36.  --
  37.        -m-------  Farrell McKay,                   fbm@ptcburp.oz.au
  38.      ---mmm-----  Pyramid Technology Aust.,        ...!munnari!ptcburp.oz!fbm
  39.    -----mmmmm---  Research Park, Bond University,  +61 75 950256
  40.  -------mmmmmmm-  Gold Coast, Qld 4229, AUSTRALIA  +61 75 722475 FAX
  41. --------------------------------------------------------------------------------
  42. #! /bin/sh
  43. # This is a shell archive.  Remove anything before this line, then feed it
  44. # into a shell via "sh file" or similar.  To overwrite existing files,
  45. # type "sh file -c".
  46. # Contents:  README CHANGES Imakefile Makefile.std Xcb.ad ack cb.h
  47. #   patchlevel.h xcb.c xcb.man
  48. # Wrapped by kent@sparky on Wed Nov 18 22:28:53 1992
  49. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  50. echo If this archive is complete, you will see the following message:
  51. echo '          "shar: End of archive 1 (of 1)."'
  52. if test -f 'README' -a "${1}" != "-c" ; then 
  53.   echo shar: Will not clobber existing file \"'README'\"
  54. else
  55.   echo shar: Extracting \"'README'\" \(5412 characters\)
  56.   sed "s/^X//" >'README' <<'END_OF_FILE'
  57. X
  58. XWhat is xcb?
  59. X============
  60. XDo you ever wish you could cut two or more separate pieces of text
  61. Xat once from a window?  Do you ever need to save the output from one
  62. Xcommand for reuse in several subsequent tasks?  Do you ever find
  63. Xyourself wanting some easy means of globally exporting data, e.g.
  64. Xto a parent shell, to another xterm or application, or to another
  65. Xmachine or user?  If you answer yes to any of these questions, then
  66. Xxcb is for you.
  67. X
  68. XXcb provides access to the 8 cut buffers built into every X server.
  69. XIt allows the buffers to be manipulated either via the command line,
  70. Xor with the mouse in a point and click manner.  The buffers can be
  71. Xused as holding pens to store and retrieve arbitrary data fragments,
  72. Xso up to 8 different pieces of data can be saved and recalled later.
  73. XThe program is designed primarily for use with textual data.
  74. X
  75. X
  76. XWhat is so good about this release?
  77. X===================================
  78. XRelease 2.1 addresses two bugs found since the 2.0 release,
  79. Xboth of which are described in the CHANGES file.  A few minor
  80. Xenhancements and porting mods have been made to the code also.
  81. XThis is, in effect, a patch release.
  82. X
  83. X
  84. XYes, but has it been ported to WHIZ-IX 12.1A.00x, on SRS-80 27-bit CPUs?
  85. X========================================================================
  86. XXcb has been ported to a wide variety of sites and systems.
  87. XIn no particular order, the machines and operating systems known
  88. Xto be running xcb include:-
  89. X
  90. X    o  OSx (5.1a)  -  Pyramid MIS-2/02
  91. X    o  DC/OSx (1.0)  -  Pyramid MIServer-S 1/32 r3000
  92. X    o  AT&T SYSV (SVR3.2, SVR4)  -  i386, DG Aviion 5200
  93. X    o  HP-UX (lots of versions)  -  HP 9000/710,720,730,750
  94. X    o  SunOS (4.1)  -  Sun3, Sun4, Solbourne Series5, SPARCstations
  95. X    o  SPARC/OS (1.1)
  96. X    o  Irix (4.0)  -  SGI
  97. X    o  ULTRIX (4.2)  -  DECstations
  98. X    o  UNICOS (6.1)  -  Cray Y-MP
  99. X    o  ConvexOS (10.0.2)  -  Convex 3100
  100. X    o  DYNIX (V3.0.17.10)  -  Sequent Symmetry S81
  101. X    o  AIX (3.2)  -  RS6000
  102. X    o  RISC/os (4.52)  -  MIPS
  103. X    o  Domain/OS (10.4)  -  Apollo DN3000, 3500, 4500, 5500
  104. X    o  Linux (0.96b)  -  i386
  105. X    o  VMS (5.5)
  106. X
  107. X
  108. XXcb has been written to compile using both ANSI and non-ANSI compilers.
  109. XIt is in use in X11 R3, R4 and R5 environments.  The current version
  110. Xis built on top of the Athena widgets (libXaw.a) and the X Toolkit library
  111. X(libXt.a).  If you do not have the Athena widgets on your machine, and
  112. Xyou do not wish to install them, then you may want to revert to version
  113. X1.1 of xcb.  Version 1.1 has a smaller feature set, but is based only
  114. Xthe X11 library (libX11.a), so is more portable.
  115. X
  116. X
  117. XOk, where is it available?
  118. X==========================
  119. XVersions of xcb can be obtained.....
  120. X
  121. X    o  from the comp.sources.misc newsgroup, or any of its archive sites.
  122. X    o  by ftp, from export.lcs.mit.edu in the file contrib/xcb-2.1.tar.Z,
  123. X    o  by ftp, from any of the sites that mirror export.lcs.mit.edu
  124. X       (Australian users look for ./X11/contrib/xcb-2.1.tar.Z on archie.au).
  125. X    o  by sending me an email message.
  126. X
  127. X
  128. XSo, it will compile, will it?
  129. X=============================
  130. XYes!  The only compile time switch in the source is -DXVIEW.  If you
  131. Xwish to cut and paste text between xcb and XView applications, you
  132. Xshould add this switch to the Imakefile or Makefile.std.
  133. X
  134. XAT&T SVR4 sites need libnsl.a during linking.  If you are using
  135. XSVR4, and you don't like Imakefiles, you will need to add -lnsl to the
  136. XLIBS in Makefile.std.
  137. X
  138. XHP-UX users may find that the Athena widgets are not installed on their
  139. Xmachine, even though the components are freely available as part of the
  140. XMIT X11 distribution.  There is an HP maintained, but unsupported, set
  141. Xof X11R4 libraries and utilities (including the Athena widgets) for the
  142. XHP 9000 Series 300, 400, 700, and 800.  You can get the libraries,
  143. Xinclude files, and config files (imake) via anonymous FTP from
  144. Xhpcvaaz.cv.hp.com (15.255.72.15) - look for pub/MitX11R4/libs.s*00.tar.Z
  145. X
  146. XAIX 3.2 users may find their Athena components are installed in a
  147. Xnon-standard place.  Check the directory /usr/lpp/X11/Xamples/lib/Xaw.
  148. X
  149. XVMS and ULTRIX users may find their Athena components are installed in
  150. Xa non-standard place too.  Check the directory /usr/include/mit for the
  151. XAthena include files.
  152. X
  153. X
  154. XAnd how do I set the thing up?
  155. X==============================
  156. XThat is pretty easy too.  Once you have compiled the program,
  157. Xyou can start using it straight away - just put it in your favourite
  158. Xbin directory.  The program contains fallback resources so that it will
  159. Xbehave itself even if there are no X resource specifications for it to
  160. Xfeed on.  To install the program, plus its application defaults file, and
  161. Xthe man page, simply type 'make install install.man', after checking
  162. Xthe target directories for the install in the Imakefile/Makefile.std.
  163. X
  164. X
  165. XWho is to blame?  Where do I send complaints?
  166. X=============================================
  167. XBlame me.  The xcb factory is in the sunny Gold Coast region of
  168. XQueensland, Australia.  Don't bother trying to find us - even
  169. Xthe postman has trouble getting here sometimes.
  170. X
  171. XIf you ever get around to compiling and installing xcb on your machine,
  172. Xplease tell me.  I am interested in tracking the size of xcb's user base.
  173. XI am also interested in bug reports, porting problems, comments,
  174. Xsuggestions, patches, etc. etc.  If typing a mail message seems like
  175. Xtoo much bother to you, then just run the "ack" script enclosed.  It
  176. Xwill do all the work for you.
  177. X
  178. XEnjoy.
  179. XFarrell McKay (fbm@ptcburp.ptcbu.oz.au)
  180. XNovember 1992
  181. END_OF_FILE
  182.   if test 5412 -ne `wc -c <'README'`; then
  183.     echo shar: \"'README'\" unpacked with wrong size!
  184.   fi
  185.   # end of 'README'
  186. fi
  187. if test -f 'CHANGES' -a "${1}" != "-c" ; then 
  188.   echo shar: Will not clobber existing file \"'CHANGES'\"
  189. else
  190.   echo shar: Extracting \"'CHANGES'\" \(2182 characters\)
  191.   sed "s/^X//" >'CHANGES' <<'END_OF_FILE'
  192. X
  193. XVersion 2.1 (patchlevel 1):
  194. X    o  Added the WM_DELETE_WINDOW protocol.
  195. X    o  Bug fix: on some platforms (SunOS, ULTRIX and VMS) xcb could
  196. X       not hand off the PRIMARY selection between its own windows,
  197. X       so windows remained highlighted, and could not be re-selected.
  198. X    o  Bug fix: rotating the buffers when using fewer than 8 cut
  199. X       buffer windows, either via mouse button 3 or via the arrow
  200. X       keys, caused the program to dump core.
  201. X
  202. XVersion 2.0 (patchlevel 0):
  203. X    o  Went to an Xaw and Xt based implementation.  Many pros and
  204. X       cons to this decision.  Some of the pros:  standardized
  205. X       support for Toolkit command line switches, support for
  206. X       resource specifications .Xdefaults app-defaults files etc.,
  207. X       control over individual subwindow sizes, placement, 
  208. X       translations etc.  Some of the cons: program is noticeably
  209. X       fatter and slower (Booo, hiss).
  210. X    o  User selectable number of cut buffers - any number from
  211. X       1 upwards; no longer limited to 8.
  212. X    o  Added code for compatibility with XView 2.0 and 3.0 applications
  213. X       (code provided Danny Vanderryn; thanks Danny!).
  214. X    o  Added XIO error handler for graceful shutdown when killed.
  215. X    o  Changed list processing for '-p' and '-s' options so that
  216. X       list order and duplicates are significant.
  217. X
  218. XVersion 1.1 (patchlevel 1):
  219. X    o  Added WM_CLASS hints to the client properties.  This fixed
  220. X       failures by some window managers (e.g. mwm, olwm) to honour
  221. X       client decoration directives.
  222. X    o  Removed 9x15bold default font specification (sigh, reluctantly).
  223. X    o  #include <stdlib.h> directive is now conditional upon __STDC__.
  224. X    o  Added another example to the man page.
  225. X    o  Several porting changes to Imakefile and Makefile.std
  226. X    o  Fallback geometry in vertical mode altered to give a tall, thin 
  227. X       window size.
  228. X    o  Support for non-standard implementations of realloc() added, i.e.
  229. X       '-s' option never passes a NULL pointer value to realloc() now.
  230. X    o  Function declarations rewritten for compilation in both
  231. X       ANSI and non-ANSI environments.
  232. X    o  usage() string concatenated.
  233. X    o  Warnings/complaints from some compilers re parameter type 
  234. X       mismatch in XChangeProperty() calls fixed.
  235. X
  236. XVersion 1.0:
  237. X    o  Initial version
  238. END_OF_FILE
  239.   if test 2182 -ne `wc -c <'CHANGES'`; then
  240.     echo shar: \"'CHANGES'\" unpacked with wrong size!
  241.   fi
  242.   # end of 'CHANGES'
  243. fi
  244. if test -f 'Imakefile' -a "${1}" != "-c" ; then 
  245.   echo shar: Will not clobber existing file \"'Imakefile'\"
  246. else
  247.   echo shar: Extracting \"'Imakefile'\" \(311 characters\)
  248.   sed "s/^X//" >'Imakefile' <<'END_OF_FILE'
  249. X
  250. XDEPLIBS        = $(DEPXALIB) $(DEPXMULIB) $(DEPXTOOLLIB) $(DEPXLIB)
  251. XLOCAL_LIBRARIES    = $(XAWLIB) $(XMULIB) $(XTOOLLIB) $(XLIB)
  252. XSYS_LIBRARIES    = 
  253. XSRCS        = xcb.c
  254. XOBJS        = xcb.o
  255. X
  256. X# Add your favourite compiler flags here.
  257. X#
  258. XDEFINES        = # -DXVIEW            # If you use XView apps.
  259. X
  260. XComplexProgramTarget(xcb)
  261. X
  262. XInstallAppDefaults(Xcb)
  263. END_OF_FILE
  264.   if test 311 -ne `wc -c <'Imakefile'`; then
  265.     echo shar: \"'Imakefile'\" unpacked with wrong size!
  266.   fi
  267.   # end of 'Imakefile'
  268. fi
  269. if test -f 'Makefile.std' -a "${1}" != "-c" ; then 
  270.   echo shar: Will not clobber existing file \"'Makefile.std'\"
  271. else
  272.   echo shar: Extracting \"'Makefile.std'\" \(1104 characters\)
  273.   sed "s/^X//" >'Makefile.std' <<'END_OF_FILE'
  274. X#
  275. X# $Header: /home/fbm/src/misc+/xcb/RCS/Makefile.std,v 1.9 1992/11/18 07:00:11 fbm Exp $
  276. X
  277. XINCS    =    
  278. X#INCS    =    -I/usr/include/mit            # ULTRIX may need this
  279. XHDRS    =    cb.h patchlevel.h
  280. XSRCS    =    xcb.c
  281. XOBJS    =    xcb.o
  282. XMISC    =    README CHANGES xcb.man Xcb.ad ack Imakefile Makefile.std
  283. XSHARS    =    $(MISC) $(SRCS) $(HDRS)
  284. X
  285. X# Add your favourite compiler flags here.
  286. X#
  287. XCFLAGS    =    $(INCS) -O # -DXVIEW
  288. XLDFLAGS =    
  289. X#LDFLAGS=    -L /usr/lpp/X11/Xamples/lib/Xaw        # AIX 3.2 may need this
  290. X
  291. X# These are the libraries required for linking.
  292. X#
  293. XLIBS    =    -lXaw -lXmu -lXt -lXext -lX11
  294. X#LIBS    =    -lXaw -lXmu -lXt -lXext -lX11 -lnsl    # SVR4 needs libnsl.a
  295. X
  296. Xall:    xcb
  297. X
  298. Xxcb:    $(OBJS)
  299. X    $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
  300. X
  301. X# You will need to check and possibly adjust the target
  302. X# directories for these install rules.
  303. X#
  304. Xinstall: xcb
  305. X    install -c xcb /usr/bin/X11
  306. X    install -c -m 0644 -o bin -g bin Xcb.ad /usr/lib/X11/app-defaults/Xcb
  307. X
  308. Xinstall.man:
  309. X    install -c -m 0644 -o bin -g bin xcb.man /usr/share/man/mrd/man1/xcb.1
  310. X
  311. Xclean clobber:
  312. X    rm -f *.o xcb
  313. X
  314. Xtags ctags:    $(HDRS) $(SRCS)
  315. X    ctags -tw $(HDRS) $(SRCS)
  316. X
  317. Xshar:
  318. X    shar -c -f part -p -x X $(SHARS)
  319. END_OF_FILE
  320.   if test 1104 -ne `wc -c <'Makefile.std'`; then
  321.     echo shar: \"'Makefile.std'\" unpacked with wrong size!
  322.   fi
  323.   # end of 'Makefile.std'
  324. fi
  325. if test -f 'Xcb.ad' -a "${1}" != "-c" ; then 
  326.   echo shar: Will not clobber existing file \"'Xcb.ad'\"
  327. else
  328.   echo shar: Extracting \"'Xcb.ad'\" \(1934 characters\)
  329.   sed "s/^X//" >'Xcb.ad' <<'END_OF_FILE'
  330. X
  331. X! Xcb application defaults resource file.
  332. X! ======================================================================
  333. X
  334. X! The xcb widget hierarchy consists of a number of custom buffer
  335. X! widgets contained within a single Athena form widget.
  336. X! The widget names and classes are as follows:
  337. X!
  338. X! buffer widgets    name = "buffer<NN>"    class = "Buffer"
  339. X! form widget       name = "container"     class = "Form"
  340. X!
  341. X! Buffer widgets are numbered from 0... onwards, and are named accordingly.
  342. X! As well as the standard core resources, each buffer widget supports
  343. X! resources for "foreground" and "font".
  344. X
  345. X! Application wide resources are as follows:
  346. X!
  347. X! "bufferCount" (default value 8)
  348. X!    This is the number of buffer widgets to create.
  349. X!    Any number of widgets (greater than zero) can be created.
  350. X!
  351. X! "layout" (default value "h")
  352. X!    Only the first character of the resource value is significant.
  353. X!    This is the geometry arrangement to apply in the form widget.
  354. X!    The layout can be "h" (horizontal), "v" (vertical), or some
  355. X!    other value to disable the geometry code and allow you to build
  356. X!    your own custom layout scheme.  An example is provided below.
  357. X!    Refer to the "Athena Widget Set" manual for further details.
  358. X
  359. XXcb.bufferCount:        8
  360. XXcb.layout:            horizontal
  361. XXcb*font:            fixed
  362. XXcb*borderWidth:        1
  363. XXcb*container.defaultDistance:    0
  364. XXcb*Buffer.width:        60
  365. XXcb*Buffer.height:        60
  366. X
  367. X! Below is an example of a layout scheme which arranges
  368. X! 10 cut buffer widgets in two rows of 5 windows.
  369. X!
  370. X!Xcb.bufferCount:        10
  371. X!Xcb.layout:            custom
  372. X!Xcb*buffer1.fromHoriz:        buffer0
  373. X!Xcb*buffer2.fromHoriz:        buffer1
  374. X!Xcb*buffer3.fromHoriz:        buffer2
  375. X!Xcb*buffer4.fromVert:        buffer0
  376. X!Xcb*buffer5.fromHoriz:        buffer4
  377. X!Xcb*buffer5.fromVert:        buffer1
  378. X!Xcb*buffer6.fromHoriz:        buffer5
  379. X!Xcb*buffer6.fromVert:        buffer2
  380. X!Xcb*buffer7.fromHoriz:        buffer6
  381. X!Xcb*buffer7.fromVert:        buffer3
  382. X!Xcb*buffer8.fromHoriz:        buffer7
  383. X!Xcb*buffer9.fromHoriz:        buffer8
  384. END_OF_FILE
  385.   if test 1934 -ne `wc -c <'Xcb.ad'`; then
  386.     echo shar: \"'Xcb.ad'\" unpacked with wrong size!
  387.   fi
  388.   # end of 'Xcb.ad'
  389. fi
  390. if test -f 'ack' -a "${1}" != "-c" ; then 
  391.   echo shar: Will not clobber existing file \"'ack'\"
  392. else
  393.   echo shar: Extracting \"'ack'\" \(582 characters\)
  394.   sed "s/^X//" >'ack' <<'END_OF_FILE'
  395. X#!/bin/sh
  396. X
  397. X# Simple minded little shell script to send an
  398. X# acknowledgment message back to the factory.
  399. X
  400. X# Some people are upset by this script.  Don't worry!
  401. X# It is nothing more than a very rough way of surveying
  402. X# a group of people, a group of machines, and the sizes
  403. X# of those machines.  No invasion of privacy is intended.
  404. X
  405. X(
  406. X    echo "Xcb 2.1 has been installed here."
  407. X    echo "who am i:" `who am i`
  408. X    echo "id      :" `id`
  409. X    echo "uname   :" `uname -a`
  410. X    echo "hostname:" `hostname`
  411. X    echo "#users  :" `wc /etc/passwd`
  412. X
  413. X) 2>/dev/null | mail fbm@ptcburp.ptcbu.oz.au && echo Mail sent
  414. END_OF_FILE
  415.   if test 582 -ne `wc -c <'ack'`; then
  416.     echo shar: \"'ack'\" unpacked with wrong size!
  417.   fi
  418.   chmod +x 'ack'
  419.   # end of 'ack'
  420. fi
  421. if test -f 'cb.h' -a "${1}" != "-c" ; then 
  422.   echo shar: Will not clobber existing file \"'cb.h'\"
  423. else
  424.   echo shar: Extracting \"'cb.h'\" \(1012 characters\)
  425.   sed "s/^X//" >'cb.h' <<'END_OF_FILE'
  426. X/*
  427. X * xcb: Copyright (C) 1992 by Farrell McKay.
  428. X *
  429. X * Permission to use, copy, modify, and distribute this software and its
  430. X * documentation for any purpose and without fee is hereby granted, provided
  431. X * that the above copyright notice appears in all copies and that both that
  432. X * copyright notice and this permission notice appear in supporting
  433. X * documentation.  This software is provided "as is" without express or
  434. X * implied warranty.
  435. X *
  436. X * This header file contains the definitions and typedefs
  437. X * for the custom cut buffer widget.
  438. X */
  439. X#ifndef _cb_h
  440. X#define _cb_h
  441. X
  442. X#include <X11/IntrinsicP.h>        /* needed for CorePart et.al.*/
  443. X
  444. X#define    XtNatom                "atom"
  445. X#define    XtCAtom                "Atom"
  446. X
  447. X
  448. Xtypedef struct _CbClassRec {
  449. X    CoreClassPart    core_class;
  450. X} CbClassRec, *CbWidgetClass;
  451. X
  452. Xtypedef struct _CbRec {
  453. X    CorePart    core;
  454. X    Pixel        fgnd;
  455. X    XFontStruct    *font;
  456. X    int        font_width;
  457. X    int        font_height;
  458. X    GC        gc;
  459. X    GC        gc_inv;
  460. X    Atom        atom;
  461. X} CbRec, *CbWidget;
  462. X
  463. X
  464. Xextern WidgetClass    cbWidgetClass;
  465. Xextern CbClassRec    cbClassRec;
  466. X
  467. X#endif
  468. END_OF_FILE
  469.   if test 1012 -ne `wc -c <'cb.h'`; then
  470.     echo shar: \"'cb.h'\" unpacked with wrong size!
  471.   fi
  472.   # end of 'cb.h'
  473. fi
  474. if test -f 'patchlevel.h' -a "${1}" != "-c" ; then 
  475.   echo shar: Will not clobber existing file \"'patchlevel.h'\"
  476. else
  477.   echo shar: Extracting \"'patchlevel.h'\" \(95 characters\)
  478.   sed "s/^X//" >'patchlevel.h' <<'END_OF_FILE'
  479. X
  480. X/* PATCHLEVEL: 1 */
  481. X
  482. Xstatic char    version[] = "@(#) Xcb 2.1 pl1 $Date: 1992/11/18 07:23:08 $";
  483. END_OF_FILE
  484.   if test 95 -ne `wc -c <'patchlevel.h'`; then
  485.     echo shar: \"'patchlevel.h'\" unpacked with wrong size!
  486.   fi
  487.   # end of 'patchlevel.h'
  488. fi
  489. if test -f 'xcb.c' -a "${1}" != "-c" ; then 
  490.   echo shar: Will not clobber existing file \"'xcb.c'\"
  491. else
  492.   echo shar: Extracting \"'xcb.c'\" \(22716 characters\)
  493.   sed "s/^X//" >'xcb.c' <<'END_OF_FILE'
  494. X/*
  495. X * xcb: Copyright (C) 1992 by Farrell McKay.
  496. X * XView modifications provided by Danny Vanderryn.
  497. X *
  498. X * Simple X interface to the cut buffers in an X server.
  499. X * The program creates a window subdivided into a number of subwindows,
  500. X * one per cut buffer.  The user may copy cut buffer contents around
  501. X * using mouse buttons 1 and 2, or rotate the buffers using mouse
  502. X * button 3.  Buffers may be cleared by using Shift-button 2.
  503. X *
  504. X * Note that this program assumes the cut buffers contain textual
  505. X * information, and displays buffer contents using the XDrawString
  506. X * function.  It is not suitable for use in any other environment.
  507. X *
  508. X * Permission to use, copy, modify, and distribute this software and its
  509. X * documentation for any purpose and without fee is hereby granted, provided
  510. X * that the above copyright notice appears in all copies and that both that
  511. X * copyright notice and this permission notice appear in supporting
  512. X * documentation.  This software is provided "as is" without express or
  513. X * implied warranty.
  514. X */
  515. X#include <ctype.h>
  516. X#include <stdio.h>
  517. X#include <string.h>            /* for strcmp() */
  518. X#ifdef __STDC__
  519. X#include <stdlib.h>            /* for exit()... */
  520. X#endif
  521. X#ifndef VMS
  522. X#include <unistd.h>            /* for read(), write() */
  523. X#endif
  524. X#include <X11/Xatom.h>            /* for pre-defined atom names */
  525. X#include <X11/StringDefs.h>        /* for XtNforeground et.al.*/
  526. X#include <X11/Intrinsic.h>
  527. X#ifndef VMS
  528. X#include <X11/Xaw/Form.h>
  529. X#else
  530. X#include <Xaw/Form.h>
  531. X#endif
  532. X
  533. X#include "cb.h"
  534. X#include "patchlevel.h"
  535. X
  536. X#define    _printf        (void) printf
  537. X#define    _fprintf    (void) fprintf
  538. X#define    _sprintf    (void) sprintf
  539. X
  540. X#define    eq(a,b)        (strcmp((a),(b)) == 0)
  541. X#define    min(a,b)    ((a) < (b)? (a): (b))
  542. X#define    max(a,b)    ((a) > (b)? (a): (b))
  543. X
  544. X#define    XtNbufferCount    "bufferCount"        /* Application resources */
  545. X#define    XtCBufferCount    "BufferCount"
  546. X#define    XtNlayout    "layout"
  547. X#define    XtCLayout    "Layout"
  548. X
  549. X#define    PGM_NAME    "xcb"
  550. X#define    PGM_CLASS    "Xcb"
  551. X#define    BUFINC        2048
  552. X
  553. Xstatic Display        *dpy;
  554. Xstatic Window        root;
  555. Xstatic XtAppContext    app;
  556. Xstatic Widget        top, box, *wdg;
  557. Xstatic Atom        delwin;
  558. Xstatic Atom        *atom;
  559. Xstatic int        natoms, nbuffs;
  560. Xstatic Window        seln;
  561. X
  562. X#ifdef XVIEW
  563. Xstatic Atom        caret, clipboard, yield;
  564. Xstatic Atom        length, lengthc;
  565. Xstatic Atom        text, ctext;
  566. X#endif
  567. X
  568. X
  569. X/*
  570. X * Fetch the contents of cut buffer n from the root window.
  571. X */
  572. Xstatic char *
  573. Xfetch_buffer(a, nb)
  574. XAtom    a;
  575. Xint    *nb;
  576. X{
  577. X    Atom        actl_type;
  578. X    int        actl_format;
  579. X    unsigned long    nitems, after;
  580. X    char        *data;
  581. X
  582. X    *nb = 0;
  583. X    if (XGetWindowProperty(dpy, root, a,
  584. X            0L, 10000000L, False, XA_STRING,
  585. X            &actl_type, &actl_format, &nitems,
  586. X            &after, (unsigned char **) &data) != Success)
  587. X        return NULL;
  588. X
  589. X    if (actl_type == XA_STRING && actl_format != 32) {
  590. X        *nb = nitems;
  591. X        return data;
  592. X    }
  593. X    if (data != NULL)
  594. X        XFree(data);
  595. X    return NULL;
  596. X}
  597. X
  598. X/*
  599. X * Store the string p into cut buffer n on the root window.
  600. X */
  601. Xstatic void
  602. Xstore_buffer(p, nb, atom)
  603. Xchar    *p;
  604. Xint    nb;
  605. XAtom    atom;
  606. X{
  607. X    XChangeProperty(dpy, root, atom, XA_STRING,
  608. X        8, PropModeReplace, (unsigned char *) p, nb);
  609. X}
  610. X
  611. X/*
  612. X * Add an atom to the program's atom cache.
  613. X */
  614. Xstatic Atom
  615. Xget_atom(n, ifexists)
  616. Xint    n, ifexists;
  617. X{
  618. X    char    tmp[32];
  619. X
  620. X    if (n >= natoms) {
  621. X        atom = (Atom *) XtRealloc((char *) atom, (n+1) * sizeof(Atom));
  622. X        while (natoms < n+1)
  623. X            atom[natoms++] = 0;
  624. X    }
  625. X    if (!atom[n]) {
  626. X        _sprintf(tmp, "CUT_BUFFER%d", n);
  627. X        atom[n] = XInternAtom(dpy, tmp, (Bool) ifexists);
  628. X    }
  629. X    return atom[n];
  630. X}
  631. X
  632. X/*
  633. X * Draw a string in the window with top-left corner justification.
  634. X */
  635. Xstatic void
  636. Xplace_text(cb, str, len, y)
  637. XCbWidget    cb;
  638. Xchar        *str;
  639. Xint        len, y;
  640. X{
  641. X    int    cols;
  642. X    GC    gc;
  643. X
  644. X    gc = (cb->core.window == seln)? cb->gc_inv: cb->gc;
  645. X    if (y <= (int) cb->core.height) {
  646. X        cols = ((int) cb->core.width + cb->font_width - 1)
  647. X                        / cb->font_width;
  648. X        len = min(len, cols);
  649. X        if (len > 0) {
  650. X            y += cb->font->ascent;
  651. X            XDrawImageString(dpy, cb->core.window, gc,
  652. X                        0, y, str, len);
  653. X        }
  654. X    }
  655. X}
  656. X
  657. X/*
  658. X * ============================================================================
  659. X * The following collection of functions and data structures define
  660. X * the cb widget.  Each cb widget displays a single cut buffer value
  661. X * in a window, and provides cut and paste access to that buffer.
  662. X */
  663. X
  664. Xstatic void
  665. Xcb_initialize(req, wdg, args, nargs)                /*ARGSUSED*/
  666. XWidget        req, wdg;
  667. XArgList        args;
  668. XCardinal    *nargs;
  669. X{
  670. X    CbWidget    cb    = (CbWidget) wdg;
  671. X
  672. X    cb->font_width = cb->font->max_bounds.width;
  673. X    cb->font_height = cb->font->ascent + cb->font->descent;
  674. X    cb->gc = 0;
  675. X    cb->gc_inv = 0;
  676. X
  677. X    XChangeProperty(dpy, root, cb->atom, XA_STRING,
  678. X        8, PropModeAppend, (unsigned char *) "", 0);
  679. X}
  680. X
  681. Xstatic void
  682. Xcb_realize(wdg, mask, attrs)
  683. XWidget            wdg;
  684. XXtValueMask        *mask;
  685. XXSetWindowAttributes    *attrs;
  686. X{
  687. X    CbWidget    cb    = (CbWidget) wdg;
  688. X    XtGCMask    v_mask    = 0L;
  689. X    XGCValues    values;
  690. X
  691. X    XtCreateWindow(wdg, InputOutput, CopyFromParent, *mask, attrs);
  692. X
  693. X    values.font = cb->font->fid;
  694. X    values.foreground = cb->fgnd;
  695. X        values.background = cb->core.background_pixel;
  696. X    v_mask = GCFont | GCForeground | GCBackground;
  697. X    cb->gc = XtGetGC(wdg, v_mask, &values);
  698. X
  699. X        values.foreground = cb->core.background_pixel;
  700. X    values.background = cb->fgnd;
  701. X    cb->gc_inv = XtGetGC(wdg, v_mask, &values);
  702. X}
  703. X
  704. X/*
  705. X * Redraw the contents of one of the subwindows.
  706. X * The function assumes the cut buffer contains text data, and parses
  707. X * it accordingly.  The data is split into lines at each '\n' character.
  708. X * Lines which extend beyond the subwindow's borders are clipped; no
  709. X * wrap-around processing is done.
  710. X * Keep it simple.
  711. X */
  712. Xstatic void
  713. Xcb_redisplay(wdg, event, region)                /*ARGSUSED*/
  714. XWidget        wdg;
  715. XXEvent        *event;
  716. XRegion        region;
  717. X{
  718. X    CbWidget    cb    = (CbWidget) wdg;
  719. X    char         *p, *pp, *base;
  720. X    int        y, nbytes;
  721. X
  722. X    y = 0;
  723. X    p = pp = base = fetch_buffer(cb->atom, &nbytes);
  724. X    while (pp < base + nbytes) {
  725. X        if (*pp == '\n') {
  726. X            place_text(cb, p, pp - p, y);
  727. X            p = pp + 1;
  728. X            y += cb->font_height;
  729. X        }
  730. X        pp++;
  731. X    }
  732. X    place_text(cb, p, pp - p, y);
  733. X    XFree(base);
  734. X}
  735. X
  736. Xstatic void
  737. Xcb_destroy(wdg)
  738. XWidget    wdg;
  739. X{
  740. X    CbWidget    cb    = (CbWidget) wdg;
  741. X
  742. X    XtReleaseGC(wdg, cb->gc);
  743. X    XtReleaseGC(wdg, cb->gc_inv);
  744. X}
  745. X
  746. X/*
  747. X * Make this widget the owner of the PRIMARY selection.
  748. X * The window contents are then redrawn with highlighting.
  749. X *
  750. X * It seems that if a XSetSelectionOwner is performed on a client's
  751. X * window, no SelectionClear event is generated if another window
  752. X * within the same client is already the selection owner.
  753. X * This function originally attempted to avoid that problem and force
  754. X * a SelectionClear event by firstly setting the selection ownership
  755. X * to None and then setting it to this widget's window.  Apparently
  756. X * that didn't work for all X servers.
  757. X *
  758. X * Therefore the function must do the SelectionClear logic itself,
  759. X * which means it must know when another xcb widget has selection
  760. X * ownership, which brings about the need for the 'seln' global variable.
  761. X * This breaks all the rules for object oriented widgets.  Disgusting, no?
  762. X */
  763. Xstatic void
  764. Xcb_cut(wdg, event, parms, nparms)                /*ARGSUSED*/
  765. XWidget        wdg;
  766. XXEvent        *event;
  767. XString        *parms;
  768. XCardinal    *nparms;
  769. X{
  770. X    CbWidget    cb    = (CbWidget) wdg;
  771. X    Window        win    = cb->core.window;
  772. X    Window        w, tmp;
  773. X
  774. X    if (win == seln)
  775. X        return;
  776. X
  777. X    XSetSelectionOwner(dpy, XA_PRIMARY, win, event->xbutton.time);
  778. X    w = XGetSelectionOwner(dpy, XA_PRIMARY);
  779. X    if (seln && w != seln) {
  780. X        tmp = seln;
  781. X        seln = 0;
  782. X        XClearArea(dpy, tmp, 0,0,0,0, False);
  783. X        cb_redisplay(XtWindowToWidget(dpy,tmp), (XEvent *)0, (Region)0);
  784. X    }
  785. X    
  786. X    if (w == win) {
  787. X        seln = win;
  788. X        XClearArea(dpy, win, 0,0,0,0, False);
  789. X        cb_redisplay(wdg, (XEvent *)0, (Region)0);
  790. X#ifdef XVIEW
  791. X        XSetSelectionOwner(dpy, caret, win, event->xbutton.time);
  792. X        XSetSelectionOwner(dpy, clipboard, win, event->xbutton.time);
  793. X#endif
  794. X    }
  795. X}
  796. X
  797. Xstatic void
  798. Xcb_paste(wdg, event, parms, nparms)                /*ARGSUSED*/
  799. XWidget        wdg;
  800. XXEvent        *event;
  801. XString        *parms;
  802. XCardinal    *nparms;
  803. X{
  804. X    CbWidget    cb    = (CbWidget) wdg;
  805. X    Window        w;
  806. X    char        *ptr;
  807. X    int        n;
  808. X
  809. X    w = XGetSelectionOwner(dpy, XA_PRIMARY);
  810. X    if (w == None) {
  811. X        ptr = fetch_buffer(atom[0], &n);    /* copy from cb0 */
  812. X        store_buffer(ptr, n, cb->atom);
  813. X        XFree(ptr);
  814. X    }
  815. X    else if (w != cb->core.window)
  816. X        XConvertSelection(dpy, XA_PRIMARY, XA_STRING,
  817. X                cb->atom, root, event->xbutton.time);
  818. X}
  819. X
  820. Xstatic void
  821. Xcb_clear(wdg, event, parms, nparms)                /*ARGSUSED*/
  822. XWidget        wdg;
  823. XXEvent        *event;
  824. XString        *parms;
  825. XCardinal    *nparms;
  826. X{
  827. X    CbWidget    cb    = (CbWidget) wdg;
  828. X    Window        win    = cb->core.window;
  829. X
  830. X    store_buffer("", 0, cb->atom);
  831. X    if (win == seln) {
  832. X        seln = 0;
  833. X        XSetSelectionOwner(dpy, XA_PRIMARY, None, event->xbutton.time);
  834. X    }
  835. X}
  836. X
  837. Xstatic void
  838. Xcb_rotate(wdg, event, parms, nparms)                /*ARGSUSED*/
  839. XWidget        wdg;
  840. XXEvent        *event;
  841. XString        *parms;
  842. XCardinal    *nparms;
  843. X{
  844. X    int    n = 0;
  845. X
  846. X    if (*nparms > 0)
  847. X        n = atoi(parms[0]);
  848. X    if (n != 0)
  849. X        XRotateWindowProperties(dpy, root, atom, nbuffs, n);
  850. X}
  851. X
  852. Xstatic void
  853. Xcb_quit(wdg, event, parms, nparms)                /*ARGSUSED*/
  854. XWidget        wdg;
  855. XXEvent        *event;
  856. XString        *parms;
  857. XCardinal    *nparms;
  858. X{
  859. X    exit(0);
  860. X}
  861. X
  862. X/*
  863. X * Clear and redraw the widget's window.
  864. X */
  865. Xstatic void
  866. Xcb_refresh(wdg, event, parms, nparms)                /*ARGSUSED*/
  867. XWidget        wdg;
  868. XXEvent        *event;
  869. XString        *parms;
  870. XCardinal    *nparms;
  871. X{
  872. X    XClearArea(dpy, wdg->core.window, 0,0,0,0, False);
  873. X    cb_redisplay(wdg, (XEvent *)0, (Region)0);
  874. X}
  875. X
  876. X/*
  877. X * Someone or something wants a copy of the current PRIMARY selection.
  878. X * Such a request is only satisfied if the target type is STRING.
  879. X * (No conversion facilities are provided by this program).
  880. X * The selection request is met by copying the current contents
  881. X * of the cut buffer to the target window+atom.
  882. X */
  883. Xstatic void
  884. Xcb_selreq(wdg, event, parms, nparms)                /*ARGSUSED*/
  885. XWidget        wdg;
  886. XXEvent        *event;
  887. XString        *parms;
  888. XCardinal    *nparms;
  889. X{
  890. X    int            nbytes;
  891. X    char            *ptr;
  892. X    XSelectionEvent        notify;
  893. X    XSelectionRequestEvent    *rq;
  894. X    CbWidget        cb    = (CbWidget) wdg;
  895. X    Window            win    = cb->core.window;
  896. X#ifdef XVIEW
  897. X    unsigned long        data;
  898. X#endif
  899. X
  900. X    rq = (XSelectionRequestEvent *) event;
  901. X
  902. X    notify.type = SelectionNotify;
  903. X    notify.display = rq->display;
  904. X    notify.requestor = rq->requestor;
  905. X    notify.selection = rq->selection;
  906. X    notify.target = rq->target;
  907. X    notify.property = None;
  908. X    notify.time = rq->time;
  909. X
  910. X#ifdef XVIEW
  911. X        if (rq->selection == XA_PRIMARY) {
  912. X        if (rq->target == yield) {
  913. X            /* tell 'em we'll give it up */
  914. X            data = 1;
  915. X            XChangeProperty(dpy, rq->requestor, rq->property,
  916. X                    rq->target, 32, PropModeReplace,
  917. X                    (unsigned char *) &data, 1);
  918. X            notify.property = rq->property;
  919. X        }
  920. X        else {
  921. X#endif        
  922. X
  923. X    if (win == seln && rq->target == XA_STRING) {
  924. X        ptr = fetch_buffer(cb->atom, &nbytes);
  925. X        XChangeProperty(dpy, rq->requestor, rq->property,
  926. X                XA_STRING, 8, PropModeReplace,
  927. X                (unsigned char *) ptr, nbytes);
  928. X        notify.property = rq->property;
  929. X        XFree(ptr);
  930. X    }
  931. X
  932. X#ifdef XVIEW
  933. X        }
  934. X    }
  935. X    else if (rq->selection == caret) {
  936. X        if (rq->target == yield) {
  937. X            /*
  938. X             * Give up the caret (which meant that we
  939. X             * own the clipboard)
  940. X             */
  941. X            XSetSelectionOwner(dpy, caret, None, 
  942. X                    event->xselectionrequest.time);
  943. X            data = 1;
  944. X            XChangeProperty(dpy, rq->requestor, rq->property,
  945. X                    rq->target, 32, PropModeReplace,
  946. X                    (unsigned char *) &data, 1);
  947. X            notify.property = rq->property;
  948. X        }
  949. X    }
  950. X    else if (rq->selection == clipboard && win == seln) {
  951. X        ptr = fetch_buffer(cb->atom, &nbytes);
  952. X        if (rq->target == lengthc || rq->target == length) {
  953. X            /*
  954. X             * Send the length of the selection.
  955. X             */
  956. X            data = nbytes;
  957. X            XChangeProperty(dpy, rq->requestor, rq->property,
  958. X                    rq->target, 32, PropModeReplace,
  959. X                    (unsigned char *) &data, 1);
  960. X            notify.property = rq->property;
  961. X        }
  962. X        else if (rq->target == XA_STRING || 
  963. X            rq->target == text || rq->target == ctext) {
  964. X            /*
  965. X             * Send the selection itself.
  966. X             * All of our selections will be XA_STRING,
  967. X             * but if they ask for COMPOUND_TEXT, it's ok
  968. X             * to say that that's what we've got...
  969. X             */
  970. X            XChangeProperty(dpy, rq->requestor, rq->property, 
  971. X                (rq->target == ctext? ctext: XA_STRING), 8,
  972. X                PropModeReplace, ptr, nbytes);
  973. X            notify.property = rq->property;
  974. X        }
  975. X        XFree(ptr);
  976. X    }
  977. X#endif
  978. X
  979. X    XSendEvent(dpy, rq->requestor, False, 0, (XEvent *) ¬ify);
  980. X}
  981. X
  982. X/*
  983. X * Boo hiss, someone has taken the PRIMARY selection ownership
  984. X * away from this widget.  The current window contents must
  985. X * be redrawn without highlighting.
  986. X */
  987. Xstatic void
  988. Xcb_selclear(wdg, event, parms, nparms)                /*ARGSUSED*/
  989. XWidget        wdg;
  990. XXEvent        *event;
  991. XString        *parms;
  992. XCardinal    *nparms;
  993. X{
  994. X    CbWidget    cb    = (CbWidget) wdg;
  995. X#ifdef XVIEW
  996. X    Window        w;
  997. X    Time        t;
  998. X#endif
  999. X
  1000. X    seln = 0;
  1001. X    XClearArea(dpy, cb->core.window, 0,0,0,0, False);
  1002. X    cb_redisplay(wdg, (XEvent *)0, (Region)0);
  1003. X#ifdef XVIEW
  1004. X    /*
  1005. X     * Since we don't have ownership of PRIMARY anymore,
  1006. X     * we'd better get rid of CLIPBOARD and _SUN_SELN_CARET,
  1007. X     * if they're still ours.
  1008. X     */
  1009. X    t = event->xselectionclear.time;
  1010. X    w = XGetSelectionOwner(dpy, caret);
  1011. X    if (w == cb->core.window)
  1012. X        XSetSelectionOwner(dpy, caret, None, t);
  1013. X    w = XGetSelectionOwner(dpy, clipboard);
  1014. X    if (w == cb->core.window)
  1015. X        XSetSelectionOwner(dpy, clipboard, None, t);
  1016. X#endif
  1017. X}
  1018. X
  1019. Xstatic XtResource    resources[] = {
  1020. X#define offset(field)        XtOffset(CbWidget, field)
  1021. X    /* {name, class, type, size, offset, default_type, default_addr}, */
  1022. X    { XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
  1023. X        offset(fgnd), XtRString, (XtPointer) "XtDefaultForeground"},
  1024. X    { XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
  1025. X        offset(font), XtRString, (XtPointer) "fixed" },
  1026. X    { XtNatom, XtCAtom, XtRAtom, sizeof(Atom),    /* internal use */
  1027. X        offset(atom), XtRImmediate, (XtPointer)0 },
  1028. X#undef offset
  1029. X};
  1030. X
  1031. Xstatic XtActionsRec    actions[] = {
  1032. X    { "cut",        cb_cut },
  1033. X    { "paste",        cb_paste },
  1034. X    { "clear",        cb_clear },
  1035. X    { "rotate",        cb_rotate },
  1036. X    { "quit",        cb_quit },
  1037. X    { "refresh",        cb_refresh },
  1038. X    { "selreq",        cb_selreq },
  1039. X    { "selclear",        cb_selclear },
  1040. X};
  1041. X
  1042. Xstatic char    cb_transl[] = "\
  1043. X    <Btn1Down>:        cut() \n\
  1044. X    Shift <Btn2Down>:    clear() \n\
  1045. X    <Btn2Down>:        paste() \n\
  1046. X    Shift <Btn3Down>:    rotate(-1) \n\
  1047. X    <Btn3Down>:        rotate(1) \n\
  1048. X    <Key>Left:        rotate(-1) \n\
  1049. X    <Key>Right:        rotate(1) \n\
  1050. X    <Key>Up:        rotate(-1) \n\
  1051. X    <Key>Down:        rotate(1) \n\
  1052. X    <Key>q:            quit() \n\
  1053. X    <SelReq>:        selreq() \n\
  1054. X    <SelClr>:        selclear() \n\
  1055. X    ";
  1056. X
  1057. XCbClassRec    cbClassRec = {
  1058. X    {
  1059. X    (WidgetClass) &widgetClassRec,        /* superclass */
  1060. X    "Buffer",                /* class_name */
  1061. X    sizeof(CbRec),                /* widget_size */
  1062. X    NULL,                    /* class_initialize */
  1063. X    NULL,                    /* class_part_initialize */
  1064. X    FALSE,                    /* class_inited */
  1065. X    cb_initialize,                /* initialize */
  1066. X    NULL,                    /* initialize_hook */
  1067. X    cb_realize,                /* realize */
  1068. X    actions,                /* actions */
  1069. X    XtNumber(actions),            /* num_actions */
  1070. X    resources,                /* resources */
  1071. X    XtNumber(resources),            /* num_resources */
  1072. X    NULLQUARK,                /* xrm_class */
  1073. X    TRUE,                    /* compress_motion */
  1074. X    TRUE,                    /* compress_exposure */
  1075. X    TRUE,                    /* compress_enterleave */
  1076. X    FALSE,                    /* visible_interest */
  1077. X    cb_destroy,                /* destroy */
  1078. X    NULL,                    /* resize */
  1079. X    cb_redisplay,                /* expose */
  1080. X    NULL,                    /* set_values */
  1081. X    NULL,                    /* set_values_hook */
  1082. X    XtInheritSetValuesAlmost,        /* set_values_almost */
  1083. X    NULL,                    /* get_values_hook */
  1084. X    NULL,                    /* accept_focus */
  1085. X    XtVersion,                /* version */
  1086. X    NULL,                    /* callback_private */
  1087. X    cb_transl,                /* tm_table */
  1088. X    XtInheritQueryGeometry,            /* query_geometry */
  1089. X    XtInheritDisplayAccelerator,        /* display_accelerator */
  1090. X    NULL                    /* extension */
  1091. X    },
  1092. X};
  1093. X
  1094. XWidgetClass    cbWidgetClass = (WidgetClass) &cbClassRec;
  1095. X
  1096. X/*
  1097. X * Here endeth the section concerned with the cb widget.
  1098. X * Normal viewing shall now be resumed.
  1099. X * ============================================================================
  1100. X */
  1101. X
  1102. X
  1103. Xstatic void
  1104. Xusage()
  1105. X{
  1106. X    _fprintf(stderr,
  1107. X        "Usage: %s [Xt option] [-l layout] [-n count] [-p|-s list] [-r count]\n",
  1108. X        PGM_NAME);
  1109. X    exit(1);
  1110. X}
  1111. X
  1112. X/*
  1113. X * Gracefully exit after an XIO error, or after a "delete window"
  1114. X * directive from the window manager.
  1115. X * xioerror() avoids messy error messages sometimes seen from xterm
  1116. X * or in the xdm-errors file when forcibly destroying the client program.
  1117. X */
  1118. Xstatic int
  1119. Xxioerror(d)                            /*ARGSUSED*/
  1120. XDisplay    *d;
  1121. X{
  1122. X    exit(1);                        /*NOTREACHED*/
  1123. X}
  1124. X
  1125. Xstatic void
  1126. Xwmdel(wdg, ptr, ep, cont)                    /*ARGSUSED*/
  1127. XWidget        wdg;
  1128. XXtPointer    ptr;
  1129. XXEvent        *ep;
  1130. XBoolean        *cont;
  1131. X{
  1132. X    if (ep->type == ClientMessage && ep->xclient.data.l[0] == delwin)
  1133. X        exit(0);
  1134. X}
  1135. X
  1136. X/*
  1137. X * Print the contents of a cut buffer on stdout.
  1138. X */
  1139. Xstatic void
  1140. Xdoprint(n, ptr, nb)
  1141. Xint    n;
  1142. Xchar    *ptr;
  1143. Xint    nb;
  1144. X{
  1145. X    Atom    a;
  1146. X
  1147. X    a = get_atom(n, True);
  1148. X    if (a) {
  1149. X        ptr = fetch_buffer(a, &nb);
  1150. X        if (write(1, ptr, nb) != nb) {
  1151. X            _fprintf(stderr, "Write error\n");
  1152. X            exit(1);
  1153. X        }
  1154. X        XFree(ptr);
  1155. X    }
  1156. X}
  1157. X
  1158. X/*
  1159. X * Load a new value into one of the cut buffers.
  1160. X */
  1161. Xstatic void
  1162. Xdoset(n, ptr, nb)
  1163. Xint    n;
  1164. Xchar    *ptr;
  1165. Xint    nb;
  1166. X{
  1167. X    store_buffer(ptr, nb, get_atom(n, False));
  1168. X}
  1169. X
  1170. X/*
  1171. X * Process an ASCII list of cut buffer numbers.
  1172. X * Lists must obey the form "buffno[,buffno...]"
  1173. X * where buffno is a non-negative integer or a range
  1174. X * of the form M-N.  A processing function is called
  1175. X * for each buffer number in the list.  Duplicates and
  1176. X * list ordering is significant.
  1177. X */
  1178. Xstatic void
  1179. Xdolist(list, fn, data, nbytes)
  1180. Xchar    *list;
  1181. Xvoid    (*fn)();
  1182. Xchar    *data;
  1183. Xint    nbytes;
  1184. X{
  1185. X    int    m, n, x;
  1186. X
  1187. X    while (*list) {
  1188. X        if (!isdigit(*list))
  1189. X            usage();
  1190. X        for (m = 0; isdigit(*list); list++)
  1191. X            m = m * 10 + *list - '0';
  1192. X
  1193. X        (*fn)(m, data, nbytes);
  1194. X
  1195. X        if (*list == '-') {
  1196. X            list++;
  1197. X            if (!isdigit(*list))
  1198. X                usage();
  1199. X            for (n = 0; isdigit(*list); list++)
  1200. X                n = n * 10 + *list - '0';
  1201. X
  1202. X            x = (m > n)? -1: 1;
  1203. X            while (m != n) {
  1204. X                m += x;
  1205. X                (*fn)(m, data, nbytes);
  1206. X            }
  1207. X        }
  1208. X
  1209. X        if (*list == ',')
  1210. X            list++;
  1211. X        else if (*list)
  1212. X            usage();
  1213. X    }
  1214. X}
  1215. X
  1216. X/*
  1217. X * Perform a task mode command, i.e.
  1218. X * do something to the cut buffers immediately,
  1219. X * without the need to create any X windows first.
  1220. X */
  1221. Xstatic void
  1222. Xdotask(cmd, arg)
  1223. Xint    cmd;
  1224. Xchar    *arg;
  1225. X{
  1226. X    char    *ptr;
  1227. X    int    i, n, nb;
  1228. X
  1229. X    ptr = (char *)0;
  1230. X    n = nb = 0;
  1231. X
  1232. X    switch (cmd) {
  1233. X    case 'p':            /* print one or more buffers */
  1234. X        dolist(arg, doprint, (char *)0, 0);
  1235. X        break;
  1236. X    case 'r':            /* rotate the buffer contents */
  1237. X        n = atoi(arg);
  1238. X        if (n == 0)
  1239. X            break;
  1240. X        for (i = nbuffs - 1; i >= 0; i--)
  1241. X            (void) get_atom(i, False);
  1242. X        for (i = nbuffs - 1; i >= 0; i--)
  1243. X            XChangeProperty(dpy, root, atom[i], XA_STRING,
  1244. X                8, PropModeAppend, (unsigned char *) "", 0);
  1245. X
  1246. X        XRotateWindowProperties(dpy, root, atom, nbuffs, n);
  1247. X        break;
  1248. X    case 's':            /* store data in one or more buffers */
  1249. X        do {
  1250. X            ptr = XtRealloc(ptr, nb + BUFINC);
  1251. X            i = BUFINC;
  1252. X            do {
  1253. X                n = read(0, ptr + nb, i);
  1254. X                nb += n;
  1255. X                i -= n;
  1256. X            } while (n > 0 && i > 0);
  1257. X        } while (n > 0);
  1258. X        if (n == -1) {
  1259. X            _fprintf(stderr, "Read error\n");
  1260. X            exit(1);
  1261. X        }
  1262. X        dolist(arg, doset, ptr, nb);
  1263. X        XtFree(ptr);
  1264. X        break;
  1265. X    }
  1266. X}
  1267. X
  1268. Xtypedef struct {
  1269. X    int    nbuffs;
  1270. X    char    *layout;
  1271. X} ares_t, *ares_ptr;
  1272. X
  1273. Xstatic ares_t    ares;
  1274. X
  1275. Xstatic XtResource    res[] = {
  1276. X#define offset(field)        XtOffset(ares_ptr, field)
  1277. X    { XtNbufferCount, XtCBufferCount, XtRInt, sizeof(int), 
  1278. X        offset(nbuffs), XtRImmediate, (XtPointer) 8 },
  1279. X    { XtNlayout, XtCLayout, XtRString, sizeof(char *),
  1280. X        offset(layout), XtRImmediate, "horiz" },
  1281. X#undef offset
  1282. X};
  1283. X
  1284. Xstatic char        *def[] = {        /* default resource values */
  1285. X    ".bufferCount:        8",
  1286. X    ".layout:        horizontal",
  1287. X    "*font:            fixed",
  1288. X    "*Buffer.width:        60",
  1289. X    "*Buffer.height:    60",
  1290. X    0,
  1291. X};
  1292. X
  1293. Xstatic XrmOptionDescRec opt[] = {
  1294. X    { "-n",    ".bufferCount",    XrmoptionSepArg, (caddr_t) 8 },
  1295. X    { "-l",    ".layout",    XrmoptionSepArg, (caddr_t) "horiz" },
  1296. X};
  1297. X
  1298. X/*
  1299. X * Parse the command line options, and
  1300. X * perform all the windows initializations.
  1301. X */
  1302. Xstatic void 
  1303. Xinit(argc, argv)
  1304. Xint    argc;
  1305. Xchar    **argv;
  1306. X{
  1307. X    int    i, n;
  1308. X    char    **p;
  1309. X    char    *attach = 0;
  1310. X    char    name[16];
  1311. X    Arg    args[2];
  1312. X
  1313. X    /*
  1314. X     * Set up the atoms that we already know about.
  1315. X     */
  1316. X    natoms = 8;
  1317. X    atom = (Atom *) XtMalloc(natoms * sizeof(Atom));
  1318. X    atom[0] = XA_CUT_BUFFER0;
  1319. X    atom[1] = XA_CUT_BUFFER1;
  1320. X    atom[2] = XA_CUT_BUFFER2;
  1321. X    atom[3] = XA_CUT_BUFFER3;
  1322. X    atom[4] = XA_CUT_BUFFER4;
  1323. X    atom[5] = XA_CUT_BUFFER5;
  1324. X    atom[6] = XA_CUT_BUFFER6;
  1325. X    atom[7] = XA_CUT_BUFFER7;
  1326. X
  1327. X    /*
  1328. X     * Initialize the toolkit, parse the command line,
  1329. X     * initialize the resources database, and find out
  1330. X     * how many buffers to deal with.
  1331. X     */
  1332. X    top = XtAppInitialize(&app, PGM_CLASS, opt, 2, &argc, argv, def, 0, 0);
  1333. X    dpy = XtDisplay(top);
  1334. X    root = RootWindow(dpy, DefaultScreen(dpy));
  1335. X
  1336. X    XtGetApplicationResources(top, &ares, res, XtNumber(res), 0, 0);
  1337. X    nbuffs = max(ares.nbuffs, 1);
  1338. X
  1339. X    /*
  1340. X     * If the command line contains one of the task mode
  1341. X     * switches (print, set, rotate), it is processed here.
  1342. X     * If there are multiple task mode args, only the first
  1343. X     * one is processed.
  1344. X     */
  1345. X    for (p = argv + 1; p < argv + argc; p++) {
  1346. X        if (eq(*p, "-p") || eq(*p, "-r") || eq(*p, "-s")) {
  1347. X            if (p == argv + argc - 1)
  1348. X                usage();
  1349. X
  1350. X            dotask(p[0][1], p[1]);
  1351. X            XCloseDisplay(dpy);
  1352. X            exit(0);
  1353. X        }
  1354. X    }
  1355. X
  1356. X    /*
  1357. X     * If no task mode request has been made of us, this code
  1358. X     * proceeds with the rest of the windows initialization.
  1359. X     * The container widget is created, the sub-widgets are
  1360. X     * created and then everything is realized.
  1361. X     */
  1362. X    if (argc > 1)
  1363. X        usage();
  1364. X    if (ares.layout[0] == 'h')
  1365. X        attach = XtNfromHoriz;
  1366. X    if (ares.layout[0] == 'v')
  1367. X        attach = XtNfromVert;
  1368. X
  1369. X    wdg = (Widget *) XtMalloc(nbuffs * sizeof(Widget));
  1370. X
  1371. X    box = XtCreateWidget("container", formWidgetClass, top, 0, 0);
  1372. X    XtManageChild(box);
  1373. X
  1374. X    for (i = 0; i < nbuffs; i++) {
  1375. X        XtSetArg(args[0], XtNatom, get_atom(i, False));
  1376. X        n = 1;
  1377. X        if (attach && i > 0) {
  1378. X            XtSetArg(args[1], attach, wdg[i-1]);
  1379. X            n = 2;
  1380. X        }
  1381. X
  1382. X        _sprintf(name, "buffer%d", i);
  1383. X        wdg[i] = XtCreateWidget(name, cbWidgetClass, box, args, n);
  1384. X        XtManageChild(wdg[i]);
  1385. X    }
  1386. X
  1387. X    XSelectInput(dpy, root, PropertyChangeMask);
  1388. X    XSetIOErrorHandler(xioerror);
  1389. X
  1390. X    XtRealizeWidget(top);
  1391. X
  1392. X    delwin = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
  1393. X    XSetWMProtocols(dpy, XtWindow(top), &delwin, 1);
  1394. X    XtAddEventHandler(top, 0, True, wmdel, (XtPointer)0);
  1395. X
  1396. X#ifdef XVIEW
  1397. X    clipboard = XInternAtom(dpy, "CLIPBOARD", False);
  1398. X    caret = XInternAtom(dpy, "_SUN_SELN_CARET", False);
  1399. X    yield = XInternAtom(dpy, "_SUN_SELN_YIELD", False);
  1400. X    length = XInternAtom(dpy, "LENGTH", False);
  1401. X    lengthc = XInternAtom(dpy, "LENGTH_CHARS", False);
  1402. X    text = XInternAtom(dpy, "TEXT", False);
  1403. X    ctext = XInternAtom(dpy, "COMPOUND_TEXT", False);
  1404. X#endif
  1405. X}
  1406. X
  1407. X/*
  1408. X * Process incoming events.
  1409. X * The program needs to know when a cut buffer value changes.
  1410. X * We achieve this by eavesdropping on PropertyNotify events arising
  1411. X * on the root window.  If such an event is delivered to us, the
  1412. X * function immediately clears the window displaying that property
  1413. X * and causes an Expose event to be generated for the window.
  1414. X * This is horrible nasty stuff.
  1415. X */
  1416. Xstatic void
  1417. Xxevents()
  1418. X{
  1419. X    XEvent    event;
  1420. X    int    i;
  1421. X
  1422. X    for (;;) {
  1423. X        XtAppNextEvent(app, &event);
  1424. X        if (event.type != PropertyNotify) {
  1425. X            (void) XtDispatchEvent(&event);
  1426. X            continue;
  1427. X        }
  1428. X
  1429. X        for (i = 0; i < nbuffs; i++)
  1430. X            if (event.xproperty.atom == atom[i])
  1431. X                XClearArea(dpy, XtWindow(wdg[i]), 0,0,0,0,True);
  1432. X    }
  1433. X}
  1434. X
  1435. Xmain(argc, argv)
  1436. Xint    argc;
  1437. Xchar    **argv;
  1438. X{
  1439. X    init(argc, argv);
  1440. X    xevents();
  1441. X    return 0;
  1442. X}
  1443. END_OF_FILE
  1444.   if test 22716 -ne `wc -c <'xcb.c'`; then
  1445.     echo shar: \"'xcb.c'\" unpacked with wrong size!
  1446.   fi
  1447.   # end of 'xcb.c'
  1448. fi
  1449. if test -f 'xcb.man' -a "${1}" != "-c" ; then 
  1450.   echo shar: Will not clobber existing file \"'xcb.man'\"
  1451. else
  1452.   echo shar: Extracting \"'xcb.man'\" \(8737 characters\)
  1453.   sed "s/^X//" >'xcb.man' <<'END_OF_FILE'
  1454. X.TH XCB 1 "May 6 1992" "X Version 11"
  1455. X.SH NAME
  1456. Xxcb \- X Cut Buffers \- Pigeon holes for your cut and paste selections.
  1457. X.SH SYNOPSIS
  1458. X.B xcb
  1459. X[\fIXt option\fP]
  1460. X[\fB\-l\fP \fIlayout\fP]
  1461. X[\fB\-n\fP \fIcount\fP]
  1462. X[\fB\-p\fP|\fB\-s\fP \fIlist\fP]
  1463. X[\fB\-r\fP \fIcount\fP]
  1464. X.SH DESCRIPTION
  1465. X\fIXcb\fP provides easy access to the cut buffers built into every X server.
  1466. XIt allows the buffers to be manipulated either via the command line,
  1467. Xor with the mouse in a point and click manner.
  1468. XThe buffers can be used as holding pens to store and retrieve
  1469. Xarbitrary data fragments.
  1470. XAny number of cut buffers may be created,
  1471. Xso any number of different pieces of data can be saved and recalled later.
  1472. XBy default, 8 cut buffers are created.
  1473. XThe program is designed primarily for use with textual data.
  1474. X.LP
  1475. X\fIXcb\fP has two modes of operation.
  1476. XNormally \fIxcb\fP provides an array of windows on your display,
  1477. Xone per cut buffer, tiled horizontally, vertically, or in some
  1478. Xuser specified layout.
  1479. XEach window displays the contents of its respective cut buffer.
  1480. XData can be cut from and pasted to the windows in a similar manner
  1481. Xto xterm.
  1482. XThe buffers can also be rotated.
  1483. X.LP
  1484. XIn task mode, \fIxcb\fP lets you access the cut buffers from the command line.
  1485. XCut buffers can be loaded from stdin, copied or concatenated
  1486. Xto stdout, or rotated an arbitrary number of positions.
  1487. XIn this mode of operation, \fIxcb\fP performs the requested task
  1488. Xand then exits.
  1489. XIt does not create any windows and
  1490. Xhas no interaction with the mouse or keyboard.
  1491. X.SH OPTIONS
  1492. X\fIXcb\fP supports the full set of X Toolkit Intrinsics options,
  1493. Xas well as those listed below.
  1494. X\fIXcb\fP options can appear in any order.
  1495. XThe presence of the
  1496. X\fB\-p\fP,
  1497. X\fB\-r\fP or
  1498. X\fB\-s\fP
  1499. Xoptions causes \fIxcb\fP to execute in task mode,
  1500. Xdescribed above.
  1501. X.IP "\fB\-l\fP \fIlayout\fP"
  1502. XThis option controls the geometry arrangement of \fIxcb's\fP subwindows.
  1503. XIt is the command line equivalent of the \fB.layout\fP resource,
  1504. Xdescribed below.
  1505. X.LP
  1506. X.IP "\fB\-n\fP \fIcount\fP"
  1507. XCreate \fIcount\fP cut buffers.
  1508. X\fICount\fP can be any integer greater than zero.
  1509. XThis option is the command line equivalent of the \fB.bufferCount\fP
  1510. Xresource, described below.
  1511. X.LP
  1512. X.IP "\fB\-p\fP \fIlist\fP"
  1513. XPrint the contents of the listed buffer(s) on stdout.
  1514. XThe buffered data is printed exactly as it is stored in the server.
  1515. XSelecting two or more buffers has the effect of concatenating
  1516. Xthe data on stdout.
  1517. XThe cut buffers are numbered from 0... onwards.
  1518. XThe list can be either a single digit,
  1519. Xa comma separated list of digits,
  1520. Xa range of the form m\-n,
  1521. Xor some combination of lists and ranges.
  1522. XThe buffers are printed in listed order,
  1523. Xso repeated numbers in the list can be used to 
  1524. Xduplicate buffer contents.
  1525. X.LP
  1526. X.IP "\fB\-r\fP \fIcount\fP"
  1527. XRotate the buffers by \fIcount\fP positions.
  1528. X\fICount\fP can be any integer, positive or negative.
  1529. XThis option may be used in conjunction with the
  1530. X\fB\-n\fP \fIcount\fP option to rotate
  1531. Xa specific number of buffers.
  1532. XIf the \fB\-n\fP option is not used, \fIxcb\fP will rotate
  1533. Xthe number of buffers given by the \fB.bufferCount\fP resource.
  1534. X.LP
  1535. X.IP "\fB\-s\fP \fIlist\fP"
  1536. XStore the data from stdin in the listed buffer(s).
  1537. XIf two or more buffers are selected the input data is duplicated
  1538. Xin each buffer.
  1539. XRefer to the \fB\-p\fP option for the definition of a list.
  1540. X.SH WIDGETS and RESOURCES
  1541. XThe \fIxcb\fP widget hierarchy consists of a collection of
  1542. Xcustom buffer widgets contained within a single Athena form widget.
  1543. X.LP
  1544. XThe name of the form widget is "container",
  1545. Xand its class name is "Form".
  1546. XThe names of the buffer widgets are "buffer0", "buffer1",
  1547. X"buffer2", .... etc., and their class name is "Buffer".
  1548. XEach buffer widget supports all the standard core widget
  1549. Xresources, plus the \fB\.foreground\fP and \fB\.font\fP resources.
  1550. X.LP
  1551. XApplication wide resources are as follows:
  1552. X.br
  1553. X.sp 1
  1554. X.nf
  1555. X  \fB\.bufferCount\fP (default value 8)
  1556. X.in +8
  1557. XThis is the number of buffer widgets to create.
  1558. XAny number of widgets (greater than zero) can be created.
  1559. X.in -8
  1560. X.sp 1
  1561. X  \fB\.layout\fP (default value "h")
  1562. X.in +8
  1563. XOnly the first character of the resource value is significant.
  1564. XThis is the geometry arrangement to apply in the form widget.
  1565. XThe layout can be "h" (horizontal), "v" (vertical), or some
  1566. Xother value to disable the geometry code and allow you to build
  1567. Xyour own custom layout scheme.  An example is provided in the
  1568. Xapplication default resources file.
  1569. X.in -8
  1570. X.fi
  1571. X.SH EVENTS and TRANSLATIONS
  1572. X\fIXcb's\fP input semantics are coded into a Toolkit translation table.
  1573. XThe default bindings have been chosen to conform with the default
  1574. Xconfiguration of other cut and paste clients, such as xterm.
  1575. XThe bindings may be altered or overridden according to your needs.
  1576. XThe actions functions provided by \fIxcb\fP are:\-
  1577. X.br
  1578. X.sp 1
  1579. X.ns
  1580. X.ta 16n
  1581. X.nf
  1582. Xcut()    causes the contents of the chosen cut buffer to become
  1583. X    the PRIMARY selection.  The window contents, if any,
  1584. X    are highlighted, and can then be pasted into other
  1585. X    cut buffers or applications.
  1586. X.sp 1
  1587. Xpaste()    causes the value of the PRIMARY selection to be
  1588. X    converted into text and pasted into the chosen cut
  1589. X    buffer, overwriting any previous buffer contents.
  1590. X    If no PRIMARY selection is present, \fIxcb\fP pastes
  1591. X    the contents of cut buffer zero into the chosen buffer.
  1592. X.sp 1
  1593. Xclear()    clears the chosen cut buffer.
  1594. X.sp 1
  1595. Xrotate(NN)    rotates the cut buffers by NN positions.  NN may
  1596. X    be any positive or negative number.
  1597. X.sp 1
  1598. Xrefresh()    causes the cut buffer window to be cleared and redrawn.
  1599. X.sp 1
  1600. Xselreq()    this action function handles paste requests
  1601. X    from other clients, or other \fIxcb\fP windows.
  1602. X    It should always be bound to SelectionRequest events.
  1603. X.sp 1
  1604. Xselclear()    this action function responds to the loss of
  1605. X    ownership of the PRIMARY selection property.
  1606. X    It should always be bound to SelectionClear events.
  1607. X.sp 1
  1608. Xquit()    causes \fIxcb\fP to terminate.
  1609. X.fi
  1610. X.ta 8n
  1611. X.sp 1
  1612. XThe default bindings are as follows:\-
  1613. X.sp 1
  1614. X.ta 20n
  1615. X.nf
  1616. X<Btn1Down>:        cut() \\n\\
  1617. XShift <Btn2Down>:    clear() \\n\\
  1618. X<Btn2Down>:        paste() \\n\\
  1619. XShift <Btn3Down>:    rotate(-1) \\n\\
  1620. X<Btn3Down>:        rotate(1) \\n\\
  1621. X<Key>Left:        rotate(-1) \\n\\
  1622. X<Key>Right:        rotate(1) \\n\\
  1623. X<Key>Up:        rotate(-1) \\n\\
  1624. X<Key>Down:        rotate(1) \\n\\
  1625. X<Key>q:            quit() \\n\\
  1626. X<SelReq>:        selreq() \\n\\
  1627. X<SelClr>:        selclear()
  1628. X.fi
  1629. X.ta 8n
  1630. X.sp 1
  1631. X.SH EXAMPLES
  1632. XThe following are some examples of \fIxcb\fP task mode usage:\-
  1633. X.sp 1
  1634. Xxcb \-s 0\-7 < /dev/null
  1635. X.br
  1636. XThis clears the first 8 cut buffers in your server.
  1637. X.sp 1
  1638. Xecho "G'day." | xcb \-display bigears:0.0 \-s 1,3,5,7
  1639. X.br
  1640. XThis loads the string "G'day." into four of the cut buffers
  1641. Xon the display "bigears".
  1642. X.sp 1
  1643. Xls \`xcb \-p 2,3\`
  1644. X.br
  1645. XThis produces a listing of all the files named in
  1646. Xcut buffers 2 and 3.
  1647. X.br
  1648. X.sp 1
  1649. Xxcb \-p 0\-7 | xcb \-s 0
  1650. X.br
  1651. XThis concatenates the values in the first 8 cut buffers, and places
  1652. Xthe result back in cut buffer zero.
  1653. X.sp 1
  1654. X.nf
  1655. Xfor i in 0 1 2 3 4 5 6 7
  1656. Xdo
  1657. X    xcb \-p $i > $HOME/.xcb/$i
  1658. Xdone
  1659. Xfor i in 0 1 2 3 4 5 6 7
  1660. Xdo
  1661. X    xcb \-s $i < $HOME/.xcb/$i
  1662. Xdone
  1663. X.fi
  1664. XThis first loop saves the contents of each of the cut buffers
  1665. Xin a separate file under your home directory.  The second loop
  1666. Xrestores the cut buffer contents from those files.
  1667. XWhen placed in your .logout and .login scripts respectively,
  1668. Xthe commands are a simple method of preserving your cut buffers
  1669. Xacross login sessions.
  1670. X.sp 1
  1671. X.nf
  1672. Xfunction g {
  1673. X    echo "$1\\\\c" | xcb \-s 7
  1674. X    grep "$@"
  1675. X}
  1676. Xfunction vg {
  1677. X    vi +/\`xcb \-p 7\` "$@"
  1678. X}
  1679. X.fi
  1680. XThese two shell functions exemplify a simple mechanism for saving and
  1681. Xreusing regular expressions.
  1682. XThe first function saves the regex used for grep\-ing into
  1683. Xcut buffer 7.  The second function reuses the most recent
  1684. Xgrep regex as a search command in vi.
  1685. XThere is considerable scope for expanding and improving these ideas.
  1686. X.SH SEE ALSO
  1687. Xxterm(1), xcutsel(1), xclipboard(1), xprop(1)
  1688. X.br
  1689. XAthena Widget Set \- C Language Interface
  1690. X.SH AUTHORS
  1691. XFarrell McKay
  1692. X.br
  1693. XE\-mail: fbm\@ptcburp.ptcbu.oz.au
  1694. X.br
  1695. X.sp 1
  1696. XXView modifications provided by Danny Vanderryn
  1697. X.br
  1698. XE\-mail: dvanderr\@us.oracle.com
  1699. X.SH COPYRIGHT
  1700. XCopyright (C) 1992 by Farrell McKay.
  1701. X.br
  1702. X.sp 1
  1703. XPermission to use, copy, modify, and distribute this software and its
  1704. Xdocumentation for any purpose and without fee is hereby granted, provided
  1705. Xthat the above copyright notice appears in all copies and that both that
  1706. Xcopyright notice and this permission notice appear in supporting
  1707. Xdocumentation.  This software is provided "as is" without express or
  1708. Ximplied warranty.
  1709. X.SH "BUGS  :\-)"
  1710. XXlib's underlying protocol for moving selection data
  1711. Xbetween client and server can sometimes be slow,
  1712. Xdepending on the amount of data involved.
  1713. XDo not expect fast performance if your selections are
  1714. Xbig or you want to store big files in your cut buffers!
  1715. X("big" means, say, over 10k bytes \- but your mileage
  1716. Xmay vary).
  1717. END_OF_FILE
  1718.   if test 8737 -ne `wc -c <'xcb.man'`; then
  1719.     echo shar: \"'xcb.man'\" unpacked with wrong size!
  1720.   fi
  1721.   # end of 'xcb.man'
  1722. fi
  1723. echo shar: End of archive 1 \(of 1\).
  1724. cp /dev/null ark1isdone
  1725. MISSING=""
  1726. for I in 1 ; do
  1727.     if test ! -f ark${I}isdone ; then
  1728.     MISSING="${MISSING} ${I}"
  1729.     fi
  1730. done
  1731. if test "${MISSING}" = "" ; then
  1732.     echo You have the archive.
  1733.     rm -f ark[1-9]isdone
  1734. else
  1735.     echo You still must unpack the following archives:
  1736.     echo "        " ${MISSING}
  1737. fi
  1738. exit 0
  1739. exit 0 # Just in case...
  1740.