Page 1 of 2

Listbrowser entering a list from a file

Posted: Sat Dec 20, 2014 2:24 pm
by JosDuchIt

Code: Select all


struct List *make_listbrowser_file (char *filepath) /// called with (input_file)
{
	BOOL						done = FALSE;
	BOOL 						ListOK = FALSE;
	char 						buf[MAX_LINE];
	STRPTR					Buffer;
	LONG						len;
	struct List 			*list=NULL;
	FILE 						*input_file = NULL;
	struct FReadLineData *frld=NULL;
   struct Node 			*node;
Printf("makeLB_file  %s\n",filepath);  /// seen
	input_file = FOpen(filepath, MODE_OLDFILE,MAX_LINE); ///IDOS->
	if(!input_file)
	{
Printf("makeLB_file  %s could not be opened\n",filepath); 		
		///log_displayBox("ReqList", 0, concat3strings("File", filepath, " cannot be opende"),NULL ); ///scr not declared 
		log_displayBox("ReqList", 0, filepath,NULL ); ///scr not declared 
		return (NULL);
	}
	if ((list = AllocVecTags (sizeof(struct List), AVT_ClearWithValue, 0, TAG_END)))
	{
		NewList (list);
		frld = AllocDosObject(DOS_FREADLINEDATA,TAG_END); ///IDOS-> and freed with FreeDosObject(),
		if(frld!=NULL)
		{
Printf("FREadline  allocated \n", NULL); /// seen
			while ((done == FALSE))
			{	
				len = FReadLine(input_file,frld); //dos.library/FReadLine	The function will return -1 on error, or the length of bytes read into 
															///	the internally allocated buffer, pointed to by frld_Line.
				if (len!=NULL) ///(len > 0)  /// line length  will hold on empty line 
				{
					   if (node = AllocListBrowserNode (1,LBNCA_Text,frld->frld_Line,TAG_END ))
						{	
Printf("FReadLinelen %ld  Line  %s\n",len, frld->frld_Line); ///  seen for all strings
							AddTail (list,node);
						}
						else
						{ ListOK = FALSE;
						  done = TRUE;
							// /EZReq node for Buffer could not be allocated
						}
				}
				else 
				{
						ListOK = TRUE;
						done =TRUE; //list will be created
				}	
			} //endwhile 
		} ///frld ok
		else
		{
		//EZReq readline failed
			ListOK = FALSE;
		}
	}
	else 
	{
		//EZReq list allocation failed
		ListOK = FALSE;
	}
	if (frld) FreeDosObject(DOS_FREADLINEDATA,frld); ///IDOS->	
	if (ListOK)
		return (list);
	else
	{
		free_listbrowser_list (list);
		return (NULL);
	}
	if(input_file) FClose(input_file);
}

What am i doing wrong ? the generated list shows the same number of lines as in the file but contains rubbish (partos oof last line & unreadable characters)

Re: Listbrowser entering a list from a file

Posted: Sat Dec 20, 2014 4:36 pm
by thomasrapp

Re: Listbrowser entering a list from a file

Posted: Sat Dec 20, 2014 6:28 pm
by LyleHaze
There are a few other things that might trip you up..

If FReadLine errors, it will return a negative value, which is not NULL.
So even if FReadLine errors, you'll still process it's result as if it were a good line.

IDOS->FReadLine will terminate on a linefeed, but the linefeed is left at the end of each line.
This shows up in a listbrowser as a "box" at each line end.

In your example code, the input_file is left open.. the "IDOS->FClose()" at the end of the
example you gave will never be reached.

And as you already figured out, you need LBNCA_CopyText, TRUE before each LBNCA_Text, "" so that the
listbrowser knows to make a copy of each string.

Code: Select all

;/*
;
; To compile from the Shell, simply type: 'Execute LBRFiles.c'
;
gcc -N -o LBRFiles lbrfiles.c -Wall
IF NOT WARN
LBRFiles lbrfiles.c
ENDIF
quit
*/

#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/utility.h>
#include <proto/intuition.h>
#include <proto/listbrowser.h>
#include <proto/window.h>
#include <proto/layout.h>
#include <classes/window.h>
#include <string.h>

Class *WindowClass = NULL;
struct Library *WindowBase = NULL;
Class *LayoutClass = NULL;
struct Library *LayoutBase = NULL;
Class *ListBrowserClass = NULL;
struct Library *ListBrowserBase = NULL;
struct ListBrowserIFace *IListBrowser = NULL;
struct Library *IntuitionBase = NULL;
struct IntuitionIFace *IIntuition = NULL;

struct List *make_listbrowser_file (char *filepath);
BOOL openGlobals(void);
BOOL closeGlobals(CONST_STRPTR);

// Any characters in badChar will be replaced with a space.
//		badChar MUST have a zero at the end!!!
char badChar[] = {'\n', '\t',0};

