Blame contrib/dbs/xtiff/xtiff.c

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