Page 2 of 2

Re: Listbrowser with autosort; restore original content

Posted: Tue Jan 06, 2015 5:26 pm
by LyleHaze
xenic wrote:
LyleHaze wrote: Is running as an endless loop. Somewhere after 300 times through it will wander into memory it should not be playing in, and things go badly from there.

Code: Select all

	while (lines[i] != NULL) 
	{
		node = AllocListBrowserNode(1, // crash
		       LBNCA_CopyText, TRUE,
		       LBNCA_Text, lines[i],
		       TAG_END);
		if (node == NULL)
		{
			FreeListBrowserList(list);
			FreeSysObject(ASOT_LIST, list);
			return NULL;
		}

		AddTail(list, node);
		++i;
	}
Due to lack of indentation in the pasted code, I think you missed the "++i" line below the section you quoted. Unless I'm missing something, I don't think it's an endless loop. However, there is a "return NULL" in a void function, which is wrong.

I failed to clip correctly, and the index is definitely being incremented.
It's only an endless loop if "while (lines != NULL)" always evaluates as true, which is does when run here.

Well, it continues to evaluate as TRUE only until the program crashes on DSI, so technically, it's NOT an
endless loop, but I don't think the original intent was "continue to increment until exception". ;)

Re: Listbrowser with autosort; restore original content

Posted: Tue Jan 06, 2015 6:51 pm
by xenic
LyleHaze wrote:Well, it continues to evaluate as TRUE only until the program crashes on DSI, so technically, it's NOT an endless loop, but I don't think the original intent was "continue to increment until exception". ;)
I misinterpreted your analysis because of the incomplete clip. Good catch on the loop control always evaluating to TRUE. I haven't tried to run the program but "lines" is declared as a 2 dimensional character array; which I think means that the first dimension will always contain a pointer to the second dimension text and lines will never be NULL unless it is set to NULL by the program.

It looks like the lines ( lines ) are being filled in elsewhere by Strlcpy() and the Strlcpy autodoc states this:

source -- Pointer to a NUL-terminated string which should be
copied to the 'destination' string buffer. This can be NULL
in which case an empty string is copied.

I think it's possible that the last lines might be a pointer to a NUL character (empty string). Perhaps something like: " while (lines[0] != '\0') " would work better for the loop in question?? It's just a guess though and the problem could be something else.

Re: Listbrowser with autosort; restore original content

Posted: Tue Jan 06, 2015 8:41 pm
by LyleHaze
xenic wrote:
LyleHaze wrote:Well, it continues to evaluate as TRUE only until the program crashes on DSI, so technically, it's NOT an endless loop, but I don't think the original intent was "continue to increment until exception". ;)
I misinterpreted your analysis because of the incomplete clip. Good catch on the loop control always evaluating to TRUE. I haven't tried to run the program but "lines" is declared as a 2 dimensional character array; which I think means that the first dimension will always contain a pointer to the second dimension text and lines will never be NULL unless it is set to NULL by the program.


I definitely made it look wrong with my bad clip.. Sorry if I mislead you.

As far as the program issues, I'm only guessing here because I have not dug in too deep..
If the purpose is to load up a bunch of ListNodes based on input text, or an input file, or whatever else.. and then
sort them by alpha ascending, alpha descending, or original order, then I'm going to suggest a different approach.

All the lines/nodes/whatever are already stored in the list nodes. keeping separate copies in a two dimensional character array is a waste of space.
Lists have no length limit, so using an array is selling yourself short anyway. The strings are stored in the list nodes already.

If each node had LBNA_UserData set to something like.. a number that is incremented with each new entry..
then restoring the list to original order would be as easy as sorting on that field.

But that's just one idea.

Re: Listbrowser with autosort; restore original content