struct List *make_listbrowser_file (char *filepath) /// called with (input_file)
{
	BPTR input_file = IDOS->FOpen(filepath, MODE_OLDFILE,0);
	if(0 == input_file)
	{
		IDOS->Printf("Could not open file %s for reading\n", filepath);
		return(NULL);
	}

	struct List *list = IExec->AllocSysObjectTags(ASOT_LIST, TAG_END);
	if(NULL == list)
	{
		IDOS->Printf("Could not allocate browser list\n");
		IDOS->FClose(input_file);
		return(NULL);
	}

	struct FReadLineData *frld = IDOS->AllocDosObject(DOS_FREADLINEDATA, TAG_END);
	if(NULL == frld)
	{
		IDOS->Printf("Could not alloc FReadLineData struct\n");
		IExec->FreeSysObject(ASOT_LIST, list);
		IDOS->FClose(input_file);
		return(NULL);
	}

	int32 len, count = 0;
	struct Node *node;

	len = IDOS->FReadLine(input_file, frld);

	while(len > 0)
	{
		// replace badChars with spaces
		char *next;
		while((next = strpbrk(frld->frld_Line, &badChar[0])))
		{
			*next = ' ';
		}

		if ((node = IListBrowser->AllocListBrowserNode (
			1,
			// CopyText, TRUE is required because the buffer
			// contents will be changing.. so we ask the
			// listbrowser to make a copy of each entry.
			LBNCA_CopyText, TRUE,
			LBNCA_Text, frld->frld_Line, 
			TAG_END )))
		{
			IExec->AddTail (list,node);
			count++;
		}
		else
		{
			IDOS->Printf("LBNode allocation failure\n");
			IDOS->SetIoErr(ERROR_NO_FREE_STORE);
			len = -1;
		}

		len = IDOS->FReadLine(input_file, frld);
	}

	if(len < 0)
	{
		IDOS->PrintFault(IDOS->IoErr(), NULL);
		IListBrowser->FreeListBrowserList(list);
		IExec->FreeSysObject(ASOT_LIST, list);
		list = NULL;
	}

	IDOS->FreeDosObject(DOS_FREADLINEDATA, frld);
	IDOS->FClose(input_file);

	return(list);
}

int main(int argc, char **argv)
{
	if(argc < 2)
	{
		IDOS->Printf("Required filename missing\n");
		return(RETURN_FAIL);
	}

	if(!openGlobals())
	{
		return(RETURN_FAIL);	
	}

	// make the list
	struct List *file_list = make_listbrowser_file(argv[1]);

	// show the list in a listbrowser window
	if(file_list)
	{
		Object *gadget;
		Object *winOb = IIntuition->NewObject(WindowClass,NULL,
			WA_CloseGadget, TRUE,
			WA_SizeGadget, TRUE,
			WA_DragBar, TRUE,
			WA_Title, "ListBrowser Example",
			WINDOW_Position, WPOS_CENTERSCREEN,
			WA_Width, 300,
			WA_Height, 300,
			WINDOW_Layout, IIntuition->NewObject(LayoutClass,NULL,
				LAYOUT_Orientation, LAYOUT_ORIENT_VERT,
				LAYOUT_AddChild, gadget = IIntuition->NewObject(
					ListBrowserClass, NULL,
					LISTBROWSER_Labels, file_list,
				TAG_END),
			TAG_END),
		TAG_END);

		if(winOb)
		{
			IIntuition->IDoMethod(winOb, WM_OPEN);

			uint32 signal, result, done = FALSE;
			uint16 code;

			IIntuition->GetAttr(WINDOW_SigMask, winOb, &signal);

			while(!done)
			{
				IExec->Wait(signal);
				while ( (result = IIntuition->IDoMethod(winOb, WM_HANDLEINPUT, &code) ) != WMHI_LASTMSG )
				{
					if(WMHI_CLOSEWINDOW == (result & WMHI_CLASSMASK))
					{
						done = TRUE;
					}
				}
			}

			IIntuition->DisposeObject(winOb);
		}

		IListBrowser->FreeListBrowserList(file_list);
		IExec->FreeSysObject(ASOT_LIST, file_list);
	}

	closeGlobals(NULL);
	return(RETURN_OK);
}

BOOL openGlobals(void)
{
	if(!(IntuitionBase = IExec->OpenLibrary("intuition.library", 53)))
	{
		return(closeGlobals("Failed to open Intuition"));
	}

	if(!(IIntuition = (struct IntuitionIFace *)IExec->GetInterface(IntuitionBase, "main", 1, NULL)))
	{
		return(closeGlobals("Failed to get intuition interface\n"));
	}

	if(!(WindowBase = (struct Library *)IIntuition->OpenClass(
		"classes/window.class", 53, &WindowClass)))
	{
		return(closeGlobals("Failed to open Window Class"));
	}

	if(!(LayoutBase = (struct Library *)IIntuition->OpenClass(
		"gadgets/layout.gadget", 53, &LayoutClass)))
	{
		return(closeGlobals("Failed to open Layout Class"));
	}

	if(!(ListBrowserBase = (struct Library *)IIntuition->OpenClass(
		"gadgets/listbrowser.gadget", 53, &ListBrowserClass)))
	{
		return(closeGlobals("Failed to open listbrowser class"));
	}

	IListBrowser = (struct ListBrowserIFace *)IExec->GetInterface(
		(struct Library *)ListBrowserBase, "main", 1L, NULL);
	if(NULL == IListBrowser)
	{
		return(closeGlobals("Failed to get ListBrowser interface"));
	}	

	return(TRUE);
}

