################################################################################
#-- NAME: KJV_Bible_SDBM.pl (or compiled to .exe)
#--
#-- AUTHOR: Eric Hansen U.S.A
#--
#-- DATE: August 29, 2017
#--
#-- LANGUAGE: Win32 Perl - ActiveState ActivePerl v5.6.1, binary build 638
#-- Win32 GUI Module (by Aldo Calpini) release 1.02
#--
#-- COMPILER: IndigoSTAR Perl2EXE v5.03, Win32 Perl Application Compiler
#--
#-- FUNCTION: KJV Bible Navigator Software. FlatFile/SDBM Database Version.
#-- DB User-Interface is a TreeView/RichEdit set of GUI widgets.
#--
#-- DATABASE: 3 input Files (JOINT DATABASE TECHNOLOGY - ISAM/NoSQL):
#--
#-- KJV_Bible_SDBM.dat (16,037 KB) Fixed-length(528 characters)
#-- records (no CR/LF), Flat File of 31102 KJV Bible verses
#-- extracted from a total of 66 books and 1189 chapters.
#-- KJV_Bible_SDBM.dir (4 KB) SDBM Binary File (part 1 of 2)
#-- KJV_Bible_SDBM.pag (128 KB) SDBM Binary File (part 2 of 2)
#-- Both used for random access indexing within the Flat File
#-- to the byte offset of the first verse within each chapter.
#-- Verses within a Chapter are read sequentially from there.
#-- These 3 files (named as shown) must reside in the application
#-- directory with program file KJV_Bible_SDBM.pl or .exe
#-- if compiled to a standalone executable.
#--
#-- OUTPUT: KJV_Bible_Genesis_Chp_3.rtf would be a Rich Edit (Wordpad) output
#-- file created in the Program/Application DIR containing all the
#-- verses for the Book of Genesis, Chapter 3. This output file is
#-- automatically created for each Book&Chapter the end-user selects.
#--
#-- HASH: Format of SDBM tied to hash table BibleIDX (for Books 1 to 66)
#-- KEY VALUE DESCRIPTION
#-- =============================================================
#-- ...
#-- 10 II Samuel,2Sa,24 Bk10 = name,abbrev,nbr_chps
#-- 10|1 4236144,27 Bk10|Chp1 = offset,nbr_verses
#-- ...
#-- 10|10 4351248,19 Bk10|Chp10 = offset,nbr_verses
#-- ...
#-- 10|24 4589904,25 Bk10|Chp24 = offset,nbr_verses
#-- ...
#--
#-- ABORTED: Should the program abort, run from a command prompt to see error.
#-- This would most likely occur if one or more of the 3 database
#-- files are missing from the application directory, or they have
#-- been renamed.
#--
#-- NO VERSES
#-- DISPLAY: If you do not see Bible verses displayed in the RichEdit widget
#-- after you have DBL-clicked your mouse on a particular chapter
#-- within the TreeView widget, it is likely due to the associated
#-- *.rtf output file already existing and having been manually
#-- set to a READ ONLY status. If the file exists, it must have
#-- WRITE permission. An Error Msg Box will pop up on the screen.
#-- To correct this problem, either delete or rename the
*.rtf file.
#-- If you wish to write personal notes within any of the *.rtf
#-- files generated, and prevent them from being stepped on
#-- (i.e. overwritten), then instead of making the file(s) READ ONLY,
#-- simply rename them. Example:
#-- KJV_Bible_Genesis_Chp_3.rtf to
KJV_Bible_Genesis_Chp3_Edited.rtf
#-- Or, you can make a subdirectory and store your edited files there
################################################################################
use Win32;
use Win32::GUI; #-- module extension by Aldo Calpini. Native Windows GUI.
use IO::Handle;
use SDBM_File;
use Fcntl;
use Win32API::File 0.08 qw( :ALL );
$SFont = new Win32::GUI::Font(
-name => "Courier New",
-size => 8,
-height => -11,
-weight => 700
);
$M1 = new Win32::GUI::Menu(
"&File" => "File1",
" > &Exit" => "Exit1",
"&Help" => "Help1",
" > &About" => "About1",
);
$W1 = new Win32::GUI::Window (
-title => "KJV Bible Navigator (FlatFile/SDBM Database Version)",
-menu => $M1,
-name => "Window1",
-minsize => [400, 200],
);
$TV = $W1->AddTreeView (
-name => "TV",
-font => $SFont,
-left => 10,
-top => 5,
-width => 180,
-height => $W1->ScaleHeight()-10,
-lines => 0,
-rootlines => 1,
-buttons => 1,
-visible => 1,
-checkboxes => 0,
-onMouseDblClick => \&TVDblClick,
);
$RE = $W1->AddRichEdit(
-name => "RE",
-height => $W1->ScaleHeight()-10,
-width => $W1->ScaleWidth()-205,
-wrap => 1,
-top => 5,
-left => 195,
-style => WS_VISIBLE | WS_VSCROLL | ES_AUTOVSCROLL | ES_MULTILINE,
-readonly => 1,
);
########################
########################
### Initialization ###
########################
########################
$DOS = Win32::GUI::GetPerlWindow();
Win32::GUI::Hide($DOS);
$PWD=Win32::GetCwd(); #-- program(p)/current(c) working(w) directory(d) location
$W1->Show();
$W1->Maximize();
Window1_Maint();
Database_Connect();
Load_TreeView();
$W1->Maximize();
Window1_Maint();
#######################
#######################
### Event Handler ###
#######################
#######################
Win32::GUI::Dialog(); #-- Enter event handler, and wait for end-user responses
#-- Logical End-of-Program is Here, although the END{} routine is performed last
#-- as cleanup.
################################################################################
################################################################################
############ SUBROUTINES ############
################################################################################
################################################################################
######################
sub Database_Connect {
######################
$hFILE = createFile("$PWD\\KJV_Bible_SDBM.dat", "r");
unless ( $hFILE ) {
die "Can't open Flat File: $PWD\\KJV_Bible_SDBM.dat (ERROR: ",
fileLastError(),")\n";
}
tie( %BibleIDX, "SDBM_File", '.\KJV_BIBLE_SDBM', O_RDONLY, 0444 );
unless ( tied %BibleIDX ) {
die "Can't tie hash tbl to SDBM Files: $PWD\\KJV_Bible_SDBM.pag (& .dir) $!";
}
}
###################
sub Load_TreeView {
###################
$TV->Clear(); $RE->Text("");
for my $bk (1 .. 66) {
my ($name, $short_name, $nbr_chps) = split(/,/,$BibleIDX{$bk});
my $node = $TV->InsertItem(-text => "$bk:$name"); #-- insert a Parent node
for my $chp (1 .. $nbr_chps) {
Win32::GUI::DoEvents(); #-- keep window from perhaps freezing up
my $key = $bk . "|" . $chp;
my ($offset, $nbr_vers) = split(/,/,$BibleIDX{$key});
$TV->InsertItem(-parent => $node, -text => "$short_name $chp:1-$nbr_vers");
}
}
}
###################
sub Window1_Maint {
###################
#-- Perform some Window Maintenance. A bit redundant (and overkill?) perhaps.
#-- Not sure how much of this is necessary? Better safe than sorry.
#-- Does not hurt performance.
$W1->BringWindowToTop(); #-- Brings window to the foreground
$W1->SetForegroundWindow(); #-- Brings window to the foreground
$W1->SetActiveWindow(); #-- Activates window
$W1->Redraw(1); #-- Same as InvalidateRect
$W1->InvalidateRect(1); #-- Redraw the Window
$W1->Update(); #-- similar to Redraw and InvalidateRect
$W1->SetFocus();
}
################################################################################
################################################################################
############ EVENTS ###############
################################################################################
################################################################################
################
sub TVDblClick {
################
my ($self, $x, $y) = @_;
my $node = $self->HitTest($x,$y);
$self->Select($node);
my $parent_node = $self->GetParent($node);
if ($node == 0 || $parent_node == 0) {
return;
}
$RE->Text("");
my %parentinfo = $self->ItemInfo($parent_node);
my ($bk, $bkname) = split(/:/,$parentinfo{-text});
my %nodeinfo = $self->ItemInfo($node);
my ($abbrev, $string) = split(/ /,$nodeinfo{-text});
my ($chp, $range) = split(/:/,$string);
my $outputfile="$PWD\\KJV_Bible_" . $bkname . "_Chp_" . $chp . ".rtf";
my $ret=0;
open(BibleRTF,"> $outputfile") || do {$ret=1;};
if (! $ret) {
BibleRTF->autoflush(1); #-- flush the output buffer each print
} else {
Win32::GUI::MessageBox($W1,"Can't open file\n$outputfile\nfor output\n$!",
"KJV Bible Navigator - Error",16,);
return;
}
print BibleRTF '{\rtf1\ansi\ansicpg1252\deff0\deflang1033\deflangfe1033'
. '{\fonttbl{\f0\fswiss\fcharset0 Tahoma;}}'
. '{\colortbl ;\red255\green0\blue0;}'
. '\viewkind4\uc1\pard\f0\fs18' . "\n";
my $key=$bk . "|" . $chp;
my ($offset, $nbr_verses) = split(/,/,$BibleIDX{$key});
my $rec = "Hello Dolly"; my $txt = "Hello Dolly";
for (my $ver=1;$ver<=$nbr_verses;$ver++) {
Win32::GUI::DoEvents(); #-- keep window from perhaps freezing up
if ($ver == 1) {
my $pos=SetFilePointer( $hFILE, $offset, [], FILE_BEGIN); #-- random access
unless ( $pos ) {
my $error = fileLastError();
my $msg = "Can't set file pointer at byte offset $offset within:\n" .
"$PWD\\KJV_Bible_SDBM.dat" .
"\nat Book of $bkname chapter $chp verse $ver\n" . $error;
Win32::GUI::MessageBox($W1,$msg,"KJV Bible Navigator - Error",16,);
last;
}
}
$ret = ReadFile( $hFILE, $rec, 528, [], [] ); #-- sequential access
unless ( $ret ) {
my $error = fileLastError();
my $msg = "Can't read input file:\n" . "$PWD\\KJV_Bible_SDBM.dat" .
"\nat Book of $bkname chapter $chp verse $ver\n" . $error;
Win32::GUI::MessageBox($W1,$msg,"KJV Bible Navigator - Error",16,);
last;
}
#-- Next, we want to trim the length of $rec before printing.
#-- Buffer $rec is initialized to fixed-length 528, and can't be trimmed.
$txt=sprintf("%s", $rec); #-- required step in removing trailing spaces
$txt=~s/ *$//; #-- remove trailing spaces or you can ...
$txt=~s/\s+$//; #-- remove trailing spaces (redundant here just to show)
#$txt=~s/^\s+//; #-- if we had needed to remove leading spaces, if any
#print BibleRTF '\ul\b\i0\highlight1 '
print BibleRTF '\ul\b0\i\highlight0 '
. "$bkname $chp:$ver (KJV)"
. '\par\ulnone\b\i0\highlight0' . $txt . '\par\par' . "\n";
}
print BibleRTF '}' . "\n";
close(BibleRTF);
$RE->Load("$outputfile");
#-- Perform some Window Maintenance.
#-- We don't want to Maximize Window because end-user may have adjusted size.
Window1_Maint();
}
##################
sub About1_Click {
##################
my $about_text="Written by Eric Hansen, U.S.A., August 29, 2017\n" .
"In the Win32 PERL language - ActiveState ActivePerl v5.6.1, build 638\n" .
"Compiled with the IndigoSTAR Perl2Exe compiler v5.03\n" .
"Perl Win32-GUI module (by Aldo Calpini) release 1.02\n" .
"Expand a Book, then DblClick a Chapter to view it.\n" .
"Close this message box to proceed.";
my $about = "About - KJV Bible Navigator - FlatFile/SDBM Database Version";
Win32::GUI::MessageBox($W1,$about_text,$about,64,);
}
#################
sub Exit1_Click {
#################
return -1; #-- stops the event handler and exits
}
#######################
sub Window1_Terminate {
#######################
return -1; #-- stops the event handler and exits
}
####################
sub Window1_Resize {
####################
my $width = $W1->ScaleWidth();
my $height = $W1->ScaleHeight();
$TV->Resize(180,$height-10);
$RE->Resize($width-205,$height-10);
}
#####
END {
#####
CloseHandle($hFILE); untie(%BibleIDX); close(BibleRTF);
Win32::GUI::Show($DOS);
return -1; #-- stops the event handler and exits
}
=====================================================================
======================================================================
ALTERNATE TreeView Double Click Event to replace the ORIGINAL:
################
sub TVDblClick {
################
my ($self, $x, $y) = @_;
my $node = $self->HitTest($x,$y);
$self->Select($node);
my $parent_node = $self->GetParent($node);
if ($node == 0 || $parent_node == 0) {
return;
}
$RE->Text("");
my %parentinfo = $self->ItemInfo($parent_node);
my ($bk, $bkname) = split(/:/,$parentinfo{-text});
my %nodeinfo = $self->ItemInfo($node);
my ($abbrev, $string) = split(/ /,$nodeinfo{-text});
my ($chp, $range) = split(/:/,$string);
my $outputfile="$PWD\\KJV_Bible_" . $bkname . "_Chp_" . $chp . ".rtf";
my $ret=0;
open(BibleRTF,"> $outputfile") || do {$ret=1;};
if (! $ret) {
BibleRTF->autoflush(1); #-- flush the output buffer each print
} else {
Win32::GUI::MessageBox($W1,"Can't open file\n$outputfile\nfor output\n$!",
"KJV Bible Navigator - Error",16,);
return;
}
my $key=$bk . "|" . $chp;
my ($offset, $nbr_verses) = split(/,/,$BibleIDX{$key});
my $pos=SetFilePointer( $hFILE, $offset, [], FILE_BEGIN); #-- random access
unless ( $pos ) {
my $error = fileLastError();
my $msg = "Can't set file pointer at byte offset $offset within:\n" .
"$PWD\\KJV_Bible_SDBM.dat" .
"\nat Book of $bkname chapter $chp verse 1\n" . $error;
Win32::GUI::MessageBox($W1,$msg,"KJV Bible Navigator - Error",16,);
close(BibleRTF);
return;
}
my $BIB_Tmpl = ""; #-- build a template to unpack an entire chapter of verses
for (my $i=1; $i<= $nbr_verses; $i++) {
$BIB_Tmpl = $BIB_Tmpl . "A528, ";
}
chop $BIB_Tmpl; chop $BIB_Tmpl; #-- remove trailing ", "
$nbr_chars=(528 * $nbr_verses);
my $buff = "Hello Dolly";
$ret=ReadFile( $hFILE, $buff, $nbr_chars, [], [] ); #-- read in a whole chapter
unless ( $ret ) {
my $error = fileLastError();
my $msg = "Can't read input file:\n" . "$PWD\\KJV_Bible_SDBM.dat" .
"\nat Book of $bkname chapter $chp verses 1 to $nbr_verses\n" . $error;
Win32::GUI::MessageBox($W1,$msg,"KJV Bible Navigator - Error",16,);
close(BibleRTF);
return;
}
my @verses=();
@verses=unpack($BIB_Tmpl,$buff);
print BibleRTF '{\rtf1\ansi\ansicpg1252\deff0\deflang1033\deflangfe1033'
. '{\fonttbl{\f0\fswiss\fcharset0 Tahoma;}}'
. '{\colortbl ;\red255\green0\blue0;}'
. '\viewkind4\uc1\pard\f0\fs18' . "\n";
for (my $j=0; $j<$nbr_verses; $j++) {
Win32::GUI::DoEvents(); #-- keep window from perhaps freezing up
$verses[$j]=~s/ *$//; #-- remove trailing spaces from ea. verse
$ver=$j+1;
#print BibleRTF '\ul\b\i0\highlight1 '
print BibleRTF '\ul\b0\i\highlight0 '
. "$bkname $chp:$ver (KJV)"
. '\par\ulnone\b\i0\highlight0' . $verses[$j] . '\par\par' . "\n";
}
print BibleRTF '}' . "\n";
close(BibleRTF);
$RE->Load("$outputfile");
#-- Perform some Window Maintenance.
#-- We don't want to Maximize Window because end-user may have adjusted size.
Window1_Maint();
}
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Perl-Win32-GUI-Users mailing list
Perl-Win32-GUI-Users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/perl-win32-gui-users
http://perl-win32-gui.sourceforge.net/