Return-Path: sun!osf.org!dbrooks
Return-Path: <sun!osf.org!dbrooks>
Received: by objy27. (5.57/SMI-4.0)
	id AA10966; Thu, 19 Mar 92 10:31:51 -0800
Received: from sun.UUCP by objy.com (4.1/SMI-4.0)
	id AA23277; Thu, 19 Mar 92 10:32:25 PST
From: sun!osf.org!dbrooks
Received: from Sun.COM (sun-barr) by sun.Eng.Sun.COM (4.1/SMI-4.1)
	id AA24789; Thu, 19 Mar 92 09:44:14 PST
Received: from postman.osf.org by Sun.COM (4.1/SMI-4.1)
	id AA27813; Thu, 19 Mar 92 09:44:08 PST
Received: from penge.osf.org by postman.osf.org (5.64+/OSF 1.0)
	id AA25953; Thu, 19 Mar 92 12:44:03 -0500
Message-Id: <9203191744.AA25953@postman.osf.org>
To: "Rick L. Spickelmier" <sun!objy!objy27!ricks>
Cc: xrn@ic.berkeley.edu, mikey@eukanuba.wpd.sgi.com
Subject: Re: Motif changes to xrn 6.17 
Date: Thu, 19 Mar 92 12:44:02 -0500

> I've had a bit of trouble patching xrn.c with your diffs.  Here is
> what I think xrn.c is after your diffs....  do you agree?

I'm sorry it was a problem; that was possibly because you were patching a
version a little post-6.17 (I have version 1.18; you have 1.22).  The change to
enable editres looks good.

However, I took out the attempt to calculate and set the size of the XmList
widget (called Text) based on the font metrics because as far as I can see,
that is unnecessary.  Both Motifs 1.1 and 1.2 get the layout right to begin
with, based only on the main geometry and the topLines parameter.  That's why I
left out the stuff around line 310 and omitted the declaration of textFontList.

I just rebuilt with the precise source you sent me, and my list area, the
"Text" widget, has grown to take over the entire article display area...

First off, topMargin and bottomMargin should be Dimension (= ushort), not
Position (=short) (compare Xaw, where the equivalent values *are* Position). 
But that doesn't explain it; the GetValues results for the margins seem to be
inexplicable.  I may have uncovered a bug in the 1.2 beta.

In any case, here is *my* version of *your* version, which does work with both
1.2 and 1.1.x.

David Brooks
Systems Engineering
Open Software Foundation



#if !defined(lint) && !defined(SABER)
static char XRNrcsid[] = "$Header: /afs/gza.com/software/xrn/src/still-to-do/RCS/motif,v 1.1 1994/10/10 08:39:01 jik Exp $";
#endif

/*
 * xrn - an X-based NNTP news reader
 *
 * Copyright (c) 1988, 1989, 1990, 1991, Ellen M. Sentovich and Rick L. Spickelmier.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee is hereby granted, provided
 * that the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation, and that the name of the University of California not
 * be used in advertising or publicity pertaining to distribution of 
 * the software without specific, written prior permission.  The University
 * of California makes no representations about the suitability of this
 * software for any purpose.  It is provided "as is" without express or
 * implied warranty.
 *
 * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO 
 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 
 * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR
 * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

/*
 * xrn.c: set up the main screens
 *
 */

#include "copyright.h"
#include <X11/Xos.h>
#include "config.h"
#include "utils.h"
#include <X11/Intrinsic.h>
#include <X11/Xutil.h>
#include <X11/StringDefs.h>
#include <X11/Shell.h>

#ifndef MOTIF
#include <X11/Xaw/Paned.h>
#include <X11/Xaw/Label.h>
#include <X11/Xaw/Box.h>
#include <X11/Xaw/AsciiText.h>
#else
#include <stdio.h>
#include <Xm/PanedW.h>
#include <Xm/Label.h>
#include <Xm/RowColumn.h>
#include <Xm/Text.h>
#include <Xm/List.h>
#include <Xm/ScrolledW.h>
#include <Xm/Separator.h>
#include "MotifXawHack.h"
#endif

#include "xthelper.h"
#include "xmisc.h"
#include "resources.h"
#include "internals.h"
#include "error_hnds.h"
#include "buttons.h"
#include "mesg.h"
#include "xrn.h"


#ifdef XFILESEARCHPATH
static void AddPathToSearchPath();
#endif

/* global variables that represent the widgets that are dynamically changed */

