Back to index

tetex-bin  3.0
hps.c
Go to the documentation of this file.
00001 /* This is the main file for hacking dvips to do HyperPostScript
00002  * Written by Mark D. Doyle 11/94. It is (C) Copyright 1994 by Mark D. Doyle
00003  * and the University of California. You may modify and use this program to
00004  * your heart's content, so long as you send modifications to Mark Doyle and
00005  * abide by the rest of the dvips copyrights. 
00006  */
00007 #include "dvips.h"
00008 #ifdef HPS
00009 #include <stdlib.h>
00010 #ifdef KPATHSEA
00011 #include <kpathsea/c-ctype.h>
00012 #else
00013 #define TOLOWER Tolower
00014 #endif
00015 #ifndef FALSE
00016 #define FALSE 0
00017 #endif
00018 #ifndef TRUE
00019 #define TRUE 1
00020 #endif
00021 #ifndef Tolower
00022 #define Tolower tolower
00023 #endif
00024 #define NAME 0
00025 #define HREF 1
00026 #define skip_space(s) for( ; *s == ' ' ; s++) ;
00027 
00028 Boolean inHTMLregion = 0 ;
00029 Boolean NO_ERROR = 1 ;
00030 Boolean HPS_ERROR = 0 ;
00031 integer HREF_COUNT ;  
00032 Boolean ISHREF = 0 ;
00033 Boolean POPPED = 0 ;
00034 Boolean PUSHED = 0 ;
00035 
00036 char *current_name ;
00037 int current_type ;
00038 int current_pushcount ;
00039 extern integer pushcount ;
00040 extern shalfword linepos ;
00041 
00042 
00043 #define GoTo 0
00044 #define GoToR 1
00045 #define Launch 2
00046 
00047 typedef struct rectangle {
00048   double llx ; /* lower left x coor */
00049   double lly ; /* lower left y coor */
00050   double urx ; /* upper right x coor */
00051   double ury ; /* upper right y coor */
00052   } dvipsRectangle ; 
00053 
00054 typedef struct hps_link {
00055   int action ; /* GoTo, GoToR, or Launch */
00056   char *file ;   /* PDF-style system-independent filename - unused now */
00057   dvipsRectangle rect ;  /* rectangle for location of link */
00058   int border[5] ; /* Border info --- with dashes*/
00059   int srcpg ; /* Page of location */
00060   int page ;  /* Page of destination --- left out is same as srcpg */
00061   int vert_dest ; /* Vertical position of destination on page */
00062   double color[3] ; /* color: length of array gives colorspace (3 <=> RGB)*/
00063   char *title ; /* Title of link */
00064   } Hps_link ;
00065 
00066 struct nlist { /* hashtable entry */
00067   struct nlist *next ; /* next entry in chain */
00068   char *name ; /* defined name */
00069   Hps_link *defn ; /* Link associated with name */
00070   } ;
00071 
00072 typedef struct rect_list { /* linked list of rectangles */
00073   struct rect_list *next ; /* next rectangle in the chain */
00074   dvipsRectangle rect ;
00075   } Rect_list ;
00076 
00077 Rect_list *current_rect_list ;
00078 
00079 #define HASHSIZE 1223 
00080 static struct nlist *link_targets[HASHSIZE] ; /* names .... */
00081 static struct nlist *link_sources[HASHSIZE] ; /* hrefs .... */
00082 
00083 #ifdef KPATHSEA
00084 #define dup_str xstrdup
00085 #else
00086 char *dup_str() ; /* duplicate a string */
00087 #endif
00088 
00089 #include "protos.h"
00090 
00091 extern Boolean removecomments ;
00092 Boolean noprocset ; /* Leave out BeginProc and EndProc comments */
00093 extern int vactualdpi ; 
00094 extern int pagecounter ;
00095 extern integer hhmem, vvmem ;
00096 extern integer vpapersize ;
00097 /* This was hardcoded to letter size.  The denominator converts scaled
00098    points to big points (65536*72.27/72). */
00099 #undef PAGESIZE /* HP-UX 10 defines for itself.  */
00100 #define PAGESIZE ((int) (vpapersize/65781.76))
00101 #define MARGIN 72
00102 #define VERTICAL 0
00103 #define HORIZONTAL 1
00104 #define FUDGE 2.0
00105 
00106 /* For later use 
00107 * static char *dest_key[9] = {"Fit", "FitB", "FitW", "FitH", "FitBH"
00108                "FitR", "FitV", "FitBV", "XYZ"} ; 
00109 */
00110 
00111 extern FILE *bitfile  ; 
00112 extern char *oname  ; 
00113 
00114 extern integer pagenum ;
00115 extern integer hh ;
00116 extern integer vv ;
00117 extern integer hoff, voff ;
00118 
00119 char *hs = NULL ; /* html string to be handled */
00120 char *url_name = NULL ; /* url between double quotes */
00121 
00122 /* parse anchor into link */
00123 void do_html P1C(char *, s)
00124 {
00125   Hps_link *nl ;
00126   url_name = (char *)malloc(strlen(s)+1) ;
00127   hs = s ;
00128   HREF_COUNT = 0 ; 
00129   skip_space(hs) ; /* skip spaces */
00130   if ( TOLOWER(*hs) == 'a') { /* valid start */
00131     POPPED = FALSE ;
00132     if (inHTMLregion) {
00133       error("previous html not closed with /A");
00134       return;
00135     } else {
00136       inHTMLregion = TRUE ;
00137       current_rect_list = NULL ;
00138     }
00139     hs++ ;
00140     skip_space(hs) ;
00141     while(*hs != '\0') {
00142       /* parse for names and href */
00143       if (!href_or_name()) { 
00144        error("Bad HMTL:") ;
00145        error(s) ;
00146        error("!") ;
00147        break ;
00148       }
00149       skip_space(hs) ;
00150     }
00151   } else if ( (*hs == '/') && (TOLOWER(hs[1]) == 'a') ) {
00152     if (!inHTMLregion) {
00153       error("In html, /A found without previous A") ;
00154       return;
00155     } else {
00156       inHTMLregion = FALSE ;
00157     }
00158        if (current_type == HREF && current_name[0] != '#') {
00159         if ((nl = lookup_link(current_name, current_type)->defn)) { 
00160           nl->rect.urx = dvi_to_hps_conv(hh + hoff,HORIZONTAL) ;
00161           nl->rect.ury = dvi_to_hps_conv(vv + voff, VERTICAL)-FUDGE+12.0 ; 
00162           stamp_external(current_name,nl); /* Broken lines ? */
00163         } else {
00164           error("!Null lookup");
00165         }
00166        } else {
00167         if ((nl = lookup_link(current_name, current_type)->defn)) { 
00168           nl->rect.urx = dvi_to_hps_conv(hh + hoff,HORIZONTAL) ;
00169           nl->rect.ury = dvi_to_hps_conv(vv + voff, VERTICAL)-FUDGE+12.0 ; 
00170           if (current_type) {
00171             stamp_hps(nl) ; /* Put link info right where special is */
00172             print_rect_list() ; /* print out rectangles */
00173           }
00174         } else {
00175                     error("!Null lookup");
00176         }
00177        } 
00178   }
00179   else {
00180     error( "No A in html special") ;
00181     error(s) ;
00182     /*error("!") ;*/
00183   }
00184   
00185   return ;
00186 }
00187 
00188 int href_or_name P1H(void) {
00189   if ((strncmp(hs, "href", 4) == 0) || (strncmp(hs, "HREF", 4) == 0)) {
00190     ISHREF = TRUE ;
00191   } else if ((strncmp(hs, "name", 4) == 0) 
00192             || (strncmp(hs, "NAME", 4) == 0)) {
00193     ISHREF = FALSE ; 
00194   } else {
00195     error("Not valid href or name html reference") ;
00196     return(HPS_ERROR) ;
00197           }
00198   if(!parseref()) return(HPS_ERROR) ;
00199   if (url_name) {
00200     if( ISHREF ) {
00201       do_link(url_name, HREF) ;
00202     } else do_link(url_name, NAME) ;
00203   } else {
00204     error("No string in qoutes ") ;
00205     return(HPS_ERROR) ;
00206   }
00207   return(NO_ERROR) ;
00208 }
00209 
00210 int parseref P1H(void) {
00211   int i = 0 ;
00212   for(i=0 ; i++ < 4 ; hs++) ; /* skip href or name in html string */
00213   skip_space(hs) ;
00214   if (*hs == '=' ) {
00215     hs++ ;
00216   } else {
00217     error("No equal sign") ;
00218     return(HPS_ERROR) ;
00219   }
00220   if(!get_string()) return(HPS_ERROR) ;
00221   return(NO_ERROR) ; /* extract stuff between double quotes */
00222 }
00223         
00224 int get_string P1H(void) {
00225   char *v = url_name ; 
00226   
00227   skip_space(hs) ;
00228   /* hash_name() ; */
00229   if (*hs == '"') {
00230     for(hs++ ; *hs != '"' && *hs != '\0' ; *v++ = *hs++) ;  /* need to esc " */
00231     if(*hs == '"') {
00232       hs++ ;
00233       *v++ = '\0' ;
00234       return(NO_ERROR) ;
00235     } else {
00236       error("Improper href. Missing closing double quote") ;
00237       return(HPS_ERROR) ;
00238     }
00239   } else {
00240     error("Improper href. Missing opening double quote") ;
00241     return(HPS_ERROR) ;
00242   }
00243 }
00244 
00245 int do_link P2C(char *, s, int, type)
00246 {
00247 
00248   Hps_link *p ;
00249   
00250   if (HREF_COUNT++ > 0) {
00251     error("!HTML string contains more than one href") ;
00252     return(HPS_ERROR) ;
00253   }
00254   p = (Hps_link *)malloc(sizeof(*p)) ;
00255   p->action = GoTo ;
00256   p->title = (char *)malloc(strlen(s)+1) ;
00257   p->title = s ;
00258   p->srcpg = pagecounter ;
00259   p->rect.llx = dvi_to_hps_conv(hh + hoff,HORIZONTAL) ; 
00260   p->rect.lly = dvi_to_hps_conv(vv + voff,VERTICAL)-FUDGE ;
00261   p->rect.urx = -1.0 ;
00262   p->rect.ury = -1.0 ;
00263   p->vert_dest = -1 ; 
00264   p->page = -1 ;
00265   p->color[0] = 0 ;
00266   p->color[1] = 0 ; /* Blue links */
00267   p->color[2] = 1 ;
00268   p->border[0] = 1 ; /* horizontal corner radius */
00269   p->border[1] = 1 ; /* vertical corner radius */
00270   p->border[2] = 1 ; /* box line width */
00271   p->border[3] = 3 ; /* dash on size */
00272   p->border[4] = 3 ;  /* dash off size */
00273 
00274   current_name = (char *)malloc(strlen(s)+1) ; 
00275   current_name = s ; 
00276   current_type = type ;
00277   current_pushcount = pushcount ;
00278   install_link(s, p, type) ;
00279   return(NO_ERROR) ;
00280 }
00281                  
00282 unsigned int hash_string P1C(char *, s) 
00283 {
00284   unsigned hashval ;
00285   for (hashval = 0 ; *s != '\0' ; s++)
00286     hashval = *s + 31 * hashval ;
00287   return hashval % HASHSIZE ;
00288 }
00289 
00290 /* lookup a hashed name */ 
00291 
00292 struct nlist *lookup_link P2C(char *, s, int, type)
00293 {
00294   struct nlist *np ;
00295   
00296   for(np = type ? link_sources[hash_string(s)] : link_targets[hash_string(s)] ;
00297         np != NULL ; np = np -> next)
00298       if (strcmp(s, np->name) == 0)
00299       return np ; /* found */
00300   return NULL ; /* not found */
00301 }
00302 
00303 struct nlist *install_link P3C(char *, name, Hps_link *, defn, int, type)
00304 {
00305   struct nlist *np ;
00306   unsigned hashval ;
00307     np = (struct nlist *)malloc(sizeof(*np)) ;
00308     if (np == NULL || (np->name = dup_str(name)) == NULL)
00309       return NULL ;
00310     hashval = hash_string(name) ;
00311     np->next = type ? link_sources[hashval] : link_targets[hashval] ;
00312     (type ? link_sources : link_targets)[hashval] = np ;
00313     if ((np->defn = link_dup(defn)) == NULL)
00314       return NULL ; 
00315   return np ;
00316 }
00317 
00318 #ifndef KPATHSEA
00319 char *dup_str P1C(char *, w) /* make a duplicate of s */
00320 {
00321   char *p ;
00322   p = (char *)malloc(strlen(w)+1) ;
00323   if (p != NULL)
00324     strcpy(p,w) ;
00325   return p ;
00326 }
00327 #endif
00328 
00329 Hps_link *link_dup P1C(Hps_link *, s) /* make a duplicate link */
00330 {
00331   Hps_link *p ;
00332   
00333   p = (Hps_link *) malloc(sizeof(*p)) ;
00334   if (p != NULL)
00335     p = s ;
00336   return p ;
00337 }
00338 
00339 double dvi_to_hps_conv P2C(int, i, int, dir)
00340 {
00341   double hps_coor ;
00342   /* Convert dvi integers into proper hps coordinates
00343      Take into account magnification and resolution that dvi file was
00344      produced at */ 
00345   hps_coor = dir ? (((i * 72.0) / vactualdpi) +MARGIN) : (PAGESIZE - ((i * 72.0) / (vactualdpi)) - MARGIN  ) ;
00346   return(hps_coor) ;
00347 }
00348 
00349 int vert_loc P1C(int, i)
00350 {
00351   int return_value ;
00352   return_value = (int) (i + (PAGESIZE / 4) + FUDGE) ; 
00353   if ( return_value > PAGESIZE) {
00354     return((int)PAGESIZE) ;
00355     } else if (return_value <  (PAGESIZE / 4.0)) {
00356         return((PAGESIZE / 4)) ;
00357         } else return(return_value) ;
00358 }
00359 
00360 Hps_link *dest_link P1C(char *, s)
00361 {
00362   /* Assume for now that only one entry with same NAME, i.e.
00363      Should be true for all legitimate papers.
00364      Also, assume prepending of # for names. */
00365   
00366   struct nlist *np ;
00367   
00368   s++ ; /* get rid of hashmark */
00369   for(np = link_targets[hash_string(s)] ; np != NULL ; np = np -> next) {
00370      if ( href_name_match(s, np->name)) {
00371       return (np->defn) ; /* found */
00372       }
00373       }
00374   error("Oh no, link not found in target hashtable") ;
00375   error(s) ;
00376   error("!") ;
00377   return NULL ; /* not found */
00378 }
00379 
00380 int count_targets P1H(void) {
00381   int count=0 ;
00382   int i ;
00383   struct nlist *np ;
00384   
00385   for (i = 0 ; i < HASHSIZE ; i++) 
00386     for(np = link_targets[i]  ; np != NULL ; np = np -> next) 
00387       count++ ; 
00388   return count ;      
00389 }
00390 
00391 void do_targets P1H(void) {
00392 
00393   struct nlist *np ;
00394   int i ;
00395   Hps_link *dest ;
00396   
00397   for (i = 0 ; i < HASHSIZE ; i++) 
00398     for(np = link_sources[i]  ; np != NULL ; np = np -> next) {
00399       if (np->name[0] == '#') { 
00400        dest = dest_link(np->name) ;
00401        np->defn->page = dest->srcpg ;
00402        np->defn->vert_dest = vert_loc((int) dest->rect.lly) ;
00403       } 
00404     }
00405 }
00406 
00407 void do_target_dict P1H(void)
00408 {
00409   struct nlist *np ;
00410   int i ;
00411   (void) fprintf(bitfile, "HPSdict begin\n") ;
00412   (void)fprintf(bitfile, "/TargetAnchors\n") ;
00413   (void)fprintf(bitfile, "%i dict dup begin\n",count_targets()) ;
00414   
00415   for (i = 0 ; i < HASHSIZE ; i++) 
00416     for(np = link_targets[i]  ; np != NULL ; np = np -> next) 
00417       (void)fprintf(bitfile, "(%s) [%i [%.0f %.0f %.0f %.0f] %i] def\n",
00418                   np->defn->title, np->defn->srcpg, 
00419                   np->defn->rect.llx, np->defn->rect.lly,
00420                   np->defn->rect.urx, np->defn->rect.ury,
00421                   vert_loc((int) np->defn->rect.lly)) ;  
00422   (void)fprintf(bitfile,"end targetdump-hook def end\n") ;
00423 }
00424 
00425 int href_name_match P2C(char *, h, char *, n)
00426 {
00427   int count = 0 ;
00428   int name_length = strlen(n) ;
00429   while((*h == *n) & (*h != '\0') )  {
00430     count++ ;
00431     h++ ;
00432     n++ ;
00433     }
00434   if (name_length == count) {
00435     return 1 ;
00436     } else {
00437      /* printf(" count: %i \n", count) ; */
00438     return 0 ;
00439     }
00440 }
00441 
00442 void stamp_hps P1C(Hps_link *, pl)
00443 {
00444   char tmpbuf[200] ;
00445   if (pl == NULL) {
00446     error("Null pointer, oh no!") ;
00447     return ;
00448   } else {
00449     /* print out the proper pdfm with local page info only 
00450      *  target info will be in the target dictionary */
00451     (void)sprintf(tmpbuf, 
00452                 " (%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,
00453                 pl->border[0], pl->border[1], pl->border[2], pl->border[3],pl->border[4],
00454                 pl->color[0], pl->color[1], pl->color[2]) ;
00455     cmdout(tmpbuf) ; 
00456   }
00457   
00458 }
00459 
00460 /* For external URL's, we just pass them through as a string. The hyperps
00461  * interpreter can then do what is wants with them.
00462  */
00463 void stamp_external P2C(char *, s, Hps_link *, pl) 
00464 {
00465   char tmpbuf[200];
00466   if (pl == NULL) {
00467     error("Null pointer, oh no!") ;
00468     return ;
00469   } else {
00470     /* print out the proper pdfm with local page info only 
00471      *  target info will be in the target dictionary */
00472     (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,
00473                 pl->border[0], pl->border[1], pl->border[2], pl->border[3],pl->border[4],
00474                 pl->color[0], pl->color[1], pl->color[2], s) ;
00475     cmdout(tmpbuf) ;
00476   }
00477 }
00478 
00479 void finish_hps P1H(void) {
00480   fclose(bitfile) ;
00481   set_bitfile("head.tmp",1);
00482   do_targets() ;
00483   do_target_dict();
00484   (void)fprintf(bitfile, "TeXDict begin\n") ;
00485   (void)fprintf(bitfile, "%%%%EndSetup\n") ;
00486   fclose(bitfile) ;
00487   open_output() ;
00488   noprocset = 1 ;
00489   removecomments = 0;
00490   copyfile("head.tmp") ;
00491   copyfile("body.tmp") ;
00492 }
00493 
00494 void set_bitfile P2C(char *, s, int, mode)
00495 {  
00496 if ((bitfile=fopen(s, mode ? FOPEN_ABIN_MODE : FOPEN_WBIN_MODE))==NULL) {
00497    error(s) ;
00498    error("!couldn't open file") ;
00499   }
00500   linepos = 0 ;
00501 }
00502 
00503 void vertical_in_hps P1H(void) { 
00504   Rect_list *rl ;
00505   /*printf("in vertical_in_hps") ; */
00506   if (current_type == NAME) return; /* Handle this case later */
00507   if (!current_rect_list) {
00508     current_rect_list = (Rect_list *)malloc(sizeof(Rect_list)) ;
00509     current_rect_list->next = NULL ;
00510   }
00511   else {
00512     rl = (Rect_list *)malloc(sizeof(Rect_list)) ;
00513     rl->next = current_rect_list ;
00514     current_rect_list = rl ;
00515   }
00516   current_rect_list->rect.llx = dvi_to_hps_conv(hh + hoff,HORIZONTAL) ; 
00517   current_rect_list->rect.lly = dvi_to_hps_conv(vv + voff,VERTICAL)-FUDGE ;
00518   current_rect_list->rect.urx = dvi_to_hps_conv(hhmem, HORIZONTAL) ;
00519   current_rect_list->rect.ury = dvi_to_hps_conv(vvmem, VERTICAL)-FUDGE ; 
00520   
00521   if (POPPED) start_new_box() ; 
00522 }
00523 
00524 void print_rect_list P1H(void) {
00525   Rect_list *rl, *rln ;
00526   
00527   for(rl = current_rect_list ; rl != NULL ; rl = rln) {
00528     /* printf("Rectangle is %.0f, %.0f, %.0f, %.0f\n", rl->rect.llx, rl->rect.lly, 
00529             rl->rect.urx, rl->rect.ury) ; */
00530     rln = rl -> next ;
00531     free(rl) ;
00532   } 
00533 } 
00534 
00535 void end_current_box P1H(void) { 
00536   Hps_link *nl ;
00537   
00538   POPPED = TRUE ;
00539   HREF_COUNT-- ;
00540   if (current_type == HREF && current_name[0] != '#') {
00541     if ((nl = lookup_link(current_name, current_type)->defn)) { 
00542       nl->rect.urx = dvi_to_hps_conv(hhmem + hoff,HORIZONTAL) ;
00543       nl->rect.ury = dvi_to_hps_conv(vvmem + voff, VERTICAL)-FUDGE+12.0 ; 
00544       stamp_external(current_name,nl); /* Broken lines ? */
00545     } else {
00546       error("!Null lookup");
00547     }
00548   } else {
00549     if ((nl = lookup_link(current_name, current_type)->defn)) { 
00550       nl->rect.urx = dvi_to_hps_conv(hhmem + hoff,HORIZONTAL) ;
00551       nl->rect.ury = dvi_to_hps_conv(vvmem + voff, VERTICAL)-FUDGE+12.0 ; 
00552       if (current_type) {
00553        stamp_hps(nl) ; /* Put link info right where special is */
00554       }
00555     } else {
00556       error("!Null lookup");
00557     }
00558     /* printf("Ended box %.0f, %.0f, %.0f, %.0f\n", nl->rect.llx, \
00559        nl->rect.lly,nl->rect.urx, nl->rect.ury) ; */
00560   }
00561 }
00562 
00563 void start_new_box P1H(void) {
00564   POPPED = FALSE ; 
00565   do_link(current_name, current_type) ;
00566 }
00567 #else
00568 int no_hypertex ; /* prevent an empty file */
00569 #endif