Posted: Wed Jan 07, 2015 8:53 am
by JosDuchIt
@LyleHaze, thanks for the reference to Trixie's blog
It certainly makes things more clear.
The source below now compilies without warnings, although not entirely conform to the recommendations
/* Programmname ReqList */
#define __USE_INLINE__
#define __NOLIBBASE__
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------*/
/* Usage */
/* ReqList TITLE "City" BODY "Please select:" CHOICES "Berlin" "London" "Madrid" "Paris" "Rome" PERSIST NOTEMPTY*/
/* ReqList TITLE "City" BODY "Please select:" I_FILE clips:0 PERSIST NOTEMPTY O_FILE T:selected */

/*----------------------------------------------------------------------------*/
/* Compile
/* gcc Req_List.c -lraauto -lauto -gstabs -N -o reqlist */
/*----------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------*/
/* System Includes */
/*----------------------------------------------------------------------------*/

#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
#include <proto/utility.h>
#include <proto/textclip.h>

#define ALL_REACTION_CLASSES
#include <reaction/reaction.h>
#include <reaction/reaction_macros.h>

#include <clib/alib_protos.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
///#include "CBIO_.c" /// not used yet ; use other clipunits


/*----------------------------------------------------------------------------*/
/* Konstanten & Makros */
/*----------------------------------------------------------------------------*/

char badChar[] = {'\n', '\t',0};
enum
{
GID_LIST,
GID_OK,
GID_CANCEL,
GID_INVERSE,
GID_ALL,
GID_NONE,
GID_RESTORE, ///to original content sequence (after having sorted)
//GID_SORT_DSC, /// taken over with toggle
GID_NUM
};

enum
{
COL_DEFAULT_SORT,
///COL_CUSTOM_SORT,
///COL_LBM_SORT,
NUM_COLS
};

#define TOTAL_LINES 300
#define MAX_LINE 1280
#define MAX_CLIP 25600

char lines[TOTAL_LINES][MAX_LINE];
int totallines = 0;


#ifdef __amigaos4__
/// http://www.os4coding.net/blog/trixie/re ... rogramming
#define BASEDEF(base) struct Library *base##Base = NULL; struct base##IFace *I##base = NULL
#define OPENLIB(base,name) if (!((base##Base) = OpenLibrary ((name),0)) || !((I##base) = (void *)GetInterface ((base##Base),"main",1,NULL))) ok = FALSE
#define OPENLIBMIN(base,name,min) if (!((base##Base) = OpenLibrary ((name),min)) || !((I##base) = (void *)GetInterface ((base##Base),"main",1,NULL))) ok = FALSE
#define CLOSELIB(base) if (I##base) DropInterface ((struct Interface *)(I##base)); if (base##Base) CloseLibrary (base##Base)
#else
#define BASEDEF(base) struct Library *base##Base = NULL
#define OPENLIB(base,name) if (!((base##Base) = OpenLibrary ((name),0))) ok = FALSE
#define OPENLIBMIN(base,name) if (!((base##Base) = OpenLibrary ((name),min))) ok = FALSE
#define CLOSELIB(base) if (base##Base) CloseLibrary (base##Base)
#endif

/*----------------------------------------------------------------------------*/
/* Typdefinitionen */
/*----------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------*/
/* Globale Variablen */
/*----------------------------------------------------------------------------*/

BASEDEF(Window);
BASEDEF(Layout);
BASEDEF(Button);
BASEDEF(ListBrowser);
BASEDEF(Requester);


/*----------------------------------------------------------------------------*/
/* ReAction-Klassen Öffnen */
/*----------------------------------------------------------------------------*/

BOOL open_classes (void)
{
BOOL ok = TRUE;

OPENLIBMIN(Window,"window.class",52);
OPENLIBMIN(Layout,"gadgets/layout.gadget",52);
OPENLIBMIN(Button,"gadgets/button.gadget",52);
OPENLIBMIN(ListBrowser,"gadgets/listbrowser.gadget",52);
OPENLIBMIN(Requester,"requester.class",52);
return (ok);
}

/*----------------------------------------------------------------------------*/
/* ReAction-Klassen schließen */
/*----------------------------------------------------------------------------*/

