/*
***************************************************************************
*
* Datei:
*    RSysSearch.c
*
* Inhalt:
*
*      --- Globale Routinen ---
*
*    void RSysFindNext ( void );
*    void RSysFindPrev ( void );
*    void RSysSearch ( void );
*
*      --- Lokale  Routinen ---
*
*    static int HandleSearchStrIDCMP ( void );
*    static int OpenSearchStrWindow ( void );
*    static int SearchCancelGadClicked ( void );
*    static int SearchOkGadClicked ( void );
*    static int SearchSGadClicked ( void );
*    static int SearchStrCloseWindow ( void );
*    static int SearchStrVanillaKey ( void );
*    static void EnterSearchString ( void );
*    static void InfoMsg ( char *fmt );
*    static void StrFound ( struct Node *node );
*    static void StrNotFound ( int num );
*
* Bemerkungen:
*    Enthält die Routinen zum Suchen nach einem Teilstring
*    in der Liste des Hauptfensters.
*
* Erstellungsdatum:
*    25-Sep-93    Rolf Böhme
*
* Änderungen:
*    25-Sep-93    Rolf Böhme    Erstellung
*
***************************************************************************
*/

#include "RSys.h"

extern int SearchSGadClicked( void );
extern int SearchOkGadClicked( void );
extern int SearchCancelGadClicked( void );

extern int HandleSearchStrIDCMP( void );
extern int SearchStrCloseWindow();
extern int SearchStrVanillaKey();
extern int OpenSearchStrWindow( void );
extern void CloseSearchStrWindow( void );
extern void EnterSearchString(void);

struct Node *actualfindnode;
long actualfindnodenum = 0;
static char searchstr[BUFSIZE];
static startsearch = FALSE;

static struct Window         *SearchStrWnd = NULL;
static struct Gadget         *SearchStrGList = NULL;
struct IntuiMessage    SearchStrMsg;
static struct Gadget         *SearchStrGadgets[SearchStr_CNT];
static UWORD                  SearchStrLeft = 81;
static UWORD                  SearchStrTop = 66;
static UWORD                  SearchStrWidth = 259;
static UWORD                  SearchStrHeight = 57;
static UBYTE                 *SearchStrWdt = (UBYTE *)NAME " - Search string";

static UWORD SearchStrGTypes[] = {
	STRING_KIND,
	BUTTON_KIND,
	BUTTON_KIND
};

static struct NewGadget SearchStrNGad[] = {
	22, 15, 208, 13, (UBYTE *)"Search String", NULL, GD_SearchSGad, PLACETEXT_ABOVE, NULL, (APTR)SearchSGadClicked,
	22, 34, 91, 13, (UBYTE *)"_Search", NULL, GD_SearchOkGad, PLACETEXT_IN, NULL, (APTR)SearchOkGadClicked,
	139, 34, 91, 13, (UBYTE *)"Cancel", NULL, GD_SearchCancelGad, PLACETEXT_IN, NULL, (APTR)SearchCancelGadClicked
};

static ULONG *SearchStrGTags[] = {
	(ULONG *)(GTST_MaxChars), (ULONG *)40, (ULONG *)(TAG_DONE),
	(ULONG *)(GT_Underscore), (ULONG *)'_', (ULONG *)(TAG_DONE),
	(ULONG *)(TAG_DONE)
};

static int SearchSGadClicked( void )
{
   char *gadtext;

	/* routine when gadget "Search String" is clicked. */
   gadtext = gadgetbuff(SearchStrGadgets[GD_SearchSGad - GD_SearchSGad]);

   if(strlen(gadtext) != 0)
   {
      strncpy(searchstr, gadtext, BUFSIZE);
      startsearch = TRUE;

      return TRUE;
   }

   searchstr[0] = STRINGEND;

   startsearch = FALSE;

   return TRUE;
}

