Blame contrib/dbs/xtiff/xtiff.c

Packit 994f1a
/*
Packit 994f1a
 * $Id: xtiff.c,v 1.2.2.1 2010-06-08 18:50:40 bfriesen Exp $
Packit 994f1a
 *
Packit 994f1a
 * xtiff - view a TIFF file in an X window
Packit 994f1a
 *
Packit 994f1a
 * Dan Sears
Packit 994f1a
 * Chris Sears
Packit 994f1a
 *
Packit 994f1a
 * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts.
Packit 994f1a
 *
Packit 994f1a
 *                      All Rights Reserved
Packit 994f1a
 *
Packit 994f1a
 * Permission to use, copy, modify, and distribute this software and its
Packit 994f1a
 * documentation for any purpose and without fee is hereby granted,
Packit 994f1a
 * provided that the above copyright notice appear in all copies and that
Packit 994f1a
 * both that copyright notice and this permission notice appear in
Packit 994f1a
 * supporting documentation, and that the name of Digital not be
Packit 994f1a
 * used in advertising or publicity pertaining to distribution of the
Packit 994f1a
 * software without specific, written prior permission.
Packit 994f1a
 *
Packit 994f1a
 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
Packit 994f1a
 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
Packit 994f1a
 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
Packit 994f1a
 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
Packit 994f1a
 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
Packit 994f1a
 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
Packit 994f1a
 * SOFTWARE.
Packit 994f1a
 *
Packit 994f1a
 * Revision 1.0  90/05/07
Packit 994f1a
 *      Initial release.
Packit 994f1a
 * Revision 2.0  90/12/20
Packit 994f1a
 *      Converted to use the Athena Widgets and the Xt Intrinsics.
Packit 994f1a
 *
Packit 994f1a
 * Notes:
Packit 994f1a
 *
Packit 994f1a
 * According to the TIFF 5.0 Specification, it is possible to have
Packit 994f1a
 * both a TIFFTAG_COLORMAP and a TIFFTAG_COLORRESPONSECURVE.  This
Packit 994f1a
 * doesn't make sense since a TIFFTAG_COLORMAP is 16 bits wide and
Packit 994f1a
 * a TIFFTAG_COLORRESPONSECURVE is tfBitsPerSample bits wide for each
Packit 994f1a
 * channel.  This is probably a bug in the specification.
Packit 994f1a
 * In this case, TIFFTAG_COLORRESPONSECURVE is ignored.
Packit 994f1a
 * This might make sense if TIFFTAG_COLORMAP was 8 bits wide.
Packit 994f1a
 *
Packit 994f1a
 * TIFFTAG_COLORMAP is often incorrectly written as ranging from
Packit 994f1a
 * 0 to 255 rather than from 0 to 65535.  CheckAndCorrectColormap()
Packit 994f1a
 * takes care of this.
Packit 994f1a
 *
Packit 994f1a
 * Only ORIENTATION_TOPLEFT is supported correctly.  This is the
Packit 994f1a
 * default TIFF and X orientation.  Other orientations will be
Packit 994f1a
 * displayed incorrectly.
Packit 994f1a
 *
Packit 994f1a
 * There is no support for or use of 3/3/2 DirectColor visuals.
Packit 994f1a
 * TIFFTAG_MINSAMPLEVALUE and TIFFTAG_MAXSAMPLEVALUE are not supported.
Packit 994f1a
 *
Packit 994f1a
 * Only TIFFTAG_BITSPERSAMPLE values that are 1, 2, 4 or 8 are supported.
Packit 994f1a
 */
Packit 994f1a
#include <math.h>
Packit 994f1a
#include <stdio.h>
Packit 994f1a
#include <stdlib.h>
Packit 994f1a
#include <tiffio.h>
Packit 994f1a
#include <X11/Xatom.h>
Packit 994f1a
#include <X11/Intrinsic.h>
Packit 994f1a
#include <X11/StringDefs.h>
Packit 994f1a
#include <X11/Xproto.h>
Packit 994f1a
#include <X11/Shell.h>
Packit 994f1a
#include <X11/Xaw/Form.h>
Packit 994f1a
#include <X11/Xaw/List.h>
Packit 994f1a
#include <X11/Xaw/Label.h>
Packit 994f1a
#include <X11/cursorfont.h>
Packit 994f1a
#define XK_MISCELLANY
Packit 994f1a
#include <X11/keysymdef.h>
Packit 994f1a
#include "xtifficon.h"
Packit 994f1a
Packit 994f1a
#define TIFF_GAMMA      "2.2"     /* default gamma from the TIFF 5.0 spec */
Packit 994f1a
#define ROUND(x)        (uint16) ((x) + 0.5)
Packit 994f1a
#define SCALE(x, s)     (((x) * 65535L) / (s))
Packit 994f1a
#define MCHECK(m)       if (!m) { fprintf(stderr, "malloc failed\n"); exit(0); }
Packit 994f1a
#define MIN(a, b)       (((a) < (b)) ? (a) : (b))
Packit 994f1a
#define MAX(a, b)       (((a) > (b)) ? (a) : (b))
Packit 994f1a
#define VIEWPORT_WIDTH  700
Packit 994f1a
#define VIEWPORT_HEIGHT 500
Packit 994f1a
#define KEY_TRANSLATE   20
Packit 994f1a
Packit 994f1a
#ifdef __STDC__
Packit 994f1a
#define PP(args)    args
Packit 994f1a
#else
Packit 994f1a
#define PP(args)    ()
Packit 994f1a
#endif
Packit 994f1a
Packit 994f1a
int main PP((int argc, char **argv));
Packit 994f1a
void OpenTIFFFile PP((void));
Packit 994f1a
void GetTIFFHeader PP((void));
Packit 994f1a
void SetNameLabel PP((void));
Packit 994f1a
void CheckAndCorrectColormap PP((void));
Packit 994f1a
void SimpleGammaCorrection PP((void));
Packit 994f1a
void GetVisual PP((void));
Packit 994f1a
Boolean SearchVisualList PP((int image_depth,
Packit 994f1a
    int visual_class, Visual **visual));
Packit 994f1a
void GetTIFFImage PP((void));
Packit 994f1a
void CreateXImage PP((void));
Packit 994f1a
XtCallbackProc SelectProc PP((Widget w, caddr_t unused_1, caddr_t unused_2));
Packit 994f1a
void QuitProc PP((void));
Packit 994f1a
void NextProc PP((void));
Packit 994f1a
void PreviousProc PP((void));
Packit 994f1a
void PageProc PP((int direction));
Packit 994f1a
void EventProc PP((Widget widget, caddr_t unused, XEvent *event));
Packit 994f1a
void ResizeProc PP((void));
Packit 994f1a
int XTiffErrorHandler PP((Display *display, XErrorEvent *error_event));
Packit 994f1a
void Usage PP((void));
Packit 994f1a
Packit 994f1a
int xtVersion = XtSpecificationRelease;     /* xtiff depends on R4 or higher */
Packit 994f1a
Packit 994f1a
/*
Packit 994f1a
 * Xt data structures
Packit 994f1a
 */