void close_classes (void)
{
CLOSELIB(Window);
CLOSELIB(Layout);
CLOSELIB(Button);
CLOSELIB(ListBrowser);
CLOSELIB(Requester);
}

/*----------------------------------------------------------------------------*/
/* free_listbrowser_list */
/*----------------------------------------------------------------------------*/

void free_listbrowser_list (struct List *list)
{
FreeListBrowserList (list);
FreeVec (list);
}



// *******************************************************************
// Make strict UPPERCASE
// return same we got (for use in functions)
// *******************************************************************

UBYTE * makeupper(UBYTE *str)
{
UBYTE *p;
for (p = str; *p!='\0'; p++) *p = toupper((char)*p); /// crash ???
return (str);
}

/*----------------------------------------------------------------------------*/
/* */
/*----------------------------------------------------------------------------*/
char *my_strtok_r(char *s, const char *sep, char **state) {
char *tok;
char c;
if (s == NULL && (s = *state) == NULL)
return NULL;
tok = s;
while ((c = *s) != '\0' && strchr(sep, c) == NULL) s++;

if (c != '\0')
*s++ = '\0';
else
s = NULL;

*state = s;

return tok;
}


/*----------------------------------------------------------------------------*/
/* Print the list */
/*----------------------------------------------------------------------------*/
void PrintListBrowser(Object *wnd, Object *lb)
{
struct Window *window;
struct List *list;
struct Node *node;
uint32 selected;
// get list
GetAttr(LISTBROWSER_Labels, lb, (uint32 *)&list);
for (node = list->lh_Head; node->ln_Succ; node = node->ln_Succ)
{
selected = FALSE;
GetListBrowserNodeAttrs(node,
LBNA_Selected, &selected,
TAG_END);
SetListBrowserNodeAttrs(node,
LBNA_Selected, !selected,
TAG_END);
}


}

/*----------------------------------------------------------------------------*/
/* Restore the original loaded sequence //maintain the selection status */
/*----------------------------------------------------------------------------*/

BOOL RestoreListBrowser(Object *wnd, Object *lb) /// listbrowser object //gadget
{
struct Window *window=NULL;
struct List *list=NULL;
struct Node *node=NULL;
int i = 0;
Printf("restore totallines %ld\n",(LONG)totallines);
GetAttr(LISTBROWSER_Labels, lb, (uint32 *)&list);
SetAttrs(lb, LISTBROWSER_Labels, ~0, TAG_END); ///remove list
list = AllocSysObject(ASOT_LIST, NULL);
if (list == NULL)
{
return (FALSE);
}
while (i < totallines)
{
node = AllocListBrowserNode(1,
LBNCA_CopyText, TRUE,
LBNCA_Text, lines,
TAG_END);
if (node == NULL)
{
FreeListBrowserList(list);
FreeSysObject(ASOT_LIST, list);
return (FALSE);
}
AddTail(list, node);
Printf("restore i %ld %s\n",(LONG)i,lines); ///seen
++i;
}

// get intuition window pointer
window = NULL;
GetAttr(WINDOW_Window, wnd, (uint32 *)&window); /// (uint32 )&window)passing argument 4 of 'IIntuition->GetAttr' makes pointer from integer without a cast
///GetAttr(WINDOW_Window, wnd, (uint32 *)window); ///passing argument 4 of 'IIntuition->GetAttr' from incompatible pointer type

Printf("GotAttr\n"); /// seen
// read list and refresh
SetGadgetAttrs((struct Gadget *)lb, window, NULL,
LISTBROWSER_Labels, list,
TAG_END);
Printf("SetAttr\n"); /// seen
return (TRUE);
}


/*----------------------------------------------------------------------------*/
/* Inverse the chosen Selection */
/*----------------------------------------------------------------------------*/