static int SearchOkGadClicked( void )
{
	/* routine when gadget "_Search" is clicked. */
   startsearch = TRUE;

   return FALSE;
}

static int SearchCancelGadClicked( void )
{
	/* routine when gadget "Cancel" is clicked. */
   startsearch = FALSE;

   return FALSE;
}

static int SearchStrCloseWindow( void )
{
	/* routine for "IDCMP_CLOSEWINDOW". */
   startsearch = FALSE;

   return FALSE;
}

static int SearchStrVanillaKey( void )
{
	/* routine for "IDCMP_VANILLAKEY". */

   if(SearchStrMsg.Code == ESC)
   {
      startsearch = FALSE;

      return FALSE;
   }

   if(ToUpper((ULONG)SearchStrMsg.Code) == (UBYTE)'S')
   {
      startsearch = TRUE;

      return FALSE;
   }

   return TRUE;
}

static int HandleSearchStrIDCMP( void )
{
	struct IntuiMessage	*m;
	int			(*func)(void);
	BOOL			running = TRUE;

	while( m = GT_GetIMsg( SearchStrWnd->UserPort ))
   {
		CopyMem(( char * )m, ( char * )&SearchStrMsg, (long)sizeof( struct IntuiMessage ));

		GT_ReplyIMsg( m );

		switch ( SearchStrMsg.Class )
      {
			case	IDCMP_REFRESHWINDOW:
            MakeWindowRefresh(SearchStrWnd);
				break;

			case	IDCMP_CLOSEWINDOW:
				running = SearchStrCloseWindow();
				break;

			case	IDCMP_VANILLAKEY:
				running = SearchStrVanillaKey();
				break;

			case	IDCMP_GADGETUP:
            HandleHelp((( struct Gadget * )SearchStrMsg.IAddress)->GadgetID);

				func = ( void * )(( struct Gadget * )SearchStrMsg.IAddress )->UserData;
				running = func();
				break;
		}
	}

	return( running );
}

static int OpenSearchStrWindow( void )
{
	struct NewGadget	ng;
	struct Gadget	*g;
	UWORD		lc, tc;
   UWORD wleft = SearchStrLeft,
         wtop = SearchStrTop,
         ww,
         wh;
   int   gl[]={GD_SearchSGad - GD_SearchSGad};

   AdjustWindowDimensions(Scr, SearchStrLeft, SearchStrTop,
                          SearchStrWidth, SearchStrHeight,
                          &wleft, &wtop, &ww, &wh);

	if ( ! ( g = CreateContext( &SearchStrGList ))) return 1L;

	for( lc = 0, tc = 0; lc < SearchStr_CNT; lc++ )
   {

		CopyMem((char * )&SearchStrNGad[ lc ], (char * )&ng, (long)sizeof( struct NewGadget ));

		ng.ng_VisualInfo = VisualInfo;
		ng.ng_TextAttr   = Font;
      ng.ng_LeftEdge = OffX + ComputeX(ng.ng_LeftEdge);
      ng.ng_TopEdge = OffY + ComputeY(ng.ng_TopEdge);
      ng.ng_Width = ComputeX(ng.ng_Width);
      ng.ng_Height = ComputeY(ng.ng_Height);

		SearchStrGadgets[ lc ] = g = CreateGadgetA((ULONG)SearchStrGTypes[ lc ], g, &ng, ( struct TagItem * )&SearchStrGTags[ tc ] );

		while( SearchStrGTags[ tc ] ) tc += 2;
		tc++;

		if ( NOT g ) return 2L;
	}

	if ( ! ( SearchStrWnd = OpenWindowTags( NULL,
            WA_Left, wleft,
            WA_Top, wtop,
            WA_Width, ww,
            WA_Height, wh,
				WA_IDCMP,	STRINGIDCMP|BUTTONIDCMP|IDCMP_CLOSEWINDOW|IDCMP_VANILLAKEY|IDCMP_REFRESHWINDOW,
				WA_Flags,	WFLG_DRAGBAR|WFLG_DEPTHGADGET|WFLG_CLOSEGADGET|WFLG_SMART_REFRESH|WFLG_ACTIVATE|WFLG_RMBTRAP,
				WA_Title,	SearchStrWdt,
            WA_PubScreenFallBack, TRUE,
            WA_PubScreen, Scr,
				TAG_DONE )))
	return 4L;

   RefreshRastPort(SearchStrWnd, SearchStrGadgets, gl, 1, FALSE, SearchStrGList);

	return NULL;
}