BOOL closeGlobals(CONST_STRPTR why)
{
	if(why)
	{
		IDOS->Printf("%s\n", why);
	}

	IExec->DropInterface((struct Interface *)IListBrowser);
	IIntuition->CloseClass((struct ClassLibrary *)ListBrowserBase);
	IIntuition->CloseClass((struct ClassLibrary *)LayoutBase);
	IIntuition->CloseClass((struct ClassLibrary *)WindowBase);
	IExec->DropInterface((struct Interface *)IIntuition);
	IExec->CloseLibrary(IntuitionBase);

	return(FALSE);
}
(edit) replaced code with updated version

Re: Listbrowser entering a list from a file

Posted: Sat Dec 20, 2014 6:44 pm
by JosDuchIt
@thomasrapp
You got the idea already:
it was more guessoworj than understanding & i ran into the "linefeed" problem LyleHaze pointed at.

@LyleHaze Thank you very much for code & tutorial remarks.

Re: Listbrowser entering a list from a file

Posted: Sat Dec 20, 2014 7:18 pm
by LyleHaze
Oops, I screwed up my example code.. (no great suprise there)

The while loop should look like this:

(edit) see post 3 for the corrected source,

That will sort out the ugly first line.. sorry about that.
I'm still learning. :)

It's a shame that anything inserted into this website as "Code" gets an extra character added to the end of every line.

It makes it impossible to just copy, paste, and compile.

(edit) As pointed out in a later post by ThomasRapp, you can press the "Quote" button then copy the text successfully from the edit box.

Have Fun!

Re: Listbrowser entering a list from a file

Posted: Sat Dec 20, 2014 9:15 pm
by nbache
LyleHaze wrote:It's a shame that anything inserted into this website as "Code" gets an extra character added to the end of every line.
Actually not to the end, but to the beginning, and it's three characters: A020A0h, i.e. a non-breaking space, a space and one more non-breaking space. When indenting, multiple copies of the same sequence are used - indeed quite weird.

Maybe we need an export function for code fields - with a choice of tabs or spaces replacing those sequences?

Best regards,

Niels

Re: Listbrowser entering a list from a file

Posted: Sat Dec 20, 2014 9:52 pm
by salass00
nbache wrote:Actually not to the end, but to the beginning, and it's three characters: A020A0h, i.e. a non-breaking space, a space and one more non-breaking space. When indenting, multiple copies of the same sequence are used - indeed quite weird.
IIRC those non-breaking space characters cause errors in gcc if you copy-paste the code into a texteditor, save and try to compile it.

Re: Listbrowser entering a list from a file

Posted: Sat Dec 20, 2014 9:52 pm
by LyleHaze
It would make posting code a lot easier.. or perhaps I should say it would make Copying code that has been posted a lot easier.

If the focus of this site was programming, I'd be a lot more likely to suggest it. But since this is an OS support website, the need for copy-and-pasting c code is probably not so important as to ask for changes.

For whatever it's worth I found and fixed a couple other small things in the example code I posted, and I have offered to EMail it to JosDuchit if he would like a corrected example. I have replaced my rather crude code for removing linefeeds with something a bit more flexible.. I'm now using strpbrk to replace any undesireable characters with blank spaces.. this makes it easy to add more characters to be filtered.. as I found out that Tab characters also show as blocks in the ListBrowser.

Thanks for the details on what went wrong in formatting.. perhaps the easiest fix would be to allow file attachments, but that opens a whole new can of worms regarding how to make sure attachments are appropriate. .

Every day I learn a bit more.. sometimes I can even remember it!

Merry Happy Joyous holiday of your personal designation. ;)

Re: Listbrowser entering a list from a file

Posted: Sat Dec 20, 2014 10:15 pm
by thomasrapp
nbache wrote:Maybe we need an export function for code fields - with a choice of tabs or spaces replacing those sequences?
Just use the Quote button and copy the code from the text entry field.

Re: Listbrowser entering a list from a file

Posted: Sat Dec 20, 2014 10:27 pm
by nbache
thomasrapp wrote:
nbache wrote:Maybe we need an export function for code fields - with a choice of tabs or spaces replacing those sequences?
Just use the Quote button and copy the code from the text entry field.
Excellent - thanks for that tip!

That does it.

Best regards,

Niels