void InvertListBrowser(Object *wnd, Object *lb)
{
struct Window *window=NULL;
struct List *list=NULL;
struct Node *node=NULL;
uint32 selected;

// get list
GetAttr(LISTBROWSER_Labels, lb, (uint32 *)&list);

// remove list
SetAttrs(lb, LISTBROWSER_Labels, ~0, TAG_END);

// make changes
for (node = list->lh_Head; node->ln_Succ; node = node->ln_Succ)
{
selected = FALSE;
GetListBrowserNodeAttrs(node,
LBNA_Selected, &selected,
TAG_END);
SetListBrowserNodeAttrs(node,
LBNA_Selected, !selected,
TAG_END);
}

// get intuition window pointer
window = NULL;
GetAttr(WINDOW_Window, wnd, (uint32 *)&window); //

// read list and refresh
SetGadgetAttrs((struct Gadget *)lb, window, NULL,
LISTBROWSER_Labels, list,
TAG_END);
}
/*----------------------------------------------------------------------------*/
/* Select All */
/*----------------------------------------------------------------------------*/

void SelectAllBrowser(Object *wnd, Object *lb)
{
struct Window *window=NULL;
struct List *list=NULL;
struct Node *node=NULL;
uint32 selected;

// get list
GetAttr(LISTBROWSER_Labels, lb, (uint32 *)&list);

// remove list /// detach
SetAttrs(lb, LISTBROWSER_Labels, ~0, TAG_END);

// make changes
ListBrowserSelectAll(list);

// get intuition window pointer
window = NULL;
GetAttr(WINDOW_Window, wnd, (uint32 *)&window);

// read list and refresh
SetGadgetAttrs((struct Gadget *)lb, window, NULL,
LISTBROWSER_Labels, list,
TAG_END);
}

/*----------------------------------------------------------------------------*/
/* Select None */
/*----------------------------------------------------------------------------*/

void SelectNoneBrowser(Object *wnd, Object *lb)
{
struct Window *window=NULL;
struct List *list=NULL;
struct Node *node=NULL;
uint32 selected;

// get list
GetAttr(LISTBROWSER_Labels, lb, (uint32 *)&list);

// remove list /// detach
SetAttrs(lb, LISTBROWSER_Labels, ~0, TAG_END);

// make changeq
ListBrowserClearAll(list);

// get intuition window pointer
window = NULL;
GetAttr(WINDOW_Window, wnd, (uint32 *)&window); /// crash

// read list and refresh
SetGadgetAttrs((struct Gadget *)lb, window, NULL,
LISTBROWSER_Labels, list,
TAG_END);
}



char msg[MAX_LINE];

/*----------------------------------------------------------------------------*/
/* concatenate 3 strings */
/*----------------------------------------------------------------------------*/


STRPTR concat3strings( STRPTR string1 , STRPTR string2, STRPTR string3)
{
snprintf(msg, sizeof msg, "%s%s", &msg[0], string1);
snprintf(msg, sizeof msg, "%s\n%s", &msg[0], string2);
snprintf(msg, sizeof msg, "%s\n%s", &msg[0], string3);
return (&msg[0]);
}


/*----------------------------------------------------------------------------*/
/* display message box */
/*----------------------------------------------------------------------------*/

void log_displayBox (const char *title, int isError, const char *msg, struct Screen * scr )
{
Object *requester;
///requester = NewObject(RequesterClass, NULL, ///IIIntuition=> problems with opening libs
requester = NewObject(REQUESTER_GetClass(), NULL, ///IIIntuition=> ///IRequester->REQUESTER_GetClass()
REQ_TitleText, title,
REQ_BodyText, msg,
REQ_GadgetText, "_Ok",
REQ_Image, isError ? REQIMAGE_ERROR : REQIMAGE_INFO,
TAG_END);
if (requester != NULL) {
//IIntuition->IDoMethod(requester, RM_OPENREQ, NULL, NULL, NULL);
IDoMethod(requester, RM_OPENREQ, NULL, NULL, scr); ///IIIntuition=>
DisposeObject(requester); ///IIIntuition=>
}
}


/*----------------------------------------------------------------------------*/
/* make_listbrowser_clip */
/*----------------------------------------------------------------------------*/

