Page 1 of 2

Listbrowser with autosort; restore original content

Posted: Mon Jan 05, 2015 9:04 pm
by JosDuchIt
My reqlist (requeslist = a requester proposing to chose a selection of lines from a listbrowser) program is progressing nicely, with appreciated help from this forum.
Input may be
- a sequence of choices in the command line
- a file
- the clipboard

output may be
- the selected lines printed to stdout
- a file
- the clipboard.

Before you validate your selection, you can manipulate the list
- select all/none/inverse the selection
- sort the lines

What i am after now is restoring the original content after a sort.
The content is saved in the global array
char lines[TOTAL_LINES] [MAX_LINE]

(Right now only generated within the make_listbrowser_clip function)

More from copy/paste guesswork than understanding i came up with
void RestoreListBrowser(Object *wnd, Object *lb)
{
struct Window *window;
struct List *list;
struct Node *node;
int i = 0;
Printf("restore totallines %ld\n",(LONG)totallines);
GetAttr(LISTBROWSER_Labels, lb, (uint32 *)&list);
SetAttrs(lb, LISTBROWSER_Labels, ~0, TAG_END);
list = AllocSysObject(ASOT_LIST, NULL);
if (list == NULL)
{
return NULL;
}
while (lines != NULL)
{
node = AllocListBrowserNode(1, // crash
LBNCA_CopyText, TRUE,
LBNCA_Text, lines,
TAG_END);
if (node == NULL) {
FreeListBrowserList(list);
FreeSysObject(ASOT_LIST, list);
return NULL;
}

AddTail(list, node);
++i;
}

// 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);
}


Of course it crashes.

What would a sound approach look like?

Full source is here
/* Programmname ReqList */
#define __USE_INLINE__

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

/*----------------------------------------------------------------------------*/
/* 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 -lauto -gstabs -N -o ram: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__
#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 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 CLOSELIB(base) if (base##Base) CloseLibrary (base##Base)
#endif


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

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

BASEDEF(Window);
BASEDEF(Layout);
BASEDEF(Button);
BASEDEF(ListBrowser);
///BASEDEF(Requester);
/// struct ClassLibrary *RequesterBase; /// opened elsewher
Class *RequesterClass;


/*----------------------------------------------------------------------------*/
/* ReAction-Klassen öffnen */
/*----------------------------------------------------------------------------*/

BOOL open_classes (void)
{
BOOL ok = TRUE;

OPENLIB(Window,"window.class");
OPENLIB(Layout,"gadgets/layout.gadget");
OPENLIB(Button,"gadgets/button.gadget");
OPENLIB(ListBrowser,"gadgets/listbrowser.gadget");
//OPENLIB(Requester,"requester.class");
RequesterBase = OpenClass("requester.class", 53, &RequesterClass); ///IIIntuition=>
if (RequesterBase = NULL)
ok = FALSE;
return (ok);
}

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

void close_classes (void)
{
CLOSELIB(Window);
CLOSELIB(Layout);
CLOSELIB(Button);
CLOSELIB(ListBrowser);
///CLOSELIB(Requester);
if(RequesterBase) CloseClass(RequesterBase);
}

/*----------------------------------------------------------------------------*/
/* 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 */
/*----------------------------------------------------------------------------*/

void RestoreListBrowser(Object *wnd, Object *lb)
{
struct Window *window;
struct List *list;
struct Node *node;
int i = 0;
Printf("restore totallines %ld\n",(LONG)totallines);
GetAttr(LISTBROWSER_Labels, lb, (uint32 *)&list);
SetAttrs(lb, LISTBROWSER_Labels, ~0, TAG_END);
list = AllocSysObject(ASOT_LIST, NULL);
if (list == NULL)
{
return NULL;
}
while (lines != NULL)
{
node = AllocListBrowserNode(1, // crash
LBNCA_CopyText, TRUE,
LBNCA_Text, lines,
TAG_END);
if (node == NULL) {
FreeListBrowserList(list);
FreeSysObject(ASOT_LIST, list);
return NULL;
}

AddTail(list, node);
++i;
}

// 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);
}

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

void InvertListBrowser(Object *wnd, Object *lb)
{
struct Window *window;
struct List *list;
struct Node *node;
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); /// crash

// 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;
struct List *list;
struct Node *node;
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); /// crash

// 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;
struct List *list;
struct Node *node;
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];
STRPTR concat3strings( STRPTR string1 , STRPTR string2, STRPTR string3)
{
///msg[MAX_LINE]=
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);
//printf("%s\n",&clip[0]);
return (&msg[0]);
}



