[0001] [0002] [0003] [0004] [0005] [0006] [0007] [0008] [0009] [0010] [0011] [0012] [0013] [0014] [0015] [0016] [0017] [0018] [0019] [0020] [0021] [0022] [0023] [0024] [0025] [0026] [0027] [0028] [0029] [0030] [0031] [0032] [0033] [0034] [0035] [0036] [0037] [0038] [0039] [0040] [0041] [0042] [0043] [0044] [0045] [0046] [0047] [0048] [0049] [0050] [0051] [0052] [0053] [0054] [0055] [0056] [0057] [0058] [0059] [0060] [0061] [0062] [0063] [0064] [0065] [0066] [0067] [0068] [0069] [0070] [0071] [0072] [0073] [0074] [0075] [0076] [0077] [0078] [0079] [0080] [0081] [0082] [0083] [0084] [0085] [0086] [0087] [0088] [0089] [0090] [0091] [0092] [0093] [0094] [0095] [0096] [0097] [0098] [0099] [0100] [0101] [0102] [0103] [0104] [0105] [0106] [0107] [0108] [0109] [0110] [0111] [0112] [0113] [0114] [0115] [0116] [0117] [0118] [0119] [0120] [0121] [0122] [0123] [0124] [0125] [0126] [0127] [0128] [0129] [0130] [0131] [0132] [0133] [0134] [0135] [0136] [0137] [0138] [0139] [0140] [0141] [0142] [0143] [0144] [0145] [0146] [0147] [0148] [0149] [0150] [0151] [0152] [0153] [0154] [0155] [0156] [0157] [0158] [0159] [0160] [0161] [0162] [0163] [0164] [0165] [0166] [0167] [0168] [0169] [0170] [0171] [0172] [0173] [0174] [0175] [0176] [0177] [0178] [0179] [0180] [0181] [0182] [0183] [0184] [0185] [0186] [0187] [0188] [0189] [0190] [0191] [0192] [0193] [0194] [0195] [0196] [0197] [0198] [0199] [0200] [0201] [0202] [0203] [0204] [0205] [0206] [0207] [0208] [0209] [0210] [0211] [0212] [0213] [0214] [0215] [0216] [0217] [0218] [0219] [0220] [0221] [0222] [0223] [0224] [0225] [0226] [0227] [0228] [0229] [0230] [0231] [0232] [0233] [0234] [0235] [0236] [0237] [0238] [0239] [0240] [0241] [0242] [0243] [0244] [0245] [0246] [0247] [0248] [0249] [0250] [0251] [0252] [0253] [0254] [0255] [0256] [0257] [0258] [0259] [0260] [0261] [0262] [0263] [0264] [0265] [0266] [0267] [0268] [0269] [0270] [0271] [0272] [0273] [0274] [0275] [0276] [0277] [0278] [0279] [0280] [0281] [0282] [0283] [0284] [0285] [0286] [0287] [0288] [0289] [0290] [0291] [0292] [0293] [0294] [0295] [0296] [0297] [0298] [0299] [0300] [0301] [0302] [0303] [0304] [0305] [0306] [0307] [0308] [0309] [0310] [0311] [0312] [0313] [0314] [0315] [0316] [0317] [0318] [0319] [0320] [0321] [0322] [0323] [0324] [0325] [0326] [0327] [0328] [0329] [0330] [0331] [0332] [0333] [0334] [0335] [0336] [0337] [0338] [0339] [0340] [0341] [0342] [0343] [0344] [0345] [0346] [0347] [0348] [0349] [0350] [0351] [0352] [0353] [0354] [0355] [0356] [0357] [0358] [0359] [0360] [0361] [0362] [0363] [0364] [0365] [0366] [0367] [0368] [0369] [0370] [0371] [0372] [0373] [0374] [0375] [0376] [0377] [0378] [0379] [0380] [0381] [0382] [0383] [0384] [0385] [0386] [0387] [0388] [0389] [0390] [0391] [0392] [0393] [0394] [0395] [0396] [0397] [0398] [0399] [0400] [0401] [0402] [0403] [0404] [0405] [0406] [0407] [0408] [0409] [0410] [0411] [0412] [0413] [0414] [0415] [0416] [0417] [0418] [0419] [0420] [0421] [0422] [0423] [0424] [0425] [0426] [0427] [0428] [0429] [0430] [0431] [0432] [0433] [0434] [0435] [0436] [0437] [0438] [0439] [0440] [0441] [0442] [0443] [0444] [0445] [0446] [0447] [0448] [0449] [0450] [0451] [0452] [0453] [0454] [0455] [0456] [0457] [0458] [0459] [0460] [0461] [0462] [0463] [0464] [0465] [0466] [0467] [0468] [0469] [0470] [0471] [0472] [0473] [0474] [0475] [0476] [0477] [0478] [0479] [0480] [0481] [0482] [0483] [0484] [0485] [0486] [0487] [0488] [0489] [0490] [0491] [0492] [0493] [0494] [0495] [0496] [0497] [0498] [0499] [0500] [0501] [0502] [0503] [0504] [0505] [0506] [0507] [0508] [0509] [0510] [0511] [0512] [0513] [0514] [0515] [0516] [0517] [0518] [0519] [0520] [0521] [0522] [0523] [0524] [0525] [0526] [0527] [0528] [0529] [0530] [0531] [0532] [0533] [0534] [0535] [0536] [0537] [0538] [0539] [0540] [0541] [0542] [0543] [0544] [0545] [0546] [0547] [0548] [0549] [0550] [0551] [0552] [0553] [0554] [0555] [0556] [0557] [0558] [0559] [0560] [0561] [0562] [0563] [0564] [0565] [0566] [0567] [0568] [0569] [0570] [0571] [0572] [0573] [0574] [0575] [0576] [0577] [0578] [0579] [0580] [0581] [0582] [0583] [0584] [0585] [0586] [0587] [0588] [0589] [0590] [0591] [0592] [0593] [0594] [0595] [0596] [0597] [0598] [0599] [0600] [0601] [0602] [0603] [0604] [0605] [0606] [0607] [0608] [0609] [0610] [0611] [0612] [0613] [0614] [0615] [0616] [0617] [0618] [0619] [0620] [0621] [0622] [0623] [0624] [0625] [0626] [0627] [0628] [0629] [0630] [0631] [0632] [0633] [0634] [0635] [0636] [0637] [0638] [0639] [0640] [0641] [0642] [0643] [0644] [0645] [0646] [0647] [0648] [0649] [0650] [0651] [0652] [0653] [0654] [0655] [0656] [0657] [0658] [0659] [0660] [0661] [0662] [0663] [0664] [0665] [0666] [0667] [0668] [0669] [0670] [0671] [0672] [0673] [0674] [0675] [0676] [0677] [0678] [0679] [0680] [0681] [0682] [0683] [0684] [0685] [0686] [0687] [0688] [0689] [0690] [0691] [0692] [0693] [0694] [0695] [0696] [0697] [0698] [0699] [0700] [0701] [0702] [0703] [0704] [0705] [0706] [0707] [0708] [0709] [0710] [0711] [0712] [0713] [0714] [0715] [0716] [0717] [0718] [0719] [0720] [0721] [0722] [0723] [0724] [0725] [0726] [0727] [0728] [0729] [0730] [0731] [0732] [0733] [0734] [0735] [0736] [0737] [0738] [0739] [0740] [0741] [0742] [0743] [0744] [0745] [0746] [0747] [0748] [0749] [0750] [0751] [0752] [0753] [0754] [0755] [0756] [0757] [0758] [0759] [0760] [0761] [0762] [0763] [0764] [0765] [0766] [0767] [0768] [0769] [0770] [0771] [0772] [0773] [0774] [0775] [0776]
/* * Bookreader to HTML comverter usage: * * path-info: * /dir/file.[Pnnn.|Itable.|Gnnn.]type (type = decw$book) * /hist1[/histn...]/disk:<dir>file.type/ (type = decw$bookshelf) * * The middle element ([Pnn.|Itable...\]) speficies a sub-section of * the file to format: * * Pnnn Returns part indicated by nnn, which is a decimal number. * The part number is an internal addressing scheme used by * the bookreader to reference a chunk to data to be read at * one time. * * Itable Format index named by 'table', name is case sensitive and * the list of available tables is defined by the document. * * Gnnn Format part nnn as graphic image (GIF). * * When the path-info ends in a slash, webbook assumes the preceding * path element is a VMS file specification of a shelf file to * format and display. Path element preceding the file name are * formatted as header lines in the resulting HTML. * * Conditional compilation symbols: * NOCGILIB When defined, build script for DCL-based CGI * environment: argv[1] is path, CGI variables are * DCL symbols/logicals of form WWW_var_name. * * NOCGIPREFIX If defined, inhibits WWW_ prefix on env. vars. * * VERBOSE When defined, include bookreader internal codes * as HTML comments and 'glue' bytes as <gxx>. * * Author: David Jones * Date: 5-MAY-1996 */ #include <stdlib.h> #include <stdio.h> #include <string.h> #include <ctype.h> #include <unixlib.h> #ifdef __DECC #ifndef shell$translate_vms /* pre 5.0 on VAX */ int decc$to_vms(); #endif #define SHELL_TO_VMS(a,b,c) decc$to_vms(a,b,c,0) /* set no-directory*/ #else #define SHELL_TO_VMS shell$to_vms int shell$to_vms(); #endif #ifdef NOCGILIB #ifdef NOCGIPREFIX #define PLEN 0 #else #define PLEN 4 #endif #define file_arg argv[1] #define cgi_init(a,b) 1 #define cgi_printf printf #define cgi_info(a) getenv((char *)( strcpy(&cgi_info_buf[PLEN],a))-PLEN) static char cgi_info_buf[64] = { 'W', 'W', 'W', '_' }; #else #include "scriptlib.h" #include "cgilib.h" #define printf cgi_printfxxx #define file_arg cgi_info("PATH_INFO") #endif #include "bookreader_recdef.h" #include "bookfile_io.h" #include "bookfile_index.h" #include "bookfile_section.h" #include "bookfile_text.h" #include "bookfile_figure.h" static char *webbook_version = "WEBBOOK 0.90, 11-JUL-1999"; static int show_part ( void * bkf, int part_num, bktxt_fntptr fontdef, int ); static int show_image ( void *bkf, int sect_num ); static char *href_fname; static char *href_type; /* for genrating HREF="name.xxx.type"*/ static char *escape_string ( char *source ); static char vms_bookfile[256]; static int save_bookfile_name ( char *name, int flags ) { strncpy ( vms_bookfile, name, 255 ); vms_bookfile[255] = '\0'; return 1; } static char nbsp = 160; /* non-breaking space */ static void error_abort ( char *sts_line, char *message ) { cgi_printf ( "Content-type: text/plain\n%s\n\n%s\n", sts_line, message ); exit ( 1 ); } static char *entify ( char *source ) { int i; char *p, *d; static char fixup[8192]; for ( p = source; *p; p++ ) if ( *p == '<' || *p == '>' || *p == '&' ) { for ( i = 0, p = source; *p; p++ ) { if ( *p == '<' ) { strcpy ( &fixup[i], "<" ); i += 4; } else if ( *p == '>' ) { strcpy ( &fixup[i], ">" ); i += 4; } else if ( *p == '&' ) { strcpy ( &fixup[i], "&" ); i += 5; } else fixup[i++] = *p; } if ( i > 8184 ) return source; /* give up */ fixup[i] = '\0'; return fixup; } return source; /* string OK as is. */ } int webbook_shelf ( char *, char * ); int main ( int argc, char **argv ) { long ndx_value; int i, j, bad, status, part_length, length, single_sect, part_num; int first, ndx_type, ndx_count, iter_count, font_count, select, type; int dir_delim; short ndx_hdr[9]; char *desc, *bookfile, *defdir, *table, *sec_str, *tmp; char bookpath[300], ndx_name[256]; unsigned char attr[4]; bkrdr_recptr root; bktxt_fntptr fontdef; void *bkf, *bki; /* * setup CGI environment. */ status = cgi_init ( argc, argv ); if ( (status&1) == 0 ) fprintf(stderr,"Status of cgi_init: %d\n", status ); if ( (status&1) == 0 ) exit ( status ); if ( argc < 2 ) { error_abort ( "500 missing argument", "usage: webbook /path/file[.xnnn].type[/]" ); } bookfile = file_arg; i = strlen ( bookfile ); if ( bookfile[i-1] == '/' ) { bookfile[i-1] = '\0'; return webbook_shelf ( bookfile, webbook_version ); } else if ( (bookfile[i-1] == ']') || (bookfile[i-1] == '>') ) { char *port; /* * Idiot forgot the trailing slash, issure redirect. */ port = cgi_info("SERVER_PORT"); if ( !port ) port = "80"; if ( strcmp ( port, "80" ) == 0 ) port = ""; cgi_printf("Location: http://%s%s%s%s%s/\n\n", cgi_info("SERVER_NAME"), *port ? ":" : "", port, cgi_info("SCRIPT_NAME"), bookfile ); return 1; } /* * Interpret command line arguments. */ i = strlen ( bookfile ); if ( i+1 >= sizeof(bookpath) ) { error_abort ( "400 bad argument", "Argument too long" ); } strcpy ( bookpath, bookfile ); /* * Scan from back for filename portion and track the periods. */ select = type = dir_delim = i; for (j=i-1; (j >= 0) && (bookpath[j] != '/'); --j) { if ( bookpath[j] == '.' ) { if ( dir_delim != i ) ; else if ( type == i ) type = j; else if ( select == i ) select = j; else { error_abort ( "404 bad filename", bookpath ); } } else if ( (bookpath[j] == ']') || (bookpath[j] == '>') ) { dir_delim = j; } } href_fname = &bookpath[j+1]; /* just filename without path */ if ( select != i ) { /* Reorder things, we stil have original in argv[1] */ strcpy ( &bookpath[select], bookfile + type ); strncpy ( &bookpath[select-type+i], bookfile+select, type - select ); bookpath[select-type+i] = '\0'; j = i + select - type; type = select; select = j+1; } fprintf(stdout,"argv[1] = '%s' -> '%s' (%d)\n", bookfile, bookpath, strcspn (":[<", bookpath) ); /* * convert filename to vms format for bkf_open. */ if ( strcspn ( ":[<", bookpath ) > 3 ) { vms_bookfile[0] = '\0'; status = SHELL_TO_VMS ( bookpath, save_bookfile_name, 1 ); if ( (status&1) == 0 ) { cgi_printf("Content-type: text/plain\nStatus: 404 bad filename\n\n"); cgi_printf("Failure to convert filename format:'%s'\n", vms_bookfile ); exit(status); } } else { /* Already in VMS format */ strncpy ( vms_bookfile, bookpath[0] == '/' ? &bookpath[1] : bookpath, 255 ); vms_bookfile[255] = '\0'; } i = strlen(vms_bookfile); if ( i > 0 ) if ( vms_bookfile[i-1] == '.' ) strcpy ( &vms_bookfile[i], "decw$book" ); fprintf(stdout,"VMS bookfile spec: '%s' (%d)\n", vms_bookfile, i ); bookfile = vms_bookfile; /* * Make printf control strings for generating HREF targets for * different tables. */ href_type = (bookpath[type] == '.') ? &bookpath[type+1] : &bookpath[type]; bookpath[type] = '\0'; href_fname = escape_string(href_fname); /* encode punctuation */ /* * Select arguments */ defdir = "sys$disk:[].decw$book"; table = sec_str = (char *) 0; if ( bookpath[select] == 'n' ) sec_str = &bookpath[select+1]; else if ( bookpath[select] == 't' ) table = &bookpath[select+1]; /* * Open file, read root page, and display some of it's fields. */ status = bkf_open ( bookfile, defdir, &bkf ); if ( (status&1) == 0 ) { cgi_printf("Content-type: text/plain\n\n"); cgi_printf("error opening bookfile '%s'\n", bookfile ); exit ( status ); } status = bkf_read_page ( bkf, 0, &part_length, &root, &length ); if ( (status&1) == 0 ) { cgi_printf("Content-type: text/plain\n\n"); cgi_printf("error reading root part: %d\n", status ); exit ( status ); } if ( bookpath[select] != 'g' && bookpath[select] != 'G' ) { cgi_printf ( "Content-type: text/html\n\n<HTML>" ); cgi_printf("<HEAD><TITLE>%s</TITLE></HEAD>\n", entify(root->first.title)); cgi_printf("<!-- partcount: %d, sectioncount %d -->\n", root->first.partcount, root->first.sectioncount ); if ( root->first.author[0] ) cgi_printf("<!-- Author: %s.-->\n", root->first.author ); cgi_printf("<!-- Software: %s --><HEAD>\n", webbook_version ); } /* * Read font table. */ status = bkt_read_font_map ( bkf, &fontdef, &font_count ); /* * Take action depending upon the first char of selector. */ part_num = 0; switch ( bookpath[select] ) { /* Convert section argument to part number and fall throuh */ case 's': case 'S': single_sect = atoi ( &bookpath[select+1] ); status = bkf_lookup_section ( bkf, single_sect, &part_num ); case 'p': case 'P': if ( part_num == 0 ) part_num = atoi ( &bookpath[select+1] ); status = show_part ( bkf, part_num, fontdef, font_count ); break; case '\0': case 't': case 'T': /* * Create context for index operations. */ status = bki_create_context ( bkf, &bki ); if ( (status&1) == 0 ) { cgi_printf("error creating index context\n" ); exit ( status ); } /* * Make directory of indexes. */ table = bookpath[select] ? &bookpath[select+1] : ""; cgi_printf ( "<H2>Available tables:</H2><UL>\n" ); for ( status = bki_find_index ( bki,"*",-1, ndx_name, &ndx_type, &ndx_count ); (status&1) == 1; status = bki_find_index ( bki, "*", -1, ndx_name, &ndx_type, &ndx_count ) ) { cgi_printf("<LI><A HREF=\"%s.t%s.%s\">%s</A> (%d entries)</LI><BR>\n", href_fname, ndx_name, href_type, ndx_name, ndx_count ); } bki_find_index_end ( bki ); cgi_printf("</UL>\n"); if (strcmp(table,"*") == 0) break; /* * List named table. */ if ( *table == '\0' ) { /* Lookup first table */ status = bki_find_index ( bki, "*", 5, ndx_name, &ndx_type, &ndx_count ); fprintf(stderr, "Find status for default index: %d, name: %s\n", status, ndx_name ); table = ndx_name; } status = bki_open_index ( bki, table ); if ( (status&1) == 0 ) { cgi_printf("Unable to open index '%s'\n", ndx_name ); break; } cgi_printf("<HR><H2>%s</H2>(%d entries)<UL>\n", entify(table), ndx_count ); for ( ; ; ) { int first; status = bki_read_index( bki, ndx_hdr, attr, ndx_name, &desc, &ndx_value); if ( (status&1) == 0 ) break; if ( ndx_value <= 0 || ndx_value > root->first.sectioncount) { cgi_printf("</UL>%s<UL>\n", entify(desc) ); } else { status = bkf_lookup_first_section ( bkf, ndx_value, &part_num, &first ); cgi_printf("<LI><A HREF=\"%s.p%d.%s#%d\">%s</A></LI><BR>\n", href_fname, part_num, href_type, ndx_value, entify(desc) ); } } cgi_printf("</UL>\n"); break; case 'g': case 'G': /* * Return figure as graphic image, argument is section number. */ cgi_printf ( "Content-type: image/gif\n\n" ); single_sect = atoi ( &bookpath[select+1] ); status = bkf_lookup_section ( bkf, single_sect, &part_num ); if ( (status&1) == 1 ) status = show_image(bkf, single_sect); else { } default: break; } if ( bookpath[select] != 'g' && bookpath[select] != 'G' ) cgi_printf("</BODY>\n"); /* * Cleanup. */ status = bkf_close ( bkf ); return status; } /* Sub-record summary information */ struct sb_summary { int type; int length; struct sb_summary *hot; /* link to hotspot def */ long hdr[9]; }; struct convert_ctx { /* input state (bookreader) */ void *bkf, *cursor; bktxt_fntptr fontdef; int font_count, cur_font; int in_x, in_y; /* output state (HTML) */ int bold_on; int italic_on; int monospace_on; int font_nonprintable; int hdr_level; int dl_depth; /* indentation level ((x-100)/50)) */ int out_x, out_y; /* virtual */ }; static struct sb_summary *check_hotspot ( short x, short y, struct sb_summary *hot ) { for ( ; hot; hot = hot->hot ) { /* cgi_printf("\ncheckhot x: %d y: %d, spot: %d %d lw: %d %d\n", x, y, hot->hdr[3],hot->hdr[4],hot->hdr[5],hot->hdr[6]); */ if ( hot->hdr[4] <= y && hot->hdr[4]+hot->hdr[6] >= y && hot->hdr[3] <= x && hot->hdr[3] + hot->hdr[5] >= x ) return hot; } return hot; } /* * Generate necessary HTML to change from current font to desired font and * update state. */ static int change_font ( unsigned char new_font, struct convert_ctx *cvt ) { bktxt_fntptr fnt; /* 12-MAY-2000 MGD (char)! */ if ( (char)new_font < 0 || new_font >= cvt->font_count ) return 0; cvt->cur_font = new_font; fnt = &cvt->fontdef[new_font]; if ( cvt->bold_on ) { if ( fnt->weight[0] != 'B' ) { cvt->bold_on = 0; cgi_printf("</B>"); } } else { if ( fnt->weight[0] == 'B' ) { cvt->bold_on = 1; cgi_printf("<B>"); } } if ( cvt->italic_on ) { if ( fnt->style[0] != 'I' ) { cvt->italic_on = 0; cgi_printf("</I>"); } } else { if ( fnt->style[0] == 'I' ) { cvt->italic_on = 1; cgi_printf("<I>"); } } if ( cvt->monospace_on ) { if ( fnt->spacing[0] != 'P' ) { cvt->monospace_on = 1; cgi_printf("<TT>"); } } else { /* test for proportional spacing */ if ( fnt->style[0] == 'P' ) { cvt->monospace_on = 0; cgi_printf("</TT>"); } } if ( cvt->font_nonprintable ) { if ( fnt->encoding[0] != '*' ) cvt->font_nonprintable = 0; } else { if ( fnt->encoding[0] == '*' ) cvt->font_nonprintable = 1; } return 1; } /* * Generate HTML to perform line breaks. */ #ifdef OLD_WAY static void change_line ( int new_x, int new_y, struct convert_ctx *cvt ) { int target_dl; target_dl = (new_x-100) / 50; if ( target_dl > cvt->dl_depth ) { /* Change indentation level */ while ( target_dl > cvt->dl_depth ) { cgi_printf("<DL><DD>"); cvt->dl_depth++; } } else if ( target_dl < cvt->dl_depth ) { while ( target_dl < cvt->dl_depth ) { cgi_printf("</DD></DL>"); cvt->dl_depth--; } cgi_printf("\n"); } else { cgi_printf( (new_y - cvt->in_y) > 100 ? "<P>\n" : "<BR>\n"); } cvt->in_x = cvt->dl_depth * 50; } #endif static void change_line ( int new_x, int new_y, struct convert_ctx *cvt, int para ) { int target_dl, i; char indent[200]; target_dl = ((new_x) / 50) * 2; if ( target_dl > 120 ) target_dl = 60; if ( target_dl < 0 ) target_dl = 0; for ( i = 0; i < target_dl; i++ ) indent[i] = nbsp; indent[target_dl] = '\0'; cgi_printf ( "%s\n%s", para ? "<p>" : "<br>", indent ); } static int format_bodytext ( struct convert_ctx *cvt, struct sb_summary *sb ) { int status, is_last, t_len, t_type, i, offset, glue, slen, is_link; short h_v[2]; unsigned char attr[4]; char *data; char buffer[256]; /* * Scan sub-sections. */ cgi_printf ( "<A NAME=\"%d\">", sb->hdr[1] ); for ( is_last = 0; !is_last; ) { status = bks_read_section ( cvt->cursor, &t_type, h_v, attr, &t_len, &data, &is_last ); if ( (status&1) == 0 ) cgi_printf("%sread error, status: %d, is_last: %d%s\n", is_last ? "<!-- ":"", status, is_last, is_last ? " -->" :"" ); if ( (status&1) == 0 ) break; #ifdef VERBOSE cgi_printf("<!-- subtxt: t=%d h=%d v=%d attr: %d %d %d %d -->\n", t_type, h_v[0], h_v[1], attr[0], attr[1], attr[2], attr[3] ); #endif if ( t_type == 3 || t_type == 2 ) { struct sb_summary *hot_link; if ( attr[0] != cvt->cur_font ) change_font ( attr[0], cvt ); if ( cvt->in_y > h_v[1] ) { change_line ( h_v[0], h_v[1], cvt, 1 ); } else if ( (cvt->in_x > h_v[0]) || (cvt->in_y < h_v[1]) ) { change_line ( h_v[0], h_v[1], cvt, 0 ); } else cgi_printf ( " " ); /* separate words */ hot_link = sb->hot; if (hot_link) hot_link = check_hotspot ( h_v[0], h_v[1], sb->hot ); if ( hot_link ) { if ( hot_link->hdr[7] == sb->hdr[1] ) cgi_printf ( "<A HREF=\"#7%d\">", hot_link->hdr[7] ); else { int part_num; bkf_lookup_section ( cvt->bkf, hot_link->hdr[7], &part_num ); cgi_printf ( "<A HREF=\"%s.p%d.%s#%d\">", href_fname, part_num, href_type, hot_link->hdr[7] ); } } cvt->in_x = h_v[0]; cvt->in_y = h_v[1]; for ( offset = 0; offset < t_len; ) { bkt_text3_scan ( t_len, data, &offset, buffer, &slen, &glue ); if ( offset < t_len ) buffer[slen++] = ' '; buffer[slen] = '\0'; if ( cvt->font_nonprintable ) { char jj; for ( jj = 0; jj < slen; jj++ ) buffer[jj] = '.'; cvt->in_x = 1000; } cgi_printf("%s", entify(buffer)); #ifdef VERBOSE cgi_printf("<g%x>", glue); #endif } if ( hot_link ) cgi_printf ( "</A>" ); }else if ( t_type == 1 ) { cgi_printf("<HR> <!-- type 1 subrec -->\n"); cvt->in_x = 0; cvt->in_y += 40; } } cgi_printf("</A><BR>\n"); cvt->in_x = 0; return status; } static int show_part ( void * bkf, int part_num, bktxt_fntptr fontdef, int font_count ) { struct convert_ctx cvt; char *desc; long ndx_value, hdr[9]; int j, i, part_info[4], sect_info[4]; int status, count, match, iter, iter_count, type, length, is_last; short ndx_hdr[9]; char name[256]; struct sb_summary *sb; /* * Create data structures used by bookfile_section.c */ cvt.bkf = bkf; cvt.fontdef = fontdef; cvt.font_count = font_count; cvt.hdr_level = 0; cvt.dl_depth = 0; status = bks_create_section_cursor ( bkf, &cvt.cursor ); if ( (status&1) == 0 ) { cgi_printf("Error creating cursor: %d\n", status ); exit ( status ); } /* * Position to begining of part, seek function returns number of * sub-records (sections) in part. */ status = bks_seek_part ( cvt.cursor, part_num, 0, &iter_count ); if ( (status&1) == 0 ) { cgi_printf("Error seeking part: %d\n", status ); exit ( status ); } /* * Make links to previous and next. */ status = bks_get_cursor_info ( cvt.cursor, part_info, sect_info ); if ( (status&1) == 1 ) { if ( part_info[2] > 0 ) cgi_printf("[<A HREF=\"%s.p%d.%s\">next</A>] ", href_fname, part_info[2], href_type ); else cgi_printf ( "[next] " ); if ( part_info[1] > 0 ) cgi_printf("[<A HREF=\"%s.p%d.%s\">previous</A>] ", href_fname, part_info[1], href_type ); else cgi_printf ( "[previous] " ); cgi_printf("[<A HREF=\"%s.%s\">contents</A>]<BR><HR>\n", href_fname, href_type ); } /* * Allocate array to hold summary information. */ sb = (struct sb_summary *) malloc(iter_count*sizeof(struct sb_summary)); if ( !sb ) return 0; for ( iter = 0; iter < iter_count; iter++ ) sb[iter].hot = (struct sb_summary *) 0; /* * Make first pass over part to get header info and hotspot info. */ for ( iter = 0; iter < iter_count; iter++ ) { status = bks_seek_section ( cvt.cursor, iter? 1 : 0, 1, &sb[iter].type, &sb[iter].length, sb[iter].hdr ); if ( (status&1) == 0 ) cgi_printf("Error in seek: %d\n", status); if ( (status&1) == 0 ) break; if ( sb[iter].type == BKSBREC_FIGHOT ) { i = sb[iter].hdr[2]; for ( j = iter-1; j >=0; --j ) if ( sb[j].type == BKSBREC_BODYTEXT && (sb[j].hdr[1] == i) ) { sb[iter].hot = sb[j].hot; sb[j].hot = &sb[iter]; } } } /* * Make second pass over data to output it. */ cvt.cur_font = -1; cvt.in_x = 0; cvt.in_y = 10000; cvt.bold_on = cvt.italic_on = cvt.monospace_on = 0; cvt.font_nonprintable = 0; status = bks_seek_part ( cvt.cursor, part_num, 0, &iter_count ); if ( (status&1) == 0 ) { cgi_printf("Error seeking part: %d\n", status ); exit ( status ); } for ( iter = 0; iter < iter_count; iter++ ) { status = bks_seek_section ( cvt.cursor, iter? 1 : 0, 1, &type, &length, hdr ); if ( (status&1) == 0 ) break; /* cgi_printf("section type: %d, length: %d nxthost: %d\n", type, length, sb[iter].hot ); */ if ( type == BKSBREC_BODYTEXT ) { #ifdef VERBOSE int k; static char *hnm[9] = { "[0]", "sec", "[2]", "[3]", "[4]", "[5]", "hgt", "[7]", "[8]" }; cgi_printf("\n<!-- bodytext hdr:" ); for ( k = 0; k < 9; k++ ) if ( hdr[k] ) cgi_printf ( " %s=%d", hnm[k], hdr[k] ); cgi_printf("-->\n"); #endif status = format_bodytext ( &cvt, &sb[iter] ); } else if ( type == BKSBREC_FIGURE ) { int t_len, t_type, is_last; short h_v[2]; unsigned char attr[4]; char *data; char buffer[256]; cgi_printf( "<!-- figure sec %d pos: (%d,%d) size: (%d %d)=%d type: %d -->\n", hdr[2], hdr[3], hdr[4], hdr[5], hdr[6], length, hdr[7]&255 ); /* */ status = bks_read_section ( cvt.cursor, &t_type, h_v, attr, &t_len, &data, &is_last ); cgi_printf("<IMG SRC=\"%s.g%d.%s\">", href_fname, hdr[2], href_type ); } } if ( cvt.monospace_on ) cgi_printf("</TT>"); if ( cvt.italic_on ) cgi_printf("</I>"); if ( cvt.bold_on ) cgi_printf("</B>"); bks_delete_section_cursor ( cvt.cursor ); return status; } static int out_to_netlink ( void *fptr, int size, char *buffer ) { int status; #ifndef NOCGILIB status = net_link_write ( buffer, size ); return status; #else status = fwrite ( buffer, size, 1, (FILE *) fptr ); return 1; #endif } static int show_image ( void *bkf, int sect_num ) { void *cursor; long hdr[9]; int j, i, k, width, height, mask, value, t_type, t_len; int status, count, match, type, length, is_last; short *cols, *rows; short h_v[2]; unsigned char attr[4]; char *data; unsigned char *cur_row, *cur_col; unsigned char *pixel_image, *pixel_row; unsigned char color_table[6] = { 0, 0, 0, 255, 255, 255 }; /* * Seek to section containing image. */ status = bks_create_section_cursor ( bkf, &cursor ); if ( (status&1) == 1 ) status = bks_seek_section ( cursor, sect_num, 0, &type, &length, hdr ); while ( (type != BKSBREC_FIGURE) && ((status&1) == 1) ) { status = bks_seek_section ( cursor, 1, 1, &type, &length, hdr ); } if ( (status&1) == 1 ) status = bks_read_section ( cursor, &t_type, h_v, attr, &t_len, &data, &is_last ); if ( (status&1) == 0 ) { cgi_printf("Error retrieving figure data: %d\n", status ); exit ( status ); } if ( type == BKSBREC_FIGURE ) { /* * Create gif file, with data going back to net link. */ #ifdef NOCGILIB char fname[256]; FILE *out; sprintf ( fname, "%s-g%d.gif", href_fname, sect_num ); out = fopen ( fname, "wb" ); if ( !out ) { fprintf(stderr, "Error openning '%s'\n", fname ); } else { #else void *out; out = (void *) 0; #endif status = bkg_convert_figure_to_gif ( hdr, (unsigned char *) data, t_len, out_to_netlink, out ); #ifdef NOCGILIB fprintf(stderr,"status of gif generate (%s): %d\n", fname, status ); fclose ( out ); } #endif } /* * Cleanup up. */ bks_delete_section_cursor ( cursor ); return status; } /****************************************************************************/ /* Convert strings containing punctuation characters into escaped strings. */ static char *escape_string ( char *source ) { int i, j, punct_count; char *dest; dest = source; punct_count = 0; for ( i = 0; source[i]; i++ ) if ( ispunct ( source[i] ) ) { if ( (source[i] != '.') && (source[i] != '$') )punct_count++; } else if ( isspace ( source[i] ) ) punct_count++; if ( punct_count > 0 ) { dest = malloc ( i + punct_count*3 + 1 ); if ( !dest ) return source; for ( i = j = 0; source[i]; i++ ) { if ( isspace(source[i]) || (ispunct ( source[i] ) && (source[i] != '.') && (source[i] != '$')) ) { sprintf ( &dest[j], "%%%02x", source[i] ); if ( dest[j+1] == ' ' ) dest[j+1] = '0'; j += 3; } else dest[j++] = source[i]; } dest[j] = '\0'; } return dest; }