From: SMTP%"VMSSERV@kcl.ac.uk" 19-AUG-1996 18:20:38.01 To: everhart@star.zko.dec.com CC: Subj: WEBBOOK.3-OF-5 -+-+-+-+-+-+-+-+ START OF PART 3 -+-+-+-+-+-+-+-+ X *first = ctx->first_sec`5Bpart_id`5D; X return 1; X`7D $ call unpack [.WEBBOOK]BOOKFILE_IO.C;1 - 2104924189 "FORMAT STREAM_LF;CARRIAGE_CONTROL CARRIAGE_RETURN" 27 8 20 $! $ create 'f' X/* X * Define low-level routines for bookreader file io. X */ X#ifndef BKREC_COMMON_HEADER X#include "bookreader_recdef.h" X#endif X/*`20 X * Define symbol for bkf_read to signify RFA for sequential read`20 X */ X#define BKF_NEXT_REC (struct file_address *) 0 X Xint bkf_open ( char *fname,\0D07de\0F07void **retctx ); Xint bkf_close ( void *ctx ); X Xchar *bkf_last_error ( void *ctx );`09`09/* Text for \2206*/ X/*`20 X * Note that bkf_read returns a pointer to the record. Caller must X * copy record if the dat will be needed after a subsequent call. The X * exception is the page id 0, whose record is allocated separately X * by bkf_open(). X */ Xint bkf_read ( void *ctx, `09`09/* I/O context */ X`09struct file_address *rfa,`09/* RMS record adress, null for next */ X`09bkrdr_recptr *bufaddr,`09`09/* Address of read record */ X`09int *length );`09`09`09/* L\0F06of RMS record read */ X Xint bkf_read_page ( void *ctx,`20 X`09int id, `09`09`09/* Page number */ X`09int *page_length,`09`09/* virtual \1406 of requested page */ X`09bkrdr_recptr *bufaddr, `09`09/* First RMS record of page */ X`09int *length );`09`09`09/* L\0F06of RMS record */ X Xint bkf_lookup_section ( void *vctx, int sect_id\0D06*part ); Xint bkf_lookup_first_section ( void *vctx, int sect_id\0D06*part\0B07first ); V Xint bkf_lookup_part_section ( void *vctx, int part_num\0E06*sect_id ); $ call unpack [.WEBBOOK]BOOKFILE_IO.H;1 - 807152963 "FORMAT STREAM_LF;CARRIAGE_CONTROL CARRIAGE_RETURN" 3 9 20 $! $ create 'f' X/* X * Define routines for traversing bodypart sections within a bookreader X * file. X * X * int bks_create_section_cursor ( void *bkf_ctx,\0F07*\1F07); X * int bks_delete_section_cursor ( void *\0F07); X * int bks_seek_section ( void *cursor, int offset\0C06dir\2A06, X *`09int *type, int *length, long *hdr`5B9`5D ); X * int bks_read_section ( void *cursor, int *type, short *h_v,`20 X *`09unsigned char attr`5B4`5D, int *length, char **data\1A07is_last ); X * X * Author: David Jones X * Date: 12-SEP-1995 X */ X#include X#include X#include X#include X X#include "bookreader_recdef.h" X#include "bookfile_io.h" X#include "bookfile_section.h"`09/* validate prototypes */ X Xstruct section_context `7B X void *bkf;`09`09`09/* bkf_open context for doing I/O */ X bkrdr_recptr root;`09`09/* pointer to root part for file */ X bkrdr_recptr cur;`09`09/* Currently open bodypart page */ X bkrdr_recptr sec;`09`09/* current subrec within bodypart */ X long sect_id;`09`09/* Currently positions section (-1) for none*/ X int cur_alloc;`09`09/* Allocation size of cur */ X int cur_offset;`09`09/* Offset of sec within cur */ X int offset;`09`09`09/* Current read\1A07 in sect */ X`7D; Xtypedef struct section_context *bksctx; X Xint bks_create_section_cursor ( void *bkf,\0B07*\1B07) X`7B X bksctx ctx; X int status, page_length, \0806; X /* X * allocate context block. X */ X ctx = (bksctx) malloc ( sizeof(struct section_context) ); X if ( !ctx ) return SS$_INSFMEM; X ctx->bkf = bkf; X ctx->cur_alloc = 0; X ctx->sect_id = -1; X ctx->offset = 0; X /* X * Make local copy of pointer to root part of file (part 0). We assume X * bkf_read returns address of a static structure for part 0. X */ X status = bkf_read_page ( bkf, 0, `26page_length, `26ctx->root, `26\1506 ); V X *cursor = (void *) ctx; X return status; X`7D X Xint bks_delete_section_cursor ( void *context ) X`7B X bksctx ctx; X /* X * Deallocate any structures and sub-\130C\2B07d. X */ X ctx = (bksctx) context; X X if ( ctx->cur_alloc > 0 ) `7B X`09free ( ctx->cur ); X`09ctx->cur_alloc = 0; X `7D X free ( ctx ); X return 1; X`7D X/********\0808\1010\2020\400C/ X/* Scan starting at current position for section with matching ID.`20 X */ Xstatic int scan_for_section ( bksctx ctx, int id ) X`7B X int i; X bkrdr_recptr cur, sec; X cur = ctx->cur; X for ( i = ctx->cur_offset; i < cur->gen.length; i += sec\160C ) `7B Xint kk; X`09sec = (bkrdr_recptr) `26cur->reloff`5Bi`5D; X#ifdef DEBUG Xprintf(" `5B%d/%d`5D subrec type %d, length: %d id: ", i,`20 X`09`09cur->gen.length, sec\1106type,`09\0F09\2006 ); Xfor (kk=0; kk < 9; kk++) printf("%d%s",sec->bodytext.bodhdr`5Bkk`5D, X(kk < 8) ? " " : "`5Cn" ); X#endif X`09if ( sec->gen.length < 0 ) return SS$_BUGCHECK; X X`09if ( sec->gen.type == BKSBREC_BODYTEXT ) `7B X`09 if ( sec->bodytext.sect_id == id ) break; X`09`7D else if ( sec->gen.type == BKSBREC_FIGHOT ) `7B X`09 if ( sec->hotspot.target == id ) break; X`09`7D else if ( sec->gen.type == BKSBREC_FIGURE ) `7B X`09 if ( sec->figure.sect == id ) break; X`09`7D else if ( sec->gen.type == BKSBREC_EXTENSION ) `7B X`09 if ( sec->extension.sect == id ) break; X`09`7D else `7B X`09 /* skip it unless current is one less */ X`09 if ( ctx->sect_id+1 == id ) break; X`09`7D X `7D X ctx->cur_offset = i; X ctx->sec = sec; X if ( i >= cur->gen.length ) return SS$_BUGCHECK; /* not found */ X ctx->sect_id = id; X X ctx->offset = sizeof(sec->bodytext);`09/* prepare for read_section() */ X return 1; X`7D X/********\0808\1010\2020\400C/ X/* Read page and intialize context for reading it's sections. X */ Xstatic int load_bodypart ( bksctx ctx, int part_num ) X`7B X bkrdr_recptr cur, tmp; X int status, tmp_len, page_length, sect_id; X /* X * Read page and validate type, function return pointer to I/O buffer. X */ X status = bkf_read_page ( ctx->bkf, part_num, `26page_length, `26tmp\0606_le Vn ); X if ( (status`261) == 0 ) return \1806;`09/* abort on read error */ X if ( tmp->gen.type != BKREC_BODYPART ) return SS$_BUGCHECK; X /* X * Make copy of I/O buffer into cursor's private \1D06, expanding it X * if needed. X */ X if ( page_length > ctx->cur_alloc ) `7B X`09if ( ctx->cur_alloc > 0 ) free\1C0B ); X`09ctx->cur_alloc = 0; X`09cur = ctx->\0B06(bkrdr_recptr) malloc ( page_length+15000); X`09if ( !cur ) return SS$_INSFMEM; X`09ctx->cur_alloc = page_length + 15000; X `7D X memcpy ( ctx->cur, tmp, page_length ); X /* X * Now position context for read_sec\1906alls. X */ X ctx->cur_offset = sizeof(cur->body);`09/* \1F07of 1st subrec */ X ctx->offset = sizeof(cur->bodytext);`09/* \2307subrec's 1st textrec*/ X tmp_len = bkf_lookup_part_section ( ctx->bkf, part_num, `26sect_id ); X ctx->sect_id = \0A07; X X return status; X`7D X/********\0808\1010\2020\400C/ X/* X * Seek_section input args corresponde to fseek(): X * direction = 0 -> offset is absolute. X * direction = 1 -> offset is relative to current position. X * direction = 2 -> offset is relative to end (unimplemented). X * Seeking to a section prepares the\1509for subtext scans, seeking X * to (cursor,0,1) resets context for the current cursor. X */ Xint bks_seek_section ( void *cursor, int offset\0C06dir\2A06, X`09int *type, int *length, long hdr`5B9`5D ) X`7B X bksctx ctx; X bkrdr_recptr cur,sec; X int status, pos, copy_size; X X ctx = (bksctx) cursor; X X#ifdef DEBUG Xprintf("/bks/ seek_section entered, current sect=%d, alloc=%d, offset=%d/%d`5C Vn", X`09ctx->sect_id, ctx->cur_alloc\100Boffset\2107\0D06 ); X#endif X cur = ctx->cur; X sec = ctx->sec; X if ( (offset == 1) `26`26 (direction\1407) `7B X`09/* X`09 * Do sequential seek to start of next subrecord in part. X`09 */ X`09if ( ctx->sect_id < 0 ) return SS$_BADPARAM; /* no current position */ X`09pos = ctx->cur_offset + sec->gen.length; X`09if ( pos >= cur->gen.length ) `7B X`09 /* X`09 * Advance to next part. X`09 */ X`09 status = load_bodypart ( ctx, cur->body.nextpart ); X`09 if ( (status`261) == 0 ) return \1806; X`09 cur = ctx->cur; X`09 pos = sizeof(cur->body); X`09`7D else `7B X`09 /* continue in same part */ X`09 ctx->cur_offset = pos; X`09`7D X`09ctx->offset = sizeof(sec->bodytext); X`09sec = ctx->\0B06(bkrdr_recptr) `26cur->reloff`5Bpos`5D; X`09offset = ctx->sect_id; X `7D else if ( direction == 1 ) `7B X`09/* Convert relative position to absolute */ X`09if ( ctx->sect_id < 0 ) return SS$_BADPARAM; /* no current position */ X`09offset += ctx->sect_id; X`09if ( offset <= 0 ) return SS$_BADPARAM; X `7D else if ( (direction != 0) `7C`7C (offset < 0) ) `7B X`09return SS$_BADPARAM; X `7D else if ( offset == ctx->sect_id ) `7B X`09/* Redo current subrec */ X`09ctx->offset = sizeof(sec->bodytext); X `7D else if ( (offset-1) == ctx->sect_id `26`26 (\110D>= 0) &0226 X`09 (cur->gen.length > (ctx->cur_offset + sec\250C)) ) `7B X`09/*`20 X`09 * We want next section and it is likely in current part`20 X`09 */ X#ifdef DEBUG Xprintf("/bks/ checking same part for section %d`5Cn", offset ); X#endif X`09ctx->cur_offset += sec->gen.length; X`09scan_for_section ( ctx, offset ); X`09sec = ctx->sec; X `7D X if ( offset != ctx->sect_id ) `7B X`09int part_num; X`09/* X`09 * We still haven't found part, use section map to locate X`09 * part number containing the section. X`09 */ X`09ctx->sect_id = -1;`09/* invalidate current position */ X`09status = bkf_lookup_section ( ctx->bkf, offset, `26part_num ); X`09if ( (status`261) == 0 ) return \1806;`09/* not in map */ X#ifdef DEBUG Xprintf("/bks/ checking new part (%d) for section %d`5Cn", part_num, offset ); V X#endif X`09/* X`09 * Load page and seek to section. X`09 */ X`09status = load_bodypart ( ctx, part_num ); X`09if ( (status`261) == 0 ) return \1806; X X`09status = scan_for_section ( ctx, offset ); X`09if ( (status`261) == 0 ) return \1806; X`09sec = ctx->sec; X `7D X X /* X * return the section header to the caller. Call may specify null for X * length and hdr arguments. X */ X *type = sec->gen.type; X if ( length ) *\0A07= sec->gen.\1C06; X if ( hdr ) `7B`09/* make it optional */ X`09copy_size = sizeof(long)*9; X`09if ( copy_size + sizeof(sec->gen) > s\0C07.length ) X `09copy_size = sec->gen.length - sizeof(\1908); X memcpy ( hdr, sec->bodytext.bodhdr, copy_size ); X `7D X return 1; X`7D X/********\0808\1010\2020\4008/ X/* Return next text record from current section.`20 X */ Xint bks_read_section ( void *cursor, int *type, short *h_v,`20 X`09unsigned char attr`5B4`5D, int *length, char **data\1A07is_last ) X`7B X bksctx ctx; X bkrdr_recptr cur,sec; X struct text_rec *txt; X int status, i, txtlen; X X ctx = (bksctx) cursor; X sec = ctx->sec; X i = ctx->offset; X#ifdef DEBUG Xprintf("/bks/ reading section of type: %d, length\0C06offset: %d`5Cn",`20 Xsec->gen.type, \0F09length, i); X#endif X if ( i < sec->gen.length ) `7B X`09/* return data */ X`09txt = (struct text_rec *) `26sec->reloff`5Bi`5D; X`09if ( sec->gen.type != BKSBREC_BODYTEXT`20 X`09`09`7C`7C txt->type < 1 \110D> 3 ) `7B X`09 *type = 0; X`09 *length = txt->reclen; X`09 h_v`5B0`5D = h_v`5B1`5D = 0; X`09 attr`5B0`5D =\0A061\0A092\14093`5D = 0; X`09 txtlen = sec->gen.length - i;`09/* rest of section */ X`09 *length = txtlen; X`09 *data = `26sec->reloff`5Bi`5D; X`09`7D else `7B X`09 /* Extract text header */ X`09 *type = txt->type; X`09 txtlen = txt->reclen; X`09 h_v`5B0`5D = txt->hor; h_v`5B1\1309ver; X`09 attr`5B0`5D = txt->fontno;\17061\1709x\12072\2909y; X`09 attr`5B3`5D = txt->data`5B0`5D; X`09 *length = txtlen - 9;`09/* subtact header */ X`09 *data = txt->data; X`09`7D X`09/* X`09 * Update offset for next call. X`09 */ X`09ctx->offset = i + txtlen; X`09if ( i > ctx->offset ) return SS$_BUGCHECK; X`09if ( ctx->offset < sec->gen.length ) *is_last = 0; X`09else `7B X`09 cur = ctx->cur; X`09 if ( cur->gen.length > (ctx->cur_offset + sec\250C))`20 X`09`09*is_last = 1; X`09 else X`09`09*is_last = 2; X`09`7D X`09return 1; X X `7D else `7B X`09/* No more records */ X`09cur = ctx->cur; X`09if ( cur->gen.length > (ctx->cur_offset + sec\250C))`20 X`09`09*is_last = 1; X`09else X`09`09*is_last = 2; X`09return SS$_ENDOFFILE; X `7D X`7D Xint bks_seek_part ( void *cursor, int part_offset\1106di\1A07*sect_cnt ) X`7B X bksctx ctx; X bkrdr_recptr cur,sec; X int status, i; X X ctx = (bksctx) cursor; X cur = ctx->cur; X X#ifdef DEBUG Xprintf("/bks/ seek_part entered, current sect=%d, alloc=%d, offset=%d/%d`5Cn", V X`09ctx->sect_id, ctx->cur_alloc\100Boffset\2107\0D06 ); Xprintf("/bks/ seek_part offset: %d dir: %d`5Cn", part_\1C06, dir ); X#endif X X if ( dir == 1 ) `7B X`09/* X`09 * Relative seek, traverse links in part headers. X`09 */ X`09if ( ctx->sect_id < 0 ) return SS$_BADPARAM; /* no current position */ X`09while ( part_offset != 0 ) `7B X`09 if ( part_offset < 0 ) `7B X`09 status = load_bodypart ( ctx, ctx->cur->body.prevpart ); X`09`09part_offset++; X`09 `7D else `7B X`09`09part_offset--; X`09 status = load_bodypart ( ctx, ctx->cur->body.nextpart ); X`09 `7D X X`09 if ( (status`261) == 0 ) return \1806; X`09`7D X `7D else if ( dir == 0 ) `7B X`09status = load_bodypart ( ctx, part_offset ); X`09if ( (status`261) == 0 ) return \1806; X `7D X if ( dir != 0 ) return SS$_BADPARAM; X /* X * scan the sub-records to determine the initial section id X */ X cur = ctx->cur; X *sect_cnt = cur->body.sectcnt; X ctx->sec = (bkrdr_recptr) `26cur->reloff`5Bsizeof(cur->body)`5D; X X return 1; X`7D X Xint bks_get_cursor_info ( void *\1406,`20 X`09int parts_info`5B4`5D, `09/* 0-cur_part, 1-prev, 2-next, 3-reserved */ X`09int sect_info`5B4`5D )`09/* 0-first_sect, 1-sect_count, 2-cur_sect */ X`7B X bksctx ctx; X bkrdr_recptr cur,sec; X struct text_rec *txt; X int status, i, txtlen; X X ctx = (bksctx) cursor; X sec = ctx->sec; X X cur = ctx->cur; X if ( !cur ) return SS$_ENDOFFILE; X bkf_lookup_first_section ( ctx->bkf,\0A06sect_id, X`09`09`26parts_info`5B0`5D, `26sect\0F08 ); X parts_info`5B1`5D = cur->body.prevpart; X parts_info`5B2`5D = cur->body.nextpart; X parts_info`5B3`5D = cur->body.unk1; X X sect_info`5B1`5D = cur->body.sectcnt; X sect_info`5B2`5D = ctx->\1406d; X sect_info`5B3`5D = ctx->offset; X return 1; X`7D $ call unpack [.WEBBOOK]BOOKFILE_SECTION.C;1 - 1191881285 "FORMAT STREAM_LF;CARRIAGE_CONTROL CARRIAGE_RETURN" 25 10 20 $! $ create 'f' X/* X * Define routiens for traversing bodypart sections within a bookreader X * file. X */ X Xint bks_create_section_cursor ( void *bkf_ctx,\0F07*\1F07); Xint bks_delete_section_cursor ( void *\0F07); X/* X * Seek_section input args corresponde to fseek(): X * direction = 0 -> offset is absolute. X * direction = 1 -> offset is relative to current position. X * direction = 2 -> offset is relative to end (unimplemented). X * Seeking to a section prepares the\1509for subtext scans, seeking X * to (cursor,0,1) resets context for the current cursor. X */ Xint bks_seek_section ( void *cursor, int offset\0C06dir\2A06, X`09int *type, int *length, long hdr`5B9`5D ); Xint bks_read_section ( void *cursor,`20 X`09int *type, `09`09/* text_rec type: 0, 1, 2, 3 */ X`09short *h_v, `09`09/* horiz/vert */ X`09unsigned char attr`5B4`5D, `09/* cont, x, y, spare */ X`09int *length, `09`09/* Legnth of data */ X`09char **data, `09`09/* Pointer to data inside record buffer, X`09`09&0209 * becomes invalid on next seek */ X`09int *is_last ); /* 0 more, 1 - end of sect, 2 -\1007part */ X Xint bks_seek_part ( void *cursor, int part\0A06di\1307*sect_cnt ); X Xint bks_get_cursor_info ( void *\1406,`20 X`09int parts_info`5B4`5D, `09/* 0-cur_part, 1-prev, 2-next, 3-reserved */ X`09int sect_info`5B4`5D );`09/* 0-first_sect, 1-sect_count, 2-cur_sect */ $ call unpack [.WEBBOOK]BOOKFILE_SECTION.H;1 - 1124460674 "FORMAT STREAM_LF;CARRIAGE_CONTROL CARRIAGE_RETURN" 3 11 20 $! $ create 'f' X/* X * routines for handling text subrecords and font information. X */ X#include X#include X#include X#include X X#include "bookreader_recdef.h" X#include "bookfile_io.h" X#include "bookfile_text.h" X X#ifdef TTTEMP Xstruct bktxt_font_def `7B X int fontno;`09`09/* font number */ X char *name;`09`09/* asciz name of font */ X`7D; Xtypedef struct bktxt_font_def *\1007ntptr; X#endif X Xint bkt_read_font_map ( void* bkfctx, `09`09/* bki_open file context */ X`09bktxt_fntptr *fontdef, `09`09/* return array of structs */ X`09int *count )`09`09&0209/* size of returned array */ X`7B X int status, page_length, \0808i, j; X bkrdr_recptr root, font, sub; X bktxt_fntptr flist; X char *pstr; X /* X * Read root record to get pointers and read the font page. X */ X status = bkf_read_page ( bkfctx, 0, `26page_length, `26root, `26\1006 ); X if ( (status`261) == 0 ) return \1806; X *count = root->first.fontcount; X status = bkf_read_page ( bkfctx, root->first.font_page, `26page_length, X`09`26font, `26length ); X if ( (status`261) == 0 ) return \1806; X if ( font->gen.type != BKREC_FONT ) return SS$_BUGCHECK; X /* X * Allocate array of structures. X */ X flist = (bktxt_fntptr) malloc ( *count * sizeof(struct \2E07ont_def) ); X if ( !flist ) return SS$_INSFMEM; X flist`5B0`5D.fontno = 0;\150Aname = ""; X for ( i = 1; i < *count; i++ ) flist`5Bi`5D = \0B060`5D; X j = 0; X for ( i=sizeof(font->font); i < font->gen.length; i += sub\160C ) `7B X`09sub = (bkrdr_recptr) `26font->reloff`5Bi`5D; X X`09if ( sub->gen.type == BKSBREC_FONT ) `7B X`09 /* X`09 * Copy data from fontdef to our array, make allocated X`09 * buffer 2 the size and copy twice for parsing. X`09 */ X`09 flist`5Bj`5D.fontno = sub->fontdef\1607; X`09 length = sub->gen.\1207- sizeof(sub->fontdef) + X`09`09sizeof(sub->fontdef.name) + 1; X`09 flist`5Bj`5D.name = malloc ( length * 2 ); X`09 strncpy ( flist`5Bj`5D.name, sub->fontdef\1307length ); X`09 flist`5Bj`5D.name`5Blength-1`5D = '`5C0'; X`09 pstr = `26flist`5Bj`5D.name`5Blength`5D; X`09 strcpy ( pstr, flist`5Bj`5D.name ); X`09 /* X`09 * Parse the separate fields from\1906tring\0707. X`09 */ X`09 for ( ; *pstr; pstr++ ) if (*pstr == '-') `7B\2406++ = '`5C0'; break;`20 V`7D X`09 flist`5Bj`5D.foundry = pstr; X X`09 for ( ; *pstr; pstr++ ) if (*pstr == '-') `7B\2406++ = '`5C0'; break;`20 V`7D X`09 flist`5Bj`5D.typeface = pstr; X X`09 for ( ; *pstr; pstr++ ) if (*pstr == '-') `7B\2406++ = '`5C0'; break;`20 V`7D X`09 flist`5Bj`5D.weight = pstr; X X`09 for ( ; *pstr; pstr++ ) if (*pstr == '-') `7B\2406++ = '`5C0'; break;`20 V`7D X`09 flist`5Bj`5D.style = pstr; X X`09 for ( ; *pstr; pstr++ ) if (*pstr == '-') `7B\2406++ = '`5C0'; break;`20 V`7D X`09 flist`5Bj`5D.width = pstr; X X`09 /* if ( *pstr == '-' ) pstr++; */ X`09 for ( ; *pstr; pstr++ ) if (*pstr == '-') `7B\2406++ = '`5C0'; break;`20 V`7D X`09 flist`5Bj`5D.id = pstr; X X`09 for ( ; *pstr; pstr++ ) if (*pstr == '-') `7B\2406++ = '`5C0'; break;`20 V`7D X`09 flist`5Bj`5D.pixel_size = (*pstr) == '*' ? -1 : atoi(pstr); X X`09 for ( ; *pstr; pstr++ ) if (*pstr == '-') `7B\2406++ = '`5C0'; break;`20 V`7D X`09 flist`5Bj`5D.point_size = (*pstr) == '*' ? -1 : atoi(pstr); X X`09 for ( ; *pstr; pstr++ ) if (*pstr == '-') `7B\2406++ = '`5C0'; break;`20 V`7D X`09 flist`5Bj`5D.res_x = (*pstr) == '*' ? -1 : atoi(pstr); X X`09 for ( ; *pstr; pstr++ ) if (*pstr == '-') `7B\2406++ = '`5C0'; break;`20 V`7D X`09 flist`5Bj`5D.res_y = (*pstr) == '*' ? -1 : atoi(pstr); X X`09 for ( ; *pstr; pstr++ ) if (*pstr == '-') `7B\2406++ = '`5C0'; break;`20 V`7D X`09 flist`5Bj`5D.spacing = pstr; X X`09 for ( ; *pstr; pstr++ ) if (*pstr == '-') `7B\2406++ = '`5C0'; break;`20 V`7D X`09 flist`5Bj`5D.average_width = (*pstr) == '*' ? -1 : atoi(pstr); X X`09 for ( ; *pstr; pstr++ ) if (*pstr == '-') `7B\2406++ = '`5C0'; break;`20 V`7D X`09 flist`5Bj`5D.encoding = pstr; X X`09 j++; X`09 if ( j >= *count ) break; X`09`7D X`09if ( sub->gen.length <= 0 ) return SS$_BUGCHECK; X `7D X *fontdef = flist; X return status; X`7D X X/* X * Scan record by setting offset to 0 and calling repeatedly X * until offset greater or equal to reclen (length of record). X */ Xint bkt_text3_scan ( int reclen, char *rec,`20 X`09int *offset, char substring`5B256`5D, int *\1206length\1307glue ) X`7B X int size, pos, i; X X pos = *offset; X if ( pos >= reclen ) return 0; X size = (unsigned) rec`5Bpos++`5D; X *stringlength = size; X for ( i = 0; i < size; i++ ) substring`5Bi`5D = rec`5Bpos++`5D; X substring`5Bi`5D = '`5C0'; X *glue = (pos < reclen) ? (unsigned) rec`5Bpos++`5D : 0; X *offset = pos; X return 1; X`7D $ call unpack [.WEBBOOK]BOOKFILE_TEXT.C;1 - 1879566452 "FORMAT STREAM_LF;CARRIAGE_CONTROL CARRIAGE_RETURN" 10 12 20 $! $ create 'f' X/* X * routines for handling text subrecords and font information. X */ Xstruct bktxt_font_def `7B X int fontno;`09`09/* font number */ X char *name;`09`09/* asciz name of font */ X /* Following are for Parse out versions for fields in name */ X char *foundry;`09/* Font designer (ADOBE) */ X char *typeface;`09/* T\0D07 family (Helvtica, Courier, etc */ X char *weight;`09/* (Book, Demi, Medium, Bold) */ X char *style;`09/* 'R'oman, 'I'talic, 'O'blique */ X char *width;`09/* Normal, Wide, Double Wide */ X char *id;`09`09/* ??? */ X int pixel_size;`09/* -1 indicates "*" */ X int point_size;`09/* 100, 120, 140, 180 */ X int res_x, res_y; /* Dot/inch */ X char *spacing;`09/* 'P'proportional, 'M'onospace, 'C'har-cell */ X int average_width;`09/* A\1206 width of characters (-1 means unknown) */ X char *encoding;`09/* ISO8859-1 is LATIN1 */ X`7D; Xtypedef struct bktxt_font_def *\1007ntptr; Xint bkt_read_font_map ( void* bkfctx, `09`09/* bki_open file context */ X`09bktxt_fntptr *fontdef, `09`09/* return array of structs */ X`09int *count );`09`09&0209/* size of returned array */ X X/* X * Scan record by setting offset to 0 and calling repeatedly X * until offset greater or equal to reclen (length of record). X */ Xint bkt_text3_scan ( int reclen, char *rec,`20 X`09int *offset, char substring`5B256`5D, int *\1206length\1307glue ); $ call unpack [.WEBBOOK]BOOKFILE_TEXT.H;1 - 335559221 "FORMAT STREAM_LF;CARRIAGE_CONTROL CARRIAGE_RETURN" 3 13 20 $! $ create 'f' X/* This file defines data structures for interpreting bookreader (DEC$BOOK) X * files. X * X * Every data structure except for text_rec has a common header format: X * X * `09 struct `7B unsigned short type; long length; `7D X * X * The length includes the header. The primary record types are: X * X * First:`09Root record for the document, is always first\2908in file. X *`09`09This record contains identifcation inform\0C06(e.g. author), X *`09`09size information (e.g. maxfontid), and pointers to the X *`09`09basic components of the documents (.e.g table of contents). X *`09`09A crucial item is the record address of the last\1B07, X *`09`09which maps part numbers (page\0E08) to file records X *`09`09(see below). X * X *`09`09After the fixed portion of\1507rst record, there is X *`09`09list of ssub-records used to describe and locate the X *`09`09indices available (contents, index) and optional license X *`09`09information. X * X * Bodypart: These records comprise the displayable 'content' of X *`09`09the document. These records have a fixed header followed X *`09`09by a variable number of sub-records. The fixed portion X *`09`09contains sizing info and forward and backward pointers to X *`09`09the bodyparts logical chain. A sub-record can contain X *`09`09text, a graphic figure, a hotspot definition, or an X *`09`09extension definition (e.g. gray area). X * X * Index:`09This records contains data to allow a user to select a X *`09`09section for viewing. It consists of a list of sub-records X *`09`09describing the items in\0D06ndex. X * X * Last:`09This record contains a table for locating the file \2E06s X *`09`09comprising a part (a.k.a. page). The\1806number used is an X *`09`09index into the table and each\0F07entry contains the X *`09`09RFA of the first record\1408part and the size \190B. X *`09`09Note that a part may be larger than 32767 so i\1F06have to X *`09`09span multiple RMS records. When a part must continue to the X *`09`09next record, the last 10 bytes of the \2106 have the RFA and X *`09`09(remaining??) part size of the continuation record. The X *`09`09continued record has type of \1D08_middle or\130Aend. X * X *`09secmap: Section Map, contains a table maping the section number X *`09`09values in an index record to the part number containing that X *`09`09section. X * X *`09f_desc:`09???? X * X *`09font:`09This part is composed a set of font definition sub-records, X *`09`09each definition binds a font number (used in the attributes X *`09`09header of a text sub-record) to the adobe font name. X * X *`09continue_middle: X * continue_end: These records hold\2108ation segements for parts X *`09`09that span multiple RMS records. The data is logically X *`09`09concatenated to the previous record starting the RFA pointing X *`09`09to this record (i.e. 10 bytes are trimmed from previou\3008). X */ X/* X * Define symbolic names for records. X */ X#define BKREC_FIRST 1`09`09`09/* Root record for decw$book file */ X#define BKREC_BODYPART 3`09`09/* Document body (text) */ X#define BKREC_INDEX 4`09`09`09/* Index to other pages */ X#define BKREC_LAST 5`09`09`09/* Page id to RFA conversion */ X#define BKREC_SECMAP 6 X#define BKREC_FDX 7 X#define BKREC_FONT 9 X#define BKREC_CONT_MID 10`09`09/* Page continuation record. */ X#define BKREC_CONT_END 11`09`09/* Final record in segmented page */ X#define BKSBREC_TABLE 12 X#define BKSBREC_ASCZ_32 13 X#define BKSBREC_FONT 14 X#define BKSBREC_FDESC 15 X#define BKSBREC_IXTXT 16 X#define BKSBREC_BODYTEXT 18 X#define BKSBREC_FIGURE 19 X#define BKSBREC_FIGHOT 20`09`09/* Figure hotspot definition */ X#define BKSBREC_EXTENSION 22 X#define BKSBREC_LICENSE 24`09`09/* Alternate license */ X X#ifdef __DECC`09`09`09/* Data structures are unaligned */ X#pragma nomember_alignment X#endif X#define BKREC_COMMON_HEADER unsigned short type; long length; X/* X * Define macros to return char pointer to start of variable region of X * record and its size. X */ X#define BKREC_VAR_P(a,typ) `26a->reloff`5Bsizeof(a->typ)`5D X#define BKREC_VAR_S(a,typ) (a->gen.length - sizeof(a->typ)) X/* X * Some dataFile contains RMS Record File Addresses (RFA), mimic this structur Ve. X */ Xstruct file_address `7B`09`09/* RMS Record File A\1E07*/ X unsigned short wrd`5B3`5D; X`7D; X Xstruct first_rec `7B X BKREC_COMMON_HEADER X unsigned short maj_ver, min_ver;`09`09/* ODS version number */ X char author`5B24`5D;`09`09&0209/* ascizz */ X char product`5B36`5D; X long partcount;`09`09&0209/* number of parts */ X long sectioncount;`09`09&0209/* number of subparts */ X long dircount;`09`09&0209/* maybe */ X long fontcount;`09`09&0209/* Number of fonts? */ X long maxfontid; X struct file_address lastptr;`09`09/* RFA of last record */ X unsigned short lastsize;`09`09`09/* Size of last record */ X long docverspage, index_\0C0Ctitle, /* page IDs, 0 means absent*/ X`09sym_table, font_page, initial\0E07copyright; `20 X unsigned char title_len; X char title`5B128`5D; X long credate`5B2`5D; X char id`5B33`5D; X`7D; X Xstruct text_rec `7B`09`09`09/* text record. */ X unsigned char type, reclen; X unsigned short hor, ver; X unsigned char fontno, x, y; X char data`5B246`5D;`09`09`09/* for type three data is X`09`09&0209`09 * counted strings separated by X`09`09&0209`09 * a flags byte (usually escape */ X/* X unsigned char length; X char text`5B255`5D; */ X`7D; X Xstruct last_rec `7B X BKREC_COMMON_HEADER X struct `7B\0908file_address rfa; long size; `7D dir`5B1`5D; X`7D; X X Xunion bkrdr_rec `7B X struct `7B`09`09&0209/* Generic record format */ X`09BKREC_COMMON_HEADER X `7D gen;`09`09&0209/* Generic header */ X char raw`5B1`5D; X char reloff`5B1`5D;`09`09`09/* For computing addresses given offset*/ X X struct first_rec\0A06;`09`09/* type = BKREC_FIRST */ X X struct `7B X`09BKREC_COMMON_HEADER X`09long partno;`09`09`09/* Part number */ X`09long unk1; X`09long sectcnt; X`09long prevpart;`09`09`09/* page id of previous part */ X`09long nextpart;`09`09`09/* Id of next part */ X `7D body;`09`09&0209/* type = BKREC_BODYPART */ X X struct `7B`20 X`09BKREC_COMMON_HEADER `09`09/* type = \2006INDEX, all subrec */ X `7D index; X X struct last_rec last;`09`09/* type = BKREC_LAST */ X X struct `7B X`09BKREC_COMMON_HEADER X`09long map`5B10`5D;`09`09`09/* Maps section #s to page id */ X `7D secmap;`09`09&0209/* type = BKREC_SECMAP */ X +-+-+-+-+-+-+-+- END OF PART 3 +-+-+-+-+-+-+-+- ================== 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:52 -0400 Received: from newt.kcl.ac.uk by mail11.digital.com (8.7.5/UNX 1.2/1.0/WV) id SAA17550; Mon, 19 Aug 1996 18:03:03 -0400 (EDT) Received: from alder.cc.kcl.ac.uk by newt.kcl.ac.uk with SMTP (PP) id <23293-0@newt.kcl.ac.uk>; Mon, 19 Aug 1996 23:02:55 +0100 Received: by alder.cc.kcl.ac.uk (MX V4.2 AXP) id 731; Mon, 19 Aug 1996 23:03:15 EDT Date: Mon, 19 Aug 1996 23:03:01 BST From: Kings College London File Server To: everhart@star.zko.dec.com Message-ID: <009A71AB.090D4F60.731@alder.cc.kcl.ac.uk> Subject: WEBBOOK.3-OF-5