diff options
Diffstat (limited to 'ipl/progs/literat.icn')
-rw-r--r-- | ipl/progs/literat.icn | 1083 |
1 files changed, 1083 insertions, 0 deletions
diff --git a/ipl/progs/literat.icn b/ipl/progs/literat.icn new file mode 100644 index 0000000..fde9c5c --- /dev/null +++ b/ipl/progs/literat.icn @@ -0,0 +1,1083 @@ +############################################################################ +# +# File: literat.icn +# +# Subject: Program to manage literature information +# +# Author: Matthias Heesch +# +# Date: March 26, 2002 +# +############################################################################ +# +# This file is in the public domain. +# +############################################################################ +# +# Database system to manage information concerning literature. +# +############################################################################ +# +# Written by: Dr. Matthias Heesch +# Department of Protestant Theology (FB 02) +# Johannes Gutenberg University +# Saarstrasse 21 / D-W-6500 Mainz 1 / Germany +# +############################################################################ +# +# Written and tested under: DR/MS-DOS, using ansi.sys +# +############################################################################ +# +# See the comment lines concerning the single user defined +# functions if you want to use them separately. Note that all screen +# access assumes ansi.sys to be installed. +# +# Since arguments to the seek() function may be long integers, +# long-integer support is required. +# +# The program uses standard files literat.fil, literat2.fil and +# adress.fil to store its data on the disk. It has a predefined +# structure of the items and predefined field labels to make it easy +# to use and to cut down the source code length.for users having some +# knowledge of the Icon language it shouldn't be difficult to +# change the program. In this case the item length (now 846 byte) +# the option lists in menue() and the field label list have to be +# modified. The main changes then will concern user defined +# function edit_item() where the number of fields within an item +# is decided by *labels. In function in_itemm() the number of dummy +# field separators has to be equal to the amount of fields desired. +# (items := list(200,"##" if two fields are desired). Within the +# other functions only the amount of bytes for a whole item within +# reads() and seek() operation has to be changed accordingly. Note +# that "literat"'s editor in its present version isn't able to scroll. +# +# See the description (comment lines) of user defined function +# line() for details of the editing facilities. +# +# The menue accepts input by <arrow up/dn> and the lower case short +# hand key of every option. The selected option has to be activated +# by <ret>. +# +# iNPUT: function to update an existing file literat.dat. When moving +# the cursor out of the actual item, the last or following item will +# be displayed and is available for the editing process. Input treats +# literat.dat as a sequential file. Only the items to be added to the +# existing file are in the computer's memory. This fastens the option +# to switch between the (new) items. Otherwise it would have been +# necessary to load the whole literat.dat into the RAM or to load +# every new item from the disk. The first would consume too much +# memory with the result of potential loss of new items, the second +# would cost much time. In one session "literat" can accept no more +# than 200 new items. +# +# tURN_OVER_ITEMS: literat.dat can be viewed and edited item by item +# moving the cursor out of the actual item causes the next/last item +# to be displayed. The edited items are written to file literat2.fil +# +# aDRESS file: type words to be indicated. If they are found, the +# item numbers of their occurrence will be recorded in file adress.fil. +# Moving the cursor out of the editor causes the indicating +# process to start. New items to adress.fil are simply added to the +# file. Therefore changes of existing material in adress.fil have to +# be made by creating a new adress.fil. +# +# qUERY: searches item using the information in adress.fil. You are +# prompted to type a word and if it's found in adress.fil the +# programm will use the item numbers to compute arguments to the +# seek()-function and then read the item. After viewing and if +# desired editing the item it will be written to file literat2.fil. +# +# dEL: prompts for an item number and removes the corresponding item. +# the file then is written to literat2.fil, literat.fil remains +# as it was. +# +# AlPHA: alphabetical sorting, sorted file written to literat2.fil. +# +# eND: return to the operating system. +# +############################################################################ +# +# Important message to the user: everybody who will find and remove +# a bug or add any improvement to the program is kindly encouraged +# to send a copy to the above address. +# +############################################################################ +# +# Note: Clerical edits were made to this file by the Icon Project. +# It's possible they introduced errors. +# +############################################################################ +# +# Requires: large-integer arithmetic, ANSI terminal support +# +############################################################################ + +############################################################################ +# # +# linfield: line and field editing package # +# # +############################################################################ +# +# +############################################################################ +# # +# set of user defined functions essential to the line editor line() # +# # +############################################################################ +# +# newkey(): redirects keyboard to make some of the editing functions +# accessable also by arrow/ctrl-arrow-keys. needs ansi.sys. +# although newkey() isn't called by line() directly, a program +# which uses line() should contain a call to newkey(), because +# otherwise line()'S function won't be available for cursor keys. + + procedure newkey() + + local code, n_keys + n_keys := list(9) +# arrow left (cursor left) + n_keys[1] := char(27) || "[0;77;1p" +# arrow right (cursor right) + n_keys[2] := char(27) || "[0;75;2p" +# arrow up (quit, decreasing line_number) + n_keys[3] := char(27) || "[0;72;14p" +# arrow down (quit, increasing line_number) + n_keys[4] := char(27) || "[0;80;21p" +# ctrl/left + n_keys[5] := char(27) || "[0;116;8p" +# ctrl/right + n_keys[6] := char(27) || "[0;115;9p" +# home + n_keys[7] := char(27) || "[0;71;4p" +# end + n_keys[8] := char(27) || "[0;79;5p" +# deL + n_keys[9] := char(27) || "[0;83;6p" +# +# activate codes + while code := get(n_keys) do { + writes(code) + } +end +# +# +# function to set cursor position + procedure locate(row,col) + + local cursor + + cursor := char(27) || "[" || row || ";" || col || "H" + writes(cursor) +end +# +# last(byte,string): detects the last occurrence of byte in +# string and returns its position + procedure last(byte,string) + + local a, r_string, rpos + + r_string := reverse(string) + rpos := find(byte,r_string) + a := (*string - rpos) + return a +end +# +# remword(string,acol): removes word at acol from string + procedure remword(string,acol) + + local blank, string_a, string_b + +# if acol points to end of string, don`t do anything + if acol + 1 > *string then return string +# if acol points to a blank just remove the blank + if string[acol + 1] == " " then { + string ? { + string_a := tab(acol + 1) + move(1) + string_b := tab(0) + string := string_a || string_b + return string + } + } +# else delete actual word + if acol = 0 then acol := 1 +# crack string into two parts + string ? { + string_a := tab(acol + 1) + string_b := tab(0) + } +# check string_a for the last blank if any + if find(" ",string_a) then { + blank := last(" ",string_a) + string_a := string_a[1:blank + 1] + } + else string_a := "" +# check string_b for the first blank if any + if blank := find(" ",string_b) then { + string_b := string_b[blank:*string_b + 1] + } + else string_b := "" +# build string out of string_a ending at its last and string_b +# beginning at its first blank. + string := string_a || string_b + if string[1] == " " then string[1] := "" + return string +end +# +# stat_line: function to display a status line with the actual row +# and column + procedure stat_line(column) + locate(24,1) + writes("LINE: ",lin_nm," COL: ",column," ","TIME: ",&clock," ") +end +# +# global variable line_number to indicate the increase or decrease +# of global variable lin_nm + global line_number +# +# global variable lin_nm to increase or decrease actual line +# in the field + global lin_nm +# +# global variable field_flag: direction flag to increase or +# decrease field number + global field_flag +# +# global variable item_flag: direction flag to increase or +# decrease item number + global item_flag +# +############################################################################ +# # +# line editor line() # +# # +############################################################################ +# +# editing commands for the line editor: +# ctrl/A: byte forward (arrow right) +# ctrl/B: byte back (arrow left) +# ctrl/D: beginning of line (home) +# ctrl/E: end of line (end) +# ctrl/F: del byte (del) +# ctrl/G: del word +# ctrl/H: word forward (ctrl/right) +# ctrl/I: word back (ctrl/ left) +# ctrl/L: perform block operation +# 1. press ctrl/L +# 2. enter relative adress (followed by <ret>) for +# block end. It must be an (numerical) offset +# pointing right to the actual cursor. +# 3. enter "r" (no <ret>!) for remove or "b" +# to move block to the beginning of field +# or "e" to transfer it to the end. +# Annotation: "impossible" adresses (beyond string +# length or negative) will be ignored. +# alt/A : wrap line (+ 1) +# esc : del line +# ctrl/K: restore line +# ctrl/n: quit line (- 1) (arrow up) +# ctrl/U: quit line (+ 1) (arrow down) +# ret : quit line (+ 1) +############################################################################ +# +# Function to edit a line. The function needs the following +# arguments +# row : (row of the line to be edited) +# bnumber: (maximum size of the string to be +# edited, further input will be +# ignored.) +# status: display actual line_number and col2 if +# status == 1 else not +# comment: (comment or input prompt) +# field : (contains the string to be edited.) +# +# The function returns a list with the first element containing +# The main part of FIELD and the second element containing +# the wrapped part if any. +# + procedure line(row,bnumber,status,comment,field) + + local beg, blank, blanks, block, byte, byte_input, col, col2, dec_byte + local dec_bytes, e1, e2, editing, fa, fb, field2, field_1, field_2 + local field_a, field_b, fieldl, highl, lg, mark, n_blank, nb, normal + local quit, r_field, rest + +# Define csets containing the keys for +# input +# editing functions +# quit / wraP +# +# Characters permitted in the edited field + n_blank := &ucase ++ &lcase ++ &digits ++ '?.,;!' + byte_input := n_blank ++ ' ' +# Characters for the editing functions + e1 := set([char(1),char(2),char(4),char(5),char(6),char(7),char(8)]) + e2 := set([char(27),char(11)]) + editing := e1 ++ e2 +# Characters to end editing + quit := set([char(13),char(30),char(14),char(21)]) +# +# List to return result + fieldl := list() +# Initialize field_a/b for a concatenation, if scanning field +# fails + field_a := "" + field_b := "" +# Initialize r_field (variable to store completely deleted field +# to keep it recoverable) + r_field := "" +# Codes to highlight screen output and to return to normal +# screen outpuT + highl := char(27) || "[7m" + normal := char(27) || "[0m" +# +# Remove single initial blank if any + if field[1] == " " then { + field := field[2:(*field+1)] + } +# +# Display field when beginning the editing process, place +# cursor behind the end of field + locate(row,1) + writes(comment,field,repl(" ",(bnumber-*field))) +# If status is set to 1 display line_number and col2 after the +# initial printing of line + if status == 1 then stat_line(*field+1) +# col: absolute cursor position (comment and field) +# col2: relative position in field + col := (*comment + *field) + 1 + col2 := *field + 1 + locate(row,col) +# +# Editing loop: continue until end character appears + while byte := getch() & not member(quit,byte) do { + if find(byte,byte_input) & *field <= bnumber - 2 then { +# If byte is a normal character (if member(byte_input,byte)) insert +# it into field at cursor position. +# + field ? { + field_a := tab(col2) + field_b := tab(0) + } + field := field_a || byte || field_b + locate(row,1) + writes(comment,field) + col +:= 1 + col2 +:= 1 + if status == 1 then stat_line(col2) + locate(row,col) + } +# else perform editing operation + else { + case byte of { +# backspace (ctrl/B) + char(2) : if col2 > 1 then { + col -:= 1 + col2 -:= 1 + if status == 1 then stat_line(col2) + locate(row,col) + } +# byte forward (ctrl/A) + char(1) : if col2 <= *field then { + col +:= 1 + col2 +:= 1 + if status == 1 then stat_line(col2) + locate(row,col) + } +# goto beginning of line (ctrl/D) + char(4) : { + col2 := 1 + col := *comment + col2 + if status == 1 then stat_line(col2) + locate(row,col) + } +# goto end of line (ctrl/E) + char(5) : { + col2 := (*field + 1) + col := *comment + col2 + if status == 1 then stat_line(col2) + locate(row,col) + } +# delete byte at cursor position (ctrl/F) + char(6) : { + if col2 <= *field then { + field ? { + beg := tab(col2) + rest := tab(0) + + } + rest[1] := "" + field := beg || rest + locate(row,1) + writes(comment,field," ") + locate(row,col) + } + } +# +# delete the actual word (ctrl/G) + char(7) : { + field2 := remword(field,col2 - 1) + blanks := *field - *field2 + field := field2 + col2 := col2 - blanks + if col2 <= 0 then col2 := 1 + col := *comment + col2 + locate(row,1) + writes(comment,field,repl(" ",blanks)) + if status == 1 then stat_line(col2) + locate(row,col) + } + +# move to the beginning of the following word (ctrl/H) + char(8) : { + if find(" ",field[col2:*field]) then { + string := field[col2:*field] + blank := find(" ",string) + col2 := col2 + blank + col := *comment + col2 + if status == 1 then stat_line(col2) + locate(row,col) + } + } +# +# move to the beginning of the recent word (ctrl/I) + char(9) : { +# jump over the blank preceding the actual word + if col2 = 1 then locate(row,col) + else { + if find(" ",field[1:(col2 - 2)]) then { + string := field[1:(col2 - 2)] + col2 := (last(" ",string) + 2) + } + else { + col2 := 1 + } + col := *comment + col2 + if status == 1 then stat_line(col2) + locate(row,col) + } + } +# +# Delete complete line, deleted line is assigned to r_field +# to be recoverable + char(27) : { + lg := *field + r_field := field + field := "" + col2 := 1 + col := *comment + col2 + locate(row,1) + writes(comment,repl(" ",lg)) + if status == 1 then stat_line(col2) + locate(row,col) + } +# Restore deleted line (overwrite new actual line, assigning it +# to r_field) + char(11) : { + if *r_field >= 1 then { + field :=: r_field + col2 := *field + 1 + col := *comment + col2 + locate(row,1) + blanks := bnumber - *field + writes(comment,field,repl(" ",blanks)) + if status == 1 then stat_line(col2) + locate(row,col) + } + } + +# Perform block operation + char(12) : { + mark := "" + dec_bytes := "" + while nb := getch() & nb ~== char(13) do { + mark ||:= nb + } + if mark < 1 then mark := 1 +# Place cursor to field's beginning if it points to its end + if col2 >= *field then col2 := 1 + field ? { + fa := tab(col2) + block := move(mark) + fb := tab(0) + } + locate(row,1) + writes(comment,fa,highl,block,normal,fb) + dec_byte := getch() + if dec_byte == ("r" | "R") then { + field := fa || fb + locate(row,1) + writes(comment,field,repl(" ",*block + 1)) + col2 := col2 - *block + if col2 < 1 then col2 := 1 + col := *comment + col2 + if status == 1 then stat_line(col2) + locate(row,col) + } + else { + if dec_byte == ("b" | "B") then { + field := block || fa || fb + } + if dec_byte == ("e" | "E") then { + field := fa || fb || block + locate(row,1) + } + locate(row,1) + writes(comment,field) + locate(row,col) + } + } + +# right brace closing case control structure + } +# right brace closing else structure (editing keys) + } +# right brace closing while-do loop + } +# +# if while-do loop stops it must be because of a key in quit. +# Therefore perform final operation and return. +# +# wrap: divide field at the last possible blank, assign the +# first part to the first element of list result, the second +# part to the second element. + if byte == char(30) & find(" ",field) then { + blank := last(" ",field) + field_1 := field[1:(blank + 1)] + field_2 := field[(blank + 2):(*field + 1)] + locate(row,(*comment + 1)) + writes(field_1,repl(" ",*field_2)) + put(fieldl,field_1) + put(fieldl,field_2) +# Increase lnumber by 1 + line_number := 1 +# Return list with main part and wrapped part as its elements + return fieldl + } +# +# normal termination by <ret> or <arrow down> + if byte == (char(13) | char(21)) then { + put(fieldl,field) + put(fieldl,"") + line_number := 1 + return fieldl + } +# normal termination by alt/e + else { + if byte == char(14) then { + put(fieldl,field) + put(fieldl,"") + line_number := -1 + return fieldl + } + } +end +# +############################################################################ +# # +# field editor edit_field() # +# # +############################################################################ +# +# edit_field: user-defined function to divide a long string into +# lines and edit them as a field. uses: line() and all user- +# defined functions called by line(). +# edit_field() accepts its data in a single string which is +# cracked apart before editing and put together afterwards. +# exceeding the size of the field (lnumber) by moving the +# cursor out of it, finishes the editing process. +# +# Annotation: edit_field() doesn't contain anything needed +# by line() and therefore should be removed if only line() +# is to be used. +# +# arguments to the function: +# startline : first line on the screen +# lnumber : number of lines within field +# byte_n : number of bytes permitted within a line +# label : label to be displayed as field's headline +# string : string to be edited + procedure edit_field(startline,lnumber,byte_n,label,string) + + local feld, item, lin, liste, n, res, rest + +# Fail if "editing beyond the end of screen" is tried or byte_n is +# too big + if {(lnumber + startline > 24) | (byte_n > 77)} then { + write("ERROR: ILLEGAL ARGUMENT!") + fail + } + n := 1 +# Initialize feld as a list to contain string's contents + feld := list(lnumber,"") +# Crack apart string into byte_n-byte items. + while lin := string[1:byte_n] do { +# Assign every item's substring upto the last " " to field[n] + feld[n] := lin[1:last(" ",lin)+1] +# Assign the rest to rest + rest := lin[(last(" ",lin)+2):*lin+1] +# Delete the first byte_n bytes, then concatenate rest and string + string[1:byte_n] := "" + string := rest || string + n +:= 1 + } + feld[n] := string +# Display field's contents + n := 1 + locate(startline-1,1) + writes(center(label,(byte_n-5)," ")) + while n <= lnumber do { + locate(startline-1+n,1) + writes(feld[n]) + n +:= 1 + } +# Begin editing process + line_number := 1 + lin_nm := 1 +# Stop if access to non permitted line number (0,>lnumber) is +# tried. + while lin_nm >= 1 & lin_nm <= lnumber do { +# locate(23,40) +# write("ZEILENTYP: ",type(startline)) +# read() + liste := line(startline,byte_n,1," ",feld[lin_nm]) + feld[lin_nm] := liste[1] + locate(startline,1) + writes(feld[lin_nm],repl(" ",byte_n-*feld[lin_nm]+1)) + startline +:= line_number + lin_nm +:= line_number +# If wrap demanded and the following line is capable to contain +# the wrapped rest of the line before and its original content, +# perform wrap. + if *liste[2] + *feld[lin_nm] <= byte_n then { + feld[lin_nm] := liste[2] || " " || feld[lin_nm] + } + } +# Set flag field_flag to -1/1 to indicate the direction +# in which the field has been quitted. + if lin_nm <= 1 then field_flag := -1 + if lin_nm >= lnumber then field_flag := 1 +# Put the string to be returned together of feld's elements. + res := "" + while item := pop(feld) do { + res := res || " " || item + } + return res +end +# +# show_field: see edit field (except editing routines) for +# details. + procedure show_field(startline,lnumber,byte_n,label,string) + + local feld, lin, n, rest + + if {(lnumber + startline > 24) | (byte_n > 77)} then { + write("ERROR: ILLEGAL ARGUMENT!") + fail + } + n := 1 + feld := list(lnumber,"") + while lin := string[1:byte_n] do { + feld[n] := lin[1:last(" ",lin)+1] + rest := lin[(last(" ",lin)+2):*lin+1] + string[1:byte_n] := "" + string := rest || string + n +:= 1 + } + feld[n] := string + n := 1 + locate(startline-1,1) + writes(center(label,(byte_n-5)," ")) + while n <= lnumber do { + locate(startline-1+n,1) + writes(feld[n]) + n +:= 1 + } +end +# +# edit_item(): function to edit the entry concerning one item +# of literature. This function makes it necessary to declare +# a fixed structure of every item within the function +# "#" separates the fields from each other. it shouldn't be +# contained in the data given to edit_item(). +# +# Structure of an item: +# TITLE +# AUTHOR +# YEAR +# TYPE +# COMMENT1 +# COMMENT2 + procedure edit_item(item) + + local ct, feld, felder, felder2, item2, labels, lin_e, n, zeile + + felder := list() + felder2 := list() + labels := ["AUTHOR","TITLE","YEAR","TYPE","COMMENT1","COMMENT2"] + item ? { + while feld := tab(upto("#")) do { + move(1) + put(felder,feld) + put(felder2,feld) + } + } + zeile := 2 +# Display the fields + n := 1 + while feld := get(felder) do { + show_field(zeile,2,70,labels[n],feld) + n +:= 1 + zeile +:= 4 + } +# Start editing process + ct := 1 + zeile := 2 + while zeile >= 2 & zeile <= 22 do { + felder2[ct] := edit_field(zeile,2,70,labels[ct],trim(felder2[ct])) + ct +:= field_flag + if field_flag = 1 then zeile +:= 4 else zeile -:= 4 + } +# Indicate the direction in which item has been quitted using +# global variable item_flag + if zeile < 2 then item_flag := -1 else item_flag := 1 + item2 := "" +# Format result: item's fields are brought up to a standard length +# of 140 bytes using blanks. + while lin_e := get(felder2) do { + item2 ||:= lin_e || repl(" ",(140 - *lin_e)) || "#" + } + return item2 +end +# +# brightwrite(string): function to highlight a string + procedure brightwrite(string) + + local highl, normal + + highl := char(27) || "[7m" + normal := char(27) || "[0m" + writes(highl,string,normal) +end +# +# findlist(wlist,item): function to return the first +# position of item in wlist. + procedure findlist(wlist,item) + + local n + + n := 1 + while n <= *wlist do { + if wlist[n] == item then return n + n +:= 1 + } + fail +end +# +# menue(header,wlist,klist): function to build up a menuE +# Arguments: header, list of options (wlist) and list of +# shorthand keys (key list). +# because menue() fails if a non defined key (not contained +# in klist, no arrow key), calls to menue() should be made +# within a loop terminated on menue()'s success, see below +# main(). + procedure menue(header,wlist,klist) + + local add, byte, n + + locate(4,10) + writes(header) + n := 5 + while (n - 4) <= *wlist do { + locate(n,10) + writes(wlist[n-4]) + n +:= 1 + } + n := 5 + locate(n,10) + brightwrite(wlist[n-4]) + while byte := getch() & { + byte == (char(21) | char(14)) | findlist(klist,byte) + } + do { +# If byte Is element of klist (shorthandkey) the element number +# within the list + 4 indicates option. + if add := findlist(klist,byte) then { + locate(n,10) + writes(wlist[n-4]) + n := 4 + add + locate(n,10) + brightwrite(wlist[n-4]) + } +# else increase/decrease actual element by one. + else { + if byte == char(14) then add := -1 + if byte == char(21) then add := 1 + locate(n,10) + writes(wlist[n-4]) + n +:= add + if (n - 4) < 1 then n +:= 1 + if (n - 4) > *wlist then n -:= 1 + locate(n,10) + brightwrite(wlist[n-4]) + } + } + if byte == char(13) then return wlist[(n-4)] else fail +end +# +# in_itemm(): function to create new items. Standard file is literat.fil +# The new items are handled as a sequential file which is added to the +# existing file when input process is finished. + procedure in_itemm() + + local answer, count, items, itnum, out_item + + item_flag := 1 + items := list(200,"######") + itnum := 0 + repeat { + itnum +:= item_flag + if itnum < 1 then itnum := 1 + items[itnum] := edit_item(items[itnum]) + writes(char(27),"[2J") + write("NEW ITEM? Yy/Nn!") + answer := getch() + if answer == ("n" | "N") then break + } + count := 1 + out_item := open("literat.fil","a") + while items[count] ~== "######" do { + writes(out_item,items[count]) + count +:= 1 + } + close(out_item) +end +# +# turn_over(): view and edit literat.fil item by item + procedure turn_over() + + local answer, in_item, it, out_item + + in_item := open("literat.fil","r") + out_item := open("literat2.fil","w") + repeat { + it := reads(in_item,846) + it := edit_item(it) + writes(out_item,it) + writes(char(27),"[2J") + write("NEW ITEM? Yy/Nn!") + answer := getch() + if answer == ("n" | "N") then break +# If item_flag is -1 seek -1692 (2 items) to access the beginning of the +# previous item because the internal file pointer points to the end of +# the actual item. + if item_flag == -1 then seek(in_item,where(in_item)-1692) + } + close(in_item) + close(out_item) +end +# +# del(num) remove numth item from filE + procedure del() + + local fil, in_item, itm, n, num, out_item + + writes(char(27),"[2J") + write("NUMBER OF ITEM TO BE REMOVED?") + num := read() + write("READING...") + fil := list() + in_item := open("literat.fil","r") + while itm := reads(in_item,846) do { + put(fil,itm) + } + close(in_item) + write("START OVERWRITE PROCESS...") + n := num + while n < *fil do { + fil[n] := fil[n+1] + n +:= 1 + } + fil[*fil] := "" + out_item := open("literat2.fil","w") + write("WRITING...") + while itm := get(fil) & itm ~== "" do { + writes(out_item,itm) + } + close(out_item) + write("DONE...") +end +# +# alpha: sorting in alphabetical order + procedure alpha() + + local fil, in_item, itm, out_item + + writes(char(27),"[2J") + write("READING...") + fil := list() + in_item := open("literat.fil","r") + while itm := reads(in_item,846) do { + put(fil,itm) + } + close(in_item) + write("ARRANGING DATA IN ALPHABETICAL ORDER...") + fil := sort(fil) + write("WRITING...") + out_item := open("literat2.fil","w") + while itm := get(fil) & itm ~== "" do { + writes(out_item,itm) + } + close(out_item) + write("DONE...") +end +# +# m_adress: function to generate a file with arguments to the seek() +# function. The file (adress.fil) will be used for sequential +# search in the computer's ram, (function (query()). The results enable +# the seek() function to place the internal file pointer on the desired +# item in literat.fil. + procedure m_adress() + + local a, adr, b, in_item, item, m, n, out_adr, out_line, wlist, wlist_2 + + out_line := "" + adr := edit_field(4,10,70,"FORMAT: <WORD>;<WORD>;ETC.","") + writes(char(27),"[2J") + write("GENERATING WORD LIST...") + wlist := list() + n := 1 + adr ? { + while put(wlist,tab(upto(";"))) do { + move(1) + write("ACTUAL WORD: ",wlist[n]) + n +:= 1 + } + } + in_item := open("literat.fil","r") + n := 1 + + wlist_2 := copy(wlist) +# Insert ; between word in wlist_2 and seqence of record numbers +# to be found out later. + while n <= *wlist_2 do { + wlist_2[n] ||:= ";" + n +:= 1 + } + n := 1 + while n <= *wlist do { + write("COMPARING WORD NUMBER: ",n,".") +# counter m: indicates record number + m := 1 + while item := reads(in_item,846) do { + if find(wlist[n],item) then { + wlist_2[n] ||:= m || ";" + } + m +:= 1 + } + wlist_2[n] ? { + a := tab(upto(";")) + b := tab(0) + } + if b == ";" then b := ";0" + wlist_2[n] := a || b + out_line ||:= wlist_2[n] || ":" +# When every item has been compared with wlist[n], move file +# pointer to the beginning of in_item and increase n by 1. + seek(in_item,1) + n +:= 1 + } + close(in_item) +# Remove trailing blank if any + if out_line[1] := " " then { + out_line := out_line[2:(*out_line+1)] + } + write("WRITING ADRESS FILE") + out_adr := open("adress.fil","a") + writes(out_adr,out_line) + close(out_adr) + write("OK") +end +# +# query(): find items using the numbers in adress.fil * 846 as +# arguments to the seek() function + procedure query() + + local byte, in_item, in_line, in_query, it_key, kkey, out_item, word, wrd + + writes(char(27),"[2J") + in_query := open("adress.fil","r") + in_line := read(in_query) + close(in_query) + in_item := open("literat.fil","r") + out_item := open("literat2.fil","a") + wrd := line(10,20,0,"TYPE WORD TO BE LOOKED FOR: ","") + word := wrd[1] + if byte := find(word,in_line) then { + in_line ? { + move(byte) + it_key := tab(upto(":")) + } + } + else { + locate(10,25) + writes("ERROR: UNKNOWN WORD! PRESS KEY!") + getch() + fail + } +# place internal cursor behind the first ; to get the first +# number: + it_key := it_key[find(";",it_key)+1:*it_key+1] + it_key ? { + while kkey := tab(upto(";")) do { + if kkey <= 0 then { + locate(10,25) + writes("ERROR: UNKNOWN WORD! PRESS KEY!") + getch() + fail + } + seek(in_item,(kkey-1)*846) + writes(out_item,edit_item(reads(in_item,846))) + move(1) + } + } + close(in_item) + close(out_item) + write("OK") +end +# +# main program. see the description of the program's functionS +# at the beginning of the source code and of every user-defined +# function if you are in doubt how to use them. +# + procedure main() + + local alist, blist, opt + + newkey() + alist := { + ["iNPUT","tURN OVER ITEMS","aDRESS FILE","qUERY","dEL","AlPHA","eND"] + } + blist := ["i","t","a","q","d","l","e"] + repeat { + repeat { + writes(char(27),"[2J") + locate(1,10) + write("LITERAT: EASY DATABASE SYSTEM") + locate(2,10) + write("WRITTEN BY: MATTHIAS HEESCH 1992") + if opt := menue("MENUE",alist,blist) then break + } + writes(char(27),"[2J") + case opt of { + "iNPUT" : in_itemm() + "tURN OVER ITEMS" : turn_over() + "aDRESS FILE" : m_adress() + "qUERY" : query() + "dEL" : del() + "AlPHA" : alpha() + "eND" : break + } + } +end |