Widget TopLevel;
Widget Frame;
Widget TopButtonBox;    /* button box containing the command buttons */
Widget BottomButtonBox; /* button box containing the article specific buttons */
Widget TopInfoLine;      /* top button info line                      */
Widget BottomInfoLine;   /* bottom button info line                   */
Widget Text;             /* newsgroup and article subject display     */
Widget ArticleText;      /* article display                           */

#ifdef MOTIF
Widget ArticleTextText;		/* Motif text widget used for article text */
Widget ArticleTextList;		/* Motif list widget used for all groups */
Widget ArticleContainer;	/* Container for the above, only one shows */

static XmString emptyString;
#endif

int XRNState;            /* XRN status: news and x                    */

int inchannel, outchannel;

/*ARGSUSED*/
main(argc, argv)
int argc;
char **argv;
{
    XtWidgetGeometry intended, return_geometry;
    static Arg frameArgs[] = {			/* main window description */
	{XtNx, (XtArgVal) 10},
	{XtNy, (XtArgVal) 10},
	{XtNheight, (XtArgVal) 800},
	{XtNwidth, (XtArgVal) 680},
    };
#ifdef TITLEBAR
    Widget titlebar;
    static Arg labelArgs[] = {
#ifndef MOTIF
	{XtNlabel, (XtArgVal) NULL},
#else
	{XmNlabelString, (XtArgVal) NULL},
	{XmNrecomputeSize, (XtArgVal) False},
	{XmNskipAdjust, (XtArgVal) True},
	{XmNallowResize, (XtArgVal) False},
#endif
    };
#endif
    static Arg genericArgs[] = {
#ifndef MOTIF
	{XtNskipAdjust, (XtArgVal) True}, /* skipAdjust DOESN'T REALLY EXIST */
#else
	{XmNlabelString, (XtArgVal) NULL},
	{XmNrecomputeSize, (XtArgVal) False},
	{XmNskipAdjust, (XtArgVal) True},
	{XmNallowResize, (XtArgVal) False},
#endif
    };
    static Arg boxArgs[] = {
#ifndef MOTIF
	/* Only the button boxes should resizeToPreferred */
	{XtNresizeToPreferred, (XtArgVal) True},
	{XtNskipAdjust, (XtArgVal) True}, /* skipAdjust DOESN'T REALLY EXIST */
#else
	{XmNallowResize, (XtArgVal) True},
#endif
    };
#ifndef MOTIF
    static XawTextSelectType selarray[] = {XawselectLine, XawselectNull};
    static Arg textArgs[] = {		/* newsgroup/subject text window */
	{XtNstring,  (XtArgVal) ""},
	{XtNselectTypes, (XtArgVal) selarray },
	{XtNtype,  (XtArgVal) XawAsciiString},
	{XtNeditType,  (XtArgVal) XawtextRead},
	{XtNuseStringInPlace,  (XtArgVal) True},
    };
#else
    static Arg listArgs[] = {
      {XmNvisibleItemCount, (XtArgVal) TOPLINES},
      {XmNskipAdjust, (XtArgVal) False},
      {XmNallowResize, (XtArgVal) False},
      {XmNselectionPolicy, (XtArgVal) XmEXTENDED_SELECT},
    };
#endif

    Arg sizeArgs[2], fontArgs[1];
#ifdef R3
    int fontHeight;
#endif

#ifndef MOTIF
    static Arg articleTextArgs[] = {	/* article/all text window */
	{XtNstring,  (XtArgVal) ""},
	{XtNselectTypes, (XtArgVal) selarray},
	{XtNtype,  (XtArgVal) XawAsciiString},
	{XtNeditType,  (XtArgVal) XawtextRead},
	{XtNuseStringInPlace,  (XtArgVal) True},
    };
#else
    static Arg articleTextArgs[] = {
        {XmNskipAdjust, (XtArgVal) False},
    };

    static Arg aListArgs[] = {
      {XmNselectionPolicy, (XtArgVal) XmEXTENDED_SELECT},
      {XmNpaneMinimum, (XtArgVal) 1},
      {XmNpaneMaximum, (XtArgVal) 1},
    };

    static Arg contArgs[] = {
      {XmNallowResize, (XtArgVal) False},
      {XmNskipAdjust, (XtArgVal) False},
      {XmNmarginHeight, (XtArgVal) 0},
      {XmNmarginWidth, (XtArgVal) 0},
      {XmNsashHeight, (XtArgVal) 1},
      {XmNsashWidth, (XtArgVal) 1},
      {XmNseparatorOn, (XtArgVal) False},
      {XmNspacing, (XtArgVal) 0},
    };

    static Arg sepArgs[] = {
      {XmNskipAdjust, (XtArgVal) True},
    };

#endif
    XFontStruct *textFont;
    Position topMargin;
    Position bottomMargin;
    void processMessage();
    int sv[2];

    pipe (sv);
    inchannel = sv[0];
    outchannel = sv[1];



    XRNState = 0;

#ifdef XFILESEARCHPATH
    AddPathToSearchPath(XFILESEARCHPATH);
#endif
    
    TopLevel = Initialize(argc, argv);

    ehInstallSignalHandlers();
    ehInstallErrorHandlers();

    if (app_resources.geometry != NIL(char)) {
	int bmask;
	bmask = XParseGeometry(app_resources.geometry,       /* geometry specification */
			       (int *) &frameArgs[0].value,    /* x      */
			       (int *) &frameArgs[1].value,    /* y      */
			       (unsigned int *) &frameArgs[3].value,    /* width  */
			       (unsigned int *) &frameArgs[2].value);   /* height */

	/* handle negative x and y values */
	if ((bmask & XNegative) == XNegative) {
	    frameArgs[0].value += (XtArgVal) DisplayWidth(XtDisplay(TopLevel),
							  DefaultScreen(XtDisplay(TopLevel)));
	    frameArgs[0].value -= (int) frameArgs[3].value;
	}
	if ((bmask & YNegative) == YNegative) {
	    frameArgs[1].value += (XtArgVal) DisplayHeight(XtDisplay(TopLevel),
							   DefaultScreen(XtDisplay(TopLevel)));
	    frameArgs[1].value -= (int) frameArgs[2].value;
	}
    }
    
    /* create the pane and its widgets */

#ifndef MOTIF    
    Frame = XtCreateManagedWidget("vpane", panedWidgetClass, TopLevel,
				  frameArgs, XtNumber(frameArgs));
#else
    emptyString = XmStringCreate(" ", XmSTRING_DEFAULT_CHARSET);
    XtSetArg(genericArgs[0], XmNlabelString, emptyString);
    XtSetWarningHandler((XtErrorHandler) XawNothing);

    Frame = XmCreatePanedWindow(TopLevel, "vpane",
				  frameArgs, XtNumber(frameArgs));
    XtManageChild(Frame);
#endif
    
#ifdef TITLEBAR
#ifndef MOTIF
    XtSetArg(labelArgs[0], XtNlabel, app_resources.title);
    titlebar = XtCreateManagedWidget("titlebar", labelWidgetClass, Frame,
				     labelArgs, XtNumber(labelArgs));
#else
    {
      XmString xs;

      xs = XmStringCreate(app_resources.title, XmSTRING_DEFAULT_CHARSET);
      XtSetArg(labelArgs[0], XmNlabelString, xs);
      titlebar = XmCreateLabel(Frame, "titlebar",
			       labelArgs, XtNumber(labelArgs));
      XtManageChild(titlebar);
      XmStringFree(xs);
    }
#endif
#endif

#ifndef MOTIF
    Text = XtCreateManagedWidget("index", asciiTextWidgetClass, Frame,
					 textArgs, XtNumber(textArgs));
#else
    XtSetArg(listArgs[0], XmNvisibleItemCount, app_resources.topLines);
    Text = XmCreateScrolledList(Frame, "index", listArgs, XtNumber(listArgs));
    XtManageChild(Text);
    XtAddCallback(Text, XmNdefaultActionCallback, TextListSelection, NULL);
    XtAddCallback(Text, XmNextendedSelectionCallback, TextListSelection, NULL);
#endif

#ifndef MOTIF
#ifdef R3
    XtSetArg(fontArgs[0], XtNheight, 0);
    XtGetValues(Text, fontArgs, XtNumber(fontArgs));

    /* 6 = 2 * yMargin + 2 */
    fontHeight = (int) fontArgs[0].value - 6;

    XtSetArg(sizeArgs[0], XtNheight,
	     app_resources.topLines * fontHeight + 4);
    XtSetValues(Text, sizeArgs, 1);
#else
    /* I have this ifdef'd for R3 because I don't feel like figuring */
    /* out how to do it properly for R3.  It's easier in R4.	     */

    XtVaGetValues(Text,
		  XtNbottomMargin, &bottomMargin,
		  XtNtopMargin, &topMargin,
		  XtNfont, &textFont,
		  NULL);

    XtVaSetValues(Text, XtNheight,
		  (XtArgVal) ((Dimension)
			      (bottomMargin + topMargin +
			       app_resources.topLines *
			       (textFont->max_bounds.ascent +
				textFont->max_bounds.descent))),
		  NULL);
#endif
#endif
    
#ifndef MOTIF
    TopInfoLine = XtCreateManagedWidget("indexinfo", labelWidgetClass, Frame,
					genericArgs, XtNumber(genericArgs));

    TopButtonBox = XtCreateManagedWidget("indexbuttons", boxWidgetClass, Frame,
					  boxArgs, XtNumber(boxArgs));

    /* article display text window */
    ArticleText = XtCreateManagedWidget("articleText", asciiTextWidgetClass, Frame,
					 articleTextArgs, XtNumber(articleTextArgs));

    BottomInfoLine = XtCreateManagedWidget("textinfo", labelWidgetClass, Frame,
					   genericArgs, XtNumber(genericArgs));

    BottomButtonBox = XtCreateManagedWidget("textbuttons", boxWidgetClass, Frame,
					     boxArgs, XtNumber(boxArgs));
#else
    TopInfoLine = XmCreateLabel(Frame, "indexinfo",
				genericArgs, XtNumber(genericArgs));
    XtManageChild(TopInfoLine);
    
    XtManageChild(XmCreateSeparator(Frame, "separator",
				    sepArgs, XtNumber(sepArgs)));

    TopButtonBox = XmCreateRowColumn(Frame, "indexbuttons",
				     boxArgs, XtNumber(boxArgs));
    XtManageChild(TopButtonBox);

    XtManageChild(XmCreateSeparator(Frame, "separator",
				    sepArgs, XtNumber(sepArgs)));

    ArticleContainer = XmCreatePanedWindow(Frame, "articleText",
				    contArgs, XtNumber(contArgs));
    XtManageChild(ArticleContainer);

    /* article display text window */
    ArticleTextText = XmCreateScrolledText(ArticleContainer, "articleTextText",
					   articleTextArgs,
					   XtNumber(articleTextArgs));
    XtManageChild(ArticleTextText);
    ArticleText = ArticleTextText;
    
    /* all groups list window */
    ArticleTextList = XmCreateScrolledList(ArticleContainer, "articleTextList",
					   aListArgs, XtNumber(aListArgs));
    XtManageChild(ArticleTextList);

    BottomInfoLine = XmCreateLabel(Frame, "textinfo",
				   genericArgs, XtNumber(genericArgs));
    XtManageChild(BottomInfoLine);

    XtManageChild(XmCreateSeparator(Frame, "separator",
				    sepArgs, XtNumber(sepArgs)));

    BottomButtonBox = XmCreateRowColumn(Frame, "textbuttons",
					boxArgs, XtNumber(boxArgs));
    XtManageChild(BottomButtonBox);
#endif

    /* initialize the news system, read the newsrc file */
    initializeNews();
    XRNState |= XRN_NEWS_UP;

    /* set up the text window, mode buttons, and question */
    determineMode();

    /* create the icon */
    xmIconCreate();

#ifdef TITLEBAR
    XtSetArg(fontArgs[0], XtNheight, 0);
    XtGetValues(titlebar, fontArgs, XtNumber(fontArgs));
#ifndef MOTIF
    XawPanedSetMinMax(titlebar,
		     (int) fontArgs[0].value, (int) fontArgs[0].value);
#else
    {
      Arg args[2];

      XtSetArg(args[0], XmNpaneMaximum, fontArgs[0].value);
      XtSetArg(args[1], XmNpaneMinimum, fontArgs[0].value);
      XtSetValues(titlebar, args, 2);
    }
#endif
#endif    

    XtSetArg(fontArgs[0], XtNheight, 0);
    XtGetValues(TopInfoLine, fontArgs, XtNumber(fontArgs));
#ifndef MOTIF
    XawPanedSetMinMax(TopInfoLine,
		     (int) fontArgs[0].value, (int) fontArgs[0].value);
#else
    {
      Arg args[2];

      XtSetArg(args[0], XmNpaneMaximum, fontArgs[0].value);
      XtSetArg(args[1], XmNpaneMinimum, fontArgs[0].value);
      XtSetValues(TopInfoLine, args, 2);
    }
#endif
    
    XtSetArg(fontArgs[0], XtNheight, 0);
    XtGetValues(BottomInfoLine, fontArgs, XtNumber(fontArgs));
#ifndef MOTIF
    XawPanedSetMinMax(BottomInfoLine,
		     (int) fontArgs[0].value, (int) fontArgs[0].value);
    XtSetKeyboardFocus(Frame, ArticleText);	/* mikey */
#else
    {
      Arg args[2];

      XtSetArg(args[0], XmNpaneMaximum, fontArgs[0].value);
      XtSetArg(args[1], XmNpaneMinimum, fontArgs[0].value);
      XtSetValues(BottomInfoLine, args, 2);
    }
#endif
    
    /*
     * This next call doesn't do anything by default, unless you
     * modify the application defaults file, because there are no
     * accelerators for Text in it.  However, it makes it possible for
     * users to add accelerators to their own resources, so that, for
     * example, they can use the arrow keys to scroll through the
     * index window rather than through the article text.  To do that,
     * they would put the following in their resources:
     *
     * xrn*index.accelerators: #override \n\
     * 		<Key>Down:	next-line() \n\
     * 		<Key>Up:	previous-line()
     */
    XtInstallAccelerators(ArticleText, Text);

#if defined(MOTIF) && defined(EDITRES) && XtSpecificationRelease == 5
    /* Enable editres interaction (needs X11R5 Xmu; Xaw already has this) */
    {
      extern void _XEditResCheckMessages();

      XtAddEventHandler(TopLevel, (EventMask)0, True,
			_XEditResCheckMessages, (XtPointer) NULL);
    }
#endif
    
    XtRealizeWidget(TopLevel);

#ifndef MOTIF
    /* Get the top button box to start out the right size. This is a */
    /* somewhat gross hack, but it does do the job.		     */
    intended.request_mode = CWWidth | XtCWQueryOnly;
    XtSetArg(sizeArgs[0], XtNwidth, &intended.width);
    XtGetValues(TopButtonBox, sizeArgs, 1);
    XtQueryGeometry(TopButtonBox, &intended, &return_geometry);
    XtSetArg(sizeArgs[0], XtNheight, return_geometry.height);
    XtSetValues(TopButtonBox, sizeArgs, 1);
    /* Let's do a similar gross hack for the bottom button box */
    XtSetArg(sizeArgs[0], XtNwidth, &intended.width);
    XtGetValues(BottomButtonBox, sizeArgs, 1);
    XtQueryGeometry(BottomButtonBox, &intended, &return_geometry);
    XtSetArg(sizeArgs[0], XtNheight, return_geometry.height);
    XtSetValues(BottomButtonBox, sizeArgs, 1);
#else
#if XmVersion >= 1001
    XmProcessTraversal(ArticleText, XmTRAVERSE_CURRENT);
#else
    XtSetKeyboardFocus(Frame, ArticleText);	/* mikey */
#endif
#endif
    
    unbusyCursor();
    addTimeOut();
    XRNState |= XRN_X_UP;
    if (app_resources.version == NULL) {
	mesgPane(XRN_SERIOUS,
"Current XRN Application Defaults file is not installed.\n\
Some XRN functionality may be missing.");
    } else if (strcmp(app_resources.version, XRN_VERSION) != 0) {
	mesgPane(XRN_SERIOUS,
"Current XRN Application Defaults file is not installed.\n\
Some XRN functionality may be missing.\nApplication defaults version: %s\n\
XRN version: %s", app_resources.version, XRN_VERSION);
    }

    if (unreadNews() > 0) {
        XSetIconName(XtDisplay(TopLevel), XtWindow(TopLevel),
		     app_resources.unreadIconName);
    }
    XtAppAddInput(XtWidgetToApplicationContext(TopLevel),
                inchannel, (XtPointer) XtInputReadMask, processMessage, NULL);

    XtMainLoop();
    exit(0);
}       


