// This file is a part of the xMule Project.
//
// Copyright (c) 2004 Theodore R. Smith (hopeseekr@xmule.ws / http://www.xmule.ws/)
// DSA-1024 Fingerprint: 10A0 6372 9092 85A2 BB7F 907B CB8B 654B E33B F1ED
//
// This file was a part of eMule
// Copyright (c) 2002 Merkur ( merkur-@users.sourceforge.net / http://www.emule-project.net )
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

//#define 	__AMULE0__
//#define	__XMULE2__

#ifndef __AMULE0__
#include <wx/settings.h>
#include <wx/sizer.h>
#include <wx/settings.h>
#include <wx/sizer.h>
#include <wx/tokenzr.h>
#include "listctrl.h"
#include <wx/splitter.h>	//Splitterwindow
#include "wx/xrc/xmlres.h"
#include "xmuleDlg.h"           // Needed for CxmuleDlg
#endif

#if defined(WIN32)
#include <wx/msw/winundef.h>      // THIS IS NEEDED OR ERRORS RESULT!!
#endif
#include <wx/wx.h>

#include "SearchDlg.h"            // Interface declarations.
#include "SearchList.h"           // Interface declarations.
#include "ED2KLink.h"             // Needed for CED2KLink
//#include "dialog.h"             // Needed for GetDlgItem2
#include "UploadQueue.h"          // Needed for CUploadQueue
#include "DownloadQueue.h"        // Needed for CDownloadQueue
#include "otherfunctions.h"       // Needed for URLEncode
#include "packets.h"              // Needed for Packet
#include "server.h"               // Needed for CServer
#include "ServerList.h"           // Needed for CServerList
#include "sockets.h"              // Needed for CServerConnect

#include <DynPrefs/DynPrefs.h>              // Needed for DynamicPreferences

#define ID_SEARCHTIMER 55219

wxMenu *pop_sresults, *pop_smasks;

// just to keep compiler happy
static wxCommandEvent nullCevent;

static wxListEvent nullLevent;

unsigned char specialtag_type[3] =
{
    0x01, 0x00, 0x03
}

;

unsigned char specialtag_extension[3] =
{
    0x01, 0x00, 0x04
}

;

unsigned char specialtag_availability[9] =
{
    0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x15
}

;

unsigned char specialtag_minsize[9] =
{
    0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x02
}

;

unsigned char specialtag_maxsize[9] =
{
    0x03, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x02
}

;

// For Type-Selected Search on Server Side
wxString specialtag_type_name[7] =
{
    "", "", "Audio", "Image", "", "", "Video"
}

;

//new-start***********************************************************************************************
#define	SDPAS		wxPoint(-1,-1),wxSize(-1,-1)
#define	SDRES		GetResString
#define SDLISTEVT 	(wxObjectEventFunction) (wxEventFunction) (wxListEventFunction) &CSearchDlg
#define SDMOUSEEVT 	(wxObjectEventFunction) (wxEventFunction) (wxMouseEventFunction) &CSearchDlg
#define SDCMDEVT 	(wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) &CSearchDlg

wxBoxSizer *row1;

wxFlexGridSizer *row2;

wxBoxSizer *row3;

wxBoxSizer *row4;

wxODListCtrl *lsmasks, *lsresults;

int lsmasks_sort, lsmasks_sort_column, lsresults_sort, lsresults_sort_column;

unsigned char *file_md4;

wxString file_id;

wxUint32 file_clientip = 0;

wxUint32 file_clientport = 0;

wxUint32 file_udpserverip = 0;

wxUint32 file_udpserverport = 0;

wxUint32 file_tagc = 0;

wxString file_name, file_extension, file_folder, file_album, file_artist, file_title, file_typename;

wxString file_codec;

wxString file_length;

wxUint32 file_size = 0;

wxUint32 file_availability = 0;

wxUint32 file_type = 0;

wxUint32 file_bitrate;

int globsearch;

unsigned int *global_search_timer;

wxTimer m_timer;

int canceld;

wxUint16 servercount;

wxTimer xmtimer;

//xm-pipestyle for fileitem:
wxString sresultdefs[32768];

//smaskindex:
int sresultindex[32768];

//next item:
int sresultnext[32768];

//previos item:
int sresultprevious[32768];

//index in ListCtrl:
int smaskindex[36];

//next in resultlist:
int smasknext[36];

//resultcounter:
int smaskresults[36];

//searchmasks:
wxString smaskdefs[36];

Packet *glspacket = NULL;

wxString name, minsize, maxsize, ava, ext;

wxString type[7] =
{
    SDRES(IDS_SEARCH_ANY),
    SDRES(IDS_SEARCH_ARC),
    SDRES(IDS_SEARCH_AUDIO),
    SDRES(IDS_SEARCH_PICS),
    SDRES(IDS_SEARCH_CDIMG),
    SDRES(IDS_SEARCH_PRG),
    SDRES(IDS_SEARCH_VIDEO)
}

;

wxString method[5] =
{
    "Server", "Global (Server)", "Jigle", "Jigle (Web)", "FileDonkey (Web)"
}

;

wxButton *sdbutton[9];

wxChoice *sdchoice[2];

wxGauge *sdgauge[1];

wxTextCtrl *sdinput[6];

wxSizer *GUI2sizer;

wxWindow *GUI2window;

// Array for Differnt Colors for Searchresults depending on Availibility
wxColour *colorarray[32];

IMPLEMENT_DYNAMIC_CLASS(CSearchDlg, wxPanel)

void DEFTEXT(wxWindow *parent, int fontsize, int fonttyp, wxColour *fontcolour, wxColour *bgcolour)
{
    parent->SetForegroundColour(*fontcolour);
    parent->SetBackgroundColour(*bgcolour);
}

void SETCOLIMAGE(wxODListCtrl *&listctrl, int column, int imageindex)
{
    wxListItem item;
    item.SetMask(wxLIST_MASK_IMAGE);
    item.SetImage(imageindex);
    listctrl->SetColumn(column, item);
}

void slfield_get(wxString basestring, int fieldnumber, wxString &field)
{
    int startpos, endpos, column;
    startpos = 0;
    endpos = 0;
    column = 0;
    while (endpos >= 0)
    {
        switch (((const char *) basestring) [endpos])
        {
        case 0:
            endpos = - 1;
            break;
        case '|':
            if (column >= fieldnumber)
            {
                field = basestring.Mid(startpos, endpos - startpos);
                endpos = - 1;
            }
            else
            {
                ++column;
                startpos = endpos + 1;
                ++endpos;
            }
            break;
        default:
            ++endpos;
            break;
        }
    }
}

void insertresult(int smaskcurrent, wxString item_new)
{
    wxString field1, field2;
    int itemindex_last, itemindex_new;
    //first entry of last searchresultlist:
    itemindex_last = smasknext[smaskcurrent];
    itemindex_new = 1;
    while ((sresultindex[itemindex_new]) && (itemindex_new < 32760))
    {
        ++itemindex_new;
    }
    if (itemindex_new < 32760)
    {
        if (itemindex_last < 1)
        {
            itemindex_last = itemindex_new;
            //top of this list:
            smasknext[smaskcurrent] = itemindex_last;
            //Itemnumber in array sstring:
            sresultindex[itemindex_new] = smaskcurrent;
            sresultdefs[itemindex_new] = item_new;
            sresultprevious[itemindex_last] = itemindex_last;
            sresultnext[itemindex_last] = itemindex_last;
            ++smaskresults[smaskcurrent];
        }
        else
        {
            do
            {
                slfield_get(sresultdefs[itemindex_last], 6, field1);
                slfield_get(item_new, 6, field2);
                if (field1 == field2)
                {
                    itemindex_new = 0;
                    //first entry of last searchresultlist:
                    itemindex_last = smasknext[smaskcurrent];
                }
                else
                {
                    //first entry of last searchresultlist:
                    itemindex_last = sresultnext[itemindex_last];
                }
            }
            while (itemindex_last != smasknext[smaskcurrent]);
            if (itemindex_new)
            {
                //Itemnumber in array sstring:
                sresultindex[itemindex_new] = smaskcurrent;
                sresultdefs[itemindex_new] = item_new;
                //last entry of this list:
                itemindex_last = sresultprevious[itemindex_last];
                sresultnext[itemindex_new] = sresultnext[itemindex_last];
                sresultprevious[itemindex_new] = itemindex_last;
                sresultnext[itemindex_last] = itemindex_new;
                sresultprevious[sresultnext[itemindex_new]] = itemindex_new;
                ++smaskresults[smaskcurrent];
            }
            // End of if(itemindex_last < 1)
        }
        // End of if(itemindex_new < 32760)
    }
}

//ok20040226:
void CSearchDlg::InputName(wxCommandEvent &event)
{
    ButtonStart(event);
}

//ok20040226:
void CSearchDlg::InputMinSize(wxCommandEvent &event)
{
    sdinput[2]->SetFocus();
}

//ok20040226:
void CSearchDlg::InputMaxSize(wxCommandEvent &event)
{
    sdinput[3]->SetFocus();
}

//ok20040226:
void CSearchDlg::InputAvailability(wxCommandEvent &event)
{
    sdinput[4]->SetFocus();
}

//ok20040226:
void CSearchDlg::InputExtension(wxCommandEvent &event)
{
    sdinput[5]->SetFocus();
}

//ok20040226:
void CSearchDlg::InputED2K(wxCommandEvent &event)
{
}

