summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvipsk/hps.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/dvipsk/hps.c')
-rw-r--r--Build/source/texk/dvipsk/hps.c622
1 files changed, 622 insertions, 0 deletions
diff --git a/Build/source/texk/dvipsk/hps.c b/Build/source/texk/dvipsk/hps.c
new file mode 100644
index 00000000000..65a1c85d7fd
--- /dev/null
+++ b/Build/source/texk/dvipsk/hps.c
@@ -0,0 +1,622 @@
+/* This is the main file for hacking dvips to do HyperPostScript
+ * Written by Mark D. Doyle 11/94. It is (C) Copyright 1994 by Mark D. Doyle
+ * and the University of California. You may modify and use this program to
+ * your heart's content.
+ */
+#include "dvips.h"
+
+/*
+ * The external declarations:
+ */
+#include "protos.h"
+
+#ifdef HPS
+#include <stdlib.h>
+#ifdef KPATHSEA
+#include <kpathsea/c-ctype.h>
+#else
+#define TOLOWER Tolower
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef Tolower
+#define Tolower tolower
+#endif
+#define NAME 0
+#define HREF 1
+#define skip_space(s) for(; *s == ' '; s++);
+
+Boolean inHTMLregion = 0;
+Boolean NO_ERROR = 1;
+Boolean HPS_ERROR = 0;
+integer HREF_COUNT;
+Boolean ISHREF = 0;
+Boolean POPPED = 0;
+Boolean PUSHED = 0;
+
+char *current_name;
+int current_type;
+int current_pushcount;
+
+
+#define GoTo 0
+#define GoToR 1
+#define Launch 2
+
+typedef struct rectangle {
+ double llx; /* lower left x coor */
+ double lly; /* lower left y coor */
+ double urx; /* upper right x coor */
+ double ury; /* upper right y coor */
+ } dvipsRectangle;
+
+typedef struct hps_link {
+ int action; /* GoTo, GoToR, or Launch */
+ char *file; /* PDF-style system-independent filename - unused now */
+ dvipsRectangle rect; /* rectangle for location of link */
+ int border[5]; /* Border info --- with dashes*/
+ int srcpg; /* Page of location */
+ int page; /* Page of destination --- left out is same as srcpg */
+ int vert_dest; /* Vertical position of destination on page */
+ double color[3]; /* color: length of array gives colorspace (3 <=> RGB)*/
+ char *title; /* Title of link */
+ } Hps_link;
+
+struct nlist { /* hashtable entry */
+ struct nlist *next; /* next entry in chain */
+ char *name; /* defined name */
+ Hps_link *defn; /* Link associated with name */
+ };
+
+typedef struct rect_list { /* linked list of rectangles */
+ struct rect_list *next; /* next rectangle in the chain */
+ dvipsRectangle rect;
+ } Rect_list;
+
+Rect_list *current_rect_list;
+
+#define HASHSIZE 1223
+static struct nlist *link_targets[HASHSIZE]; /* names .... */
+static struct nlist *link_sources[HASHSIZE]; /* hrefs .... */
+
+#ifdef KPATHSEA
+#define dup_str xstrdup
+#else
+char *dup_str(); /* duplicate a string */
+#endif
+
+Boolean noprocset; /* Leave out BeginProc and EndProc comments */
+/* This was hardcoded to letter size. The denominator converts scaled
+ points to big points (65536*72.27/72). */
+#undef PAGESIZE /* HP-UX 10 defines for itself. */
+#define PAGESIZE ((int) (vpapersize/65781.76))
+#define MARGIN 72
+#define VERTICAL 0
+#define HORIZONTAL 1
+#define FUDGE 2.0
+
+/* For later use
+* static char *dest_key[9] = {"Fit", "FitB", "FitW", "FitH", "FitBH"
+ "FitR", "FitV", "FitBV", "XYZ"};
+*/
+
+char *hs = NULL; /* html string to be handled */
+char *url_name = NULL; /* url between double quotes */
+
+static int href_or_name(void);
+static int parseref(void);
+static int get_string(void);
+static int do_link(char *s, int type);
+static struct nlist *lookup_link(char *s, int type);
+static struct nlist *install_link(char *name, struct hps_link *defn, int type);
+static Hps_link *link_dup(struct hps_link *s);
+static double dvi_to_hps_conv(int i, int dir);
+static int href_name_match(char *h, char *n);
+static void stamp_hps(struct hps_link *pl);
+static void stamp_external(char *s, struct hps_link *pl);
+static void print_rect_list(void);
+
+/* parse anchor into link */
+void
+do_html(char *s)
+{
+ Hps_link *nl;
+ url_name = (char *)malloc(strlen(s)+1);
+ hs = s;
+ HREF_COUNT = 0;
+ skip_space(hs); /* skip spaces */
+ if ( TOLOWER(*hs) == 'a') { /* valid start */
+ POPPED = FALSE;
+ if (inHTMLregion) {
+ error("previous html not closed with /A");
+ return;
+ } else {
+ inHTMLregion = TRUE;
+ current_rect_list = NULL;
+ }
+ hs++;
+ skip_space(hs);
+ while(*hs != '\0') {
+ /* parse for names and href */
+ if (!href_or_name()) {
+ error("Bad HMTL:");
+ error(s);
+ error("!");
+ break;
+ }
+ skip_space(hs);
+ }
+ } else if ( (*hs == '/') && (TOLOWER(hs[1]) == 'a') ) {
+ if (!inHTMLregion) {
+ error("In html, /A found without previous A");
+ return;
+ } else {
+ inHTMLregion = FALSE;
+ }
+ if (current_type == HREF && current_name[0] != '#') {
+ if ((nl = lookup_link(current_name, current_type)->defn)) {
+ nl->rect.urx = dvi_to_hps_conv(hh, HORIZONTAL);
+ nl->rect.ury = dvi_to_hps_conv(vv, VERTICAL)-FUDGE+12.0;
+ stamp_external(current_name,nl); /* Broken lines ? */
+ } else {
+ error("!Null lookup");
+ }
+ } else {
+ if ((nl = lookup_link(current_name, current_type)->defn)) {
+ nl->rect.urx = dvi_to_hps_conv(hh, HORIZONTAL);
+ nl->rect.ury = dvi_to_hps_conv(vv, VERTICAL)-FUDGE+12.0;
+ if (current_type) {
+ stamp_hps(nl); /* Put link info right where special is */
+ print_rect_list(); /* print out rectangles */
+ }
+ } else {
+ error("!Null lookup");
+ }
+ }
+ }
+ else {
+ error( "No A in html special");
+ error(s);
+ /*error("!");*/
+ }
+
+ return;
+}
+
+static int
+href_or_name(void) {
+ if ((strncmp(hs, "href", 4) == 0) || (strncmp(hs, "HREF", 4) == 0)) {
+ ISHREF = TRUE;
+ } else if ((strncmp(hs, "name", 4) == 0)
+ || (strncmp(hs, "NAME", 4) == 0)) {
+ ISHREF = FALSE;
+ } else {
+ error("Not valid href or name html reference");
+ return(HPS_ERROR);
+ }
+ if(!parseref()) return(HPS_ERROR);
+ if (url_name) {
+ if( ISHREF ) {
+ do_link(url_name, HREF);
+ } else do_link(url_name, NAME);
+ } else {
+ error("No string in qoutes ");
+ return(HPS_ERROR);
+ }
+ return(NO_ERROR);
+}
+
+static int
+parseref(void) {
+ int i = 0;
+ for(i=0; i++ < 4; hs++); /* skip href or name in html string */
+ skip_space(hs);
+ if (*hs == '=' ) {
+ hs++;
+ } else {
+ error("No equal sign");
+ return(HPS_ERROR);
+ }
+ if(!get_string()) return(HPS_ERROR);
+ return(NO_ERROR); /* extract stuff between double quotes */
+}
+
+static int
+get_string(void) {
+ char *v = url_name;
+
+ skip_space(hs);
+ /* hash_name(); */
+ if (*hs == '"') {
+ for(hs++; *hs != '"' && *hs != '\0'; *v++ = *hs++); /* need to esc " */
+ if(*hs == '"') {
+ hs++;
+ *v++ = '\0';
+ return(NO_ERROR);
+ } else {
+ error("Improper href. Missing closing double quote");
+ return(HPS_ERROR);
+ }
+ } else {
+ error("Improper href. Missing opening double quote");
+ return(HPS_ERROR);
+ }
+}
+
+static int
+do_link(char *s, int type)
+{
+
+ Hps_link *p;
+
+ if (HREF_COUNT++ > 0) {
+ error("!HTML string contains more than one href");
+ return(HPS_ERROR);
+ }
+ p = (Hps_link *)malloc(sizeof(*p));
+ p->action = GoTo;
+ p->title = (char *)malloc(strlen(s)+1);
+ p->title = s;
+ p->srcpg = pagecounter;
+ p->rect.llx = dvi_to_hps_conv(hh, HORIZONTAL);
+ p->rect.lly = dvi_to_hps_conv(vv, VERTICAL)-FUDGE;
+ p->rect.urx = -1.0;
+ p->rect.ury = -1.0;
+ p->vert_dest = -1;
+ p->page = -1;
+ p->color[0] = 0;
+ p->color[1] = 0; /* Blue links */
+ p->color[2] = 1;
+ p->border[0] = 1; /* horizontal corner radius */
+ p->border[1] = 1; /* vertical corner radius */
+ p->border[2] = 1; /* box line width */
+ p->border[3] = 3; /* dash on size */
+ p->border[4] = 3; /* dash off size */
+
+ current_name = (char *)malloc(strlen(s)+1);
+ current_name = s;
+ current_type = type;
+ current_pushcount = pushcount;
+ install_link(s, p, type);
+ return(NO_ERROR);
+}
+
+static unsigned int
+hash_string(char *s)
+{
+ unsigned hashval;
+ for (hashval = 0; *s != '\0'; s++)
+ hashval = *s + 31 * hashval;
+ return hashval % HASHSIZE;
+}
+
+/* lookup a hashed name */
+
+static struct nlist *
+lookup_link(char *s, int type)
+{
+ struct nlist *np;
+
+ for(np = type ? link_sources[hash_string(s)] : link_targets[hash_string(s)];
+ np != NULL; np = np -> next)
+ if (strcmp(s, np->name) == 0)
+ return np; /* found */
+ return NULL; /* not found */
+}
+
+static struct nlist *
+install_link(char *name, Hps_link *defn, int type)
+{
+ struct nlist *np;
+ unsigned hashval;
+ np = (struct nlist *)malloc(sizeof(*np));
+ if (np == NULL || (np->name = dup_str(name)) == NULL)
+ return NULL;
+ hashval = hash_string(name);
+ np->next = type ? link_sources[hashval] : link_targets[hashval];
+ (type ? link_sources : link_targets)[hashval] = np;
+ if ((np->defn = link_dup(defn)) == NULL)
+ return NULL;
+ return np;
+}
+
+#ifndef KPATHSEA
+char *
+dup_str(char *w) /* make a duplicate of s */
+{
+ char *p;
+ p = (char *)malloc(strlen(w)+1);
+ if (p != NULL)
+ strcpy(p,w);
+ return p;
+}
+#endif
+
+static Hps_link *
+link_dup(Hps_link *s) /* make a duplicate link */
+{
+ Hps_link *p;
+
+ p = (Hps_link *) malloc(sizeof(*p));
+ if (p != NULL)
+ p = s;
+ return p;
+}
+
+static double
+dvi_to_hps_conv(int i, int dir)
+{
+ double hps_coor;
+ /* Convert dvi integers into proper hps coordinates
+ Take into account magnification and resolution that dvi file was
+ produced at */
+ hps_coor = dir ? (((i * 72.0) / vactualdpi) +MARGIN) : (PAGESIZE - ((i * 72.0) / (vactualdpi)) - MARGIN );
+ return(hps_coor);
+}
+
+static int
+vert_loc(int i)
+{
+ int return_value;
+ return_value = (int) (i + (PAGESIZE / 4) + FUDGE);
+ if ( return_value > PAGESIZE) {
+ return((int)PAGESIZE);
+ } else if (return_value < (PAGESIZE / 4.0)) {
+ return((PAGESIZE / 4));
+ } else return(return_value);
+}
+
+static Hps_link *
+dest_link(char *s)
+{
+ /* Assume for now that only one entry with same NAME, i.e.
+ Should be true for all legitimate papers.
+ Also, assume prepending of # for names. */
+
+ struct nlist *np;
+
+ s++; /* get rid of hashmark */
+ for(np = link_targets[hash_string(s)]; np != NULL; np = np -> next) {
+ if ( href_name_match(s, np->name)) {
+ return (np->defn); /* found */
+ }
+ }
+ error("Oh no, link not found in target hashtable");
+ error(s);
+ error("!");
+ return NULL; /* not found */
+}
+
+static int
+count_targets(void) {
+ int count=0;
+ int i;
+ struct nlist *np;
+
+ for (i = 0; i < HASHSIZE; i++)
+ for(np = link_targets[i]; np != NULL; np = np -> next)
+ count++;
+ return count;
+}
+
+static void
+do_targets(void) {
+
+ struct nlist *np;
+ int i;
+ Hps_link *dest;
+
+ for (i = 0; i < HASHSIZE; i++)
+ for(np = link_sources[i]; np != NULL; np = np -> next) {
+ if (np->name[0] == '#') {
+ dest = dest_link(np->name);
+ np->defn->page = dest->srcpg;
+ np->defn->vert_dest = vert_loc((int) dest->rect.lly);
+ }
+ }
+}
+
+static void
+do_target_dict(void)
+{
+ struct nlist *np;
+ int i;
+ (void) fprintf(bitfile, "HPSdict begin\n");
+ fprintf(bitfile, "/TargetAnchors\n");
+ fprintf(bitfile, "%i dict dup begin\n",count_targets());
+
+ for (i = 0; i < HASHSIZE; i++)
+ for(np = link_targets[i]; np != NULL; np = np -> next)
+ fprintf(bitfile, "(%s) [%i [%.0f %.0f %.0f %.0f] %i] def\n",
+ np->defn->title, np->defn->srcpg,
+ np->defn->rect.llx, np->defn->rect.lly,
+ np->defn->rect.urx, np->defn->rect.ury,
+ vert_loc((int) np->defn->rect.lly));
+ fprintf(bitfile,"end targetdump-hook def end\n");
+}
+
+static int
+href_name_match(char *h, char *n)
+{
+ int count = 0;
+ int name_length = strlen(n);
+ while((*h == *n) & (*h != '\0') ) {
+ count++;
+ h++;
+ n++;
+ }
+ if (name_length == count) {
+ return 1;
+ } else {
+ /* printf(" count: %i \n", count); */
+ return 0;
+ }
+}
+
+static void
+stamp_hps(Hps_link *pl)
+{
+ char *tmpbuf;
+ unsigned tmpsize;
+
+ if (pl == NULL) {
+ error("stamp_hps: null pl pointer, oh no!");
+ return;
+ }
+ if (pl->title == NULL) {
+ error("stamp_hps: null pl->title pointer, oh no!");
+ return;
+ }
+
+ tmpsize = strlen(pl->title) + 500;
+ tmpbuf = xmalloc(tmpsize);
+
+ /* print out the proper pdfm with local page info only
+ * target info will be in the target dictionary */
+ snprintf(tmpbuf, tmpsize,
+ " (%s) [[%.0f %.0f %.0f %.0f] [%i %i %i [%i %i]] [%.0f %.0f %.0f]] pdfm ",
+ pl->title, pl->rect.llx, pl->rect.lly, pl->rect.urx, pl->rect.ury,
+ pl->border[0], pl->border[1], pl->border[2], pl->border[3],pl->border[4],
+ pl->color[0], pl->color[1], pl->color[2]);
+ cmdout(tmpbuf);
+ free(tmpbuf);
+
+
+}
+
+/* For external URL's, we just pass them through as a string. The hyperps
+ * interpreter can then do what is wants with them.
+ */
+static void
+stamp_external(char *s, Hps_link *pl)
+{
+ char *tmpbuf;
+ unsigned tmpsize;
+ if (pl == NULL) {
+ error("stamp_external: null pl pointer, oh no!");
+ return;
+ }
+ if (s == NULL) {
+ error("stamp_external: null s pointer, oh no!");
+ return;
+ }
+
+ tmpsize = strlen(s) + 500;
+ tmpbuf = xmalloc(tmpsize);
+
+ /* print out the proper pdfm with local page info only
+ * target info will be in the target dictionary */
+ snprintf(tmpbuf, tmpsize,
+ " [[%.0f %.0f %.0f %.0f] [%i %i %i [%i %i]] [%.0f %.0f %.0f]] (%s) pdfm ",
+ pl->rect.llx, pl->rect.lly, pl->rect.urx, pl->rect.ury,
+ pl->border[0], pl->border[1], pl->border[2], pl->border[3],pl->border[4],
+ pl->color[0], pl->color[1], pl->color[2], s);
+ cmdout(tmpbuf);
+ free(tmpbuf);
+}
+
+void
+finish_hps(void) {
+ fclose(bitfile);
+ set_bitfile("head.tmp",1);
+ do_targets();
+ do_target_dict();
+ fprintf(bitfile, "TeXDict begin\n");
+ fprintf(bitfile, "%%%%EndSetup\n");
+ fclose(bitfile);
+ open_output();
+ noprocset = 1;
+ removecomments = 0;
+ copyfile("head.tmp");
+ copyfile("body.tmp");
+ if (dvips_debug_flag == 0 && debug_flag == 0) {
+ unlink("head.tmp");
+ unlink("body.tmp");
+ }
+}
+
+void
+set_bitfile(const char *s, int mode)
+{
+if ((bitfile=fopen(s, mode ? FOPEN_ABIN_MODE : FOPEN_WBIN_MODE))==NULL) {
+ error(s);
+ error("!couldn't open file");
+ }
+ linepos = 0;
+}
+
+void
+vertical_in_hps(void) {
+ Rect_list *rl;
+ /*printf("in vertical_in_hps"); */
+ if (current_type == NAME) return; /* Handle this case later */
+ if (!current_rect_list) {
+ current_rect_list = (Rect_list *)malloc(sizeof(Rect_list));
+ current_rect_list->next = NULL;
+ }
+ else {
+ rl = (Rect_list *)malloc(sizeof(Rect_list));
+ rl->next = current_rect_list;
+ current_rect_list = rl;
+ }
+ current_rect_list->rect.llx = dvi_to_hps_conv(hh, HORIZONTAL);
+ current_rect_list->rect.lly = dvi_to_hps_conv(vv, VERTICAL)-FUDGE;
+ current_rect_list->rect.urx = dvi_to_hps_conv(hhmem, HORIZONTAL);
+ current_rect_list->rect.ury = dvi_to_hps_conv(vvmem, VERTICAL)-FUDGE;
+
+ if (POPPED) start_new_box();
+}
+
+static void
+print_rect_list(void) {
+ Rect_list *rl, *rln;
+
+ for(rl = current_rect_list; rl != NULL; rl = rln) {
+ /* printf("Rectangle is %.0f, %.0f, %.0f, %.0f\n", rl->rect.llx, rl->rect.lly,
+ rl->rect.urx, rl->rect.ury); */
+ rln = rl -> next;
+ free(rl);
+ }
+}
+
+void
+end_current_box(void) {
+ Hps_link *nl;
+
+ POPPED = TRUE;
+ HREF_COUNT--;
+ if (current_type == HREF && current_name[0] != '#') {
+ if ((nl = lookup_link(current_name, current_type)->defn)) {
+ nl->rect.urx = dvi_to_hps_conv(hhmem, HORIZONTAL);
+ nl->rect.ury = dvi_to_hps_conv(vvmem, VERTICAL)-FUDGE+12.0;
+ stamp_external(current_name,nl); /* Broken lines ? */
+ } else {
+ error("!Null lookup");
+ }
+ } else {
+ if ((nl = lookup_link(current_name, current_type)->defn)) {
+ nl->rect.urx = dvi_to_hps_conv(hhmem, HORIZONTAL);
+ nl->rect.ury = dvi_to_hps_conv(vvmem, VERTICAL)-FUDGE+12.0;
+ if (current_type) {
+ stamp_hps(nl); /* Put link info right where special is */
+ }
+ } else {
+ error("!Null lookup");
+ }
+ /* printf("Ended box %.0f, %.0f, %.0f, %.0f\n", nl->rect.llx, \
+ nl->rect.lly,nl->rect.urx, nl->rect.ury); */
+ }
+}
+
+void
+start_new_box(void) {
+ POPPED = FALSE;
+ do_link(current_name, current_type);
+}
+#else
+int no_hypertex; /* prevent an empty file */
+#endif