//---------------------------------------------------------------------------
#include <vcl\vcl.h>
#pragma hdrstop
#include "searchfrm.h"
#include <listkey.h>
#include "mainfrm.h"
#include <regex.h>
#include "RangeMaintFrm.h"
#include <unicode.hpp>
#include <unicodertf.h>
#include "rtfhintfrm.h"
#include <localemgr.h>
#include "vrslstfrm.h"
//---------------------------------------------------------------------------
#pragma resource "*.dfm"
TsearchForm *searchForm;
//---------------------------------------------------------------------------
__fastcall TsearchForm::TsearchForm(TComponent* Owner)
: TForm(Owner) {
initializing = true;
pvrtf = new TRxRichEditX(this);
pvrtf->Parent = plPreview;
pvrtf->Align = alClient;
pvrtf->ScrollBars = ssVertical;
pvrtf->ReadOnly = true;
// pvrtf->PopupMenu = PopupMenu2;
// SearchText = 0;
// if (!SearchText) {
SearchTextOld->Visible = false;
SearchText = new TTntComboBox(this);
SearchText->Parent = Panel3;
SearchText->Align = alClient;
SearchText->ParentFont = false;
SearchText->Font->Size = 12;
// }
// mod->Disp(*displays.insert(displays.begin(), new RTFDisp(newrtf)));
// mod->setKey(DefaultVSKey);
// return 0;
target = 0;
}
//---------------------------------------------------------------------------
void __fastcall TsearchForm::searchBtnClick(TObject *Sender)
{
// ModMap::iterator target;
class TWaitCursor {
public:
TWaitCursor() : oldc(Screen->Cursor) { Screen->Cursor = crHourGlass; }
~TWaitCursor() { Screen->Cursor = oldc; }
private:
TCursor oldc;
} wait; // show hourglass
if (!SearchText->Text.Length())
return;
int index = SearchText->Items->IndexOf(SearchText->Text);
SearchText->Items->Insert(0, SearchText->Text);
if (index >= 0)
SearchText->Items->Delete(index+1);
SearchText->ItemIndex = 0;
Caption = "";
if (target) {
Caption = _tr("Searching");
Caption += (AnsiString)" [ " + (AnsiString)target->Description() + (AnsiString)" (" + (AnsiString)target->Name() + (AnsiString)") ]...";
resultsLV->Items->Clear();
int searchType;
switch (searchTypeGroup->ItemIndex) {
case 0: searchType = -2; break;
case 1: searchType = -1; break;
case 2: searchType = 0; break;
}
int searchOptions = (caseSensitiveCkBx->Checked) ? 0 : REG_ICASE;
SWKey *scope = 0;
switch (scopeGroup->ItemIndex) {
case 2:
if (ComboBox1->ItemIndex < 0)
results = VerseKey().ParseVerseList(ComboBox1->Text.c_str(), "", true);
else {
TCustomRange *rs = (TCustomRange *)ComboBox1->Items->Objects[ComboBox1->ItemIndex];
results = VerseKey().ParseVerseList(rs->text.c_str(), "", true);
}
case 1:
if (!results.Count())
return;
scope = &results; break;
}
searchBtn->Caption = _tr("Halt");
searchBtn->OnClick = TerminateSearch;
searchThread = new TSearchThread(this, WideStringToUTF8(SearchText->Text).c_str(), searchType, searchOptions, scope);
}
else Caption = "Error finding target module";
}
void __fastcall TsearchForm::TerminateSearch(TObject *Sender)
{
target->terminateSearch = true;
}
//---------------------------------------------------------------------------
void __fastcall TsearchForm::ListBox1DblClick(TObject *Sender)
{
if (!resultsLV->Items->Count) return; // assert items in list view
TListItem *focused = resultsLV->ItemFocused;
if (focused) {
int row = focused->Index;
SWKey *key = (SWKey *)*target;
(*key) = resultsLV->Items->Item[row]->Caption.c_str();
if (targetpc == Form1->LexDictPageControl) {
Form1->DictKeyEdit->Text = resultsLV->Items->Item[row]->Caption.c_str();
}
else {
Form1->TextKeyChanged();
}
}
}
//---------------------------------------------------------------------------
void __fastcall TsearchForm::ListBox1Click(TObject *Sender)
{
if (!resultsLV->Items->Count) return; // assert items in list view
if (target) {
TListItem *focused = resultsLV->ItemFocused;
if (focused) {
int row = focused->Index;
ListKey verse;
SWKey *key = target->CreateKey();
*key = resultsLV->Items->Item[row]->Caption.c_str();
verse << *key;
delete key;
pvrtf->fillWithVerses(target, &verse, true, false, "Search");
}
}
}
//---------------------------------------------------------------------------
__fastcall TsearchForm::TSearchThread::TSearchThread(TsearchForm *parent, string searchText, int searchType, int searchOptions, SWKey *scope, bool CreateSuspended)
: TThread(CreateSuspended)
{
this->parent = parent;
this->searchText = searchText;
this->searchType = searchType;
this->searchOptions = searchOptions;
this->scope = scope;
Priority = tpNormal;
FreeOnTerminate = true;
}
void __fastcall TsearchForm::TSearchThread::updateProgressBar(void) {
parent->progressBar->Position = parent->status;
parent->progressBar->Repaint();
}
void __fastcall TsearchForm::TSearchThread::updateStatus(void) {
Synchronize((TThreadMethod)&updateProgressBar);
}
void TsearchForm::TSearchThread::searchProgressCallback(char status, void *searchThread) {
TsearchForm::TSearchThread *thread = (TsearchForm::TSearchThread *)searchThread;
thread->parent->status = status;
thread->updateStatus();
}
void __fastcall TsearchForm::TSearchThread::FillListBox(void)
{
TListItem *pItem;
SWKey *savekey = (SWKey *)*(parent->target);
SWKey origKeyVal = *savekey;
if (!savekey->Persist()) {
savekey = 0;
}
for (results = TOP; !results.Error(); results++) {
parent->target->setKey(results);
pItem = parent->resultsLV->Items->Add();
pItem->Caption = (const char *)results;
pItem->SubItems->Add("");
// pItem->SubItems->Add((*parent->target).second->StripText());
// pItem = resultsLV->Items->Add(
}
if (savekey)
parent->target->setKey(*savekey);
else parent->target->setKey(origKeyVal); //remove our persist key
// ListBox1->Items->Pack(); // so Count is set correctly (per helpfile)
parent->Caption = ((AnsiString)parent->resultsLV->Items->Count + (AnsiString)" " + (AnsiString)((parent->resultsLV->Items->Count == 1) ? _tr("match") : _tr("matches"))) + (AnsiString)" from [ " + (AnsiString)parent->target->Description() + (AnsiString)" (" + (AnsiString)parent->target->Name() + (AnsiString)") ]";
parent->searchBtn->Caption = _tr("Search");
parent->searchBtn->OnClick = parent->searchBtnClick;
}
void __fastcall TsearchForm::TSearchThread::Execute()
{
results = parent->target->Search(searchText.c_str(), searchType, searchOptions, scope, 0, searchProgressCallback, this);
Synchronize((TThreadMethod)&FillListBox);
parent->results = results;
}
void __fastcall TsearchForm::scopeGroupClick(TObject *Sender) {
bool enabled = (scopeGroup->ItemIndex == 2);
customRangeBtn->Enabled = enabled;
ComboBox1->Enabled = enabled;
}
//---------------------------------------------------------------------------
void __fastcall TsearchForm::customRangeBtnClick(TObject *Sender)
{
RangeMaintForm->ShowModal();
populateRanges();
}
//---------------------------------------------------------------------------
void TsearchForm::populateRanges() {
ConfigEntMap::iterator loop, end;
SWConfig config("./options.conf");
ComboBox1->Clear();
loop = config.Sections["CustomRanges"].begin();
end = config.Sections["CustomRanges"].end();
while (loop != end) {
TCustomRange *rs = new TCustomRange(loop->first.c_str(), loop->second.c_str());
ComboBox1->Items->AddObject(rs->name.c_str(), rs);
loop++;
}
}
void __fastcall TsearchForm::FormShow(TObject *Sender)
{
populateRanges();
fillList();
Button1Click(0); //initially hide the modSelect sidebar
}
//---------------------------------------------------------------------------
void __fastcall TsearchForm::resultsLVChange(TObject *Sender, TListItem *Item,
TItemChange Change)
{
ListBox1Click(Sender);
}
//---------------------------------------------------------------------------
void __fastcall TsearchForm::resultsLVCustomDrawItem(TCustomListView *Sender, TListItem *Item, TCustomDrawState State, bool &DefaultDraw) {
if (target && !Form1->closing) {
TRect rect = Item->DisplayRect(drSelectBounds);
static UnicodeRTF filter;
char buf[255];
strcpy(buf, Item->Caption.c_str());
SWKey *key = *target;
if (!SWDYNAMIC_CAST(VerseKey, key))
filter.ProcessText(buf, 253, *target, target);
RTFHintForm->searchListDrawer->fillWithRTFString(target, ((String)" \\b " + buf + " ").c_str(), "Search");
if (resultsLV->Selected == Item) RTFHintForm->searchListDrawer->Color = TColor(0xB4CDBB);
Sender->Canvas->Brush->Color = RTFHintForm->searchListDrawer->Color;
Sender->Canvas->FillRect(rect);
rect.Right = resultsLV->Column[0]->Width;
RTFHintForm->searchListDrawer->paintTo(Sender->Canvas->Handle, &rect, 0);
ListKey verse;
verse << Item->Caption.c_str();
RTFHintForm->searchListDrawer->fillWithVerses(target, &verse, false, false, "Search", true);
//set color back in case it got changed in fill*
if (resultsLV->Selected == Item) RTFHintForm->searchListDrawer->Color = TColor(0xB4CDBB);
RTFHintForm->searchListDrawer->SelStart = 3;
RTFHintForm->searchListDrawer->SelLength = 1;
double textHeight = RTFHintForm->searchListDrawer->SelAttributes->Height;
double multiplier = 1.2;
textHeight *= multiplier;
int textWithMargin = 3 + textHeight;
if (resultsLV->StateImages->Height < textWithMargin) {
resultsLV->StateImages->Height = textWithMargin;
DefaultDraw = false;
return;
}
RTFHintForm->searchListDrawer->SelLength = 0;
rect = Item->DisplayRect(drSelectBounds);
rect.Left = rect.Left + resultsLV->Column[0]->Width;// + 5;
RTFHintForm->searchListDrawer->paintTo(Sender->Canvas->Handle, &rect, 0);
}
DefaultDraw = false;
}
//---------------------------------------------------------------------------
void __fastcall TsearchForm::resultsLVInfoTip(TObject *Sender,
TListItem *Item, AnsiString &InfoTip)
{
InfoTip = "";
}
//---------------------------------------------------------------------------
void __fastcall TsearchForm::Button1Click(TObject *Sender)
{
bool newVisible = !pnlChooseMod->Visible;
ChooseModSplitter->Visible = newVisible;
pnlChooseMod->Visible = newVisible;
}
//---------------------------------------------------------------------------
void __fastcall TsearchForm::FormActivate(TObject *Sender)
{
if (!Form1->closing) {
Mouse->Capture = 0;
if (searchBtn->OnClick != TerminateSearch) {
TPageControl *targetpc = Form1->TextPageControl;
if ((Form1->ActiveControl == Form1->CommentaryPageControl) || (IsChild(Form1->CommentaryPageControl->Handle, Form1->ActiveControl->Handle)))
targetpc = Form1->CommentaryPageControl;
if ((Form1->ActiveControl == Form1->LexDictPageControl) || (IsChild(Form1->LexDictPageControl->Handle, Form1->ActiveControl->Handle)))
targetpc = Form1->LexDictPageControl;
ModMap::iterator it = Form1->mainmgr->Modules.find(targetpc->ActivePage->Caption.c_str());
if (it != Form1->mainmgr->Modules.end()) {
setTarget(it->second);
}
SearchText->SetFocus();
}
}
initializing = false;
}
void TsearchForm::setTarget(SWModule *itarget) {
target = itarget;
moduleName->Caption = target->Description() + (AnsiString) " (" + target->Name() + ")";
RTFHintForm->searchListDrawer->fillWithRTFString(target, "yoyo");
SearchText->Font->Name = RTFHintForm->searchListDrawer->dispAttribs.fontName;
// SearchText->Font->Size = RTFHintForm->searchListDrawer->dispAttribs.fontSize;
resultsLV->StateImages->Height = 1;
}
//---------------------------------------------------------------------------
void TsearchForm::fillList()
{
BibleCSMGR *manager;
ModMap::iterator mods;
TTreeNode *node;
string nodeName;
manager = Form1->mainmgr;
modTreeView->Items->Clear();
if (!manager->configPath)
return;
for (mods = manager->Modules.begin(); mods != manager->Modules.end(); mods++) {
for (node = modTreeView->Items->GetFirstNode(); node; node = node->getNextSibling()) {
if (!strcmp(node->Text.c_str(), mods->second->Type())) {
break;
}
}
if (!node) { // Add Section
if (!strncmp(mods->second->Type(), "Bibl", 4)) // If Bibles, put first in list
node = modTreeView->Items->AddChildFirst(0, mods->second->Type());
else node = modTreeView->Items->AddChild(0, mods->second->Type());
}
nodeName = "[";
nodeName += mods->second->Name();
nodeName += "] ";
nodeName += mods->second->Description();
node = modTreeView->Items->AddChildObject(node, nodeName.c_str(), mods->second->Name());
}
//for (node = modTreeView->Items->GetFirstNode(); node; node = node->getNextSibling())
// node->Expand(true);
node = modTreeView->Items->GetFirstNode();
if (node)
node->MakeVisible();
}
void __fastcall TsearchForm::modTreeViewChange(TObject *Sender, TTreeNode *Node) {
BibleCSMGR *manager;
ModMap::iterator mods;
TTreeNode *node;
string nodeName;
manager = Form1->mainmgr;
TTreeNode* currNode = modTreeView->Selected;
AnsiString nodeSubString;
AnsiString modName;
for (mods = manager->Modules.begin(); mods != manager->Modules.end(); mods++) {
if (currNode->Text.SubString(2, currNode->Text.Pos("]") - 2) == mods->second->Name()) { // Add Section
setTarget(mods->second);
}
}
}
//---------------------------------------------------------------------------
void __fastcall TsearchForm::Button2Click(TObject *Sender)
{
string helpDir;
ConfigEntMap::iterator it = Form1->optionsconf->Sections["Help"].find("Directory");
if (it != Form1->optionsconf->Sections["Help"].end())
helpDir = (*it).second;
else helpDir = ".\\help";
string helpExe = helpDir + "\\Sword.chm::searchh.html";
if ((int)ShellExecute(this->Handle, "open", "hh", helpExe.c_str(), NULL, SW_SHOWNORMAL) < 33) {
helpExe = helpDir + "\\searchh.html";
ShellExecute(this->Handle, "open", helpExe.c_str(), NULL, NULL, SW_SHOWNORMAL);
}
}
//---------------------------------------------------------------------------
void __fastcall TsearchForm::Button3Click(TObject *Sender)
{
if (resultsLV->Items->Count > 0) {
ListKey tmpVerseList;
for (int i = 0; i < resultsLV->Items->Count; i++) {
tmpVerseList << resultsLV->Items->Item[i]->Caption.c_str();
}
TVerseListForm *tmpForm = new TVerseListForm(this, tmpVerseList);
tmpForm->Caption = _tr("Search Verse List");
tmpForm->Show();
}
}
//---------------------------------------------------------------------------