From: simon Date: Sat, 9 Dec 2006 18:03:18 +0000 (+0000) Subject: Support, in the winhelp module only, for adding pictures to .HLP X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/halibut/commitdiff_plain/83ac0debd7ddd9dfd9defefbcd15c8bef7905d6f Support, in the winhelp module only, for adding pictures to .HLP files. Halibut does not make use of this feature, but I hope that one day it might. git-svn-id: svn://svn.tartarus.org/sgt/halibut@6980 cda61777-01e9-0310-a592-d414129be87e --- diff --git a/winhelp.c b/winhelp.c index 7db4801..40053ca 100644 --- a/winhelp.c +++ b/winhelp.c @@ -183,6 +183,7 @@ struct WHLP_tag { int para_flags; int para_attrs[7]; int ncontexts; + int picture_index; }; /* Functions to return the index and leaf data for B-tree contents. */ @@ -196,6 +197,10 @@ static void whlp_file_add(struct file *f, const void *data, int len); static void whlp_file_add_char(struct file *f, int data); static void whlp_file_add_short(struct file *f, int data); static void whlp_file_add_long(struct file *f, int data); +static void whlp_file_add_cushort(struct file *f, int data); +static void whlp_file_add_csshort(struct file *f, int data); +static void whlp_file_add_culong(struct file *f, int data); +static void whlp_file_add_cslong(struct file *f, int data); static void whlp_file_fill(struct file *f, int len); static void whlp_file_seek(struct file *f, int pos, int whence); static int whlp_file_offset(struct file *f); @@ -797,6 +802,94 @@ void whlp_tab(WHLP h) whlp_linkdata(h, 1, 0x83); } +int whlp_add_picture(WHLP h, int wd, int ht, const void *vpicdata, + const unsigned long *palette) +{ + struct file *f; + char filename[80]; + const unsigned char *picdata = (const unsigned char *)vpicdata; + int picstart, picoff, imgoff, imgstart; + int palettelen; + int i, index; + int wdrounded; + + /* + * Determine the limit of the colour palette. + */ + palettelen = -1; + for (i = 0; i < wd*ht; i++) + if (palettelen < picdata[i]) + palettelen = picdata[i]; + palettelen++; + + /* + * Round up the width to the next multiple of 4. + */ + wdrounded = (wd + 3) & ~3; + + index = h->picture_index++; + sprintf(filename, "bm%d", index); + + f = whlp_new_file(h, filename); + whlp_file_add_short(f, 0x706C); /* magic number */ + whlp_file_add_short(f, 1); /* number of pictures */ + picoff = whlp_file_offset(f); + whlp_file_add_long(f, 0); /* offset of first (only) picture */ + picstart = whlp_file_offset(f); + whlp_file_add_char(f, 6); /* DIB */ + whlp_file_add_char(f, 0); /* no packing */ + whlp_file_add_culong(f, 100); /* xdpi */ + whlp_file_add_culong(f, 100); /* ydpi */ + whlp_file_add_cushort(f, 1); /* planes (?) */ + whlp_file_add_cushort(f, 8); /* bitcount */ + whlp_file_add_culong(f, wd); /* width */ + whlp_file_add_culong(f, ht); /* height */ + whlp_file_add_culong(f, palettelen);/* colours used */ + whlp_file_add_culong(f, palettelen);/* colours important */ + whlp_file_add_culong(f, wdrounded*ht); /* `compressed' data size */ + whlp_file_add_culong(f, 0); /* hotspot size (no hotspots) */ + imgoff = whlp_file_offset(f); + whlp_file_add_long(f, 0); /* offset of `compressed' data */ + whlp_file_add_long(f, 0); /* offset of hotspot data (none) */ + for (i = 0; i < palettelen; i++) + whlp_file_add_long(f, palette[i]); + imgstart = whlp_file_offset(f); + /* + * Windows Help files, like BMP, start from the bottom scanline. + */ + for (i = ht; i-- > 0 ;) { + whlp_file_add(f, picdata + i*wd, wd); + if (wd < wdrounded) + whlp_file_add(f, "\0\0\0", wdrounded - wd); + } + + /* Now go back and fix up internal offsets */ + whlp_file_seek(f, picoff, 0); + whlp_file_add_long(f, picstart); + whlp_file_seek(f, imgoff, 0); + whlp_file_add_long(f, imgstart - picstart); + whlp_file_seek(f, 0, 2); + + return index; +} + +void whlp_ref_picture(WHLP h, int picid) +{ + /* + * Write a NUL into linkdata2. + */ + whlp_linkdata(h, 2, 0); + /* + * Write the formatting command and its followup data to + * specify a picture in a separate file. + */ + whlp_linkdata(h, 1, 0x86); + whlp_linkdata(h, 1, 3); /* type (picture without hotspots) */ + whlp_linkdata_cslong(h, 1, 4); + whlp_linkdata_short(h, 1, 0); + whlp_linkdata_short(h, 1, picid); +} + void whlp_text(WHLP h, char *text) { while (*text) { @@ -1538,6 +1631,46 @@ static void whlp_file_add_long(struct file *f, int data) whlp_file_add(f, s, 4); } +static void whlp_file_add_cushort(struct file *f, int data) +{ + if (data <= 0x7F) { + whlp_file_add_char(f, data*2); + } else { + whlp_file_add_char(f, 1 + (data%128 * 2)); + whlp_file_add_char(f, data/128); + } +} + +#if 0 /* currently unused */ +static void whlp_file_add_csshort(struct file *f, int data) +{ + if (data >= -0x40 && data <= 0x3F) + whlp_file_add_cushort(f, data+64); + else + whlp_file_add_cushort(f, data+16384); +} +#endif + +static void whlp_file_add_culong(struct file *f, int data) +{ + if (data <= 0x7FFF) { + whlp_file_add_short(f, data*2); + } else { + whlp_file_add_short(f, 1 + (data%32768 * 2)); + whlp_file_add_short(f, data/32768); + } +} + +#if 0 /* currently unused */ +static void whlp_file_add_cslong(struct file *f, int data) +{ + if (data >= -0x4000 && data <= 0x3FFF) + whlp_file_add_culong(f, data+16384); + else + whlp_file_add_culong(f, data+67108864); +} +#endif + static void whlp_file_fill(struct file *f, int len) { if (f->pos + len > f->size) { @@ -1599,6 +1732,7 @@ WHLP whlp_new(void) ret->prevtopic = NULL; ret->ncontexts = 0; ret->link = NULL; + ret->picture_index = 0; return ret; } @@ -2123,7 +2257,32 @@ int main(void) whlp_begin_para(h, WHLP_PARA_SCROLL); whlp_set_font(h, 1); - whlp_text(h, "This third topic is almost as boring as the first. Woo!"); + whlp_text(h, "This third topic is not nearly as boring as the first, " + "because it has a picture: "); + { + const unsigned long palette[] = { + 0xFF0000, + 0xFFFF00, + 0x00FF00, + 0x00FFFF, + 0x0000FF, + }; + const unsigned char picture[] = { + 0, 0, 0, 0, 1, 2, 3, 4, + 0, 0, 0, 0, 1, 2, 3, 4, + 0, 0, 0, 0, 1, 2, 3, 4, + 0, 0, 0, 1, 2, 3, 4, 4, + 0, 0, 0, 1, 2, 3, 4, 4, + 0, 0, 0, 1, 2, 3, 4, 4, + 0, 0, 1, 2, 3, 4, 4, 4, + 0, 0, 1, 2, 3, 4, 4, 4, + 0, 0, 1, 2, 3, 4, 4, 4, + 0, 1, 2, 3, 4, 4, 4, 4, + 0, 1, 2, 3, 4, 4, 4, 4, + 0, 1, 2, 3, 4, 4, 4, 4, + }; + whlp_ref_picture(h, whlp_add_picture(h, 8, 12, picture, palette)); + } whlp_end_para(h); /* diff --git a/winhelp.h b/winhelp.h index d0c81d5..b22e4e0 100644 --- a/winhelp.h +++ b/winhelp.h @@ -166,3 +166,33 @@ void whlp_text(WHLP h, char *text); void whlp_start_hyperlink(WHLP h, WHLP_TOPIC target); void whlp_end_hyperlink(WHLP h); void whlp_tab(WHLP h); + +/* + * Routines to add images to a help file. + * + * First call whlp_add_picture() to load some actual image data + * into a help file. This will return a numeric index which + * identifies the picture. Then you can call whlp_ref_picture() to + * indicate that that picture should be displayed inline in the + * current paragraph (i.e. it occurs between a call to + * whlp_begin_para() and whlp_end_para()). + */ + +/* + * The parameters to this function are: + * + * - wd and ht give the width and height of the image in pixels. + * - picdata is a pointer to the actual bitmap data. This _must_ + * be formatted as one byte per pixel, with each byte being an + * index into the `palette' array. Ordering is the normal one + * (top to bottom, left to right), not the Windows BMP one. + * - palettelen is an array of up to 256 unsigned longs. Each + * unsigned long represents an RGB value, in the form + * 0x00RRGGBB. Thus 0x00FF0000 is red, 0x00FF00 is green, + * 0x000000FF is blue, 0x00FFFFFF is white, zero is black, and + * so on. You may supply fewer than 256 entries if the image + * data does not refer to all possible values. + */ +int whlp_add_picture(WHLP h, int wd, int ht, const void *picdata, + const unsigned long *palette); +void whlp_ref_picture(WHLP h, int index);