From 55dc43bff4c516a324aba0cb9581f0c1341344bd Mon Sep 17 00:00:00 2001 From: Stefan Kebekus Date: Sun, 11 Jun 2000 07:04:57 +0000 Subject: [PATCH] Implemented Hyperlinks svn path=/trunk/kdegraphics/kdvi/; revision=52871 --- AUTHORS | 31 +++++-- TODO | 13 ++- dvi_init.cpp | 17 ++-- dviwin.cpp | 92 +++++++++++++------ dviwin.h | 26 ++++-- kdvi_multipage.cpp | 16 +++- kdvi_multipage.h | 8 +- special.cpp | 216 ++++++++++++++++----------------------------- version.h | 1 - vf.cpp | 7 +- 10 files changed, 222 insertions(+), 205 deletions(-) delete mode 100644 version.h diff --git a/AUTHORS b/AUTHORS index 3f694c453..0d869c999 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,12 +1,24 @@ -This program, xdvik, was modified by kb@cs.umb.edu from Paul -Vojta's xdvi distribution for common path searching, GNU-style -configuration, etc. Send bug reports to tex-k@cs.umb.edu, not to Paul. -See the README for more info. +The programm KDVI is based on the dvi-previewer xdvik, See below. KDVI +was written by Markku Hihnala with the help of many +collaborators. Later KDVI became a plug-in to KViewShell and Stefan +Kebekus re-implemented parts of the program. The current version of +KDVI shares a substantial amount of code with xdvi, not not very much +with the first versions of KDVI. + +------------------------------------------------------------------------------ + + +AUTHORS OF xdvik +================ + +This program, xdvik, was modified by kb@cs.umb.edu from Paul Vojta's +xdvi distribution for common path searching, GNU-style configuration, +etc. Send bug reports to tex-k@cs.umb.edu, not to Paul. See the +README for more info. Here are the credits for the original xdvi program: - This program is the combined work of many people, including but not -restricted to: +This program is the combined work of many people, including but not restricted to: Eric Cooper, CMU Bob Scheifler, MIT LCS Paal Kvamme, Norwegian Institute of Technology @@ -16,9 +28,10 @@ restricted to: Jeffrey Lee, U of Toronto Donald Richardson, Clarkson Univ. -In addition to the various comp.sources.x archives, current versions of this -program (the original xdvi, not xdvik) can also be obtained via -anonymous ftp from the following location: +In addition to the various comp.sources.x archives, current versions +of this program (the original xdvi, not xdvik) can also be obtained +via anonymous ftp from the following location: + export.lcs.mit.edu [18.30.0.212] file contrib/xdvi.tar.Z To ease the load on expo, you may also check other X archives, for example: gatekeeper.dec.com [16.1.0.2] file pub/X11/contrib/xdvi.shar.Z diff --git a/TODO b/TODO index 3357512f8..1ae0d9819 100644 --- a/TODO +++ b/TODO @@ -3,12 +3,13 @@ ToDo-List for kdvi URGENT +o implement SaveAs + o Fonts should be free when file is reloaded and the fonts are no longer needed o Optionrequester: changes (e.g. PostScript on/off) are not applied until restart of the program. -o Re-Implement PostScript specials, including proper handling of header (="bang") - specials. +o Optionrequester: Hypertext on/off, Warnings on/off o Proper Error handling with throw/catch @@ -18,12 +19,9 @@ o Document the technical specs. o Bugfixing -o psgs should remove tmp-files - -o epsf specials should forward keywords to the postscript file. +o psgs should use and remove tmp-files -o Support for Hyperlatex specials (xxx.lanl.gov, probably the world's largest - collection of dvi-files, uses Hyperlatex for every file!) +o kvieshell should change pageno when clicking on internal hyperlinks HIGHLY DESIRABLE @@ -51,3 +49,4 @@ o Two page view o Support for even more TeX specials o Popup-Window to inform the user when Fonts are generated o Search option +o dynamical storage allocation for hyperlinks (see dviwin.h) diff --git a/dvi_init.cpp b/dvi_init.cpp index f09032869..b3b84b564 100644 --- a/dvi_init.cpp +++ b/dvi_init.cpp @@ -249,7 +249,6 @@ static void process_preamble() magnification = four(dvi_file); dimconv = (((double) numerator * magnification) / ((double) denominator * 1000.)); dimconv = dimconv * (((long) pixels_per_inch)<<16) / 254000; - tpic_conv = pixels_per_inch * magnification / 1000000.0; k = one(dvi_file); Fread(job_id, sizeof(char), (int) k, dvi_file); job_id[k] = '\0'; @@ -393,21 +392,27 @@ Boolean dviWindow::init_dvi_file() PostScriptDirectory = new QVector(total_pages+1); PostScriptDirectory->setAutoDelete(TRUE); PostScriptHeaderString.truncate(0); - for(int i=0; iinsert(i,PostScriptOutPutString); + + PostScriptDirectory->insert(current_page,PostScriptOutPutString); } PostScriptOutPutString = NULL; - + current_page = save_current_page; return True; } diff --git a/dviwin.cpp b/dviwin.cpp index c54d93dbb..f57b8288b 100644 --- a/dviwin.cpp +++ b/dviwin.cpp @@ -15,11 +15,13 @@ #include #include #include +#include #include #include #include #include +#include #include "dviwin.h" #include "optiondialog.h" @@ -38,11 +40,10 @@ struct WindowRec currwin = {(Window) 0, 3, 0, 0, 0, 0, MAXDIM, 0, MAXDIM, 0}; extern struct WindowRec alt; struct drawinf currinf; -int _debug; +//int _debug; char *prog; Display *DISP; -int min_x, max_x, min_y, max_y; -double tpic_conv; +//int min_x, max_x, min_y, max_y; struct font *font_head = NULL; char *dvi_name = NULL; int total_pages; @@ -52,9 +53,6 @@ const char *dvi_oops_msg; /* error message */ double dimconv; int n_files_left; /* for LRU closing of fonts */ jmp_buf dvi_env; /* mechanism to communicate dvi file errors */ -long magnification; - -unsigned int page_w, page_h; long *page_offset; QIntDict tn_table; @@ -68,20 +66,28 @@ Screen *SCRN; int _pixels_per_inch; _Xconst char *_paper; + + +// The following are really used +long magnification; +unsigned int page_w; +unsigned int page_h; +// end of "really used" + extern char * prog; extern char * dvi_name; extern FILE * dvi_file; extern int n_files_left; -extern int min_x; -extern int min_y; -extern int max_x; -extern int max_y; +//extern int min_x; +//extern int min_y; +//extern int max_x; +//extern int max_y; extern unsigned int page_w, page_h; extern int current_page; extern int total_pages; extern Display * DISP; extern Screen * SCRN; -Window mainwin; +Window mainwin; int useAlpha; void draw_page(void); @@ -200,25 +206,25 @@ int dviWindow::makePK() void dviWindow::setFontPath( const char *s ) { - if (!ChangesPossible) - KMessageBox::sorry( this, + if (!ChangesPossible) + KMessageBox::sorry( this, i18n("The change in font path will be effective\n" - "only after you start kdvi again!")); - FontPath = s; + "only after you start kdvi again!")); + FontPath = s; } const char * dviWindow::fontPath() { - return FontPath; + return FontPath; } void dviWindow::setMetafontMode( const char *mfm ) { - if (!ChangesPossible) - KMessageBox::sorry( this, + if (!ChangesPossible) + KMessageBox::sorry( this, i18n("The change in Metafont mode will be effective\n" - "only after you start kdvi again!") ); - MetafontMode = mfm; + "only after you start kdvi again!") ); + MetafontMode = mfm; } const char * dviWindow::metafontMode() @@ -252,7 +258,7 @@ void dviWindow::setResolution( int bdpi ) int dviWindow::resolution() { - return basedpi; + return basedpi; } @@ -302,10 +308,12 @@ void dviWindow::drawPage() return; } + /*@@@ min_x = 0; min_y = 0; max_x = page_w; max_y = page_h; + */ if ( !pixmap ) return; @@ -343,8 +351,10 @@ bool dviWindow::correctDVI() if ( n < 134 ) // Too short for a dvi file return FALSE; f.at( n-4 ); + char test[4]; unsigned char trailer[4] = { 0xdf,0xdf,0xdf,0xdf }; + if ( f.readBlock( test, 4 )<4 || strncmp( test, (char *) trailer, 4 ) ) return FALSE; // We suppose now that the dvi file is complete and OK @@ -374,12 +384,12 @@ void dviWindow::changePageSize() void dviWindow::setFile( const char *fname ) { - if (ChangesPossible){ - initDVI(); - } - filename = fname; - dvi_name = 0; - drawPage(); + if (ChangesPossible){ + initDVI(); + } + filename = fname; + dvi_name = 0; + drawPage(); } @@ -429,10 +439,36 @@ void dviWindow::paintEvent(QPaintEvent *ev) void dviWindow::mousePressEvent ( QMouseEvent * e ) { +#ifdef DEBUG_SPECIAL kdDebug() << "mouse event" << endl; +#endif for(int i=0; ipos())) { - kdDebug() << "hit:" << hyperLinkList[i].linkText << endl; + if (hyperLinkList[i].linkText[0] == '#' ) { +#ifdef DEBUG_SPECIAL + kdDebug() << "hit: local link to " << hyperLinkList[i].linkText << endl; +#endif + QString locallink = hyperLinkList[i].linkText.mid(1); // Drop the '#' at the beginning + for(int j=0; jaddChild(window); + connect(window, SIGNAL(request_goto_page(int, int)), this, SLOT(goto_page(int, int) ) ); readSettings(); } @@ -127,6 +128,15 @@ bool KDVIMultiPage::gotoPage(int page) return true; } +void KDVIMultiPage::goto_page(int page, int y) +{ + window->gotoPage(page+1); + scrollView()->ensureVisible(scrollView()->width()/2, (int)(y/window->zoom()) ); + + emit previewChanged(true); + emit moved_to_page(page); +} + double KDVIMultiPage::setZoom(double zoom) { diff --git a/kdvi_multipage.h b/kdvi_multipage.h index e4698d2bd..134508b4f 100644 --- a/kdvi_multipage.h +++ b/kdvi_multipage.h @@ -84,18 +84,22 @@ public: virtual void reload(); - signals: /// emitted to indicate the number of pages in the file void numberOfPages(int nr); + /// emitted to indicate that KDVIMultiPage has jumped to a different + //page without being asked to by the kviewshell, i.e. because the + //user clicked on a hyperlink. + void moved_to_page(int nr); + protected slots: void doSettings(); void preferencesChanged(); - + void goto_page(int page, int y); private: diff --git a/special.cpp b/special.cpp index 8392a89e9..4d49e8099 100644 --- a/special.cpp +++ b/special.cpp @@ -1,121 +1,42 @@ -#define DEBUG_SPECIAL +// special.cpp +// Methods for dviwin which deal with "\special" commands found in the +// DVI file + +// Copyright 2000, Stefan Kebekus (stefan.kebekus@uni-bayreuth.de). + + +#include #include #include "dviwin.h" #include #include -#include #include "oconfig.h" -extern "C" { -#define HAVE_PROTOTYPES -#include -#include -#include -#include -#include -#include -} - - extern QPainter foreGroundPaint; +extern double xres; -void draw_bbox() +void dviWindow::html_anchor_special(QString cp) { -#ifdef auskommentiert - if (bbox_valid) { - put_border(PXL_H - currwin.base_x, - PXL_V - currwin.base_y - bbox_voffset, - bbox_width, bbox_height); - bbox_valid = False; - } + if (PostScriptOutPutString != NULL) { // only during scanning, not during rendering + cp.truncate(cp.find('"')); +#ifdef DEBUG_SPECIAL + kdDebug() << "HTML-special, anchor " << cp.latin1() << endl; + kdDebug() << "page " << current_page << endl; #endif + + AnchorList_String[numAnchors] = cp; + AnchorList_Page[numAnchors] = current_page; + AnchorList_Vert[numAnchors] = (DVI_V*xres)/(65536*basedpi); // multiply with zoom to get pixel coords + if (numAnchors < MAX_ANCHORS-2) + numAnchors++; + } } -#ifdef auskommentiert -/* If FILENAME starts with a left quote, set *DECOMPRESS to 1 and return - the rest of FILENAME. Otherwise, look up FILENAME along the usual - path for figure files, set *DECOMPRESS to 0, and return the result - (NULL if can't find the file). */ - -static string find_fig_file (char *filename) -{ - char *name; - - name = kpse_find_pict (filename); - if (!name) - kdError() << "Cannot open PS file " << filename << endl; - - return name; -} - - -/* If DECOMPRESS is zero, pass NAME to the drawfile proc. But if - DECOMPRESS is nonzero, open a pipe to it and pass the resulting - output to the drawraw proc (in chunks). */ - -static void draw_file (psprocs psp, char *name) -{ - kDebugInfo(DEBUG, 4300, "draw file %s",name); - psp.drawfile (name); -} - -static void psfig_special(char *cp) -{ - kDebugInfo("PSFig special: %s",cp); - - char *filename; - int raww, rawh; - - if (strncmp(cp, ":[begin]", 8) == 0) { - cp += 8; - bbox_valid = False; - if (sscanf(cp,"%d %d\n", &raww, &rawh) >= 2) { - bbox_valid = True; - bbox_width = pixel_conv(spell_conv(raww)); - bbox_height = pixel_conv(spell_conv(rawh)); - bbox_voffset = 0; - } - if (currwin.win == mane.win) - psp.drawbegin(PXL_H - currwin.base_x, PXL_V - currwin.base_y,cp); - } else - if (strncmp(cp, " plotfile ", 10) == 0) { - cp += 10; - while (isspace(*cp)) cp++; - for (filename = cp; !isspace(*cp); ++cp); - *cp = '\0'; - { - char *name = find_fig_file (filename); - if (name && currwin.win == mane.win) { - draw_file(psp, name); - if (name != filename) - free (name); - } - } - } else - if (strncmp(cp, ":[end]", 6) == 0) { - cp += 6; - if (currwin.win == mane.win) - psp.drawend(cp); - bbox_valid = False; - } else { /* I am going to send some raw postscript stuff */ - if (*cp == ':') - ++cp; /* skip second colon in ps:: */ - if (currwin.win == mane.win) { - /* It's drawbegin that initializes the ps process, so make - sure it's started up. */ - psp.drawbegin(PXL_H - currwin.base_x, PXL_V - currwin.base_y, ""); - psp.drawend(""); - psp.drawraw(cp); - } - } -} -#endif - void dviWindow::html_href_special(QString cp) { cp.truncate(cp.find('"')); @@ -148,13 +69,13 @@ void dviWindow::header_special(QString cp) kdDebug() << "PostScript-special, header " << cp.latin1() << endl; #endif - if (PostScriptOutPutString) { + if (PostScriptOutPutString && QFile::exists(cp)) { PostScriptHeaderString.append( QString(" (%1) run\n").arg(cp) ); } } -static void parse_special_argument(QString strg, char *argument_name, int *variable) +static void parse_special_argument(QString strg, const char *argument_name, int *variable) { bool OK; @@ -174,7 +95,9 @@ static void parse_special_argument(QString strg, char *argument_name, int *varia void dviWindow::epsf_special(QString cp) { +#ifdef DEBUG_SPECIAL kdError() << "epsf-special: psfile=" << cp <append( "@beginspecial @setspecial \n" ); - PostScriptOutPutString->append( QString(" (%1) run\n").arg(filename) ); - PostScriptOutPutString->append( "@endspecial \n" ); + if (QFile::exists(filename)) { + PostScriptOutPutString->append( QString(" %1 %2 moveto\n").arg(DVI_H/65536 - 300).arg(DVI_V/65536 - 520) ); + PostScriptOutPutString->append( "@beginspecial " ); + PostScriptOutPutString->append( QString(" %1 @llx").arg(llx) ); + PostScriptOutPutString->append( QString(" %1 @lly").arg(lly) ); + PostScriptOutPutString->append( QString(" %1 @urx").arg(urx) ); + PostScriptOutPutString->append( QString(" %1 @ury").arg(ury) ); + if (rwi != 0) + PostScriptOutPutString->append( QString(" %1 @rwi").arg(rwi) ); + if (rhi != 0) + PostScriptOutPutString->append( QString(" %1 @rhi").arg(rwi) ); + PostScriptOutPutString->append( " @setspecial \n" ); + PostScriptOutPutString->append( QString(" (%1) run\n").arg(filename) ); + PostScriptOutPutString->append( "@endspecial \n" ); + } } else { - kdDebug() << "_postscript " << _postscript << endl; - if (!_postscript) { - // Don't show PostScript, just draw to bounding box + if (!_postscript || !QFile::exists(filename)) { + // Don't show PostScript, just draw the bounding box + // For this, calculate the size of the bounding box in Pixels + double bbox_width = urx - llx; + double bbox_height = lly - ury; + + if ((rwi != 0)&&(bbox_width != 0)) { + bbox_height = bbox_height*rwi/bbox_width; + bbox_width = rwi; + } + if ((rhi != 0)&&(bbox_height != 0)) { + bbox_height = rhi; + bbox_width = bbox_width*rhi/bbox_height; + } + + bbox_width *= 0.1 * dimconv / shrink_factor; + bbox_height *= 0.1 * dimconv / shrink_factor; + QRect bbox(PXL_H - currwin.base_x, PXL_V - currwin.base_y, (int)bbox_width, (int)bbox_height); - foreGroundPaint.setBrush(Qt::lightGray); - foreGroundPaint.setPen (Qt::black); - foreGroundPaint.drawRoundRect(bbox, 1, 1); - foreGroundPaint.drawText (bbox, (int)(Qt::AlignCenter), filename, -1, &bbox); + if (QFile::exists(filename)) + foreGroundPaint.setBrush(Qt::lightGray); + else + foreGroundPaint.setBrush(Qt::red); + foreGroundPaint.setPen(Qt::black); + foreGroundPaint.drawRoundRect(bbox, 2, 2); + if (QFile::exists(filename)) + foreGroundPaint.drawText (bbox, (int)(Qt::AlignCenter), filename, -1, &bbox); + else + foreGroundPaint.drawText (bbox, (int)(Qt::AlignCenter), + QString("File not found:\n %1").arg(filename), -1, &bbox); } } return; @@ -249,7 +181,7 @@ void dviWindow::epsf_special(QString cp) void dviWindow::bang_special(QString cp) { #ifdef DEBUG_SPECIAL - // kdDebug() << "PostScript-special, literal header " << cp.latin1() << endl; + kdDebug() << "PostScript-special, literal header " << cp.latin1() << endl; #endif if (currwin.win == mane.win && PostScriptOutPutString) { @@ -316,6 +248,12 @@ void dviWindow::applicationDoSpecial(char *cp) return; } + // HTML anchor special + if (special_command.find("html: #include @@ -64,16 +63,18 @@ extern void oops(const char *message, ...); void font::read_VF_index(void) { +#ifdef DEBUG_FONTS kdDebug() << "read_VF_index" << endl; - +#endif FILE *VF_file = file; unsigned char cmnd; unsigned char *avail, *availend; /* available space for macros */ flags |= FONT_VIRTUAL; set_char_p = &dviWindow::set_vf_char; +#ifdef DEBUG_FONTS kdDebug() << "Reading VF pixel file " << filename << endl; - +#endif // Read preamble. Fseek(VF_file, (long) one(VF_file), 1); /* skip comment */ long file_checksum = four(VF_file);