struct List *make_listbrowser_clip (void) {
STRPTR clipstring;
uint32 clipsize;
struct List *list;
STRPTR line, state;
struct Node *node;
int i=0;
if (!ReadClipVector(&clipstring, &clipsize))
return NULL;
list = AllocSysObject(ASOT_LIST, NULL);
if (list == NULL) {
DisposeClipVector(clipstring);
return NULL;
}
line = my_strtok_r(clipstring, "\n", &state);
while (line != NULL)
{
Strlcpy((STRPTR)&lines,(CONST_STRPTR)line,MAX_LINE); ///IUtility-> ///passing argument 2 of 'IUtility->Strlcpy' from incompatible pointer type

node = AllocListBrowserNode(1,
LBNCA_CopyText, TRUE,
LBNCA_Text, line,
TAG_END);
if (node == NULL) {
DisposeClipVector(clipstring);
FreeListBrowserList(list);
FreeSysObject(ASOT_LIST, list);
return NULL;
}

AddTail(list, node);

line = my_strtok_r(NULL, "\n", &state);
++i;
}
totallines = i;
Printf("_clip totallines %ld\n",(LONG)totallines);
DisposeClipVector(clipstring);

if (IsListEmpty(list)) {
FreeSysObject(ASOT_LIST, list);
return NULL;
}

return list;
}

/*----------------------------------------------------------------------------*/
/* make_listbrowser_choices */
/*----------------------------------------------------------------------------*/

struct List *make_listbrowser_choices (char **args) /// called with (args.choices)
{
struct List *list=NULL;
if ((list = AllocVecTags (sizeof(struct List), AVT_ClearWithValue, 0, TAG_END)))
{
NewList (list);
while (*args) //crash
{
struct Node *node;
if (node = AllocListBrowserNode (1,LBNCA_Text,*args,TAG_END))
AddTail (list,node);
else
{
free_listbrowser_list (list);
return (NULL);
}
args++;
}
if (!(list->lh_Head->ln_Succ))
{
free_listbrowser_list (list);
return (NULL);
}
}
return (list);
}

/*----------------------------------------------------------------------------*/
/* make_listbrowser_file */
/*----------------------------------------------------------------------------*/

struct List *make_listbrowser_file (char *filepath) /// called with (input_file)
{
BPTR input_file = FOpen(filepath, MODE_OLDFILE,0); ///IDOS-> /// buffersize 0 ??
if(0 == input_file)
{
log_displayBox("ReqList", 0, concat3strings("Could not open file ",filepath ,"for reading"),NULL );
//Printf("Could not open file %s for reading\n", filepath); ///IDOS->
/// If the file cannot be opened for any reason, the value returned will be zero, and a secondary error code will be available by calling the routine IoErr().

PrintFault (IoErr(), "Error opening file");
return(NULL);
}

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

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

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

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

if ((node = AllocListBrowserNode ( ///IListBrowser->
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 )))
{
AddTail (list,node); ///IExec->
count++;
}
else
{
Printf("LBNode allocation failure\n"); ///IDOS->
SetIoErr(ERROR_NO_FREE_STORE); ///IDOS->
len = -1;
}
len = FReadLine(input_file, frld); ///IDOS->
}

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

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

return(list);
}


/*----------------------------------------------------------------------------*/
/* Request selected info & take action according to hit button */
/* returns as "result" the list of selected lines
//reponds to each action on LV, as well select as unselect
/*----------------------------------------------------------------------------*/

char *request_list (struct Screen *scr,const char *title,const char *body,struct List *list,BOOL multi,BOOL persist,BOOL notempty)