void CSearchDlg::ButtonStart(wxCommandEvent &event)
{
    int z = 0, l = 0, n = 0, smaskcurrent_last, smaskhighest_last;
    unsigned long v1 = 0, v2 = 0;
    file_udpserverip = 0;
    globsearch = false;
    if (glspacket != NULL)
    {
        delete glspacket;
        glspacket = NULL;
    }
    if ((sdchoice[1]->GetSelection() != 1) &&(!theApp.serverconnect->IsConnected()))
    {
        wxMessageDialog *dlg = new wxMessageDialog(GUI2window,
        SDRES(IDS_ERR_NOTCONNECTED), SDRES(IDS_NOTCONNECTED), wxOK |wxCENTRE |wxICON_INFORMATION);
        dlg->ShowModal();
        delete dlg;
    }
    else
    {
        smaskcurrent_last = smaskcurrent;
        smaskhighest_last = smaskhighest;
        smaskcurrent = 0;
        while (n < smaskhighest)
        {
            if (!smasknext[++n])
            {
                smaskcurrent = n;
                n = smaskhighest;
            }
        }
        if ((!smaskcurrent) && (smaskhighest < 32))
        {
            smaskhighest++;
            smaskcurrent = smaskhighest;
        }
        if (!smaskcurrent)
        {
            m_timer.Stop();
            sdbutton[0]->Enable(true);
            sdbutton[2]->Enable(false);
            sdgauge[0]->SetValue(0);
            global_search_timer = 0;
            globsearch = false;
            canceld = true;
            smaskcurrent = smaskcurrent_last;
            smaskhighest = smaskhighest_last;
        }
        else
        {
            sdbutton[0]->Enable(false);
            sdbutton[2]->Enable(true);
            name = sdinput[0]->GetValue() .Trim();
            minsize = sdinput[1]->GetValue() .Trim();
            maxsize = sdinput[2]->GetValue() .Trim();
            ava = sdinput[3]->GetValue() .Trim();
            ext = sdinput[4]->GetValue() .Trim();
            canceld = false;
            if (name.Len() > 2)
            {
                smaskdefs[smaskcurrent] = name;
                smasknext[smaskcurrent] = - 1;
                smaskresults[smaskcurrent] = 0;
                smaskdefs[smaskcurrent] += "|";
                switch (sdchoice[1]->GetSelection())
                {
                    //local search:
                case 0:
                    smaskdefs[smaskcurrent] += "Local";
                    break;
                    //global search:
                case 1:
                    smaskdefs[smaskcurrent] += "Global";
                    break;
                }
                packetbufferz = 0;
                n = sdchoice[0]->GetSelection();
                l = specialtag_type_name[n].Len();
                minsize.ToULong( &v1, 10);
                maxsize.ToULong( &v2, 10);
                if (l) z++;
                if (v1) z++;
                if (v2) z++;
                if (ava.Len()) z++;
                if (ext.Len()) z++;
                if (z)
                {
                    packetbuffer[packetbufferz++] = 0;
                    packetbuffer[packetbufferz++] = 0;
                    z--;
                }
                l = name.Len();
                packetbuffer[packetbufferz++] = 1;
                packetbuffer[packetbufferz++] = l &255;
                packetbuffer[packetbufferz++] = (l >> 8) &255;
                while (l) packetbuffer[packetbufferz++] = name[name.Len() - l--];
                if (z)
                {
                    packetbuffer[packetbufferz++] = 0;
                    packetbuffer[packetbufferz++] = 0;
                    z--;
                }
                n = sdchoice[0]->GetSelection();
                l = specialtag_type_name[n].Len();
                if (l)
                {
                    packetbuffer[packetbufferz++] = 2;
                    packetbuffer[packetbufferz++] = l;
                    packetbuffer[packetbufferz++] = 0;
                    while (l) packetbuffer[packetbufferz++] = specialtag_type_name[n][specialtag_type_name[n].Len() - l--];
                    l = 3;
                    while (l) packetbuffer[packetbufferz++] = specialtag_type[3 - l--];
                }
                smaskdefs[smaskcurrent] += "|";
                smaskdefs[smaskcurrent] += type[n];
                if (z)
                {
                    packetbuffer[packetbufferz++] = 0;
                    packetbuffer[packetbufferz++] = 0;
                    z--;
                }
                if (v1)
                {
                    l = 9;
                    while (l) packetbuffer[packetbufferz++] = specialtag_minsize[9 - l--];
                    packetbuffer[packetbufferz - 6] = (v1 &15) << 4;
                    packetbuffer[packetbufferz - 5] = (v1 >> 4) &0xff;
                }
                smaskdefs[smaskcurrent] += "|";
                smaskdefs[smaskcurrent] += minsize;
                if (z)
                {
                    packetbuffer[packetbufferz++] = 0;
                    packetbuffer[packetbufferz++] = 0;
                    z--;
                }
                if (v2)
                {
                    l = 9;
                    while (l) packetbuffer[packetbufferz++] = specialtag_maxsize[9 - l--];
                    packetbuffer[packetbufferz - 6] = (v1 &15) << 4;
                    packetbuffer[packetbufferz - 5] = (v1 >> 4) &0xff;
                }
                smaskdefs[smaskcurrent] += "|";
                smaskdefs[smaskcurrent] += maxsize;
                if (z)
                {
                    packetbuffer[packetbufferz++] = 0;
                    packetbuffer[packetbufferz++] = 0;
                    z--;
                }
                ava.ToULong( &v1, 10);
                if (v1 > 1)
                {
                    v1--;
                    l = 9;
                    while (l) packetbuffer[packetbufferz++] = specialtag_availability[9 - l--];
                    packetbuffer[packetbufferz - 8] = v1 &255;
                    packetbuffer[packetbufferz - 7] = (v1 >> 8) &0xff;
                }
                smaskdefs[smaskcurrent] += "|";
                smaskdefs[smaskcurrent] += ava;
                l = ext.Len() &255;
                if (l)
                {
                    packetbuffer[packetbufferz++] = 2;
                    packetbuffer[packetbufferz++] = l;
                    packetbuffer[packetbufferz++] = 0;
                    while (l) packetbuffer[packetbufferz++] = ext[ (ext.Len() &255) - l--];
                    l = 3;
                    while (l) packetbuffer[packetbufferz++] = specialtag_extension[3 - l--];
                }
                smaskdefs[smaskcurrent] += "|";
                smaskdefs[smaskcurrent] += ext;
                smaskdefs[smaskcurrent] += "|";
                n = smaskcurrent - 1;
                while (n > 0)
                {
                    if (smaskdefs[n] == smaskdefs[smaskcurrent])
                    {
                        smaskresults[smaskcurrent] = 0;
                        smasknext[smaskcurrent] = 0;
                        if (smaskcurrent == smaskhighest)--smaskhighest;
                        m_timer.Stop();
                        sdbutton[0]->Enable(true);
                        sdbutton[2]->Enable(false);
                        sdgauge[0]->SetValue(0);
                        global_search_timer = 0;
                        globsearch = false;
                        canceld = true;
                        smaskcurrent = n;
                        n = - n;
                    }
                    else
                    {
                        --n;
                    }
                }
#ifdef __XMULE2__
                Packet *packet = new Packet(OP_SEARCHREQUEST, packetbuffer, packetbufferz);
#else
                Packet *packet = new Packet(OP_SEARCHREQUEST, packetbufferz, 0xe3, packetbuffer);
#endif
                if (theApp.serverconnect->IsConnected())
                {
                    theApp.uploadqueue->AddUpDataOverheadServer(packetbufferz + 6);
#ifdef __XMULE2__
                    theApp.serverconnect->SendServerPacket(packet, true);
#else
                    theApp.serverconnect->SendPacket(packet, true);
#endif
                }
                if (!srtab_lock) ShowSearchMasks();
                if (sdchoice[1]->GetSelection() == 1)
                {
                    servercount = 0;
                    globsearch = true;
                    if (theApp.serverconnect->IsConnected())
                    {
                        CServer *toask = theApp.serverlist->GetServerByAddress(theApp.serverconnect->GetCurrentServer() ->
                        GetAddress(), theApp.serverconnect->GetCurrentServer()->GetPort());
                        if (toask->GetUDPFlags() &SRV_UDPFLG_EXT_GETFILES)
                        {
#ifdef __XMULE2__
                            glspacket = new Packet(OP_GLOBSEARCHREQ2, packetbuffer, packetbufferz);
#else
                            glspacket = new Packet(OP_GLOBSEARCHREQ2, packetbufferz, 0xe3, packetbuffer);
#endif
                        }
                        else
                        {
#ifdef __XMULE2__
                            glspacket = new Packet(OP_GLOBSEARCHREQ, packetbuffer, packetbufferz);
#else
                            glspacket = new Packet(OP_GLOBSEARCHREQ, packetbufferz, 0xe3, packetbuffer);
#endif
                        }
                        if (theApp.dynprefs->Get<bool>("use-safe-connect") == true)
                        {
                            theApp.serverlist->ResetSearchServerPos();
                        }
                    }
                    else
                    {
#ifdef __XMULE2__
                        glspacket = new Packet(OP_GLOBSEARCHREQ, packetbuffer, packetbufferz);
#else
                        glspacket = new Packet(OP_GLOBSEARCHREQ, packetbufferz, 0xe3, packetbuffer);
#endif
printf("glspacket2\n");
                        theApp.serverlist->ResetSearchServerPos();
                        SearchEnd((char *) "0000", 4, 0, 0);
                    }
                }
                else
                {
                    globsearch = false;
                }
                sdgauge[0]->SetRange(theApp.serverlist->GetServerCount() - 1);
            }
            else
            {
                smaskcurrent = smaskcurrent_last;
                smaskhighest = smaskhighest_last;
                wxMessageDialog *dlg = new wxMessageDialog(GUI2window, "Search-string too short! (min. 3 characters)", "Error 101",
                wxOK |wxCENTRE |wxICON_INFORMATION);
                dlg->ShowModal();
                delete dlg;
                m_timer.Stop();
                sdbutton[0]->Enable(true);
                sdbutton[2]->Enable(false);
                sdgauge[0]->SetValue(0);
                global_search_timer = 0;
                globsearch = false;
                canceld = true;
            }
        }
    }
}

void CSearchDlg::ExecuteLinkED2K(wxString ed2k)
{
    bool result = false;
    wxString ed2klink;
    int p1 = 0, p2 = 0, l = 0;
    CED2KLink *pLink;
    ed2k.Replace("%20", " ");
    l = ed2k.Len();
    while (p2 < l)
    {
        switch ((char) *ed2k.Mid(p2, 1))
        {
        case '\r':
        case '\n':
            if (p2 > p1)
            {
                result = true;
                ed2klink = ed2k.Mid(p1, p2 - p1);
                if (ed2klink.Right(1) != "/")
                {
                    ed2klink += "/";
                }
                pLink = CED2KLink::CreateLinkFromUrl(ed2klink);
                if (pLink->GetKind() == CED2KLink::kFile)
                {
                    theApp.downloadqueue->AddFileLinkToDownload(pLink->GetFileLink());
                }
                delete pLink;
            }
            p1 = p2 + 1;
            break;
        }
        p2++;
    }
    if (p2 > p1)
    {
        result = true;
        ed2klink = ed2k.Mid(p1, p2 - p1);
        if (ed2klink.Right(1) != "/")
        {
            ed2klink += "/";
        }
        pLink = CED2KLink::CreateLinkFromUrl(ed2klink);
        if (pLink->GetKind() == CED2KLink::kFile)
        {
            theApp.downloadqueue->AddFileLinkToDownload(pLink->GetFileLink());
        }
        delete pLink;
    }
}

void CSearchDlg::ButtonMore(wxCommandEvent &event)
{
    //printf("bumore + enter\n");
}

void CSearchDlg::ButtonCancel(wxCommandEvent &event)
{
    globsearch = false;
    if (glspacket != NULL)
    {
        delete glspacket;
        glspacket = NULL;
    }
    m_timer.Stop();
    sdbutton[0]->Enable(true);
    sdbutton[2]->Enable(false);
    sdgauge[0]->SetValue(0);
    global_search_timer = 0;
    globsearch = false;
    canceld = true;
    global_search_timer = 0;
    globsearch = false;
    canceld = true;
    if (srtab_refresh == 0)
    {
        srtab_refresh = 1;
        ShowSearchResults();
    }
}

