[comp.sys.mac.programmer] List Manager Strangeness

mithomas@bsu-cs.bsu.edu (Michael Thomas Niehaus) (09/22/89)

I am trying to get the List Manager to keep a list of items for me in a
modeless dialog.  So far, everything works as planned, but I occasionally
get strange behaviors.  For example, sometimes I can select the first item
in the list, then click on the second (with no modifier keys) and still
manage to select both cells.  Double clicking on any cell does not get
LClick to return true, unless the above behavior is also happening at the
same time.  Does anyone know what is going on?

For diagnostic purposes (and general interest), I have included the portion
of source code that creates the dialog, replaces the userItem with the list
update routine, etc.  Does anyone see any problems with this?

Thanks for any help.  (By the way, this is from my Booz program, the Zoo
archive extracting application.  I have posted this to comp.binaries.mac,
but nothing I have ever sent there has made it past the moderator.  I guess
it is not seen as useful.  This code is actually from my latest version, but
the version that I posted has the same behavior, annoying but not severe.)

-Michael

	SetDAFont(21);	
	localDialog=GetNewDialog(133,0,-1);
	SetWTitle((WindowPtr) localDialog,whatFile);
	SelectWindow( (WindowPtr) localDialog);
	SetPort(localDialog);
	SetDAFont(0);

	csize.v=0;
	csize.h=199;
	SetRect(&viewRect,10,10,200,200);
	SetRect(&dataBounds,0,0,1,0);

	GetDItem( localDialog, 2, &itemType, &theItemHandle, &theItemRect );
	SetDItem( localDialog, 2, itemType, UpdateList, &theItemRect );
	
	localList = LNew(&viewRect,&dataBounds,csize,0,localDialog,
		true,false,false,true);
	SetWRefCon(localDialog,(long) localList);
	LActivate(true,localList);
	
	/*  Open file, read header and entries.  */
	
	SetFPos(localFile, 1,zoo_header.zoo_start);
	theCell.h=0;
	theCell.v=-1;
	
	rd_dir(&direntry,localFile);

	while (direntry.next != 0L )
	{
		if (direntry.lo_tag != LO_TAG || direntry.hi_tag != HI_TAG)
		{
			prterror (stopAlert, "\pBad entry in archive");
			err=-1;
			break;
		}
		theCell.v=LAddRow(1,theCell.v+1,localList);
		if (direntry.namlen==0)
			LSetCell(&(direntry.fname),
                          strlen((char *) &(direntry.fname)),theCell,localList);
		else
			LSetCell(&(direntry.lfname),direntry.namlen,
				theCell,localList);
		SetFPos (localFile, 1, direntry.next);
		rd_dir (&direntry,localFile);
	}
	LUpdate( (localDialog)->visRgn,localList);

	
-- 
Michael Niehaus        UUCP: <backbones>!{iuvax,pur-ee}!bsu-cs!mithomas
Apple Student Rep      ARPA:  mithomas@bsu-cs.bsu.edu
Ball State University  AppleLink: ST0374 (from UUCP: st0374@applelink.apple.com)

jb@aries5.uucp (10/18/89)

In article <10152@bsu-cs.bsu.edu> mithomas@bsu-cs.bsu.edu (Michael Thomas Niehaus) writes:
>I am trying to get the List Manager to keep a list of items for me in a
>modeless dialog.  So far, everything works as planned, but I occasionally
>
>	csize.v=0;
>	csize.h=199;
>	SetRect(&viewRect,10,10,200,200);
>	SetRect(&dataBounds,0,0,1,0);

the width of the viewRect:  200 - 10 = 190
the width of the cellSize:  199
199 > 190
I think this is your problem, I have never tried having cells wider
than the view rectangle.

Otherwise it is in your filter proc, send me/post a copy of it.

Jim Bruyn
Computer Systems Group
University of Waterloo

sdh@flash.bellcore.com (Stephen D Hawley) (02/28/90)

Hey - here's a question.

I have a list that contains a list of available font names (built as per
TN 191) and I want to find which font name matches a particular window's
font.  So I call LSearch() and it returns FALSE no matter what.  So I
do a break and stepp through and find out that yes, in fact, the font name
I have is in the list.  So I install my own comparison function.  It never
gets called (!!).  Is this normal behavior?  I'm now doing the following:

ListHandle fontList;

FindCurrentFont(win)
WindowPtr win;
{
	int fNum, i, dataLen;
	Str255 fName, cellName;
	Cell c;

	fNum = win->txFont;

	GetFontName(fNum, fName);

/* This for() loop works --but the rom call (commented out below) doesn't.
 */
/*
 *	c.h = c.v = 0;
 *	if (!LSearch((Ptr)(fName+1), (int)(*((unsigned char*)fName)),
 *		NIL, &c, fontList)) c.v = 0;
 */ 
	c.h = 0;
	for (i=(**fontList).dataBounds.top; i<(**fontlist).dataBounds.bottom;
		i++) {
		c.v = i;
		/* get 1 more character than the length of the target name */
		dataLen = (int)(*((unsigned char *)fName))+1;
		LGetCell((Ptr)(cellName+1), &dataLen, c, fontList);
		/* dataLen has the actual length now */
		*cellName = (char)dataLen;
		if ((int)(*((unsigned char*)fName)) == dataLen &&
			strncmp(fName+1, cellName+1, dataLen) == 0) break;
	}
	if (i >= (**fontList).dataBounds.bottom) c.v = 0; /* no match */

	return(c.v); /* I actually do something else, but you get the idea */
}