{
char *result = NULL; /// text of the line
int32 *line_nr;
Object *winobj;
struct Gadget *lbo;
struct Gadget *bdo;

///===============
struct ColumnInfo *ci = AllocLBColumnInfo(NUM_COLS, ///IListBrowser->
LBCIA_Column,COL_DEFAULT_SORT,
LBCIA_Title, "Click to toggle sort",
LBCIA_AutoSort, TRUE,
LBCIA_SortArrow, TRUE,
TAG_DONE);

///================

/// bdo = body ? ButtonObject,
bdo = body ? (struct Gadget *)ButtonObject,
///bdo = body ? (struct Gadget *)NewObject(NULL, "button.gadget",
GA_Text,body,
GA_ReadOnly,TRUE,
BUTTON_BevelStyle,BVS_NONE,
BUTTON_Transparent,TRUE,
EndObject : NULL; ///warning: assignment from incompatible pointer type


winobj = WindowObject,
WA_Title,title ? title : "Request",
WA_Flags,WFLG_CLOSEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_SIZEGADGET | WFLG_SIZEBBOTTOM | WFLG_ACTIVATE,
WA_PubScreen,scr,
WA_Width,scr->Width * 4 / 10,
WA_Height,scr->Height * 6 / 10,
WINDOW_Position,WPOS_CENTERSCREEN,
WINDOW_Layout,VGroupObject, /// no parent group ??
LAYOUT_SpaceOuter,TRUE,
bdo ? LAYOUT_AddChild : TAG_IGNORE,bdo,
CHILD_WeightMinimum,TRUE,
LAYOUT_AddChild,lbo = (struct Gadget *) ListBrowserObject,
GA_ID,GID_LIST,
GA_RelVerify,TRUE,
LISTBROWSER_ColumnInfo, ci, /// added
LISTBROWSER_ColumnTitles, TRUE, /// added
LISTBROWSER_TitleClickable, TRUE, /// added
LISTBROWSER_SortColumn, 0, /// added
LISTBROWSER_Labels,list, /// >>>>>>> attached here
LISTBROWSER_ShowSelected,TRUE,
LISTBROWSER_MultiSelect,multi,
LISTBROWSER_PersistSelect,persist,
EndObject, ///warning: assignment from incompatible pointer type
StartHGroup,
LAYOUT_EvenSize,TRUE, ///
LAYOUT_FixedVert,FALSE,
LAYOUT_AddChild,
Button("Ok",GID_OK), /// continue = FALSE
LAYOUT_AddChild,
Button("All",GID_ALL),
LAYOUT_AddChild,
Button("None",GID_NONE),
LAYOUT_AddChild,
Button("Inverse",GID_INVERSE),
LAYOUT_AddChild,
Button("Restore",GID_RESTORE),
LAYOUT_AddChild,
Button("Cancel",GID_CANCEL),
EndHGroup,
EndVGroup,
EndWindow;

if (winobj)
{
struct Window *win;
if (win = RA_OpenWindow (winobj)) //// >>macro >>>>>>>>>>>>>>>>>>>
{
BOOL cont = TRUE;
ULONG winsig;
struct Node *node = NULL;
GetAttr (WINDOW_SigMask,winobj,&winsig);
do /// while cont
{ /// loop
ULONG sigs = Wait (winsig | SIGBREAKF_CTRL_C); /// wait for a signal
if (sigs & SIGBREAKF_CTRL_C)
cont = FALSE;
if (sigs & winsig)
{
ULONG code;
while ((code = RA_HandleInput(winobj,NULL)) != WMHI_LASTMSG) ///
{
switch (code & WMHI_CLASSMASK)
{
case WMHI_GADGETUP:
switch (code & WMHI_GADGETMASK)
{
case GID_LIST:
GetAttr (LISTBROWSER_SelectedNode,(Object *)lbo,(uint32 *)&node); ///(ULONG *)&node); ///(uint32 *)
if (node)
{
ULONG sel = 0;
GetListBrowserNodeAttrs (node,LBNA_Selected,&sel,LBNCA_Text,&result,TAG_END);
if (multi && !sel)
result = NULL;
else if (!multi && !persist)
cont = FALSE; ///>>>>>
}
break;
case GID_OK:
if (result) /// at least 1 line selected
cont = FALSE; ///>>>>>
else if (notempty)
DisplayBeep (scr);
else
{
result = "";
cont = FALSE; ///>>>
}
break;
case GID_INVERSE:
InvertListBrowser(winobj,(Object *) lbo); /// warning: passing argument 2 of 'InvertListBrowser' from incompatible pointer type
break;
case GID_NONE:
SelectNoneBrowser(winobj,(Object *) lbo);
break;
case GID_ALL:
SelectAllBrowser(winobj,(Object *) lbo);
break;
case GID_RESTORE:
RestoreListBrowser(winobj,(Object *) lbo);
break;
case GID_CANCEL:
cont = FALSE;
break;
}
break;
case WMHI_CLOSEWINDOW:
cont = FALSE;
break;
}
}
} //CLASSMASK
} ///while
while (cont);
} /// do
else
Printf ("cannot open window\n");

DisposeObject (winobj);
}
else
Printf ("cannot create objects\n");
return (result);
}



