Back to index

tetex-bin  3.0
ppagelist.c
Go to the documentation of this file.
00001 /* ppagelist.c */
00002 
00003 /************************************************************************
00004 
00005   Part of the dvipng distribution
00006 
00007   This program is free software; you can redistribute it and/or modify
00008   it under the terms of the GNU General Public License as published by
00009   the Free Software Foundation; either version 2 of the License, or
00010   (at your option) any later version.
00011 
00012   This program is distributed in the hope that it will be useful, but
00013   WITHOUT ANY WARRANTY; without even the implied warranty of
00014   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015   General Public License for more details.
00016 
00017   You should have received a copy of the GNU General Public License
00018   along with this program; if not, write to the Free Software
00019   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
00020   02111-1307, USA.
00021 
00022   Copyright (C) 2002-2005 Jan-Åke Larsson
00023 
00024 ************************************************************************/
00025 
00026 #include "dvipng.h"
00027 
00028 /* Some code at the end of this file is adapted from dvips */
00029 
00030 static int32_t first=PAGE_FIRSTPAGE, last=PAGE_LASTPAGE;
00031 static bool    abspage=false, reverse=false;
00032 bool           no_ppage=true;
00033 
00034 /* dvips' behaviour:
00035  * -pp outputs _all_ pages with the correct numbers,
00036  * -p, -l outputs from the first occurrence of firstpage to the first
00037  * occurrence of lastpage. Using '=' means absolute pagenumbers
00038  */
00039 
00040 void FirstPage(int32_t page, bool data)
00041 {
00042   first=page;
00043   abspage |= data;
00044 }
00045 void LastPage(int32_t page,bool data)
00046 {
00047   last=page;
00048   abspage |= data;
00049 }
00050 void Reverse(bool new)
00051 {
00052   reverse=new;
00053 }
00054 /*-->NextPPage*/
00055 /**********************************************************************/
00056 /****************************  NextPPage  *****************************/
00057 /**********************************************************************/
00058 /* Return the page in turn on our queue */
00059 /* (Implicitly, PAGE_POST is never in the pagelist) */
00060 bool InPageList(int32_t i);
00061 
00062 struct page_list* NextPPage(void* dvi, struct page_list* page)
00063 {
00064   if (! reverse) { /*********** normal order */
00065     if (page == NULL) { /* first call: find first page */ 
00066       if (no_ppage)
00067        return(NULL);
00068       page=FindPage(dvi,first,abspage);
00069     } else              /* later calls: count up, except "last" page */ 
00070       page=(last==page->count[abspage ? 0 : 10]) ? NULL : NextPage(dvi,page);
00071     /* seek for pages in pagelist */ 
00072     while (page!=NULL && ! InPageList(page->count[0]))
00073       page=(last==page->count[abspage ? 0 : 10]) ? NULL : NextPage(dvi,page);
00074   } else { /******************** reverse order */
00075     if (page == NULL) { /* first call: find "last" page */ 
00076       if (no_ppage)
00077        return(NULL);
00078       page=FindPage(dvi,last,abspage);
00079     } else              /* later calls: count down, except "first" page */
00080       page=(first==page->count[abspage ? 0 : 10]) ? NULL : PrevPage(dvi,page);
00081     /* seek for pages in pagelist */ 
00082     while (page!=NULL && ! InPageList(page->count[0])) 
00083       page=(first==page->count[abspage ? 0 : 10]) ? NULL : PrevPage(dvi,page);
00084   }
00085   return(page);
00086 }
00087 
00088 struct pp_list {
00089     struct pp_list *next;   /* next in a series of alternates */
00090     int32_t ps_low, ps_high;       /* allowed range */
00091 } *ppages = 0;       /* the list of allowed pages */
00092 
00093 /*-->InPageList*/
00094 /**********************************************************************/
00095 /******************************  InPageList  **************************/
00096 /**********************************************************************/
00097 /* Return true iff i is one of the desired output pages */
00098 
00099 bool InPageList(int32_t i)
00100 {
00101   register struct pp_list *pl = ppages;
00102 
00103   while (pl) {
00104     if ( i >= pl -> ps_low && i <= pl -> ps_high)
00105       return(true);         /* success */
00106     pl = pl -> next;
00107   }
00108   return(false);
00109 }
00110 
00111 void ListPage(int32_t pslow, int32_t pshigh)
00112 {
00113   register struct pp_list   *pl;
00114 
00115   /* Some added code, we want to reuse the list */
00116   no_ppage=false;
00117   pl = ppages;
00118   while (pl != NULL && pl->ps_low <= pl->ps_high)
00119     pl = pl->next;
00120   if (pl == NULL) {
00121     if ((pl = (struct pp_list *)malloc(sizeof(struct pp_list)))
00122        ==NULL) 
00123       Fatal("cannot allocate memory for page queue");
00124     pl -> next = ppages;
00125     ppages = pl;
00126   }
00127   pl -> ps_low = pslow;
00128   pl -> ps_high = pshigh;
00129 }
00130 
00131 /* Parse a string representing a list of pages.  Return 0 iff ok.  As a
00132    side effect, the page selection(s) is (are) prepended to ppages. */
00133 
00134 bool ParsePages(char *s)
00135 {
00136   char *c;           /* conversion start */
00137   long int ps_low = PAGE_MINPAGE, ps_high = PAGE_MAXPAGE;
00138 
00139   while (*s==' ' || *s=='\t') s++;
00140   while (*s!='\0') {
00141     if (*s=='-' || *s==':') { /* range with no starting value */
00142       ps_low = PAGE_MINPAGE;
00143       c=s+1;
00144       ps_high = strtol(c,&s,10);
00145       if (c==s) ps_high=PAGE_MAXPAGE; /* no number */
00146       while (*s==' ' || *s=='\t') s++;
00147       if (*s=='-' || *s==':') { /* Oh, range with negative starting value */
00148        ps_low = -ps_high;
00149        c=s+1;
00150        ps_high = strtol(c,&s,10);
00151        if (c==s) ps_high=PAGE_MAXPAGE; /* no number */
00152       }
00153     } else { /* range with starting value, or singleton */
00154       c=s;
00155       ps_low = ps_high = strtol(c,&s,10);
00156       if (c==s) 
00157        return(true);
00158       if (*s=='-' || *s==':') { /* range */
00159        c=s+1;
00160        ps_high = strtol(c,&s,10);
00161        if (c==s) ps_high=PAGE_MAXPAGE; /* no number */
00162       }
00163     }
00164     ListPage(ps_low, ps_high);
00165     while (*s==' ' || *s=='\t' || *s==',') s++;
00166   }
00167   return(false);
00168 }
00169 
00170 /* Addition, we want to be able to clear the pplist */
00171 void ClearPpList(void)
00172 {
00173   register struct pp_list *pl = ppages;
00174 
00175   while (pl) {
00176     ppages=ppages->next;
00177     free(pl);
00178     pl = ppages;
00179   }
00180   first=PAGE_FIRSTPAGE;
00181   last=PAGE_LASTPAGE;
00182   abspage = false;
00183   no_ppage=true;
00184 }
00185