So what gives?

Steve Hawley
sdh@flash.bellcore.com
A noun's a special kind of word.
It's ev'ry name you ever heard.
I find it quite interesting,
A noun's a person place or thing.

mithomas@bsu-cs.bsu.edu (Michael Thomas Niehaus) (02/28/90)

The following code is extracted from one of my programs.  Basically, it
goes through a list, comparing every entry against some given text.
(Actually, it does some wildcard expansion/comparison, but I hacked it
apart to do this instead.)

In this case, it hilites any entry in the list that equals "Helvitica".

	strcpy(&theText,"Helvitica");
        theCell.h=0;
	numRows=(**localList).dataBounds.bottom;
	for (i=0;i<numRows;i++)
	{
		dataLen=64;
		theCell.v=i;
		LGetCell(&listText,&dataLen,theCell,localList);
		listText[dataLen] = 0;
		if ( strcmp(&theText,&listText) == 0)
			LSetSelect(true,theCell,localList);
	}

There is one thing to point out in this routine (written in Think's C,
if anyone cares).  Both theText and listText are C strings.

For theText, this is done by the strcpy on the first line.  (I know, literals
are bad, but this is only an example.)

For listText, this is done by setting the character element after the end of
listText to 0, to signifiy the end of the string.  (The list manager does not
do this for you.  It just returns the text and the length and you have to
combine them.  I found that if you don't put that 0 on the end, your
comparison will almost always turn up false, unless by some stroke of luck
there was a 0 there anyway.)

Be careful that either both strings are C strings, or both are Pascal strings.
If they are C strings, make sure they are null-terminated.

-Michael

-- 
Michael Niehaus        UUCP: <backbones>!{iuvax,pur-ee}!bsu-cs!mithomas
Apple Student Rep      ARPA:  mithomas@bsu-cs.bsu.edu
Ball State University  AppleLink: ST0374 (from UUCP: st0374@applelink.apple.com)

d88-jwa@nada.kth.se (Jon Watte) (02/28/90)

In article <10841@bsu-cs.bsu.edu> mithomas@bsu-cs.UUCP (Michael Thomas Niehaus) writes:
>The following code is extracted from one of my programs.  Basically, it

Did it work ( the program ) ? 

>	strcpy(&theText,"Helvitica");

>		LGetCell(&listText,&dataLen,theCell,localList);
>		listText[dataLen] = 0;
>		if ( strcmp(&theText,&listText) == 0)

listText is declared as char *, right ? So when you do LGetCell,
you get a char pointer, and you dereference it with offset dataLen.
The problem is, why do you send the address of this pointer to strcmp ?
And, if theText is a pointer as well, you're not doing the right
thing (in fact, you cannot take the address of an array in C...)

or am i riding alone in never-never land again ?

>Be careful that either both strings are C strings, or both are Pascal strings.
>If they are C strings, make sure they are null-terminated.

And if they are pascal strings, of course you cannot use strcmp()

Best thing to do is using EqualString (you'll have to convert C strings
to pascal things, of course) with diacritical sensitivity to TRUE and
case sensitivity to FALSE (Note: In sweden, the A and O with dots over
them come at the end of the alphabet, so the SFGetFile that places OE
right after O is very disturbing. Apple; take note !)

h+
-- 
   ---  Stay alert !  -  Trust no one !  -  Keep your laser handy !  ---
             h+@nada.kth.se  ==  h+@proxxi.se  ==  Jon Watte
                    longer .sig available on request

sdh@flash.bellcore.com (Stephen D Hawley) (02/28/90)