/*----------------------------------------------------------------------------*/
/* Hauptprogramm

If I_FILE is used choices will be disregarded, unless
- no file is given ??
- or the given file does not exist, ??
- is not a text file or ??
- is too large ??

If choices not used, & I_FILE switch not set, a secundary file requester will ask for the input file ??

I_FILE can be clips:0, then content of clipboard is used
If only text: if not => ??
// IF CLIP is set, the output will be directed tot the clipboard
If O_File is given the outputt will be directed to the given output file
Output file can be clips:0 (Textclip.library only sufficiênt for single line output (not multi)

>if (!(args.choices))
if (!(args.i_file))
ReqFile
LoadFile
else
LoadFile
endif
makelist_fromfile
else // choices
makelist_fromchoices
endif >>>> */

/*----------------------------------------------------------------------------*/

int main (void)
{
int rc = RETURN_FAIL;
struct RDArgs *rdargs;
struct
{
char *title;
char *body;
char *i_file;
char **choices;
long multi;
long persist;
long notempty;
long clip;
char *o_file;
char *pubscreen;
} args = {0};
struct List *list;
BPTR output_file=ZERO;///NULL; ///FILE *output_file=NULL; FILE ANSI
//FILE *input_file=NULL;
char *Selected[TOTAL_LINES]; /// not used
char buf[MAX_LINE];
char *str[TOTAL_LINES];
char clip[MAX_CLIP]= {""}; ///crash
int i =0;
if (!open_classes())
{
Printf ("cannot load required classes\n");
close_classes();
return (RETURN_FAIL);
}
rdargs = ReadArgs ("TITLE/K,BODY/K,I_FILE/K,CHOICES/A/M,MULTI/S,PERSIST/S,NOTEMPTY/S,PUBSCREEN/K,O_FILE/K",(LONG *)&args,NULL);

if (!rdargs)
{
PrintFault (IoErr(),NULL);
close_classes();
return (RETURN_ERROR);
}


if (args.o_file)
{ //> check ifexists warn, & delete if ok to overwrite
Printf("main args.o_file %s\n", args.o_file);
if (strcmp(makeupper(args.o_file),"CLIPS:0")== 0)
{ //No output file to open startup writing to clips ///No

}
else
{
output_file = Open((CONST_STRPTR)args.o_file, MODE_NEWFILE ); ///warning: assignment makes pointer from integer without a cast

if (!output_file)
{
log_displayBox("ReqList", 0, concat3strings("File ", args.o_file ,"cannot be opened"),NULL ); // screen not declared
//ReqFile
}
}
}
if(!args.i_file) ///
{
list = make_listbrowser_choices (args.choices); //>>>>>>>>>>>>>>>>>>>>1st internal call
}
else
{
if (strcmp(makeupper(args.i_file),"CLIPS:0")== 0)
{
list = make_listbrowser_clip();
/// list = make_listbrowser_file (args.i_file);
}
else
{
list = make_listbrowser_file (args.i_file);
}
} // args.i
if (list)
{
struct Screen *scr;
if (scr = LockPubScreen (args.pubscreen))
{
char *result;
if (result = request_list (scr,args.title,args.body,list,args.multi,args.persist,args.notempty)) /// internal call 2
{
if (args.multi) //selection of a nr of lines
{
struct Node *node,*next;
for (node = list->lh_Head; next = node->ln_Succ; node = next) /// loop
{
char *text = NULL;
ULONG sel = 0;
BOOL inverse = FALSE;
GetListBrowserNodeAttrs (node, /// verifcation if line is selected
LBNA_Selected,&sel,
LBNCA_Text,&text,
TAG_END);
if (sel && text) /// if line is selected
{
if (args.o_file)
{
if (strcmp(makeupper(args.o_file),"CLIPS:0")== 0) /// crash there is no args.o_file
{ ++i;
////add2clipboard(text,strlen(text) ;
if (i > 1)
snprintf(clip, sizeof clip, "%s\n%s", &clip[0], text);
else
snprintf(clip, sizeof clip, "%s%s", &clip[0], text);
}
else if (output_file)
FPrintf(output_file,"%s\n", text);
else ///if (!output_file) /// not opened if output is clips:0
Printf("%s\n",text); /// seen 1 for each selected line
}
else
Printf("%s\n",text);

}
} //node
WriteClipVector(&clip[0], strlen(&clip[0])); ///->ITextClip a global write of all the lines
} //args.multi
else /// only one line selected
{
if (args.o_file)
{
if (strcmp(makeupper(args.o_file),"CLIPS:0")== 0) /// crash there is no args.o_file
WriteClipVector(result, strlen(result)); ///->ITextClip
else if (output_file)
FPrintf(output_file,"%s\n", result);
else ///if (!output_file) /// not opened if output is clips:0
Printf("%s\n",result); /// seen 1 for each selected line
}
else
Printf("%s\n",result);
}
rc = RETURN_OK;
} //result
else
rc = RETURN_WARN;
UnlockPubScreen (NULL,scr);
} //scr
free_listbrowser_list (list);
} //list
else
{
}
// if (output_file) fclose (output_file);
FreeArgs (rdargs);
close_classes();
return (rc);
}//main