Packit 994f1a
Widget shellWidget, formWidget, listWidget, labelWidget, imageWidget;
Packit 994f1a
Packit 994f1a
enum { ButtonQuit = 0, ButtonPreviousPage = 1, ButtonNextPage = 2 };
Packit 994f1a
Packit 994f1a
String buttonStrings[] = { "Quit", "Previous", "Next" };
Packit 994f1a
Packit 994f1a
static XrmOptionDescRec shellOptions[] = {
Packit 994f1a
    { "-help", "*help", XrmoptionNoArg, (caddr_t) "True" },
Packit 994f1a
    { "-gamma", "*gamma", XrmoptionSepArg, NULL },
Packit 994f1a
    { "-usePixmap", "*usePixmap", XrmoptionSepArg, NULL },
Packit 994f1a
    { "-viewportWidth", "*viewportWidth", XrmoptionSepArg, NULL },
Packit 994f1a
    { "-viewportHeight", "*viewportHeight", XrmoptionSepArg, NULL },
Packit 994f1a
    { "-translate", "*translate", XrmoptionSepArg, NULL },
Packit 994f1a
    { "-verbose", "*verbose", XrmoptionSepArg, NULL }
Packit 994f1a
};
Packit 994f1a
Packit 994f1a
typedef struct {
Packit 994f1a
    Boolean help;
Packit 994f1a
    float gamma;
Packit 994f1a
    Boolean usePixmap;
Packit 994f1a
    uint32 viewportWidth;
Packit 994f1a
    uint32 viewportHeight;
Packit 994f1a
    int translate;
Packit 994f1a
    Boolean verbose;
Packit 994f1a
} AppData, *AppDataPtr;
Packit 994f1a
Packit 994f1a
AppData appData;
Packit 994f1a
Packit 994f1a
XtResource clientResources[] = {
Packit 994f1a
    {
Packit 994f1a
        "help", XtCBoolean, XtRBoolean, sizeof(Boolean),
Packit 994f1a
        XtOffset(AppDataPtr, help), XtRImmediate, (XtPointer) False
Packit 994f1a
    }, {
Packit 994f1a
        "gamma", "Gamma", XtRFloat, sizeof(float),
Packit 994f1a
        XtOffset(AppDataPtr, gamma), XtRString, (XtPointer) TIFF_GAMMA
Packit 994f1a
    }, {
Packit 994f1a
        "usePixmap", "UsePixmap", XtRBoolean, sizeof(Boolean),
Packit 994f1a
        XtOffset(AppDataPtr, usePixmap), XtRImmediate, (XtPointer) True
Packit 994f1a
    }, {
Packit 994f1a
        "viewportWidth", "ViewportWidth", XtRInt, sizeof(int),
Packit 994f1a
        XtOffset(AppDataPtr, viewportWidth), XtRImmediate,
Packit 994f1a
        (XtPointer) VIEWPORT_WIDTH
Packit 994f1a
    }, {
Packit 994f1a
        "viewportHeight", "ViewportHeight", XtRInt, sizeof(int),
Packit 994f1a
        XtOffset(AppDataPtr, viewportHeight), XtRImmediate,
Packit 994f1a
        (XtPointer) VIEWPORT_HEIGHT
Packit 994f1a
    }, {
Packit 994f1a
        "translate", "Translate", XtRInt, sizeof(int),
Packit 994f1a
        XtOffset(AppDataPtr, translate), XtRImmediate, (XtPointer) KEY_TRANSLATE
Packit 994f1a
    }, {
Packit 994f1a
        "verbose", "Verbose", XtRBoolean, sizeof(Boolean),
Packit 994f1a
        XtOffset(AppDataPtr, verbose), XtRImmediate, (XtPointer) True
Packit 994f1a
    }
Packit 994f1a
};
Packit 994f1a
Packit 994f1a
Arg formArgs[] = {
Packit 994f1a
    { XtNresizable, True }
Packit 994f1a
};
Packit 994f1a
Packit 994f1a
Arg listArgs[] = {
Packit 994f1a
    { XtNresizable, False },
Packit 994f1a
    { XtNborderWidth, 0 },
Packit 994f1a
    { XtNdefaultColumns, 3 },
Packit 994f1a
    { XtNforceColumns, True },
Packit 994f1a
    { XtNlist, (int) buttonStrings },
Packit 994f1a
    { XtNnumberStrings, XtNumber(buttonStrings) },
Packit 994f1a
    { XtNtop, XtChainTop },
Packit 994f1a
    { XtNleft, XtChainLeft },
Packit 994f1a
    { XtNbottom, XtChainTop },
Packit 994f1a
    { XtNright, XtChainLeft }
Packit 994f1a
};
Packit 994f1a
Packit 994f1a
Arg labelArgs[] = {
Packit 994f1a
    { XtNresizable, False },
Packit 994f1a
    { XtNwidth, 200 },
Packit 994f1a
    { XtNborderWidth, 0 },
Packit 994f1a
    { XtNjustify, XtJustifyLeft },
Packit 994f1a
    { XtNtop, XtChainTop },
Packit 994f1a
    { XtNleft, XtChainLeft },
Packit 994f1a
    { XtNbottom, XtChainTop },
Packit 994f1a
    { XtNright, XtChainLeft }
Packit 994f1a
};
Packit 994f1a
Packit 994f1a
Arg imageArgs[] = {
Packit 994f1a
    { XtNresizable, True },
Packit 994f1a
    { XtNborderWidth, 0 },
Packit 994f1a
    { XtNtop, XtChainTop },
Packit 994f1a
    { XtNleft, XtChainLeft },
Packit 994f1a
    { XtNbottom, XtChainTop },
Packit 994f1a
    { XtNright, XtChainLeft }
Packit 994f1a
};
Packit 994f1a
Packit 994f1a
XtActionsRec actionsTable[] = {
Packit 994f1a
    { "quit", QuitProc },
Packit 994f1a
    { "next", NextProc },
Packit 994f1a
    { "previous", PreviousProc },
Packit 994f1a
    { "notifyresize", ResizeProc }
Packit 994f1a
};
Packit 994f1a
Packit 994f1a
char translationsTable[] = "<Key>q:      quit() \n \
Packit 994f1a
                            <Key>Q:      quit() \n \
Packit 994f1a
                            <Message>WM_PROTOCOLS: quit()\n \
Packit 994f1a
                            <Key>p:      previous() \n \
Packit 994f1a
                            <Key>P:      previous() \n \
Packit 994f1a
                            <Key>n:      next() \n \
Packit 994f1a
                            <Key>N:      next() \n \
Packit 994f1a
                            <Configure>: notifyresize()";
Packit 994f1a
Packit 994f1a
/*
Packit 994f1a
 * X data structures
Packit 994f1a
 */
Packit 994f1a
Colormap            xColormap;
Packit 994f1a
Display *           xDisplay;
Packit 994f1a
Pixmap              xImagePixmap;
Packit 994f1a
Visual *            xVisual;
Packit 994f1a
XImage *            xImage;
Packit 994f1a
GC                  xWinGc;
Packit 994f1a
int                 xImageDepth, xScreen, xRedMask, xGreenMask, xBlueMask,
Packit 994f1a
                    xOffset = 0, yOffset = 0, grabX = -1, grabY = -1;
Packit 994f1a
unsigned char       basePixel = 0;
Packit 994f1a
Packit 994f1a
/*
Packit 994f1a
 * TIFF data structures
Packit 994f1a
 */
Packit 994f1a
TIFF *              tfFile = NULL;
Packit 994f1a
uint32              tfImageWidth, tfImageHeight;
Packit 994f1a
uint16              tfBitsPerSample, tfSamplesPerPixel, tfPlanarConfiguration,
Packit 994f1a
                    tfPhotometricInterpretation, tfGrayResponseUnit,
Packit 994f1a
                    tfImageDepth, tfBytesPerRow;
Packit 994f1a
int                 tfDirectory = 0, tfMultiPage = False;
Packit 994f1a
double              tfUnitMap, tfGrayResponseUnitMap[] = {
Packit 994f1a
                        -1, -10, -100, -1000, -10000, -100000
Packit 994f1a
                    };
Packit 994f1a
Packit 994f1a
/*
Packit 994f1a
 * display data structures
Packit 994f1a
 */
Packit 994f1a
double              *dRed, *dGreen, *dBlue;
Packit 994f1a
Packit 994f1a
/*
Packit 994f1a
 * shared data structures
Packit 994f1a
 */
Packit 994f1a
uint16 *            redMap = NULL, *greenMap = NULL, *blueMap = NULL,
Packit 994f1a
                    *grayMap = NULL, colormapSize;