void CSearchDlg::ButtonDownload(wxCommandEvent &event)
{
    unsigned int i;
    int number_selected = 0;
    long index = - 1, itemdata = 0;
    char *filename;
    if (!srtab_lock)
    {
        srtab_lock = 2;
        number_selected = lsresults->GetSelectedItemCount();
        while (number_selected)
        {
            index = lsresults->GetNextItem(index, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
            if (index == - 1)
            {
                number_selected = 0;
            }
            else
            {
                itemdata = lsresults->GetItemData(index);
                filename = (char *) malloc(sresultdefs[itemdata].Len() + 1);
                for (i = 0 ; i < sresultdefs[itemdata].Len() ; i++)
                {
                    filename[i] = ((const char *) sresultdefs[itemdata]) [i];
                }
                filename[i] = 0;
                CSearchFile *csf = new CSearchFile(filename, smaskcurrent);
                theApp.downloadqueue->AddSearchToDownload(csf);
                lsresults->SetItemState(index, 0, wxLIST_STATE_SELECTED);
                number_selected--;
                free(filename);
            }
        }
        srtab_lock = 0;
    }
}

void CSearchDlg::SearchResultsRemoveSelected(wxCommandEvent &event)
{
    int maskitem, itemindex_prev, itemindex_next, number_selected = 0;
    long index = - 1, itemdata = 0;
    srtab_deep++;
    if (!srtab_lock)
    {
        srtab_lock = 3;
        number_selected = lsresults->GetSelectedItemCount();
        while (number_selected)
        {
            index = lsresults->GetNextItem(index, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
            if (index == - 1)
            {
                number_selected = 0;
            }
            else
            {
                itemdata = lsresults->GetItemData(index);
                lsresults->SetItemState(index, 0, wxLIST_STATE_SELECTED);
                itemindex_next = sresultnext[itemdata];
                itemindex_prev = sresultprevious[itemdata];
                maskitem = sresultindex[itemdata];
                smaskresults[maskitem]--;
                sresultdefs[itemdata] = "";
                sresultindex[itemdata] = 0;
                sresultprevious[itemdata] = 0;
                sresultnext[itemdata] = 0;
                if (itemindex_next == itemdata)
                {
                    //this is our last item
                    smasknext[maskitem] = - 1;
                }
                else
                {
                    if (smasknext[maskitem] == itemdata) smasknext[maskitem] = itemindex_next;
                    sresultprevious[itemindex_next] = itemindex_prev;
                    sresultnext[itemindex_prev] = itemindex_next;
                }
                number_selected--;
            }
        }
        srtab_lock = 0;
        ShowSearchResults();
    }
    srtab_deep--;
}

void CSearchDlg::SearchResultsRemoveAll(wxCommandEvent &event)
{
    long itemdata = 0;
    srtab_deep++;
    if (!srtab_lock)
    {
        srtab_lock = 4;
        itemdata = smasknext[smaskcurrent];
        while (itemdata > 0)
        {
            smasknext[smaskcurrent] = sresultnext[itemdata];
            sresultdefs[itemdata] = "";
            sresultindex[itemdata] = 0;
            sresultprevious[itemdata] = 0;
            sresultnext[itemdata] = 0;
            itemdata = smasknext[smaskcurrent];
        }
        smaskresults[smaskcurrent] = 0;
        smasknext[smaskcurrent] = - 1;
        srtab_lock = 0;
        ShowSearchResults();
    }
    srtab_deep--;
}

void CSearchDlg::SearchResultsCloseThisRL(wxCommandEvent &event)
{
    srtab_deep++;
    if (!srtab_lock)
    {
        SearchResultsRemoveAll(event);
        srtab_lock = 5;
        smasknext[smaskcurrent] = 0;
        smaskdefs[smaskcurrent] = "";
        while ((smaskhighest > 0) && (!smasknext[smaskhighest])) smaskhighest--;
        smaskcurrent = smaskhighest;
        srtab_lock = 0;
        ShowSearchResults();
    }
    srtab_deep--;
}

void CSearchDlg::SearchResultsCloseAllRL(wxCommandEvent &event)
{
    srtab_deep++;
    if (!srtab_lock)
    {
        for (int i = smaskhighest ; i ; i--)
        {
            smaskcurrent = i;
            SearchResultsCloseThisRL(event);
        }
        smaskhighest = 0;
        smaskcurrent = smaskhighest;
        ShowSearchResults();
    }
    srtab_deep--;
}

void CSearchDlg::SearchResultsCloseThisSM(wxCommandEvent &event)
{
    long number_selected, index = - 1;
    srtab_deep++;
    if (!srtab_lock)
    {
        number_selected = lsmasks->GetSelectedItemCount();
        while (number_selected)
        {
            index = lsmasks->GetNextItem(index, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
            if (index == - 1)
            {
                number_selected = 0;
            }
            else
            {
                smaskcurrent = lsmasks->GetItemData(index);
                lsmasks->SetItemState(index, 0, wxLIST_STATE_SELECTED);
                SearchResultsCloseThisRL(event);
            }
        }
        smaskcurrent = smaskhighest;
        ShowSearchResults();
    }
    srtab_deep--;
}

void CSearchDlg::SearchResultsCloseAllSM(wxCommandEvent &event)
{
    srtab_deep++;
    if (!srtab_lock)
    {
        for (int i = smaskhighest ; i ; i--)
        {
            smaskcurrent = i;
            SearchResultsCloseThisRL(event);
        }
        smaskhighest = 0;
        smaskcurrent = smaskhighest;
        ShowSearchResults();
    }
    srtab_deep--;
}

void CSearchDlg::ButtonStartLink(wxCommandEvent &event)
{
    const char *linkname;
    linkname = (const char *) sdinput[5]->GetValue() .Trim();
    switch (linkname[0])
    {
        //http-link (to realize):
    case 'H':
        break;
        //ftp-link (to realize):
    case 'F':
        break;
        //ed2k-link:
    default:
#ifdef __AMULE0__
        theApp.amuledlg->StartFast(sdinput[5]);
#elifdef __XMULE2__
        theApp.xmuledlg->StartFast(sdinput[5]);
#else
        ExecuteLinkED2K(sdinput[5]->GetValue().Trim());
#endif
        sdinput[5]->Clear();
        break;
    }
}

void CSearchDlg::ButtonClearAll(wxCommandEvent &event)
{
    int i;
    (void) lsresults->DeleteAllItems();
    (void) lsmasks->DeleteAllItems();
    ButtonReset(event);
    //clear searchlists, clear searchrequests
    smaskhighest = 0;
    smaskcurrent = 0;
    for (i = 0 ; i < 32768 ; i++)
    {
        if (sresultindex[i])
        {
            sresultdefs[i] = "";
            sresultnext[i] = 0;
            sresultprevious[i] = 0;
            sresultindex[i] = 0;
        }
    }
    for (i = 0 ; i < 36 ; i++)
    {
        if (smasknext[i])
        {
            smaskdefs[i] = "";
        }
        smasknext[i] = 0;
        smaskresults[i] = 0;
    }
}

//ok20040226:
void CSearchDlg::ButtonReset(wxCommandEvent &event)
{
    int i;
    sdchoice[0]->SetSelection(0);
    sdchoice[1]->SetSelection(1);
    for (i = 0 ; i < 6 ; i++) sdinput[i]->SetValue("");
    sdinput[0]->SetFocus();
}

void CSearchDlg::ButtonSaveTabs(wxCommandEvent &event)
{
    int c, n, nextresult;
    unsigned int characterposition;
    wxString filepath;
    FILE *sam;
    wxFileDialog sresultsandmasks(this, "Save searchresults & -masks", "", "xmulesam.xmt", "*.xmt", wxSAVE, wxDefaultPosition);
    if (sresultsandmasks.ShowModal() == wxID_OK)
    {
        filepath = sresultsandmasks.GetPath();
        sam = fopen((const char *) filepath, "w");
        if (sam)
        {
            n = 0;
            while (n < smaskhighest)
            {
                nextresult = smasknext[++n];
                if (nextresult)
                {
                    fwrite("smask|", 6, 1, sam);
                    fwrite((const char *) smaskdefs[n], smaskdefs[n].Len(), 1, sam);
                    fwrite("\r\n", 2, 1, sam);
                    if (nextresult > 0)
                    {
                        do
                        {
                            c = 0;
                            characterposition = 0;
                            while (c < 2)
                            {
                                if (characterposition < sresultdefs[nextresult].Len())
                                {
                                    switch (((const char *) sresultdefs[nextresult]) [characterposition])
                                    {
                                    case '|': c++;
                                        break;
                                    }
                                    characterposition++;
                                }
                                else c = 2;
                            }
                            fwrite("entry|||", 8, 1, sam);
                            fwrite((const char *) sresultdefs[nextresult].Mid(characterposition, wxSTRING_MAXLEN), sresultdefs[nextresult].Len() - characterposition, 1, sam);
                            fwrite("\r\n", 2, 1, sam);
                            nextresult = sresultnext[nextresult];
                        }
                        while (nextresult != smasknext[n]);
                    }
                }
            }
            (void) fclose(sam);
        }
    }
}

void CSearchDlg::ButtonLoadTabs(wxCommandEvent &event)
{
    unsigned char byte[2] =
    {
        0x00, 0x00
        };
    wxString filepath, directory, filename, line;
    FILE *sam;
    srtab_deep++;
    wxFileDialog sresultsandmasks(this, "Load searchresults & -masks", "", "xmulesam.xmt", "*.xmt", wxOPEN, wxDefaultPosition);
    if (sresultsandmasks.ShowModal() == wxID_OK)
    {
        filepath = sresultsandmasks.GetPath();
        sam = fopen((const char *) filepath, "r");
        if (sam)
        {
            //file exist
            ButtonClearAll(event);
            line = "";
            while (!feof(sam))
            {
                (void) fread( &byte, 1, 1, sam);
                switch (byte[0])
                {
                    //nothing:
                case 0: break;
                    //nothing:
                case '\r': break;
                case '\n':
                    switch (((const char *) line) [0])
                    {
                        //smask (resultlist):
                    case 's':
                        smaskdefs[++smaskhighest] = line.Mid(6, wxSTRING_MAXLEN);
                        smasknext[smaskhighest] = - 1;
                        smaskresults[smaskhighest] = 0;
                        break;
                        //entry (resultlist):
                    case 'e':
                        insertresult(smaskhighest, line.Mid(6, wxSTRING_MAXLEN));
                        break;
                        //ignore:
                    default:
                        break;
                    }
                    line = "";
                    //lineend:
                    break;
                default: line += (wxChar) byte[0];
                    break;
                }
            }
            (void) fclose(sam);
            smaskcurrent = smaskhighest;
        }
    }
    if (!srtab_lock)
    {
        ShowSearchResults();
    }
    srtab_deep--;
}

//ok20040226:
void CSearchDlg::ChoiceType(wxCommandEvent &event)
{
}

//ok20040226:
void CSearchDlg::ChoiceMethod(wxCommandEvent &event)
{
}

void CSearchDlg::ListSelectedSearchMask(wxListEvent &event)
{
    int l;
    if (lsmasks->GetSelectedItemCount() <= 1)
    {
        srtab_deep++;
        l = smaskcurrent;
        smaskcurrent = lsmasks->GetItemData(event.m_itemIndex);
        if (l != smaskcurrent)
        {
            lsresults_sort -= 64;
            ListSortSearchResults(nullLevent);
            if (!srtab_lock)
            {
                ShowSearchResults();
            }
        }
        srtab_deep--;
    }
}

void CSearchDlg::ListSortSearchMasks(wxListEvent &event)
{
    wxString field1, field2;
    int lastsort, maxsort, smaski, smaskr, smaskn, pointer = 0, itemindex_current, itemindex_last;
    wxString smasks, item_last, item_current;
    SETCOLIMAGE(lsmasks, lsmasks_sort_column, - 1);
    if (lsmasks_sort < 0)
    {
        lsmasks_sort += 64;
    }
    else
    {
        lsmasks_sort_column = event.GetColumn();
        lsmasks_sort = 1 - lsmasks_sort;
    }
    SETCOLIMAGE(lsmasks, lsmasks_sort_column, lsmasks_sort);
    lastsort = 1;
    maxsort = 32;
    while (maxsort)
    {
        lastsort = 0;
        itemindex_last = - 1;
        itemindex_current = 0;
        while (itemindex_current < maxsort)
        {
            if (smasknext[itemindex_current])
            {
                if (itemindex_last >= 0)
                {
                    switch (lsmasks_sort_column)
                    {
                        //number of searchresults:
                    case 0:
                        field1 = wxString::Format("%d", smaskresults[itemindex_last]);
                        field2 = wxString::Format("%d", smaskresults[itemindex_current]);
                        break;
                    default:
                        item_last = smaskdefs[itemindex_last];
                        item_current = smaskdefs[itemindex_current];
                        slfield_get(item_last, lsmasks_sort_column - 1, field1);
                        slfield_get(item_current, lsmasks_sort_column - 1, field2);
                        break;
                    }
                    pointer = 0;
                    if (!lsmasks_sort)
                    {
                        if (field1.Cmp(field2) > 0) pointer = 1;
                        //up:
                        //down:
                    }
                    else if(field1.Cmp(field2) < 0) pointer = 1;
                    if (pointer)
                    {
                        //switch items (n,r,s)
                        smaski = smaskindex[itemindex_last];
                        smaskindex[itemindex_last] = smaskindex[itemindex_current];
                        smaskindex[itemindex_current] = smaski;
                        smaskn = smasknext[itemindex_last];
                        smasknext[itemindex_last] = smasknext[itemindex_current];
                        smasknext[itemindex_current] = smaskn;
                        smaskr = smaskresults[itemindex_last];
                        smaskresults[itemindex_last] = smaskresults[itemindex_current];
                        smaskresults[itemindex_current] = smaskr;
                        smasks = smaskdefs[itemindex_last];
                        smaskdefs[itemindex_last] = smaskdefs[itemindex_current];
                        smaskdefs[itemindex_current] = smasks;
                        lastsort = itemindex_current;
                    }
                }
                itemindex_last = itemindex_current;
            }
            itemindex_current++;
        }
        maxsort = lastsort;
    }
    if (!srtab_lock)
    {
        srtab_deep++;
        ShowSearchResults();
        srtab_deep--;
    }
}

void CSearchDlg::ListSortSearchResults(wxListEvent &event)
{
    int lastsort, maxsort, sresulti, itemindex_current, itemindex_last;
    wxString field1, field2, sresults, item_last, item_current;
    long pointer;
    srtab_deep++;
    SETCOLIMAGE(lsresults, lsresults_sort_column, - 1);
    if (lsresults_sort < 0)
    {
        lsresults_sort += 64;
    }
    else
    {
        lsresults_sort_column = event.GetColumn();
        lsresults_sort = 1 - lsresults_sort;
    }
    SETCOLIMAGE(lsresults, lsresults_sort_column, lsresults_sort);
    lastsort = 1;
    maxsort = sresultprevious[smasknext[smaskcurrent]];
    while (maxsort > 0)
    {
        lastsort = 0;
        itemindex_last = - 1;
        itemindex_current = smasknext[smaskcurrent];
        do
        {
            if (itemindex_last >= 0)
            {
                item_last = (const char *) sresultdefs[itemindex_last];
                item_current = (const char *) sresultdefs[itemindex_current];
                switch (lsresults_sort_column)
                {
                case 1:
                case 2:
                case 8:
                case 9:
                case 13:
                    slfield_get(item_last, lsresults_sort_column + 2, field1);
                    field1.ToLong( &pointer, 10);
                    field1 = wxString::Format("%08lx", pointer);
                    slfield_get(item_current, lsresults_sort_column + 2, field2);
                    field2.ToLong( &pointer, 10);
                    field2 = wxString::Format("%08lx", pointer);
                    break;
                default:
                    slfield_get(item_last, lsresults_sort_column + 2, field1);
                    slfield_get(item_current, lsresults_sort_column + 2, field2);
                    break;
                }
                pointer = 0;
                if (!lsresults_sort)
                {
                    if (field1.Cmp(field2) > 0) pointer = 1;
                    //up:
                    //down:
                }
                else if(field1.Cmp(field2) < 0) pointer = 1;
                if (pointer)
                {
                    //switch items (n,r,s)
                    sresulti = sresultindex[itemindex_last];
                    sresultindex[itemindex_last] = sresultindex[itemindex_current];
                    sresultindex[itemindex_current] = sresulti;
                    sresults = sresultdefs[itemindex_last];
                    sresultdefs[itemindex_last] = sresultdefs[itemindex_current];
                    sresultdefs[itemindex_current] = sresults;
                    lastsort = itemindex_current;
                }
            }
            itemindex_last = itemindex_current;
            itemindex_current = sresultnext[itemindex_current];
        }
        while (itemindex_last != maxsort);
        maxsort = lastsort;
    }
    if (!srtab_lock)
    {
        ShowSearchResults();
    }
    srtab_deep--;
}

void CSearchDlg::PopupSearchResults(wxMouseEvent &event)
{
    PopupMenu(pop_sresults, event.GetPosition());
}

void CSearchDlg::PopupSearchMasks(wxMouseEvent &event)
{
    PopupMenu(pop_smasks, event.GetPosition());
}

CSearchDlg::CSearchDlg(wxWindow *pParent): wxPanel(pParent, CSearchDlg::IDD), m_timer(this, ID_SEARCHTIMER)
{
    Init();
        GUI2window = pParent;

}

void CSearchDlg::Init()
{
    int column;
    srtab_refresh = true;
    // Color for the Buttons
    wxColour button_bgcolour(0xd1, 0xc7, 0xff);
    // Differnt Colors for Searchresults depending on Availibility
    for (int j = 0 ; j < 16 ; j++)
    {
        colorarray[j] = new wxColour(0x00, 0x00, j *0x0e + 0x0e);
        colorarray[16 + j] = new wxColour(0x00, j *0x0e + 0x0e, 0x00);
    }
    // Backgroundcolor for the Searchresults and Searchmasks List
    wxColour DARK_WHITE(0xef, 0xef, 0xef);
    srtab_lock = 0;
    srtab_deep = 0;
    pop_sresults = new wxMenu("xMule-Searchresults");
    pop_sresults->AppendSeparator();
    pop_sresults->Append(17001, "Download selected");
    pop_sresults->Append(17002, "Remove selected");
    pop_sresults->Append(17003, "Remove all");
    pop_sresults->Append(17004, "Close this result-list");
    pop_sresults->Append(17005, "Close all result-lists");
    pop_sresults->AppendSeparator();
#if 0
    pop_sresults->Append(17011, "Copy ED2k-link to clipboard");
    pop_sresults->Append(17012, "Copy ED2k-link to clipboard (HTML)");
    pop_sresults->Append(17013, "Check Fake");
    pop_sresults->AppendSeparator();
#endif
    pop_sresults->Append(17097, "Save tables");
    pop_sresults->Append(17098, "Load tables");
    pop_sresults->Append(17099, "Clear all");
    pop_smasks = new wxMenu("xMule-Searchmasks");
    pop_smasks->AppendSeparator();
    pop_smasks->Append(17051, "Remove selected");
    pop_smasks->Append(17052, "Remove all");
    pop_smasks->AppendSeparator();
    pop_smasks->Append(17097, "Save tables");
    pop_smasks->Append(17098, "Load tables");
    pop_smasks->Append(17099, "Clear all");
    // Headline of the Searchregion
    DEFTEXT((wxWindow *) this, 13, 0, wxGREEN, wxLIGHT_GREY);
    wxStaticBox *sb001 = new wxStaticBox(this, 10001, "Search", wxPoint( - 1, - 1), wxSize(312, 96), 0, "sb001");
    // Text ahead of the Search String Input Box
    DEFTEXT((wxWindow *) this, 12, 0, wxBLUE, wxBLACK);
    wxStaticText *st001 = new wxStaticText(this, 10101, "Name:", SDPAS, 0, "st001");
    // Search String Input Box
    sdinput[0] = new wxTextCtrl(this, 11001, "", SDPAS, wxTE_PROCESS_ENTER, wxDefaultValidator, "tc000");
    // Text ahead of the Type Selection Button
    DEFTEXT((wxWindow *) this, 12, 0, wxBLACK, wxWHITE);
    wxStaticText *st009 = new wxStaticText(this, 10109, "Type:", SDPAS, 0, "st009");
    // Type Selection Button
    sdchoice[0] = new wxChoice(this, 13001, SDPAS, 7, type, 0, wxDefaultValidator, "ch000");
    // Text ahead of the Search Methode Seletion Button
    wxStaticText *st010 = new wxStaticText(this, 10110, "Method:", SDPAS, 0, "st010");
    // Search Methode Selection Button
    sdchoice[1] = new wxChoice(this, 13002, SDPAS, 5, method, 0, wxDefaultValidator, "ch001");
    sdchoice[1]->SetSelection(1);
    // Reset Button
    DEFTEXT((wxWindow *) this, 12, 0, wxBLACK, &button_bgcolour);
    sdbutton[7] = new wxButton(this, 12008, "Reset", SDPAS, 0, wxDefaultValidator, "bu005");
    // Sizer for the Searchregion
    wxBoxSizer *sb001a = new wxBoxSizer(wxVERTICAL);
    sb001a->Add(st001, 0, wxALIGN_LEFT, 0);
    sb001a->Add(sdinput[0], 1, wxALIGN_LEFT |wxGROW, 4);
    wxBoxSizer *ch009s = new wxBoxSizer(wxVERTICAL);
    ch009s->Add(st009, 0, wxALIGN_LEFT, 0);
    ch009s->Add(sdchoice[0], 0, wxALIGN_LEFT, 0);
    wxBoxSizer *ch010s = new wxBoxSizer(wxVERTICAL);
    ch010s->Add(st010, 0, wxALIGN_LEFT, 0);
    ch010s->Add(sdchoice[1], 0, wxALIGN_LEFT, 0);
    wxBoxSizer *sb001b = new wxBoxSizer(wxHORIZONTAL);
    sb001b->Add(ch009s, 0, wxRIGHT |wxALIGN_CENTER, 4);
    sb001b->Add(ch010s, 0, wxRIGHT |wxALIGN_CENTER, 4);
    sb001b->Add(sdbutton[7], 0, wxRIGHT |wxALIGN_CENTER, 4);
    wxStaticBoxSizer *sb001s = new wxStaticBoxSizer(sb001, wxVERTICAL);
    sb001s->Add(sb001a, 1, wxALIGN_LEFT |wxGROW, 0);
    sb001s->Add(sb001b, 1, wxALIGN_LEFT |wxGROW, 0);
    // Headline of the Filterregion
    DEFTEXT((wxWindow *) this, 13, 0, wxGREEN, wxLIGHT_GREY);
    wxStaticBox *sb002 = new wxStaticBox(this, 10002, "Filter", wxPoint( - 1, - 1), wxSize(196, 96), 0, "sb002");
    // Definition for the Text ahead min Size Input Box, max Size Input Box, Availability Input Box, Extension Input Box, Text 'MB'
    DEFTEXT((wxWindow *) this, 12, 0, wxBLUE, wxBLACK);
    // Text ahead the min. Size Input Box
    wxStaticText *st002 = new wxStaticText(this, 10102, "min. Size:", SDPAS, 0, "st002");
    // min. Size Input Box
    sdinput[1] = new wxTextCtrl(this, 11002, "", SDPAS, wxTE_PROCESS_ENTER, wxDefaultValidator, "tc001");
    // Text ahead the max. Size Input Box
    wxStaticText *st003 = new wxStaticText(this, 10103, "max. Size:", SDPAS, 0, "st003");
    // max Size Input Box
    sdinput[2] = new wxTextCtrl(this, 11003, "", SDPAS, wxTE_PROCESS_ENTER, wxDefaultValidator, "tc002");
    // Text 'MB' behind min. & max.Size Input Box
    wxStaticText *st004 = new wxStaticText(this, 0, "MB", SDPAS, 0, "st004");
    wxStaticText *st005 = new wxStaticText(this, 0, "  ", SDPAS, 0, "st005");
    wxStaticText *st004b = new wxStaticText(this, 0, "MB", SDPAS, 0, "s004b");
    wxStaticText *st005b = new wxStaticText(this, 0, "  ", SDPAS, 0, "st005b");
    // Text ahead the min. Availability Input Box
    wxStaticText *st006 = new wxStaticText(this, 10106, "Availability:", SDPAS, 0, "st006");
    // min. Availability Input Box
    sdinput[3] = new wxTextCtrl(this, 11006, "", SDPAS, wxTE_PROCESS_ENTER, wxDefaultValidator, "tc003");
    // Text ahead the Extension Input Box
    wxStaticText *st007 = new wxStaticText(this, 10107, "Extension:", SDPAS, 0, "st007");
    // Extension Input Box
    sdinput[4] = new wxTextCtrl(this, 11007, "", SDPAS, wxTE_PROCESS_ENTER, wxDefaultValidator, "tc004");
    // Sizer for the Filterregion
    wxBoxSizer *sb002a = new wxBoxSizer(wxVERTICAL);
    sb002a->Add(st002, 0, wxALIGN_LEFT, 4);
    sb002a->Add(sdinput[1], 0, wxALIGN_LEFT, 4);
    sb002a->Add(st006, 0, wxALIGN_LEFT, 4);
    sb002a->Add(sdinput[3], 0, wxALIGN_LEFT, 4);
    wxBoxSizer *sb002b = new wxBoxSizer(wxVERTICAL);
    sb002b->Add(st005, 0, wxALIGN_LEFT, 4);
    sb002b->Add(st004, 0, wxALIGN_LEFT, 4);
    wxBoxSizer *sb002c = new wxBoxSizer(wxVERTICAL);
    sb002c->Add(st003, 0, wxALIGN_LEFT, 4);
    sb002c->Add(sdinput[2], 0, wxALIGN_LEFT, 4);
    sb002c->Add(st007, 0, wxALIGN_LEFT, 4);
    sb002c->Add(sdinput[4], 0, wxALIGN_LEFT, 4);
    wxBoxSizer *sb002d = new wxBoxSizer(wxVERTICAL);
    sb002d->Add(st005b, 0, wxALIGN_LEFT, 4);
    sb002d->Add(st004b, 0, wxALIGN_LEFT, 4);
    wxStaticBoxSizer *sb002s = new wxStaticBoxSizer(sb002, wxHORIZONTAL);
    sb002s->Add(sb002a, 0, wxLEFT, 4);
    sb002s->Add(sb002b, 0, wxLEFT, 4);
    sb002s->Add(sb002c, 0, wxLEFT, 4);
    sb002s->Add(sb002d, 0, wxLEFT, 4);
    // Headline for the Direct Download region
    DEFTEXT((wxWindow *) this, 13, 0, wxBLUE, wxLIGHT_GREY);
    wxStaticBox *sb003 = new wxStaticBox(this, 10003, "Direct Download", wxPoint( - 1, - 1), wxSize(152, 96), 0, "sb003");
    // Text ahead the Direct Download Input Box
    DEFTEXT((wxWindow *) this, 12, 0, wxBLUE, wxBLACK);
    wxStaticText *st008 = new wxStaticText(this, 10108, "ED2K/HTTP/FTP-link(s):", SDPAS, 0, "st008");
    // Direct Download Input Box
    sdinput[5] = new wxTextCtrl(this, 11008, "", SDPAS, wxTE_MULTILINE |wxID_COPY |wxID_PASTE, wxDefaultValidator, "tc005");
    // Sizer for the Direct Download region
    wxStaticBoxSizer *sb003s = new wxStaticBoxSizer(sb003, wxVERTICAL);
    sb003s->Add(st008, 0, wxLEFT |wxALIGN_LEFT, 4);
    sb003s->Add(sdinput[5], 3, wxLEFT |wxALIGN_LEFT |wxGROW, 4);
    //
    row1 = new wxBoxSizer(wxHORIZONTAL);
    row1->Add(sb001s, 0, wxRIGHT, 4);
    row1->Add(sb002s, 0, wxRIGHT |wxGROW, 4);
    row1->Add(sb003s, 3, wxGROW);
    // Buttons
    DEFTEXT((wxWindow *) this, 12, 0, wxBLACK, &button_bgcolour);
    sdbutton[0] = new wxButton(this, 12001, "Start", SDPAS, 0, wxDefaultValidator, "bu000");
    sdbutton[1] = new wxButton(this, 12002, "More", SDPAS, 0, wxDefaultValidator, "bu001");
    sdbutton[2] = new wxButton(this, 12003, "Cancel", SDPAS, 0, wxDefaultValidator, "bu002");
    sdbutton[3] = new wxButton(this, 12004, "Download Selected", SDPAS, 0, wxDefaultValidator, "bu003");
    sdbutton[4] = new wxButton(this, 12005, "Save Tabs", SDPAS, 0, wxDefaultValidator, "bu007");
    sdbutton[5] = new wxButton(this, 12006, "Load Tabs", SDPAS, 0, wxDefaultValidator, "bu008");
    sdbutton[6] = new wxButton(this, 12007, "Clear All", SDPAS, 0, wxDefaultValidator, "bu005");
    sdbutton[8] = new wxButton(this, 12009, "Start Direct Download-Link", SDPAS, 0, wxDefaultValidator, "bu004");
    // commenting this line out shows no difference !!!
    DEFTEXT((wxWindow *) this, 13, 0, wxGREEN, wxLIGHT_GREY);
    //
    row2 = new wxFlexGridSizer(8, 0, 0);
    row2->AddGrowableCol(3);
    row2->AddGrowableCol(5);
    row2->AddGrowableCol(6);
    row2->AddGrowableCol(8);
    row2->Add(sdbutton[0], 0, 0, 0);
    row2->Add(sdbutton[1], 0, 0, 0);
    row2->Add(sdbutton[2], 0, 0, 0);
    row2->Add(sdbutton[3], 0, wxALIGN_CENTER, 0);
    row2->Add(sdbutton[4], 0, wxALIGN_CENTER, 0);
    row2->Add(sdbutton[5], 0, wxALIGN_LEFT, 0);
    row2->Add(sdbutton[6], 0, wxALIGN_LEFT, 0);
    row2->Add(sdbutton[8], 0, wxALIGN_RIGHT, 0);
    row3 = new wxBoxSizer(wxHORIZONTAL);
    wxSplitterWindow *spw1 = new wxSplitterWindow(this, 16001, SDPAS, wxSP_LIVE_UPDATE |
    wxCLIP_CHILDREN |wxSP_NOBORDER);
    row3->Add(spw1, 3, wxGROW, 0);
    wxPanel *spw1sub1 = new wxPanel(spw1, - 1);
    wxPanel *spw1sub2 = new wxPanel(spw1, - 1);
    // Definition for the Headlines of the Search Results and the History Box
    DEFTEXT(spw1sub1, 13, 0, wxGREEN, wxLIGHT_GREY);
    // Search Results Box
    wxStaticBox *sb005 = new wxStaticBox(spw1sub1, 10005, "Search Results", SDPAS, 0, "sb005");
    // History Box
    wxStaticBox *sb006 = new wxStaticBox(spw1sub2, 10006, "History", SDPAS, 0, "sb006");
    // Sizer for Search Results and History Box
    wxStaticBoxSizer *sb005s = new wxStaticBoxSizer(sb005, wxVERTICAL);
    wxStaticBoxSizer *sb006s = new wxStaticBoxSizer(sb006, wxVERTICAL);
    // Outline of the Search Results Box
    DEFTEXT(spw1sub1, 13, 0, wxBLACK, wxWHITE);
    lsresults = new wxODListCtrl(spw1sub1, 14001, SDPAS,
    wxSUNKEN_BORDER |wxLC_REPORT, wxDefaultValidator, "list1");
    //sort-direction for the Search Results List Box
    lsresults_sort = 0;
    //sort-column: for the Search Results List Box
    lsresults_sort_column = 0;
    // Search Results List Box
    wxListItem ic1;
    ic1.m_mask = wxLIST_MASK_TEXT |wxLIST_MASK_IMAGE;
    ic1.m_image = - 1;
    // Colors of the Search Resuts List Box
    lsresults->SetTextColour( *wxBLACK);
    lsresults->SetBackgroundColour(DARK_WHITE);
    lsresults->SetName("History");
    // <-- huh ?
    // Colums of the Search Results List Box
    column = 0;
#if 0
    ic1.m_text = _("No.");
    lsresults->InsertColumn(column, ic1);
    lsresults->SetColumnWidth(column, 40);
#endif
    ic1.m_text = _("Filename");
    lsresults->InsertColumn(column, ic1);
    lsresults->SetColumnWidth(column, 250);
    ic1.m_text = _("Size");
    lsresults->InsertColumn(++column, ic1);
    lsresults->SetColumnWidth(column, 80);
    ic1.m_text = _("Availablity");
    lsresults->InsertColumn(++column, ic1);
    lsresults->SetColumnWidth(column, 70);
    ic1.m_text = _("Type");
    lsresults->InsertColumn(++column, ic1);
    lsresults->SetColumnWidth(column, 60);
    ic1.m_text = _("File-ID");
    lsresults->InsertColumn(++column, ic1);
    lsresults->SetColumnWidth(column, 250);
    ic1.m_text = _("Artist");
    lsresults->InsertColumn(++column, ic1);
    lsresults->SetColumnWidth(column, 40);
    ic1.m_text = _("Album");
    lsresults->InsertColumn(++column, ic1);
    lsresults->SetColumnWidth(column, 45);
    ic1.m_text = _("Title");
    lsresults->InsertColumn(++column, ic1);
    lsresults->SetColumnWidth(column, 50);
    ic1.m_text = _("Length");
    lsresults->InsertColumn(++column, ic1);
    lsresults->SetColumnWidth(column, 45);
    ic1.m_text = _("Bitrate");
    lsresults->InsertColumn(++column, ic1);
    lsresults->SetColumnWidth(column, 45);
    ic1.m_text = _("Codec");
    lsresults->InsertColumn(++column, ic1);
    lsresults->SetColumnWidth( + column, 45);
    ic1.m_text = _("Folder");
    lsresults->InsertColumn(++column, ic1);
    lsresults->SetColumnWidth(column, 45);
    ic1.m_text = _("ServerIP");
    lsresults->InsertColumn(++column, ic1);
    lsresults->SetColumnWidth(column, 70);
    ic1.m_text = _("ServerPort");
    lsresults->InsertColumn(++column, ic1);
    lsresults->SetColumnWidth(column, 70);
    SETCOLIMAGE(lsresults, lsresults_sort_column, lsresults_sort);
    sb005s->Add(lsresults, 3, wxGROW, 0);
    lsmasks = new wxODListCtrl(spw1sub2, 14002, SDPAS, /*wxDefaultPosition,wxDefaultSize,*/
    wxSUNKEN_BORDER |wxLC_REPORT, wxDefaultValidator, "list2");
    //sort-direction for the Search History List Box
    lsmasks_sort = 0;
    //sort-column: for the Search History List Box
    lsmasks_sort_column = 1;
    // Outline of the Search History List Box
    DEFTEXT(spw1sub2, 13, 0, wxBLACK, wxWHITE);
    // Search History List Box
    wxListItem ic2;
    ic2.m_mask = wxLIST_MASK_TEXT | wxLIST_MASK_IMAGE;
    ic2.m_image = - 1;
    // Colors of the Search History List Box
    lsmasks->SetTextColour( *wxBLUE);
    lsmasks->SetBackgroundColour(DARK_WHITE);
    lsmasks->SetName("History");
    // Colums of the Search History List Box
    column = 0;
    ic2.m_text = _("Results");
    lsmasks->InsertColumn(column, ic2);
    lsmasks->SetColumnWidth(column, 50);
    ic2.m_text = _("Name");
    lsmasks->InsertColumn(++column, ic2);
    lsmasks->SetColumnWidth(column, 150);
    ic2.m_text = _("L/G");
    lsmasks->InsertColumn(++column, ic2);
    lsmasks->SetColumnWidth(column, 40);
    ic2.m_text = _("Type");
    lsmasks->InsertColumn(++column, ic2);
    lsmasks->SetColumnWidth(column, 40);
    ic2.m_text = _("min. Size");
    lsmasks->InsertColumn(++column, ic2);
    lsmasks->SetColumnWidth(column, 60);
    ic2.m_text = _("max. Size");
    lsmasks->InsertColumn(++column, ic2);
    lsmasks->SetColumnWidth(column, 60);
    ic2.m_text = _("Availability");
    lsmasks->InsertColumn(++column, ic2);
    lsmasks->SetColumnWidth(column, 70);
    ic2.m_text = _("Extension");
    lsmasks->InsertColumn(++column, ic2);
    lsmasks->SetColumnWidth(column, 60);
    SETCOLIMAGE(lsmasks, lsmasks_sort_column, lsmasks_sort);
    sb006s->Add(lsmasks, 3, wxGROW, 0);
    //
    spw1sub1->SetAutoLayout(TRUE);
    spw1sub1->SetSizer(sb005s);
    sb005s->Fit(spw1sub1);
    sb005s->SetSizeHints(spw1sub1);
    spw1sub2->SetAutoLayout(TRUE);
    spw1sub2->SetSizer(sb006s);
    sb006s->Fit(spw1sub2);
    sb006s->SetSizeHints(spw1sub2);
    spw1->SplitVertically(spw1sub1, spw1sub2);
    row4 = new wxBoxSizer(wxHORIZONTAL);
    sdgauge[0] = new wxGauge(this, 15001, 100, wxDefaultPosition, wxSize( - 1, 8), 0);
    row4->Add(sdgauge[0], 2, wxGROW, 0);
    wxBoxSizer *root = new wxBoxSizer(wxVERTICAL);
    root->Add(row1, 0, wxALL |wxGROW, 4);
#if 0
    wxALL = border(4), wxGROW = horizonal stretchable:
#endif
    root->Add(row2, 0, wxALL |wxGROW, 4);
#if 0
    (f2 = 1) = horizontal stretchable, (f2 = 2) = vertical stretchable:
#endif
    root->Add(row3, 3, wxALL |wxGROW, 4);
#if 0
    (f2 = 1) = horizontal stretchable, (f2 = 2) = vertical stretchable:
#endif
    root->Add(row4, 0, wxGROW, 0);
    this->SetAutoLayout(TRUE);
    this->SetSizer(root);
    root->Fit(this);
    root->SetSizeHints(this);
    DEFTEXT(this, 13, 0, wxGREEN, wxWHITE);
    root->Show(this, TRUE);
    spw1->SetSashPosition(700, TRUE);
    lsresults->Connect(wxID_ANY, wxEVT_RIGHT_DOWN, SDMOUSEEVT::PopupSearchResults);
    lsmasks->Connect(wxID_ANY, wxEVT_RIGHT_DOWN, SDMOUSEEVT::PopupSearchMasks);
    this->Connect(11001, wxEVT_COMMAND_TEXT_ENTER, (wxObjectEventFunction) &CSearchDlg::InputName);
    this->Connect(11002, wxEVT_COMMAND_TEXT_ENTER, (wxObjectEventFunction) &CSearchDlg::InputMinSize);
    this->Connect(11003, wxEVT_COMMAND_TEXT_ENTER, (wxObjectEventFunction) &CSearchDlg::InputMaxSize);
    this->Connect(11006, wxEVT_COMMAND_TEXT_ENTER, (wxObjectEventFunction) &CSearchDlg::InputAvailability);
    this->Connect(11007, wxEVT_COMMAND_TEXT_ENTER, (wxObjectEventFunction) &CSearchDlg::InputExtension);
#if 0
    this->Connect(11008, wxEVT_COMMAND_TEXT_ENTER, (wxObjectEventFunction) &CSearchDlg::InputED2K);
#endif
    this->Connect(12001, wxEVT_COMMAND_BUTTON_CLICKED, (wxObjectEventFunction) &CSearchDlg::ButtonStart);
    this->Connect(12002, wxEVT_COMMAND_BUTTON_CLICKED, (wxObjectEventFunction) &CSearchDlg::ButtonMore);
    this->Connect(12003, wxEVT_COMMAND_BUTTON_CLICKED, (wxObjectEventFunction) &CSearchDlg::ButtonCancel);
    this->Connect(12004, wxEVT_COMMAND_BUTTON_CLICKED, (wxObjectEventFunction) &CSearchDlg::ButtonDownload);
    this->Connect(12005, wxEVT_COMMAND_BUTTON_CLICKED, (wxObjectEventFunction) &CSearchDlg::ButtonSaveTabs);
    this->Connect(12006, wxEVT_COMMAND_BUTTON_CLICKED, (wxObjectEventFunction) &CSearchDlg::ButtonLoadTabs);
    this->Connect(12007, wxEVT_COMMAND_BUTTON_CLICKED, (wxObjectEventFunction) &CSearchDlg::ButtonClearAll);
    this->Connect(12008, wxEVT_COMMAND_BUTTON_CLICKED, (wxObjectEventFunction) &CSearchDlg::ButtonReset);
    this->Connect(12009, wxEVT_COMMAND_BUTTON_CLICKED, (wxObjectEventFunction) &CSearchDlg::ButtonStartLink);
#if 0
    this->Connect(13001, wxEVT_COMMAND_CHOICE_SELECTED, (wxObjectEventFunction) &CSearchDlg::ChoiceType);
    this->Connect(13002, wxEVT_COMMAND_CHOICE_SELECTED, (wxObjectEventFunction) &CSearchDlg::ChoiceMethod);
    this->Connect(13001, wxEVT_COMMAND_CHOICE_SELECTED, (wxObjectEventFunction) NULL);
    this->Connect(13002, wxEVT_COMMAND_CHOICE_SELECTED, (wxObjectEventFunction) NULL);
#endif
    this->Connect(14001, wxEVT_COMMAND_LIST_COL_CLICK, SDLISTEVT::ListSortSearchResults);
    this->Connect(14001, wxEVT_COMMAND_LIST_ITEM_ACTIVATED, (wxObjectEventFunction) &CSearchDlg::ButtonDownload);
    this->Connect(14002, wxEVT_COMMAND_LIST_ITEM_SELECTED, SDLISTEVT::ListSelectedSearchMask);
    this->Connect(14002, wxEVT_COMMAND_LIST_COL_CLICK, SDLISTEVT::ListSortSearchMasks);
    this->Connect(17001, wxEVT_COMMAND_MENU_SELECTED, (wxObjectEventFunction) &CSearchDlg::ButtonDownload);
    this->Connect(17002, wxEVT_COMMAND_MENU_SELECTED, (wxObjectEventFunction) &CSearchDlg::SearchResultsRemoveSelected);
    this->Connect(17003, wxEVT_COMMAND_MENU_SELECTED, (wxObjectEventFunction) &CSearchDlg::SearchResultsRemoveAll);
    this->Connect(17004, wxEVT_COMMAND_MENU_SELECTED, (wxObjectEventFunction) &CSearchDlg::SearchResultsCloseThisRL);
    this->Connect(17005, wxEVT_COMMAND_MENU_SELECTED, (wxObjectEventFunction) &CSearchDlg::SearchResultsCloseAllRL);
    this->Connect(17051, wxEVT_COMMAND_MENU_SELECTED, (wxObjectEventFunction) &CSearchDlg::SearchResultsCloseThisSM);
    this->Connect(17052, wxEVT_COMMAND_MENU_SELECTED, (wxObjectEventFunction) &CSearchDlg::SearchResultsCloseAllSM);
    this->Connect(17097, wxEVT_COMMAND_MENU_SELECTED, (wxObjectEventFunction) &CSearchDlg::ButtonSaveTabs);
    this->Connect(17098, wxEVT_COMMAND_MENU_SELECTED, (wxObjectEventFunction) &CSearchDlg::ButtonLoadTabs);
    this->Connect(17099, wxEVT_COMMAND_MENU_SELECTED, (wxObjectEventFunction) &CSearchDlg::ButtonClearAll);
    this->Connect(ID_SEARCHTIMER, wxEVT_TIMER, (wxObjectEventFunction)(wxTimerEventFunction) &CSearchDlg::OnTimer);
    //more:
    sdbutton[1]->Enable(false);
    //cancel:
    sdbutton[2]->Enable(false);
    ButtonClearAll(nullCevent);
    globsearch = false;
    glspacket = NULL;
    global_search_timer = NULL;
    SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWFRAME));
}

CSearchDlg::~CSearchDlg()
{
    // Let's remove the lists.

}

void CSearchDlg::OnTimer(wxTimerEvent &evt)
{
    srtab_refresh = 0;
    CServer *toask = theApp.serverlist->GetNextSearchServer();
    if (theApp.serverconnect->IsConnected())
    {
        if (toask == theApp.serverlist->GetServerByAddress(
        theApp.serverconnect->GetCurrentServer()->GetAddress(),
        theApp.serverconnect->GetCurrentServer()->GetPort()))
        {
            toask = theApp.serverlist->GetNextSearchServer();
        }
    }
    else
    {
        toask = theApp.serverlist->GetNextSearchServer();
    }
    if (toask && theApp.serverlist->GetServerCount() - 1 != servercount)
    {
        servercount++;
        if (toask->GetIP())
        {
            file_udpserverip = toask->GetIP();
            if (toask->GetUDPFlags() &SRV_UDPFLG_EXT_GETFILES)
            {
#ifdef __XMULE2__
                glspacket->M_opcode = OP_GLOBSEARCHREQ2;
#else
                glspacket->opcode = OP_GLOBSEARCHREQ2;
#endif
            }
            else
            {
#ifdef __XMULE2__
                glspacket->M_opcode = OP_GLOBSEARCHREQ;
#else
                glspacket->opcode = OP_GLOBSEARCHREQ;
#endif
            }
//            printf("SendUDPPacket for UDPsearch to %s:%d\n", toask->GetAddress(), toask->GetPort());
#ifdef __XMULE2__
            theApp.serverconnect->SendServerUDPPacket(glspacket, toask, false);
#else
            theApp.serverconnect->SendUDPPacket(glspacket, toask, false);
#endif
            sdgauge[0]->SetValue(sdgauge[0]->GetValue() + 1);
        }
    }
    else
    {
        ButtonCancel(nullCevent);
    }
}

bool CSearchDlg::CheckTabNameExists(wxString searchString)
{
    //dummy
    return false;
}

void CSearchDlg::CreateNewTab(wxString searchString, wxUint32 nSearchID)
{
    //dummy
}

void pdump(char *info, unsigned char *pck, int pckl)
{
#if defined(__DEBUG__)
    int z = 0;
    printf("%s: packetlength=%d: ", info, pckl);
    while (z < pckl)
    {
        if (! (z%32))
        {
            printf("\n%4x  ", z);
        }
        printf("%2x ", pck[z]);
        ++z;
    }
    printf("\n");
#endif
}

void get_md4(unsigned char *&md4, unsigned char *&pck, int &pcksize)
{
    if (pcksize > 15)
    {
        int i = 0;
        while (i < 16)
        {
            md4[i] = pck[i];
            ++i;
        }
        pck += 16;
        pcksize -= 16;
    }
    else
    {
        pcksize = 0;
    }
}

void get_ip(wxUint32 &ip, unsigned char *&pck, int &pcksize)
{
    if (pcksize > 3)
    {
        int i = 0;
        while (i < 4)
        {
            ip = (ip << 8) + pck[i];
            ++i;
        }
        pck += 4;
        pcksize -= 4;
    }
    else
    {
        pcksize = 0;
    }
}

void get_po(wxUint32 &port, unsigned char *&pck, int &pcksize)
{
    if (pcksize > 1)
    {
        int i = 0;
        while (i < 2)
        {
            port = (port << 8) + pck[1 - i];
            ++i;
        }
        pck += 2;
        pcksize -= 2;
    }
    else
    {
        pcksize = 0;
    }
}

void get_tagc(wxUint32 &tagcounter, unsigned char *&pck, int &pcksize)
{
    if (pcksize > 3)
    {
        int i = 0;
        while (i < 4)
        {
            tagcounter += (tagcounter << 8) + (wxChar) pck[3 - i];
            ++i;
        }
        pck += 4;
        pcksize -= 4;
    }
    else
    {
        pcksize = 0;
    }
}

void get_tag(unsigned char *&pck, int &pcksize)
{
    int i = 0, metatagtype, sptaglength = 0, sptagtype = 0, sptagtype2 = 0, metatag_stringlength;
    unsigned char *pcklast;
    int pcksizelast;
    //printf("get_tag-start\n");
    if (pcksize)
    {
        metatagtype = pck[0];
        if (metatagtype > 0 &&metatagtype < 8)
        {
            if (pcksize > 3)
            {
                pcklast = pck;
                pcksizelast = pcksize;
                sptaglength = pck[1] + (pck[2] << 8);
                sptagtype = pck[3];
                sptagtype2 = pck[4];
                pck += 3;
                pcksize -= 3;
                pck += sptaglength;
                pcksize -= sptaglength;
                if (sptaglength < pcksize)
                {
                    switch (metatagtype)
                    {
                        //hash:
                    case 1:
#if defined(__DEBUG__)
                        printf("\nmtagtype=%d sptagl=%d sptagt=%d \n", metatagtype, sptaglength, sptagtype);
                        pdump("CSDLG::SearchEnd mtag-1: ", pcklast, pcksizelast);
#endif
                        break;
                        //string:
                    case 2:
                        if (pcksize > 1)
                        {
                            metatag_stringlength = pck[0] + (pck[1] << 8);
                            pck += 2;
                            pcksize -= 2;
                            if (pcksize >= metatag_stringlength)
                            {
                                switch (sptagtype)
                                {
                                    //(file)name:
                                case 1:
                                    file_name = "";
                                    while (i < metatag_stringlength &&i < pcksize)
                                    {
                                        file_name += (wxChar) pck[i];
                                        ++i;
                                    }
                                    break;
                                    //(file):
                                case 3:
                                    file_typename = "";
                                    while (i < metatag_stringlength &&i < pcksize)
                                    {
                                        file_typename += (wxChar) pck[i];
                                        ++i;
                                    }
                                    break;
                                    //(file)extension:
                                case 4:
                                    file_extension = "";
                                    while (i < metatag_stringlength &&i < pcksize)
                                    {
                                        file_extension += (wxChar) pck[i];
                                        ++i;
                                    }
                                    break;
                                    //Artist+Album:
                                case 65:
                                    switch (sptagtype)
                                    {
                                        //Album:
                                    case 108:
                                        file_album = "";
                                        while (i < metatag_stringlength &&i < pcksize)
                                        {
                                            file_album += (wxChar) pck[i];
                                            ++i;
                                        }
                                        break;
                                        //Artist:
                                    case 114:
                                        file_artist = "";
                                        while (i < metatag_stringlength &&i < pcksize)
                                        {
                                            file_artist += (wxChar) pck[i];
                                            ++i;
                                        }
                                        break;
                                        //unknown:
                                    default:
#if defined(__DEBUG__)
                                        printf("\nA+mtagtype=%d sptagl=%d sptagt=%d \n", metatagtype, sptaglength, sptagtype);
                                        pdump("CSDLG::SearchEnd mtag-1: ", pcklast, pcksizelast);
#endif
                                        break;
                                    }
                                    break;
                                    //Folder:
                                case 70:
                                    file_folder = "";
                                    while (i < metatag_stringlength &&i < pcksize)
                                    {
                                        file_folder += (wxChar) pck[i];
                                        ++i;
                                    }
                                    break;
                                    //Titel:
                                case 84:
                                    file_title = "";
                                    while (i < metatag_stringlength &&i < pcksize)
                                    {
                                        file_title += (wxChar) pck[i];
                                        ++i;
                                    }
                                    break;
                                    //div3/codec:
                                case 99:
                                    file_codec = "";
                                    while (i < metatag_stringlength &&i < pcksize)
                                    {
                                        file_codec += (wxChar) pck[i];
                                        ++i;
                                    }
                                    break;
                                    //1:42/length:
                                case 108:
                                    file_length = "";
                                    while (i < metatag_stringlength &&i < pcksize)
                                    {
                                        file_length += (wxChar) pck[i];
                                        ++i;
                                    }
                                    break;
                                default:
#if defined(__DEBUG__)
                                    printf("stag-string %d=%x: %s\n", sptagtype, sptagtype, pck);
                                    printf("mtagtype    %d sptagl=%d sptagt=%d \n", metatagtype, sptaglength, sptagtype);
                                    printf("----------unknown mtag2-%d: ", sptagtype);
                                    pdump("CSDLG::SearchEnd: ", pcklast, pcksizelast);
#endif
                                    break;
                                }
                                pcksize -= i;
                                pck += i;
                            }
                            else
                            {
                                pcksize = 0;
                            }
                        }
                        else
                        {
                            pcksize = 0;
                        }
                        break;
                        //dword:
                    case 3:
                        if (pcksize >= 4)
                        {
                            switch (sptagtype)
                            {
                                //(file)size:
                            case 2:
                                file_size = pck[0] + (pck[1] << 8) + (pck[2] << 16) + (pck[3] << 24);
                                break;
                                //port:
                            case 0x0f:
                                file_clientport = pck[0] + (pck[1] << 8) + (pck[2] << 16) + (pck[3] << 24);
                                break;
                                //availability:
                            case 0x15:
                                file_availability = pck[0] + (pck[1] << 8) + (pck[2] << 16) + (pck[3] << 24);
                                break;
                                //unknown dword:
                            case 0x30:
                                break;
                                //bitrate:
                            case 98:
                                file_bitrate = pck[0] + (pck[1] << 8) + (pck[2] << 16) + (pck[3] << 24);
                                break;
                            default:
#if defined(__DEBUG__)
                                printf("\nmtagtype=%d sptagl=%d sptagt=%d \n", metatagtype, sptaglength, sptagtype);
                                printf("----------unknown mtag3-%d: ", sptagtype);
                                pdump("CSDLG::SearchEnd: ", pcklast, pcksizelast);
#endif
                                break;
                            }
                            pck += 4;
                            pcksize -= 4;
                        }
                        else
                        {
                            pcksize = 0;
                        }
                        break;
                        //float:
                    case 4:
#if defined(__DEBUG__)
                        printf("\nmtagtype=%d sptagl=%d sptagt=%d \n", metatagtype, sptaglength, sptagtype);
                        pdump("CSDLG::SearchEnd mtag-4: ", pcklast, pcksizelast);
#endif
                        break;
                        //bool:
                    case 5:
#if defined(__DEBUG__)
                        printf("\nmtagtype=%d sptagl=%d sptagt=%d \n", metatagtype, sptaglength, sptagtype);
                        pdump("CSDLG::SearchEnd mtag-5: ", pcklast, pcksizelast);
#endif
                        break;
                        //bool array:
                    case 6:
#if defined(__DEBUG__)
                        printf("\nmtagtype=%d sptagl=%d sptagt=%d \n", metatagtype, sptaglength, sptagtype);
                        pdump("CSDLG::SearchEnd mtag-6: ", pcklast, pcksizelast);
#endif
                        break;
                        //blob:
                    case 7:
#if defined(__DEBUG__)
                        printf("\nmtagtype=%d sptagl=%d sptagt=%d \n", metatagtype, sptaglength, sptagtype);
                        pdump("CSDLG::SearchEnd mtag-7: ", pcklast, pcksizelast);
#endif
                        break;
                    }
                    // End of switch(metatagtype)
                }
                else
                {
                    pcksize = 0;
                }
                // End of if(sptaglength < pcksize)
            }
            else
            {
                pcksize = 0;
            }
            // End of if(pcksize>3)
        }
        else
        {
            switch (metatagtype)
            {
                //undefined:
            case 0:
                break;
                //unknown:
            default:
#if defined(__DEBUG__)
                printf(" unknown metatag-type=%d in srlist ", metatagtype);
                printf("\nmtagtype=%d sptagl=%d sptagt=%d \n", metatagtype, sptaglength, sptagtype);
                pdump("CSDLG::SearchEnd mtag-8: ", pcklast, pcksizelast);
#endif
                ++pck;
                --pcksize;
                break;
            }
        }
        // End of if(metatagtype > 0 && metatagtype < 8)
    }
    else
    {
#if defined(__DEBUG__)
        printf(" byte-shortage in searchresult-list \n");
#endif
    }
    // End of if(pcksize):
}

void put_tag(unsigned char *&slistentry_ed2k, int &startpos, int tagtype)
{
    int i = 0, c;
    switch (tagtype)
    {
        //Byte17..20:ip:
    case 0:
        startpos = 16;
        while (i < 4)
        {
            slistentry_ed2k[3 - i + startpos] = file_clientip &255;
            file_clientip = file_clientip >> 8;
            ++i;
        }
        startpos += 4;
        break;
        //Byte21..22:port:
    case 1:
        startpos = 20;
        while (i < 2)
        {
            slistentry_ed2k[startpos] = file_clientport &255;
            file_clientport = file_clientport >> 8;
            ++i;
            ++startpos;
        }
        break;
        //file_name:
    case 2:
        startpos = 26;
        slistentry_ed2k[startpos] = 2;
        slistentry_ed2k[startpos + 1] = 1;
        slistentry_ed2k[startpos + 2] = 0;
        slistentry_ed2k[startpos + 3] = 1;
        startpos += 4;
        while (i < (int) file_name.Len())
        {
            slistentry_ed2k[startpos + 2 + i] = ((const char *) file_name)[i];
            ++i;
        }
        slistentry_ed2k[startpos] = i;
        slistentry_ed2k[startpos + 2] = 0;
        startpos += i + 2;
        break;
        //file_size:
    case 3:
        slistentry_ed2k[startpos] = 3;
        slistentry_ed2k[startpos + 1] = 1;
        slistentry_ed2k[startpos + 2] = 0;
        slistentry_ed2k[startpos + 3] = 2;
        startpos += 4;
        while (i < 4)
        {
            slistentry_ed2k[startpos + 1] = file_size &255;
            file_size = file_size >> 8;
            ++i;
            ++startpos;
        }
        break;
        //file_availability:
    case 4:
        slistentry_ed2k[startpos] = 3;
        slistentry_ed2k[startpos + 1] = 1;
        slistentry_ed2k[startpos + 2] = 0;
        slistentry_ed2k[startpos + 3] = 15;
        startpos += 4;
        while (i < 4)
        {
            slistentry_ed2k[startpos] = file_availability &255;
            file_availability = file_availability >> 8;
            ++i;
            ++startpos;
        }
        break;
        //Byte01..16:file_id=md4_hash:
    case 6:
        startpos = 0;
        while (startpos < 16)
        {
            c = ((const char *) file_id) [i];
            ++i;
            if (c >= 'a' &&c <= 'f')
            {
                slistentry_ed2k[startpos] = c - 'a' + 10;
            }
            else if(c >= 'A' &&c <= 'F')
            {
                slistentry_ed2k[startpos] = c - 'A' + 10;
            }
            else if(c >= '0' &&c <= '9')
            {
                slistentry_ed2k[startpos] = c - '0';
            }
            c = ((const char *) file_id) [i];
            ++i;
            slistentry_ed2k[startpos] = slistentry_ed2k[startpos] << 4;
            if (c >= 'a' &&c <= 'f')
            {
                slistentry_ed2k[startpos] += c - 'a' + 10;
            }
            else if(c >= 'A' &&c <= 'F')
            {
                slistentry_ed2k[startpos] += c - 'A' + 10;
            }
            else if(c >= '0' &&c <= '9')
            {
                slistentry_ed2k[startpos] += c - '0';
            }
            ++startpos;
            // End of while(startpos < 16):
        }
        break;
        //file_tagc(tagcounter):
    case 99:
        startpos = 22;
        while (i < 4)
        {
            slistentry_ed2k[startpos] = file_tagc &255;
            file_tagc = file_tagc >> 8;
            ++i;
            ++startpos;
        }
        break;
        // End of switch(tagtype):
    }
}

void CSearchDlg::ShowSearchResults()
{
    if (srtab_refresh)
    {
        wxString linebuffer;
        wxListItem item;
        item.m_mask = wxLIST_MASK_TEXT;
        unsigned int startpos, endpos, column;
        int itemindex;
        // Item (Line) Counter
        int i = 0;
        // Help-variable for different colors depending on file availabitily
        int col_dummy = 0;
        // Variable for the Availability of the current file
        long int availability;
        if (srtab_deep < 2)
        {
            srtab_lock = 1;
            (void) lsresults->DeleteAllItems();
            itemindex = smasknext[smaskcurrent];
            if (itemindex > 0)
            {
                // Show Search Results
                do
                {
                    // We need the availibility of this file
                    startpos = 0;
                    endpos = 0;
                    column = 0;
                    while (endpos < sresultdefs[itemindex].Len())
                    {
                        switch (((const char *) sresultdefs[itemindex]) [endpos])
                        {
                        case '|':
                            switch (column)
                            {
                            case 4: if(endpos > startpos)
                                {
                                    linebuffer = wxString::Format("%s", (const char *) sresultdefs[itemindex].Mid(startpos, endpos - startpos));
                                }
                                linebuffer.ToLong( &availability);
                            default:++column;
                                break;
                            }
                            startpos = endpos + 1;
                            break;
                        default:
                            break;
                        }
                        ++endpos;
                    }
                    // Show 1 Search Result
                    startpos = 0;
                    endpos = 0;
                    column = 0;
                    while (endpos < sresultdefs[itemindex].Len())
                    {
                        switch (((const char *) sresultdefs[itemindex]) [endpos])
                        {
                        case '|':
                            switch (column)
                            {
                                //column
                                //clientip:
                            case 0:
                                //clientport:
                            case 1: ++column;
                                break;
                            case 2:
                                if (endpos > startpos)
                                {
                                    if (startpos <= sresultdefs[itemindex].Len())
                                    {
                                        if (endpos <= sresultdefs[itemindex].Len())
                                        {
                                            linebuffer = wxString::Format("%s", (const char *)
                                            sresultdefs[itemindex].Mid(startpos, endpos - startpos));
                                        }
                                    }
                                }
                                else
                                {
                                    linebuffer.Printf(wxT(" "));
                                }
                                // Set Text Color Depending on File Availability
                                item.SetId(i);
                                if (lsresults->GetItem(item))
                                {
                                    if (availability <= 16)
                                    {
                                        col_dummy = availability - 1;
                                        if (col_dummy < 0)
                                        {
                                            col_dummy = 0;
                                        }
                                    }
                                    else
                                    {
                                        col_dummy = 17 + ((availability - 16) / 8);
                                        if (col_dummy > 31)
                                        {
                                            col_dummy = 31;
                                        }
                                    }
                                    item.SetTextColour( *colorarray[col_dummy]);
                                }
                                item.SetColumn(column++ - 2);
                                item.SetText(linebuffer);
                                (void) lsresults->InsertItem(item);
                                lsresults->SetItemData(i, itemindex);
                                break;
                            default:
                                if (endpos > startpos)
                                {
                                    //printf("searchresults %d %d %d %d %s\n",column,i,startpos,endpos,
                                    //(const char *)sresultdefs[itemindex].Mid(startpos,endpos-startpos));
                                    linebuffer.Printf(sresultdefs[itemindex].Mid(startpos, endpos - startpos));
                                }
                                else
                                {
                                    linebuffer.Printf(wxT(" "));
                                }
                                item.SetColumn(column++ - 2);
                                item.SetText(linebuffer);
                                lsresults->SetItem(item);
                                break;
                            }
                            // End of switch(column)
                            startpos = endpos + 1;
                            break;
                        default:
                            break;
                        }
                        // End of switch(((const char *) sresultdefs[itemindex]) [endpos])
                        ++endpos;
                    }
                    // End of while(((const char *) sresultdefs[itemindex]) [endpos])
                    itemindex = sresultnext[itemindex];
                    //next item:
                    ++i;
                }
                //End of do
                while ((int) itemindex != smasknext[smaskcurrent]);
            }
            // End of if(itemindex > 0)
            srtab_lock = 0;
            ShowSearchMasks();
        }
        // End of if(srtab_deep < 2)
    }
}

void CSearchDlg::ShowSearchMasks()
{
    wxString linebuffer, itemstring;
    int i = 0, c, startpos, endpos, itemindex = 0, column;
    srtab_lock = 2;
    (void) lsmasks->DeleteAllItems();
    while (itemindex <= smaskhighest)
    {
        if (smasknext[itemindex] != 0)
        {
            startpos = 0;
            endpos = 0;
            column = 0;
            itemstring = smaskdefs[itemindex];
            while (endpos < (int) itemstring.Len())
            {
                //show line
                c = ((const char *) itemstring) [endpos];
                switch (c)
                {
                    //show next item
                case '|':
                    switch (column)
                    {
                        //column
                    case 0:
                        if (endpos > startpos)
                        {
                            //itemindex);:
                            linebuffer.Printf(wxT("%d"), smaskresults[itemindex]);
                        }
                        else
                        {
                            linebuffer.Printf(wxT(" "));
                        }
                        if (itemindex == smaskcurrent)
                        {
                            //No.:
                            (void) lsmasks->InsertItem(i, linebuffer, lsresults_sort);
                        }
                        else
                        {
                            //No.:
                            (void) lsmasks->InsertItem(i, linebuffer, - 1);
                        }
                        lsmasks->SetItemData(i, itemindex);
                    default:
                        if (endpos > startpos)
                        {
                            linebuffer.Printf(itemstring.Mid(startpos, endpos - startpos));
                        }
                        else
                        {
                            linebuffer.Printf(wxT(" "));
                        }
                        lsmasks->SetItem(i,++column, linebuffer);
                        smaskindex[itemindex] = i;
                        break;
                    }
                    startpos = endpos + 1;
                    break;
                default:
                    break;
                }
                ++endpos;
            }
            ++i;
        }
        //next item:
        ++itemindex;
    }
    srtab_lock = 0;
}

void CSearchDlg::SearchEnd(char *packet, wxUint32 packetsize, wxUint32 nServerIP, wxUint16 nServerPort)
{
    wxString linebuffer;
    wxString slistentry;
    unsigned char *pck, *pcklast;
    int lsmaskr = 0, pcksize, i;
    ++srtab_deep;
    pck = (unsigned char *) packet;
    pcksize = packetsize;
    if (!nServerPort)
    {
        //tcp-search->fileinfo-number
        pcksize -= 4;
        pck += 4;
    }
    lsmaskr = smaskresults[smaskcurrent];
    if (!canceld)
    {
        file_md4 = (unsigned char *) malloc(20);
        while (pcksize > 22)
        {
            //get fileinfo from searchlist
            file_clientip = 0;
            file_clientport = 0;
            file_tagc = 0;
            file_size = 0;
            file_availability = 0;
            //0=any:
            file_type = 0;
            file_bitrate = 0;
            file_name = "";
            file_album = "";
            file_artist = "";
            file_codec = "";
            file_folder = "";
            file_length = "";
            file_title = "";
            file_extension = "";
            file_typename = "";
            file_id = "";
            file_udpserverip = nServerIP;
            file_udpserverport = nServerPort;
            pcklast = pck;
            //md4-hash:
            get_md4(file_md4, pck, pcksize);
            //ip-source:
            get_ip(file_clientip, pck, pcksize);
            //port-source:
            get_po(file_clientport, pck, pcksize);
            //tagcounter:
            get_tagc(file_tagc, pck, pcksize);

            for (i = 0 ; i < 16 ; ++i)
            {
                file_id += wxString::Format("%02x", file_md4[i]);
            }

            while (file_tagc)
            {
                //tagcounter:
                if (pcksize) get_tag(pck, pcksize);
                --file_tagc;
            }

            if (file_name.Len())
            {
                file_type = GetFTIDbyName(file_name);
                slistentry = wxString::Format("%u", file_clientip);
                slistentry += "|";
                slistentry += wxString::Format("%d", file_clientport);
                slistentry += "|";
                slistentry += file_name;
                slistentry += "|";
                slistentry += wxString::Format("%u", file_size);
                slistentry += "|";
                slistentry += wxString::Format("%d", file_availability);
                slistentry += "|";
                slistentry += type[file_type];
                slistentry += "|";
                slistentry += file_id;
                slistentry += "|";
                slistentry += file_artist;
                slistentry += "|";
                slistentry += file_album;
                slistentry += "|";
                slistentry += file_title;
                slistentry += "|";
                slistentry += file_length;
                slistentry += "|";
                slistentry += wxString::Format("%d", file_bitrate);
                slistentry += "|";
                slistentry += file_codec;
                slistentry += "|";
                slistentry += file_folder;
                slistentry += "|";
                slistentry += wxString::Format("%08x", file_udpserverip);
                slistentry += "|";
                slistentry += wxString::Format("%d", file_udpserverport);
                slistentry += "|";
#if 0
                //creation of a clean ed2k-fileitem - test for ftp&http-protokoll
                file_tagc = 2;
                slp = 0;
                put_tag(sed2kentry, slp, 6);
                //file_id
                put_tag(sed2kentry, slp, 0);
                //file_clientip
                put_tag(sed2kentry, slp, 1);
                //file_clientport
                put_tag(sed2kentry, slp, 99);
                //file_tagc
                put_tag(sed2kentry, slp, 2);
                //file_name
                put_tag(sed2kentry, slp, 3);
                //file_size
                put_tag(sed2kentry, slp, 4);
                //file_availability
                p.dump("original", (unsigned char *) pcklast, (long) pck - (long) pcklast);
                p.dump("put_tag", (unsigned char *) sed2kentry, slp);
#endif
                if (!sdchoice[0]->GetSelection() || (sdchoice[0]->GetSelection() == (int) file_type))
                {
                    // For Type-Selected-Search
                    insertresult(smaskcurrent, slistentry);
                }
            }
            if (nServerPort)
            {
                //UDP-Searchresults
                if (pcksize >= 2)
                {
                    if (pck[0] == OP_EDONKEYPROT)
                    {
                        if (pck[1] == OP_GLOBSEARCHRES)
                        {
                            //udp-searchresult-separator:
                            pck += 2;
                            pcksize -= 2;
                        }
                    }
                }
            }
        }
        free(file_md4);
        linebuffer.Printf("%d", smaskresults[smaskcurrent]);
        lsmasks->SetItem(smaskindex[smaskcurrent], 0, linebuffer);
        if (!globsearch)
        {
            m_timer.Stop();
            sdbutton[0]->Enable(true);
            sdbutton[2]->Enable(false);
            sdgauge[0]->SetValue(0);
            global_search_timer = 0;
            globsearch = false;
            canceld = true;
        }
        else
        {
            m_timer.Start(750);
            global_search_timer = (unsigned int *) 1;
        }
    }
    if (lsmaskr != smaskresults[smaskcurrent])
    {
        if (!srtab_lock)
        {
            ShowSearchResults();
        }
    }
    srtab_deep--;
}

wxString CSearchDlg::CreateWebQuery()
{
    wxString query;
    query = "http://www.filedonkey.com/fdsearch/index.php?media=";
    //switch (typebox.GetCurSel())
    int x = 1;
    switch (x)
    {
    case 1:
        query += "Audio";
        break;
    case 2:
        query += "Video";
        break;
    case 3:
        query += "Pro";
        break;
    default:
        break;
    }
#if 0
    //wxString tosearch;
    GetDlgItem(IDC_SWEB)->GetWindowText(tosearch);
    tosearch = wxString(URLEncode(tosearch) .GetData());
    tosearch.Replace("%20", "+");
    query += "&pattern=";
    query += tosearch;
    query += "&action=search&name=FD-Search&op=modload&file=index&requestby=amule";
#endif
    return query;
}