/*----------------------------------------------------------------------------*/
/* Ende des Quelltextes */
/*----------------------------------------------------------------------------*/



Re: Listbrowser with autosort; restore original content

Posted: Wed Jan 07, 2015 9:35 am
by JosDuchIt
@LyleHaze
If each node had LBNA_UserData set to something like.. a number that is incremented with each new entry..
then restoring the list to original order would be as easy as sorting on that field.
I did only read this suggestion now. Quite simple indeed
Would this additional number show up in the listview ? i guess, if so , can it be hidden?
Can sorting on some column be initiated elsewhere than from column title?

Re: Listbrowser with autosort; restore original content

Posted: Wed Jan 07, 2015 12:10 pm
by trixie
@JosDuchIt

LBNA_UserData is never shown in the listview.

Re: Listbrowser with autosort; restore original content

Posted: Wed Jan 07, 2015 5:43 pm
by LyleHaze
JosDuchIt wrote:@LyleHaze
If each node had LBNA_UserData set to something like.. a number that is incremented with each new entry..
then restoring the list to original order would be as easy as sorting on that field.
I did only read this suggestion now. Quite simple indeed
Would this additional number show up in the listview ? i guess, if so , can it be hidden?
Can sorting on some column be initiated elsewhere than from column title?
From the IListBrowser->SetListBrowserNodeAttrs() autodoc, LBNA_UserData:
" LBNA_UserData (APTR)
Arbitrary user data for this node. This field will be made
available in the LBSortMsg.lbsm_UserDataA or B fields when
using the LBM_SORT method.
"
Note that it is an APTR.
You could cast it as a uint32 and use it as a simple number, If you needed to carry
more data (or more complex data) you could define a small structure with all
you need, and allocate one for every ListBrowser node, using this as a pointer to
that additional structure.