home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / clients / xclipboard / xclipboard.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-22  |  17.4 KB  |  720 lines

  1. /*
  2.  * $XConsortium: xclipboard.c,v 1.25 91/07/22 15:53:36 converse Exp $
  3.  *
  4.  * Copyright 1989 Massachusetts Institute of Technology
  5.  *
  6.  * Permission to use, copy, modify, and distribute this software and its
  7.  * documentation for any purpose and without fee is hereby granted, provided
  8.  * that the above copyright notice appear in all copies and that both that
  9.  * copyright notice and this permission notice appear in supporting
  10.  * documentation, and that the name of M.I.T. not be used in advertising
  11.  * or publicity pertaining to distribution of the software without specific,
  12.  * written prior permission.  M.I.T. makes no representations about the
  13.  * suitability of this software for any purpose.  It is provided "as is"
  14.  * without express or implied warranty.
  15.  *
  16.  * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  17.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
  18.  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  19.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  20.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
  21.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22.  *
  23.  * Author:  Ralph Swick, DEC/Project Athena
  24.  * Updated for R4:  Chris D. Peterson,  MIT X Consortium.
  25.  * Reauthored by: Keith Packard, MIT X Consortium.
  26.  */
  27.  
  28. #include <stdio.h>
  29. #include <X11/Intrinsic.h>
  30. #include <X11/StringDefs.h>
  31. #include <X11/Xatom.h>
  32.  
  33. #include <X11/Xmu/Atoms.h>
  34. #include <X11/Xmu/StdSel.h>
  35.  
  36. #include <X11/Shell.h>
  37. #include <X11/Xaw/Form.h>
  38. #include <X11/Xaw/Label.h>
  39. #include <X11/Xaw/Command.h>
  40. #include <X11/Xaw/AsciiText.h>
  41. #include <X11/Xaw/Dialog.h>
  42. #include <X11/Xaw/Cardinals.h>
  43. #include <X11/Xfuncs.h>
  44.  
  45. #define Command commandWidgetClass
  46. #define Label    labelWidgetClass
  47. #define Text    asciiTextWidgetClass
  48.  
  49. #define INFINITY 10000000    /* pretty big, huh? */
  50.  
  51. typedef struct _Clip {
  52.     struct _Clip    *next, *prev;
  53.     char        *clip;
  54.     char        *filename;
  55.     int            avail;
  56. } ClipRec, *ClipPtr;
  57.  
  58. extern char *malloc ();
  59.  
  60. static Atom wm_delete_window;
  61. static Atom wm_protocols;
  62.  
  63. static long TextLength (w)
  64.     Widget  w;
  65. {
  66.     return XawTextSourceScan (XawTextGetSource (w),
  67.                   (XawTextPosition) 0,
  68.                    XawstAll, XawsdRight, 1, TRUE);
  69. }
  70.  
  71. SaveClip (w, clip)
  72.     Widget  w;
  73.     ClipPtr clip;
  74. {
  75.     Arg        args[1];
  76.     char    *data;
  77.     int        len;
  78.     Widget  source;
  79.  
  80.     source = XawTextGetSource (w);
  81.     XtSetArg (args[0], XtNstring, &data);
  82.     XtGetValues (source, args, 1);
  83.     len = strlen (data);
  84.     if (len >= clip->avail)
  85.     {
  86.     if (clip->clip)
  87.         free (clip->clip);
  88.     clip->clip = malloc (len + 1);
  89.     if (!clip->clip)
  90.         clip->avail = 0;
  91.     else
  92.         clip->avail = len + 1;
  93.     }
  94.     if (clip->avail)
  95.     {
  96.     strcpy (clip->clip, data);
  97.     }
  98. }
  99.  
  100. RestoreClip (w, clip)
  101.     Widget  w;
  102.     ClipPtr clip;
  103. {
  104.     Arg        args[1];
  105.     Widget  source;
  106.  
  107.     source = XawTextGetSource (w);
  108.     XtSetArg (args[0], XtNstring, clip->clip);
  109.     XtSetValues (source, args, 1);
  110. }
  111.  
  112. /*ARGSUSED*/
  113. ClipPtr 
  114. NewClip (w, old)
  115.     Widget  w;
  116.     ClipPtr old;
  117. {
  118.     ClipPtr newClip;
  119.  
  120.     newClip = (ClipPtr) malloc (sizeof (ClipRec));
  121.     if (!newClip)
  122.     return newClip;
  123.     newClip->clip = 0;
  124.     newClip->avail = 0;
  125.     newClip->prev = old;
  126.     newClip->next = NULL;
  127.     newClip->filename = NULL;
  128.     if (old)
  129.     {
  130.     newClip->next = old->next;
  131.     old->next = newClip;
  132.     }
  133.     return newClip;
  134. }
  135.  
  136. /*ARGSUSED*/
  137. DeleteClip (w, clip)
  138.     Widget  w;
  139.     ClipPtr clip;
  140. {
  141.     if (clip->prev)
  142.     clip->prev->next = clip->next;
  143.     if (clip->next)
  144.     clip->next->prev = clip->prev;
  145.     if (clip->clip)
  146.     free (clip->clip);
  147.     free ((char *) clip);
  148. }
  149.  
  150. static ClipPtr    currentClip;
  151. static Widget    top;
  152. static Widget    text, nextButton, prevButton, indexLabel;
  153. static Widget    fileDialog, fileDialogShell;
  154. static Widget    failDialog, failDialogShell;
  155.  
  156. static int
  157. IndexCurrentClip ()
  158. {
  159.     int    i = 0;
  160.     ClipPtr clip;
  161.  
  162.     for (clip = currentClip; clip; clip = clip->prev)
  163.     i++;
  164.     return i;
  165. }
  166.  
  167. static void
  168. set_button_state ()
  169. {
  170.     Boolean prevvalid, nextvalid;
  171.     Arg arg;
  172.     char labelString[10];
  173.  
  174.     prevvalid = currentClip->prev != NULL;
  175.     nextvalid = currentClip->next != NULL;
  176.     XtSetArg (arg, XtNsensitive, prevvalid);
  177.     XtSetValues (prevButton, &arg, ONE);
  178.     XtSetArg (arg, XtNsensitive, nextvalid);
  179.     XtSetValues (nextButton, &arg, ONE);
  180.     sprintf (labelString, "%d", IndexCurrentClip ());
  181.     XtSetArg (arg, XtNlabel, labelString);
  182.     XtSetValues (indexLabel, &arg, ONE);
  183. }
  184.  
  185. /* ARGSUSED */
  186. static void
  187. NextCurrentClip (w, ev, parms, np)
  188.     Widget    w;
  189.     XEvent    *ev;
  190.     String    *parms;
  191.     Cardinal    *np;
  192. {
  193.     if (currentClip->next)
  194.     {
  195.     SaveClip (text, currentClip);
  196.     currentClip = currentClip->next;
  197.     RestoreClip (text, currentClip);
  198.     set_button_state ();
  199.     }
  200. }
  201.  
  202. /* ARGSUSED */
  203. static void
  204. PrevCurrentClip (w, ev, parms, np)
  205.     Widget    w;
  206.     XEvent    *ev;
  207.     String    *parms;
  208.     Cardinal    *np;
  209. {
  210.     if (currentClip->prev)
  211.     {
  212.     SaveClip (text, currentClip);
  213.     currentClip = currentClip->prev;
  214.     RestoreClip (text, currentClip);
  215.     set_button_state ();
  216.     }
  217. }
  218.  
  219. /* ARGSUSED */
  220. static void
  221. DeleteCurrentClip (w, ev, parms, np)
  222.     Widget    w;
  223.     XEvent    *ev;
  224.     String    *parms;
  225.     Cardinal    *np;
  226. {
  227.     ClipPtr newCurrent;
  228.  
  229.     if (currentClip->prev)
  230.     newCurrent = currentClip->prev;
  231.     else
  232.     newCurrent = currentClip->next;
  233.     if (newCurrent)
  234.     {
  235.     DeleteClip (text, currentClip);
  236.     currentClip = newCurrent;
  237.     RestoreClip (text, currentClip);
  238.     }
  239.     else
  240.     EraseTextWidget ();
  241.     set_button_state ();
  242. }
  243.  
  244. /* ARGSUSED */
  245. static void
  246. Quit (w, ev, parms, np)
  247.     Widget    w;
  248.     XEvent    *ev;
  249.     String    *parms;
  250.     Cardinal    *np;
  251. {
  252.     XtCloseDisplay  (XtDisplay (text));
  253.     exit (0);
  254. }
  255.  
  256. static void
  257. CenterWidgetAtPoint (w, x, y)
  258.     Widget  w;
  259.     int        x, y;
  260. {
  261.     Arg    args[2];
  262.     Dimension    width, height;
  263.  
  264.     XtSetArg(args[0], XtNwidth, &width);
  265.     XtSetArg(args[1], XtNheight, &height);
  266.     XtGetValues (w, args, 2);
  267.     x = x - (int) width / 2;
  268.     y = y - (int) height / 2;
  269.     if (x < 0)
  270.     x = 0;
  271.     else {
  272.     int scr_width = WidthOfScreen (XtScreen(w));
  273.     if (x + (int)width > scr_width)
  274.         x = scr_width - width;
  275.     }
  276.     if (y < 0)
  277.     y = 0;
  278.     else {
  279.     int scr_height = HeightOfScreen (XtScreen(w));
  280.     if (y + (int)height > scr_height)
  281.         y = scr_height - height;
  282.     }
  283.     XtSetArg(args[0], XtNx, x);
  284.     XtSetArg(args[1], XtNy, y);
  285.     XtSetValues (w, args, 2);
  286. }
  287.  
  288. static void
  289. CenterWidgetOnEvent (w, e)
  290.     Widget  w;
  291.     XEvent  *e;
  292. {
  293.     CenterWidgetAtPoint (w, e->xbutton.x_root, e->xbutton.y_root);
  294. }
  295.  
  296. static void
  297. CenterWidgetOnWidget (w, wT)
  298.     Widget  w, wT;
  299. {
  300.     Position    rootX, rootY;
  301.     Dimension    width, height;
  302.     Arg        args[2];
  303.  
  304.     XtSetArg (args[0], XtNwidth, &width);
  305.     XtSetArg (args[1], XtNheight, &height);
  306.     XtGetValues (wT, args, 2);
  307.     XtTranslateCoords (wT, (Position) width/2, (Position) height/2, &rootX, &rootY);
  308.     CenterWidgetAtPoint (w, (int) rootX, (int) rootY);
  309. }
  310.  
  311. /*ARGSUSED*/
  312. static void
  313. SaveToFile (w, e, argv, argc)
  314.     Widget  w;
  315.     XEvent  *e;
  316.     String  *argv;
  317.     Cardinal        *argc;
  318. {
  319.     Arg        args[1];
  320.     char    *filename;
  321.  
  322.     filename = "clipboard";
  323.     if (currentClip->filename)
  324.     filename = currentClip->filename;
  325.     XtSetArg(args[0], XtNvalue, filename);
  326.     XtSetValues (fileDialog, args, 1);
  327.     CenterWidgetOnEvent (fileDialogShell, e);
  328.     XtPopup (fileDialogShell, XtGrabNone);
  329. }
  330.  
  331. /*ARGSUSED*/
  332. static void
  333. AcceptSaveFile (w, e, argv, argc)
  334.     Widget  w;
  335.     XEvent  *e;
  336.     String  *argv;
  337.     Cardinal    *argc;
  338. {
  339.     char    *filename;
  340.     Boolean success;
  341.     Arg        args[1];
  342.  
  343.     filename = XawDialogGetValueString (fileDialog);
  344.     success = XawAsciiSaveAsFile (XawTextGetSource (text), filename);
  345.     XtPopdown (fileDialogShell);
  346.     if (!success)
  347.     {
  348.     char    failMessage[1024];
  349.  
  350.     sprintf (failMessage, "Can't open file \"%s\"", filename);
  351.     XtSetArg (args[0], XtNlabel, failMessage);
  352.     XtSetValues (failDialog, args, 1);
  353.     CenterWidgetOnEvent (failDialogShell, e);
  354.     XtPopup (failDialogShell, XtGrabNone);
  355.     }
  356.     else
  357.     {
  358.     if (currentClip->filename)
  359.         free (currentClip->filename);
  360.     currentClip->filename = malloc (strlen (filename) + 1);
  361.     if (currentClip->filename)
  362.         strcpy (currentClip->filename, filename);
  363.     }
  364. }
  365.  
  366. /* ARGSUSED */
  367. static void
  368. CancelSaveFile (w, ev, parms, np)
  369.     Widget    w;
  370.     XEvent    *ev;
  371.     String    *parms;
  372.     Cardinal    *np;
  373. {
  374.     XtPopdown (fileDialogShell);
  375. }
  376.  
  377. /* ARGSUSED */
  378. static void
  379. FailContinue (w, ev, parms, np)
  380.     Widget    w;
  381.     XEvent    *ev;
  382.     String    *parms;
  383.     Cardinal    *np;
  384. {
  385.     XtPopdown (failDialogShell);
  386. }
  387.  
  388. /*ARGSUSED*/
  389. static void WMProtocols(w, ev, params, n)
  390.     Widget    w;
  391.     XEvent    *ev;
  392.     String    *params;
  393.     Cardinal    *n;
  394. {
  395.     if (ev->type == ClientMessage &&
  396.     ev->xclient.message_type == wm_protocols &&
  397.     ev->xclient.data.l[0] == wm_delete_window) {
  398.     while (w && !XtIsShell(w))
  399.         w = XtParent(w);
  400.     if (w == top)
  401.         Quit(w, ev, params, n);
  402.     else if (w == fileDialogShell)
  403.         CancelSaveFile(w, ev, params, n);
  404.     else if (w == failDialogShell)
  405.         FailContinue(w, ev, params, n);
  406.     }
  407. }
  408.  
  409. /* ARGUSED */
  410. static void
  411. NewCurrentClip (w, ev, parms, np)
  412.     Widget    w;
  413.     XEvent    *ev;
  414.     String    *parms;
  415.     Cardinal    *np;
  416. {
  417.     NewCurrentClipContents ("", 0);
  418. }
  419.  
  420. NewCurrentClipContents (data, len)
  421.     char    *data;
  422.     int        len;
  423. {
  424.     XawTextBlock textBlock;
  425.  
  426.     SaveClip (text, currentClip);
  427.  
  428.     /* append new clips at the end */
  429.     while (currentClip && currentClip->next)
  430.     currentClip = currentClip->next;
  431.     /* any trailing clips with no text get overwritten */
  432.     if (strlen (currentClip->clip) != 0)
  433.     currentClip = NewClip (text, currentClip);
  434.     
  435.     textBlock.ptr = data;
  436.     textBlock.firstPos = 0;
  437.     textBlock.length = len;
  438.     textBlock.format = FMT8BIT;
  439.     if (XawTextReplace(text, 0, TextLength (text), &textBlock))
  440.     XBell( XtDisplay(text), 0);
  441.     set_button_state ();
  442. }
  443.  
  444. EraseTextWidget ()
  445. {
  446.     XawTextBlock block;
  447.  
  448.     block.ptr = "";
  449.     block.length = 0;
  450.     block.firstPos = 0;
  451.     block.format = FMT8BIT;
  452.  
  453.     XawTextReplace(text, 0, INFINITY, &block);
  454.     /* If this fails, too bad. */
  455. }
  456.  
  457.  
  458. XtActionsRec xclipboard_actions[] = {
  459.     "NewClip", NewCurrentClip,
  460.     "NextClip",    NextCurrentClip,
  461.     "PrevClip", PrevCurrentClip,
  462.     "DeleteClip", DeleteCurrentClip,
  463.     "Save", SaveToFile,
  464.     "AcceptSave", AcceptSaveFile,
  465.     "CancelSave", CancelSaveFile,
  466.     "FailContinue", FailContinue,
  467.     "Quit", Quit,
  468.     "WMProtocols", WMProtocols
  469. };
  470.  
  471. static XrmOptionDescRec table[] = {
  472.     {"-w",        "wrap",        XrmoptionNoArg,  "on"},
  473. /*    {"-nw",        "wrap",        XrmoptionNoArg,  "False"} */
  474. };
  475.  
  476. static void    LoseSelection ();
  477. static void    InsertClipboard ();
  478. static Boolean    ConvertSelection();
  479. static Atom    ManagerAtom, ClipboardAtom;
  480.  
  481. /*ARGSUSED*/
  482. static void 
  483. InsertClipboard(w, client_data, selection, type, value, length, format)
  484. Widget w;
  485. XtPointer client_data;
  486. Atom *selection, *type;
  487. XtPointer value;
  488. unsigned long *length;
  489. int *format;
  490. {
  491.     if (*type != XT_CONVERT_FAIL)
  492.     NewCurrentClipContents ((char *) value, *length);
  493.     else
  494.     {
  495.     Arg arg;
  496.     XtSetArg (arg, XtNlabel, "CLIPBOARD selection conversion failed");
  497.     XtSetValues (failDialog, &arg, 1);
  498.     CenterWidgetOnWidget (failDialogShell, text);
  499.     XtPopup (failDialogShell, XtGrabNone);
  500.     XBell( XtDisplay(w), 0 );
  501.     }
  502.     
  503.     XtOwnSelection(top, ClipboardAtom, CurrentTime,
  504.            ConvertSelection, LoseSelection, NULL);
  505.     XFree(value);
  506. }
  507.  
  508. static Boolean ConvertSelection(w, selection, target,
  509.                 type, value, length, format)
  510.     Widget w;
  511.     Atom *selection, *target, *type;
  512.     XtPointer *value;
  513.     unsigned long *length;
  514.     int *format;
  515. {
  516.     Display* d = XtDisplay(w);
  517.     XSelectionRequestEvent* req =
  518.     XtGetSelectionRequest(w, *selection, (XtRequestId)NULL);
  519.  
  520.     if (*target == XA_TARGETS(d)) {
  521.     Atom* targetP;
  522.     Atom* std_targets;
  523.     unsigned long std_length;
  524.     XmuConvertStandardSelection(w, req->time, selection, target, type,
  525.                   (caddr_t*)&std_targets, &std_length, format);
  526.     *value = XtMalloc(sizeof(Atom)*(std_length + 5));
  527.     targetP = *(Atom**)value;
  528.     *targetP++ = XA_STRING;
  529.     *targetP++ = XA_TEXT(d);
  530.     *targetP++ = XA_LENGTH(d);
  531.     *targetP++ = XA_LIST_LENGTH(d);
  532.     *targetP++ = XA_CHARACTER_POSITION(d);
  533.     *length = std_length + (targetP - (*(Atom **) value));
  534.     bcopy((char*)std_targets, (char*)targetP, sizeof(Atom)*std_length);
  535.     XtFree((char*)std_targets);
  536.     *type = XA_ATOM;
  537.     *format = 32;
  538.     return True;
  539.     }
  540.  
  541.     if (*target == XA_LIST_LENGTH(d) ||
  542.     *target == XA_LENGTH(d))
  543.     {
  544.         long * temp;
  545.         
  546.         temp = (long *) XtMalloc(sizeof(long));
  547.         if (*target == XA_LIST_LENGTH(d))
  548.             *temp = 1L;
  549.         else            /* *target == XA_LENGTH(d) */
  550.             *temp = (long) TextLength (text);
  551.         
  552.         *value = (caddr_t) temp;
  553.         *type = XA_INTEGER;
  554.         *length = 1L;
  555.         *format = 32;
  556.         return True;
  557.     }
  558.     
  559.     if (*target == XA_CHARACTER_POSITION(d))
  560.     {
  561.         long * temp;
  562.         
  563.         temp = (long *) XtMalloc(2 * sizeof(long));
  564.         temp[0] = (long) 0;
  565.         temp[1] = TextLength (text);
  566.         *value = (caddr_t) temp;
  567.         *type = XA_SPAN(d);
  568.         *length = 2L;
  569.         *format = 32;
  570.         return True;
  571.     }
  572.     
  573.     if (*target == XA_STRING ||
  574.       *target == XA_TEXT(d) ||
  575.       *target == XA_COMPOUND_TEXT(d))
  576.     {
  577.     extern char *_XawTextGetSTRING();
  578.         if (*target == XA_COMPOUND_TEXT(d))
  579.         *type = *target;
  580.         else
  581.         *type = XA_STRING;
  582.     *length = TextLength (text);
  583.         *value = _XawTextGetSTRING((TextWidget) text, 0, *length);
  584.         *format = 8;
  585.         return True;
  586.     }
  587.     
  588.     if (XmuConvertStandardSelection(w, req->time, selection, target, type,
  589.                     (caddr_t *)value, length, format))
  590.     return True;
  591.  
  592.     return False;
  593. }
  594.  
  595. static void LoseSelection(w, selection)
  596.     Widget w;
  597.     Atom *selection;
  598. {
  599.     XtGetSelectionValue(w, *selection, XA_STRING, InsertClipboard,
  600.             NULL, CurrentTime);
  601. }
  602.  
  603. /*ARGSUSED*/
  604. static Boolean RefuseSelection(w, selection, target,
  605.                    type, value, length, format)
  606.     Widget w;
  607.     Atom *selection, *target, *type;
  608.     XtPointer *value;
  609.     unsigned long *length;
  610.     int *format;
  611. {
  612.     return False;
  613. }
  614.  
  615. /*ARGSUSED*/
  616. static void LoseManager(w, selection)
  617.     Widget w;
  618.     Atom *selection;
  619. {
  620.     XtError("another clipboard has taken over control\n");
  621. }
  622.  
  623. typedef struct {
  624.   Boolean wrap;
  625. } ResourceData, *ResourceDataPtr;
  626.  
  627. static ResourceData userOptions;
  628.  
  629. #define Offset(field) XtOffsetOf(ResourceData, field)
  630.  
  631. XtResource resources[] = {
  632.   {"wrap", "Wrap", XtRBoolean, sizeof(Boolean),
  633.      Offset(wrap), XtRImmediate, (XtPointer)False}
  634. };
  635.  
  636. #undef Offset
  637.  
  638. void
  639. main(argc, argv)
  640. int argc;
  641. char **argv;
  642. {
  643.     Arg args[4];
  644.     Cardinal n;
  645.     XtAppContext xtcontext;
  646.     Widget parent, quit, delete, new, save;
  647.  
  648.     top = XtAppInitialize( &xtcontext, "XClipboard", table, XtNumber(table),
  649.               &argc, argv, NULL, NULL, 0);
  650.  
  651.     XtGetApplicationResources(top, (XtPointer)&userOptions, resources, 
  652.                   XtNumber(resources), NULL, 0);
  653.  
  654.     XtAppAddActions (xtcontext,
  655.              xclipboard_actions, XtNumber (xclipboard_actions));
  656.     /* CLIPBOARD_MANAGER is a non-standard mechanism */
  657.     ManagerAtom = XInternAtom(XtDisplay(top), "CLIPBOARD_MANAGER", False);
  658.     ClipboardAtom = XA_CLIPBOARD(XtDisplay(top));
  659.     if (XGetSelectionOwner(XtDisplay(top), ManagerAtom))
  660.     XtError("another clipboard is already running\n");
  661.  
  662.     parent = XtCreateManagedWidget("form", formWidgetClass, top, NULL, ZERO);
  663.     quit = XtCreateManagedWidget("quit", Command, parent, NULL, ZERO);
  664.     delete = XtCreateManagedWidget("delete", Command, parent, NULL, ZERO);
  665.     new = XtCreateManagedWidget("new", Command, parent, NULL, ZERO);
  666.     save = XtCreateManagedWidget("save", Command, parent, NULL, ZERO);
  667.     nextButton = XtCreateManagedWidget("next", Command, parent, NULL, ZERO);
  668.     prevButton = XtCreateManagedWidget("prev", Command, parent, NULL, ZERO);
  669.     indexLabel = XtCreateManagedWidget("index", Label, parent, NULL, ZERO);
  670.  
  671.     n=0;
  672.     XtSetArg(args[n], XtNtype, XawAsciiString); n++;
  673.     XtSetArg(args[n], XtNeditType, XawtextEdit); n++;
  674.     if (userOptions.wrap) {
  675.     XtSetArg(args[n], XtNwrap, XawtextWrapWord); n++;
  676.     XtSetArg(args[n], XtNscrollHorizontal, False); n++;
  677.     }
  678.  
  679.     text = XtCreateManagedWidget( "text", Text, parent, args, n);
  680.     
  681.     currentClip = NewClip (text, (ClipPtr) 0);
  682.  
  683.     set_button_state ();
  684.  
  685.     fileDialogShell = XtCreatePopupShell("fileDialogShell",
  686.                      transientShellWidgetClass,
  687.                      top, NULL, ZERO);
  688.     fileDialog = XtCreateManagedWidget ("fileDialog", dialogWidgetClass,
  689.                     fileDialogShell, NULL, ZERO);
  690.     XawDialogAddButton(fileDialog, "accept", NULL, NULL);
  691.     XawDialogAddButton(fileDialog, "cancel", NULL, NULL);
  692.  
  693.     failDialogShell = XtCreatePopupShell("failDialogShell",
  694.                      transientShellWidgetClass,
  695.                      top, NULL, ZERO);
  696.     failDialog = XtCreateManagedWidget ("failDialog", dialogWidgetClass,
  697.                     failDialogShell, NULL, ZERO);
  698.     XawDialogAddButton (failDialog, "continue", NULL, NULL);
  699.  
  700.     XtRealizeWidget(top);
  701.     XtRealizeWidget(fileDialogShell);
  702.     XtRealizeWidget(failDialogShell);
  703.     XtOwnSelection(top, ManagerAtom, CurrentTime,
  704.            RefuseSelection, LoseManager, NULL);
  705.     if (XGetSelectionOwner (XtDisplay(top), ClipboardAtom)) {
  706.     LoseSelection (top, &ClipboardAtom);
  707.     } else {
  708.         XtOwnSelection(top, ClipboardAtom, CurrentTime,
  709.                ConvertSelection, LoseSelection, NULL);
  710.     }
  711.     wm_delete_window = XInternAtom(XtDisplay(top), "WM_DELETE_WINDOW", False);
  712.     wm_protocols = XInternAtom(XtDisplay(top), "WM_PROTOCOLS", False);
  713.     (void) XSetWMProtocols(XtDisplay(top), XtWindow(top), &wm_delete_window,1);
  714.     (void) XSetWMProtocols(XtDisplay(top), XtWindow(fileDialogShell),
  715.                &wm_delete_window,1);
  716.     (void) XSetWMProtocols(XtDisplay(top), XtWindow(failDialogShell),
  717.                &wm_delete_window,1);
  718.     XtAppMainLoop(xtcontext);
  719. }
  720.