#ifdef XFILESEARCHPATH
static void
AddPathToSearchPath(path)
char *path;
{
     char *old, *new;

     old = getenv("XFILESEARCHPATH");
     if (old) {
#ifdef USE_PUTENV
	  /* +1 for =, +2 for :, +3 for null */
	  new = XtMalloc((Cardinal) (strlen("XFILESEARCHPATH") +
				     strlen(old) +
				     strlen(path) + 3));
	  (void) strcpy(new, "XFILESEARCHPATH");
	  (void) strcat(new, "=");
	  (void) strcat(new, old);
	  (void) strcat(new, ":");
	  (void) strcat(new, path);
	  putenv(new);
#else
	  /* +1 for colon, +2 for null */
	  new = XtMalloc((Cardinal) (strlen(old) + strlen(path) + 2));
	  (void) strcpy(new, old);
	  (void) strcat(new, ":");
	  (void) strcat(new, path);
	  setenv("XFILESEARCHPATH", new, 1);
#endif
     }
     else {
#ifdef USE_PUTENV
	  new = XtMalloc((Cardinal) (strlen("XFILESEARCHPATH") +
				     strlen(path) + 2));
	  (void) strcpy(new, "XFILESEARCHPATH");
	  (void) strcat(new, "=");
	  (void) strcat(new, path);
	  putenv(new);
#else
	  setenv("XFILESEARCHPATH", path, 1);
#endif
     }
}
#endif
