From: Eric H. <eri...@gm...> - 2017-10-08 16:22:45
|
################################################################################ #-- 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(); } |