void log_displayBox (const char *title, int isError, const char *msg, struct Screen * scr )
{
Object *requester;
requester = NewObject(RequesterClass, NULL, ///IIIntuition=>
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);
///lines = line;

while (line != NULL)
{
Strlcpy(&lines,line,MAX_LINE); ///IUtility->
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("makecliplist %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->
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->
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,
GA_Text,body,
GA_ReadOnly,TRUE,
BUTTON_BevelStyle,BVS_NONE,
BUTTON_Transparent,TRUE,
EndObject : NULL;

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 = 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,
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,lbo,(ULONG *)&node);
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, lbo);
break;
case GID_NONE:
SelectNoneBrowser(winobj, lbo);
break;
case GID_ALL:
SelectAllBrowser(winobj, lbo);
break;
case GID_RESTORE:
RestoreListBrowser(winobj, 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;
FILE *output_file=NULL;
//FILE *input_file=NULL;
char *Selected[TOTAL_LINES]; /// not used
char buf[MAX_LINE];
//char *str[TOTAL_LINES]; /// all the lines not used
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(args.o_file, MODE_NEWFILE );
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: Tue Jan 06, 2015 12:21 am
by tonyw
What do you mean by "it crashes"? Where does it crash? At which line?

The stack dump will tell you. Save it somewhere and post it here (just the stack dump, not all the system and library stuff).

We'll show you how to interpret it.

Re: Listbrowser with autosort; restore original content

Posted: Tue Jan 06, 2015 3:35 am
by xenic
@tonyw
Maybe it crashed at the line with the comment "//crash" :-)

Re: Listbrowser with autosort; restore original content

Posted: Tue Jan 06, 2015 6:09 am
by LyleHaze
I loaded the code to compile..
there are LOTS of warnings to be cleaned up. IT's a good idea to try and correct compiler warnings, as they are often pointing out possible mistakes...

Here's an example:

if (RequesterBase = NULL)
ok = FALSE;

The above brings the following warning:
warning: suggest parentheses around assignment used as truth value

If you assume that warnings can safely be ignored, you might miss the real issue. RequesterBase will ALWAYS be NULL after this has executed. Even if it had been opened sucessfully, this will NULL the pointer.

Now if you change the above to look like
if (RequesterBase == NULL)
ok = FALSE;

Now you are testing the value against NULL instead of asigning NULL to RequesterBase.

This is a common problem, you are not the first one to assign NULL instead of testing for it.
I have leaned that whenever I am comparing a variable to a constant, I always put the constant
first. That way if I make this mistake, I get an error instead of a warning.

So,
if(RequesterBase == NULL)
will work, and
if(NULL == RequesterBase)
will also work, but will make this particular mistake much harder to commit.


On to your code..

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

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.


Have Fun!

Re: Listbrowser with autosort; restore original content

Posted: Tue Jan 06, 2015 9:50 am
by OldFart
@LyleHazel
...whenever I am comparing a variable to a constant, I always put the constant
first. That way if I make this mistake, I get an error instead of a warning.
When "Green is Grass", remember? Makes a hell of a lot more sense to me now... ;)

OldFart

Re: Listbrowser with autosort; restore original content

Posted: Tue Jan 06, 2015 10:03 am
by trixie
@JosDuchIt
void RestoreListBrowser(Object *wnd, Object *lb)
{
struct Window *window;
struct List *list;
struct Node *node;
Also make a point of ALWAYS initializing your automatic variables inside your functions. Don't just assume that the function code uses assigment to give your variable(s) a proper value: you may modify your code later, potentially leaving your variable(s) unitialized. Be consistent, it may save you a lot of trouble:
void RestoreListBrowser(Object *wnd, Object *lb)
{
struct Window *window = NULL;
struct List *list = NULL;
struct Node *node = NULL;

Re: Listbrowser with autosort; restore original content

Posted: Tue Jan 06, 2015 1:56 pm
by JosDuchIt
@LyleHaze
took your advice & clened up the warnings: 2 left though. How can i get rid of these
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,
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 = 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;

Re: Listbrowser with autosort; restore original content

Posted: Tue Jan 06, 2015 4:37 pm
by xenic
@JosDuchIt

Try making these changes:

bdo = body ? (struct Gadget *)ButtonObject,

LAYOUT_AddChild,lbo = (struct Gadget *)ListBrowserObject,

Re: Listbrowser with autosort; restore original content

Posted: Tue Jan 06, 2015 5:19 pm
by xenic
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.

Re: Listbrowser with autosort; restore original content

Posted: Tue Jan 06, 2015 5:20 pm
by LyleHaze
JosDuchIt wrote:@LyleHaze
took your advice & clened up the warnings: 2 left though. How can i get rid of these

bdo = body ? ButtonObject,
GA_Text,body,
GA_ReadOnly,TRUE,
BUTTON_BevelStyle,BVS_NONE,
BUTTON_Transparent,TRUE,
EndObject : NULL; ///warning: assignment from incompatible pointer type

It took me a minute to see what was missing.. then I realized it.
It can be hard to see what you are really doing while using the reaction macros.
They were meant to make things easier, but they can also hide things that
you might not want hidden.

I read a really great tutorial on coding for Reaction here:
http://www.os4coding.net/blog/trixie/re ... rogramming

Once I stopped using the macros it was a bit easier to see what was really happening, and before
long reaction started making better sense that it had before.

Have Fun!