//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "PrintFrm.h"
#include "mainfrm.h"
#include <Printers.hpp>
#include <Math.hpp>
#include <localemgr.h>
#include "PreviewForm.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "RxCombos"
#pragma resource "*.dfm"
TPrintForm *PrintForm;
//---------------------------------------------------------------------------
__fastcall TPrintForm::TPrintForm(TComponent* Owner)
: TForm(Owner)
{
rtfPrint = new TRxRichEditX(this);
rtfPrint->Parent = this;
rtfPrint->Visible = false;
rtfPrint->Font->Name = "Arial";
// Put in the RXLib Font combobox component
cmbFont = new TFontComboBox(this);
cmbFont->Parent = pnlFontComboBox;
cmbFont->Align = alClient;
cmbFont->Font->Size = 12;
cmbFont->ParentFont = true;
cmbFont->UseFonts = true;
cmbFont->ItemIndex = cmbFont->Items->IndexOf("Arial");
}
//---------------------------------------------------------------------------
void __fastcall TPrintForm::FormShow(TObject *Sender) {
if(Form1->optionsconf->Sections["Printing"]["Notice"] != "1"){
Application->MessageBox("This release of The Sword Printer is preliminary and is not yet fully functional, therefore some of the features here have been disabled. Please be sure to take a look at the formatting options to be able to fully take control of how your page will look. Also be sure to use the \"Print Preview\" feature to preview how your page(s) will look on paper before printing. Enjoy! From, The Sword Project Development Team!", "The Sword Printer", MB_ICONINFORMATION | MB_OK);
Form1->optionsconf->Sections["Printing"]["Notice"] = "1";
Form1->optionsconf->Save();
}
}
//TODO: fix! :) I added wishlist functionality with parameters that isn't implemented! :) Sorry.
void TPrintForm::print(ListKey *keys, SWModule *module) {
ConfigEntMap::iterator eit;
AnsiString fontName;
BibleCSMGR *manager = Form1->mainmgr;
ModMap::iterator mods;
TPageControl* pc;
if ((Form1->ActiveControl == Form1->CommentaryPageControl) || (IsChild(Form1->CommentaryPageControl->Handle, Form1->ActiveControl->Handle))){
pc = Form1->CommentaryPageControl;
radComm->Checked = true;
staticRange->Caption = "Verse Range or List";
editStart->Text = (keys) ? keys->getRangeText() : Form1->DefaultVSKey->getText();
}
else if ((Form1->ActiveControl == Form1->LexDictPageControl) || (IsChild(Form1->LexDictPageControl->Handle, Form1->ActiveControl->Handle))){
pc = Form1->LexDictPageControl;
radLD->Checked = true;
staticRange->Caption = "Lookup Range";
editStart->Text = (keys) ? WideString(keys->getRangeText()) : Form1->DictKeyEdit->Text;
}
else {
pc = Form1->TextPageControl;
radText->Checked = true;
staticRange->Caption = "Verse Range or List";
editStart->Text = (keys) ? keys->getRangeText() : Form1->DefaultVSKey->getText();
}
FillModuleCombo();
AnsiString temp;
for (int count = 0; count < cmbModule->Items->Count; count++) {
temp = cmbModule->Items->Strings[count].SubString(2, cmbModule->Items->Strings[count].Pos("]") - 2);
if (temp == pc->ActivePage->Caption)
cmbModule->ItemIndex = count;
}
SetHint();
fontName = ((eit = Form1->optionsconf->Sections["PrintPrefs"].find("PrintFontName")) != Form1->optionsconf->Sections["PrintPrefs"].end())? (*eit).second.c_str() : "Times New Roman";
cmbFont->ItemIndex = cmbFont->Items->IndexOf(fontName);
PageControl1->ActivePage = shtSelection;
SetDefaultOps();
ShowModal();
}
//---------------------------------------------------------------------------
void __fastcall TPrintForm::btnCloseClick(TObject *Sender)
{
Close();
}
//---------------------------------------------------------------------------
void TPrintForm::FillModuleCombo()
{
TStringList *moduleNames = new TStringList;
BibleCSMGR *manager = Form1->mainmgr;
ModMap::iterator mods;
AnsiString modName;
for (mods = manager->Modules.begin(); mods != manager->Modules.end(); mods++) {
modName = "[" + (AnsiString)mods->second->Name() + "] " + (AnsiString)mods->second->Description();
if(!strncmp(mods->second->Type(), "Bibl", 4) && radText->Checked){
moduleNames->Add(modName);
}else if(!strncmp(mods->second->Type(), "Comm", 4) && radComm->Checked){
moduleNames->Add(modName);
}else if(!strncmp(mods->second->Type(), "Lexi", 4) && radLD->Checked){
moduleNames->Add(modName);
}
}
cmbModule->Items = moduleNames;
cmbModule->ItemIndex = 0;
}
void __fastcall TPrintForm::radTextClick(TObject *Sender)
{
cmbModule->Enabled = true;
staticRange->Caption = _tr("Verse Range or List");
SetHint();
FillModuleCombo();
SetDefaultOps();
}
//---------------------------------------------------------------------------
void __fastcall TPrintForm::radCommClick(TObject *Sender)
{
staticRange->Caption = _tr("Verse Range or List");
SetHint();
FillModuleCombo();
SetDefaultOps();
}
//---------------------------------------------------------------------------
void __fastcall TPrintForm::radLDClick(TObject *Sender)
{
cmbModule->Enabled = true;
staticRange->Caption = _tr("Lookup Entry");
SetHint();
FillModuleCombo();
SetDefaultOps();
}
//---------------------------------------------------------------------------
void __fastcall TPrintForm::spinLeftClick(TObject *Sender,
TUDBtnType Button)
{
if(Button == Comctrls::btNext)
editLeft->Text = FloatToStr(StrToFloat(editLeft->Text) + .05);
else
editLeft->Text = FloatToStr(StrToFloat(editLeft->Text) - .05);
}
//---------------------------------------------------------------------------
void __fastcall TPrintForm::spinRightClick(TObject *Sender,
TUDBtnType Button)
{
if(Button == Comctrls::btNext)
editRight->Text = FloatToStr(StrToFloat(editRight->Text) + .05);
else
editRight->Text = FloatToStr(StrToFloat(editRight->Text) - .05);
}
//---------------------------------------------------------------------------
void __fastcall TPrintForm::spinBottomClick(TObject *Sender,
TUDBtnType Button)
{
if(Button == Comctrls::btNext)
editBottom->Text = FloatToStr(StrToFloat(editBottom->Text) + .05);
else
editBottom->Text = FloatToStr(StrToFloat(editBottom->Text) - .05);
}
//---------------------------------------------------------------------------
void __fastcall TPrintForm::spinTopClick(TObject *Sender,
TUDBtnType Button)
{
if(Button == Comctrls::btNext)
editTop->Text = FloatToStr(StrToFloat(editTop->Text) + .05);
else
editTop->Text = FloatToStr(StrToFloat(editTop->Text) - .05);
}
//---------------------------------------------------------------------------
void __fastcall TPrintForm::btnPrintClick(TObject *Sender)
{
if(cmbModule->Text.data() != NULL && editStart->Text.data() != NULL){
PrepareRTF();
OnPrint(rtfPrint);
}
}
//---------------------------------------------------------------------------
void __fastcall TPrintForm::OnPrint(TRxRichEdit* rtfPrint)
{
/* TODO 2 -oDavid -cPrinting : Add Printing of Headers and Footers */
float leftMargin = StrToFloat(editLeft->Text),
rightMargin = StrToFloat(editRight->Text),
topMargin = StrToFloat(editTop->Text),
bottomMargin = StrToFloat(editBottom->Text);
// Sets the font we will use for the headers and footers
Printer()->Canvas->Font->Name = "Arial";
Printer()->Canvas->Font->Size = -8;
Printer()->Canvas->Font->Color = clBlack;
int wPage = ::GetDeviceCaps(Printer()->Handle, PHYSICALWIDTH);
int hPage = ::GetDeviceCaps(Printer()->Handle, PHYSICALHEIGHT);
int xPPI = ::GetDeviceCaps(Printer()->Handle, LOGPIXELSX);
int yPPI = ::GetDeviceCaps(Printer()->Handle, LOGPIXELSY);
int wTwips = ::MulDiv(wPage, 1440, xPPI);
int hTwips = ::MulDiv(hPage, 1440, yPPI);
/*
// Adjust for the headers and footers if needed
if(ckHeader->Checked){
int headerCoord = hTwips;
hTwips -= (Printer()->Canvas->Font->Height + (.25 * Printer()->Canvas->Font->Height));
}
if(ckFooter->Checked){
int footerCoord = hTwips;
hTwips -= (Printer()->Canvas->Font->Height + (.25 * Printer()->Canvas->Font->Height));
}
*/
RECT pageRect;
pageRect.left = pageRect.top = 0;
pageRect.right = wTwips;
pageRect.bottom = hTwips;
RECT rendRect;
rendRect.left = rendRect.top = 0;
rendRect.right = pageRect.right - 1440 * (leftMargin + rightMargin);
rendRect.bottom = pageRect.bottom - 1440 * (topMargin + bottomMargin);
std::vector<TPageOffsets> FPageOffsets;
TPageOffsets po;
po.Start = 0;
TFormatRange fr;
fr.hdc = Printer()->Handle;
fr.hdcTarget = Printer()->Handle;
fr.chrg.cpMin = po.Start;
fr.chrg.cpMax = -1;
int lastOffset = ::SendMessage(rtfPrint->Handle, WM_GETTEXTLENGTH, 0, 0);
::SendMessage(rtfPrint->Handle, EM_FORMATRANGE, (WPARAM) 0, (LPARAM) 0);
::SaveDC(fr.hdc);
::SetMapMode(fr.hdc, MM_TEXT);
int xOffset = -::GetDeviceCaps(Printer()->Handle, PHYSICALOFFSETX);
int yOffset = -::GetDeviceCaps(Printer()->Handle, PHYSICALOFFSETY);
xOffset += ::MulDiv((leftMargin * 1440), xPPI, 1440);
yOffset += ::MulDiv((topMargin * 1440), yPPI, 1440);
::SetViewportOrgEx(fr.hdc, xOffset, yOffset, NULL);
do {
fr.rc = rendRect;
fr.rcPage = pageRect;
po.Start = fr.chrg.cpMin;
fr.chrg.cpMin = ::SendMessage(rtfPrint->Handle, EM_FORMATRANGE,(WPARAM) 0, (LPARAM) &fr);
// I don't know why I need to do this, but there is an apparent bug in the TRXRichEdit control
// and it doesn't handle the last page properly if there are more than 3 pages of text.
if(fr.chrg.cpMin == po.End)
fr.chrg.cpMin = lastOffset;
po.End = fr.chrg.cpMin - 1;
po.rendRect = fr.rc;
if(fr.chrg.cpMin < lastOffset)
FPageOffsets.push_back(po);
} while (fr.chrg.cpMin != -1 && fr.chrg.cpMin < lastOffset);
int pageCount = FPageOffsets.size();
::SendMessage(rtfPrint->Handle, EM_FORMATRANGE, (WPARAM) 0, (LPARAM) 0);
::RestoreDC(fr.hdc, -1);
Printer()->BeginDoc();
fr.hdc = Printer()->Handle;
fr.hdcTarget = Printer()->Handle;
::SaveDC(fr.hdc);
/*
if(ckHeader->Checked == true){
Printer()->Canvas->TextOut(100,100,"This is my test");
}
*/
bool firstPage = true;
int currPage = 0;
do {
if (firstPage) firstPage = false;
else Printer()->NewPage();
::SetViewportOrgEx(fr.hdc, xOffset, yOffset, NULL);
fr.rc = FPageOffsets[currPage].rendRect;
fr.rcPage = pageRect;
fr.chrg.cpMin = FPageOffsets[currPage].Start;
fr.chrg.cpMax = FPageOffsets[currPage].End;
fr.chrg.cpMin = ::SendMessage(rtfPrint->Handle, EM_FORMATRANGE, (WPARAM) 1, (LPARAM) &fr);
} while (++currPage < pageCount);
::RestoreDC(fr.hdc, -1);
Printer()->EndDoc();
::SendMessage(rtfPrint->Handle, EM_FORMATRANGE, (WPARAM) 0, (LPARAM) 0);
FPageOffsets.erase(FPageOffsets.begin(), FPageOffsets.end());
}
void TPrintForm::SetHint()
{
TStringList* strList = new TStringList;
if(radText->Checked || radComm->Checked){
strList->Add("Examples:");
strList->Add("John 1:1 Prints John chapter 1 verse 1");
strList->Add("John 1 Prints the entire first chapter of John");
strList->Add("John 1,2 Prints chapters 1 and 2 of John");
strList->Add("John 3:16;Rom 3:23 Prints John 3:16 and Romans 3:23");
}else{
strList->Add("Examples:");
/* TODO 2 -oDavid -cPrinting : Make printing ranges of dictionaries work */
// The ranges don't work yet.
//strList->Add("Aaron - David Prints dictionary entries from Aaron to David");
strList->Add("Jesus Prints dictionary entry for Jesus");
//strList->Add("0051 - 0054 Prints dictionary entry for range 0051 to 0054");
strList->Add("0051 Prints dictionary entry for 0051");
}
editStart->Hint = strList->Text;
delete strList;
}
void __fastcall TPrintForm::btnSetupClick(TObject *Sender)
{
PrinterSetupDialog->Execute();
}
//---------------------------------------------------------------------------
void __fastcall TPrintForm::BitBtn5Click(TObject *Sender)
{
//To do
}
//---------------------------------------------------------------------------
void TPrintForm::PrepareRTF()
{
BibleCSMGR* manager = Form1->mainmgr;
RTF_FORMAT format;
AnsiString newtext = "";
AnsiString moduleName = cmbModule->Text.SubString(2,cmbModule->Text.Pos("]") - 2);
SWModule *module = manager->Modules[moduleName.c_str()];
ListKey lstKey;
StrKey testKey;
format.bkFontHeadSize = 2 * editHeading->Text.ToInt();
format.bodyFontSize = 2 * editBody->Text.ToInt();
format.vsNumFontSize = 2 * editNumbers->Text.ToInt();
format.chFontHeadSize = 2 * editHeading->Text.ToInt();
format.fontFace = cmbFont->Text;
format.paragraph = ckParagraph->Checked;
format.prBookHeadings = ckBookHead->Checked;
format.prChHeadings = ckChHead->Checked;
format.prPreFix = ckPrefix->Checked;
format.prPostFix = ckPostfix->Checked;
format.prVerseNum = ckVSNum->Checked;
format.superVSNum = ckSuperVS->Checked;
lstKey.Persist(1);
if(!radLD->Checked){
lstKey = VerseKey().ParseVerseList(editStart->Text.c_str(),*(Form1->DefaultVSKey), true);
module->setKey(&lstKey);
rtfPrint->RenderModule(module, format);
module->setKey(Form1->DefaultVSKey);
}
else{
testKey.setText(WideStringToUTF8(editStart->Text).c_str());
lstKey << testKey;
module->setKey(&lstKey);
rtfPrint->RenderModule(module, format);
module->setKey(Form1->DefaultStrKey);
}
}
void __fastcall TPrintForm::btnPreviewClick(TObject *Sender)
{
if(cmbModule->Text.data() != NULL && editStart->Text.data() != NULL){
PrepareRTF();
PreviewForm->currPage = 0;
if(PreviewForm->ShowModal() == mrOk)
OnPrint(rtfPrint);
}
}
void __fastcall TPrintForm::ckHeaderClick(TObject *Sender)
{
editHeader->Enabled = ckHeader->Checked;
}
//---------------------------------------------------------------------------
void __fastcall TPrintForm::ckFooterClick(TObject *Sender)
{
editFooter->Enabled = ckFooter->Checked;
}
//---------------------------------------------------------------------------
void __fastcall TPrintForm::ckVSNumClick(TObject *Sender)
{
ckSuperVS->Enabled = ckVSNum->Checked;
}
//---------------------------------------------------------------------------
void TPrintForm::SetDefaultOps()
{
if(radText->Checked){
ckBookHead->Checked = true;
ckChHead->Checked = true;
ckParagraph->Checked = true;
ckVSNum->Checked = true;
ckSuperVS->Checked = true;
ckPrefix->Checked = false;
ckPostfix->Checked = false;
}else if(radComm->Checked){
ckBookHead->Checked = false;
ckChHead->Checked = false;
ckParagraph->Checked = false;
ckVSNum->Checked = false;
ckSuperVS->Checked = false;
ckPrefix->Checked = false;
ckPostfix->Checked = true;
}else if(radLD->Checked){
ckBookHead->Checked = false;
ckChHead->Checked = false;
ckParagraph->Checked = false;
ckVSNum->Checked = false;
ckSuperVS->Checked = false;
ckPrefix->Checked = false;
ckPostfix->Checked = false;
}
}