home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume4 / xconf / part01 next >
Encoding:
Internet Message Format  |  1993-04-28  |  55.9 KB

  1. From: argv@island.uu.net (Dan Heller)
  2. Newsgroups: comp.sources.x
  3. Subject: v04i082: xconf -- X-based conferencing tool, Part01/05
  4. Message-ID: <933@island.uu.net>
  5. Date: 25 Jul 89 08:10:11 GMT
  6. Approved: island!argv@sun.com
  7.  
  8. Submitted-by: Jon Crowcroft <J.Crowcroft@Cs.Ucl.AC.UK>
  9. Posting-number: Volume 4, Issue 82
  10. Archive-name: xconf/part01
  11.  
  12. [ This seems to be sun-specific since it uses sun rpc's.  I didn't look
  13.   at the code to be sure, tho.  It compiled fine using the Makefile tho
  14.   I had to modify it to point to a place where IntrinsicI.h is used (it
  15.   is no longer in the X11 include files as it was in R2; it's now in the
  16.   lib/Xt dir in the R3 source tree).  Also, Text.c was too big so I hadda
  17.   split it up into 3 parts (Text.c.a[abc] -- be sure to glue them back
  18.   together before trying to make).  By its description, it seems like a
  19.   useful program.  --argv ]
  20.  
  21. #! /bin/sh
  22. # This is a shell archive.  Remove anything before this line, then feed it
  23. # into a shell via "sh file" or similar.  To overwrite existing files,
  24. # type "sh file -c".
  25. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  26. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  27. # If this archive is complete, you will see the following message at the end:
  28. #        "End of archive 1 (of 5)."
  29. # Contents:  xconf/HELP xconf/Text.c.aa xconf/xconf.c
  30. # Wrapped by argv@sumatra on Tue Jul 25 01:01:04 1989
  31. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  32. if test -f 'xconf/HELP' -a "${1}" != "-c" ; then 
  33.   echo shar: Will not clobber existing file \"'xconf/HELP'\"
  34. else
  35. echo shar: Extracting \"'xconf/HELP'\" \(2603 characters\)
  36. sed "s/^X//" >'xconf/HELP' <<'END_OF_FILE'
  37. XDESCRIPTION...
  38. XXconf is a simple text based conferencing program.
  39. X
  40. XIt works by opening multiple windows, one per conferee, one on each
  41. Xconferees displays (does not pre-empt user being in multiple
  42. Xconferences though).
  43. X
  44. XIt sets up a top level window with quit/help/accept buttons.
  45. XAccept popups a box widget with multiple asciiTextwidget's (one per
  46. Xconferee). One is for input, the rest show what every one is typeing
  47. Xon their input windows...
  48. X
  49. XNote that the ascii widget is like a jove edit window, and that edit
  50. Xcommands typed in it will have the same effect on the output windows
  51. Xon each other conferees display as on your input window. [Try typing
  52. XCtl-V to go down a page, Meta-V to go up].
  53. X
  54. XOne user starts the conference, specifying all the users (including
  55. Xthemselves) at startup.
  56. XUsers may choose not to accept the conference, by quiting immediately.
  57. XWhen the last person quits, the conference terminates.
  58. X
  59. XA User is specified by user name. This may be optionally appended by
  60. Xa machine (user@machine) and also by a display
  61. X(user@machine:Display#). if the user name appears alone, it can be
  62. Xused to find where the user is logged in, and which of possibly many
  63. Xlogins is least recently idle. If the machine/display is specified,
  64. Xthe user name is ignored, and used simply as a tag for their
  65. Xconference windows.
  66. X
  67. XThere is no floor control at present, so it is a "free for all" 
  68. Xconference, just like an n-way talk.
  69. X
  70. X
  71. XNOTE BENE: 
  72. X
  73. XUnder twm, you need to set NoTitleFocus in your .twmrc file, else
  74. Xkeyboard input never gets focused properly - a sort of feature of twm
  75. X- not really a bug in xconf though...
  76. X
  77. XUSAGE...
  78. XTo run, type
  79. X
  80. Xxconf <user@machine>+ [-typicalXArgs]
  81. X
  82. Xe.g. 
  83. Xxconf jon@perky pp@lagavulin steve@lion -fg green -bg blue
  84. X
  85. XA box appears on each users display, with three command buttons:
  86. X
  87. XQuit
  88. XQuits now, or at any point in the conference.
  89. X
  90. XHelp
  91. XPopups a help window with soem assistance displayed, and a subsidery
  92. Xquit button.
  93. X
  94. XAccept
  95. XAccepts the conference, Popups a new box, with a text window for this
  96. Xuser to type in, and other users input to be output on. The windows
  97. Xare labelled to show whose is whose. If you quit, all the windows
  98. Xvanish on your display, and your output window vanishes onm each other
  99. Xpersons display.
  100. X
  101. XYou type at the widnow marked <= in.
  102. X
  103. XBUGS...
  104. XCurrently there are some odd problems with some window managers.
  105. X
  106. XIf the user who started the conference kills the program, the
  107. Xconference terminates for everyone else [although they may just quit
  108. Xwithout this happening].
  109. X
  110. XWhen you quit, you output window on other conferees display is
  111. Xdestroyed, but not the label.
  112. END_OF_FILE
  113. if test 2603 -ne `wc -c <'xconf/HELP'`; then
  114.     echo shar: \"'xconf/HELP'\" unpacked with wrong size!
  115. fi
  116. # end of 'xconf/HELP'
  117. fi
  118. if test -f 'xconf/Text.c.aa' -a "${1}" != "-c" ; then 
  119.   echo shar: Will not clobber existing file \"'xconf/Text.c.aa'\"
  120. else
  121. echo shar: Extracting \"'xconf/Text.c.aa'\" \(30780 characters\)
  122. sed "s/^X//" >'xconf/Text.c.aa' <<'END_OF_FILE'
  123. X#ifndef lint
  124. Xstatic char Xrcsid[] = "$XConsortium: Text.c,v 1.77 88/10/25 00:14:46 jim Exp $";
  125. X#endif
  126. X
  127. X
  128. X/***********************************************************
  129. XCopyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
  130. Xand the Massachusetts Institute of Technology, Cambridge, Massachusetts.
  131. X
  132. X                        All Rights Reserved
  133. X
  134. XPermission to use, copy, modify, and distribute this software and its 
  135. Xdocumentation for any purpose and without fee is hereby granted, 
  136. Xprovided that the above copyright notice appear in all copies and that
  137. Xboth that copyright notice and this permission notice appear in 
  138. Xsupporting documentation, and that the names of Digital or MIT not be
  139. Xused in advertising or publicity pertaining to distribution of the
  140. Xsoftware without specific, written prior permission.  
  141. X
  142. XDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  143. XALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  144. XDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  145. XANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  146. XWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  147. XARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  148. XSOFTWARE.
  149. X
  150. X******************************************************************/
  151. X
  152. X#include <X11/IntrinsicP.h>
  153. X#include <X11/StringDefs.h>
  154. X#include <X11/Shell.h>
  155. X#include <X11/Xatom.h>
  156. X#include <X11/Xmu.h>
  157. X#include <X11/Cardinals.h>
  158. X#include <X11/Label.h>
  159. X#include <X11/Command.h>
  160. X#include <X11/Dialog.h>
  161. X#include <X11/Scroll.h>
  162. X#include "TextP.h"
  163. X
  164. XAtom FMT8BIT = NULL;
  165. X
  166. Xextern void bcopy();
  167. Xextern void LowerCase();
  168. Xextern int errno, sys_nerr;
  169. Xextern char* sys_errlist[];
  170. X
  171. X#define abs(x)    (((x) < 0) ? (-(x)) : (x))
  172. X#define min(x,y)    ((x) < (y) ? (x) : (y))
  173. X#define max(x,y)    ((x) > (y) ? (x) : (y))
  174. X#define GETLASTPOS  (*ctx->text.source->Scan) (ctx->text.source, 0, XtstAll, XtsdRight, 1, TRUE)
  175. X
  176. X#define zeroPosition ((XtTextPosition) 0)
  177. X#define BIGNUM ((Dimension)32023)
  178. X
  179. Xstatic void BuildLineTable ();
  180. Xstatic void ScrollUpDownProc();
  181. Xstatic void ThumbProc();
  182. X
  183. X/****************************************************************
  184. X *
  185. X * Full class record constant
  186. X *
  187. X ****************************************************************/
  188. X
  189. Xstatic XtTextSelectType defaultSelectTypes[] = {
  190. X    XtselectPosition,
  191. X    XtselectWord,
  192. X    XtselectLine,
  193. X    XtselectParagraph,
  194. X    XtselectAll,
  195. X    XtselectNull
  196. X};
  197. X
  198. Xstatic caddr_t defaultSelectTypesPtr = (caddr_t)defaultSelectTypes;
  199. Xextern char defaultTextTranslations[];    /* fwd ref */
  200. Xstatic Dimension defWidth = 100;
  201. Xstatic Dimension defHeight = DEFAULT_TEXT_HEIGHT;
  202. X
  203. X#define offset(field) XtOffset(TextWidget, field)
  204. Xstatic XtResource resources[] = {
  205. X    {XtNwidth, XtCWidth, XtRDimension, sizeof(Dimension),
  206. X        offset(core.width), XtRDimension, (caddr_t)&defWidth},
  207. X    {XtNcursor, XtCCursor, XtRCursor, sizeof(Cursor),
  208. X    offset(simple.cursor), XtRString, "xterm"},
  209. X    {XtNheight, XtCHeight, XtRDimension, sizeof(Dimension),
  210. X        offset(core.height), XtRDimension, (caddr_t)&defHeight},
  211. X    {XtNtextOptions, XtCTextOptions, XtRInt, sizeof (int),
  212. X        offset(text.options), XtRImmediate, (caddr_t)0},
  213. X    {XtNdialogHOffset, XtCMargin, XtRInt, sizeof(int),
  214. X     offset(text.dialog_horiz_offset), XtRImmediate, (caddr_t)0},
  215. X    {XtNdialogVOffset, XtCMargin, XtRInt, sizeof(int),
  216. X     offset(text.dialog_vert_offset), XtRImmediate, (caddr_t)0},
  217. X    {XtNdisplayPosition, XtCTextPosition, XtRInt,
  218. X     sizeof (XtTextPosition), offset(text.lt.top), XtRImmediate, (caddr_t)0},
  219. X    {XtNinsertPosition, XtCTextPosition, XtRInt,
  220. X        sizeof(XtTextPosition), offset(text.insertPos), XtRImmediate, (caddr_t)0},
  221. X    {XtNleftMargin, XtCMargin, XtRDimension, sizeof (Dimension),
  222. X        offset(text.client_leftmargin), XtRImmediate, (caddr_t)2},
  223. X    {XtNselectTypes, XtCSelectTypes, XtRPointer,
  224. X        sizeof(XtTextSelectType*), offset(text.sarray),
  225. X    XtRPointer, (caddr_t)&defaultSelectTypesPtr},
  226. X    {XtNtextSource, XtCTextSource, XtRPointer, sizeof (caddr_t),
  227. X         offset(text.source), XtRPointer, NULL},
  228. X    {XtNtextSink, XtCTextSink, XtRPointer, sizeof (caddr_t),
  229. X         offset(text.sink), XtRPointer, NULL},
  230. X    {XtNselection, XtCSelection, XtRPointer, sizeof(caddr_t),
  231. X     offset(text.s), XtRPointer, NULL},
  232. X#ifdef JON
  233. X    {XtNcallback, XtCCallback, XtRCallback, sizeof(caddr_t),
  234. X     offset(text.callbacks), XtRCallback, (caddr_t)NULL},
  235. X#endif JON
  236. X};
  237. X#undef offset
  238. X
  239. X  
  240. X#define done(address, type) \
  241. X        { toVal->size = sizeof(type); toVal->addr = (caddr_t) address; }
  242. X
  243. X/* EditType enumeration constants */
  244. X
  245. Xstatic  XrmQuark  XtQTextRead;
  246. Xstatic  XrmQuark  XtQTextAppend;
  247. Xstatic  XrmQuark  XtQTextEdit;
  248. X
  249. X/* ARGSUSED */
  250. Xstatic void CvtStringToEditMode(args, num_args, fromVal, toVal)
  251. X    XrmValuePtr args;        /* unused */
  252. X    Cardinal    *num_args;    /* unused */
  253. X    XrmValuePtr    fromVal;
  254. X    XrmValuePtr    toVal;
  255. X{
  256. X    static XtTextEditType editType;
  257. X    XrmQuark    q;
  258. X    char        lowerName[1000];
  259. X
  260. X/* ||| where to put LowerCase */
  261. X    LowerCase((char *)fromVal->addr, lowerName);
  262. X    q = XrmStringToQuark(lowerName);
  263. X    if (q == XtQTextRead ) {
  264. X        editType = XttextRead;
  265. X        done(&editType, XtTextEditType);
  266. X        return;
  267. X    }
  268. X    if (q == XtQTextAppend) {
  269. X        editType = XttextAppend;
  270. X        done(&editType, XtTextEditType);
  271. X        return;
  272. X    }
  273. X    if (q == XtQTextEdit) {
  274. X        editType = XttextEdit;
  275. X        done(&editType, XtTextEditType);
  276. X        return;
  277. X    }
  278. X    toVal->size = 0;
  279. X    toVal->addr = NULL;
  280. X};
  281. X
  282. X
  283. Xstatic void ClassInitialize()
  284. X{
  285. X    XtQTextRead   = XrmStringToQuark(XtEtextRead);
  286. X    XtQTextAppend = XrmStringToQuark(XtEtextAppend);
  287. X    XtQTextEdit   = XrmStringToQuark(XtEtextEdit);
  288. X
  289. X    XtAddConverter(XtRString, XtREditMode, CvtStringToEditMode, NULL, 0);
  290. X}
  291. X
  292. Xstatic void CreateScrollbar(w)
  293. X    TextWidget w;
  294. X{
  295. X    Arg args[1];
  296. X    Dimension bw;
  297. X    Widget sbar;
  298. X
  299. X    XtSetArg(args[0], XtNheight, w->core.height);
  300. X    w->text.sbar = sbar =
  301. X        XtCreateWidget("scrollbar", scrollbarWidgetClass, w, args, ONE);
  302. X    XtAddCallback( sbar, XtNscrollProc, ScrollUpDownProc, (caddr_t)w );
  303. X    XtAddCallback( sbar, XtNjumpProc, ThumbProc, (caddr_t)w );
  304. X    w->text.leftmargin += sbar->core.width + (bw = sbar->core.border_width);
  305. X    XtMoveWidget( sbar, -(Position)bw, -(Position)bw );
  306. X}
  307. X
  308. X/* ARGSUSED */
  309. Xstatic void Initialize(request, new)
  310. X Widget request, new;
  311. X{
  312. X    TextWidget ctx = (TextWidget) new;
  313. X
  314. X    if (!FMT8BIT)
  315. X        FMT8BIT = XInternAtom(XtDisplay(new), "FMT8BIT", False);
  316. X
  317. X    if (ctx->core.height == DEFAULT_TEXT_HEIGHT) {
  318. X        ctx->core.height = (2*yMargin) + 2;
  319. X        if (ctx->text.sink)
  320. X        ctx->core.height += (*ctx->text.sink->MaxHeight)(new, 1);
  321. X    }
  322. X
  323. X    ctx->text.lt.lines = 0;
  324. X    ctx->text.lt.info = NULL;
  325. X    ctx->text.s.left = ctx->text.s.right = 0;
  326. X    ctx->text.s.type = XtselectPosition;
  327. X    ctx->text.s.selections = NULL;
  328. X    ctx->text.s.atom_count = ctx->text.s.array_size = 0;
  329. X    ctx->text.sbar = ctx->text.outer = NULL;
  330. X    ctx->text.lasttime = 0; /* ||| correct? */
  331. X    ctx->text.time = 0; /* ||| correct? */
  332. X    ctx->text.showposition = TRUE;
  333. X    ctx->text.lastPos = ctx->text.source ? GETLASTPOS : 0;
  334. X    ctx->text.dialog = NULL;
  335. X    ctx->text.updateFrom = (XtTextPosition *) XtMalloc((unsigned)1);
  336. X    ctx->text.updateTo = (XtTextPosition *) XtMalloc((unsigned)1);
  337. X    ctx->text.numranges = ctx->text.maxranges = 0;
  338. X    ctx->text.gc = DefaultGCOfScreen(XtScreen(ctx));
  339. X    ctx->text.hasfocus = FALSE;
  340. X    ctx->text.leftmargin = ctx->text.client_leftmargin;
  341. X    ctx->text.update_disabled = False;
  342. X    ctx->text.old_insert = -1;
  343. X
  344. X    if (ctx->text.options & scrollVertical)
  345. X    CreateScrollbar(ctx);
  346. X}
  347. X
  348. Xvoid ForceBuildLineTable();
  349. X
  350. Xstatic void Realize( w, valueMask, attributes )
  351. X   Widget w;
  352. X   Mask *valueMask;
  353. X   XSetWindowAttributes *attributes;
  354. X{
  355. X   TextWidget ctx = (TextWidget)w;
  356. X
  357. X   *valueMask |= CWBitGravity;
  358. X   attributes->bit_gravity =
  359. X       (ctx->text.options & wordBreak) ? ForgetGravity : NorthWestGravity;
  360. X
  361. X   (*textClassRec.core_class.superclass->core_class.realize)
  362. X       (w, valueMask, attributes);
  363. X
  364. X   if (ctx->text.sbar) {
  365. X       XtRealizeWidget(ctx->text.sbar);
  366. X       XtMapWidget(ctx->text.sbar);
  367. X   }
  368. X   ForceBuildLineTable(ctx);
  369. X}
  370. X
  371. X
  372. Xstatic /*void*/ _CreateCutBuffers(d)
  373. X    Display *d;
  374. X{
  375. X    static struct _DisplayRec {
  376. X    struct _DisplayRec *next;
  377. X    Display *dpy;
  378. X    } *dpy_list = NULL;
  379. X    struct _DisplayRec *dpy_ptr;
  380. X
  381. X    for (dpy_ptr = dpy_list; dpy_ptr != NULL; dpy_ptr = dpy_ptr->next) {
  382. X    if (dpy_ptr->dpy == d) return;
  383. X    }
  384. X
  385. X    dpy_ptr = XtNew(struct _DisplayRec);
  386. X    dpy_ptr->next = dpy_list;
  387. X    dpy_ptr->dpy = d;
  388. X    dpy_list = dpy_ptr;
  389. X
  390. X#define Create(buffer) \
  391. X    XChangeProperty(d, RootWindow(d, 0), buffer, XA_STRING, 8, \
  392. X            PropModeAppend, NULL, 0 );
  393. X
  394. X    Create( XA_CUT_BUFFER0 );
  395. X    Create( XA_CUT_BUFFER1 );
  396. X    Create( XA_CUT_BUFFER2 );
  397. X    Create( XA_CUT_BUFFER3 );
  398. X    Create( XA_CUT_BUFFER4 );
  399. X    Create( XA_CUT_BUFFER5 );
  400. X    Create( XA_CUT_BUFFER6 );
  401. X    Create( XA_CUT_BUFFER7 );
  402. X
  403. X#undef Create
  404. X}
  405. X
  406. X/* Utility routines for support of Text */
  407. X
  408. X
  409. X/*
  410. X * Procedure to manage insert cursor visibility for editable text.  It uses
  411. X * the value of ctx->insertPos and an implicit argument. In the event that
  412. X * position is immediately preceded by an eol graphic, then the insert cursor
  413. X * is displayed at the beginning of the next line.
  414. X*/
  415. Xstatic void InsertCursor (w, state)
  416. X  Widget w;
  417. X  XtTextInsertState state;
  418. X{
  419. X    TextWidget ctx = (TextWidget)w;
  420. X    Position x, y;
  421. X    int dy, line, visible;
  422. X    XtTextBlock text;
  423. X
  424. X    if (ctx->text.lt.lines < 1) return;
  425. X    visible = LineAndXYForPosition(ctx, ctx->text.insertPos, &line, &x, &y);
  426. X    if (line < ctx->text.lt.lines)
  427. X    dy = (ctx->text.lt.info[line + 1].y - ctx->text.lt.info[line].y) + 1;
  428. X    else
  429. X    dy = (ctx->text.lt.info[line].y - ctx->text.lt.info[line - 1].y) + 1;
  430. X
  431. X    /** If the insert position is just after eol then put it on next line **/
  432. X    if (x > ctx->text.leftmargin &&
  433. X    ctx->text.insertPos > 0 &&
  434. X    ctx->text.insertPos >= ctx->text.lastPos) {
  435. X       /* reading the source is bogus and this code should use scan */
  436. X       (*ctx->text.source->Read) (ctx->text.source, ctx->text.insertPos - 1, &text, 1);
  437. X       if (text.ptr[0] == '\n') {
  438. X           x = ctx->text.leftmargin;
  439. X           y += dy;
  440. X       }
  441. X    }
  442. X    y += dy;
  443. X    if (visible)
  444. X    (*ctx->text.sink->InsertCursor)(w, x, y, state);
  445. X    ctx->text.ev_x = x;
  446. X    ctx->text.ev_y = y;
  447. X}
  448. X
  449. X
  450. X/*
  451. X * Procedure to register a span of text that is no longer valid on the display
  452. X * It is used to avoid a number of small, and potentially overlapping, screen
  453. X * updates. [note: this is really a private procedure but is used in
  454. X * multiple modules].
  455. X*/
  456. X_XtTextNeedsUpdating(ctx, left, right)
  457. X  TextWidget ctx;
  458. X  XtTextPosition left, right;
  459. X{
  460. X    int     i;
  461. X    if (left < right) {
  462. X    for (i = 0; i < ctx->text.numranges; i++) {
  463. X        if (left <= ctx->text.updateTo[i] && right >= ctx->text.updateFrom[i]) {
  464. X        ctx->text.updateFrom[i] = min(left, ctx->text.updateFrom[i]);
  465. X        ctx->text.updateTo[i] = max(right, ctx->text.updateTo[i]);
  466. X        return;
  467. X        }
  468. X    }
  469. X    ctx->text.numranges++;
  470. X    if (ctx->text.numranges > ctx->text.maxranges) {
  471. X        ctx->text.maxranges = ctx->text.numranges;
  472. X        i = ctx->text.maxranges * sizeof(XtTextPosition);
  473. X        ctx->text.updateFrom = (XtTextPosition *) 
  474. X               XtRealloc((char *)ctx->text.updateFrom, (unsigned) i);
  475. X        ctx->text.updateTo = (XtTextPosition *) 
  476. X        XtRealloc((char *)ctx->text.updateTo, (unsigned) i);
  477. X    }
  478. X    ctx->text.updateFrom[ctx->text.numranges - 1] = left;
  479. X    ctx->text.updateTo[ctx->text.numranges - 1] = right;
  480. X    }
  481. X}
  482. X
  483. X
  484. X/*
  485. X * Procedure to read a span of text in Ascii form. This is purely a hack and
  486. X * we probably need to add a function to sources to provide this functionality.
  487. X * [note: this is really a private procedure but is used in multiple modules].
  488. X*/
  489. Xchar *_XtTextGetText(ctx, left, right)
  490. X  TextWidget ctx;
  491. X  XtTextPosition left, right;
  492. X{
  493. X    char   *result, *tempResult;
  494. X    int length, resultLength;
  495. X    XtTextBlock text;
  496. X    XtTextPosition end, nend;
  497. X    
  498. X    resultLength = right - left + 10;    /* Bogus? %%% */
  499. X    result = (char *)XtMalloc((unsigned) resultLength);
  500. X    end = (*ctx->text.source->Read)(ctx->text.source, left, &text, right - left);
  501. X    (void) strncpy(result, text.ptr, text.length);
  502. X    length = text.length;
  503. X    while (end < right) {
  504. X        nend = (*ctx->text.source->Read)(ctx->text.source, end, &text, right - end);
  505. X    tempResult = result + length;
  506. X        (void) strncpy(tempResult, text.ptr, text.length);
  507. X    length += text.length;
  508. X        end = nend;
  509. X    }
  510. X    result[length] = 0;
  511. X    return result;
  512. X}
  513. X
  514. X
  515. X
  516. X/* 
  517. X * This routine maps an x and y position in a window that is displaying text
  518. X * into the corresponding position in the source.
  519. X */
  520. Xstatic XtTextPosition PositionForXY (ctx, x, y)
  521. X  TextWidget ctx;
  522. X  Position x,y;
  523. X{
  524. X /* it is illegal to call this routine unless there is a valid line table! */
  525. X    int     width, fromx, line;
  526. X    XtTextPosition position, resultstart, resultend;
  527. X
  528. X    /*** figure out what line it is on ***/
  529. X    if (ctx->text.lt.lines == 0) return 0;
  530. X
  531. X    for (line = 0; line < ctx->text.lt.lines - 1; line++) {
  532. X    if (y <= ctx->text.lt.info[line + 1].y)
  533. X        break;
  534. X    }
  535. X    position = ctx->text.lt.info[line].position;
  536. X    if (position >= ctx->text.lastPos)
  537. X    return ctx->text.lastPos;
  538. X    fromx = ctx->text.lt.info[line].x;    /* starting x in line */
  539. X    width = x - fromx;            /* num of pix from starting of line */
  540. X    (*ctx->text.sink->Resolve) (ctx, position, fromx, width,
  541. X        &resultstart, &resultend);
  542. X    if (resultstart >= ctx->text.lt.info[line + 1].position)
  543. X    resultstart = (*ctx->text.source->Scan)(ctx->text.source,
  544. X        ctx->text.lt.info[line + 1].position, XtstPositions, XtsdLeft, 1, TRUE);
  545. X    return resultstart;
  546. X}
  547. X
  548. X/*
  549. X * This routine maps a source position in to the corresponding line number
  550. X * of the text that is displayed in the window.
  551. X*/
  552. Xstatic int LineForPosition (ctx, position)
  553. X  TextWidget ctx;
  554. X  XtTextPosition position;
  555. X  /* it is illegal to call this routine unless there is a valid line table!*/
  556. X{
  557. X    int     line;
  558. X
  559. X    if (position <= ctx->text.lt.info[0].position)
  560. X    return 0;
  561. X    for (line = 0; line < ctx->text.lt.lines; line++)
  562. X    if (position < ctx->text.lt.info[line + 1].position)
  563. X        break;
  564. X    return line;
  565. X}
  566. X
  567. X/*
  568. X * This routine maps a source position into the corresponding line number
  569. X * and the x, y coordinates of the text that is displayed in the window.
  570. X*/
  571. Xstatic int LineAndXYForPosition (ctx, pos, line, x, y)
  572. X  TextWidget ctx;
  573. X  XtTextPosition pos;
  574. X  int *line;
  575. X  Position *x, *y;
  576. X  /* it is illegal to call this routine unless there is a valid line table!*/
  577. X{
  578. X    XtTextPosition linePos, endPos;
  579. X    int     visible, realW, realH;
  580. X
  581. X    *line = 0;
  582. X    *x = ctx->text.leftmargin;
  583. X    *y = yMargin;
  584. X    visible = IsPositionVisible(ctx, pos);
  585. X    if (visible) {
  586. X    *line = LineForPosition(ctx, pos);
  587. X    *y = ctx->text.lt.info[*line].y;
  588. X    *x = ctx->text.lt.info[*line].x;
  589. X    linePos = ctx->text.lt.info[*line].position;
  590. X    (*ctx->text.sink->FindDistance)((Widget)ctx, linePos,
  591. X                                     *x, pos, &realW, &endPos, &realH);
  592. X    *x = *x + realW;
  593. X    }
  594. X    return visible;
  595. X}
  596. X
  597. X/*
  598. X * This routine builds a line table. It does this by starting at the
  599. X * specified position and measuring text to determine the staring position
  600. X * of each line to be displayed. It also determines and saves in the
  601. X * linetable all the required metrics for displaying a given line (e.g.
  602. X * x offset, y offset, line length, etc.).
  603. X*/
  604. Xstatic void BuildLineTable (ctx, position)
  605. X  TextWidget ctx;
  606. X  XtTextPosition position;
  607. X{
  608. X    Position x, y;
  609. X    int width, realW, realH;
  610. X    int line, lines;
  611. X    XtTextPosition startPos, endPos;
  612. X    Boolean     rebuild;
  613. X
  614. X    rebuild = (Boolean) (position != ctx->text.lt.top);
  615. X    lines = (*ctx->text.sink->MaxLines)((Widget)ctx, ctx->core.height);
  616. X    if (ctx->text.lt.info != NULL && lines != ctx->text.lt.lines) {
  617. X    XtFree((char *) ctx->text.lt.info);
  618. X    ctx->text.lt.info = NULL;
  619. X    }
  620. X    if (ctx->text.lt.info == NULL) {
  621. X    ctx->text.lt.info = (XtTextLineTableEntry *)
  622. X        XtCalloc((unsigned)lines + 1, (unsigned)sizeof(XtTextLineTableEntry));
  623. X    rebuild = TRUE;
  624. X    }
  625. X    if (rebuild) {
  626. X    XtTextLineTableEntry *lt;
  627. X    int options = ctx->text.options;
  628. X    int (*FindPosition)() = ctx->text.sink->FindPosition;
  629. X    int (*Scan)() = ctx->text.source->Scan;
  630. X    ctx->text.lt.top = position;
  631. X    ctx->text.lt.lines = lines;
  632. X    startPos = position;
  633. X    x = ctx->text.leftmargin;
  634. X    y = yMargin;
  635. X    for (line = 0, lt = ctx->text.lt.info; line <= ctx->text.lt.lines;
  636. X         line++, lt++) {
  637. X        lt->x = x;
  638. X        lt->y = y;
  639. X        lt->position = startPos;
  640. X        if (startPos <= ctx->text.lastPos) {
  641. X        width = (options & resizeWidth) ? BIGNUM : ctx->core.width - x;
  642. X        (*FindPosition)((Widget)ctx, startPos, x,
  643. X                width, (options & wordBreak),
  644. X                &endPos, &realW, &realH);
  645. X        if (!(options & wordBreak) && endPos < ctx->text.lastPos) {
  646. X            endPos = (*Scan)(ctx->text.source, startPos,
  647. X                     XtstEOL, XtsdRight, 1, TRUE);
  648. X            if (endPos == startPos)
  649. X            endPos = ctx->text.lastPos + 1;
  650. X        }
  651. X        lt->endX = realW + x;
  652. X        startPos = endPos;
  653. X        }
  654. X        else lt->endX = x;
  655. X        y = y + realH;
  656. X    }
  657. X    }
  658. X}
  659. X
  660. X/*
  661. X * This routine is used to re-display the entire window, independent of
  662. X * its current state.
  663. X*/
  664. Xvoid ForceBuildLineTable(ctx)
  665. X    TextWidget ctx;
  666. X{
  667. X    XtTextPosition position;
  668. X
  669. X    position = ctx->text.lt.top;
  670. X    ctx->text.lt.top++; /* ugly, but it works */
  671. X    BuildLineTable(ctx, position);
  672. X}
  673. X
  674. X/*
  675. X * This routine is used by Text to notify an associated scrollbar of the
  676. X * correct metrics (position and shown fraction) for the text being currently
  677. X * displayed in the window.
  678. X*/
  679. Xstatic void SetScrollBar(ctx)
  680. X    TextWidget ctx;
  681. X{
  682. X    float   first, last;
  683. X    if (ctx->text.sbar) {
  684. X    if ((ctx->text.lastPos > 0)  &&  (ctx->text.lt.lines > 0)) {
  685. X        first = ctx->text.lt.top;
  686. X        first /= ctx->text.lastPos; 
  687. X                    /* Just an approximation */
  688. X        last = ctx->text.lt.info[ctx->text.lt.lines].position;
  689. X        last /= ctx->text.lastPos;
  690. X    }
  691. X    else {
  692. X        first = 0.0;
  693. X        last = 1.0;
  694. X    }
  695. X    XtScrollBarSetThumb(ctx->text.sbar, first, last - first);
  696. X    }
  697. X}
  698. X
  699. X
  700. X/*
  701. X * The routine will scroll the displayed text by lines.  If the arg  is
  702. X * positive, move up; otherwise, move down. [note: this is really a private
  703. X * procedure but is used in multiple modules].
  704. X*/
  705. X_XtTextScroll(ctx, n)
  706. X  TextWidget ctx;
  707. X  int n;            /* assumed <= ctx->text.lt.lines */
  708. X{
  709. X    XtTextPosition top, target;
  710. X    if (n >= 0) {
  711. X    top = min(ctx->text.lt.info[n].position, ctx->text.lastPos);
  712. X    BuildLineTable(ctx, top);
  713. X    if (top >= ctx->text.lastPos)
  714. X        DisplayTextWindow(ctx);
  715. X    else {
  716. X        XCopyArea(XtDisplay(ctx), XtWindow(ctx), XtWindow(ctx), ctx->text.gc,
  717. X              0, ctx->text.lt.info[n].y, (int)ctx->core.width,
  718. X              (int)ctx->core.height - ctx->text.lt.info[n].y,
  719. X              0, ctx->text.lt.info[0].y);
  720. X        (*ctx->text.sink->ClearToBackground)(ctx, 0,
  721. X        ctx->text.lt.info[0].y + ctx->core.height - ctx->text.lt.info[n].y,
  722. X        (int)ctx->core.width, (int)ctx->core.height);
  723. X        if (n < ctx->text.lt.lines) n++; /* update descenders at bottom */
  724. X        _XtTextNeedsUpdating(ctx,
  725. X            ctx->text.lt.info[ctx->text.lt.lines - n].position, ctx->text.lastPos);
  726. X        SetScrollBar(ctx);
  727. X    }
  728. X    } else {
  729. X    int tempHeight;
  730. X    n = -n;
  731. X    target = ctx->text.lt.top;
  732. X    top = (*ctx->text.source->Scan)(ctx->text.source, target, XtstEOL,
  733. X                     XtsdLeft, n+1, FALSE);
  734. X    BuildLineTable(ctx, top);
  735. X    if (ctx->text.lt.info[n].position == target) {
  736. X        tempHeight = ctx->text.lt.info[ctx->text.lt.lines-n].y - 1;
  737. X        XCopyArea(XtDisplay(ctx), XtWindow(ctx), XtWindow(ctx), ctx->text.gc,
  738. X              0, ctx->text.lt.info[0].y, (int)ctx->core.width, tempHeight,
  739. X              0, ctx->text.lt.info[n].y);
  740. X        (*ctx->text.sink->ClearToBackground)(ctx, 0,
  741. X        ctx->text.lt.info[0].y,
  742. X        (int)ctx->core.width, ctx->text.lt.info[n].y - 1);
  743. X        _XtTextNeedsUpdating(ctx, 
  744. X            ctx->text.lt.info[0].position, ctx->text.lt.info[n].position);
  745. X        SetScrollBar(ctx);
  746. X    } else if (ctx->text.lt.top != target) DisplayTextWindow(ctx);
  747. X    }
  748. X}
  749. X
  750. X/*
  751. X * The routine will scroll the displayed text by pixels.  If the arg is
  752. X * positive, move up; otherwise, move down.
  753. X*/
  754. X/*ARGSUSED*/
  755. Xstatic void ScrollUpDownProc (w, closure, callData)
  756. X    Widget w;
  757. X    caddr_t closure;        /* TextWidget */
  758. X    caddr_t callData;        /* #pixels */
  759. X{
  760. X    TextWidget ctx = (TextWidget)closure;
  761. X    int     apix, line;
  762. X    _XtTextPrepareToUpdate(ctx);
  763. X    apix = abs((int)callData);
  764. X    for (line = 1;
  765. X        line < ctx->text.lt.lines && apix > ctx->text.lt.info[line + 1].y;
  766. X        line++);
  767. X    if (((int)callData) >= 0)
  768. X    _XtTextScroll(ctx, line);
  769. X    else
  770. X    _XtTextScroll(ctx, -line);
  771. X    _XtTextExecuteUpdate(ctx);
  772. X}
  773. X
  774. X/*
  775. X * The routine "thumbs" the displayed text. Thumbing means reposition the
  776. X * displayed view of the source to a new position determined by a fraction
  777. X * of the way from beginning to end. Ideally, this should be determined by
  778. X * the number of displayable lines in the source. This routine does it as a
  779. X * fraction of the first position and last position and then normalizes to
  780. X * the start of the line containing the position.
  781. X*/
  782. X/*ARGSUSED*/
  783. Xstatic void ThumbProc (w, closure, callData)
  784. X    Widget w;
  785. X    caddr_t closure;        /* TextWidget */
  786. X    float *callData;
  787. X  /* BUG/deficiency: The normalize to line portion of this routine will
  788. X   * cause thumbing to always position to the start of the source.
  789. X   */
  790. X{
  791. X    TextWidget ctx= (TextWidget)closure;
  792. X    XtTextPosition position, old_top, old_bot;
  793. X    _XtTextPrepareToUpdate(ctx);
  794. X    old_top = ctx->text.lt.top;
  795. X    old_bot = ctx->text.lt.info[ctx->text.lt.lines-1].position;
  796. X    position = *callData * ctx->text.lastPos;
  797. X    position = (*ctx->text.source->
  798. X        Scan)(ctx->text.source, position, XtstEOL, XtsdLeft, 1, FALSE);
  799. X    if (position >= old_top && position <= old_bot) {
  800. X    int line;
  801. X    for (line = 0; line < ctx->text.lt.lines &&
  802. X               position > ctx->text.lt.info[line].position; line++);
  803. X    if (line)
  804. X        _XtTextScroll(ctx, line);
  805. X    }
  806. X    else {
  807. X    BuildLineTable(ctx, position);
  808. X    if (old_top >= ctx->text.lt.top &&
  809. X        old_top <= ctx->text.lt.info[ctx->text.lt.lines-1].position) {
  810. X        int line;
  811. X        for (line = 0;
  812. X         line < ctx->text.lt.lines &&
  813. X         old_top > ctx->text.lt.info[line].position; line++);
  814. X        BuildLineTable(ctx, old_top);
  815. X        if (line)
  816. X        _XtTextScroll(ctx, -line);
  817. X    }
  818. X    else {
  819. X        DisplayTextWindow(ctx);
  820. X    }
  821. X    }
  822. X    _XtTextExecuteUpdate(ctx);
  823. X}
  824. X
  825. X
  826. Xstatic Boolean ConvertSelection(w, selection, target,
  827. X                type, value, length, format)
  828. X  Widget w;
  829. X  Atom *selection, *target, *type;
  830. X  caddr_t *value;
  831. X  unsigned long *length;
  832. X  int *format;
  833. X{
  834. X    Display* d = XtDisplay(w);
  835. X    TextWidget ctx = (TextWidget)w;
  836. X
  837. X    if (*target == XA_TARGETS(d)) {
  838. X    Atom* targetP;
  839. X    Atom* std_targets;
  840. X    unsigned long std_length;
  841. X    if (ctx->text.source->ConvertSelection == NULL ||
  842. X        !(*ctx->text.source->
  843. X          ConvertSelection) (d, ctx->text.source, selection, target,
  844. X                 type, value, length, format)) {
  845. X        *value = NULL;
  846. X        *length = 0;
  847. X    }
  848. X    XmuConvertStandardSelection(w, ctx->text.time, selection, target, type,
  849. X                   (caddr_t*)&std_targets, &std_length, format);
  850. X    *value = XtRealloc(*value, sizeof(Atom)*(std_length + 6 + *length));
  851. X    targetP = *(Atom**)value + *length;
  852. X    *length += std_length + 5;
  853. X    if (ctx->text.source->edit_mode == XttextEdit)
  854. X        (*length)++;
  855. X    *targetP++ = XA_STRING;
  856. X    *targetP++ = XA_TEXT(d);
  857. X    *targetP++ = XA_LENGTH(d);
  858. X    *targetP++ = XA_LIST_LENGTH(d);
  859. X    *targetP++ = XA_CHARACTER_POSITION(d);
  860. X    if (ctx->text.source->edit_mode == XttextEdit)
  861. X        *targetP++ = XA_DELETE(d);
  862. X    bcopy((char*)std_targets, (char*)targetP, sizeof(Atom)*std_length);
  863. X    XtFree((char*)std_targets);
  864. X    *type = XA_ATOM;
  865. X    *format = 32;
  866. X    return True;
  867. X    }
  868. X
  869. X    if (ctx->text.source->ConvertSelection != NULL &&
  870. X    (*ctx->text.source->
  871. X     ConvertSelection) (d, ctx->text.source, selection,
  872. X                target, type, value, length, format))
  873. X    return True;
  874. X
  875. X    if (*target == XA_STRING || *target == XA_TEXT(d)) {
  876. X    *type = XA_STRING;
  877. X    *value = _XtTextGetText(ctx, ctx->text.s.left, ctx->text.s.right);
  878. X    *length = strlen(*value);
  879. X    *format = 8;
  880. X    return True;
  881. X    }
  882. X    if (*target == XA_LIST_LENGTH(d)) {
  883. X    *value = XtMalloc(4);
  884. X    if (sizeof(long) == 4)
  885. X        *(long*)*value = 1;
  886. X    else {
  887. X        long temp = 1;
  888. X        bcopy( ((char*)&temp)+sizeof(long)-4, (char*)*value, 4);
  889. X    }
  890. X    *type = XA_INTEGER;
  891. X    *length = 1;
  892. X    *format = 32;
  893. X    return True;
  894. X    }
  895. X    if (*target == XA_LENGTH(d)) {
  896. X    *value = XtMalloc(4);
  897. X    if (sizeof(long) == 4)
  898. X        *(long*)*value = ctx->text.s.right - ctx->text.s.left;
  899. X    else {
  900. X        long temp = ctx->text.s.right - ctx->text.s.left;
  901. X        bcopy( ((char*)&temp)+sizeof(long)-4, (char*)*value, 4);
  902. X    }
  903. X    *type = XA_INTEGER;
  904. X    *length = 1;
  905. X    *format = 32;
  906. X    return True;
  907. X    }
  908. X    if (*target == XA_CHARACTER_POSITION(d)) {
  909. X    *value = XtMalloc(8);
  910. X    (*(long**)value)[0] = ctx->text.s.left + 1;
  911. X    (*(long**)value)[1] = ctx->text.s.right;
  912. X    *type = XA_SPAN(d);
  913. X    *length = 2;
  914. X    *format = 32;
  915. X    return True;
  916. X    }
  917. X    if (*target == XA_DELETE(d)) {
  918. X    void KillCurrentSelection();
  919. X    KillCurrentSelection(ctx, (XEvent*)NULL);
  920. X    *value = NULL;
  921. X    *type = XA_NULL(d);
  922. X    *length = 0;
  923. X    *format = 32;
  924. X    return True;
  925. X    }
  926. X    if (XmuConvertStandardSelection(w, ctx->text.time, selection, target, type,
  927. X                    value, length, format))
  928. X    return True;
  929. X
  930. X    /* else */
  931. X    return False;
  932. X}
  933. X
  934. X
  935. Xstatic void LoseSelection(w, selection)
  936. X  Widget w;
  937. X  Atom *selection;
  938. X{
  939. X    TextWidget ctx = (TextWidget)w;
  940. X    Boolean update_in_progress = (ctx->text.old_insert >= 0);
  941. X    register Atom* atomP;
  942. X    int i, empty;
  943. X
  944. X    _XtTextPrepareToUpdate(ctx);
  945. X
  946. X    for (i = 0, atomP = ctx->text.s.selections;
  947. X     i < ctx->text.s.atom_count; i++, atomP++)
  948. X    {
  949. X    if (*selection == *atomP) *atomP = (Atom)0;
  950. X    switch (*atomP) {
  951. X      case XA_CUT_BUFFER0:
  952. X      case XA_CUT_BUFFER1:
  953. X      case XA_CUT_BUFFER2:
  954. X      case XA_CUT_BUFFER3:
  955. X      case XA_CUT_BUFFER4:
  956. X      case XA_CUT_BUFFER5:
  957. X      case XA_CUT_BUFFER6:
  958. X      case XA_CUT_BUFFER7:    *atomP = (Atom)0;
  959. X    }
  960. X    }
  961. X
  962. X    for (i = ctx->text.s.atom_count; i; i--) {
  963. X    if (ctx->text.s.selections[i-1] != 0) break;
  964. X    }
  965. X    ctx->text.s.atom_count = i;
  966. X
  967. X    for (i = 0, atomP = ctx->text.s.selections;
  968. X     i < ctx->text.s.atom_count; i++, atomP++)
  969. X    {
  970. X    if (*atomP == (Atom)0) {
  971. X        *atomP = ctx->text.s.selections[--ctx->text.s.atom_count];
  972. X    }
  973. X    }
  974. X
  975. X    if (ctx->text.s.atom_count == 0)
  976. X    _XtTextSetNewSelection(ctx, ctx->text.insertPos, ctx->text.insertPos,
  977. X                   NULL, ZERO);
  978. X
  979. X    if (!update_in_progress) {
  980. X    _XtTextExecuteUpdate(ctx);
  981. X    }
  982. X}
  983. X
  984. X
  985. Xstatic int _XtTextSetNewSelection(ctx, left, right, selections, count)
  986. X  TextWidget ctx;
  987. X  XtTextPosition left, right;
  988. X  Atom *selections;
  989. X  Cardinal count;
  990. X{
  991. X    XtTextPosition pos;
  992. X    void (*nullProc)() = NULL;
  993. X
  994. X    if (left < ctx->text.s.left) {
  995. X    pos = min(right, ctx->text.s.left);
  996. X    _XtTextNeedsUpdating(ctx, left, pos);
  997. X    }
  998. X    if (left > ctx->text.s.left) {
  999. X    pos = min(left, ctx->text.s.right);
  1000. X    _XtTextNeedsUpdating(ctx, ctx->text.s.left, pos);
  1001. X    }
  1002. X    if (right < ctx->text.s.right) {
  1003. X    pos = max(right, ctx->text.s.left);
  1004. X    _XtTextNeedsUpdating(ctx, pos, ctx->text.s.right);
  1005. X    }
  1006. X    if (right > ctx->text.s.right) {
  1007. X    pos = max(left, ctx->text.s.right);
  1008. X    _XtTextNeedsUpdating(ctx, pos, right);
  1009. X    }
  1010. X
  1011. X    ctx->text.s.left = left;
  1012. X    ctx->text.s.right = right;
  1013. X    if (ctx->text.source->SetSelection != nullProc) {
  1014. X    (*ctx->text.source->SetSelection) (ctx->text.source,
  1015. X                       left, right,
  1016. X                       count ? selections[0] : NULL);
  1017. X    }
  1018. X    if (left < right) {
  1019. X    int buffer;
  1020. X    while (count) {
  1021. X        Atom selection = selections[--count];
  1022. X        switch (selection) {
  1023. X          case XA_CUT_BUFFER0: buffer = 0; break;
  1024. X          case XA_CUT_BUFFER1: buffer = 1; break;
  1025. X          case XA_CUT_BUFFER2: buffer = 2; break;
  1026. X          case XA_CUT_BUFFER3: buffer = 3; break;
  1027. X          case XA_CUT_BUFFER4: buffer = 4; break;
  1028. X          case XA_CUT_BUFFER5: buffer = 5; break;
  1029. X          case XA_CUT_BUFFER6: buffer = 6; break;
  1030. X          case XA_CUT_BUFFER7: buffer = 7; break;
  1031. X          default:           buffer = -1;
  1032. X        }
  1033. X        if (buffer >= 0) {
  1034. X        char *ptr =
  1035. X            _XtTextGetText(ctx, ctx->text.s.left, ctx->text.s.right);
  1036. X        if (buffer == 0) {
  1037. X            _CreateCutBuffers(XtDisplay((Widget)ctx));
  1038. X            XRotateBuffers(XtDisplay((Widget)ctx), 1);
  1039. X        }
  1040. X        XStoreBuffer(XtDisplay((Widget)ctx), ptr,
  1041. X                 min(strlen(ptr), MAXCUT), buffer);
  1042. X        XtFree (ptr);
  1043. X        } else {
  1044. X        XtOwnSelection((Widget)ctx, selection, ctx->text.time,
  1045. X                   ConvertSelection, LoseSelection, NULL);
  1046. X        }
  1047. X    }
  1048. X    }
  1049. X}
  1050. X
  1051. X
  1052. X
  1053. X/*
  1054. X * This internal routine deletes the text from pos1 to pos2 in a source and
  1055. X * then inserts, at pos1, the text that was passed. As a side effect it
  1056. X * "invalidates" that portion of the displayed text (if any).
  1057. X*/
  1058. Xstatic
  1059. Xint ReplaceText (ctx, pos1, pos2, text)
  1060. X  TextWidget ctx;
  1061. X  XtTextPosition pos1, pos2;
  1062. X  XtTextBlock *text;
  1063. X
  1064. X /* it is illegal to call this routine unless there is a valid line table!*/
  1065. X{
  1066. X    int i, line1, visible, delta, error;
  1067. X    Position x, y;
  1068. X    int realW, realH, width;
  1069. X    XtTextPosition startPos, endPos, updateFrom;
  1070. X    int (*Scan)() = ctx->text.source->Scan;
  1071. X
  1072. X    /* the insertPos may not always be set to the right spot in XttextAppend */
  1073. X    if ((pos1 == ctx->text.insertPos) &&
  1074. X    (ctx->text.source->edit_mode == XttextAppend)) {
  1075. X      ctx->text.insertPos = ctx->text.lastPos;
  1076. X      pos2 = pos2 - pos1 + ctx->text.insertPos;
  1077. X      pos1 = ctx->text.insertPos;
  1078. X    }
  1079. X    updateFrom = (*Scan)(ctx->text.source, pos1, XtstWhiteSpace, XtsdLeft,
  1080. X        1, TRUE);
  1081. X    updateFrom = (*Scan)(ctx->text.source, updateFrom, XtstPositions, XtsdLeft,
  1082. X        1, TRUE);
  1083. X    startPos = max(updateFrom, ctx->text.lt.top);
  1084. X    visible = LineAndXYForPosition(ctx, startPos, &line1, &x, &y);
  1085. X    error = (*ctx->text.source->Replace)(ctx->text.source, pos1, pos2, text);
  1086. X    if (error) return error;
  1087. X    ctx->text.lastPos = GETLASTPOS;
  1088. X    if (ctx->text.lt.top >= ctx->text.lastPos) {
  1089. X    BuildLineTable(ctx, ctx->text.lastPos);
  1090. X    ClearWindow(ctx);
  1091. X    SetScrollBar(ctx);
  1092. X    return error;
  1093. X    }
  1094. X    delta = text->length - (pos2 - pos1);
  1095. X    if (delta < ctx->text.lastPos) {
  1096. X    pos2 += delta;
  1097. X    for (i = 0; i < ctx->text.numranges; i++) {
  1098. X        if (ctx->text.updateFrom[i] > pos1)
  1099. X        ctx->text.updateFrom[i] += delta;
  1100. X        if (ctx->text.updateTo[i] >= pos1)
  1101. X        ctx->text.updateTo[i] += delta;
  1102. X    }
  1103. X    }
  1104. X
  1105. X    /* 
  1106. X     * fixup all current line table entries to reflect edit.
  1107. X     * %%% it is not legal to do arithmetic on positions.
  1108. X     * using Scan would be more proper.
  1109. X     */
  1110. X    if (delta) {
  1111. X    XtTextLineTableEntry *lineP;
  1112. X    int line2 = LineForPosition(ctx, pos1) + 1;
  1113. X    for (i = line2, lineP = ctx->text.lt.info + line2;
  1114. X         i <= ctx->text.lt.lines; i++, lineP++)
  1115. X        lineP->position += delta;
  1116. X    }
  1117. X
  1118. X    /*
  1119. X     * Now process the line table and fixup in case edits caused
  1120. X     * changes in line breaks. If we are breaking on word boundaries,
  1121. X     * this code checks for moving words to and from lines.
  1122. X    */
  1123. END_OF_FILE
  1124. if test 30780 -ne `wc -c <'xconf/Text.c.aa'`; then
  1125.     echo shar: \"'xconf/Text.c.aa'\" unpacked with wrong size!
  1126. fi
  1127. # end of 'xconf/Text.c.aa'
  1128. fi
  1129. if test -f 'xconf/xconf.c' -a "${1}" != "-c" ; then 
  1130.   echo shar: Will not clobber existing file \"'xconf/xconf.c'\"
  1131. else
  1132. echo shar: Extracting \"'xconf/xconf.c'\" \(18989 characters\)
  1133. sed "s/^X//" >'xconf/xconf.c' <<'END_OF_FILE'
  1134. X#include "xconf.h"
  1135. X#ifndef lint
  1136. Xstatic char *rcsid = "$Header: $";
  1137. X#endif
  1138. X
  1139. X/*
  1140. X * Written By Jon Crowcroft, May 1989
  1141. X * yours to do with as you wish
  1142. X *
  1143. X * I do not claim it has any value whatsoever... 
  1144. X *
  1145. X * TOFIX
  1146. X * Unsatisfactory nature of the conference starter having to name
  1147. X * themselves in the argument list.
  1148. X *
  1149. X */
  1150. X
  1151. Xchar *usage = "user@host user@host ... [-e] [-X typicalXargs]";
  1152. X
  1153. X/*
  1154. X * For help, click help
  1155. X */
  1156. Xextern char defaultTextTranslations[];
  1157. X/*
  1158. X * Some dimensions for the conference windows.
  1159. X */
  1160. Xstatic int widthb = DEFWIDTHB, heightb = DEFHEIGHTB;
  1161. Xstatic int widthw = DEFWIDTHW, heightw = DEFHEIGHTB;
  1162. X
  1163. X
  1164. X/*
  1165. X * The conference/window desription structures as far as xa is concerned
  1166. X * These are xa private structures, not X-Windows ones...
  1167. X */
  1168. Xxconf_t Conference[MAXCONF];
  1169. Xstatic XtAppContext context;
  1170. Xstatic int numberofthem = 0;
  1171. Xstatic int numberlive = 0;
  1172. X
  1173. Xstatic Arg args[10];
  1174. Xstatic Cardinal nargs;
  1175. X
  1176. Xstatic char **saved_argv;
  1177. Xstatic int saved_argc; 
  1178. X
  1179. Xstatic int firsttime = True;
  1180. Xstatic int exptl = False;
  1181. X
  1182. X
  1183. Xmain(argc, argv)
  1184. Xchar *argv[];
  1185. X{
  1186. X    int i, max;
  1187. X/*
  1188. X * Must be talking to at least one person 
  1189. X */
  1190. X     if (argc < 2) {
  1191. X        (void)fprintf(stderr, "%s %s\n", argv[0], usage);
  1192. X        exit(-1);
  1193. X    }
  1194. X
  1195. X/*
  1196. X * Parse cmd line args
  1197. X * [User[@host[:Display#]]]+ -X TypicalXArgs
  1198. X * and count number of users...
  1199. X */
  1200. X    max = (argc-1 > MAXCONF) ? MAXCONF : argc-1;
  1201. X    for(i = 1; i <= max; i++) {
  1202. X/*
  1203. X * ignore real X args here
  1204. X */
  1205. X        if (strcmp(argv[i], "-X") == 0)
  1206. X            break;
  1207. X        if (strcmp(argv[i], "-e") == 0) {
  1208. X            exptl = True;
  1209. X            continue;
  1210. X        }
  1211. X        ParseUserDisplay(&Conference[numberofthem], argv[i]);
  1212. X        numberofthem += 1;
  1213. X    }
  1214. X
  1215. X    if (numberofthem <= 0) {
  1216. X        (void)fprintf(stderr, "No confederates?\n");
  1217. X        exit(-1);
  1218. X    }
  1219. X
  1220. X/*
  1221. X * Start talking Xt
  1222. X * Create Application Context
  1223. X */
  1224. X    XtToolkitInitialize();    
  1225. X    context = XtCreateApplicationContext();
  1226. X
  1227. X/*
  1228. X * For each user(display), 
  1229. X *     there is 1 display which we open a window for their input, 
  1230. X *     on which is for each other user
  1231. X *        a window for their output
  1232. X *
  1233. X * TODO:
  1234. X * Should invite user first - could ask them simply to 
  1235. X * do xhost <confhost>
  1236. X *    where <confhost> is the conference chair...
  1237. X */
  1238. X    for(i = 0; i < numberofthem; i++) 
  1239. X        (void)StartConference(context,
  1240. X                i,
  1241. X                Conference,
  1242. X                numberofthem,
  1243. X                argc, 
  1244. X                argv);
  1245. X    firsttime = False;
  1246. X    numberlive = i;
  1247. X/*
  1248. X * And let X take over
  1249. X */
  1250. X    XtAppMainLoop(context);
  1251. X}
  1252. X
  1253. XParseUserDisplay(conf, arg)
  1254. Xxconf_t *conf;
  1255. Xchar *arg;
  1256. X{
  1257. X    char *cp, *FindMostRecentActiveLogin();
  1258. X    (void)strcpy(conf->user, arg);
  1259. X    if ((cp = strchr(arg, '@')) == NULL) {
  1260. X#ifdef SUNRPC
  1261. X        (void)strcpy(conf->display, FindMostRecentActiveLogin(arg));
  1262. X#else SUNRPC
  1263. X        (void)strcpy(conf->display, "");
  1264. X#endif SUNRPC
  1265. X    } else {
  1266. X        cp += 1;
  1267. X        (void)strcpy(conf->display, cp);
  1268. X        if (strchr(arg, ':') == NULL) 
  1269. X              (void)strcat(conf->display, ":0"); 
  1270. X    }
  1271. X}
  1272. X
  1273. X
  1274. X/*
  1275. X * This is called by X, when someone clicks on the qb (QUIT)
  1276. X * TODO: Fix box to re-layout after conferee exits
  1277. X */
  1278. X
  1279. X/* ARGSUSED */
  1280. Xvoid Alldone(widget, data, event)
  1281. XWidget widget;
  1282. Xcaddr_t data, event;
  1283. X{
  1284. X    int i, j, someleft = 0;
  1285. X    int w,h;
  1286. X    XtGeometryResult res;
  1287. X    XtWidgetGeometry preferred, intended;
  1288. X    int foundsize = False;
  1289. X
  1290. X    for(i=0; i < numberofthem; i++) {
  1291. X        if (Conference[i].qb == widget)  {
  1292. X            XtDestroyWidget(Conference[i].toplevel);
  1293. X            Conference[i].live = False;
  1294. X            for(j=0; j< numberofthem; j++) {
  1295. X                if (j != i && Conference[j].live) {
  1296. X                    XtDestroyWidget(Conference[j].them[i].v);
  1297. X                    if (!foundsize) {
  1298. X                        intended.request_mode = 
  1299. X                        preferred.request_mode = 
  1300. X                        XtCWQueryOnly|CWWidth|CWHeight;
  1301. X                        intended.width = intended.height = 1000;
  1302. X                        res = XtQueryGeometry(Conference[j].box, 
  1303. X                        &intended, &preferred);
  1304. X                        w = preferred.width;
  1305. X                        h = preferred.height;
  1306. X                        foundsize = True;
  1307. X                    }
  1308. X                    XtSetArg(args[0], XtNwidth, w);
  1309. X                    XtSetArg(args[1], XtNheight, h);
  1310. X                    XtSetValues(Conference[j].pop, args, TWO);
  1311. X                    XtResizeWindow(Conference[j].pop);
  1312. X
  1313. X                    XtSetArg(args[0], XtNwidth, w);
  1314. X                    XtSetArg(args[1], XtNheight, h);
  1315. X                    XtSetValues(Conference[j].box, args, TWO);
  1316. X                    XtResizeWindow(Conference[j].box);
  1317. X                }
  1318. X            }
  1319. X            (void)fprintf(stderr,"%s has left the conference\n", 
  1320. X                Conference[i].user);
  1321. X            numberlive--;
  1322. X        }
  1323. X        if (XtIsRealized(Conference[i].toplevel))
  1324. X            someleft++;
  1325. X    }
  1326. X    if (!someleft || numberlive <= 0) {
  1327. X        (void)fprintf(stderr, "The Conference is now Closed\n");
  1328. X        exit(0);
  1329. X    }
  1330. X}
  1331. X
  1332. X/*
  1333. X * Call back to accept conference and pop up all windows
  1334. X */
  1335. X/* ARGSUSED */
  1336. Xvoid Accept(widget, data, event)
  1337. XWidget widget;
  1338. Xcaddr_t data, event;
  1339. X{
  1340. X    xconf_t *conf = (xconf_t *)data;
  1341. X    XtPopup(conf->pop, XtGrabNone);
  1342. X    XtSetKeyboardFocus(conf->box, XtNameToWidget(conf->box, "value"));
  1343. X}
  1344. X
  1345. X/*
  1346. X * Call back to pop up add conferee thingy
  1347. X */
  1348. X/* ARGSUSED */
  1349. Xvoid Add(widget, data, event)
  1350. XWidget widget;
  1351. Xcaddr_t data, event;
  1352. X{
  1353. X    xconf_t *conf = (xconf_t *)data;
  1354. X    XtPopup(conf->npop, XtGrabNone);
  1355. X}
  1356. X
  1357. X/*
  1358. X * Actually add the new conferee
  1359. X */
  1360. X/* ARGSUSED */
  1361. Xvoid AddOk(widget, data, event)
  1362. XWidget widget;
  1363. Xcaddr_t data, event;
  1364. X{
  1365. X        int i, j;
  1366. X    char *cp;
  1367. X    xconf_t *conf = (xconf_t *)data;
  1368. X    int newconf = numberofthem;
  1369. X    int w,h;
  1370. X    XtGeometryResult res;
  1371. X    XtWidgetGeometry preferred, intended;
  1372. X
  1373. X    cp = XtDialogGetValueString(conf->nap);
  1374. X    ParseUserDisplay(&Conference[newconf], cp);
  1375. X    numberofthem++;
  1376. X    if (!StartConference(context, 
  1377. X            newconf, 
  1378. X            Conference, 
  1379. X            numberofthem,
  1380. X            0,
  1381. X            NO(char **))) {
  1382. X        numberofthem--;
  1383. X        XtSetArg(args[0], XtNvalue, "Cannot find User");
  1384. X        XtSetValues(conf->nap, args, ONE);
  1385. X        return;
  1386. X    }
  1387. X
  1388. X/*
  1389. X * set size of old conferences by new one i.e. let
  1390. X * box choose size for this number of children
  1391. X */
  1392. X    intended.request_mode = 
  1393. X        preferred.request_mode = 
  1394. X        XtCWQueryOnly|CWWidth|CWHeight;
  1395. X    intended.width = intended.height = 1000;
  1396. X    res = XtQueryGeometry(Conference[newconf].box, 
  1397. X        &intended, &preferred);
  1398. X    w = preferred.width;
  1399. X    h = preferred.height;
  1400. X
  1401. X/*
  1402. X * And add output for everyone else, resizing as we go
  1403. X */
  1404. X    for(j=0; j<numberofthem; j++) {
  1405. X        if (Conference[j].live && j != newconf) {
  1406. X            place(&Conference[j], 
  1407. X                Conference[newconf].user, 
  1408. X                newconf, j);
  1409. X/*
  1410. X * Seems to be that you cannot just resize one or the other, 
  1411. X * and expect them to "do the right thing"
  1412. X */
  1413. X            XtSetArg(args[0], XtNwidth, w);
  1414. X            XtSetArg(args[1], XtNheight, h);
  1415. X            XtSetValues(Conference[j].pop, args, TWO);
  1416. X            XtResizeWindow(Conference[j].pop);
  1417. X
  1418. X            XtSetArg(args[0], XtNwidth, w);
  1419. X            XtSetArg(args[1], XtNheight, h);
  1420. X            XtSetValues(Conference[j].box, args, TWO);
  1421. X            XtResizeWindow(Conference[j].box);
  1422. X        }
  1423. X    }
  1424. X    numberlive++;
  1425. X    XtPopdown(conf->npop);
  1426. X}
  1427. X/* ARGSUSED */
  1428. Xvoid AddQuit(widget, data, event)
  1429. XWidget widget;
  1430. Xcaddr_t data, event;
  1431. X{
  1432. X    xconf_t *conf = (xconf_t *)data;
  1433. X    XtPopdown(conf->npop);
  1434. X}
  1435. X
  1436. X/* ARGSUSED */
  1437. Xvoid KeyIn(widget, data, event)
  1438. XWidget widget;
  1439. Xcaddr_t data;
  1440. XXEvent *event;
  1441. X{
  1442. X        int i,j;
  1443. X    Widget w;
  1444. X
  1445. X    for(i=0; i<numberofthem; i++) {
  1446. X        if (Conference[i].me.w == widget) {
  1447. X            for(j=0; j<numberofthem; j++) {
  1448. X                if ((j != i) && Conference[j].live) {
  1449. X                    static XEvent ev;
  1450. X                    w = Conference[j].them[i].w;
  1451. X                    ev = *event;
  1452. X                    ev.xany.display = XtDisplay(w);
  1453. X                    ev.xany.window = XtWindow(w);
  1454. X                    XtDispatchEvent(&ev);
  1455. X                }
  1456. X            }
  1457. X            return;
  1458. X        }
  1459. X    }
  1460. X    (void)fprintf(stderr,"input from nobody\n");
  1461. X}
  1462. X
  1463. X/* ARGSUSED */
  1464. Xvoid Help(widget, data, event)
  1465. XWidget widget;
  1466. Xcaddr_t data, event;
  1467. X{
  1468. X    xconf_t *conf = (xconf_t *)data;
  1469. X    XtPopup(conf->hpop, XtGrabNone);
  1470. X    XtSetKeyboardFocus(conf->hap, XtNameToWidget(conf->hap, "value"));
  1471. X}
  1472. X
  1473. X
  1474. X/* ARGSUSED */
  1475. Xvoid HelpQuit(widget, data, event)
  1476. XWidget widget;
  1477. Xcaddr_t data, event;
  1478. X{
  1479. X    xconf_t *conf = (xconf_t *)data;
  1480. X    XtPopdown(conf->hpop);
  1481. X}
  1482. X
  1483. X/* ARGSUSED */
  1484. Xvoid Hapropos(widget, data, event)
  1485. XWidget widget;
  1486. Xcaddr_t data, event;
  1487. X{
  1488. X    xconf_t *conf = (xconf_t *)data;
  1489. X    Arg arg[1];
  1490. X    char *cp = "", *dohap();
  1491. X
  1492. X    cp = XtDialogGetValueString(conf->hap);
  1493. X    XtSetArg(arg[0], XtNlabel, dohap(cp));
  1494. X    XtSetValues(conf->hapres, arg, ONE);
  1495. X}
  1496. X
  1497. X/*
  1498. X * Extract string from default text translations - need
  1499. X * to hack round the newlines, tabs and colons to get
  1500. X * out a normal looking string
  1501. X */
  1502. Xchar *
  1503. Xdohap(cp)
  1504. Xchar *cp;
  1505. X{
  1506. X    char *dp = defaultTextTranslations, *cdp;
  1507. X    static char buf[80], *cb = buf;
  1508. X
  1509. X    if (cp != '\0') {
  1510. X        while(*dp != '\0') {
  1511. X            if (strncmp(cp, dp, strlen(cp)) == 0) {
  1512. X                cdp = dp;
  1513. X                while((*cdp != '\0') && (*cdp != '\n'))
  1514. X                    cdp--;
  1515. X                cdp++;
  1516. X                while (*cdp != ':')
  1517. X                    *cb++ = *cdp++;
  1518. X                *cb = '\0';
  1519. X                return buf;
  1520. X            }
  1521. X            dp++;
  1522. X        }
  1523. X    }
  1524. X    return "Nothing Apt";
  1525. X}
  1526. X
  1527. X#ifdef JOKE
  1528. Xvoid Joke(widget, data, event)
  1529. XWidget widget;
  1530. Xcaddr_t data, event;
  1531. X{
  1532. X    Arg arg[1];
  1533. X    XtSetArg(arg[0], XtNlabel, "I told you Not to");
  1534. X    XtSetValues(widget, arg, ONE);
  1535. X}
  1536. X#endif JOKE
  1537. X
  1538. X#ifdef EXPTL
  1539. X/*
  1540. X * Call backs for assertion etc...
  1541. X */
  1542. X/* ARGSUSED */
  1543. Xassert(widget, data, event)
  1544. XWidget widget;
  1545. Xcaddr_t data, event;
  1546. X{
  1547. X    int i;
  1548. X/*
  1549. X * Assertion = This fact is the case...
  1550. X * Bell for Assertion
  1551. X */
  1552. X    for(i=0;i<numberofthem; i++)
  1553. X        if(Conference[i].live)
  1554. X            XBell(XtDisplay(Conference[i].toplevel), 50);
  1555. X}
  1556. X
  1557. X/* ARGSUSED */
  1558. Xcommit(widget, data, event)
  1559. XWidget widget;
  1560. Xcaddr_t data, event;
  1561. X{
  1562. X/*
  1563. X * Committing = I will do this...
  1564. X */
  1565. X}
  1566. X
  1567. X/* ARGSUSED */
  1568. Xdirect(widget, data, event)
  1569. XWidget widget;
  1570. Xcaddr_t data, event;
  1571. X{
  1572. X/*
  1573. X * Direction = You will do this...
  1574. X */
  1575. X}
  1576. X
  1577. X/* ARGSUSED */
  1578. Xdeclare(widget, data, event)
  1579. XWidget widget;
  1580. Xcaddr_t data, event;
  1581. X{
  1582. X/*
  1583. X * Declaration = Varialbe <- Value, from now on...
  1584. X */
  1585. X}
  1586. X
  1587. X/* ARGSUSED */
  1588. Xexpress(widget, data, event)
  1589. XWidget widget;
  1590. Xcaddr_t data, event;
  1591. X{
  1592. X/*
  1593. X * Expression = This is how i feel about this
  1594. X *
  1595. X * This one really needs a scale most of all
  1596. X * color might be used to express here
  1597. X */
  1598. X}
  1599. X#endif EXPTL
  1600. X
  1601. X/*
  1602. X *******************************************************************
  1603. X * Set up a toplevel and sub windows on each conf display...
  1604. X *******************************************************************
  1605. X */
  1606. XStartConference(context, nth, confs, nconf, argc, argv)
  1607. XXtAppContext context;
  1608. Xint    nth;
  1609. Xxconf_t *confs;
  1610. Xint     nconf;
  1611. Xint     argc;
  1612. Xchar     *argv[];
  1613. X{
  1614. X    Screen *scrn;
  1615. X    int i;
  1616. X    xconf_t *conf = &confs[nth];
  1617. X    char *ptr = "";
  1618. X
  1619. X/*
  1620. X * Tie to approprate display, copy args to saved_args 
  1621. X */
  1622. X    saved_argc = argc;
  1623. X    saved_argv = (char **) XtCalloc(
  1624. X        (unsigned) ((argc) + 1), (unsigned)sizeof(*saved_argv));
  1625. X    for(i=0; i<argc; i++)
  1626. X        saved_argv[i] = argv[i];
  1627. X    saved_argv[i] = NULL;
  1628. X    conf->dpy = XtOpenDisplay(context,
  1629. X                      conf->display,
  1630. X                      "xconf",
  1631. X                      "XConf",
  1632. X                    NULL, 0,
  1633. X                      &saved_argc, saved_argv);
  1634. X
  1635. X    if (conf->dpy == NO(Display *)) {
  1636. X        (void)fprintf(stderr,"oops, cannot open display %s\n",
  1637. X                conf->display);
  1638. X/*
  1639. X * maye we should continue with less people...
  1640. X*/
  1641. X        if (firsttime)
  1642. X            exit(-1);
  1643. X        else
  1644. X            return False;
  1645. X    }
  1646. X/*
  1647. X * Find right screen for the toplevel... 
  1648. X * And do some scaling
  1649. X * Note, after this, added conferees may clutter the screen...nis
  1650. X */
  1651. X    if (firsttime) 
  1652. X        Scale(conf->dpy, nconf, &widthb, &heightb, &widthw, &heightw);
  1653. X
  1654. X/*
  1655. X * Create a shell widget to put all the others in
  1656. X */
  1657. X    nargs = 0;
  1658. X    scrn = DefaultScreenOfDisplay(conf->dpy);
  1659. X    XtSetArg(args[nargs], XtNscreen, scrn); nargs++;
  1660. X    XtSetArg(args[nargs], XtNargc, saved_argc); nargs++;
  1661. X    XtSetArg(args[nargs], XtNargv, saved_argv); nargs++;
  1662. X    conf->toplevel = XtAppCreateShell("xconf",
  1663. X                    "XConf",
  1664. X#ifdef OVERRIDE
  1665. X                    overrideShellWidgetClass,
  1666. X#else OVERRIDE
  1667. X                    applicationShellWidgetClass,
  1668. X#endif OVERRIDE
  1669. X                    conf->dpy,
  1670. X                    args,
  1671. X                    nargs);
  1672. X/*
  1673. X * Request Box...
  1674. X */
  1675. X    conf->tbox = XtCreateManagedWidget("ConfCtlBox", 
  1676. X            boxWidgetClass, conf->toplevel, NO(Arg *), ZERO);
  1677. X/*
  1678. X * And a quit command
  1679. X */
  1680. X        conf->qb = XtCreateManagedWidget("Quit Conference",  
  1681. X            commandWidgetClass, conf->tbox, NO(Arg *), ZERO);
  1682. X    XtAddCallback(conf->qb, XtNcallback, Alldone, (caddr_t) conf);
  1683. X/*
  1684. X * And an add conferee button
  1685. X */
  1686. X        conf->nb = XtCreateManagedWidget("Add Conferee",  
  1687. X            commandWidgetClass, conf->tbox, NO(Arg *), ZERO);
  1688. X    XtAddCallback(conf->nb, XtNcallback, Add, (caddr_t) conf);
  1689. X    conf->npop = XtCreatePopupShell("AddConf",
  1690. X            topLevelShellWidgetClass, conf->toplevel, NULL, ZERO);
  1691. X/*
  1692. X * and the rest to do conferee adding...
  1693. X */
  1694. X    conf->nbox = XtCreateManagedWidget("ABox",
  1695. X                        boxWidgetClass, conf->npop, NO(Arg *), ZERO);
  1696. X    XtSetArg(args[0], XtNlabel, "Add: ");
  1697. X    XtSetArg(args[1], XtNvalue, ptr);
  1698. X    conf->nap = XtCreateManagedWidget("AddPop",
  1699. X            dialogWidgetClass, conf->nbox, args, TWO);
  1700. X    conf->nok = XtCreateManagedWidget("Add ok?",
  1701. X            commandWidgetClass, conf->nap, NO(Arg *), ZERO);
  1702. X    XtAddCallback(conf->nok, XtNcallback, AddOk, (caddr_t)conf);
  1703. X    conf->nq = XtCreateManagedWidget("Add Quit?",
  1704. X            commandWidgetClass, conf->nap, NO(Arg *), ZERO);
  1705. X    XtAddCallback(conf->nq, XtNcallback, AddQuit, (caddr_t)conf);
  1706. X
  1707. X/*
  1708. X * And a accept command
  1709. X */
  1710. X        conf->ab = XtCreateManagedWidget("Accept Conference",  
  1711. X            commandWidgetClass, conf->tbox, NO(Arg *), ZERO);
  1712. X    XtAddCallback(conf->ab, XtNcallback, Accept, (caddr_t)conf);
  1713. X/*
  1714. X * And a Help Button
  1715. X */
  1716. X    conf->hb = XtCreateManagedWidget("Help",
  1717. X                        commandWidgetClass, conf->tbox, NO(Arg *), ZERO);
  1718. X    XtAddCallback(conf->hb, XtNcallback, Help, (caddr_t)conf);
  1719. X
  1720. X/*
  1721. X * Do each conf as a popup application window...
  1722. X */
  1723. X    XtSetArg(args[0], XtNallowResize, True);
  1724. X    conf->pop = XtCreatePopupShell("xonferee",
  1725. X            topLevelShellWidgetClass, conf->toplevel, args, ONE);
  1726. X/*
  1727. X * Make a box, with dimensions
  1728. X */
  1729. X    XtSetArg(args[0], XtNallowResize, True);
  1730. X    conf->box = XtCreateManagedWidget("confereebox", 
  1731. X            boxWidgetClass, conf->pop, args, ONE);
  1732. X
  1733. X/*
  1734. X * And a popup help window
  1735. X */
  1736. X    conf->hpop = XtCreatePopupShell("HelpPop",
  1737. X            topLevelShellWidgetClass, conf->toplevel, NULL, ZERO);
  1738. X/*
  1739. X * was topLevel
  1740. X */
  1741. X    conf->hbox = XtCreateManagedWidget("HelpBox", 
  1742. X            boxWidgetClass, conf->hpop, args, TWO);
  1743. X/*
  1744. X * Why the following?, coz of defects in X{t}whatever
  1745. X * it doesnt quite work as we'd like
  1746. X */
  1747. X    XtAppAddConverter(context, XtRString, XtROrientation, 
  1748. X            XmuCvtStringToOrientation, NULL, (Cardinal)0 );
  1749. X
  1750. X    XtSetArg(args[0], XtNfile, (XtArgVal)HELPFILE);
  1751. X    XtSetArg(args[1], XtNtextOptions, scrollVertical|wordBreak);
  1752. X    XtSetArg(args[2], XtNwidth, widthw);
  1753. X    XtSetArg(args[3], XtNheight, heightw);
  1754. X    XtSetArg(args[4], XtNeditType, (XtArgVal)XttextEdit); 
  1755. X    conf->htxt = XtCreateManagedWidget("Help", 
  1756. X            asciiDiskWidgetClass, conf->hbox, args, FIVE);
  1757. X    XtSetArg(args[0], XtNlabel, "Hapropos: ");
  1758. X    XtSetArg(args[1], XtNvalue, ptr);
  1759. X    conf->hap = XtCreateManagedWidget("Hapropos",
  1760. X            dialogWidgetClass, conf->hbox, args, TWO);
  1761. X    conf->hapok = XtCreateManagedWidget("apropos ok?",
  1762. X            commandWidgetClass, conf->hap, NO(Arg *), ZERO);
  1763. X    XtAddCallback(conf->hapok, XtNcallback, Hapropos, (caddr_t)conf);
  1764. X    conf->hapres = XtCreateManagedWidget("apropos res:",
  1765. X            labelWidgetClass, conf->hbox, NO(Arg *), ZERO);
  1766. X    conf->hq = XtCreateManagedWidget("Quit Help",
  1767. X                        commandWidgetClass, conf->hbox, NO(Arg *), ZERO);
  1768. X    XtAddCallback(conf->hq, XtNcallback, HelpQuit, (caddr_t)conf);
  1769. X
  1770. X#ifdef JOKE
  1771. X    conf->jb = XtCreateManagedWidget("Do Not Press This Button",
  1772. X        commandWidgetClass, conf->tbox, NULL, 0);
  1773. X    XtAddCallback(conf->jb, XtNcallback, Joke, (caddr_t)conf);
  1774. X#endif JOKE
  1775. X
  1776. X/* 
  1777. X * Now the windows for user typing in, and
  1778. X * others output
  1779. X */
  1780. X    conf->live = True;
  1781. X    for(i=0; i < nconf; i++) 
  1782. X        if (firsttime || Conference[i].live)
  1783. X            place(conf, Conference[i].user, i, nth);
  1784. X
  1785. X/*
  1786. X * And realize this conferees top level
  1787. X */
  1788. X    XtRealizeWidget(conf->toplevel);
  1789. X    XBell(XtDisplay(conf->toplevel), 50);
  1790. X
  1791. X    return True;
  1792. X}
  1793. X
  1794. X/*
  1795. X * Set up a ascii String class widget, (called lotsaa times, once per
  1796. X * conferee
  1797. X */
  1798. Xplace(conf, name, j, nth)
  1799. Xxconf_t *conf;
  1800. Xchar *name;
  1801. Xint j;
  1802. Xint nth;
  1803. X{
  1804. X    int i;
  1805. X    char nb[80];
  1806. X    xwin_t *ww = &(conf->them[j]);
  1807. X/*
  1808. X * Set Xt ascii string class arguments such as
  1809. X *     string
  1810. X *    edit style
  1811. X *     text options for scollbar and word breaking
  1812. X *    width and height
  1813. X */
  1814. X
  1815. X    nargs = 0;
  1816. X    XtSetArg(args[nargs], XtNallowResize, True);
  1817. X    nargs++;
  1818. X    XtSetArg(args[nargs], XtNwidth, widthw+16);
  1819. X    nargs++;
  1820. X    XtSetArg(args[nargs], XtNheight, heightw+16);
  1821. X    nargs++;
  1822. X    ww->v = XtCreateManagedWidget("win", vPanedWidgetClass, 
  1823. X            conf->box, args, nargs);
  1824. X
  1825. X    for(i=0; i<BUFFSIZE; i++)
  1826. X        ww->buff[i] = ' ';
  1827. X    nargs = 0;
  1828. X    XtSetArg(args[nargs], XtNstring, (XtArgVal)ww->buff); 
  1829. X    nargs++;
  1830. X    XtSetArg(args[nargs], XtNtextSource, ww->source);
  1831. X    nargs++;
  1832. X    XtSetArg(args[nargs], XtNeditType, (XtArgVal)XttextEdit); 
  1833. X    nargs++;
  1834. X    XtSetArg(args[nargs], XtNwidth, widthw); 
  1835. X    nargs++;
  1836. X        XtSetArg(args[nargs], XtNheight, heightw); 
  1837. X    nargs++;
  1838. X    XtSetArg(args[nargs], XtNtextOptions, scrollVertical|wordBreak); 
  1839. X    nargs++;
  1840. X/*  
  1841. X * Distinguish input and output windows by reverse video
  1842. X */
  1843. X    if ( j != nth ) {
  1844. X        XtSetArg(args[nargs], XtNbackground, XtDefaultForeground); 
  1845. X        nargs++;
  1846. X        XtSetArg(args[nargs], XtNforeground, XtDefaultBackground); 
  1847. X        nargs++;
  1848. X    }
  1849. X
  1850. X/*
  1851. X * Note could be asciiDiskWidgetClass, with tmp fil nam, top record procedings
  1852. X */
  1853. X    ww->w = XtCreateManagedWidget("win", asciiStringWidgetClass, 
  1854. X            ww->v, args, nargs);
  1855. X    if (ww->w == NULL) {
  1856. X        (void)fprintf(stderr, "win create failed...\n");
  1857. X        exit(-1);
  1858. X    }
  1859. X
  1860. X/*
  1861. X * and our funky text widget callback
  1862. X */
  1863. X    if (j == nth) {
  1864. X        Conference[nth].me.w = ww->w;
  1865. X        XtAddCallback(ww->w, XtNcallback, KeyIn, (caddr_t)conf);
  1866. X        (void)sprintf(nb, "<- In  %10s", name);
  1867. X    } else {
  1868. X        (void)sprintf(nb, "<- Out %10s", name);
  1869. X    }
  1870. X
  1871. X    XtTextSetLastPos(ww->w, 0);
  1872. X    XtTextEnableRedisplay(ww->w);
  1873. X/*
  1874. X * And a label to say who we are
  1875. X */
  1876. X    XtSetArg(args[0], XtNlabel, (XtArgVal)nb);
  1877. X    XtSetArg(args[1], XtNallowResize, True);
  1878. X    XtSetArg(args[2], XtNheight, 12);
  1879. X    ww->lab = XtCreateManagedWidget(name, labelWidgetClass,
  1880. X            ww->v, args, THREE);
  1881. X
  1882. X#ifdef EXPTL
  1883. X/*
  1884. X * And a bunch of illocutionary buttons (see Searle)
  1885. X */
  1886. X    if (exptl && (j == nth)) {
  1887. X        ww->assert = XtCreateManagedWidget("Assert",
  1888. X                commandWidgetClass,
  1889. X                ww->v, NO(Arg *), ZERO);
  1890. X        XtAddCallback(ww->assert, XtNcallback, assert, (caddr_t)conf);
  1891. X        
  1892. X        ww->commit = XtCreateManagedWidget("Commit",
  1893. X                commandWidgetClass,
  1894. X                ww->v, NO(Arg *), ZERO);
  1895. X        XtAddCallback(ww->commit, XtNcallback, commit, (caddr_t)conf);
  1896. X                
  1897. X        ww->direct = XtCreateManagedWidget("Direct",
  1898. X                commandWidgetClass,
  1899. X                ww->v, NO(Arg *), ZERO);
  1900. X        XtAddCallback(ww->direct, XtNcallback, direct, (caddr_t)conf);
  1901. X
  1902. X        ww->declare = XtCreateManagedWidget("Declare",
  1903. X                commandWidgetClass,
  1904. X                ww->v, NO(Arg *), ZERO);
  1905. X        XtAddCallback(ww->declare, XtNcallback, declare, (caddr_t)conf);
  1906. X
  1907. X        ww->express = XtCreateManagedWidget("Express",
  1908. X                commandWidgetClass,
  1909. X                ww->v, NO(Arg *), ZERO);
  1910. X        XtAddCallback(ww->express, XtNcallback, express, (caddr_t)conf);
  1911. X    }
  1912. X#endif EXPTL
  1913. X/*
  1914. X * Get round munge mess that box widget seems to get into if sizeing
  1915. X * in a popup
  1916. X    {
  1917. X    int foo;
  1918. X        XtSetArg(args[0], XtNheight, &foo);
  1919. X    XtGetValues(conf->box, args, ONE);
  1920. X        XtSetArg(args[0], XtNheight, foo);
  1921. X    XtSetValues(ww->v, args, ONE);
  1922. X    }
  1923. X */
  1924. X}
  1925. X
  1926. X
  1927. XScale(d, n, wb, hb, ww, hw)
  1928. XDisplay *d;
  1929. Xint n;
  1930. Xint *wb, *hb, *ww, *hw;
  1931. X{
  1932. X    Dimension w, h;
  1933. X    int s = DefaultScreen(d);
  1934. X
  1935. X    w = DisplayWidth(d, s);
  1936. X    h = DisplayHeight(d, s);
  1937. X
  1938. X    *wb = (w * 5) / 6;
  1939. X    *hb = (h * 5) / 6;
  1940. X
  1941. X    *ww = (*wb) / (n+2);  
  1942. X    *hw = (*hb) / (n+2); 
  1943. X}
  1944. X/*
  1945. X * EOF :-)
  1946. X */
  1947. END_OF_FILE
  1948. if test 18989 -ne `wc -c <'xconf/xconf.c'`; then
  1949.     echo shar: \"'xconf/xconf.c'\" unpacked with wrong size!
  1950. fi
  1951. # end of 'xconf/xconf.c'
  1952. fi
  1953. echo shar: End of archive 1 \(of 5\).
  1954. cp /dev/null ark1isdone
  1955. MISSING=""
  1956. for I in 1 2 3 4 5 ; do
  1957.     if test ! -f ark${I}isdone ; then
  1958.     MISSING="${MISSING} ${I}"
  1959.     fi
  1960. done
  1961. if test "${MISSING}" = "" ; then
  1962.     echo You have unpacked all 5 archives.
  1963.     rm -f ark[1-9]isdone
  1964. else
  1965.     echo You still need to unpack the following archives:
  1966.     echo "        " ${MISSING}
  1967. fi
  1968. ##  End of shell archive.
  1969. exit 0
  1970.