I take no responsibility for this source. It's freeware, do whatever you like with it.

#include <exec/types.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
#include <intuition/gadgetclass.h>
#include <utility/tagitem.h>
#include <libraries/gadtools.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <clib/exec_protos.h>
#include <clib/graphics_protos.h>
#include <clib/intuition_protos.h>
#include <clib/gadtools_protos.h>
#define LISTLEFT Secwin[0]
#define LISTTOP Secwin[1]
#define LISTWIDTH Secwin[2]
#define LISTHEIGHT Secwin[3]
#define MAXROW 20
#define GADHEIGHT 20
SHORT Secwin[4] = {0,139,446,88}; /* List-windows position */
BOOL flag;
struct Month
{
struct Node nd;
UBYTE txt[MAXROW];
};
void NewList(struct List *);
void bail_out(int code, STRPTR error),CreateAllGadgets(WORD,WORD);
ULONG SortList( struct List * );
int NodeNameCompare( struct Node **, struct Node ** );
int NodeNameCompare2( struct Node **, struct Node ** );
STRPTR MonthLabels[] =
{
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December",
NULL,
};
struct List listpek;
struct Screen *mysc;
struct Remember *RKey;
struct Gadget *glist;
struct Window *mywin;
void *vi;
BOOL terminated;
struct Gadget *lvgad,*gad;
WORD x,y;
void main(void)
{
struct IntuiMessage *imsg;
struct Gadget *gad;
ULONG imsgClass;
UWORD imsgCode;
terminated = FALSE;
if(!(mysc = LockPubScreen(NULL)))
bail_out(20, "Couldn't lock default public screen");
if(!(vi = GetVisualInfo(mysc,TAG_DONE)))
bail_out(20, "GetVisualInfo() failed");
if(!(mywin = (struct Window *)OpenWindowTags(NULL,
WA_Left,LISTLEFT,WA_Top,LISTTOP,WA_InnerWidth,LISTWIDTH,WA_InnerHeight,LISTHEIGHT,
WA_IDCMP,LISTVIEWIDCMP | IDCMP_CLOSEWINDOW | IDCMP_NEWSIZE,
WA_Flags,WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET,
WA_PubScreen,NULL,TAG_DONE)))
bail_out(20, "OpenWindow() failed");
CreateAllGadgets(LISTWIDTH,LISTHEIGHT);
while(!terminated)
{
Wait(1 << mywin->UserPort->mp_SigBit);
while((!terminated) && (imsg = GT_GetIMsg(mywin->UserPort)))
{
imsgClass = imsg->Class;
imsgCode = imsg->Code;
gad = (struct Gadget *)imsg->IAddress;
GT_ReplyIMsg(imsg);
switch (imsgClass)
{
case GADGETUP:
if(gad->GadgetID == 1)
{
flag ^= 1; /* switch between 0 and 1 */
GT_SetGadgetAttrs(lvgad,mywin,NULL,GTLV_Labels, ~0, TAG_DONE);
SortList(&listpek);
GT_SetGadgetAttrs(lvgad,mywin,NULL,GTLV_Labels, &listpek, TAG_DONE);
}
else
{
printf("GADGETUP. ");
printf("ListView: clicked on '%s'\n", MonthLabels[imsgCode]);
}
break;
case NEWSIZE:
RemoveGList(mywin,glist, -1);
FreeGadgets(glist);
x = mywin->Width - mywin->BorderLeft - mywin->BorderRight;
y = mywin->Height - mywin->BorderTop - mywin->BorderBottom;
Move(mywin->RPort,0,0);
ClearScreen(mywin->RPort);
CreateAllGadgets(x,y);
break;
case CLOSEWINDOW:
terminated = TRUE;
break;
case IDCMP_REFRESHWINDOW:
GT_BeginRefresh(mywin);
GT_EndRefresh(mywin,TRUE);
}
}
}
bail_out(0, NULL);
}
void bail_out(int code, STRPTR error)
{
if (mywin)
CloseWindow(mywin);
if(vi)
FreeVisualInfo(vi);
if(glist)
FreeGadgets(glist);
if (mysc)
UnlockPubScreen(NULL, mysc);
if (RKey)
FreeRemember(&RKey, TRUE);
if (error)
printf("Error: %s\n", error);
exit(code);
}
void CreateAllGadgets(WORD x, WORD y)
{
struct NewGadget ng;
WORD index;
struct Month *node;
gad = CreateContext(&glist);
if(!RKey)
{
NewList(&listpek);
index = 0;
while (MonthLabels[index])
{
node = (struct Month *)AllocRemember(&RKey, sizeof(struct Month), MEMF_CLEAR);
sprintf(node->txt,"%s",MonthLabels[index++]);
node->nd.ln_Name = (UBYTE *)node->txt;
AddTail(&listpek, &node->nd);
}
}
ng.ng_LeftEdge = mywin->BorderLeft;
ng.ng_TopEdge = mywin->BorderTop;
ng.ng_Height = GADHEIGHT;
ng.ng_Width = x;
ng.ng_VisualInfo = vi;
ng.ng_GadgetText = "Sort";
ng.ng_TextAttr = NULL;
ng.ng_GadgetID = 1;
ng.ng_Flags = 0;
lvgad = gad = CreateGadget(BUTTON_KIND, gad, &ng, GTLV_Labels, &listpek, TAG_DONE);
ng.ng_Height = y - GADHEIGHT;
ng.ng_TopEdge = mywin->BorderTop + GADHEIGHT;
ng.ng_GadgetID = 2;
lvgad = CreateGadget(LISTVIEW_KIND, gad, &ng, GTLV_Labels, &listpek, TAG_DONE);
AddGList(mywin,glist,-1, -1, NULL);
RefreshWindowFrame(mywin);
RefreshGList(glist, mywin, NULL, -1);
GT_RefreshWindow(mywin, NULL);
}
/* The Function that is sent to qsort(). compare 2 strings*/
int NodeNameCompare(struct Node **node1, struct Node **node2 )
{
return( strcmp( ( *node1 )->ln_Name, ( *node2 )->ln_Name ) );
}
int NodeNameCompare2(struct Node **node1, struct Node **node2 )
{
return( strcmp( ( *node2 )->ln_Name, ( *node1 )->ln_Name ) );
}
/* Sort a linked list in the ln_Name field.
* Returns:
* 0 = All ok.
* 1 = No mem
*/
ULONG SortList( struct List *list )
{
struct Node *node;
LONG nodecount = 0;
struct Node **buf;
/* Count nodes */
for( node = list->lh_Head; node->ln_Succ; node = node->ln_Succ )
nodecount++;
/* Allocates 1 memblock for pointer to sort*/
if( buf = ( struct Node ** ) AllocVec( nodecount * 4, 0 ) )
{
/* 2 identical Nodes buf,work */
struct Node **work = buf;
/* Copy the pointers */
for( node = list->lh_Head; node->ln_Succ; node = node->ln_Succ )
*work++ = node;
if(flag)
qsort( buf, nodecount, 4, NodeNameCompare );
else
qsort( buf, nodecount, 4, NodeNameCompare2 );
NewList( list );
/* Put the names back in the Struct List * */
for( work = buf; nodecount--; )
AddTail( list, *work++ );
FreeVec( buf );
return( 0 );
}
else
return( 1 );
}