From: SMTP%"VMSSERV@kcl.ac.uk" 19-AUG-1996 18:19:49.55 To: everhart@star.zko.dec.com CC: Subj: WEBBOOK.1-OF-5 $! ------------------ CUT HERE ----------------------- $ v='f$verify(f$trnlnm("SHARE_UNPACK_VERIFY"))' $! $! This archive created: $! Name : WEBBOOK $! By : Andy Harper $! Date : 19-JUN-1996 12:01:51.84 $! Using: VMS_SHARE 8.5-1, (C) 1993 Andy Harper, Kings College London UK $! $! Credit is due to these people for their original ideas: $! James Gray, Michael Bednarek $! $! To unpack this archive: $!+ Ensure that all parts are present, (5 at about 60 Blocks each). $!+ Append all parts together to form one larger file. $! Minimum of VMS 4.4 (VAX) / OpenVMS 1.0 (Alpha) is required. $! Remove the headers of the first part, up to `cut here' line. $! Execute file as a command procedure. $! $! The following file(s) will be created after unpacking: $! 1. [.WEBBOOK]AAAREADME.WEBBOOK;1 $! 2. [.WEBBOOK]BOOKFILE_DEMO.C;1 $! 3. [.WEBBOOK]BOOKFILE_DEMO.OPT;1 $! 4. [.WEBBOOK]BOOKFILE_FIGURE.C;1 $! 5. [.WEBBOOK]BOOKFILE_FIGURE.H;1 $! 6. [.WEBBOOK]BOOKFILE_INDEX.C;1 $! 7. [.WEBBOOK]BOOKFILE_INDEX.H;1 $! 8. [.WEBBOOK]BOOKFILE_IO.C;1 $! 9. [.WEBBOOK]BOOKFILE_IO.H;1 $! 10. [.WEBBOOK]BOOKFILE_SECTION.C;1 $! 11. [.WEBBOOK]BOOKFILE_SECTION.H;1 $! 12. [.WEBBOOK]BOOKFILE_TEXT.C;1 $! 13. [.WEBBOOK]BOOKFILE_TEXT.H;1 $! 14. [.WEBBOOK]BOOKREADER_RECDEF.H;1 $! 15. [.WEBBOOK]BUILD_WEBBOOK.COM;1 $! 16. [.WEBBOOK]WEBBOOK.C;1 $! 17. [.WEBBOOK]WEBBOOK.OPT;1 $! 18. [.WEBBOOK]WEBBOOK_SHELF.C;1 $! 19. [.WEBBOOK.HTTP.SERVERDOC]BOOK.XBM;1 $! 20. [.WEBBOOK.HTTP.SERVERDOC]SHELF.XBM;1 $! $ set="set" $ set symbol/scope=(nolocal,noglobal) $ f="SYS$SCRATCH:."+f$getjpi("","PID")+";" $ if f$trnlnm("SHARE_UNPACK") .nes. "" then $ - f=f$parse("SHARE_UNPACK_TEMP",f) $ e="write sys$error ""%UNPACK"", " $ w="write sys$output ""%UNPACK"", " $ if .not. f$trnlnm("SHARE_UNPACK_LOG") then $ w = "!" $ if f$getsyi("CPU") .gt. 127 then $ goto start $ ve=f$getsyi("version") $ if ve-f$extract(0,1,ve) .ges. "4.4" then $ goto start $ e "-E-OLDVER, Must run at least VMS 4.4" $ v=f$verify(v) $ exit 44 $unpack:subroutine!P1=file,P2=chksum,P3=attrib,P4=size,P5=fileno,P6=filetotal $ if f$parse(P1) .nes. "" then $ goto dirok $ dn=f$parse(P1,,,"DIRECTORY") $ w "-I-CREDIR, Creating directory ''dn'" $ create/dir 'dn' $ if $status then $ goto dirok $ e "-E-CREDIRFAIL, Unable to create ''dn' File skipped" $ delete 'f'* $ exit $dirok: $ x=f$search(P1) $ if x .eqs. "" then $ goto file_absent $ e "-W-EXISTS, File ''P1' exists. Skipped" $ delete 'f'* $ exit $file_absent: $ w "-I-UNPACK, Unpacking ", P5, " of ", P6, " - ", P1, " - ", P4, " Blocks" $ n=P1 $ if P3 .nes. "" then $ n=f $ if .not. f$verify() then $ define/user sys$output nl: $ EDIT/TPU/NOSEC/NODIS/COM=SYS$INPUT/NOJOURNAL 'f'/OUT='n' PROCEDURE GetHex(s,p)LOCAL x1,x2;x1:=INDEX(t,SUBSTR(s,p,1))-1;x2:=INDEX(t, SUBSTR(s,p+1,1))-1;RETURN 16*x1+x2;ENDPROCEDURE;PROCEDURE SkipPartsep LOCAL m; LOOP m:=MARK(NONE);EXITIF m=END_OF(CURRENT_BUFFER);DELETE(m);EXITIF INDEX( ERASE_LINE,"-+-+-+-+-+-+-+-+")=1;ENDLOOP;ENDPROCEDURE; PROCEDURE ProcessLine LOCAL c,s,l,b,n,p;s := ERASE_LINE;EDIT(s,TRIM);c := SUBSTR(s,1,1);s := s-c;IF c = "X" THEN SPLIT_LINE; ENDIF;MOVE_HORIZONTAL(-1); l := LENGTH(s);p := 1;LOOP EXITIF p > l;c := SUBSTR(s,p,1);p := p+1; CASE c FROM ' ' TO '`' ['\']: b:=GetHex(s,p); n:=GetHex(s,p+2); p:=p+4; COPY_TEXT( SUBSTR(CURRENT_LINE,CURRENT_OFFSET-b+1,n));['&']: b:=GetHex(s,p); n:=GetHex(s,p+2); p:=p+4; COPY_TEXT(ASCII(n)*b);['`']: COPY_TEXT(ASCII(GetHex( s,p))); p:=p+2;[INRANGE,OUTRANGE]: COPY_TEXT(c);ENDCASE;ENDLOOP;ENDPROCEDURE; PROCEDURE Decode(b)LOCAL m;POSITION(BEGINNING_OF(b));LOOP m:=MARK(NONE); EXITIF m=END_OF(b);DELETE(m);IF INDEX(CURRENT_LINE,"+-+-+-+-+-+-+-+-")= 1 THEN SkipPartSep;ELSE ProcessLine;MOVE_HORIZONTAL(1);ENDIF;ENDLOOP; ENDPROCEDURE;SET(FACILITY_NAME,"UNPACK");SET(SUCCESS,OFF);SET(INFORMATIONAL, OFF);t:="0123456789ABCDEF";f:=GET_INFO(COMMAND_LINE,"file_name");o:= CREATE_BUFFER(f,f);Decode(o);WRITE_FILE(o,GET_INFO(COMMAND_LINE,"output_file")) ;QUIT; $ if p3 .eqs. "" then $ goto dl $ open/write fdl &f $ write fdl "RECORD" $ write fdl P3 $ close fdl $ w "-I-CONVRFM, Converting record format to ", P3 $ convert/fdl='f' 'f'-1 'f' $ fa=f$getdvi(f$parse(f),"ALLDEVNAM") $ Pa=f$getdvi(f$parse(P1),"ALLDEVNAM") $ if fa .eqs. Pa then $ rename &f 'f$parse(P1)' $ if fa .nes. Pa then $ copy &f 'f$parse(P1)' $dl: delete 'f'* $ checksum 'P1' $ if checksum$checksum .nes. P2 then $ - e "-E-CHKSMFAIL, Checksum of ''P1' failed." $ exit $ endsubroutine $start: $! $ create 'f' XHere is a summary of the changes for this maintainence round (5-may-1996) Xfor webbook: X X - Integrate bookshelf program into webbook script, routine in X file webbook_shelf.c is called when path_info ends in slash. X X - Modify webbook_shelf.c to include full file spec in HREFS, allowing X shelves to point to other directories. X X - Fix formatting for document text to use character as non-breaking X space rather than
construct. X X - Fix bug in generation of GIF output done by bookfile_figure.c. X XTo install: X X 1. Unpack the zip file in the webbook.\1810`5B.script_code`5D X directory of (code relies upon cgilib.*, script\0D07link_\1206.com). X `20 X 2. Copy book.xbm and shelf.xbm to the `5B.serverdoc`5D (url path /demo/)`20 X directory. If you wish to locate the icon files elsewhere, edit X webbook_shelf.c and change the SHELF_ICON and BOOK\0F06macro X definitions at the top of the file. X X 3. Build the executable by invoking build_webbook.com, note no TCP/IP X is involved. The build procedure copies the file to default script`20 X directory (`5B-.bin`5D). The code has been test built under both DEC C X and VAX C and server version 1.9c and 2.0 (should work with earlier X versions as well). X X 4. To get the default bookshelf, invoke the script as URL X "http://your-host/htbin/webbook/decw$book/" (note the trailing slash). X `20 XNote for using consolidated documenation disks: X X If you've mounted the documentation CD's on several disks, you must use X a search list logical with all translations 'concealed', e.g.: X X`09$ define doc_cd/trans=(term,conceal) dka400:,dka5\0807600: X`09$ define decw$book doc_cd:`5B\1209`5D X X $ call unpack [.WEBBOOK]AAAREADME.WEBBOOK;1 - 1583458265 "FORMAT STREAM_LF;CARRIAGE_CONTROL CARRIAGE_RETURN" 4 1 20 $! $ create 'f' X/* X * Test bookfile_*.c routines, usage: X * X * testbook `5B-f file`5D `5B-d def-f\0E07t tab\1906n entry`5D `5B-i iter V`5D X * X * options (all\0D09have mandatory following argument): X *`09-f`09Bookreader file to read (def: b\1E09.decw$book). X *`09-d`09Default file spec for open (def: sys$disk:`5B`5D.decw$book). X *`09-t`09Table (index) to use. If option specifed as "*", all tables X *`09`09present in book will be listed. If option not \3007, X *`09`09bookfile_demo will use first type 5 (TOC) table found. X *`09`09Note that names are case sensitive. X *`09-n`09Entry number within selected table to display. The section X *`09`09of the book pointed to by the entry will be displayed. X *`09`09If option not present, the table entries will be listed. X *`09-i`09Iteration count, number of additional sections to display X *`09`09from file. X */ X#include X#include X#include X#include "bookreader_recdef.h" X#include "bookfile_io.h" X#include "bookfile_index.h" X#include "bookfile_section.h" X#include "bookfile_text.h" X Xstatic void show_section (\1406*,\0808 char *, int, int, int ); Xstatic void show_part (\1106* bkf, int part_num ); Xvoid show_font ( void *bki, long font_page\100Bcount ); X Xstatic int convert_text3 ( int length, char *in\0A08out ) X`7B X int i, offset, slen, glue, j; X for ( j = offset = 0;\0C08< length; ) `7B X`09bkt_text3_scan ( length, in, `26offset, `26out`5Bj`5D, `26slen, `26glue ); V X`09j += slen; X`09if ( offset < length ) `7B X`09 sprintf(`26out`5Bj`5D, "`7C%x`7C", glue ); X`09 j += strlen ( `26out`5Bj`5D ); X`09 /* out`5Bj++`5D = ' '; */ X`09`7D X `7D X out`5Bj`5D = '`5C0'; X return j; X`7D X Xint main ( int argc, char **argv ) X`7B X int i, bad, status, part_length, \0808single_sect; X int ndx_type, ndx_count, iter\0C08font\1806; X char *bookfile, *defdir, *table, *sec_str; X char ndx_name`5B256`5D; X bkrdr_recptr root, subrec; X bktxt_fntptr fontdef; X void *bkf, *bki; X /* X * Interpret command line arguments. X */ X bookfile = "bookreader.decw$book"; X defdir = "sys$disk:`5B`5D.decw$book"; X table = sec_str = (char *) 0; X single_sect = 0; X iter_count = 0; X for ( bad = 0, i = 1; !bad `26`26 i < argc; i++ ) `7B X`09if ( argv`5Bi`5D`5B0`5D != '-' ) `7B bad = 1; break;`7D X`09if ( i + 1 >= argc ) `7B bad = 1; break; `7D X`09switch ( argv`5Bi`5D`5B1`5D ) `7B X`09 case 'f': bookfile = argv`5B++i`5D; break; X`09 case 'd': defdir = argv`5B++i`5D; break; X`09 case 't': table = argv`5B++i`5D; break; X`09 case 'n': sec_str = argv`5B++i`5D; break; X`09 case 'i': iter_count = atoi(argv`5B++i`5D); break; X`09 case 's': single_sect = atoi(argv`5B++i`5D); break; X`09 default: X`09`09bad = 1; X`09`09break; X`09`7D X `7D X if ( bad ) `7B X`09printf("Usage: 'testbook `5B-f file`5D `5B-d dir`5D `5B-t tab\1406n entry V`5D'`5Cn"); X`09exit ( 1 ); X `7D X /* X * Open file, read root page, and display some of it's fields. X */ X status = bkf_open ( bookfile, defdir, `26bkf ); X if ( (status`261) == 0 ) `7B X`09printf("error opening bookfile '%s'`5Cn",\120A);`20 X`09exit ( status ); X `7D X status = bkf_read_page ( bkf, 0, `26part_length, `26root, `26\1006 ); X if ( (status`261) == 0 ) `7B X`09printf("error reading root part: %d`5Cn", status ); X`09exit ( status ); X `7D X printf("Book opened, root info:`5Cn title: '%s'\1308parts: %d`5Cn", X`09root->first.title, \130Cpartcount ); X printf(" sections: %d`5Cn author: '%s'`5Cn`5Cn",`20 X`09root->first.sectioncount, \1A0Cauthor ); X /* X * Read font table. X */ X status = bkt_read_font_map ( bkf, `26fontde\0A08_count ); X printf("Font data status: %d, font count: %d table: %d`5Cn",`20 X`09`09status, font_count\0C06def ); X if ( table ) for ( i = 0; i < font_count; i++ ) printf ( X`09"Font`5B%d`5D = '%s'`5Cn pixel_size: %d point: %d enc: \2806",`20 X`09`09fontdef`5Bi`5D.fontno, \130Bname\110Dpixel_size, X`09`09fontdef`5Bi`5D.point_size,\170Cencoding ); X /* X * Lookup table name. X */ X status = bki_create_context ( bkf, `26bki ); X if ( (status`261) == 0 ) `7B X`09printf("error creating index context`5Cn" );`20 X`09exit ( status ); X `7D X if ( table ) `7B X`09int list_mode; X`09list_mode = (strcmp(table,"*") == 0); X`09if ( list_mode ) printf ( "Available tables:`5Cn" ); X X`09for ( status = bki_find_index ( bki,table,-1, ndx_name, X`09`09`26ndx_type, `26ndx_count ); (status`261) == 1 `26`26 list_mode; X`09 `09status = bki_find_index ( bki, table, -1, ndx_name, X`09 `09`09`26ndx_type, `26ndx_count ) ) `7B X`09 printf(" '%s', type = %d, siz\0B06 entries`5Cn", ndx_name, X`09`09`09ndx_type, ndx_count ); X`09`7D X`09if ( list_mode ) exit ( 1 ); X `7D else `7B X`09/*`20 X`09 * No table given on command line, find name of first type 5`20 X`09 * table and use it. X`09 */ X`09status = bki_find_index ( bki, "*", 5,`20 X`09`09ndx_name, `26ndx_typ\0B08count ); X `7D X if ( (status`261) == 0 ) `7B X`09printf("Unable to find index '%s'`5Cn", table ?\0807: "`7Bcontents`7D" ); X`09exit ( status ); X `7D X bki_find_index_end ( bki ); X X /* show_font ( bkf, root->first.font_page\1712count ); */ X /* X * Open table for section access using matched name returned by find_index V. X */ X status = bki_open_index ( bki, ndx_name ); X if ( (status`261) == 0 ) `7B X`09printf("Unable to open index '%s'`5Cn", ndx_name ); X`09exit ( status ); X `7D X printf("Table '%s' opened, entries: %d`5Cn", ndx_name\0A06count ); X /* X * Now display section corresponding to matching X */ X X show_section ( bkf, bki, sec_str, single_sect, ndx_count, iter\0C06 ); X /* X * Cleanup. X */ X status = bki_close_index ( bki ); X status = bki_delete_context ( bki ); X status = bkf_close ( bkf ); X return status; X`7D X Xstatic char *rtype ( short type ) X`7B X static char *desc`5B26`5D = `7B "unknown", "first", "U\14062", X`09"bodypart", "index", "last", "secmap", "fdx", X`09"unknown8", "font", "cont_mid\0C09end", X`09"sb_tblhdr", "ascz_32", "sb_font\0B08desc\1707ixtxt", X`09"unknown11", "text", "figure", "hotspot", "sb_unk15", X`09"sb_extension", "sb_unk17\0C07license", ">24" `7D; X static char out_of_range`5B20`5D; X if ( (type < 0) `7C`7C\0E07> 24) ) `7B X`09sprintf(out_of_range, "unknown%d", type ); X`09return out_of_range; X `7D else `7B X`09return desc`5Btype`5D; X `7D X`7D X/********\0808\1010\2020\400A/ X/* Retreive and display contents section specified by table entry number. X */ Xstatic void show_section (\1406*bkf,\0B09i, char *entry_num_str, X`09int single_sect, int ndx_size\0E06iter_count ) X`7B X char *desc; void *cursor; X long ndx_value; X int status, count, part_num, match, iter; X short ndx_hdr`5B9`5D; X unsigned char attr`5B4`5D; X char name`5B256`5D; X /* X * Convert entry number string to integer (match), if\1E08null, X * set to last table entry. X */ X match = ndx_size; X if ( entry_num_str ) match = atoi\1F12; X if ( match < 1 )\0C07= 1; X if ( match > ndx_size )\1307=\1309; X /* X * Iterate through sub-records in selected table (bki) to retrieve the X * desired table entry information. X */ X if ( single_sect ) `7B X ndx_value = single_sect; X`09if ( iter_count == 0 )\120D 1; X`09desc = ""; X `7D else for ( count = 0;\0B07< match\0F07++ ) `7B X`09status = bki_read_index( bki, ndx_hdr, attr, name, `26desc, `26ndx_value); V X`09if ( (status`261) == 0 ) `7B X`09 printf("Error reading index entry %d`5Cn", count ); X`09 exit ( status ); X`09`7D X /* X * If null entry specified, list the table members. X`09 */ X`09if ( !entry_num_str ) printf ( "`5B%d`5D %s, (sect=%d)`5Cn",`20 X`09`09count+1, desc, ndx_value ); X `7D X if ( !entry_num_str `26`26 !single_sect ) return; /* Done with list */ X /* X * Create data structures used by bookfile_section.c X */ X status = bks_create_section_cursor ( bkf, `26\0F07); X if ( (status`261) == 0 ) `7B X printf("Error creating cursor: %d`5Cn", status ); X`09exit ( status ); X `7D else `7B X`09int first, type, length; long hdr`5B9`5D; X`09/* X`09 * Report entry information and lookup part number containing section. X`09 */ X`09printf("Entry %d found in table:`5Cn title: '%s'\1206Sect #: %d`5Cn", X`09`09 count, desc, ndx_value ); X`09if ( iter_count <= 0 ) `7B X`09 status = bkf_lookup_first_section ( bkf, ndx_value,`20 X`09`09`09`26part_num, `26first ); X`09 if ( (status `261) == 1 )`20 X`09`09status = bks_seek_part ( cursor, part_num, 0, `26iter_count ); X`09 else iter_count = 0; X`09 printf ( " Part #: %d first sect: %d, sub-records: %d (lookup status V: %d)`5Cn`5Cn",`20 X`09`09`09part_num, first, iter_count, status ); X`09 ndx_value = first;`09`09/* reset to start of page */ X`09`7D else `7B X`09 status = bkf_lookup_section ( bkf, ndx_value, `26part_num ); X`09 printf ( " Part #: %d (lookup status: %d)`5Cn`5Cn", part_num, \1C06 V ); X`09 first = -1; X`09`7D X`09/* X`09 * Show the next iter_count sections. X`09 */ X`09for ( iter = 0; (iter < iter_count); iter++ ) `7B X`09 int is_last, t_type, t_len;`20 X`09 short h_v`5B2`5D; unsigned char attr`5B4`5D; char *data\0C07buffer`5B25 V60`5D; X`09 /* X`09 * seek. Aboslute on first read. X`09 */ X`09 if ( ndx_value == first ) `7B X`09`09first = -1; X`09`09status = bks_seek_section ( cursor, 0, 1, `26type, `26length, hdr ); X`09 `7D X`09 else if ( iter == 0 ) X`09 status = bks_seek_section ( cursor, ndx_value+iter, 0, `26type,`20 X`09`09`09`26length, hdr ); X`09 else X`09`09status = bks_seek_section ( cursor, 1, 1, `26type, `26length, hdr ); X X`09 if ( (status`261) == 0 ) printf("Error in seek: %d`5Cn", status); X`09 if ( (status`261) == 0 ) break; X`09 /* X`09 * Now call read_section in loop to extract the contents X`09 * of the current section. is_last will be set true when X`09 * sub-record returned is last in section. X`09 */ X`09 is_last = 0; X`09 if ( type == BKSBREC_FIGURE ) `7B X`09 `09unsigned char *ub; X`09`09ndx_value = hdr`5B2`5D; X`09 printf("`5Bsect=%d,type='%s',len=%d`5D`5Cn",`20 X`09`09`09ndx_value, rtype(type), length); X`09`09printf(" fig: X=%d Y=%d Width=%d Height=%d picbytes: %d`5Cn",`20 X`09`09`09hdr`5B3`5D, hdr`5B4\08075\10076\18077`5D ); X`09`09ub = (unsigned char *) `26hdr`5B8`5D; X`09`09printf(" fig: primitive: %d ???: %d %d %d`5Cn", ub`5B0`5D, X`09`09`09ub`5B1`5D, ub`5B2\07063`5D ); X X`09 `7D else if ( type != BKSBREC_BODYTEXT ) `7B X`09`09int j; X`09 printf("`5Bsect=(%d),type='%s', h_v=%d/%d, len=%d, args: ",`20 X`09`09`09ndx_value, rtype(type), h_v`5B0`5D\08061`5D, length); X`09`09for(j=0;j<9;j++) printf("%d%s",hdr`5Bj`5D,j<8?" ":"`5D`5Cn"); X`09`09status = bks_read_section ( cursor, `26t_type, h_v, attr, X`09`09`09`26t_len, `26data, `26is_last ); X`09 `7D else `7B X`09`09ndx_value = hdr`5B1`5D; X`09 printf("`5Bsect=%d,type='%s'(%d), h_v=%d/%d, len=%d`5D`5Cn",`20 X`09`09`09ndx_value, rtype(type), type, h_v`5B0`5D\08061`5D, length); X`09 `7D X`09 while ( !is_last ) `7B X`09`09status = bks_read_section ( cursor, `26t_type, h_v, attr, X`09`09`09`26t_len, `26data, `26is_last ); X`09`09if ( (status`261) == 0 )`20 X`09`09 printf(" xxx: `7Bread error, status: %d, is_last: %d`7D`5Cn", X`09`09`09status, is_last ); X`09`09if ( (status`261) == 0 ) break; X`09`09/* X`09`09 * Convert type 3 data into single string. X`09`09 */ X`09`09if ( t_type == 1 ) `7B X`09`09 printf ( " ---: `7Btype %d`7D`5Cn", t_type );`09/* can't handle */ X`09`09`7D else if ( t_len > 0 `26`26\0D07< 256 ) `7B X`09`09 if ( (t_type == 2) `7C`7C\110C3) ) X`09`09`09t_len = convert_text3 ( t_len, data, buffer ); X`09`09 buffer`5Bt_len`5D = '`5C0'; X`09`09 printf("%4d: %s `7B%d`7D`5Cn", t_len, buffer, attr`5B0`5D ); X`09`09`7D else if ( t_len > 255 ) `7B X`09`09 int j; X`09`09 printf(" ***: `7Boverflow, %d bytes`7D`5Cn", t_len); X`09`09 printf("subrec data:"); X`09 for ( j = 0; j < t_len; j++ ) printf("%d%s", X`09`09`09data`5Bj`5D, ((j0) ? " " : "`5Cn" ); X`09`09`7D X`09 `7D X`09 if ( is_last == 2 ) printf("////: `7Bpart boundary`7D`5Cn"); X`09`7D X `7D X bks_delete_section_cursor ( \0907); X`7D X Xvoid show_font ( void *bkf, long font_page\100Bcount ) X`7B X bkrdr_recptr font, sub; X int status, length, i, part_\1008j, sublen; X `20 X status = bkf_read_page ( bkf, font_page, `26part_length, `26font, `26\1006 V ); X printf("Status of reading font page (%d): %d, length: %d/%d`5Cn",`20 X`09`09font_page, status, length, part_\0D06 ); X if ( (status`261) == 0 ) return; X X printf("Font record type: %s, size: %d, count: %d`5Cn", rtype(font->gen.ty Vpe), X`09font->gen.length, fontcount ); X if ( font->gen.type != BKREC_FONT ) return; X X for ( i=sizeof(font->font); i < fo\1108.length; i+=sub->gen\1407) `7B X`09sub = (bkrdr_recptr) `26font->reloff`5Bi`5D; X X`09if ( sub->gen.type == BKSBREC_FONT ) `7B X`09 printf ( "Font #%d is '%s' l=%d`5Cn", sub->fontdef.fontno, X`09`09sub->fontdef.name, sub->gen.length ); X`09`7D else `7B X`09 printf("%s subrec at offset %d, size: %d`5Cn", X`09`09rtype(sub->gen.type), i, sub->fontdef.length); X`09 printf("subrec data: `5Cn"); X sublen = sub->gen.length - sizeof(\1908); X for ( j = 1; j <= sublen; j++ ) printf("%d%s", X`09sub->raw`5Bj+5`5D, ((jraw`5B8`5D ); X`09`7D X `7D X`7D $ call unpack [.WEBBOOK]BOOKFILE_DEMO.C;1 - 1292029452 "FORMAT STREAM_LF;CARRIAGE_CONTROL CARRIAGE_RETURN" 26 2 20 $! $ create 'f' Xbookfile_demo,\0E09section\110Aindex\0F0B\2C0Btext $ call unpack [.WEBBOOK]BOOKFILE_DEMO.OPT;1 - 1544495510 "FORMAT STREAM_LF;CARRIAGE_CONTROL CARRIAGE_RETURN" 1 3 20 $! $ create 'f' X/* X * Convert data format of figure X */ X#include X#include X#include X X#include "bookfile_figure.h"`09/* verify prototypes */ X#include "bookreader_recdef.h" Xstruct bitstream `7B X int words_filled;`09`09/* Completed\1C06 */ X int bit_off;`09`09/* bits written to current word */ X int (*flush)(void *,int,char *); X void *flush_arg; X unsigned long buffer`5B65`5D; X`7D; Xstatic int add_bits ( struct bitstream *bs, int value\0B06size ); Xstatic int compress_data ( struct bitstream *bs,`20 X`09int code_size, unsigned char *data, int width\0B06height ); X X/* hdr`5B2`5D = section #, hdr`5B3`5D = x\0C064`5D = y\18065`5D = w hdr`5B6 V`5D = h X * hdr`5B7`5D = picbytes, hdr`5B8`5D<0..7> = primitive X * data`5B4..5`5D col,\10066..7`5D = rows X */ Xint LIB$INIT_TIMER(), LIB$SHOW\1208; Xint bkg_convert_figure_to_gif (`20 X`09long hdr`5B10`5D, `09`09`09/* Section header figure subrec */ X`09unsigned char *data, int datalen, /* data read from section */ X`09int (*output)(void*, int, char *), /* User-supplied \2E06 function */ X`09void *outarg )`09`09`09/* user-arg for output function */ X`7B X FILE* out; X int i, j, k, width, height, value, mask, status; X float aspect; X short *cols, *rows; X char trailer`5B2`5D = `7B 0, ';' `7D; X unsigned char *cur_row,\0A06col; X unsigned char *pixel_row,\0C08image; X int size, count; X#ifdef __DECC X#pragma nomember_alignment X#endif X struct gif_header `7B X`09char signature`5B6`5D;`09`09/* GIF87a */ X`09short width, height;`09`09/* little-endian */ X`09unsigned char flags;`09`09/* <0..2> gct_size (2**(val+1)). */ X`09`09&0209`09/* <3> color table sorted */ X`09`09&0209`09/* <4..6> out device clr res (7)*/ X`09`09&0209`09/* <7> Global color table if set */ X`09short aspect;`09`09`09/*\0D07 ratio */ X`09unsigned char color_table`5B6`5D;`09/* 2-entry\1B06 table */ X`09`09`09/* Image header follows */ X`09char separator;`09`09`09/* ',' */ X`09short left,top;`09`09`09/* origin */ X`09short iwidth, iheight;`09`09/* Image size */ X`09unsigned char iflags;`09`09/* <0..2> pixel depth */ X`09`09&0209`09/* <3..5> mbz */ X`09`09&0209`09/* <6> Interlace flag */ X`09`09&0209`09/* <7> local color table */ X`09unsigned char code_size;`09/* first byte of image data */ X `7D header; X#ifdef __DECC X#pragma member_alignment X#endif X struct bitstream bs; X /* X * Get dimensions of image and move data point to start \2609bits. X */ X data += 4; X cols = (short *)`26data`5B0`5D; row\1B0B*) \1B062`5D; X datalen =\0A09- 8; X data += 4;`09`09 /* skip origin and size info */ X width = *cols; X height = *rows; X /* X * Build gif header in structure and output. X */ X strcpy ( header.signature, "GIF87a" ); X header.width = *cols; X header.height = *rows; X header.flags = 0;`09`09`09/* ASSUME 2`5E(0+1) = 2 BITS */ X header.flags =\0F0E`7C 0x00080;`09/* include GCT */ X header.aspect = 0; X header.color_table`5B0`5D =\18141\18172`5D = 0; X header.color_table`5B3`5D =\18144\18175`5D = 255; X header.separator = ','; X header.left =\0E08top = 0; X header.iwidth = width; X header.iheight = height; X header.iflags = 0; X header.code_size = 2;`09`09/* first byte of raster data */ X X status = output( outarg, sizeof(header), (char *) `26\1306 ); X if ( (status`261) == 0 ) return \1806; X /* X * Initialize data stream structure and do LZ compression on bits. X * add bits automatically calls output routine when buffer fills. X */ XLIB$INIT_TIMER(); X bs.words_filled = 0; X bs.bit_off = 8;`09`09`09/* leave room for count byte. */ X bs.flush = output; X bs.flush_arg = outarg; X bs.buffer`5B0`5D = 0; X X status = compress_data ( `26bs, 2, data, width, height ); X if ( (status`261) == 0 ) return \1806; X /* X * Flush remaining bits in buffer and add final trailer bytes. X */ X count = bs.words_filled*4 + (bs.bit_off+7)/8;`09/* include whole byte */ X if ( count > 1 ) `7B X`09bs.buffer`5B0`5D `7C= (count-1); X status = output ( outarg, count, (char *) bs.buffer ); X`09if ( (status`261) == 0 ) return \1806; X `7D X X status = output ( outarg, 2, trailer ); X if ( (status`261) == 0 ) return \1806; XLIB$SHOW_TIMER(); X return status; X`7D X/* X * GIF encoder. `20 X * X * The Graphics Interchange Format(c) is the Copyright property of X * CompuServe Incorporated. GIF(sm) is a Service Mark property of`20 X * CompuServe Incorporated." X * X */ X X X/********\0808\1010\2020\400D/ Xstatic unsigned bmask`5B33`5D = `7B`20 X`090, 1, 3, 7, 15, 31, 63, 127, 255,`20 X`09511, 1023, 2047, 4095, 8191, 0x03fff, 0x07\0908ffff,`20 X`090x01ffff, 0x03\0A097\1409fffff,`20 X`090x01fffff, 0x03\0A097\1409ffffff, X`090x01ffffff, 0x03\0B0A7\160A\2107 X`090x1fffffff, 0x3\0B0A7\160A\2107f `7D; X X Xstatic int add_bits ( struct bitstream *bs, int value\0B06size ) X`7B X int cur, pos, off, ov_bits, status; X unsigned low; X X cur = bs->words_filled; X off = bs->bit_off; X#ifdef DEBUG Xprintf("<%d,%d=%d>", off, size, value ); X#endif X if ( off + size <= 32 ) `7B X`09/* X`09 * All fits in current longword of buffer. X`09 */ X`09low = (value `26bmask`5Bsize`5D); X`09bs->buffer`5Bcur`5D `7C= (low << off); X`09bs->bit_off = off + size; X `7D else `7B X`09/* X`09 * value straddles two longwords. X`09 */ X`09ov_bits = size + off - 32; X`09if ( ov_bits > 0 ) `7B X`09 low = (value `26 bmask`5Bsize-ov_bits`5D); X`09 bs->buffer`5Bcur++`5D `7C= (low<buffer`5Bcur-1`5D ); X#endif X`09if ( cur > 62 ) `7B X`09 long bcount; X`09 bcount = cur*4; X`09 bs->buffer`5B0`5D `7C= (bcount-1);`09/* load first (low) byte */ X`09 `20 X`09 status = bs->flush (\0C0A_arg, cur*4, (char *)bs->buffer ); X`09 if ( (status`261) == 0 ) return cur; X`09 value = (\0906`26 (`7Ebmask`5Bsize-ov_bits`5D));`09/* zero field */ X`09 value =\0807<< 8; /* make room for count */ X`09 ov_bits += 8; X`09 size += 8; X`09 cur = 0; X`09`7D X X`09low = value; X`09low = (low>>(size-ov_bits)); X`09bs->buffer`5Bcur`5D = (low `26 bmask`5Bov_bits`5D); X`09bs->bit_off = ov_bits; X `7D X bs->words_filled = cur; X return cur; X`7D X Xstruct code_t_entry `7B X short prefix, code, next_hash; X`7D; X Xstruct lz_state `7B X int code_size;`09`09`09/* Number of bits of input size */ X int clear;`09`09&0209/* value of\1606 code (2`5Ecode_size) */ X int eoi;`09`09&0209/* End-of-info code (clear+1); */ X int out_size; X int max_code;`09`09`09/* hight entry in code_table */ X int max_hash; X#define HASH_BITS 13 X#define HASH_TABLE_SIZE 8192 X int hash_shift;`09`09`09/* shift for charval in hash func */ X struct code_t_entry table`5B4096`5D;`09/* code\1506 */ X short hash_table`5BHASH_TABLE_SIZE`5D; X`7D; Xtypedef struct lz_state *lzptr; X Xstatic int initialize_lz_state ( lzptr lz, int code_size ) X`7B X int i, max_code\0A06hash; X struct code_t_entry *table; X short *hash; X X lz->code_size = \0C09; X lz->clear = 1; X for ( i = 0; i < code_size; i++ ) lz->clear *= 2; X lz->eoi = lz->clear+1; X lz->out_size = code\0C06+ 1; X lz->max_code = \0B0Blz->eoi; X X max_hash = HASH_TABLE_SIZE; X lz->hash_shift = 12; X while ( (code_size+lz->hash_shift) > HASH_BITS) `7B X`09lz->hash_shift = \110F- 1; X `7D X /* max_hash = bmask`5Bcode_size+lz->hash_shift`5D; * / X max_hash = bmask`5BHASH_BITS`5D;`09/* optimize for 1 bit data */ X lz->max_hash = \0B08; X /* X * Initialize the tables. X */ X table = lz->table; X for ( i = 0; i <= max_code; i++ ) `7B`20 X`09table`5Bi`5D.prefix = -1; \1609code = i\130Bnext_hash = 0; X `7D X for ( ; i < 4096; i++ ) table`5Bi`5D.prefix =\120Acode = 0; X X hash = lz->hash_table; X for ( i = 0; i < max_hash; i++ ) hash`5Bi`5D = 0; X X return 1; X`7D X X Xstatic int compress_data ( struct bitstream *bs,`20 X`09int code_size, unsigned char *data, int width\0B06height ) X`7B X int code, prefix, current, new, out_size, i, j, hashval; X int code_limit, value, mask; X unsigned char *dptr, *data_end; X struct code_t_entry *table; X short *hash_table; X struct lz_state lz; X X dptr = data; X X initialize_lz_state ( `26lz, code_size ); X table = lz.table; X hash_table = lz.\100A; +-+-+-+-+-+-+-+- END OF PART 1 +-+-+-+-+-+-+-+- ================== RFC 822 Headers ================== Return-Path: VMSSERV@kcl.ac.uk Received: by galaxy.zko.dec.com (UCX V4.0-10B, OpenVMS V6.2 VAX); Mon, 19 Aug 1996 18:17:36 -0400 Received: from newt.kcl.ac.uk by mail11.digital.com (8.7.5/UNX 1.2/1.0/WV) id SAA16640; Mon, 19 Aug 1996 18:02:59 -0400 (EDT) Received: from alder.cc.kcl.ac.uk by newt.kcl.ac.uk with SMTP (PP) id <23288-0@newt.kcl.ac.uk>; Mon, 19 Aug 1996 23:02:45 +0100 Received: by alder.cc.kcl.ac.uk (MX V4.2 AXP) id 732; Mon, 19 Aug 1996 23:03:04 EDT Date: Mon, 19 Aug 1996 23:02:48 BST From: Kings College London File Server To: everhart@star.zko.dec.com Message-ID: <009A71AB.01585940.732@alder.cc.kcl.ac.uk> Subject: WEBBOOK.1-OF-5