{$S+}{} program index(input,output) ; { This PASCAL MT+ index generator program is placed in the public domain on the understanding that it is for non-profit redistribution via individuals for through RCPM systems Donated 23/6/83 Matthew Starr P.O. Box 25 Wahroonga N.S.W 2076 Australia Matthew Starr 13/12/81 WordStar index generator program which will read through WordStar disk file output files and include strings delimited by ^Q and ^W as Major and Minor references respectively, creating an index which is then sorted and output as a WordStar source file. A required option for the Disk-file print is form feed page separation. (See procedure HELP) } const main_code = 17 ; {code for boldface ref} sub_code = 23 ; {code for normal ref} bold_code = 2 ; {makes it boldface} formfeed = 12 ; stringz = 50 ; {P.S. also change assgmnt} max_entries = 500 ; {max # different entries} max_refs = 5 ; {max # refs of either type} type my_string = packed array[1 .. stringz] of char ; pointer = ^entry_type ; entry_type = record subject : my_string ; n_mains : integer ; mains : array[1 .. max_refs] of integer ; n_subs : integer ; subs : array[1 .. max_refs] of integer ; end ; { entry decl. } table_type = array[1 .. maxentries] of pointer ; ws_file = file of char ; index_file = file of entry_type ; var index : index_file ; text_in : ws_file ; text_out : text ; end_file : entry_type ; table : table_type ; filename,response : string ; i, num_entries, result : integer ; procedure addentry(var table:table_type; var tablength:integer; newentry:entry_type) ; begin if tablength >= max_entries then writeln('Too many entries - entry table full') else begin tablength := tablength+1 ; new(table[tablength]) ; table[tablength]^ := newentry end { else there is room } end; procedure readarray(var name:my_string) ; var ch : char; nameindex : 0 .. stringz; procedure uppercase(var ch:char) ; begin if ord(ch)>127 then ch := chr( ord(ch) - 128 ) ; if (ch >= 'a') and (ch <='z') then ch := chr( ord(ch)-(ord('a')-ord('A')) ); end ; {uppercase} begin name := ' ' ; nameindex := 0 ; read(text_in,ch) ; uppercase(ch) ; while (name_indexmain_code) and (ord(ch)<>sub_code) do begin nameindex := nameindex+1 ; name[nameindex] := ch ; read(text_in,ch) ; uppercase(ch) { and throw away terminating control code } end {while} end ; {readarray} procedure get_main (var table:tabletype; var tablength:integer; var page, created, added_to:integer); var name: my_string; this_entry: entry_type; i: integer; begin readarray(name); i := 1 ; while (i<=num_entries) and (name<>table[i]^.subject) do i:=i+1 ; if i>num_entries { i.e. if not found } then begin { create a new entry } with this_entry do begin created := created + 1 ; subject := name ; n_mains := 1 ; n_subs := 0 ; mains[1] := page end { with } ; addentry(table,tablength,this_entry) end {then} else {add to the ith entry} with table[i]^ do begin added_to := added_to + 1 ; if n_mains >= max_refs then writeln('Too many main references to ',subject) else begin n_mains := n_mains+1 ; mains[n_mains] := page end {else} end {with} end ; {get_main} procedure get_sub (var table:tabletype; var tablength:integer; var page, created, added_to:integer); var name: my_string; this_entry: entry_type; i: integer; begin readarray(name); i := 1 ; while (i<=num_entries) and (name<>table[i]^.subject) do i:=i+1 ; if i>num_entries {i.e. was it found ?} then begin { create a new entry } with this_entry do begin created := created + 1 ; subject := name ; n_mains := 0 ; n_subs := 1 ; subs[1] := page ; end { with } ; addentry(table,tablength,this_entry) end {then} else with table[i]^ do begin added_to := added_to + 1 ; if n_subs >= max_refs then writeln('Too many minor references to ',subject) else begin n_subs := n_subs+1 ; subs[n_subs] := page end {else} end {with} end ; {get_sub} procedure scanfile (var table:tabletype; var tablength:integer; filename:string); var ch:char ; page, created, added_to : integer ; begin created := 0 ; added_to := 0 ; assign(text_in,filename) ; reset(text_in) ; if ioresult = 255 then writeln('Could not open ',filename) else begin write('Page number start for this file? '); read(page) ; while not eof(text_in) do begin read(text_in,ch) ; if ord(ch)=formfeed then page := page + 1 else if ord(ch)=main_code then get_main(table,tablength,page, created, added_to) else if ord(ch)=sub_code then get_sub(table,tablength,page, created, added_to) end ; writeln(created,' new entries created'); writeln(added_to,' references added to existing subjects.') end { else file opened successfully } end ; { scanfile } function lessthan(el1,el2 : pointer) : boolean ; {compare the two entries as per ascii} begin lessthan := el1^.subject < el2^.subject end ; {compare} procedure swap(var el1,el2 : pointer) ; {swap two entries pointed to by el1, el2} var temporary : pointer ; begin temporary := el1 ; el1 := el2 ; el2 := temporary end {swap} ; procedure split( var splitee :table_type; low,high :integer; var midindex :integer) ; var middle : pointer ; flag,up,down : integer ; begin up := low ; down := high+1 ; middle := splitee[low]; {split from first entry} flag := 1 ; while up < down do if flag = 1 then {search downwards for a wrong one} begin down := down-1 ; if (up<>down) and not lessthan(middle,splitee[down]) then begin flag := 0 ; splitee[up] := splitee[down] end {THEN it's out of place} end {THEN try and find a wrong one down} else {search upwards for a wrong one} begin up := up + 1 ; if (up <> down) and lessthan(middle,splitee[up]) then begin flag := 1 ; splitee[down] := splitee[up] end {THEN it's out of place} end {ELSE try finding a wrong one upwards}; splitee[up] := middle ; {fit splitting element back} midindex := up ; {where it was split} end ; {split} procedure quicksort(var sortee: table_type; lower,upper:integer) ; var centre : integer ; begin if lower < upper then begin split(sortee,lower,upper,centre) ; quicksort(sortee,lower,centre-1) ; quicksort(sortee,centre+1,upper) end {then} end; {quicksort} procedure writeentry(var outfile:text; item : entry_type) ; var j : integer ; begin with item do begin write(outfile,subject) ; if n_mains <> 0 then begin write(outfile,chr(bold_code)) ; write(outfile,mains[1]:1) ; for j := 2 to n_mains do write(outfile,',',mains[j]:1) ; write(outfile,chr(bold_code)) ; if n_subs <> 0 then write(outfile,',') end ; {then} if n_subs <> 0 then begin write(outfile,subs[1]:1) ; for j := 2 to n_subs do write(outfile,',',subs[j]:1) end ; { then } writeln(outfile) end {with} end ; {writeentry} procedure help; var null_line : string ; begin writeln(' This program generates a WordStar source') ; writeln('file of an index for manuals, etc.') ; writeln(' The index can be compiled from many files') ; writeln('which may be scanned at different times.') ; writeln(' The cumulative index file is stored in a') ; writeln('file called "index" and is updated after') ; writeln('each run of this program, so ERAse it when') ; writeln('you want to restart the index compilation') ; writeln(' The input files you are prompted for MUST') ; writeln('be "DISK FILE OUTPUT"s from the WordStar') ; writeln('Print command, with the FORMFEED option') ; writeln(' The output file is WordStar compatible,') ; writeln('and may be ^K Read into an index framework'); write('Press return') ; read (null_line) ; writeln(' To mark an item for inclusion as one of'); writeln('the main references, use ^KQ.') ; writeln(' To mark a minor reference, use ^KW') ; writeln(' These markers must SURROUND the reference'); writeln('as for underlining.') ; writeln(' The main references are listed first in'); writeln('BOLD type, and the minors after that in') ; writeln('normal type') ; writeln(' All marked text is converted to UPPER case'); writeln('The max. number of references per subject'); writeln('is ',max_refs,', and the maximum number of'); writeln('subjects is ',max_entries) end ; {help} begin {main program} assign(index,'index') ; { read in as much of the index as has been done already } num_entries := 0 ; reset(index) ; if ioresult <> 255 then begin while (index^.n_mains<>-1) and not eof(index)do begin addentry(table,num_entries,index^) ; get(index) end {while} end ; {then} writeln(num_entries,' entries read from old index file'); { read in the new WordStar source files to be scanned } repeat writeln('Enter name of WordStar print file, or CR to continue') ; read(filename) ; if filename <> '' then if (filename = 'help') or (filename = 'HELP') then help else scanfile(table,num_entries,filename) until filename = '' ; { sort the new index } quicksort(table,1,num_entries) ; { save the new index } rewrite(index) ; if ioresult = 255 then writeln('Could not update index file') else begin { write index to the file } for i := 1 to num_entries do write(index,table[i]^) ; { now add end of file mark with n_mains =-1 } end_file.n_mains := -1 ; write(index,end_file) ; close(index,result) ; if ioresult = 255 then writeln('Could not close index file') else writeln(num_entries,' entries written to index file') end {else} ; { ask if a WordStar output file is required yet } write('Is a WordStar output file required yet (y/n) ? ') ; read(response) ; if (response[1] = 'y') or (response[1] = 'Y') then begin write('What filename ? ') ; read(filename) ; assign(text_out,filename) ; rewrite(text_out) ; if ioresult = 255 then writeln('Could not create ',filename) else begin for i := 1 to num_entries do writeentry(text_out,table[i]^); close(text_out,result) end {else} end {then} end. {index} .