summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Tatham <anakin@pobox.com>2006-12-09 18:03:18 +0000
committerSimon Tatham <anakin@pobox.com>2006-12-09 18:03:18 +0000
commit54b3f1e9c08c91e07a87cf57282490a546b93a44 (patch)
tree04045be5dd476156846a93cc6ea95d342bf04fd2
parent937f5354c40e29a59bc725f101416d1f6f8f6987 (diff)
downloadhalibut-54b3f1e9c08c91e07a87cf57282490a546b93a44.zip
halibut-54b3f1e9c08c91e07a87cf57282490a546b93a44.tar.gz
halibut-54b3f1e9c08c91e07a87cf57282490a546b93a44.tar.bz2
halibut-54b3f1e9c08c91e07a87cf57282490a546b93a44.tar.xz
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. [originally from svn r6980]
-rw-r--r--winhelp.c161
-rw-r--r--winhelp.h30
2 files changed, 190 insertions, 1 deletions
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);