home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume20 / bibleref / part01 next >
Text File  |  1991-07-18  |  36KB  |  1,169 lines

  1. Newsgroups: comp.sources.misc
  2. From: Richard Goerwitz <goer@midway.uchicago.edu>
  3. Subject:  v20i099:  bibleref - Word and passage retrievals from King James Bible, Part01/07
  4. Message-ID: <csm-v20i099=bibleref.215242@sparky.imd.sterling.com>
  5. X-Md4-Signature: ead405db03944642c762da100f918f03
  6. Date: Thu, 18 Jul 1991 03:00:17 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: Richard Goerwitz <goer@midway.uchicago.edu>
  10. Posting-number: Volume 20, Issue 99
  11. Archive-name: bibleref/part01
  12. Environment: ICON, UNIX
  13.  
  14. Program:  Bibleref
  15. Language: Icon
  16. Purpose:  Perform word and passage-based retrievals on the King James Bible
  17. Overview:
  18.     This package, Bibleref, offers simple tools for word and
  19. passage-based access to the King James Bible on UNIX platforms.
  20. Bibleref is fast, and easy to install (assuming you possess a suitable
  21. King James Bible text and a sufficiently powerful machine).  It will
  22. also run with stock terminals - even nasty old ones that leave magic
  23. cookies on your screen.  Bibleref will, however, put a significant
  24. dent in your mass storage resources.  Along with the 4-5 megabytes of
  25. King James Bible text, you'll need to house some 2 megabytes of
  26. indices, and also the 150k icode file (more if you compile, rather
  27. than interpret).  In-core requirements start at about 800k, and go up
  28. from there (if your searches are complex enough, you could easily eat
  29. up two or three megabytes).  In brief: Bibleref has a large appetite
  30. for memory.  Once set up, though, it can operate with fairly minimal
  31. impact on the CPU.
  32.     With Bibleref, you can perform most of the more basic,
  33. low-level functions commercial Bible browsing packages offer (and
  34. perhaps a few not found in some of the commercial packages).  You can,
  35. for example,
  36.  
  37.     -  retrieve any passage in the Bible instantaneously
  38.     -  move forward or backward relative to the retrieved passage
  39.     -  search the entire Bible for words and/or word-patterns
  40.     -  search for word co-occurrences (or the absence thereof)
  41.     -  save passages and/or passage-lists for use with an editor
  42.  
  43. Although this program is hardly the product of any major research
  44. effort :-), it should prove sophisticated enough for quick lookup of
  45. passages whose precise location you have forgotten, for research on
  46. sermons and Bible study classes, and for general topical perusal of
  47. the biblical text.
  48.  
  49.     To install Bibleref, you'll need to get a hold of the King
  50. James Bible text as packaged in the PC-SIG disk set (19 disks), which
  51. is available from wsmr-simtel20.army.mil.  I happen to have gotten my
  52. texts (very similar to the PC-SIG version) from helens.stanford.edu
  53. (36.0.2.99; kjv.tar.Z).  These ones work as well.  There are a number
  54. of KJV texts floating around which are derivative of the PC-SIG disk
  55. set.  Only ones which have not been edited too severely will work,
  56. unmodified, with the stock Bibleref installation program.
  57. Additional Notes:
  58.  
  59.     As mentioned above, this package is really just a wrapper
  60. around a more general set of indexing and retrieval utilities I'm
  61. using for personal research.  Despite the way they are used here,
  62. these utilities are *not* geared solely for the KJV.  In fact, they
  63. are set up so that they can be used with just about any text broken up
  64. into hierarchically arranged divisions.  If, for instance, you don't
  65. like Renaissance English, and have a more modern Bible translation
  66. online, you can certainly use that instead.  All you'll need to do is
  67. copy the kjv2rtv.icn file to, say, kjv2rsv.icn, edit it to reflect the
  68. text you are using, run it on your text, and then index it as you
  69. would have done for the King James text.  You can tell Bibleref to use
  70. this text instead of the King James text either by modifying
  71. bibleref.icn to point to the new file, or by giving it a filename
  72. argument, a la "bibleref -f your.indexed.bible.text."
  73.  
  74.    -Richard L. Goerwitz              goer%sophist@uchicago.bitnet
  75.    goer@sophist.uchicago.edu         rutgers!oddjob!gide!sophist!goer
  76.  
  77. ---- Cut Here and feed the following to sh ----
  78. #!/bin/sh
  79. # This is a shell archive (produced by shar 3.49)
  80. # To extract the files from this archive, save it to a file, remove
  81. # everything above the "!/bin/sh" line above, and type "sh file_name".
  82. #
  83. # made 07/14/1991 19:06 UTC by richard@zenu
  84. # Source directory /u/richard/Bibleref/src
  85. #
  86. # existing files will NOT be overwritten unless -c is specified
  87. # This format requires very little intelligence at unshar time.
  88. # "if test", "cat", "rm", "echo", "true", and "sed" may be needed.
  89. #
  90. # This is part 1 of a multipart archive                                    
  91. # do not concatenate these parts, unpack them in order with /bin/sh        
  92. #
  93. # This shar contains:
  94. # length  mode       name
  95. # ------ ---------- ------------------------------------------
  96. #   6521 -rw-r--r-- bibleref.src
  97. #   3103 -r--r--r-- ref2bmap.icn
  98. #   2991 -r--r--r-- name2num.icn
  99. #   2716 -r--r--r-- convertb.icn
  100. #  13413 -r--r--r-- listutil.icn
  101. #   7191 -r--r--r-- passutil.icn
  102. #   2816 -r--r--r-- readfile.icn
  103. #   6117 -r--r--r-- srchutil.icn
  104. #    456 -r--r--r-- version.icn
  105. #   5988 -r--r--r-- complete.icn
  106. #    744 -r--r--r-- ipause.icn
  107. #   4314 -r--r--r-- rewrap.icn
  108. #   1855 -r--r--r-- binsrch.icn
  109. #   4974 -r--r--r-- bmp2text.icn
  110. #   3059 -r--r--r-- initfile.icn
  111. #   7107 -r--r--r-- retrieve.icn
  112. #   7264 -r--r--r-- indexutl.icn
  113. #   6797 -r--r--r-- retrops.icn
  114. #   6601 -r--r--r-- whatnext.icn
  115. #  18055 -r--r--r-- iolib.icn
  116. #   6945 -r--r--r-- iscreen.icn
  117. #  20980 -r--r--r-- findre.icn
  118. #   2176 -r--r--r-- kjv2rtv.icn
  119. #   1328 -r--r--r-- convertr.icn
  120. #  16283 -r--r--r-- makeind.icn
  121. #   2423 -r--r--r-- gettokens.icn
  122. #   4827 -r--r--r-- Makefile.dist
  123. #  15535 -rw-r--r-- README
  124. #  15504 -rw-r--r-- README.rtv
  125. #
  126. if test -r _shar_seq_.tmp; then
  127.     echo 'Must unpack archives in sequence!'
  128.     echo Please unpack part `cat _shar_seq_.tmp` next
  129.     exit 1
  130. fi
  131. # ============= bibleref.src ==============
  132. if test -f 'bibleref.src' -a X"$1" != X"-c"; then
  133.     echo 'x - skipping bibleref.src (File already exists)'
  134.     rm -f _shar_wnt_.tmp
  135. else
  136. > _shar_wnt_.tmp
  137. echo 'x - extracting bibleref.src (Text)'
  138. sed 's/^X//' << 'SHAR_EOF' > 'bibleref.src' &&
  139. X############################################################################
  140. X#
  141. X#    Name:     bibleref.icn
  142. X#
  143. X#    Title:     Bible Reference Finder
  144. X#
  145. X#    Author:     Richard L. Goerwitz
  146. X#
  147. X#    Version: 1.18
  148. X#
  149. X############################################################################
  150. X#
  151. X#  This program helps the user locate and browse passages from the
  152. X#  King James Bible, as distributed in the 19-disk PC-SIG set.
  153. X#  Startup syntax is
  154. X#
  155. X#      bibleref [-f filename] [-v]
  156. X#
  157. X#  where filename is the name of the indexed Bible text you wish to
  158. X#  peruse.  Because the KJV filename is hard-coded into the program,
  159. X#  you need not supply the -f argument.  It is available, though,
  160. X#  just in case you have indexed another biblical file, and wish to
  161. X#  use that instead.
  162. X#
  163. X#  If bibleref is called with a -v argument, it prints the version
  164. X#  number and patchlevel, then exits.
  165. X#
  166. X#  This particular file contains only the basic command loop, some
  167. X#  initialization routines, and some basic clearing/prompting/reading
  168. X#  utilities.  The other integral file is listutil.icn, which contains
  169. X#  all of the basic list and passage display routines.
  170. X#
  171. X############################################################################
  172. X#
  173. X#  Requires: UNIX, fully updated & installed Icon Program Library
  174. X#
  175. X############################################################################
  176. X#
  177. X#  Links: ./ref2bmap.icn ./name2num.icn ./convertb.icn ./complete.icn
  178. X#         ./binsrch.icn ./bmp2text.icn ./initfile.icn ./retrieve.icn
  179. X#         ./indexutl.icn ./retrops.icn ./whatnext.icn ./iolib.icn
  180. X#         ./iscreen.icn ./listutil.icn ./rewrap.icn ./passutil.icn
  181. X#         ./srchutil.icn ./readfile (and probably others I've forgotten)
  182. X#
  183. X#  Until incorporated into Icon, also link:  ./ipause.icn
  184. X#
  185. X#  See also: kjv2rtv.icn, makeind.icn, retrieve.icn, iolib.icn
  186. X#
  187. X############################################################################
  188. X
  189. Xglobal kjv_filename, lists
  190. Xrecord lst(l,pos,old_n,s)
  191. X
  192. X
  193. Xprocedure main(a)
  194. X
  195. X    local option_table, filename, prompt, intext, first, result
  196. X    # global lists
  197. X    initial {
  198. X    lists := []
  199. X    checkout_features()
  200. X    option_table := getopts(a, "f:v")
  201. X    if \option_table["v"] then abort("Bibleref", _version(), 0)
  202. X    kjv_filename := \option_table["f"] | "/usr/local/lib/bibleref/kjv.rtv"
  203. X    initialize_screen()
  204. X    message("Initializing offset file...")
  205. X    initfile(kjv_filename) |
  206. X        quit("main","can't locate "||kjv_filename,1)
  207. X    }
  208. X
  209. X    # Setup initial prompt.
  210. X    prompt := "Enter passage, or f to find a word (q to quit):  "
  211. X
  212. X    # Read user input.
  213. X    while intext := snarf_input(prompt) do {
  214. X
  215. X    trim(intext,'\t ') ? {
  216. X
  217. X        # See if the user has just input a passage reference.
  218. X        # If so, then display it...
  219. X        if display_passage(intext) then
  220. X        result := "yes"
  221. X
  222. X        # ...otherwise, see if his/her input matches any of the
  223. X        # following commands:
  224. X        else {
  225. X        first := move(1) | "c"
  226. X        case first of {
  227. X            "!" : push_shell() & initialize_screen()
  228. X            "c" : initialize_screen()        # c = clear
  229. X            "d" : display_list()             # d = display (a list)
  230. X            "f" : {                 # f = find a word
  231. X            if search_database() # insert new list into "lists"
  232. X            then display_list()  # stores it as a record (lst)
  233. X            }
  234. X            "l" : show_lists()             # l = list all lists
  235. X            "q" : {                 # q = quit program
  236. X            if pos(0) & "y" == snarf_input("Really quit? (y/n)  ")
  237. X            then break
  238. X            }
  239. X            "r" : readfile() & display_list()# r = read file from disk
  240. X            default : {                 # input error
  241. X            err_message("Unrecognized passage or command.")
  242. X            next
  243. X            }
  244. X        }
  245. X        }
  246. X        # If we have any tangible search results, or else have viewed
  247. X        # a passage, then alter the prompt to reflect the full range
  248. X        # of options.
  249. X        \result | *\lists > 0 &
  250. X        prompt := "Enter passage, or !/c/d/f/l/q/r:  "
  251. X    }
  252. X    }
  253. X
  254. X    # Clear, say goodbye, and exit with zero status.
  255. X    initialize_screen()
  256. X    message("Thanks for using Bibleref.")
  257. X    write(); exit(0)
  258. X
  259. Xend
  260. X
  261. X
  262. Xprocedure initialize_screen()
  263. X
  264. X    #
  265. X    # Initialize screen
  266. X    #
  267. X    local msg, short_message
  268. X
  269. X    pos(0) | {
  270. X    err_message("Garbage characters after \"c\" command.")
  271. X    fail
  272. X    }
  273. X
  274. X    msg := "\"Bibleref\" - a King James Bible browser _
  275. X           by Richard Goerwitz"
  276. X    short_message := "\"Bibleref,\" by Richard Goerwitz"
  277. X
  278. X    clear()
  279. X    status_line(msg, short_message, "c") &
  280. X    return
  281. X
  282. Xend
  283. X
  284. X
  285. Xprocedure snarf_input(prompt)
  286. X
  287. X    #
  288. X    # Read user input after displaying a prompt.
  289. X    #
  290. X    local command
  291. X    # global commands
  292. X
  293. X    /prompt := "Please input:  "
  294. X    message(prompt)
  295. X    return read()
  296. X
  297. Xend
  298. X
  299. X
  300. Xprocedure err_message(msg)
  301. X
  302. X    #
  303. X    #  Display error message for 1 second; erase.
  304. X    #
  305. X    /msg := "Error."
  306. X    message(msg)
  307. X    ipause(700)        # until Icon gets a sleep function
  308. X    message("")
  309. X    return
  310. X
  311. Xend
  312. X    
  313. X
  314. Xprocedure status_message(msg)
  315. X
  316. X    #
  317. X    #  Display some status message on the highlighted status line.
  318. X    #
  319. X    status_line(msg) &
  320. X    return
  321. X
  322. Xend
  323. X    
  324. X
  325. Xprocedure checkout_features()
  326. X
  327. X    #
  328. X    # Check to see if we have the necessary terminal & OS features.
  329. X    #
  330. X    local capname
  331. X
  332. X    every capname := ("li","co","ce","so") do {
  333. X    getval(capname) | {
  334. X        quit("check_features",
  335. X         "terminal lacks "||capname||" capability", 2)
  336. X    }
  337. X    }
  338. X    find("UNIX",&features) |
  339. X    quit("check_features", "OS unsupported", 1)
  340. X    return
  341. X
  342. Xend
  343. X
  344. X
  345. Xprocedure quit(s1, s2, i)
  346. X    
  347. X    #
  348. X    # Move cursor to bottom screen line & abort, sending the message
  349. X    # s1: s2 to the user, and exiting with status i.
  350. X    #
  351. X    iputs(igoto(getval("cm"), 1, getval("li")))
  352. X    iputs(getval("ce"))
  353. X    abort(s1, s2, i)
  354. X
  355. Xend
  356. X
  357. X
  358. Xprocedure getopts(arg,optstring)
  359. X
  360. X    #
  361. X    # Get opts.  Based on Bob Alexander & Gregg Townsend's IPL
  362. X    # options procedure.
  363. X    #
  364. X    local x,i,c,otab,flist,o,p
  365. X
  366. X    /optstring := string(&letters)
  367. X    otab := table()
  368. X    flist := []
  369. X    while x := get(arg) do {
  370. X    x ? {
  371. X        if ="-" & not pos(0) then {
  372. X        if ="-" & pos(0) then break
  373. X        while c := move(1) do
  374. X            if i := find(c,optstring) + 1 then
  375. X            otab[c] :=
  376. X            if any(':+.',o := optstring[i]) then {
  377. X                        p := "" ~== tab(0) | get(arg) |
  378. X                quit("getopts", "No parameter following -"||c, 1)
  379. X                        case o of {
  380. X                ":": p
  381. X                "+": integer(p) |
  382. X                quit("getopts", "-"||c||" needs numeric", 1)
  383. X                ".": real(p) |
  384. X                quit("getopts", "-"||c||" needs numeric", 1)
  385. X            }
  386. X            }
  387. X            else 1
  388. X            else quit("getopts","Unrecognized option: -"||c, 1)
  389. X        }
  390. X        else put(flist,x)
  391. X    }
  392. X    }
  393. X    while push(arg,pull(flist))
  394. X    return otab
  395. X
  396. Xend
  397. SHAR_EOF
  398. true || echo 'restore of bibleref.src failed'
  399. rm -f _shar_wnt_.tmp
  400. fi
  401. # ============= ref2bmap.icn ==============
  402. if test -f 'ref2bmap.icn' -a X"$1" != X"-c"; then
  403.     echo 'x - skipping ref2bmap.icn (File already exists)'
  404.     rm -f _shar_wnt_.tmp
  405. else
  406. > _shar_wnt_.tmp
  407. echo 'x - extracting ref2bmap.icn (Text)'
  408. sed 's/^X//' << 'SHAR_EOF' > 'ref2bmap.icn' &&
  409. X############################################################################
  410. X#
  411. X#    Name:     ref2bmap.icn
  412. X#
  413. X#    Title:     convert English reference to a bitmap
  414. X#
  415. X#    Author:     Richard L. Goerwitz
  416. X#
  417. X#    Version: 1.6
  418. X#
  419. X############################################################################
  420. X#
  421. X#  Converts an English reference (e.g. "Ex 4:21" to a bitmap suitable
  422. X#  for retrieval via bitmap_2_text(bitmap, filename)).  Syntax:
  423. X#
  424. X#      ref_2_bitmap(english_ref, filename)
  425. X#
  426. X#  fails if the requested conversion can't be performed on account of
  427. X#  a misspelling.  Aborts if the file whose name is given as arg 2
  428. X#  does not have a transparently book:chapter:verse organization (i.e.
  429. X#  IS.no must = 3).
  430. X#
  431. X############################################################################
  432. X#
  433. X#  Links: complete.icn, ./initfile.icn ./name2num.icn
  434. X#
  435. X############################################################################
  436. X
  437. X# Declared in indexutl.icn.
  438. X# record is(FS, s_len, len, no, is_case_sensitive)
  439. X# global IS
  440. X
  441. X# Declared in initfile.icn.
  442. X# global filestats
  443. X# record Fs(ind_filename,bmp_filename,lim_filename, IS, ofs_table,all_bitmaps)
  444. X
  445. X
  446. Xprocedure ref_2_bitmap(s, filename)
  447. X
  448. X    local bitmap, bookname, book_numeric, field, no
  449. X
  450. X    # Check for sloppy programming.
  451. X    /filename & abort("ref_2_bitmap","you called me without a filename",54)
  452. X
  453. X    # If necessary, initialize stats for the current file.
  454. X    #
  455. X    if /filestats | /filestats[filename]
  456. X    then initfile(filename)           # see initfile.icn
  457. X    IS := filestats[filename].IS
  458. X    IS.no ~= 3 & abort("ref_2_bitmap","can't yet handle IS.no ~= 3",51)
  459. X
  460. X    # IS.len   = the number of bits needed to hold an integer
  461. X    #            representation of a single field in filename
  462. X    # IS.no    = number of fields in bitmaps for filename
  463. X    # s        = English Bible reference (e.g. Gen 8:10)
  464. X    # no       = number of fields minus one
  465. X
  466. X    no       := IS.no - 1
  467. X    bookname := ""
  468. X    bitmap   := 0
  469. X
  470. X    s ? {
  471. X
  472. X    # Find book name, convert it to an integer.
  473. X    bookname ||:= tab(any('1234'));    tab(many(' '))
  474. X    bookname ||:= tab(many(&letters)) | fail
  475. X    # Fail if the user gives us just a single letter...
  476. X    *bookname > 1 | fail
  477. X    # ...otherwise, convert book name into the correct value for
  478. X    # for this file, and fit it into a proper-length bit field.
  479. X    book_numeric :=  name2num(bookname) | fail
  480. X    bitmap := ior(bitmap, ishift(book_numeric, no * IS.len)) | fail
  481. X    
  482. X    # Get book and verse fields.  Add them, shifted appropriately,
  483. X    # to bitmap.
  484. X    while tab(upto(&digits)) do {
  485. X        no -:= 1
  486. X        # If no goes below 0 then we have too many fields for the
  487. X        # file named in arg 2.
  488. X        no >= 0 | fail
  489. X        # If you prefer to abort with an error, uncomment this.
  490. X        # no >= 0 | abort("ref_2_bitmap", "impossible reference",52)
  491. X        bitmap := ior(bitmap, ishift(tab(many(&digits)), no * IS.len))
  492. X    }
  493. X    }
  494. X
  495. X    # If the current no is not 0, then we have either too
  496. X    # many or too few fields.  This check can be disabled,
  497. X    # to allow for dummy specifications (e.g. Exod, which would
  498. X    # imply all of the book of Exodus).
  499. X    no = 0 | fail
  500. X
  501. X    return bitmap
  502. X
  503. Xend
  504. SHAR_EOF
  505. true || echo 'restore of ref2bmap.icn failed'
  506. rm -f _shar_wnt_.tmp
  507. fi
  508. # ============= name2num.icn ==============
  509. if test -f 'name2num.icn' -a X"$1" != X"-c"; then
  510.     echo 'x - skipping name2num.icn (File already exists)'
  511.     rm -f _shar_wnt_.tmp
  512. else
  513. > _shar_wnt_.tmp
  514. echo 'x - extracting name2num.icn (Text)'
  515. sed 's/^X//' << 'SHAR_EOF' > 'name2num.icn' &&
  516. X############################################################################
  517. X#
  518. X#    Name:     name2num.icn
  519. X#
  520. X#    Title:     convert English book name to an integer
  521. X#
  522. X#    Author:     Richard L. Goerwitz
  523. X#
  524. X#    Version: 1.3
  525. X#
  526. X############################################################################
  527. X#
  528. X#  Used by ref_2_bitmap(), convertr(), etc.
  529. X#
  530. X############################################################################
  531. X
  532. X
  533. Xprocedure name2num(s)
  534. X
  535. X    # Map English book names or abbreviations to numeric values.
  536. X
  537. X    local n, b_name, tmp_names, i, nameset
  538. X    static names, abbrevtbl
  539. X    initial {
  540. X
  541. X    names :=     ["genesis", "exodus", "leviticus", "numbers",
  542. X              "deuteronomy", "joshua", "judges", "ruth",
  543. X              "1samuel", "2samuel", "1kings", "2kings",
  544. X              "1chronicles", "2chronicles", "ezra",
  545. X              "nehemiah", "esther", "job", "psalms",
  546. X              "proverbs", "ecclesiastes", "canticles",
  547. X              "isaiah", "jeremiah", "lamentations", "ezekiel",
  548. X              "daniel", "hosea", "joel", "amos", "obadiah",
  549. X              "jonah", "micah", "nahum", "habakkuk",
  550. X              "zephaniah", "haggai", "zechariah", "malachi",
  551. X              "matthew", "mark", "luke", "john", "acts",
  552. X              "romans", "1corinthians", "2corinthians",
  553. X              "galations", "ephesians", "philippians",
  554. X              "colossians", "1thessalonians",
  555. X              "2thessalonians", "1timothy", "2timothy",
  556. X              "titus", "philemon", "hebrews", "james",
  557. X              "1peter", "2peter", "1john", "2john", "3john",
  558. X              "jude", "revelation", "tobit", "judith", "wisdom",
  559. X              "sirach", "baruch", "1maccabees", "2maccabees",
  560. X
  561. X              "gen", "exod", "lev", "num", "deut", "josh",
  562. X              "judg", "ruth", "1sam", "2sam", "1kgs", "2kgs",
  563. X              "1chr", "2chr", "ezra", "neh", "esth", "job",
  564. X              "pss", "prov", "qoh", "cant", "isa", "jer",
  565. X              "lam", "ezek", "dan", "hos", "joel", "amos",
  566. X              "obad", "jonah", "mic", "nahum", "hab", "zeph",
  567. X              "hag", "zech", "mal", "mat", "mark", "luke",
  568. X              "john", "acts", "rom", "1cor", "2cor", "gal",
  569. X              "eph", "phil", "col", "1thess", "2thess",
  570. X              "1tim", "2tim", "titus", "phlm", "heb", "jas",
  571. X              "1pet", "2pet", "1john", "2john", "3john",
  572. X              "jude", "rev", "tob", "jdt", "wis", "sir",
  573. X              "bar", "1macc", "2macc",
  574. X
  575. X              "dt", "jdg", "jg", "rth", "sa1", "sa2", "ki1",
  576. X              "ki2", "ch1", "ch2", "jl", "mt", "mk", "lk",
  577. X              "jn", "co1", "co2", "th1", "th2", "ti1", "ti2",
  578. X              "phm", "pe1", "pe2", "jo1", "jo2", "jo3", "1jn",
  579. X              "2jn", "3jn",
  580. X
  581. X              "son", "solomon", "ecclesiasticus", "ecclus"]
  582. X
  583. X        abbrevtbl := table()
  584. X    tmp_names := copy(names)
  585. X    every i := (1 to 73) | (1 to 73) |
  586. X        5|7|7|8|9|10|11|12|13|14|29|40|41|42|43|46|
  587. X        47|52|53|54|55|57|60|61|62|63|64|62|63|64|
  588. X        22|22|70|70
  589. X    do {
  590. X        insert(abbrevtbl, get(tmp_names), i)
  591. X    }
  592. X    }
  593. X
  594. X    nameset := set()
  595. X    every insert(nameset, complete(map(s), names))
  596. X    case *nameset of {
  597. X    0 : fail
  598. X    1 : return abbrevtbl[!nameset]
  599. X    default : suspend abbrevtbl[!sort(nameset)]
  600. X    }
  601. X    
  602. Xend
  603. SHAR_EOF
  604. true || echo 'restore of name2num.icn failed'
  605. rm -f _shar_wnt_.tmp
  606. fi
  607. # ============= convertb.icn ==============
  608. if test -f 'convertb.icn' -a X"$1" != X"-c"; then
  609.     echo 'x - skipping convertb.icn (File already exists)'
  610.     rm -f _shar_wnt_.tmp
  611. else
  612. > _shar_wnt_.tmp
  613. echo 'x - extracting convertb.icn (Text)'
  614. sed 's/^X//' << 'SHAR_EOF' > 'convertb.icn' &&
  615. X############################################################################
  616. X#
  617. X#    Name:     convertb.icn
  618. X#
  619. X#    Title:     convert 3-field book,chap,verse bitmap into a human-
  620. X#                readable book chapter:verse reference
  621. X#
  622. X#    Author:     Richard L. Goerwitz
  623. X#
  624. X#    Version: 1.3
  625. X#
  626. X############################################################################
  627. X#
  628. X#  Links: complete.icn ./initfile.icn
  629. X#
  630. X############################################################################
  631. X
  632. X# Declared in indexutl.icn.
  633. X# record is(FS, s_len, len, no, is_case_sensitive)
  634. X# global IS
  635. X
  636. X# Declared in initfile.icn.
  637. X# global filestats
  638. X# record Fs(ind_filename,bmp_filename,lim_filename, IS, ofs_table,all_bitmaps)
  639. X
  640. Xprocedure convertb(bitmap, filename)
  641. X
  642. X    local no, reference, field_mask
  643. X
  644. X    # Check for sloppy programming.
  645. X    /filename & abort("convertb","you called me without a filename",70)
  646. X
  647. X    # If necessary, initialize stats for the current file.
  648. X    #
  649. X    if /filestats | /filestats[filename]
  650. X    then initfile(filename)           # see initfile.icn
  651. X    IS := filestats[filename].IS
  652. X    IS.no ~= 3 & abort("convertb", "can't yet handle IS.no ~= 3", 71)
  653. X
  654. X    # IS.len   = the number of bits needed to hold an integer
  655. X    #            representation of a single field in filename
  656. X    # IS.no    = number of fields in bitmaps for filename
  657. X
  658. X    no := IS.no-1
  659. X    field_mask := 2^(IS.len)-1
  660. X
  661. X    # No need for mask here; add it just in case.
  662. X    reference  := Num2Name(
  663. X    iand(field_mask, ishift(bitmap, -(no*IS.len))), "kjv.rtv") |
  664. X    abort("convertb", "can't convert first field", 52)
  665. X
  666. X    no -:= 1
  667. X    reference ||:= " " || iand(field_mask, ishift(bitmap, -(no*IS.len)))
  668. X    no -:= 1
  669. X    reference ||:= ":" || iand(field_mask, ishift(bitmap, -(no*IS.len)))
  670. X
  671. X    return reference
  672. X
  673. Xend
  674. X
  675. X
  676. X
  677. Xprocedure Num2Name(i)
  678. X
  679. X    # Map English book names or abbreviations to numeric values.
  680. X
  681. X    local names, n
  682. X    static num_table
  683. X    initial {
  684. X    names     := ["Gen", "Exod", "Lev", "Num", "Deut", "Josh",
  685. X              "Judg", "Ruth", "1Sam", "2Sam", "1Kgs", "2Kgs",
  686. X              "1Chr", "2Chr", "Ezra", "Neh", "Esth", "Job",
  687. X              "Pss", "Prov", "Qoh", "Cant", "Isa", "Jer",
  688. X              "Lam", "Ezek", "Dan", "Hos", "Joel", "Amos",
  689. X              "Obad", "Jonah", "Mic", "Nahum", "Hab", "Zeph",
  690. X              "Hag", "Zech", "Mal", "Mat", "Mark", "Luke",
  691. X              "John", "Acts", "Rom", "1Cor", "2Cor", "Gal",
  692. X              "Eph", "Phil", "Col", "1Thess", "2Thess",
  693. X              "1Tim", "2Tim", "Titus", "Phlm", "Heb", "Jas",
  694. X              "1Pet", "2Pet", "1John", "2John", "3John",
  695. X              "Jude", "Rev", "Tob", "Jdt", "Wis", "Sir",
  696. X              "Bar", "1Macc", "2Macc"]
  697. X        num_table :=  table()
  698. X    every n := 1 to 73 do
  699. X        insert(num_table, n, get(names))
  700. X    }
  701. X
  702. X    return num_table[i]
  703. X
  704. Xend
  705. SHAR_EOF
  706. true || echo 'restore of convertb.icn failed'
  707. rm -f _shar_wnt_.tmp
  708. fi
  709. # ============= listutil.icn ==============
  710. if test -f 'listutil.icn' -a X"$1" != X"-c"; then
  711.     echo 'x - skipping listutil.icn (File already exists)'
  712.     rm -f _shar_wnt_.tmp
  713. else
  714. > _shar_wnt_.tmp
  715. echo 'x - extracting listutil.icn (Text)'
  716. sed 's/^X//' << 'SHAR_EOF' > 'listutil.icn' &&
  717. X############################################################################
  718. X#
  719. X#    Name:     1.20
  720. X#
  721. X#    Title:     bibleref list display utilities
  722. X#
  723. X#    Author:     Richard L. Goerwitz
  724. X#
  725. X#    Version: listutil.icn
  726. X#
  727. X############################################################################
  728. X#
  729. X#  Contains:
  730. X#
  731. X#      display_list(), which displays all passages in a given bitmap
  732. X#          list by calling listlist(), which converts the bitmaps to
  733. X#          human-readable format, and writes them to the screen
  734. X#
  735. X#      listlist(), on which see above,
  736. X#
  737. X#      writelist(), which writes a bitmap list in human readable form
  738. X#          to a file.
  739. X#
  740. X############################################################################
  741. X#
  742. X#  Links: ./rewrap.icn (also uses push_shell(), which is in ./passutil.icn)
  743. X#
  744. X############################################################################
  745. X
  746. X# Declared in bibleref.icn.  l is the list itself, pos is the viewer's
  747. X# last position in the list.  old_n is the last passage in the list that
  748. X# was viewed.  s is a brief indication of the search string used to gen-
  749. X# erate the list.
  750. X# record lst(l,pos,old_n,s)
  751. X
  752. X
  753. Xprocedure display_list()
  754. X
  755. X    #
  756. X    #  Display a retrieved "hit list."
  757. X    #
  758. X    local passage, subscr
  759. X
  760. X    #
  761. X    # We're in the midst of a scanning expression in the main
  762. X    # command loop.  If the "d" command was given with no arguments,
  763. X    # then default to the last list retrieved.
  764. X    #
  765. X    if pos(0) then {
  766. X    subscr := (0 ~= *lists) | {
  767. X        err_message("No lists have been created yet.")
  768. X        fail
  769. X    }
  770. X    }
  771. X    #
  772. X    # If we are not at pos(0) then we are to go to a specific list
  773. X    # in the list history.
  774. X    #
  775. X    else {
  776. X    if not {
  777. X        tab(upto('-+' ++ &digits)) &
  778. X        subscr := integer(tab(many('-+' ++ &digits))) &
  779. X        pos(0)
  780. X    }
  781. X    # If we don't have an integer, then the user has screwed
  782. X    # up somehow.
  783. X    then {
  784. X        err_message("Garbage characters after \"d\" command.")
  785. X        fail
  786. X    }
  787. X    # Check to be sure the subscript give is in range.
  788. X    lists[subscr] | {
  789. X        err_message("There is no list number "||subscr||".")
  790. X        fail
  791. X    }
  792. X    }
  793. X
  794. X    #
  795. X    # While listlist gives us a valid passage reference, display it.
  796. X    # When it returns &null or fails, quit.
  797. X    #
  798. X    repeat {
  799. X
  800. X        # Display the list (defaults above to the last list in the list
  801. X        # history).  Use listlist().  Arg 1 is the lst record, which
  802. X        # contains a list and a position to start viewing that list at.
  803. X        # The second arg to listlist tells the user the length of the
  804. X        # list.  The last arg specifies how many display columns we can
  805. X        # eat up before truncating.
  806. X     passage :=
  807. X        listlist(
  808. X            lists[subscr],
  809. X           "length = "||*lists[subscr].l||"; "||
  810. X           "search string = "||lists[subscr].s,
  811. X            getval("co")-10
  812. X            )                    |  fail
  813. X    if /passage then return
  814. X    else display_passage(passage)
  815. X    }
  816. Xend
  817. X
  818. X
  819. X
  820. Xprocedure listlist(lst_rec, msg, width)
  821. X
  822. X    local l, i, ss, j, n, prompt, rsp, rsp2
  823. X    static lines
  824. X    initial lines := getval("li")-3
  825. X
  826. X    # "l" is a record of type lst, containing the list to print
  827. X    # "msg" is the message to put on the status line
  828. X    # "width" gives the length to which lines in l are truncated
  829. X    # "offset" gives the starting offset in l at which to begin
  830. X    #    printing (default 0).
  831. X
  832. X    l := lst_rec.l
  833. X
  834. X    repeat {
  835. X    i := 0
  836. X    while *l >= (ss := lst_rec.pos + (lines > (i +:= 1))) do {
  837. X        iputs(igoto(getval("cm"), 1, i))
  838. X        normal(); iputs(getval("ce"))
  839. X        writes(" ", left(ss||".",7))
  840. X        if ss = \lst_rec.old_n then {
  841. X        # Boldface last viewed passage from this list.
  842. X        boldface(); writes(convertb(l[ss], kjv_filename)[1:\width|0])
  843. X        normal()
  844. X        } else writes(convertb(l[ss], kjv_filename)[1:\width|0])
  845. X    }
  846. X
  847. X    # If we haven't reached the end of the displayable screen,
  848. X    # then clear lines until we reach it...
  849. X    if i-1 ~= lines+1 then {
  850. X        every j := i to lines do {
  851. X        iputs(igoto(getval("cm"), 1, j))
  852. X        normal(); iputs(getval("ce"))
  853. X        }
  854. X    }
  855. X    # Display message on status line.
  856. X    status_line("-- " || \msg || " --" | "", "", "c")
  857. X
  858. X    # If we're to the end of the screen, and there's still more to
  859. X    # display, then...
  860. X    if *l > lines-1 & (lst_rec.pos+i) ~= (*l+1) then {
  861. X        rsp :=
  862. X        snarf_input("Press !/a/b/c/m/n/p/s/v/w (q = quit viewing):  ")
  863. X        case map(rsp) of {
  864. X        ""     : lst_rec.pos := (*l > (lst_rec.pos+1))
  865. X        "!"    : push_shell()
  866. X        "/"    : lst_rec.pos := search_list(lst_rec,rsp,lines)
  867. X        "?"    : lst_rec.pos := search_list(lst_rec,rsp,lines)
  868. X        "a"    : write_list(l, "append")
  869. X        "b"    : lst_rec.pos := (0 < lst_rec.pos-lines+1) | 0
  870. X        "c"    : next
  871. X        "m"    : lst_rec.pos := (*l > (lst_rec.pos+i-1))
  872. X        "n"    : {
  873. X            n := \lst_rec.old_n+1 | {
  874. X            err_message("Type \"v\" to set the current passage.")
  875. X            next
  876. X            }
  877. X            if 0 < n <= *l then {
  878. X            if not (lst_rec.pos < n < lst_rec.pos+lines)
  879. X            then lst_rec.pos := (0 < n-2) | n-1
  880. X            lst_rec.old_n := n & (return l[n])
  881. X            } else err_message("Out of range.")
  882. X        }            
  883. X        "p"    : {
  884. X            n := \lst_rec.old_n-1 | {
  885. X            err_message("Type \"v\" to set the current passage.")
  886. X            next
  887. X            }
  888. X            if 0 < n <= *l then {
  889. X            if not (lst_rec.pos < n < lst_rec.pos+lines)
  890. X            then lst_rec.pos := (0 < n-2) | n-1
  891. X            lst_rec.old_n := n & (return l[n])
  892. X            } else err_message("Out of range.")
  893. X        }            
  894. X        "q"    : break
  895. X        "s"    : {
  896. X            l := (lst_rec.l := sort(lst_rec.l))
  897. X            lst_rec.old_n := &null
  898. X        }
  899. X        "v"    : {
  900. X            rsp2 := snarf_input("View which passage:  ")
  901. X            rsp2 == "q" & next
  902. X            rsp2 == ""  & rsp2 := lst_rec.old_n
  903. X            if n := integer(rsp2) then {
  904. X            if 0 < n <= *l then {
  905. X                if not (lst_rec.pos < n < lst_rec.pos+lines)
  906. X                then lst_rec.pos := (0 < n-2) | n-1
  907. X                lst_rec.old_n := n
  908. X                return l[n]
  909. X            } else err_message("Out of range.")
  910. X            } else err_message("Invalid passage number.")
  911. X        }
  912. X        "w"    : write_list(l)
  913. X        default : {
  914. X            if rsp ? {
  915. X            lst_rec.pos :=
  916. X                search_list(lst_rec,tab(any('?/')),lines)
  917. X            }
  918. X            then next
  919. X            else {
  920. X            if n := integer(rsp)-1 then {
  921. X                if 0 <= n < *l
  922. X                then lst_rec.pos := n
  923. X                else err_message("Out of range.")
  924. X            } else {
  925. X                err_message("Invalid command.")
  926. X            }
  927. X            }
  928. X        }
  929. X        }
  930. X    }
  931. X    # ...otherwise, we've displayed everything.
  932. X    else {
  933. X        prompt := "c/n/p/s/v/w (q to go to previous menu):  "
  934. X        if *l <= lines
  935. X        then rsp:= snarf_input("Press !/a/" || prompt) | next
  936. X        else rsp :=    snarf_input("Press !/a/b/" || prompt) | next
  937. X        case map(rsp) of {
  938. X        "!"    : push_shell()
  939. X        "/"    : lst_rec.pos := search_list(lst_rec,rsp,lines)
  940. X        "?"    : lst_rec.pos := search_list(lst_rec,rsp,lines)
  941. X        "a"    : write_list(l,"append")
  942. X        "b"    : lst_rec.pos := (0 < lst_rec.pos-lines+1) | 0
  943. X        "c"|"" : next
  944. X        "m"    : next    # no more to display; just stay were we are
  945. X        "n"    : {
  946. X            n := \lst_rec.old_n+1 | {
  947. X            err_message("No passage viewed yet from this list.")
  948. X            next
  949. X            }
  950. X            if 0 < n <= *l then {
  951. X            lst_rec.old_n := n & (return l[n])
  952. X            if not (lst_rec.pos < n < lst_rec.pos+lines)
  953. X            then lst_rec.pos := (0 < n-2) | n-1
  954. X            } else err_message("Out of range.")
  955. X        }            
  956. X        "p"    : {
  957. X            n := \lst_rec.old_n-1 | {
  958. X            err_message("No passage viewed yet from this list.")
  959. X            next
  960. X            }
  961. X            if 0 < n <= *l then {
  962. X            lst_rec.old_n := n & (return l[n])
  963. X            if not (lst_rec.pos < n < lst_rec.pos+lines)
  964. X            then lst_rec.pos := (0 < n-2) | n-1
  965. X            } else err_message("Out of range.")
  966. X        }            
  967. X        "q"    : break
  968. X        "s"    : {
  969. X            l := (lst_rec.l := sort(lst_rec.l))
  970. X            lst_rec.old_n := &null
  971. X        }
  972. X        "v"    : {
  973. X            rsp2 := snarf_input("View which passage:  ")
  974. X            rsp2 == "q" & next
  975. X            rsp2 == ""  & rsp2 := lst_rec.old_n
  976. X            if n := integer(rsp2) then {
  977. X            if 0 < n <= *l then {
  978. X                if not (lst_rec.pos < n < lst_rec.pos+lines)
  979. X                then lst_rec.pos := (0 < n-2) | n-1
  980. X                lst_rec.old_n := n
  981. X                return l[n]
  982. X            } else err_message("Out of range.")
  983. X            } else err_message("Invalid passage number.")
  984. X        }
  985. X        "w"    : write_list(l)
  986. X        default : {    
  987. X            if rsp ? {
  988. X            lst_rec.pos :=
  989. X                search_list(lst_rec,tab(any('?/')),lines)
  990. X            }
  991. X            then next
  992. X            else {
  993. X            if n := integer(rsp)-1 then {
  994. X                if 0 <= n < *l
  995. X                then lst_rec.pos := n
  996. X                else err_message("Out of range.")
  997. X            } else {
  998. X                err_message("Invalid command.")
  999. X            }
  1000. X            }
  1001. X        }
  1002. X        }
  1003. X    }
  1004. X    }
  1005. X    return
  1006. X
  1007. Xend
  1008. X
  1009. X
  1010. X
  1011. Xprocedure write_list(l, switch)
  1012. X
  1013. X    #
  1014. X    # Used for writing the contents of a displayed list to a file.
  1015. X    #
  1016. X    local fname, outtext, i, firstchar
  1017. X
  1018. X    # Get straight whether we are appending or clobbering.
  1019. X    (\switch := "a") | (switch := "w")
  1020. X
  1021. X    until \outtext do {
  1022. X    fname := snarf_input("Enter filename (! for shell; q to quit):  ")
  1023. X    fname ? {
  1024. X        firstchar := move(1) | ""
  1025. X        case firstchar of {
  1026. X        ""   : fail
  1027. X        "!"  : push_shell() & initialize_screen()
  1028. X        "q"  : pos(0) & fail
  1029. X        default : {
  1030. X            outtext := open(fname, switch) | {
  1031. X            case switch of {
  1032. X                "a" : err_message("Can't append to "|| fname ||".")
  1033. X                "w" : err_message("Can't write to "|| fname ||".")
  1034. X                default : quit("write_passage","internal error",80)
  1035. X            }
  1036. X            }
  1037. X        }
  1038. X        }
  1039. X    }
  1040. X    }
  1041. X    message("Writing...")
  1042. X    every i := 1 to *l do
  1043. X    write(outtext, " ", left(i||".",7), convertb(l[i], kjv_filename))
  1044. X    close(outtext)
  1045. X    message("Done.")
  1046. X    return
  1047. X
  1048. Xend
  1049. X
  1050. X
  1051. X
  1052. Xprocedure show_lists()
  1053. X
  1054. X    #
  1055. X    # Display stats for all generated lists.  So far the only routine
  1056. X    # that can generate lists is search_database().  Every time it
  1057. X    # generates a list, it inserts that list into the global list,
  1058. X    # lists (declared and initialized in bibleref.icn).
  1059. X    #
  1060. X    local expanded_list, i, result
  1061. X    
  1062. X    #
  1063. X    # We're in the midst of a scanning expression in the main
  1064. X    # command loop.  If the "l" command was given with no arguments,
  1065. X    # then default to the last list retrieved.
  1066. X    #
  1067. X    if not pos(0) then {
  1068. X    err_message("Garbage characters after \"l\" command.")
  1069. X    fail
  1070. X    }
  1071. X    *lists = 0 & {
  1072. X    err_message("No lists in memory.")
  1073. X    fail
  1074. X    }
  1075. X
  1076. X    repeat {
  1077. X    result :=
  1078. X        listlistS(lists, "list of viewable lists", getval("co")-10) | fail
  1079. X    if /result
  1080. X    then return
  1081. X    else result ? display_list()
  1082. X    }
  1083. Xend
  1084. X
  1085. X
  1086. X
  1087. Xprocedure listlistS(all_lists, msg, width)
  1088. X
  1089. X    local l, offset, i, ss, j, prompt, rsp, rsp2
  1090. X    static lines, last_viewed
  1091. X    initial lines := getval("li")-3
  1092. X
  1093. X    # "all_lists" is a list of records of type lst
  1094. X    # "msg" is the message to put on the status line
  1095. X    # "width" gives the length to which lines in l are truncated
  1096. X
  1097. X    l := all_lists
  1098. X
  1099. X    offset := 0
  1100. X    repeat {
  1101. X    i := 0
  1102. X    while *l >= (ss := offset + (lines > (i +:= 1))) do {
  1103. X        iputs(igoto(getval("cm"), 1, i))
  1104. X        normal(); iputs(getval("ce"))
  1105. X        writes(" ", left(ss||".",5))
  1106. X        writes("length = " || *l[i].l || ", search pattern = " || l[i].s)
  1107. X    }
  1108. X
  1109. X    # If we haven't reached the end of the displayable screen,
  1110. X    # then clear lines until we reach it...
  1111. X    if i-1 ~= lines+1 then {
  1112. X        every j := i to lines do {
  1113. X        iputs(igoto(getval("cm"), 1, j))
  1114. X        normal(); iputs(getval("ce"))
  1115. X        }
  1116. X    }
  1117. X    # Display message on status line.
  1118. X    status_line("-- " || \msg || " --" | "", "", "c")
  1119. X
  1120. X    # If we're to the end of the screen, and there's still more to
  1121. X    # display, then...
  1122. X    if *l > lines-1 & (offset+i) ~= (*l+1) then {
  1123. X        rsp := snarf_input("Press !/b/c/m/v (q = quit viewing):  ")
  1124. X        case map(rsp) of {
  1125. X        ""     : offset := (*l > (offset+1))
  1126. X        "!"    : push_shell()
  1127. X        "b"    : offset := (0 < offset-lines+1) | 0
  1128. X        "c"    : next            
  1129. X        "m"    : (offset := (*l > (offset+i-1)))
  1130. X        "q"    : break
  1131. X        "v"    : {
  1132. X            rsp2 := snarf_input("View which list:  ")
  1133. X            rsp2 == "q" & next
  1134. X            rsp2 == ""  & rsp2 := \last_viewed
  1135. X            if last_viewed := integer(rsp2) then {
  1136. X            if 0 < last_viewed <= *l
  1137. X            then return last_viewed
  1138. X            else err_message("Out of range.")
  1139. X            }
  1140. X            else err_message("Invalid list number.")
  1141. X        }
  1142. X        default : {
  1143. X            err_message("Command invalid in this context.")
  1144. X        }
  1145. X        }
  1146. X    }
  1147. X    # ...otherwise, we've displayed everything.
  1148. X    else {
  1149. X        prompt := "c/v (q to go to previous menu):  "
  1150. X        if *l <= lines
  1151. X        then rsp:= snarf_input("Press !/" || prompt) | next
  1152. X        else rsp :=    snarf_input("Press !/b/" || prompt) | next
  1153. SHAR_EOF
  1154. true || echo 'restore of listutil.icn failed'
  1155. fi
  1156. echo 'End of  part 1'
  1157. echo 'File listutil.icn is continued in part 2'
  1158. echo 2 > _shar_seq_.tmp
  1159. exit 0
  1160.  
  1161. exit 0 # Just in case...
  1162. -- 
  1163. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  1164. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  1165. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  1166. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  1167.