home *** CD-ROM | disk | FTP | other *** search
/ Aminet 10 / aminetcdnumber101996.iso / Aminet / util / gnu / groff_src.lha / groff-1.10src / xditview / Dvi.c < prev    next >
C/C++ Source or Header  |  1994-04-18  |  15KB  |  545 lines

  1. #ifndef SABER
  2. #ifndef lint
  3. static char Xrcsid[] = "$XConsortium: Dvi.c,v 1.9 89/12/10 16:12:25 rws Exp $";
  4. #endif /* lint */
  5. #endif /* SABER */
  6.  
  7. /*
  8.  * Dvi.c - Dvi display widget
  9.  *
  10.  */
  11.  
  12. #define XtStrlen(s)    ((s) ? strlen(s) : 0)
  13.  
  14.   /* The following are defined for the reader's convenience.  Any
  15.      Xt..Field macro in this code just refers to some field in
  16.      one of the substructures of the WidgetRec.  */
  17.  
  18. #include <X11/IntrinsicP.h>
  19. #include <X11/StringDefs.h>
  20. #include <X11/Xmu/Converters.h>
  21. #include <stdio.h>
  22. #include <ctype.h>
  23. #include "DviP.h"
  24.  
  25. /****************************************************************
  26.  *
  27.  * Full class record constant
  28.  *
  29.  ****************************************************************/
  30.  
  31. /* Private Data */
  32.  
  33. static char default_font_map[] =  "\
  34. TR    -adobe-times-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\
  35. TI    -adobe-times-medium-i-normal--*-100-*-*-*-*-iso8859-1\n\
  36. TB    -adobe-times-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\
  37. TBI    -adobe-times-bold-i-normal--*-100-*-*-*-*-iso8859-1\n\
  38. CR    -adobe-courier-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\
  39. CI    -adobe-courier-medium-o-normal--*-100-*-*-*-*-iso8859-1\n\
  40. CB    -adobe-courier-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\
  41. CBI    -adobe-courier-bold-o-normal--*-100-*-*-*-*-iso8859-1\n\
  42. HR    -adobe-helvetica-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\
  43. HI    -adobe-helvetica-medium-o-normal--*-100-*-*-*-*-iso8859-1\n\
  44. HB    -adobe-helvetica-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\
  45. HBI    -adobe-helvetica-bold-o-normal--*-100-*-*-*-*-iso8859-1\n\
  46. NR    -adobe-new century schoolbook-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\
  47. NI    -adobe-new century schoolbook-medium-i-normal--*-100-*-*-*-*-iso8859-1\n\
  48. NB    -adobe-new century schoolbook-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\
  49. NBI    -adobe-new century schoolbook-bold-i-normal--*-100-*-*-*-*-iso8859-1\n\
  50. S    -adobe-symbol-medium-r-normal--*-100-*-*-*-*-adobe-fontspecific\n\
  51. SS    -adobe-symbol-medium-r-normal--*-100-*-*-*-*-adobe-fontspecific\n\
  52. ";
  53.  
  54. #define offset(field) XtOffset(DviWidget, field)
  55.  
  56. #define MY_WIDTH(dw) ((int)(dw->dvi.paperwidth * dw->dvi.scale_factor + .5))
  57. #define MY_HEIGHT(dw) ((int)(dw->dvi.paperlength * dw->dvi.scale_factor + .5))
  58.  
  59. static XtResource resources[] = { 
  60.     {XtNfontMap, XtCFontMap, XtRString, sizeof (char *),
  61.      offset(dvi.font_map_string), XtRString, default_font_map},
  62.     {XtNforeground, XtCForeground, XtRPixel, sizeof (unsigned long),
  63.      offset(dvi.foreground), XtRString, "XtDefaultForeground"},
  64.     {XtNbackground, XtCBackground, XtRPixel, sizeof (unsigned long),
  65.      offset(dvi.background), XtRString, "XtDefaultBackground"},
  66.     {XtNpageNumber, XtCPageNumber, XtRInt, sizeof (int),
  67.      offset(dvi.requested_page), XtRString, "1"},
  68.     {XtNlastPageNumber, XtCLastPageNumber, XtRInt, sizeof (int),
  69.      offset (dvi.last_page), XtRString, "0"},
  70.     {XtNfile, XtCFile, XtRFile, sizeof (FILE *),
  71.      offset (dvi.file), XtRFile, (char *) 0},
  72.     {XtNseek, XtCSeek, XtRBoolean, sizeof (Boolean),
  73.      offset(dvi.seek), XtRString, "false"},
  74.     {XtNfont, XtCFont, XtRFontStruct, sizeof (XFontStruct *),
  75.      offset(dvi.default_font), XtRString, "xtdefaultfont"},
  76.     {XtNbackingStore, XtCBackingStore, XtRBackingStore, sizeof (int),
  77.      offset(dvi.backing_store), XtRString, "default"},
  78.     {XtNnoPolyText, XtCNoPolyText, XtRBoolean, sizeof (Boolean),
  79.      offset(dvi.noPolyText), XtRString, "false"},
  80.     {XtNresolution, XtCResolution, XtRInt, sizeof(int),
  81.      offset(dvi.default_resolution), XtRString, "75"},
  82. };
  83.  
  84. #undef offset
  85.  
  86. static void        ClassInitialize ();
  87. static void        ClassPartInitialize();
  88. static void        Initialize(), Realize (), Destroy (), Redisplay ();
  89. static Boolean        SetValues (), SetValuesHook ();
  90. static XtGeometryResult    QueryGeometry ();
  91. static void        ShowDvi ();
  92. static void        CloseFile (), OpenFile ();
  93. static void        FindPage ();
  94.  
  95. static void        SaveToFile ();
  96.  
  97. DviClassRec dviClassRec = {
  98. {
  99.     &widgetClassRec,        /* superclass          */    
  100.     "Dvi",                /* class_name          */
  101.     sizeof(DviRec),            /* size              */
  102.     ClassInitialize,        /* class_initialize      */
  103.     ClassPartInitialize,        /* class_part_initialize  */
  104.     FALSE,                /* class_inited          */
  105.     Initialize,            /* initialize          */
  106.     NULL,                /* initialize_hook      */
  107.     Realize,            /* realize          */
  108.     NULL,                /* actions          */
  109.     0,                /* num_actions          */
  110.     resources,            /* resources          */
  111.     XtNumber(resources),        /* resource_count      */
  112.     NULLQUARK,            /* xrm_class          */
  113.     FALSE,                /* compress_motion      */
  114.     TRUE,                /* compress_exposure      */
  115.     TRUE,                /* compress_enterleave    */
  116.     FALSE,                /* visible_interest      */
  117.     Destroy,            /* destroy          */
  118.     NULL,                /* resize          */
  119.     Redisplay,            /* expose          */
  120.     SetValues,            /* set_values          */
  121.     SetValuesHook,            /* set_values_hook      */
  122.     NULL,                /* set_values_almost      */
  123.     NULL,                /* get_values_hook      */
  124.     NULL,                /* accept_focus          */
  125.     XtVersion,            /* version          */
  126.     NULL,                /* callback_private      */
  127.     0,                /* tm_table          */
  128.     QueryGeometry,            /* query_geometry      */
  129.     NULL,                /* display_accelerator      */
  130.     NULL                /* extension          */
  131. },{
  132.     SaveToFile,            /* save    */
  133. },
  134. };
  135.  
  136. WidgetClass dviWidgetClass = (WidgetClass) &dviClassRec;
  137.  
  138. static void ClassInitialize ()
  139. {
  140.     XtAddConverter( XtRString, XtRBackingStore, XmuCvtStringToBackingStore,
  141.             NULL, 0 );
  142. }
  143.  
  144. /****************************************************************
  145.  *
  146.  * Private Procedures
  147.  *
  148.  ****************************************************************/
  149.  
  150. /* ARGSUSED */
  151. static void Initialize(request, new)
  152.     Widget request, new;
  153. {
  154.     DviWidget    dw = (DviWidget) new;
  155.  
  156.     dw->dvi.current_page = 0;
  157.     dw->dvi.font_map = 0;
  158.     dw->dvi.cache.index = 0;
  159.     dw->dvi.text_x_width = 0;
  160.     dw->dvi.text_device_width = 0;
  161.     dw->dvi.word_flag = 0;
  162.     dw->dvi.file = 0;
  163.     dw->dvi.tmpFile = 0;
  164.     dw->dvi.state = 0;
  165.     dw->dvi.readingTmp = 0;
  166.     dw->dvi.cache.char_index = 0;
  167.     dw->dvi.cache.font_size = -1;
  168.     dw->dvi.cache.font_number = -1;
  169.     dw->dvi.cache.adjustable[0] = 0;
  170.     dw->dvi.file_map = 0;
  171.     dw->dvi.fonts = 0;
  172.     dw->dvi.seek = False;
  173.     dw->dvi.device_resolution = dw->dvi.default_resolution;
  174.     dw->dvi.display_resolution = dw->dvi.default_resolution;
  175.     dw->dvi.paperlength = dw->dvi.default_resolution*11;
  176.     dw->dvi.paperwidth = (dw->dvi.default_resolution*8
  177.                   + dw->dvi.default_resolution/2);
  178.     dw->dvi.scale_factor = 1.0;
  179.     dw->dvi.sizescale = 1;
  180.     dw->dvi.line_thickness = -1;
  181.     dw->dvi.line_width = 1;
  182.     dw->dvi.fill = DVI_FILL_MAX;
  183.     dw->dvi.device_font = 0;
  184.     dw->dvi.device_font_number = -1;
  185.     dw->dvi.device = 0;
  186.     dw->dvi.native = 0;
  187. }
  188.  
  189. #include <X11/bitmaps/gray>
  190.  
  191. static void
  192. Realize (w, valueMask, attrs)
  193.     Widget            w;
  194.     XtValueMask        *valueMask;
  195.     XSetWindowAttributes    *attrs;
  196. {
  197.     DviWidget    dw = (DviWidget) w;
  198.     XGCValues    values;
  199.  
  200.     if (dw->dvi.backing_store != Always + WhenMapped + NotUseful) {
  201.         attrs->backing_store = dw->dvi.backing_store;
  202.         *valueMask |= CWBackingStore;
  203.     }
  204.     XtCreateWindow (w, (unsigned)InputOutput, (Visual *) CopyFromParent,
  205.             *valueMask, attrs);
  206.     values.foreground = dw->dvi.foreground;
  207.     values.cap_style = CapRound;
  208.     values.join_style = JoinRound;
  209.     values.line_width = dw->dvi.line_width;
  210.     dw->dvi.normal_GC = XCreateGC (XtDisplay (w), XtWindow (w),
  211.                        GCForeground|GCCapStyle|GCJoinStyle
  212.                        |GCLineWidth,
  213.                        &values);
  214.     dw->dvi.gray = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
  215.                          gray_bits,
  216.                          gray_width, gray_height);
  217.     values.background = dw->dvi.background;
  218.     values.stipple = dw->dvi.gray;
  219.     dw->dvi.fill_GC = XCreateGC (XtDisplay (w), XtWindow (w),
  220.                      GCForeground|GCBackground|GCStipple,
  221.                      &values);
  222.  
  223.     dw->dvi.fill_type = DVI_FILL_BLACK;
  224.  
  225.     if (dw->dvi.file)
  226.         OpenFile (dw);
  227.     ParseFontMap (dw);
  228. }
  229.  
  230. static void
  231. Destroy(w)
  232.     Widget w;
  233. {
  234.     DviWidget    dw = (DviWidget) w;
  235.  
  236.     XFreeGC (XtDisplay (w), dw->dvi.normal_GC);
  237.     XFreeGC (XtDisplay (w), dw->dvi.fill_GC);
  238.     XFreePixmap (XtDisplay (w), dw->dvi.gray);
  239.     DestroyFontMap (dw->dvi.font_map);
  240.     DestroyFileMap (dw->dvi.file_map);
  241.     device_destroy (dw->dvi.device);
  242. }
  243.  
  244. /*
  245.  * Repaint the widget window
  246.  */
  247.  
  248. /* ARGSUSED */
  249. static void
  250. Redisplay(w, event, region)
  251.     Widget w;
  252.     XEvent *event;
  253.     Region region;
  254. {
  255.     DviWidget    dw = (DviWidget) w;
  256.     XRectangle    extents;
  257.     
  258.     XClipBox (region, &extents);
  259.     dw->dvi.extents.x1 = extents.x;
  260.     dw->dvi.extents.y1 = extents.y;
  261.     dw->dvi.extents.x2 = extents.x + extents.width;
  262.     dw->dvi.extents.y2 = extents.y + extents.height;
  263.     ShowDvi (dw);
  264. }
  265.  
  266. /*
  267.  * Set specified arguments into widget
  268.  */
  269. /* ARGSUSED */
  270. static Boolean
  271. SetValues (current, request, new)
  272.     DviWidget current, request, new;
  273. {
  274.     Boolean        redisplay = FALSE;
  275.     char        *new_map;
  276.     int        cur, req;
  277.  
  278.     if (current->dvi.font_map_string != request->dvi.font_map_string) {
  279.         new_map = XtMalloc (strlen (request->dvi.font_map_string) + 1);
  280.         if (new_map) {
  281.             redisplay = TRUE;
  282.             strcpy (new_map, request->dvi.font_map_string);
  283.             new->dvi.font_map_string = new_map;
  284.             if (current->dvi.font_map_string)
  285.                 XtFree (current->dvi.font_map_string);
  286.             current->dvi.font_map_string = 0;
  287.             ParseFontMap (new);
  288.         }
  289.     }
  290.  
  291.     req = request->dvi.requested_page;
  292.     cur = current->dvi.requested_page;
  293.     if (cur != req) {
  294.         if (!request->dvi.file)
  295.             req = 0;
  296.         else {
  297.             if (req < 1)
  298.                 req = 1;
  299.             if (current->dvi.last_page != 0 &&
  300.             req > current->dvi.last_page)
  301.                 req = current->dvi.last_page;
  302.         }
  303.         if (cur != req)
  304.                 redisplay = TRUE;
  305.         new->dvi.requested_page = req;
  306.         if (current->dvi.last_page == 0 && req > cur)
  307.             FindPage (new);
  308.     }
  309.  
  310.     return redisplay;
  311. }
  312.  
  313. /*
  314.  * use the set_values_hook entry to check when
  315.  * the file is set
  316.  */
  317.  
  318. static Boolean
  319. SetValuesHook (dw, args, num_argsp)
  320.     DviWidget    dw;
  321.     ArgList        args;
  322.     Cardinal    *num_argsp;
  323. {
  324.     Cardinal    i;
  325.  
  326.     for (i = 0; i < *num_argsp; i++) {
  327.         if (!strcmp (args[i].name, XtNfile)) {
  328.             CloseFile (dw);
  329.             OpenFile (dw);
  330.             return TRUE;
  331.         }
  332.     }
  333.     return FALSE;
  334. }
  335.  
  336. static void CloseFile (dw)
  337.     DviWidget    dw;
  338. {
  339.     if (dw->dvi.tmpFile)
  340.         fclose (dw->dvi.tmpFile);
  341.     ForgetPagePositions (dw);
  342. }
  343.  
  344. static void OpenFile (dw)
  345.     DviWidget    dw;
  346. {
  347.     char    tmpName[sizeof ("/tmp/dviXXXXXX")];
  348.  
  349.     dw->dvi.tmpFile = 0;
  350.     if (!dw->dvi.seek) {
  351.         strcpy (tmpName, "/tmp/dviXXXXXX");
  352.         mktemp (tmpName);
  353.         dw->dvi.tmpFile = fopen (tmpName, "w+");
  354.         unlink (tmpName);
  355.     }
  356.     dw->dvi.requested_page = 1;
  357.     dw->dvi.last_page = 0;
  358. }
  359.  
  360. static XtGeometryResult
  361. QueryGeometry (w, request, geometry_return)
  362.     Widget            w;
  363.     XtWidgetGeometry    *request, *geometry_return;
  364. {
  365.     XtGeometryResult    ret;
  366.     DviWidget        dw = (DviWidget) w;
  367.  
  368.     ret = XtGeometryYes;
  369.     if (((request->request_mode & CWWidth)
  370.          && request->width < MY_WIDTH(dw))
  371.         || ((request->request_mode & CWHeight)
  372.         && request->height < MY_HEIGHT(dw)))
  373.         ret = XtGeometryAlmost;
  374.     geometry_return->width = MY_WIDTH(dw);
  375.     geometry_return->height = MY_HEIGHT(dw);
  376.     geometry_return->request_mode = CWWidth|CWHeight;
  377.     return ret;
  378. }
  379.  
  380. SetDevice (dw, name)
  381.     DviWidget    dw;
  382.     char         *name;
  383. {
  384.     XtWidgetGeometry    request, reply;
  385.     XtGeometryResult ret;
  386.  
  387.     ForgetFonts (dw);
  388.     dw->dvi.device = device_load (name);
  389.     if (!dw->dvi.device)
  390.         return;
  391.     dw->dvi.sizescale = dw->dvi.device->sizescale;
  392.     dw->dvi.device_resolution = dw->dvi.device->res;
  393.     dw->dvi.native = dw->dvi.device->X11;
  394.     dw->dvi.paperlength = dw->dvi.device->paperlength;
  395.     dw->dvi.paperwidth = dw->dvi.device->paperwidth;
  396.     if (dw->dvi.native) {
  397.         dw->dvi.display_resolution = dw->dvi.device_resolution;
  398.         dw->dvi.scale_factor = 1.0;
  399.     }
  400.     else {
  401.         dw->dvi.display_resolution = dw->dvi.default_resolution;
  402.         dw->dvi.scale_factor = ((double)dw->dvi.display_resolution
  403.                     / dw->dvi.device_resolution);
  404.     }
  405.     request.request_mode = CWWidth|CWHeight;
  406.     request.width = MY_WIDTH(dw);
  407.     request.height = MY_HEIGHT(dw);
  408.     ret = XtMakeGeometryRequest ((Widget)dw, &request, &reply);
  409.     if (ret == XtGeometryAlmost
  410.         && reply.height >= request.height
  411.         && reply.width >= request.width) {
  412.         request.width = reply.width;
  413.         request.height = reply.height;
  414.         XtMakeGeometryRequest ((Widget)dw, &request, &reply);
  415.     }
  416. }
  417.  
  418. static void
  419. ShowDvi (dw)
  420.     DviWidget    dw;
  421. {
  422.     if (!dw->dvi.file) {
  423.         static char Error[] = "No file selected";
  424.  
  425.         XSetFont (XtDisplay(dw), dw->dvi.normal_GC,
  426.               dw->dvi.default_font->fid);
  427.         XDrawString (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
  428.                  20, 20, Error, strlen (Error));
  429.         return;
  430.     }
  431.  
  432.     FindPage (dw);
  433.     
  434.     dw->dvi.display_enable = 1;
  435.     ParseInput (dw);
  436.     if (dw->dvi.last_page && dw->dvi.requested_page > dw->dvi.last_page)
  437.         dw->dvi.requested_page = dw->dvi.last_page;
  438. }
  439.  
  440. static void
  441. FindPage (dw)
  442.     DviWidget    dw;
  443. {
  444.     int    i;
  445.     long    file_position;
  446.  
  447.     if (dw->dvi.requested_page < 1)
  448.         dw->dvi.requested_page = 1;
  449.  
  450.     if (dw->dvi.last_page != 0 && dw->dvi.requested_page > dw->dvi.last_page)
  451.         dw->dvi.requested_page = dw->dvi.last_page;
  452.  
  453.     file_position = SearchPagePosition (dw, dw->dvi.requested_page);
  454.     if (file_position != -1) {
  455.         FileSeek(dw, file_position);
  456.         dw->dvi.current_page = dw->dvi.requested_page;
  457.     } else {
  458.         for (i=dw->dvi.requested_page; i > 0; i--) {
  459.             file_position = SearchPagePosition (dw, i);
  460.             if (file_position != -1)
  461.                 break;
  462.         }
  463.         if (file_position == -1)
  464.             file_position = 0;
  465.         FileSeek (dw, file_position);
  466.  
  467.         dw->dvi.current_page = i;
  468.         
  469.         dw->dvi.display_enable = 0;
  470.         while (dw->dvi.current_page != dw->dvi.requested_page) {
  471.             dw->dvi.current_page = ParseInput (dw);
  472.             /*
  473.              * at EOF, seek back to the beginning of this page.
  474.              */
  475.             if (!dw->dvi.readingTmp && feof (dw->dvi.file)) {
  476.                 file_position = SearchPagePosition (dw,
  477.                         dw->dvi.current_page);
  478.                 if (file_position != -1)
  479.                     FileSeek (dw, file_position);
  480.                 dw->dvi.requested_page = dw->dvi.current_page;
  481.                 break;
  482.             }
  483.         }
  484.     }
  485. }
  486.  
  487. void DviSaveToFile(w, fp)
  488.     Widget w;
  489.     FILE *fp;
  490. {
  491.     XtCheckSubclass(w, dviWidgetClass, NULL);
  492.     (*((DviWidgetClass) XtClass(w))->command_class.save)(w, fp);
  493. }
  494.  
  495. static
  496. void SaveToFile(w, fp)
  497.     Widget w;
  498.     FILE *fp;
  499. {
  500.     DviWidget dw = (DviWidget)w;
  501.     long pos;
  502.     int c;
  503.  
  504.     if (dw->dvi.tmpFile) {
  505.         pos = ftell(dw->dvi.tmpFile);
  506.         if (dw->dvi.ungot) {
  507.             pos--;
  508.             dw->dvi.ungot = 0;
  509.             /* The ungot character is in the tmpFile, so we don't
  510.                want to read it from file. */
  511.             (void)getc(dw->dvi.file);
  512.         }
  513.     }
  514.     else
  515.         pos = ftell(dw->dvi.file);
  516.     FileSeek(dw, 0L);
  517.     while (DviGetC(dw, &c) != EOF)
  518.         if (putc(c, fp) == EOF) {
  519.             /* XXX print error message */
  520.             break;
  521.         }
  522.     FileSeek(dw, pos);
  523. }
  524.  
  525. static
  526. void ClassPartInitialize(widget_class)
  527.     WidgetClass widget_class;
  528. {
  529.     DviWidgetClass wc = (DviWidgetClass)widget_class;
  530.     DviWidgetClass super = (DviWidgetClass) wc->core_class.superclass;
  531.     if (wc->command_class.save == InheritSaveToFile)
  532.         wc->command_class.save = super->command_class.save;
  533. }
  534.     
  535. /*
  536. Local Variables:
  537. c-indent-level: 8
  538. c-continued-statement-offset: 8
  539. c-brace-offset: -8
  540. c-argdecl-indent: 8
  541. c-label-offset: -8
  542. c-tab-always-indent: nil
  543. End:
  544. */
  545.