diff options
author | Karl Berry <karl@freefriends.org> | 2006-01-17 21:41:51 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2006-01-17 21:41:51 +0000 |
commit | 487ca4806cc046076293cf6cc5fbba0db282bac7 (patch) | |
tree | 847b412ab5158dd7bdd7ed7e5a4cc3fbca94be32 /Build/source/texk/dvipsk/hps.c | |
parent | a3d3111bfe26b8e5f5bc6049dfb2a4ca2edc7881 (diff) |
texk 1
git-svn-id: svn://tug.org/texlive/trunk@1485 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/dvipsk/hps.c')
-rw-r--r-- | Build/source/texk/dvipsk/hps.c | 569 |
1 files changed, 569 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..320ba41f56b --- /dev/null +++ b/Build/source/texk/dvipsk/hps.c @@ -0,0 +1,569 @@ +/* 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, so long as you send modifications to Mark Doyle and + * abide by the rest of the dvips copyrights. + */ +#include "dvips.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 ; +extern integer pushcount ; +extern shalfword linepos ; + + +#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 + +#include "protos.h" + +extern Boolean removecomments ; +Boolean noprocset ; /* Leave out BeginProc and EndProc comments */ +extern int vactualdpi ; +extern int pagecounter ; +extern integer hhmem, vvmem ; +extern integer vpapersize ; +/* 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"} ; +*/ + +extern FILE *bitfile ; +extern char *oname ; + +extern integer pagenum ; +extern integer hh ; +extern integer vv ; +extern integer hoff, voff ; + +char *hs = NULL ; /* html string to be handled */ +char *url_name = NULL ; /* url between double quotes */ + +/* parse anchor into link */ +void do_html P1C(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 + hoff,HORIZONTAL) ; + nl->rect.ury = dvi_to_hps_conv(vv + voff, 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 + hoff,HORIZONTAL) ; + nl->rect.ury = dvi_to_hps_conv(vv + voff, 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 ; +} + +int href_or_name P1H(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) ; +} + +int parseref P1H(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 */ +} + +int get_string P1H(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) ; + } +} + +int do_link P2C(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 + hoff,HORIZONTAL) ; + p->rect.lly = dvi_to_hps_conv(vv + voff,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) ; +} + +unsigned int hash_string P1C(char *, s) +{ + unsigned hashval ; + for (hashval = 0 ; *s != '\0' ; s++) + hashval = *s + 31 * hashval ; + return hashval % HASHSIZE ; +} + +/* lookup a hashed name */ + +struct nlist *lookup_link P2C(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 */ +} + +struct nlist *install_link P3C(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 P1C(char *, w) /* make a duplicate of s */ +{ + char *p ; + p = (char *)malloc(strlen(w)+1) ; + if (p != NULL) + strcpy(p,w) ; + return p ; +} +#endif + +Hps_link *link_dup P1C(Hps_link *, s) /* make a duplicate link */ +{ + Hps_link *p ; + + p = (Hps_link *) malloc(sizeof(*p)) ; + if (p != NULL) + p = s ; + return p ; +} + +double dvi_to_hps_conv P2C(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) ; +} + +int vert_loc P1C(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) ; +} + +Hps_link *dest_link P1C(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 */ +} + +int count_targets P1H(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 ; +} + +void do_targets P1H(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) ; + } + } +} + +void do_target_dict P1H(void) +{ + struct nlist *np ; + int i ; + (void) fprintf(bitfile, "HPSdict begin\n") ; + (void)fprintf(bitfile, "/TargetAnchors\n") ; + (void)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) + (void)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)) ; + (void)fprintf(bitfile,"end targetdump-hook def end\n") ; +} + +int href_name_match P2C(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 ; + } +} + +void stamp_hps P1C(Hps_link *, pl) +{ + char tmpbuf[200] ; + if (pl == NULL) { + error("Null pointer, oh no!") ; + return ; + } else { + /* print out the proper pdfm with local page info only + * target info will be in the target dictionary */ + (void)sprintf(tmpbuf, + " (%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) ; + } + +} + +/* For external URL's, we just pass them through as a string. The hyperps + * interpreter can then do what is wants with them. + */ +void stamp_external P2C(char *, s, Hps_link *, pl) +{ + char tmpbuf[200]; + if (pl == NULL) { + error("Null pointer, oh no!") ; + return ; + } else { + /* print out the proper pdfm with local page info only + * target info will be in the target dictionary */ + (void)sprintf(tmpbuf," [[%.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) ; + } +} + +void finish_hps P1H(void) { + fclose(bitfile) ; + set_bitfile("head.tmp",1); + do_targets() ; + do_target_dict(); + (void)fprintf(bitfile, "TeXDict begin\n") ; + (void)fprintf(bitfile, "%%%%EndSetup\n") ; + fclose(bitfile) ; + open_output() ; + noprocset = 1 ; + removecomments = 0; + copyfile("head.tmp") ; + copyfile("body.tmp") ; +} + +void set_bitfile P2C(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 P1H(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 + hoff,HORIZONTAL) ; + current_rect_list->rect.lly = dvi_to_hps_conv(vv + voff,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() ; +} + +void print_rect_list P1H(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 P1H(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 + hoff,HORIZONTAL) ; + nl->rect.ury = dvi_to_hps_conv(vvmem + voff, 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 + hoff,HORIZONTAL) ; + nl->rect.ury = dvi_to_hps_conv(vvmem + voff, 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 P1H(void) { + POPPED = FALSE ; + do_link(current_name, current_type) ; +} +#else +int no_hypertex ; /* prevent an empty file */ +#endif |