Packit 994f1a
char *             imageMemory;
Packit 994f1a
char *              fileName;
Packit 994f1a
Packit 994f1a
int
Packit 994f1a
main(int argc, char **argv)
Packit 994f1a
{
Packit 994f1a
    XSetWindowAttributes window_attributes;
Packit 994f1a
    Widget widget_list[3];
Packit 994f1a
    Arg args[5];
Packit 994f1a
Packit 994f1a
    setbuf(stdout, NULL); setbuf(stderr, NULL);
Packit 994f1a
Packit 994f1a
    shellWidget = XtInitialize(argv[0], "XTiff", shellOptions,
Packit 994f1a
        XtNumber(shellOptions), &argc, argv);
Packit 994f1a
Packit 994f1a
    XSetErrorHandler(XTiffErrorHandler);
Packit 994f1a
Packit 994f1a
    XtGetApplicationResources(shellWidget, &appData,
Packit 994f1a
        (XtResourceList) clientResources, (Cardinal) XtNumber(clientResources),
Packit 994f1a
        (ArgList) NULL, (Cardinal) 0);
Packit 994f1a
Packit 994f1a
    if ((argc <= 1) || (argc > 2) || appData.help)
Packit 994f1a
        Usage();
Packit 994f1a
Packit 994f1a
    if (appData.verbose == False) {
Packit 994f1a
        TIFFSetErrorHandler(0);
Packit 994f1a
        TIFFSetWarningHandler(0);
Packit 994f1a
    }
Packit 994f1a
Packit 994f1a
    fileName = argv[1];
Packit 994f1a
Packit 994f1a
    xDisplay = XtDisplay(shellWidget);
Packit 994f1a
    xScreen = DefaultScreen(xDisplay);
Packit 994f1a
Packit 994f1a
    OpenTIFFFile();
Packit 994f1a
    GetTIFFHeader();
Packit 994f1a
    SimpleGammaCorrection();
Packit 994f1a
    GetVisual();
Packit 994f1a
    GetTIFFImage();
Packit 994f1a
Packit 994f1a
    /*
Packit 994f1a
     * Send visual, colormap, depth and iconPixmap to shellWidget.
Packit 994f1a
     * Sending the visual to the shell is only possible with the advent of R4.
Packit 994f1a
     */
Packit 994f1a
    XtSetArg(args[0], XtNvisual, xVisual);
Packit 994f1a
    XtSetArg(args[1], XtNcolormap, xColormap);
Packit 994f1a
    XtSetArg(args[2], XtNdepth,
Packit 994f1a
        xImageDepth == 1 ? DefaultDepth(xDisplay, xScreen) : xImageDepth);
Packit 994f1a
    XtSetArg(args[3], XtNiconPixmap,
Packit 994f1a
        XCreateBitmapFromData(xDisplay, RootWindow(xDisplay, xScreen),
Packit 994f1a
            xtifficon_bits, xtifficon_width, xtifficon_height));
Packit 994f1a
    XtSetArg(args[4], XtNallowShellResize, True);
Packit 994f1a
    XtSetValues(shellWidget, args, 5);
Packit 994f1a
Packit 994f1a
    /*
Packit 994f1a
     * widget instance hierarchy
Packit 994f1a
     */
Packit 994f1a
    formWidget = XtCreateManagedWidget("form", formWidgetClass,
Packit 994f1a
        shellWidget, formArgs, XtNumber(formArgs));
Packit 994f1a
Packit 994f1a
        widget_list[0] = listWidget = XtCreateWidget("list",
Packit 994f1a
            listWidgetClass, formWidget, listArgs, XtNumber(listArgs));
Packit 994f1a
Packit 994f1a
        widget_list[1] = labelWidget = XtCreateWidget("label",
Packit 994f1a
            labelWidgetClass, formWidget, labelArgs, XtNumber(labelArgs));
Packit 994f1a
Packit 994f1a
        widget_list[2] = imageWidget = XtCreateWidget("image",
Packit 994f1a
            widgetClass, formWidget, imageArgs, XtNumber(imageArgs));
Packit 994f1a
Packit 994f1a
    XtManageChildren(widget_list, XtNumber(widget_list));
Packit 994f1a
Packit 994f1a
    /*
Packit 994f1a
     * initial widget sizes - for small images let xtiff size itself
Packit 994f1a
     */
Packit 994f1a
    if (tfImageWidth >= appData.viewportWidth) {
Packit 994f1a
        XtSetArg(args[0], XtNwidth, appData.viewportWidth);
Packit 994f1a
        XtSetValues(shellWidget, args, 1);
Packit 994f1a
    }
Packit 994f1a
    if (tfImageHeight >= appData.viewportHeight) {
Packit 994f1a
        XtSetArg(args[0], XtNheight, appData.viewportHeight);
Packit 994f1a
        XtSetValues(shellWidget, args, 1);
Packit 994f1a
    }
Packit 994f1a
Packit 994f1a
    XtSetArg(args[0], XtNwidth, tfImageWidth);
Packit 994f1a
    XtSetArg(args[1], XtNheight, tfImageHeight);
Packit 994f1a
    XtSetValues(imageWidget, args, 2);
Packit 994f1a
Packit 994f1a
    /*
Packit 994f1a
     * formWidget uses these constraints but they are stored in the children.
Packit 994f1a
     */
Packit 994f1a
    XtSetArg(args[0], XtNfromVert, listWidget);
Packit 994f1a
    XtSetValues(imageWidget, args, 1);
Packit 994f1a
    XtSetArg(args[0], XtNfromHoriz, listWidget);
Packit 994f1a
    XtSetValues(labelWidget, args, 1);
Packit 994f1a
Packit 994f1a
    SetNameLabel();
Packit 994f1a
Packit 994f1a
    XtAddCallback(listWidget, XtNcallback, (XtCallbackProc) SelectProc,
Packit 994f1a
        (XtPointer) NULL);
Packit 994f1a
Packit 994f1a
    XtAddActions(actionsTable, XtNumber(actionsTable));
Packit 994f1a
    XtSetArg(args[0], XtNtranslations,
Packit 994f1a
        XtParseTranslationTable(translationsTable));
Packit 994f1a
    XtSetValues(formWidget, &args[0], 1);
Packit 994f1a
    XtSetValues(imageWidget, &args[0], 1);
Packit 994f1a
Packit 994f1a
    /*
Packit 994f1a
     * This is intended to be a little faster than going through
Packit 994f1a
     * the translation manager.
Packit 994f1a
     */
Packit 994f1a
    XtAddEventHandler(imageWidget, ExposureMask | ButtonPressMask
Packit 994f1a
        | ButtonReleaseMask | Button1MotionMask | KeyPressMask,
Packit 994f1a
        False, EventProc, NULL);
Packit 994f1a
Packit 994f1a
    XtRealizeWidget(shellWidget);
Packit 994f1a
Packit 994f1a
    window_attributes.cursor = XCreateFontCursor(xDisplay, XC_fleur);
Packit 994f1a
    XChangeWindowAttributes(xDisplay, XtWindow(imageWidget),
Packit 994f1a
        CWCursor, &window_attributes);
Packit 994f1a
Packit 994f1a
    CreateXImage();
Packit 994f1a
Packit 994f1a
    XtMainLoop();
Packit 994f1a
Packit 994f1a
    return 0;
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
void
Packit 994f1a
OpenTIFFFile()
Packit 994f1a
{
Packit 994f1a
    if (tfFile != NULL)
Packit 994f1a
        TIFFClose(tfFile);
Packit 994f1a
Packit 994f1a
    if ((tfFile = TIFFOpen(fileName, "r")) == NULL) {
Packit 994f1a
	fprintf(appData.verbose ? stderr : stdout,
Packit 994f1a
	    "xtiff: can't open %s as a TIFF file\n", fileName);
Packit 994f1a
        exit(0);
Packit 994f1a
    }
Packit 994f1a
Packit 994f1a
    tfMultiPage = (TIFFLastDirectory(tfFile) ? False : True);
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
void
Packit 994f1a
GetTIFFHeader()
Packit 994f1a
{
Packit 994f1a
    register int i;
Packit 994f1a
Packit 994f1a
    if (!TIFFSetDirectory(tfFile, tfDirectory)) {
Packit 994f1a
        fprintf(stderr, "xtiff: can't seek to directory %d in %s\n",
Packit 994f1a
            tfDirectory, fileName);
Packit 994f1a
        exit(0);
Packit 994f1a
    }
Packit 994f1a
Packit 994f1a
    TIFFGetField(tfFile, TIFFTAG_IMAGEWIDTH, &tfImageWidth);
Packit 994f1a
    TIFFGetField(tfFile, TIFFTAG_IMAGELENGTH, &tfImageHeight);
Packit 994f1a
Packit 994f1a
    /*
Packit 994f1a
     * If the following tags aren't present then use the TIFF defaults.
Packit 994f1a
     */
Packit 994f1a
    TIFFGetFieldDefaulted(tfFile, TIFFTAG_BITSPERSAMPLE, &tfBitsPerSample);
Packit 994f1a
    TIFFGetFieldDefaulted(tfFile, TIFFTAG_SAMPLESPERPIXEL, &tfSamplesPerPixel);
Packit 994f1a
    TIFFGetFieldDefaulted(tfFile, TIFFTAG_PLANARCONFIG, &tfPlanarConfiguration);
Packit 994f1a
    TIFFGetFieldDefaulted(tfFile, TIFFTAG_GRAYRESPONSEUNIT, &tfGrayResponseUnit);
Packit 994f1a
Packit 994f1a
    tfUnitMap = tfGrayResponseUnitMap[tfGrayResponseUnit];
Packit 994f1a
    colormapSize = 1 << tfBitsPerSample;
Packit 994f1a
    tfImageDepth = tfBitsPerSample * tfSamplesPerPixel;
Packit 994f1a
Packit 994f1a
    dRed = (double *) malloc(colormapSize * sizeof(double));
Packit 994f1a
    dGreen = (double *) malloc(colormapSize * sizeof(double));
Packit 994f1a
    dBlue = (double *) malloc(colormapSize * sizeof(double));
Packit 994f1a
    MCHECK(dRed); MCHECK(dGreen); MCHECK(dBlue);
Packit 994f1a
Packit 994f1a
    /*
Packit 994f1a
     * If TIFFTAG_PHOTOMETRIC is not present then assign a reasonable default.
Packit 994f1a
     * The TIFF 5.0 specification doesn't give a default.
Packit 994f1a
     */
Packit 994f1a
    if (!TIFFGetField(tfFile, TIFFTAG_PHOTOMETRIC,
Packit 994f1a
            &tfPhotometricInterpretation)) {
Packit 994f1a
        if (tfSamplesPerPixel != 1)
Packit 994f1a
            tfPhotometricInterpretation = PHOTOMETRIC_RGB;
Packit 994f1a
        else if (tfBitsPerSample == 1)
Packit 994f1a
            tfPhotometricInterpretation = PHOTOMETRIC_MINISBLACK;
Packit 994f1a
        else if (TIFFGetField(tfFile, TIFFTAG_COLORMAP,
Packit 994f1a
                &redMap, &greenMap, &blueMap)) {
Packit 994f1a
            tfPhotometricInterpretation = PHOTOMETRIC_PALETTE;
Packit 994f1a
            redMap = greenMap = blueMap = NULL;
Packit 994f1a
        } else
Packit 994f1a
            tfPhotometricInterpretation = PHOTOMETRIC_MINISBLACK;
Packit 994f1a
    }
Packit 994f1a
Packit 994f1a
    /*
Packit 994f1a
     * Given TIFFTAG_PHOTOMETRIC extract or create the response curves.
Packit 994f1a
     */
Packit 994f1a
    switch (tfPhotometricInterpretation) {
Packit 994f1a
    case PHOTOMETRIC_RGB:
Packit 994f1a
	redMap = (uint16 *) malloc(colormapSize * sizeof(uint16));
Packit 994f1a
	greenMap = (uint16 *) malloc(colormapSize * sizeof(uint16));
Packit 994f1a
	blueMap = (uint16 *) malloc(colormapSize * sizeof(uint16));
Packit 994f1a
	MCHECK(redMap); MCHECK(greenMap); MCHECK(blueMap);
Packit 994f1a
	for (i = 0; i < colormapSize; i++)
Packit 994f1a
	    dRed[i] = dGreen[i] = dBlue[i]
Packit 994f1a
		= (double) SCALE(i, colormapSize - 1);
Packit 994f1a
        break;
Packit 994f1a
    case PHOTOMETRIC_PALETTE:
Packit 994f1a
        if (!TIFFGetField(tfFile, TIFFTAG_COLORMAP,
Packit 994f1a
                &redMap, &greenMap, &blueMap)) {
Packit 994f1a
            redMap = (uint16 *) malloc(colormapSize * sizeof(uint16));
Packit 994f1a
            greenMap = (uint16 *) malloc(colormapSize * sizeof(uint16));
Packit 994f1a
            blueMap = (uint16 *) malloc(colormapSize * sizeof(uint16));
Packit 994f1a
            MCHECK(redMap); MCHECK(greenMap); MCHECK(blueMap);
Packit 994f1a
            for (i = 0; i < colormapSize; i++)
Packit 994f1a
                dRed[i] = dGreen[i] = dBlue[i]
Packit 994f1a
                    = (double) SCALE(i, colormapSize - 1);
Packit 994f1a
        } else {
Packit 994f1a
            CheckAndCorrectColormap();
Packit 994f1a
            for (i = 0; i < colormapSize; i++) {
Packit 994f1a
                dRed[i] = (double) redMap[i];
Packit 994f1a
                dGreen[i] = (double) greenMap[i];
Packit 994f1a
                dBlue[i] = (double) blueMap[i];
Packit 994f1a
            }
Packit 994f1a
        }
Packit 994f1a
        break;
Packit 994f1a
    case PHOTOMETRIC_MINISWHITE:
Packit 994f1a
        redMap = (uint16 *) malloc(colormapSize * sizeof(uint16));
Packit 994f1a
        greenMap = (uint16 *) malloc(colormapSize * sizeof(uint16));
Packit 994f1a
        blueMap = (uint16 *) malloc(colormapSize * sizeof(uint16));
Packit 994f1a
        MCHECK(redMap); MCHECK(greenMap); MCHECK(blueMap);
Packit 994f1a
	for (i = 0; i < colormapSize; i++)
Packit 994f1a
	    dRed[i] = dGreen[i] = dBlue[i] = (double)
Packit 994f1a
		 SCALE(colormapSize-1-i, colormapSize-1);
Packit 994f1a
        break;
Packit 994f1a
    case PHOTOMETRIC_MINISBLACK:
Packit 994f1a
        redMap = (uint16 *) malloc(colormapSize * sizeof(uint16));
Packit 994f1a
        greenMap = (uint16 *) malloc(colormapSize * sizeof(uint16));
Packit 994f1a
        blueMap = (uint16 *) malloc(colormapSize * sizeof(uint16));
Packit 994f1a
        MCHECK(redMap); MCHECK(greenMap); MCHECK(blueMap);
Packit 994f1a
	for (i = 0; i < colormapSize; i++)
Packit 994f1a
	    dRed[i] = dGreen[i] = dBlue[i] = (double) SCALE(i, colormapSize-1);
Packit 994f1a
        break;
Packit 994f1a
    default:
Packit 994f1a
        fprintf(stderr,
Packit 994f1a
            "xtiff: can't display photometric interpretation type %d\n",
Packit 994f1a
            tfPhotometricInterpretation);
Packit 994f1a
        exit(0);
Packit 994f1a
    }
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
void
Packit 994f1a
SetNameLabel()
Packit 994f1a
{
Packit 994f1a
    char buffer[BUFSIZ];
Packit 994f1a
    Arg args[1];
Packit 994f1a
Packit 994f1a
    if (tfMultiPage)
Packit e16d97
        snprintf(buffer, sizeof(buffer), "%s - page %d", fileName, tfDirectory);
Packit 994f1a
    else
Packit e16d97
        snprintf(buffer, sizeof(buffer), "%s", fileName);
Packit 994f1a
    XtSetArg(args[0], XtNlabel, buffer);
Packit 994f1a
    XtSetValues(labelWidget, args, 1);
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
/*
Packit 994f1a
 * Many programs get TIFF colormaps wrong.  They use 8-bit colormaps instead of
Packit 994f1a
 * 16-bit colormaps.  This function is a heuristic to detect and correct this.
Packit 994f1a
 */
Packit 994f1a
void
Packit 994f1a
CheckAndCorrectColormap()
Packit 994f1a
{
Packit 994f1a
    register int i;
Packit 994f1a
Packit 994f1a
    for (i = 0; i < colormapSize; i++)
Packit 994f1a
        if ((redMap[i] > 255) || (greenMap[i] > 255) || (blueMap[i] > 255))
Packit 994f1a
            return;
Packit 994f1a
Packit 994f1a
    for (i = 0; i < colormapSize; i++) {
Packit 994f1a
        redMap[i] = SCALE(redMap[i], 255);
Packit 994f1a
        greenMap[i] = SCALE(greenMap[i], 255);
Packit 994f1a
        blueMap[i] = SCALE(blueMap[i], 255);
Packit 994f1a
    }
Packit 994f1a
    TIFFWarning(fileName, "Assuming 8-bit colormap");
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
void
Packit 994f1a
SimpleGammaCorrection()
Packit 994f1a
{
Packit 994f1a
    register int i;
Packit 994f1a
    register double i_gamma = 1.0 / appData.gamma;
Packit 994f1a
Packit 994f1a
    for (i = 0; i < colormapSize; i++) {
Packit 994f1a
        if (((tfPhotometricInterpretation == PHOTOMETRIC_MINISWHITE)
Packit 994f1a
            && (i == colormapSize - 1))
Packit 994f1a
            || ((tfPhotometricInterpretation == PHOTOMETRIC_MINISBLACK)
Packit 994f1a
            && (i == 0)))
Packit 994f1a
            redMap[i] = greenMap[i] = blueMap[i] = 0;
Packit 994f1a
        else {
Packit 994f1a
            redMap[i] = ROUND((pow(dRed[i] / 65535.0, i_gamma) * 65535.0));
Packit 994f1a
            greenMap[i] = ROUND((pow(dGreen[i] / 65535.0, i_gamma) * 65535.0));
Packit 994f1a
            blueMap[i] = ROUND((pow(dBlue[i] / 65535.0, i_gamma) * 65535.0));
Packit 994f1a
        }
Packit 994f1a
    }
Packit 994f1a
Packit 994f1a
    free(dRed); free(dGreen); free(dBlue);
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
static char* classNames[] = {
Packit 994f1a
    "StaticGray",
Packit 994f1a
    "GrayScale",
Packit 994f1a
    "StaticColor",
Packit 994f1a
    "PseudoColor",
Packit 994f1a
    "TrueColor",
Packit 994f1a
    "DirectColor"
Packit 994f1a
};
Packit 994f1a
Packit 994f1a
/*
Packit 994f1a
 * Current limitation: the visual is set initially by the first file.
Packit 994f1a
 * It cannot be changed.
Packit 994f1a
 */
Packit 994f1a
void
Packit 994f1a
GetVisual()
Packit 994f1a
{
Packit 994f1a
    XColor *colors = NULL;
Packit 994f1a
    unsigned long *pixels = NULL;
Packit 994f1a
    unsigned long i;
Packit 994f1a
Packit 994f1a
    switch (tfImageDepth) {
Packit 994f1a
    /*
Packit 994f1a
     * X really wants a 32-bit image with the fourth channel unused,
Packit 994f1a
     * but the visual structure thinks it's 24-bit.  bitmap_unit is 32.
Packit 994f1a
     */
Packit 994f1a
    case 32:
Packit 994f1a
    case 24:
Packit 994f1a
        if (SearchVisualList(24, DirectColor, &xVisual) == False) {
Packit 994f1a
            fprintf(stderr, "xtiff: 24-bit DirectColor visual not available\n");
Packit 994f1a
            exit(0);
Packit 994f1a
        }
Packit 994f1a
Packit 994f1a
        colors = (XColor *) malloc(3 * colormapSize * sizeof(XColor));
Packit 994f1a
        MCHECK(colors);
Packit 994f1a
Packit 994f1a
        for (i = 0; i < colormapSize; i++) {
Packit 994f1a
            colors[i].pixel = (i << 16) + (i << 8) + i;
Packit 994f1a
            colors[i].red = redMap[i];
Packit 994f1a
            colors[i].green = greenMap[i];
Packit 994f1a
            colors[i].blue = blueMap[i];
Packit 994f1a
            colors[i].flags = DoRed | DoGreen | DoBlue;
Packit 994f1a
        }
Packit 994f1a
Packit 994f1a
        xColormap = XCreateColormap(xDisplay, RootWindow(xDisplay, xScreen),
Packit 994f1a
            xVisual, AllocAll);
Packit 994f1a
        XStoreColors(xDisplay, xColormap, colors, colormapSize);
Packit 994f1a
        break;
Packit 994f1a
    case 8:
Packit 994f1a
    case 4:
Packit 994f1a
    case 2:
Packit 994f1a
        /*
Packit 994f1a
         * We assume that systems with 24-bit visuals also have 8-bit visuals.
Packit 994f1a
         * We don't promote from 8-bit PseudoColor to 24/32 bit DirectColor.
Packit 994f1a
         */
Packit 994f1a
        switch (tfPhotometricInterpretation) {
Packit 994f1a
        case PHOTOMETRIC_MINISWHITE:
Packit 994f1a
        case PHOTOMETRIC_MINISBLACK:
Packit 994f1a
            if (SearchVisualList((int) tfImageDepth, GrayScale, &xVisual) == True)
Packit 994f1a
                break;
Packit 994f1a
        case PHOTOMETRIC_PALETTE:
Packit 994f1a
            if (SearchVisualList((int) tfImageDepth, PseudoColor, &xVisual) == True)
Packit 994f1a
                break;
Packit 994f1a
        default:
Packit 994f1a
            fprintf(stderr, "xtiff: Unsupported TIFF/X configuration\n");
Packit 994f1a
            exit(0);
Packit 994f1a
        }
Packit 994f1a
Packit 994f1a
        colors = (XColor *) malloc(colormapSize * sizeof(XColor));
Packit 994f1a
        MCHECK(colors);
Packit 994f1a
Packit 994f1a
        for (i = 0; i < colormapSize; i++) {
Packit 994f1a
            colors[i].pixel = i;
Packit 994f1a
            colors[i].red = redMap[i];
Packit 994f1a
            colors[i].green = greenMap[i];
Packit 994f1a
            colors[i].blue = blueMap[i];
Packit 994f1a
            colors[i].flags = DoRed | DoGreen | DoBlue;
Packit 994f1a
        }
Packit 994f1a
Packit 994f1a
        /*
Packit 994f1a
         * xtiff's colormap allocation is private.  It does not attempt
Packit 994f1a
         * to detect whether any existing colormap entries are suitable
Packit 994f1a
         * for its use.  This will cause colormap flashing.  Furthermore,
Packit 994f1a
         * background and foreground are taken from the environment.
Packit 994f1a
         * For example, the foreground color may be red when the visual
Packit 994f1a
         * is GrayScale.  If the colormap is completely populated,
Packit 994f1a
         * Xt will not be able to allocate fg and bg.
Packit 994f1a
         */
Packit 994f1a
        if (tfImageDepth == 8)
Packit 994f1a
            xColormap = XCreateColormap(xDisplay, RootWindow(xDisplay, xScreen),
Packit 994f1a
                xVisual, AllocAll);
Packit 994f1a
        else {
Packit 994f1a
            xColormap = XCreateColormap(xDisplay, RootWindow(xDisplay, xScreen),
Packit 994f1a
                xVisual, AllocNone);
Packit 994f1a
            pixels = (unsigned long *)
Packit 994f1a
                malloc(colormapSize * sizeof(unsigned long));
Packit 994f1a
            MCHECK(pixels);
Packit 994f1a
            (void) XAllocColorCells(xDisplay, xColormap, True,
Packit 994f1a
                NULL, 0, pixels, colormapSize);
Packit 994f1a
            basePixel = (unsigned char) pixels[0];
Packit 994f1a
            free(pixels);
Packit 994f1a
        }
Packit 994f1a
        XStoreColors(xDisplay, xColormap, colors, colormapSize);
Packit 994f1a
        break;
Packit 994f1a
    case 1:
Packit 994f1a
        xImageDepth = 1;
Packit 994f1a
        xVisual = DefaultVisual(xDisplay, xScreen);
Packit 994f1a
        xColormap = DefaultColormap(xDisplay, xScreen);
Packit 994f1a
        break;
Packit 994f1a
    default:
Packit 994f1a
        fprintf(stderr, "xtiff: unsupported image depth %d\n", tfImageDepth);
Packit 994f1a
        exit(0);
Packit 994f1a
    }
Packit 994f1a
Packit 994f1a
    if (appData.verbose == True)
Packit 994f1a
	fprintf(stderr, "%s: Using %d-bit %s visual.\n",
Packit 994f1a
	    fileName, xImageDepth, classNames[xVisual->class]);
Packit 994f1a
Packit 994f1a
    if (colors != NULL)
Packit 994f1a
        free(colors);
Packit 994f1a
    if (grayMap != NULL)
Packit 994f1a
        free(grayMap);
Packit 994f1a
    if (redMap != NULL)
Packit 994f1a
        free(redMap);
Packit 994f1a
    if (greenMap != NULL)
Packit 994f1a
        free(greenMap);
Packit 994f1a
    if (blueMap != NULL)
Packit 994f1a
        free(blueMap);
Packit 994f1a
Packit 994f1a
    colors = NULL; grayMap = redMap = greenMap = blueMap = NULL;
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
/*
Packit 994f1a
 * Search for an appropriate visual.  Promote where necessary.
Packit 994f1a
 * Check to make sure that ENOUGH colormap entries are writeable.
Packit 994f1a
 * basePixel was determined when XAllocColorCells() contiguously
Packit 994f1a
 * allocated enough entries.  basePixel is used below in GetTIFFImage.
Packit 994f1a
 */
Packit 994f1a
Boolean
Packit 994f1a
SearchVisualList(image_depth, visual_class, visual)
Packit 994f1a
    int image_depth, visual_class;
Packit 994f1a
    Visual **visual;
Packit 994f1a
{
Packit 994f1a
    XVisualInfo template_visual, *visual_list, *vl;
Packit 994f1a
    int i, n_visuals;
Packit 994f1a
Packit 994f1a
    template_visual.screen = xScreen;
Packit 994f1a
    vl = visual_list = XGetVisualInfo(xDisplay, VisualScreenMask,
Packit 994f1a
        &template_visual, &n_visuals);
Packit 994f1a
Packit 994f1a
    if (n_visuals == 0) {
Packit 994f1a
        fprintf(stderr, "xtiff: visual list not available\n");
Packit 994f1a
        exit(0);
Packit 994f1a
    }
Packit 994f1a
Packit 994f1a
    for (i = 0; i < n_visuals; vl++, i++) {
Packit 994f1a
        if ((vl->class == visual_class) && (vl->depth >= image_depth)
Packit 994f1a
            && (vl->visual->map_entries >= (1 << vl->depth))) {
Packit 994f1a
            *visual = vl->visual;
Packit 994f1a
            xImageDepth = vl->depth;
Packit 994f1a
            xRedMask = vl->red_mask;
Packit 994f1a
            xGreenMask = vl->green_mask;
Packit 994f1a
            xBlueMask = vl->blue_mask;
Packit 994f1a
            XFree((char *) visual_list);
Packit 994f1a
            return True;
Packit 994f1a
        }
Packit 994f1a
    }
Packit 994f1a
Packit 994f1a
    XFree((char *) visual_list);
Packit 994f1a
    return False;
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
void
Packit 994f1a
GetTIFFImage()
Packit 994f1a
{
Packit 994f1a
    int pixel_map[3], red_shift, green_shift, blue_shift;
Packit 994f1a
    char *scan_line, *output_p, *input_p;
Packit 994f1a
    uint32 i, j;
Packit 994f1a
    uint16 s;
Packit 994f1a
Packit 994f1a
    scan_line = (char *) malloc(tfBytesPerRow = TIFFScanlineSize(tfFile));
Packit 994f1a
    MCHECK(scan_line);
Packit 994f1a
Packit 994f1a
    if ((tfImageDepth == 32) || (tfImageDepth == 24)) {
Packit 994f1a
        output_p = imageMemory = (char *)
Packit 994f1a
            malloc(tfImageWidth * tfImageHeight * 4);
Packit 994f1a
        MCHECK(imageMemory);
Packit 994f1a
Packit 994f1a
        /*
Packit 994f1a
         * Handle different color masks for different frame buffers.
Packit 994f1a
         */
Packit 994f1a
        if (ImageByteOrder(xDisplay) == LSBFirst) { /* DECstation 5000 */
Packit 994f1a
            red_shift = pixel_map[0] = xRedMask == 0xFF000000 ? 3
Packit 994f1a
                : (xRedMask == 0xFF0000 ? 2 : (xRedMask == 0xFF00 ? 1 : 0));
Packit 994f1a
            green_shift = pixel_map[1] = xGreenMask == 0xFF000000 ? 3
Packit 994f1a
                : (xGreenMask == 0xFF0000 ? 2 : (xGreenMask == 0xFF00 ? 1 : 0));
Packit 994f1a
            blue_shift = pixel_map[2] = xBlueMask == 0xFF000000 ? 3
Packit 994f1a
                : (xBlueMask == 0xFF0000 ? 2 : (xBlueMask == 0xFF00 ? 1 : 0));
Packit 994f1a
        } else { /* Ardent */
Packit 994f1a
            red_shift = pixel_map[0] = xRedMask == 0xFF000000 ? 0
Packit 994f1a
                : (xRedMask == 0xFF0000 ? 1 : (xRedMask == 0xFF00 ? 2 : 3));
Packit 994f1a
            green_shift = pixel_map[0] = xGreenMask == 0xFF000000 ? 0
Packit 994f1a
                : (xGreenMask == 0xFF0000 ? 1 : (xGreenMask == 0xFF00 ? 2 : 3));
Packit 994f1a
            blue_shift = pixel_map[0] = xBlueMask == 0xFF000000 ? 0
Packit 994f1a
                : (xBlueMask == 0xFF0000 ? 1 : (xBlueMask == 0xFF00 ? 2 : 3));
Packit 994f1a
        }
Packit 994f1a
Packit 994f1a
        if (tfPlanarConfiguration == PLANARCONFIG_CONTIG) {
Packit 994f1a
            for (i = 0; i < tfImageHeight; i++) {
Packit 994f1a
                if (TIFFReadScanline(tfFile, scan_line, i, 0) < 0)
Packit 994f1a
                    break;
Packit 994f1a
                for (input_p = scan_line, j = 0; j < tfImageWidth; j++) {
Packit 994f1a
                    *(output_p + red_shift) = *input_p++;
Packit 994f1a
                    *(output_p + green_shift) = *input_p++;
Packit 994f1a
                    *(output_p + blue_shift) = *input_p++;
Packit 994f1a
                    output_p += 4;
Packit 994f1a
                    if (tfSamplesPerPixel == 4) /* skip the fourth channel */
Packit 994f1a
                        input_p++;
Packit 994f1a
                }
Packit 994f1a
            }
Packit 994f1a
        } else {
Packit 994f1a
            for (s = 0; s < tfSamplesPerPixel; s++) {
Packit 994f1a
                if (s == 3)             /* skip the fourth channel */
Packit 994f1a
                    continue;
Packit 994f1a
                for (i = 0; i < tfImageHeight; i++) {
Packit 994f1a
                    if (TIFFReadScanline(tfFile, scan_line, i, s) < 0)
Packit 994f1a
                        break;
Packit 994f1a
                    input_p = scan_line;
Packit 994f1a
                    output_p = imageMemory + (i*tfImageWidth*4) + pixel_map[s];
Packit 994f1a
                    for (j = 0; j < tfImageWidth; j++, output_p += 4)
Packit 994f1a
                        *output_p = *input_p++;
Packit 994f1a
                }
Packit 994f1a
            }
Packit 994f1a
        }
Packit 994f1a
    } else {
Packit 994f1a
        if (xImageDepth == tfImageDepth) {
Packit 994f1a
            output_p = imageMemory = (char *)
Packit 994f1a
                malloc(tfBytesPerRow * tfImageHeight);
Packit 994f1a
            MCHECK(imageMemory);
Packit 994f1a
Packit 994f1a
            for (i = 0; i < tfImageHeight; i++, output_p += tfBytesPerRow)
Packit 994f1a
                if (TIFFReadScanline(tfFile, output_p, i, 0) < 0)
Packit 994f1a
                    break;
Packit 994f1a
        } else if ((xImageDepth == 8) && (tfImageDepth == 4)) {
Packit 994f1a
            output_p = imageMemory = (char *)
Packit 994f1a
                malloc(tfBytesPerRow * 2 * tfImageHeight + 2);
Packit 994f1a
            MCHECK(imageMemory);
Packit 994f1a
Packit 994f1a
            /*
Packit 994f1a
             * If a scanline is of odd size the inner loop below will overshoot.
Packit 994f1a
             * This is handled very simply by recalculating the start point at
Packit 994f1a
             * each scanline and padding imageMemory a little at the end.
Packit 994f1a
             */
Packit 994f1a
            for (i = 0; i < tfImageHeight; i++) {
Packit 994f1a
                if (TIFFReadScanline(tfFile, scan_line, i, 0) < 0)
Packit 994f1a
                    break;
Packit 994f1a
                output_p = &imageMemory[i * tfImageWidth];
Packit 994f1a
                input_p = scan_line;
Packit 994f1a
                for (j = 0; j < tfImageWidth; j += 2, input_p++) {
Packit 994f1a
                    *output_p++ = (*input_p >> 4) + basePixel;
Packit 994f1a
                    *output_p++ = (*input_p & 0xf) + basePixel;
Packit 994f1a
                }
Packit 994f1a
            }
Packit 994f1a
        } else if ((xImageDepth == 8) && (tfImageDepth == 2)) {
Packit 994f1a
            output_p = imageMemory = (char *)
Packit 994f1a
                malloc(tfBytesPerRow * 4 * tfImageHeight + 4);
Packit 994f1a
            MCHECK(imageMemory);
Packit 994f1a
Packit 994f1a
            for (i = 0; i < tfImageHeight; i++) {
Packit 994f1a
                if (TIFFReadScanline(tfFile, scan_line, i, 0) < 0)
Packit 994f1a
                    break;
Packit 994f1a
                output_p = &imageMemory[i * tfImageWidth];
Packit 994f1a
                input_p = scan_line;
Packit 994f1a
                for (j = 0; j < tfImageWidth; j += 4, input_p++) {
Packit 994f1a
                    *output_p++ = (*input_p >> 6) + basePixel;
Packit 994f1a
                    *output_p++ = ((*input_p >> 4) & 3) + basePixel;
Packit 994f1a
                    *output_p++ = ((*input_p >> 2) & 3) + basePixel;
Packit 994f1a
                    *output_p++ = (*input_p & 3) + basePixel;
Packit 994f1a
                }
Packit 994f1a
            }
Packit 994f1a
        } else if ((xImageDepth == 4) && (tfImageDepth == 2)) {
Packit 994f1a
            output_p = imageMemory = (char *)
Packit 994f1a
                malloc(tfBytesPerRow * 2 * tfImageHeight + 2);
Packit 994f1a
            MCHECK(imageMemory);
Packit 994f1a
Packit 994f1a
            for (i = 0; i < tfImageHeight; i++) {
Packit 994f1a
                if (TIFFReadScanline(tfFile, scan_line, i, 0) < 0)
Packit 994f1a
                    break;
Packit 994f1a
                output_p = &imageMemory[i * tfBytesPerRow * 2];
Packit 994f1a
                input_p = scan_line;
Packit 994f1a
                for (j = 0; j < tfImageWidth; j += 4, input_p++) {
Packit 994f1a
                    *output_p++ = (((*input_p>>6) << 4)
Packit 994f1a
                        | ((*input_p >> 4) & 3)) + basePixel;
Packit 994f1a
                    *output_p++ = ((((*input_p>>2) & 3) << 4)
Packit 994f1a
                        | (*input_p & 3)) + basePixel;
Packit 994f1a
                }
Packit 994f1a
            }
Packit 994f1a
        } else {
Packit 994f1a
            fprintf(stderr,
Packit 994f1a
                "xtiff: can't handle %d-bit TIFF file on an %d-bit display\n",
Packit 994f1a
                tfImageDepth, xImageDepth);
Packit 994f1a
            exit(0);
Packit 994f1a
        }
Packit 994f1a
    }
Packit 994f1a
Packit 994f1a
    free(scan_line);
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
void
Packit 994f1a
CreateXImage()
Packit 994f1a
{
Packit 994f1a
    XGCValues gc_values;
Packit 994f1a
    GC bitmap_gc;
Packit 994f1a
Packit 994f1a
    xOffset = yOffset = 0;
Packit 994f1a
    grabX = grabY = -1;
Packit 994f1a
Packit 994f1a
    xImage = XCreateImage(xDisplay, xVisual, xImageDepth,
Packit 994f1a
        xImageDepth == 1 ? XYBitmap : ZPixmap, /* offset */ 0,
Packit 994f1a
        (char *) imageMemory, tfImageWidth, tfImageHeight,
Packit 994f1a
        /* bitmap_pad */ 8, /* bytes_per_line */ 0);
Packit 994f1a
Packit 994f1a
    /*
Packit 994f1a
     * libtiff converts LSB data into MSB but doesn't change the FillOrder tag.
Packit 994f1a
     */
Packit 994f1a
    if (xImageDepth == 1)
Packit 994f1a
        xImage->bitmap_bit_order = MSBFirst;
Packit 994f1a
    if (xImageDepth <= 8)
Packit 994f1a
        xImage->byte_order = MSBFirst;
Packit 994f1a
Packit 994f1a
    /*
Packit 994f1a
     * create an appropriate GC
Packit 994f1a
     */
Packit 994f1a
    gc_values.function = GXcopy;
Packit 994f1a
    gc_values.plane_mask = AllPlanes;
Packit 994f1a
    if (tfPhotometricInterpretation == PHOTOMETRIC_MINISBLACK) {
Packit 994f1a
        gc_values.foreground = XWhitePixel(xDisplay, xScreen);
Packit 994f1a
        gc_values.background = XBlackPixel(xDisplay, xScreen);
Packit 994f1a
    } else {
Packit 994f1a
        gc_values.foreground = XBlackPixel(xDisplay, xScreen);
Packit 994f1a
        gc_values.background = XWhitePixel(xDisplay, xScreen);
Packit 994f1a
    }
Packit 994f1a
    xWinGc = XCreateGC(xDisplay, XtWindow(shellWidget),
Packit 994f1a
        GCFunction | GCPlaneMask | GCForeground | GCBackground, &gc_values);
Packit 994f1a
Packit 994f1a
    /*
Packit 994f1a
     * create the pixmap and load the image
Packit 994f1a
     */
Packit 994f1a
    if (appData.usePixmap == True) {
Packit 994f1a
        xImagePixmap = XCreatePixmap(xDisplay, RootWindow(xDisplay, xScreen),
Packit 994f1a
            xImage->width, xImage->height, xImageDepth);
Packit 994f1a
Packit 994f1a
        /*
Packit 994f1a
         * According to the O'Reilly X Protocol Reference Manual, page 53,
Packit 994f1a
         * "A pixmap depth of one is always supported and listed, but windows
Packit 994f1a
         * of depth one might not be supported."  Therefore we create a pixmap
Packit 994f1a
         * of depth one and use XCopyPlane().  This is idiomatic.
Packit 994f1a
         */
Packit 994f1a
        if (xImageDepth == 1) {         /* just pass the bits through */
Packit 994f1a
            gc_values.foreground = 1;   /* foreground describes set bits */
Packit 994f1a
            gc_values.background = 0;   /* background describes clear bits */
Packit 994f1a
            bitmap_gc = XCreateGC(xDisplay, xImagePixmap,
Packit 994f1a
                GCForeground | GCBackground, &gc_values);
Packit 994f1a
            XPutImage(xDisplay, xImagePixmap, bitmap_gc, xImage,
Packit 994f1a
                0, 0, 0, 0, xImage->width, xImage->height);
Packit 994f1a
        } else
Packit 994f1a
            XPutImage(xDisplay, xImagePixmap, xWinGc, xImage,
Packit 994f1a
                0, 0, 0, 0, xImage->width, xImage->height);
Packit 994f1a
        XDestroyImage(xImage);
Packit 994f1a
        free(imageMemory);
Packit 994f1a
    }
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
XtCallbackProc
Packit 994f1a
SelectProc(w, unused_1, unused_2)
Packit 994f1a
    Widget w;
Packit 994f1a
    caddr_t unused_1;
Packit 994f1a
    caddr_t unused_2;
Packit 994f1a
{
Packit 994f1a
    XawListReturnStruct *list_return;
Packit 994f1a
Packit 994f1a
    list_return = XawListShowCurrent(w);
Packit 994f1a
Packit 994f1a
    switch (list_return->list_index) {
Packit 994f1a
    case ButtonQuit:
Packit 994f1a
        QuitProc();
Packit 994f1a
        break;
Packit 994f1a
    case ButtonPreviousPage:
Packit 994f1a
        PreviousProc();
Packit 994f1a
        break;
Packit 994f1a
    case ButtonNextPage:
Packit 994f1a
        NextProc();
Packit 994f1a
        break;
Packit 994f1a
    default:
Packit 994f1a
        fprintf(stderr, "error in SelectProc\n");
Packit 994f1a
        exit(0);
Packit 994f1a
    }
Packit 994f1a
    XawListUnhighlight(w);
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
void
Packit 994f1a
QuitProc(void)
Packit 994f1a
{
Packit 994f1a
    exit(0);
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
void
Packit 994f1a
NextProc()
Packit 994f1a
{
Packit 994f1a
    PageProc(ButtonNextPage);
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
void
Packit 994f1a
PreviousProc()
Packit 994f1a
{
Packit 994f1a
    PageProc(ButtonPreviousPage);
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
void
Packit 994f1a
PageProc(direction)
Packit 994f1a
    int direction;
Packit 994f1a
{
Packit 994f1a
    XEvent fake_event;
Packit 994f1a
    Arg args[4];
Packit 994f1a
Packit 994f1a
    switch (direction) {
Packit 994f1a
    case ButtonPreviousPage:
Packit 994f1a
        if (tfDirectory > 0)
Packit 994f1a
            TIFFSetDirectory(tfFile, --tfDirectory);
Packit 994f1a
        else
Packit 994f1a
            return;
Packit 994f1a
        break;
Packit 994f1a
    case ButtonNextPage:
Packit 994f1a
        if (TIFFReadDirectory(tfFile) == True)
Packit 994f1a
            tfDirectory++;
Packit 994f1a
        else
Packit 994f1a
            return;
Packit 994f1a
        break;
Packit 994f1a
    default:
Packit 994f1a
        fprintf(stderr, "error in PageProc\n");
Packit 994f1a
        exit(0);
Packit 994f1a
    }
Packit 994f1a
Packit 994f1a
    xOffset = yOffset = 0;
Packit 994f1a
    grabX = grabY = -1;
Packit 994f1a
Packit 994f1a
    GetTIFFHeader();
Packit 994f1a
    SetNameLabel();
Packit 994f1a
    GetTIFFImage();
Packit 994f1a
Packit 994f1a
    if (appData.usePixmap == True)
Packit 994f1a
        XFreePixmap(xDisplay, xImagePixmap);
Packit 994f1a
    else
Packit 994f1a
        XDestroyImage(xImage);
Packit 994f1a
Packit 994f1a
    CreateXImage();
Packit 994f1a
Packit 994f1a
    /*
Packit 994f1a
     * Using XtSetValues() to set the widget size causes a resize.
Packit 994f1a
     * This resize gets propagated up to the parent shell.
Packit 994f1a
     * In order to disable this visually disconcerting effect,
Packit 994f1a
     * shell resizing is temporarily disabled.
Packit 994f1a
     */
Packit 994f1a
    XtSetArg(args[0], XtNallowShellResize, False);
Packit 994f1a
    XtSetValues(shellWidget, args, 1);
Packit 994f1a
Packit 994f1a
    XtSetArg(args[0], XtNwidth, tfImageWidth);
Packit 994f1a
    XtSetArg(args[1], XtNheight, tfImageHeight);
Packit 994f1a
    XtSetValues(imageWidget, args, 2);
Packit 994f1a
Packit 994f1a
    XtSetArg(args[0], XtNallowShellResize, True);
Packit 994f1a
    XtSetValues(shellWidget, args, 1);
Packit 994f1a
Packit 994f1a
    XClearWindow(xDisplay, XtWindow(imageWidget));
Packit 994f1a
Packit 994f1a
    fake_event.type = Expose;
Packit 994f1a
    fake_event.xexpose.x = fake_event.xexpose.y = 0;
Packit 994f1a
    fake_event.xexpose.width = tfImageWidth;    /* the window will clip */
Packit 994f1a
    fake_event.xexpose.height = tfImageHeight;
Packit 994f1a
    EventProc(imageWidget, NULL, &fake_event);
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
void
Packit 994f1a
EventProc(widget, unused, event)
Packit 994f1a
    Widget widget;
Packit 994f1a
    caddr_t unused;
Packit 994f1a
    XEvent *event;
Packit 994f1a
{
Packit 994f1a
    int ih, iw, ww, wh, sx, sy, w, h, dx, dy;
Packit 994f1a
    Dimension w_width, w_height;
Packit 994f1a
    XEvent next_event;
Packit 994f1a
    Arg args[2];
Packit 994f1a
Packit 994f1a
    if (event->type == MappingNotify) {
Packit 994f1a
        XRefreshKeyboardMapping((XMappingEvent *) event);
Packit 994f1a
        return;
Packit 994f1a
    }
Packit 994f1a
Packit 994f1a
    if (!XtIsRealized(widget))
Packit 994f1a
        return;
Packit 994f1a
Packit 994f1a
    if ((event->type == ButtonPress) || (event->type == ButtonRelease))
Packit 994f1a
        if (event->xbutton.button != Button1)
Packit 994f1a
            return;
Packit 994f1a
Packit 994f1a
    iw = tfImageWidth;  /* avoid sign problems */
Packit 994f1a
    ih = tfImageHeight;
Packit 994f1a
Packit 994f1a
    /*
Packit 994f1a
     * The grabX and grabY variables record where the user grabbed the image.
Packit 994f1a
     * They also record whether the mouse button is down or not.
Packit 994f1a
     */
Packit 994f1a
    if (event->type == ButtonPress) {
Packit 994f1a
        grabX = event->xbutton.x;
Packit 994f1a
        grabY = event->xbutton.y;
Packit 994f1a
        return;
Packit 994f1a
    }
Packit 994f1a
Packit 994f1a
    /*
Packit 994f1a
     * imageWidget is a Core widget and doesn't get resized.
Packit 994f1a
     * So we calculate the size of its viewport here.
Packit 994f1a
     */
Packit 994f1a
    XtSetArg(args[0], XtNwidth, &w_width);
Packit 994f1a
    XtSetArg(args[1], XtNheight, &w_height);
Packit 994f1a
    XtGetValues(shellWidget, args, 2);
Packit 994f1a
    ww = w_width;
Packit 994f1a
    wh = w_height;
Packit 994f1a
    XtGetValues(listWidget, args, 2);
Packit 994f1a
    wh -= w_height;
Packit 994f1a
Packit 994f1a
    switch (event->type) {
Packit 994f1a
    case Expose:
Packit 994f1a
        dx = event->xexpose.x;
Packit 994f1a
        dy = event->xexpose.y;
Packit 994f1a
        sx = dx + xOffset;
Packit 994f1a
        sy = dy + yOffset;
Packit 994f1a
        w = MIN(event->xexpose.width, iw);
Packit 994f1a
        h = MIN(event->xexpose.height, ih);
Packit 994f1a
        break;
Packit 994f1a
    case KeyPress:
Packit 994f1a
        if ((grabX >= 0) || (grabY >= 0)) /* Mouse button is still down */
Packit 994f1a
            return;
Packit 994f1a
        switch (XLookupKeysym((XKeyEvent *) event, /* KeySyms index */ 0)) {
Packit 994f1a
        case XK_Up:
Packit 994f1a
            if (ih < wh)    /* Don't scroll if the window fits the image. */
Packit 994f1a
                return;
Packit 994f1a
            sy = yOffset + appData.translate;
Packit 994f1a
            sy = MIN(ih - wh, sy);
Packit 994f1a
            if (sy == yOffset)  /* Filter redundant stationary refreshes. */
Packit 994f1a
                return;
Packit 994f1a
            yOffset = sy;
Packit 994f1a
            sx = xOffset;
Packit 994f1a
            dx = dy = 0;
Packit 994f1a
            w = ww; h = wh;
Packit 994f1a
            break;
Packit 994f1a
        case XK_Down:
Packit 994f1a
            if (ih < wh)
Packit 994f1a
                return;
Packit 994f1a
            sy = yOffset - appData.translate;
Packit 994f1a
            sy = MAX(sy, 0);
Packit 994f1a
            if (sy == yOffset)
Packit 994f1a
                return;
Packit 994f1a
            yOffset = sy;
Packit 994f1a
            sx = xOffset;
Packit 994f1a
            dx = dy = 0;
Packit 994f1a
            w = ww; h = wh;
Packit 994f1a
            break;
Packit 994f1a
        case XK_Left:
Packit 994f1a
            if (iw < ww)
Packit 994f1a
                return;
Packit 994f1a
            sx = xOffset + appData.translate;
Packit 994f1a
            sx = MIN(iw - ww, sx);
Packit 994f1a
            if (sx == xOffset)
Packit 994f1a
                return;
Packit 994f1a
            xOffset = sx;
Packit 994f1a
            sy = yOffset;
Packit 994f1a
            dx = dy = 0;
Packit 994f1a
            w = ww; h = wh;
Packit 994f1a
            break;
Packit 994f1a
        case XK_Right:
Packit 994f1a
            if (iw < ww)
Packit 994f1a
                return;
Packit 994f1a
            sx = xOffset - appData.translate;
Packit 994f1a
            sx = MAX(sx, 0);
Packit 994f1a
            if (sx == xOffset)
Packit 994f1a
                return;
Packit 994f1a
            xOffset = sx;
Packit 994f1a
            sy = yOffset;
Packit 994f1a
            dx = dy = 0;
Packit 994f1a
            w = ww; h = wh;
Packit 994f1a
            break;
Packit 994f1a
        default:
Packit 994f1a
            return;
Packit 994f1a
        }
Packit 994f1a
        break;
Packit 994f1a
    case MotionNotify:
Packit 994f1a
        /*
Packit 994f1a
         * MotionEvent compression.  Ignore multiple motion events.
Packit 994f1a
         * Ignore motion events if the mouse button is up.
Packit 994f1a
         */
Packit 994f1a
        if (XPending(xDisplay)) /* Xlib doesn't flush the output buffer */
Packit 994f1a
            if (XtPeekEvent(&next_event))
Packit 994f1a
                if (next_event.type == MotionNotify)
Packit 994f1a
                    return;
Packit 994f1a
        if ((grabX < 0) || (grabY < 0))
Packit 994f1a
            return;
Packit 994f1a
        sx = xOffset + grabX - (int) event->xmotion.x;
Packit 994f1a
        if (sx >= (iw - ww))    /* clamp x motion but allow y motion */
Packit 994f1a
            sx = iw - ww;
Packit 994f1a
        sx = MAX(sx, 0);
Packit 994f1a
        sy = yOffset + grabY - (int) event->xmotion.y;
Packit 994f1a
        if (sy >= (ih - wh)) /* clamp y motion but allow x motion */
Packit 994f1a
            sy = ih - wh;
Packit 994f1a
        sy = MAX(sy, 0);
Packit 994f1a
        if ((sx == xOffset) && (sy == yOffset))
Packit 994f1a
            return;
Packit 994f1a
        dx = dy = 0;
Packit 994f1a
        w = ww; h = wh;
Packit 994f1a
        break;
Packit 994f1a
    case ButtonRelease:
Packit 994f1a
        xOffset = xOffset + grabX - (int) event->xbutton.x;
Packit 994f1a
        xOffset = MIN(iw - ww, xOffset);
Packit 994f1a
        xOffset = MAX(xOffset, 0);
Packit 994f1a
        yOffset = yOffset + grabY - (int) event->xbutton.y;
Packit 994f1a
        yOffset = MIN(ih - wh, yOffset);
Packit 994f1a
        yOffset = MAX(yOffset, 0);
Packit 994f1a
        grabX = grabY = -1;
Packit 994f1a
    default:
Packit 994f1a
        return;
Packit 994f1a
    }
Packit 994f1a
Packit 994f1a
    if (appData.usePixmap == True) {
Packit 994f1a
        if (xImageDepth == 1)
Packit 994f1a
            XCopyPlane(xDisplay, xImagePixmap, XtWindow(widget),
Packit 994f1a
                xWinGc, sx, sy, w, h, dx, dy, 1);
Packit 994f1a
        else
Packit 994f1a
            XCopyArea(xDisplay, xImagePixmap, XtWindow(widget),
Packit 994f1a
                xWinGc, sx, sy, w, h, dx, dy);
Packit 994f1a
    } else
Packit 994f1a
        XPutImage(xDisplay, XtWindow(widget), xWinGc, xImage,
Packit 994f1a
            sx, sy, dx, dy, w, h);
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
void
Packit 994f1a
ResizeProc()
Packit 994f1a
{
Packit 994f1a
    Dimension w_width, w_height;
Packit 994f1a
    int xo, yo, ww, wh;
Packit 994f1a
    XEvent fake_event;
Packit 994f1a
    Arg args[2];
Packit 994f1a
Packit 994f1a
    if ((xOffset == 0) && (yOffset == 0))
Packit 994f1a
        return;
Packit 994f1a
Packit 994f1a
    XtSetArg(args[0], XtNwidth, &w_width);
Packit 994f1a
    XtSetArg(args[1], XtNheight, &w_height);
Packit 994f1a
    XtGetValues(shellWidget, args, 2);
Packit 994f1a
    ww = w_width;
Packit 994f1a
    wh = w_height;
Packit 994f1a
    XtGetValues(listWidget, args, 2);
Packit 994f1a
    wh -= w_height;
Packit 994f1a
Packit 994f1a
    xo = xOffset; yo = yOffset;
Packit 994f1a
Packit 994f1a
    if ((xOffset + ww) >= tfImageWidth)
Packit 994f1a
        xOffset = MAX((int) tfImageWidth - ww, 0);
Packit 994f1a
    if ((yOffset + wh) >= tfImageHeight)
Packit 994f1a
        yOffset = MAX((int) tfImageHeight - wh, 0);
Packit 994f1a
Packit 994f1a
    /*
Packit 994f1a
     * Send an ExposeEvent if the origin changed.
Packit 994f1a
     * We have to do this because of the use and semantics of bit gravity.
Packit 994f1a
     */
Packit 994f1a
    if ((xo != xOffset) || (yo != yOffset)) {
Packit 994f1a
        fake_event.type = Expose;
Packit 994f1a
        fake_event.xexpose.x = fake_event.xexpose.y = 0;
Packit 994f1a
        fake_event.xexpose.width = tfImageWidth;
Packit 994f1a
        fake_event.xexpose.height = tfImageHeight;
Packit 994f1a
        EventProc(imageWidget, NULL, &fake_event);
Packit 994f1a
    }
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
int
Packit 994f1a
XTiffErrorHandler(display, error_event)
Packit 994f1a
    Display *display;
Packit 994f1a
    XErrorEvent *error_event;
Packit 994f1a
{
Packit 994f1a
    char message[80];
Packit 994f1a
Packit 994f1a
    /*
Packit 994f1a
     * Some X servers limit the size of pixmaps.
Packit 994f1a
     */
Packit 994f1a
    if ((error_event->error_code == BadAlloc)
Packit 994f1a
            && (error_event->request_code == X_CreatePixmap))
Packit 994f1a
        fprintf(stderr, "xtiff: requested pixmap too big for display\n");
Packit 994f1a
    else {
Packit 994f1a
        XGetErrorText(display, error_event->error_code, message, 80);
Packit 994f1a
        fprintf(stderr, "xtiff: error code %s\n", message);
Packit 994f1a
    }
Packit 994f1a
Packit 994f1a
    exit(0);
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
void
Packit 994f1a
Usage()
Packit 994f1a
{
Packit 994f1a
    fprintf(stderr, "Usage xtiff: [options] tiff-file\n");
Packit 994f1a
    fprintf(stderr, "\tstandard Xt options\n");
Packit 994f1a
    fprintf(stderr, "\t[-help]\n");
Packit 994f1a
    fprintf(stderr, "\t[-gamma gamma]\n");
Packit 994f1a
    fprintf(stderr, "\t[-usePixmap (True | False)]\n");
Packit 994f1a
    fprintf(stderr, "\t[-viewportWidth pixels]\n");
Packit 994f1a
    fprintf(stderr, "\t[-viewportHeight pixels]\n");
Packit 994f1a
    fprintf(stderr, "\t[-translate pixels]\n");
Packit 994f1a
    fprintf(stderr, "\t[-verbose (True | False)]\n");
Packit 994f1a
    exit(0);
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
/* vim: set ts=8 sts=8 sw=8 noet: */
Packit 994f1a
Packit 994f1a
/*
Packit 994f1a
 * Local Variables:
Packit 994f1a
 * mode: c
Packit 994f1a
 * c-basic-offset: 8
Packit 994f1a
 * fill-column: 78
Packit 994f1a
 * End:
Packit 994f1a
 */