static void
InfoMsg(char *fmt)
{
   char msg[BUFSIZE];

   sprintf(msg, fmt, searchstr);
   PrintInfo(msg, SPEAK, 30);

   return;
}

static void
StrNotFound(int num)
{
   actualfindnode = GetNode(&ListeLVList, (ULONG)num);
   actualfindnodenum = num;

   topentry = actualfindnodenum;
   SetMainLVTop(actualfindnodenum);

   InfoMsg("\"%s\" not found...");

   PrintStatistics();

   return;
}

static void
StrFound(struct Node *node)
{
   actualfindnode = node;

   topentry = actualfindnodenum;
   SetMainLVTop(topentry);

   InfoMsg("\"%s\" found...");

   PrintStatistics();

   return;
}

void
RSysFindNext(void)
{
   struct Node *node;
   int lastnum = actualfindnodenum;

   HandleHelp(MN_FindNext);

   if(actualfindnodenum >= (countentries - newlvh)) return;

   if(strlen(searchstr) == 0)
   {
      EnterSearchString();

      if(!startsearch) return;
   }

   InfoMsg("Find next \"%s\"...");

   for(node = actualfindnode->ln_Succ, actualfindnodenum++;
       node->ln_Succ; node = node->ln_Succ, actualfindnodenum++)
      if(strstr(node->ln_Name, searchstr))
      {
         StrFound(node);

         return;
      }

   StrNotFound(lastnum);

   return;
}

void
RSysFindPrev(void)
{
   struct Node *node;
   int lastnum = actualfindnodenum;

   HandleHelp(MN_FindPrev);

   if(actualfindnodenum <= 0) return;

   if(strlen(searchstr) == 0)
   {
      EnterSearchString();

      if(!startsearch) return;
   }

   InfoMsg("Find prev: \"%s\"...");

   actualfindnodenum--;

   for(node = actualfindnode->ln_Pred; node->ln_Pred; node = node->ln_Pred, actualfindnodenum--)
      if(strstr(node->ln_Name, searchstr))
      {
         StrFound(node);
         return;
      }

   StrNotFound(lastnum);

   return;
}

static void
EnterSearchString(void)
{
   PrintInfo("Search string...", SPEAK, 0);

   if (OpenASysWindow(OpenSearchStrWindow, NO_KILL))
   {
      LockMainWindow(LOCK);

   	GT_SetGadgetAttrs(SearchStrGadgets[GD_SearchSGad - GD_SearchSGad], SearchStrWnd,
	   						NULL,
		   					GTST_String, (UBYTE *) searchstr,
			   				TAG_DONE);

      ActivateGadget(SearchStrGadgets[GD_SearchSGad - GD_SearchSGad], SearchStrWnd, NULL);

      while (HandleSearchStrIDCMP()) ;

      CloseASysWindow(&SearchStrWnd, &SearchStrGList, NULL);

      LockMainWindow(UNLOCK);
   }

   return;
}

void
RSysSearch(void)
{
   HandleHelp(MN_Search);

   EnterSearchString();

   if(startsearch && strlen(searchstr) == 0L) startsearch = FALSE;

   if(startsearch)
   {
      startsearch = FALSE;
      actualfindnode = ListeLVList.lh_Head;
      actualfindnodenum = 0;

      RSysFindNext();
   }

   PrintStatistics();

   return;
}
