/*
   ***************************************************************************
   *
   * 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 ( 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"
#include "protos.h"

static int SearchSGadClicked (void);
static int SearchOkGadClicked (void);
static int SearchCancelGadClicked (void);
static int HandleSearchStrIDCMP (void);
static int SearchStrCloseWindow ();
static int SearchStrVanillaKey ();
static int OpenSearchStrWindow (void);
static void EnterSearchString (void);


static char searchstr[BUFSIZE];
static startsearch = FALSE;

static WINDOW *SearchStrWnd = NULL;
static GADGET *SearchStrGList = NULL;
INTUIMESSAGE SearchStrMsg;
static 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 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)
{
  INTUIMESSAGE *m;
  int (*func) (void);
  BOOL running = TRUE;

  while (m = GT_GetIMsg (SearchStrWnd->UserPort))
    {
      CopyMem ((char *) m, (char *) &SearchStrMsg,
	       (long) sizeof (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 ((enum RSysNumber)
		      ((GADGET *) SearchStrMsg.IAddress)->GadgetID);

	  func = (int (*)()) ((GADGET *) SearchStrMsg.IAddress)->UserData;
	  running = func ();
	  break;
	}
    }

  return (running);
}

static int
OpenSearchStrWindow (void)
{
  NEWGADGET ng;
  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 (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, (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 (NODE * node)
{
  actualfindnode = node;

  topentry = actualfindnodenum;
  SetMainLVTop (topentry);

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

  PrintStatistics ();

  return;
}

void
RSysFindNext (void)
{
  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)
{
  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 (WIN_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 (WIN_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;
}
