From: lee@sq.sq.com (Liam R. E. Quin)
Subject: Re: How to set fonts in xview
Organization: SoftQuad Inc., Toronto, Canada
Distribution: usa
Date: Wed, 14 Oct 92 03:58:36 GMT

mpk9172@ultb.isc.rit.edu (M.P. Kirby) writes:
>The problem is in Xview running on openwindows 3.0.  I want to be able
>to set the font of an xview scrolling list to be fixed width.  The obvious
>reason is that I need to be able to organize information in columns.  

I posted the same question a while ago.

The XView list package obviously badly needs a multi-colum mode.

After careful perusal of the source, here are the alternatives:

(1) set the font of the enclosing Panel to be a fixed width font.
    This will affect most of the other panel items, but you can set the
    fonts of some of them back again.

(2) build your own ListInsert procedure, as outlined in the following
    untested code.  This is untested, but the same basic code does work.
    You must have XView 3 for the PANEL_LIST_INSERT_ROWS and
    PANEL_LIST_DELETE_ROWS attributes to work, but it should be clear how to
    replace them.

    The trick is to set PANEL_LIST_FONT on each row of the list when one
    inserts it into the list.

(3) hack p_list.c to add a global font for the list.  Ugh.
    For XView 2 this is the only choice, I think.


Lee


// in header file
typedef struct s_PendingStrings {
    int HowManyAllocated;
    int HowManyUsed;
    char **Strings;
} t_PendingStrings;

#define BATCH_INSERT_AMOUNT 150

void ListInsert(/* List, String */);
void ListInsertSync(/* List */);
void ListClear(List);

// SomewhereInStartupCode()

    PENDING_STRINGS = xv_unique_key(); /* returns different no. each time */
    MY_LIST_FONT = xv_unique_key();

    Font f = (Font) xv_find(owner, XV_FONT, ......);
    xv_set(List,
	XV_KEY_DATA, MY_LIST_FONT, f,
	NULL
    );

    .
    .
    .
    xv_set(List,
	XV_SHOW, FALSE,
	NULL
    );

    ListClear(List);
    ListInsert(List, String);
    ListInsert(List, AnotherString);
    .
    .
    .
    .
    ListInsertSync(List);

    xv_set(List,
	XV_SHOW, TRUE,
	NULL
    );


// in library file:

static void ListBatchInsert(/*List, PendingStrings*/);

void
ListClear(List)
    Panel_item List;
{
    int n = xv_get(List, PANEL_LIST_NROWS);

    xv_set(List,
	PANEL_LIST_DELETE_ROWS, 0, n,
	NULL
    );
}

void
ListInsert(List, String)
    Panel_item List;
    char *String;
{
    char *NewString;
    t_PendingStrings *PendingStrings = (t_PendingStrings *) xv_get(List,
	XV_KEY_DATA, PENDING_STRINGS
    );

    if (!String) {
	// error...
    }

    NewString = malloc(strlen(String) + 1);
    // check malloc return value
    (void) strcpy(NewString, String);

    if (!PendingStrings) {
	PendingStrings = (t_PendingStrings *) malloc(sizeof(t_PendingStrings));
	// check malloc return value and error if out of memory
	PendingStrings->HowManyUsed = 0;
	PendingStrings->HowManyAllocated = BATCH_INSERT_AMOUNT;
	PendingStrings->Strings = (char **)
				malloc(sizeof(char *) * BATCH_INSERT_AMOUNT);
	// check malloc return value
	xv_set(List,
	    XV_KEY_DATA, PENDING_STRINGS, PendingStrings,
	    NULL
	);
    }

    if (PendingStrings->HowManyUsed >= BATCH_INSERT_AMOUNT) {
	ListBatchInsert(List, PendingStrings);
    }

    PendingStrings[PendingStrings->HowManyUsed++] = String;
    PendingStrings[PendingStrings->HowManyUsed] = NULL;
}

void
ListInsertSync(List)
    Panel_item List;
{
    char *NewString;
    t_PendingStrings *PendingStrings = (t_PendingStrings *) xv_get(List,
	XV_KEY_DATA, PENDING_STRINGS
    
    if (PendingStrings) {
	register int i = PendingStrings->HowManyUsed;

	if (i) {
	    ListBatchInsert(List, PendingStrings);

	    while (i-- > 0) {
		(void) free(PendingStrings->Strings[i]);
	    }
	}

	(void) free(PendingStrings);
	xv_set(List,
	    XV_KEY_DATA, PENDING_STRINGS, NULL,
	    NULL
	);

    } else {
	// is this an error?  I'd say not.
    }
}

static void
ListBatchInsert(List, PendingStrings)
    Panel_item List;
    t_PendingStrings *PendingStrings;
{
    register int i, j;
    int n;
    char *s;
    void *Attributes[ATTR_STANDARD_SIZE];
    Font f = (Font) xv_get(List, XV_KEY_DATA, MY_LIST_FONT);
    n = (int) xv_get(List, PANEL_LIST_NROWS);

    if (f) {
	for (i = 0, j = 0; i < PendingStrings->HowManyUsed; i++) {
	    Attributes[j++] = (void *) PANEL_INSERT_STRING;
	    Attributes[j++] = (void *) n + i;
	    Attributes[j++] = (void *) PendingStrings->Strings[i];
	    Attributes[j++] = (void *) PANEL_LIST_FONT;
	    Attributes[j++] = (void *) n + i;
	    Attributes[j++] = f;

	    if (j + 6 >= ATTR_STANDARD_SIZE) {
		Attributes[j] = (void *) NULL;
		xv_set(List,
		    ATTR_LIST, Attributes,
		    NULL
		);
		j = 0;
	    }
	}
	if (j) {
	    Attributes[j] = (void *) NULL;
	    xv_set(List,
		ATTR_LIST, Attributes,
		NULL
	    );
	}
    } else {
	/* simple batch insert */
	xv_set(List,
	    PANEL_INSERT_STRINGS, n + 1, PendingStrings->Strings,
	    NULL
	);
    }
}

// put my .signature in a comment :-)

-- 
Liam Quin, lee@sq.com, SoftQuad, Toronto, 416 239-4801; the barefoot programmer
 lq-text (Unix text retrieval package) mailing list: lq-text-request@sq.com
 HexSweeper NeWS game/OPEN LOOK UI FAQ & program list/Metafont list/XView ports