Hi,
I have a function called make_browserlist as follows:
BOOL make_browserlist(struct List *list, char **tagstring, int columns) { struct Node *node; IExec->NewList(list); switch (columns) { case 2: while (*tagstring) { if (node = IListBrowser->AllocListBrowserNode(columns, LBNA_Column, 0, LBNCA_Text, *tagstring++, LBNA_Column, 1, LBNCA_Text, *tagstring++, TAG_DONE)) { IExec->AddTail(list, node); } else { IDOS->Printf(" AllocListBrowserNode() failed\n"); return(FALSE); } } case 3: while (*tagstring) { if (node = IListBrowser->AllocListBrowserNode(columns, LBNA_Column, 0, LBNCA_Text, *tagstring++, LBNA_Column, 1, LBNCA_Text, *tagstring++, LBNA_Column, 2, LBNCA_Text, *tagstring++, TAG_DONE)) { IExec->AddTail(list, node); } else { IDOS->Printf(" AllocListBrowserNode() failed\n"); return(FALSE); } } case 5: while (*tagstring) { if (node = IListBrowser->AllocListBrowserNode(columns, LBNA_Column, 0, LBNCA_Text, *tagstring++, LBNA_Column, 1, LBNCA_Text, *tagstring++, LBNA_Column, 2, LBNCA_Text, *tagstring++, LBNA_Column, 3, LBNCA_Text, *tagstring++, LBNA_Column, 4, LBNCA_Text, *tagstring++, TAG_DONE)) { IExec->AddTail(list, node); } else { IDOS->Printf(" AllocListBrowserNode() failed\n"); return(FALSE); } } break; default: IDOS->Printf(" Invalid number of list fields\n"); return(FALSE); }; // switch return(TRUE); }
I can call this with static STRPTR string data and populate my listbrowsers fine.
However, I want to use char[] arrays that have strings I have retrieved from an input text file to populate my listbrowser lists using this same function.
I suspect I need to coerce my character arrays into static strings somehow. When I try to pass my char arrays into this function I always seem to get DSI errors no matter what I do. So for example I might do the following:
char mylist[1000]; ... if(make_browserlist(&listbrowser_list1, mylist, 3) { // list made okay - continue with program } else { IDOS-Printf("Error making browser list!\n"); }
I am retrieving mylist using basic C fileio and verifying that the string data is actually populated in mylist.
Does mylist have to be global? I have tried calling make_browserlist with (char *)&mylist etc but always get the same result.
Thanks!
As you say, the file I/O routines do not return arrays of string pointers, they fill a user buffer with characters until EoF or CR.
You will need to take this buffer and manually copy each word in it into an array of STRPTRs in order to pass it to your function.
Alternatively, you can use FGetC() to retrieve one character from the file at a time and copy these while parsing for white space and newlines.
Simon
<*>
You will need to take this buffer and manually copy each word in it into an array of STRPTRs in order to pass it to your function.
*>
Yes...painful!
From what I can glean from playing with the GCC debugger, it looks like a STRPTR type is an array of pointers to static strings, each null (byte) terminated. So, for example:
really shows a series of four addresses, each of which I believe points to a static string in memory. Thus PageLabels[0] = 0x12345678 (an address in memory), which points to the null terminated static string "Credit or Bank Cards".
So is there an easier way to populate list browser strings from getline() file I/O?
Thanks
It really all depends on how your file is structured.
For example, an xml file would make it easier to read in the strings and place them in a list, which could then be used to create the listbrowser nodes.
To be honest, this conversation is far too general to try and offer any solutions. Specific problems are much easier to offer assistance with.
Simon
@ AmigaOneFan
Not that it answers your questions but anyway: I've found it easier and safer to use "LBNCA_CopyText, TRUE" when populating a listbrowser list from string pointers.
AmigaOne X5000-020 / 2GB RAM / Sapphire Pulse Radeon RX 560 / AmigaOS 4.1 Final Edition Update 2
Hi Simon,
Yes, I haven't given a lot of specifics. Thankfully, I have found a solution, not really elegant but it works! You can find my updated source code here: http://www.os4coding.net/source/162
Since we are using arrays of string pointers, here is a way I populate the data from getline file I/O:
I get the string and put it into mystring temporarily, convert the trailing \n into a nul, then copy it to Tab1Strings, which is defined as follows:
It is VITALLY IMPORTANT to be sure to malloc the memory I intend to use to store the strings, which I do in my main function prior to calling the LoadFile function that populates the strings:
I also am sure to free this memory upon closing the program. I could simply allocate the memory for each string as I use it and save a few thousand bytes of RAM, but this is a quick and dirty way to ensure I have all the space I need without worrying about malloc and free for every string populate and delete I will do.
So my AmiSafe.c program right now loads in a file of data, populates the list browsers for the four tabs of information from this file data, allows the user to edit in place the content of the strings, then (if you select the HELP button, for now) writes out the data in a format usable by the program in the amisafe.dat file.
Now all I need to do is come up with a way to add a new entry, delete a selected entry, and then add a 4x4 button matrix at startup to allow the user to create and use a password, then incorporate the RIJNDAEL algorithm to encode and decode the file data.
Easy.....I hope!
I hope this source and program helps others who want to do similar things in REACTION listbrowsers.
Okay, now a slightly different subject....
I am adding new data to a listbrowser by creating a new node and calling AddTail.
How do I update the display and the listbrowser attributes for this new entry? I'm sure there is some simple way to do this.....
Thanks!
To make any changes to the list currently displayed, you first have to detach the list by calling
Then you can make your changes (adding, removing or changing attributes). Once that is done, you reattach the list. Depending on how you do this depends on whether the list gets updated visually.
If you use SetAttrs() you will need to manually referesh the gadget afterwards. Luckily, the list can be set like so:
and this will refresh the gadget for you. You might want to check out the listbrowser examples in the Examples directory of the SDK, all this is covered quite nicely.
Simon
Hmmm...
I manage to deadlock the system (I think) when I do this. Here's what I am doing, please feel free to point out my foolish mistakes!
What am I doing wrong?
It can only be an invalid pointer, everything else looks fine (what there is of it).
Simon
@AmigaOneFan
Your use of type casts looks a little awkward there. OBJ(OBJ_LISTBROWSER1) should have been declared as a pointer to Object so you don't need to cast it to struct Gadget* in SetAttrs(). The correct line would be:
IIntuition->SetAttrs(OBJ(OBJ_LISTBROWSER1), LISTBROWSER_Labels, NULL, TAG_DONE);
SetGadgetAttrs() and RefreshSetGadgetAttrs(), on the other hand, expect their first argument to be a struct Gadget pointer (instead of an Object pointer) so the type cast is appropriate.
In your particular example, not much harm will be done but be careful about unnecessary type casting, it may cause trouble elsewhere.
AmigaOne X5000-020 / 2GB RAM / Sapphire Pulse Radeon RX 560 / AmigaOS 4.1 Final Edition Update 2