In article <10841@bsu-cs.bsu.edu> mithomas@bsu-cs.UUCP (Michael Thomas Niehaus) writes:
> [Michael's code removed]
>-Michael
>
>-- 
>Michael Niehaus        UUCP: <backbones>!{iuvax,pur-ee}!bsu-cs!mithomas
>Apple Student Rep      ARPA:  mithomas@bsu-cs.bsu.edu
>Ball State University  AppleLink: ST0374 (from UUCP: st0374@applelink.apple.com)


Thanks for the code, Michael, but as I said, the code I posted works well
enough, I would just like to know why LSearch() is failing so miserably.

Steve Hawley
sdh@flash.bellcore.com
A noun's a special kind of word.
It's ev'ry name you ever heard.
I find it quite interesting,
A noun's a person place or thing.

bowman@reed.UUCP (Eric Bowman) (03/01/90)

In article <3039@draken.nada.kth.se> d88-jwa@nada.kth.se (Jon W{tte) writes:
>In article <10841@bsu-cs.bsu.edu> mithomas@bsu-cs.UUCP (Michael Thomas Niehaus) writes:
>
>>		LGetCell(&listText,&dataLen,theCell,localList);
>>		listText[dataLen] = 0;
>>		if ( strcmp(&theText,&listText) == 0)
>
>listText is declared as char *, right ? So when you do LGetCell,
>you get a char pointer, and you dereference it with offset dataLen.

Right.

>The problem is, why do you send the address of this pointer to strcmp ?

Right again.

>thing (in fact, you cannot take the address of an array in C...)
        ^^^^^^^
I don't think fact is the right word to use here...since this statement
has nothing to do with truth.

>or am i riding alone in never-never land again ?

Pretty much.

This is legitimate:

	char a[5],b[5],c[5],*d[3];

	d[0]=&a;
	d[1]=&b;
	d[2]=&c;

	<blah, blah, blah>

The beauty of C is no matter what weird and potentially pointless thing
you want to do, you can do it.

BobO
bowman@reed.{bitnet,UUCP}
"*or she.  Masculine pronouns in this book are usually not intended to
connote gender.  Occasional chauvinistic comments are not to be
taken seriously."  - Donald E. Knuth, _The Art of Computer Programming_, vol 1

	
>             h+@nada.kth.se  ==  h+@proxxi.se  ==  Jon Watte
>                    longer .sig available on request

dan@lclark.UUCP (Dan Revel) (03/02/90)

In article <20392@bellcore.bellcore.com> sdh@flash.UUCP (Stephen D Hawley) writes:
> *	if (!LSearch((Ptr)(fName+1), (int)(*((unsigned char*)fName)),
> *		NIL, &c, fontList)) c.v = 0;
                                    ^^^^^^^
>	if (i >= (**fontList).dataBounds.bottom) c.v = 0; /* no match */
                                                 ^^^^^^^
Watch out!  c = {0,0} is a valid cell for the List Manager.

>So what gives?

I don't know, this works for me (Mac IIx, 5Megs, Multifinder, Think C 4.0):

ListHandle	fList;

main()
{
	WindowPtr	fWind;
	Cell		cSize = {15, 100};
	Rect		bounds = {40, 40, 400, 140};
	Rect		rView = {0, 0, 360, 100};
	Rect		dBounds = {0, 0, 0, 1};			/* no rows, one column */

	fWind = NewWindow(0L,&bounds,"\pFonts",TRUE,plainDBox,-1L,FALSE,0L);
	fList = LNew(&rView,&dBounds,cSize,0,fWind,TRUE,FALSE,FALSE,FALSE);
	BuildFontList();
	FindCurrentFont(fWind);
	while (!Button()) ;
}

FindCurrentFont(w)
WindowPtr	w;
{
	Cell	c;
	Str255	fName;
	int		fNum;
	
	fNum = (*w).txFont;
	GetFontName(fNum, fName);
	c.h = c.v = 0;
	if (LSearch(&fName[1],fName[0],0L,&c,fList))
		LSetSelect(TRUE,c,fList);
}

#define	UnusedMenuID	150

BuildFontList()
{
	MenuHandle	tempMenu;
	int			fontCount;
	Str255		aFontName;
	Cell		c = {0, 0};
	
	tempMenu = NewMenu(UnusedMenuID,'x');
	AddResMenu(tempMenu,'FONT');
	fontCount = CountMItems(tempMenu);
	c.v = LAddRow(fontCount, (**fList).dataBounds.bottom, fList);
	for (c.v = 0; c.v < fontCount; c.v++) {
		GetItem(tempMenu, (c.v + 1), aFontName);
		LSetCell(&aFontName[1], aFontName[0], c, fList);
	}
	DisposeMenu(tempMenu);
}
-- 
dan@lclark
tektronix!reed!lclark!dan			Dylsexics untie! (-|

d88-jwa@nada.kth.se (Jon Watte) (03/02/90)

In article <14318@reed.UUCP> bowman@reed.UUCP (Eric Bowman) writes:
>In article <3039@draken.nada.kth.se> d88-jwa@nada.kth.se (Jon W{tte) writes:

>>thing (in fact, you cannot take the address of an array in C...)

>I don't think fact is the right word to use here...since this statement
>has nothing to do with truth.

>	char a[5],b[5],c[5],*d[3];

>The beauty of C is no matter what weird and potentially pointless thing
>you want to do, you can do it.

I know. I could have sworn I happened upon some strange construct
using "address of array" or some such that wasn't valid C a while
ago...

Maybe it was something like char *(foo[]); which is _not_ valid C.

h+
-- 
   ---  Stay alert !  -  Trust no one !  -  Keep your laser handy !  ---
             h+@nada.kth.se  ==  h+@proxxi.se  ==  Jon Watte
                    longer .sig available on request