From 6e9c41a892ed0e0da326e0278b3221ce3f5713b8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= <debian@jff-webhosting.net>
Date: Mon, 6 Oct 2014 14:00:40 +0200
Subject: Initial import of sane-backends version 1.0.24-1.2

---
 japi/ImageCanvas.java       |  110 ++++
 japi/ImageCanvasClient.java |   54 ++
 japi/Jscanimage.java        | 1166 +++++++++++++++++++++++++++++++++++++++++++
 japi/Makefile.am            |   47 ++
 japi/Makefile.in            |  738 +++++++++++++++++++++++++++
 japi/README.JAVA            |   55 ++
 japi/Sane.c                 |  493 ++++++++++++++++++
 japi/Sane.java              |  144 ++++++
 japi/SaneDevice.java        |   55 ++
 japi/SaneOption.java        |  145 ++++++
 japi/SaneParameters.java    |   68 +++
 japi/SaneRange.java         |   53 ++
 japi/ScanIt.java            |  391 +++++++++++++++
 japi/Test.java              |  175 +++++++
 14 files changed, 3694 insertions(+)
 create mode 100644 japi/ImageCanvas.java
 create mode 100644 japi/ImageCanvasClient.java
 create mode 100644 japi/Jscanimage.java
 create mode 100644 japi/Makefile.am
 create mode 100644 japi/Makefile.in
 create mode 100644 japi/README.JAVA
 create mode 100644 japi/Sane.c
 create mode 100644 japi/Sane.java
 create mode 100644 japi/SaneDevice.java
 create mode 100644 japi/SaneOption.java
 create mode 100644 japi/SaneParameters.java
 create mode 100644 japi/SaneRange.java
 create mode 100644 japi/ScanIt.java
 create mode 100644 japi/Test.java

(limited to 'japi')

diff --git a/japi/ImageCanvas.java b/japi/ImageCanvas.java
new file mode 100644
index 0000000..56cf34c
--- /dev/null
+++ b/japi/ImageCanvas.java
@@ -0,0 +1,110 @@
+/* sane - Scanner Access Now Easy.
+   Copyright (C) 1997 Jeffrey S. Freedman
+   This file is part of the SANE package.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+   As a special exception, the authors of SANE give permission for
+   additional uses of the libraries contained in this release of SANE.
+
+   The exception is that, if you link a SANE library with other files
+   to produce an executable, this does not by itself cause the
+   resulting executable to be covered by the GNU General Public
+   License.  Your use of that executable is in no way restricted on
+   account of linking the SANE library code into it.
+
+   This exception does not, however, invalidate any other reasons why
+   the executable file might be covered by the GNU General Public
+   License.
+
+   If you submit changes to SANE to the maintainers to be included in
+   a subsequent release, you agree by submitting the changes that
+   those changes may be distributed with this exception intact.
+
+   If you write modifications of your own for SANE, it is your choice
+   whether to permit this exception to apply to your modifications.
+   If you do not wish that, delete this exception notice.  */
+
+/**
+ **	ImageCanvas.java - A canvas that displays an image.
+ **
+ **	Written: 11/4/97 - JSF
+ **/
+
+import java.awt.Canvas;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.image.ImageProducer;
+
+/*
+ *	Here's a canvas that just shows an image.
+ */
+
+public class ImageCanvas extends Canvas
+    {
+    Image image = null;			// The image to display.
+    ImageCanvasClient client = null;	// 1 client for now.
+
+	/*
+	 *	Create with empty image.
+	 */
+    ImageCanvas()
+	{
+	}
+
+	/*
+	 *	Create image from an image producer.
+	 */
+    void setImage(ImageProducer iprod, ImageCanvasClient c)
+	{
+	client = c;
+	image = createImage(iprod);
+	repaint();
+	}
+
+	/*
+	 *	Paint.
+	 */
+    public void paint(Graphics g)
+	{
+	System.out.println("In ImageCanvas.paint()");
+	Dimension dim = getSize();
+	g.drawRect(0, 0, dim.width - 1, dim.height - 1);
+	if (image != null)
+		{
+		g.drawImage(image, 1, 1, dim.width - 2, dim.height - 2, this);
+		}
+	}
+
+	/*
+	 *	Image has been updated.
+	 */
+    public boolean imageUpdate(Image theimg, int infoflags,
+				int x, int y, int w, int h)
+	{
+	System.out.println("In imageUpdate()");
+	boolean done = ((infoflags & (ERROR | FRAMEBITS | ALLBITS)) != 0);
+//	repaint();
+	paint(getGraphics());
+	if (done && client != null)	// Tell client when done.
+		{
+		client.imageDone((infoflags & ERROR) != 0);
+		client = null;
+		}
+	return (!done);
+	}
+    }
diff --git a/japi/ImageCanvasClient.java b/japi/ImageCanvasClient.java
new file mode 100644
index 0000000..f9caebe
--- /dev/null
+++ b/japi/ImageCanvasClient.java
@@ -0,0 +1,54 @@
+/* sane - Scanner Access Now Easy.
+   Copyright (C) 1997 Jeffrey S. Freedman
+   This file is part of the SANE package.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+   As a special exception, the authors of SANE give permission for
+   additional uses of the libraries contained in this release of SANE.
+
+   The exception is that, if you link a SANE library with other files
+   to produce an executable, this does not by itself cause the
+   resulting executable to be covered by the GNU General Public
+   License.  Your use of that executable is in no way restricted on
+   account of linking the SANE library code into it.
+
+   This exception does not, however, invalidate any other reasons why
+   the executable file might be covered by the GNU General Public
+   License.
+
+   If you submit changes to SANE to the maintainers to be included in
+   a subsequent release, you agree by submitting the changes that
+   those changes may be distributed with this exception intact.
+
+   If you write modifications of your own for SANE, it is your choice
+   whether to permit this exception to apply to your modifications.
+   If you do not wish that, delete this exception notice.  */
+
+/**
+ **	ImageCanvasClient.java - A client of the canvas that displays an image.
+ **
+ **	Written: 11/20/97 - JSF
+ **/
+
+/*
+ *	This interface lets its owner know when an image canvas is through
+ *	being painted.
+ */
+interface ImageCanvasClient
+    {
+    void imageDone(boolean failed);	// Image is complete.
+    }
diff --git a/japi/Jscanimage.java b/japi/Jscanimage.java
new file mode 100644
index 0000000..d3ab32d
--- /dev/null
+++ b/japi/Jscanimage.java
@@ -0,0 +1,1166 @@
+/* sane - Scanner Access Now Easy.
+   Copyright (C) 1997 Jeffrey S. Freedman
+   This file is part of the SANE package.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+   As a special exception, the authors of SANE give permission for
+   additional uses of the libraries contained in this release of SANE.
+
+   The exception is that, if you link a SANE library with other files
+   to produce an executable, this does not by itself cause the
+   resulting executable to be covered by the GNU General Public
+   License.  Your use of that executable is in no way restricted on
+   account of linking the SANE library code into it.
+
+   This exception does not, however, invalidate any other reasons why
+   the executable file might be covered by the GNU General Public
+   License.
+
+   If you submit changes to SANE to the maintainers to be included in
+   a subsequent release, you agree by submitting the changes that
+   those changes may be distributed with this exception intact.
+
+   If you write modifications of your own for SANE, it is your choice
+   whether to permit this exception to apply to your modifications.
+   If you do not wish that, delete this exception notice.  */
+
+/**
+ **	Jscanimage.java - Java scanner program using SANE.
+ **
+ **	Written: 10/31/97 - JSF
+ **/
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import java.awt.image.ImageConsumer;
+import java.awt.image.ColorModel;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.text.NumberFormat;
+import javax.swing.*;
+import javax.swing.border.*;
+import javax.swing.event.*;
+
+/*
+ *	Main program.
+ */
+public class Jscanimage extends Frame implements WindowListener,
+			ActionListener, ItemListener, ImageCanvasClient
+    {
+    //
+    //	Static data.
+    //
+    private static Sane sane;		// The main class.
+    private static SaneDevice devList[];// List of devices.
+    //
+    //	Instance data.
+    //
+    private Font font;			// For dialog items.
+    private int saneHandle;		// Handle of open device.
+    private ScanIt scanIt = null;	// Does the actual scan.
+					// File to output to.
+    private FileOutputStream outFile = null;
+    private String outDir = null;	// Stores dir. for output dialog.
+    private Vector controls;		// Dialog components for SANE controls.
+    private double unitLength = 1;	// # of mm for units to display
+					//    (mm = 1, cm = 10, in = 25.4).
+    private ImageCanvas imageDisplay = null;
+					// "Scan", "Preview" buttons.
+    private JButton scanButton, previewButton;
+    private JButton browseButton;	// For choosing output filename.
+    private JTextField outputField;	// Field for output filename.
+    private MenuItem exitMenuItem;	// Menu items.
+    private CheckboxMenuItem toolTipsMenuItem;
+    private CheckboxMenuItem mmMenuItem;
+    private CheckboxMenuItem cmMenuItem;
+    private CheckboxMenuItem inMenuItem;
+
+	/*
+	 *	Main program.
+	 */
+    public static void main(String args[])
+	{
+	if (!initSane())		// Initialize SANE.
+		return;
+	Jscanimage prog = new Jscanimage();
+	prog.pack();
+	prog.show();
+	}
+
+	/*
+	 *	Create main window.
+	 */
+    public Jscanimage()
+	{
+	super("SANE Scanimage");
+	addWindowListener(this);
+					// Open SANE device.
+	saneHandle = initSaneDevice(devList[0].name);
+	if (saneHandle == 0)
+		System.exit(-1);
+					// Create scanner class.
+	scanIt = new ScanIt(sane, saneHandle);
+	init();
+	}
+
+	/*
+	 *	Clean up.
+	 */
+    public void finalize()
+	{
+	if (sane != null)
+		{
+		if (saneHandle != 0)
+			sane.close(saneHandle);
+		sane.exit();
+		sane = null;
+		}
+	saneHandle = 0;
+	if (outFile != null)
+		{
+		try
+			{
+			outFile.close();
+			}
+		catch (IOException e)
+			{ }
+		outFile = null;
+		}
+	System.out.println("In finalize()");
+	}
+
+	/*
+	 *	Return info.
+	 */
+    public Sane getSane()
+	{ return sane; }
+    public int getSaneHandle()
+	{ return saneHandle; }
+    public double getUnitLength()
+	{ return unitLength; }
+
+	/*
+	 *	Initialize SANE.
+	 */
+    private static boolean initSane()
+	{
+	sane = new Sane();
+	int version[] = new int[1];	// Array to get version #.
+	int status = sane.init(version);
+	if (status != Sane.STATUS_GOOD)
+		{
+		System.out.println("getDevices() failed.  Status= " + status);
+		return (false);
+		}
+					// Get list of devices.
+					// Allocate room for 50.
+	devList = new SaneDevice[50];
+	status = sane.getDevices(devList, false);
+	if (status != Sane.STATUS_GOOD)
+		{
+		System.out.println("getDevices() failed.  Status= " + status);
+		return (false);
+		}
+	for (int i = 0; i < 50 && devList[i] != null; i++)
+		{
+		System.out.println("Device '" + devList[i].name + "' is a " +
+			devList[i].vendor + " " + devList[i].model + " " +
+			devList[i].type);
+		}
+	return (true);
+	}
+
+	/*
+	 *	Open device.
+	 *
+	 *	Output:	Handle, or 0 if error.
+	 */
+    private int initSaneDevice(String name)
+	{
+	int handle[] = new int[1];
+					// Open 1st device, for now.
+	int status = sane.open(name, handle);
+	if (status != Sane.STATUS_GOOD)
+		{
+		System.out.println("open() failed.  Status= " + status);
+		return (0);
+		}
+	setTitle("SANE - " + name);
+	System.out.println("Open handle=" + handle[0]);
+	return (handle[0]);
+	}
+
+	/*
+	 *	Add a labeled option to the main dialog.
+	 */
+    private void addLabeledOption(JPanel group, String title, Component opt,
+						GridBagConstraints c)
+	{
+	JLabel label = new JLabel(title);
+	c.gridwidth = GridBagConstraints.RELATIVE;
+	c.fill = GridBagConstraints.NONE;
+	c.anchor = GridBagConstraints.WEST;
+	c.weightx = .1;
+	group.add(label, c);
+	c.gridwidth = GridBagConstraints.REMAINDER;
+	c.fill = GridBagConstraints.HORIZONTAL;
+	c.weightx = .4;
+	group.add(opt, c);
+	}
+
+	/*
+	 *	Get options for device.
+	 */
+    private boolean initSaneOptions()
+	{
+	JPanel group = null;
+	GridBagConstraints c = new GridBagConstraints();
+	c.weightx = .4;
+	c.weighty = .4;
+					// Get # of device options.
+	int numDevOptions[] = new int[1];
+	int status = sane.getControlOption(saneHandle, 0, numDevOptions, null);
+	if (status != Sane.STATUS_GOOD)
+		{
+		System.out.println("controlOption() failed.  Status= " 
+								+ status);
+		return (false);
+		}
+	System.out.println("Number of device options=" + numDevOptions[0]);
+					// Do each option.
+	for (int i = 0; i < numDevOptions[0]; i++)
+		{
+		SaneOption opt = sane.getOptionDescriptor(saneHandle, i);
+		if (opt == null)
+			{
+			System.out.println("getOptionDescriptor() failed for "
+						+ i);
+			continue;
+			}
+/*
+		System.out.println("Option title: " + opt.title);
+		System.out.println("Option desc:  " + opt.desc);
+		System.out.println("Option type:  " + opt.type);
+ */
+		String title;		// Set up title.
+		if (opt.unit == SaneOption.UNIT_NONE)
+			title = opt.title;
+		else			// Show units.
+			title = opt.title + " [" + 
+					opt.unitString(unitLength) + ']';
+		switch (opt.type)
+			{
+		case SaneOption.TYPE_GROUP:
+					// Group for a set of options.
+			group = new JPanel(new GridBagLayout());
+			c.gridwidth = GridBagConstraints.REMAINDER;
+			c.fill = GridBagConstraints.BOTH;
+			c.anchor = GridBagConstraints.CENTER;
+			add(group, c);
+			group.setBorder(new TitledBorder(title));
+			break;
+		case SaneOption.TYPE_BOOL:
+					// A checkbox.
+			SaneCheckBox cbox = new SaneCheckBox(opt.title,
+						this, i, opt.desc);
+			c.gridwidth = GridBagConstraints.REMAINDER;
+			c.fill = GridBagConstraints.NONE;
+			c.anchor = GridBagConstraints.WEST;
+			if (group != null)
+				group.add(cbox, c);
+			addControl(cbox);
+			break;
+		case SaneOption.TYPE_FIXED:
+					// Fixed-point value.
+			if (opt.size != 4)
+				break;	// Not sure about this.
+			switch (opt.constraintType)
+				{
+			case SaneOption.CONSTRAINT_RANGE:
+					// A scale.
+				SaneSlider slider = new FixedSaneSlider(
+						opt.rangeConstraint.min, 
+						opt.rangeConstraint.max,
+						opt.unit == SaneOption.UNIT_MM,
+						this, i, opt.desc);
+				addLabeledOption(group, title, slider, c);
+				addControl(slider);
+				break;
+			case SaneOption.CONSTRAINT_WORD_LIST:
+					// Select from a list.
+				SaneFixedBox list = new SaneFixedBox(
+							this, i, opt.desc);
+				addLabeledOption(group, title, list, c);
+				addControl(list);
+				break;
+				}
+			break;
+		case SaneOption.TYPE_INT:
+					// Integer value.
+			if (opt.size != 4)
+				break;	// Not sure about this.
+			switch (opt.constraintType)
+				{
+			case SaneOption.CONSTRAINT_RANGE:
+					// A scale.
+				SaneSlider slider = new SaneSlider(
+						opt.rangeConstraint.min, 
+						opt.rangeConstraint.max,
+						this, i, opt.desc);
+				addLabeledOption(group, title, slider, c);
+				addControl(slider);
+				break;
+			case SaneOption.CONSTRAINT_WORD_LIST:
+					// Select from a list.
+				SaneIntBox list = new SaneIntBox(
+							this, i, opt.desc);
+				addLabeledOption(group, title, list, c);
+				addControl(list);
+				break;
+				}
+			break;
+		case SaneOption.TYPE_STRING:
+					// Text entry or choice box.
+			switch (opt.constraintType)
+				{
+			case SaneOption.CONSTRAINT_STRING_LIST:
+					// Make a list.
+				SaneStringBox list = new SaneStringBox(
+							this, i, opt.desc);
+				addLabeledOption(group, title, list, c);
+				addControl(list);
+				break;
+			case SaneOption.CONSTRAINT_NONE:
+				SaneTextField tfield = new SaneTextField(16, 
+							this, i, opt.desc);
+				addLabeledOption(group, title, tfield, c);
+				addControl(tfield);
+				break;
+				}
+			break;
+		case SaneOption.TYPE_BUTTON:
+			c.gridwidth = GridBagConstraints.REMAINDER;
+			c.fill = GridBagConstraints.HORIZONTAL;
+			c.anchor = GridBagConstraints.CENTER;
+			c.insets = new Insets(8, 4, 4, 4);
+			JButton btn = new SaneButton(title, this, i, opt.desc);
+			group.add(btn, c);
+			c.insets = null;
+			break;
+		default:
+			break;
+			}
+		}
+	return (true);
+	}
+
+	/*
+	 *	Set up "Output" panel.
+	 */
+    private JPanel initOutputPanel()
+	{
+	JPanel panel = new JPanel(new GridBagLayout());
+	GridBagConstraints c = new GridBagConstraints();
+					// Want 1 row.
+	c.gridx = GridBagConstraints.RELATIVE;
+	c.gridy = 0;
+	c.anchor = GridBagConstraints.WEST;
+//	c.fill = GridBagConstraints.HORIZONTAL;
+	c.weightx = .4;
+	c.weighty = .4;
+	panel.setBorder(new TitledBorder("Output"));
+	panel.add(new Label("Filename"), c);
+	outputField = new JTextField("out.pnm", 16);
+	panel.add(outputField, c);
+	c.insets = new Insets(0, 8, 0, 0);
+	browseButton = new JButton("Browse");
+	browseButton.addActionListener(this);
+	panel.add(browseButton, c);
+	return (panel);
+	}
+
+	/*
+	 *	Initialize main window.
+	 */
+    private void init()
+	{
+	controls = new Vector();	// List of SaneComponent's.
+					// Try a light blue:
+	setBackground(new Color(140, 200, 255));
+					// And a larger font.
+	font = new Font("Helvetica", Font.PLAIN, 12);
+	setFont(font);
+	initMenu();
+					// Main panel will be 1 column.
+	setLayout(new GridBagLayout());
+	GridBagConstraints c = new GridBagConstraints();
+	c.gridwidth = GridBagConstraints.REMAINDER;
+	c.fill = GridBagConstraints.BOTH;
+	c.weightx = .4;
+	c.weighty = .4;
+					// Panel for output:
+	JPanel outputPanel = initOutputPanel();
+	add(outputPanel, c);
+	initSaneOptions();		// Get SANE options, set up dialog.
+	initButtons();			// Put buttons at bottom.
+	}
+
+	/*
+	 *	Add a control to the dialog and set its initial value.
+	 */
+    private void addControl(SaneComponent comp)
+	{
+	controls.addElement(comp);
+	comp.setFromControl();		// Get initial value.
+	}
+
+	/*
+	 *	Reinitialize components from SANE controls.
+	 */
+    private void reinit()
+	{
+	Enumeration ctrls = controls.elements();
+	while (ctrls.hasMoreElements())	// Do each control.
+		{
+		SaneComponent comp = (SaneComponent) ctrls.nextElement();
+		comp.setFromControl();
+		}
+	}
+
+	/*
+	 *	Set up the menubar.
+	 */
+    private void initMenu()
+	{
+	MenuBar mbar = new MenuBar();
+	Menu file = new Menu("File");
+	mbar.add(file);
+	exitMenuItem = new MenuItem("Exit");
+	exitMenuItem.addActionListener(this);
+	file.add(exitMenuItem);
+	Menu pref = new Menu("Preferences");
+	mbar.add(pref);
+	toolTipsMenuItem = new CheckboxMenuItem("Show tooltips", true);
+	toolTipsMenuItem.addItemListener(this);
+	pref.add(toolTipsMenuItem);
+	Menu units = new Menu("Length unit");
+	pref.add(units);
+	mmMenuItem = new CheckboxMenuItem("millimeters", true);
+	mmMenuItem.addItemListener(this);
+	units.add(mmMenuItem);
+	cmMenuItem = new CheckboxMenuItem("centimeters", false);
+	cmMenuItem.addItemListener(this);
+	units.add(cmMenuItem);
+	inMenuItem = new CheckboxMenuItem("inches", false);
+	inMenuItem.addItemListener(this);
+	units.add(inMenuItem);
+	setMenuBar(mbar);
+	}
+
+	/*
+	 *	Set up buttons panel at very bottom.
+	 */
+    private void initButtons()
+	{
+					// Buttons are at bottom.
+	JPanel bottomPanel = new JPanel(new GridBagLayout());
+					// Indent around buttons.
+	GridBagConstraints c = new GridBagConstraints();
+	c.gridwidth = GridBagConstraints.REMAINDER;
+	c.insets = new Insets(8, 8, 8, 8);
+	c.weightx = .4;
+	c.weighty = .2;
+	c.fill = GridBagConstraints.HORIZONTAL;
+	add(bottomPanel, c);
+	c.weighty = c.weightx = .4;
+	c.fill = GridBagConstraints.BOTH;
+	c.gridwidth = c.gridheight = 1;
+					// Create image display box.
+	imageDisplay = new ImageCanvas();
+	bottomPanel.add(imageDisplay, c);
+					// Put btns. to right in 1 column.
+	JPanel buttonsPanel = new JPanel(new GridLayout(0, 1, 8, 8));
+	bottomPanel.add(buttonsPanel, c);
+	scanButton = new JButton("Scan");
+	buttonsPanel.add(scanButton);
+	scanButton.addActionListener(this);
+	previewButton = new JButton("Preview Window");
+	buttonsPanel.add(previewButton);
+	previewButton.addActionListener(this);
+	}
+
+	/*
+	 *	Set a SANE integer option.
+	 */
+    public void setControlOption(int optNum, int val)
+	{
+	int [] info = new int[1];
+	if (sane.setControlOption(saneHandle, optNum, 
+			SaneOption.ACTION_SET_VALUE, val, info) 
+							!= Sane.STATUS_GOOD)
+		System.out.println("setControlOption() failed.");
+	checkOptionInfo(info[0]);
+	}
+
+	/*
+	 *	Set a SANE text option.
+	 */
+    public void setControlOption(int optNum, String val)
+	{
+	int [] info = new int[1];
+	if (sane.setControlOption(saneHandle, optNum, 
+			SaneOption.ACTION_SET_VALUE, val, info) 
+							!= Sane.STATUS_GOOD)
+		System.out.println("setControlOption() failed.");
+	checkOptionInfo(info[0]);
+	}
+
+	/*
+	 *	Check the 'info' word returned from setControlOption().
+	 */
+    private void checkOptionInfo(int info)
+	{
+					// Does everything completely change?
+	if ((info & SaneOption.INFO_RELOAD_OPTIONS) != 0)
+		reinit();
+					// Need to update status line?
+	if ((info & SaneOption.INFO_RELOAD_PARAMS) != 0)
+		;			// ++++++++FILL IN.
+	}
+
+	/*
+	 *	Handle a user action.
+	 */
+    public void actionPerformed(ActionEvent e)
+	{
+	if (e.getSource() == scanButton)
+		{
+		System.out.println("Rescanning");
+					// Get file name.
+		String fname = outputField.getText();
+		if (fname == null || fname.length() == 0)
+			fname = "out.pnm";
+		try
+			{
+			outFile = new FileOutputStream(fname);
+			}
+		catch (IOException oe)
+			{
+			System.out.println("Error creating file:  " + fname);
+			outFile = null;
+			return;
+			}
+					// Disable "Scan" button.
+		scanButton.setEnabled(false);
+		scanIt.setOutputFile(outFile);
+		imageDisplay.setImage(scanIt, this);
+		}
+	else if (e.getSource() == browseButton)
+		{
+		File file;		// For working with names.
+		FileDialog dlg = new FileDialog(this, "Output Filename",
+						FileDialog.SAVE);
+		if (outDir != null)	// Set to last directory.
+			dlg.setDirectory(outDir);
+					// Get current name.
+		String fname = outputField.getText();
+		if (fname != null)
+			{
+			file = new File(fname);
+			dlg.setFile(file.getName());
+			String dname = file.getParent();
+			if (dname != null)
+				dlg.setDirectory(outDir);
+			}
+		dlg.show();		// Wait for result.
+		fname = dlg.getFile();
+					// Store dir. for next time.
+		outDir = dlg.getDirectory();
+		if (fname != null)
+			{
+			file = new File(outDir, fname);
+			String curDir;
+			String fullName;
+			try
+				{
+				curDir = (new File(".")).getCanonicalPath();
+				fullName = file.getCanonicalPath();
+					// Not in current directory?
+				if (!curDir.equals(
+					(new File(fullName)).getParent()))
+					fname = fullName;
+				}
+			catch (IOException ex)
+				{ curDir = "."; fname = file.getName(); }
+			outputField.setText(fname);
+			}
+		}
+	else if (e.getSource() == exitMenuItem)
+		{
+		finalize();		// Just to be safe.
+		System.exit(0);
+		}
+	}
+
+	/*
+	 *	Handle checkable menu items.
+	 */
+    public void itemStateChanged(ItemEvent e)
+	{
+	if (e.getSource() == mmMenuItem)
+		{			// Wants mm.
+		unitLength = 1;
+		if (e.getStateChange() == ItemEvent.SELECTED)
+			{
+			cmMenuItem.setState(false);
+			inMenuItem.setState(false);
+			reinit();	// Re-display controls.
+			}
+		else			// Don't let him deselect.
+			mmMenuItem.setState(true);
+		}
+	if (e.getSource() == cmMenuItem)
+		{			// Wants cm.
+		unitLength = 10;
+		if (e.getStateChange() == ItemEvent.SELECTED)
+			{
+			mmMenuItem.setState(false);
+			inMenuItem.setState(false);
+			reinit();	// Re-display controls.
+			}
+		else
+			cmMenuItem.setState(true);
+		}
+	if (e.getSource() == inMenuItem)
+		{			// Wants inches.
+		unitLength = 25.4;
+		if (e.getStateChange() == ItemEvent.SELECTED)
+			{
+			mmMenuItem.setState(false);
+			cmMenuItem.setState(false);
+			reinit();	// Re-display controls.
+			}
+		else			// Don't let him deselect.
+			inMenuItem.setState(true);
+		}
+	}
+
+	/*
+	 *	Scan is complete.
+	 */
+    public void imageDone(boolean error)
+	{
+	if (error)
+		System.out.println("Scanning error.");
+	if (outFile != null)		// Close file.
+		try
+			{
+			outFile.close();
+			}
+		catch (IOException e)
+			{ }
+	scanButton.setEnabled(true);	// Can scan again.
+	}
+
+	/*
+	 *	Default window event handlers.
+	 */
+    public void windowClosed(WindowEvent event)
+	{
+	finalize();			// Just to be safe.
+	}
+    public void windowDeiconified(WindowEvent event) { }
+    public void windowIconified(WindowEvent event) { }
+    public void windowActivated(WindowEvent event) { }
+    public void windowDeactivated(WindowEvent event) { }
+    public void windowOpened(WindowEvent event) { }
+					// Handle closing event.
+    public void windowClosing(WindowEvent event)
+	{
+	finalize();			// Just to be safe.
+	System.exit(0);
+	}
+    }
+
+/*
+ *	Interface for our dialog controls.
+ */
+interface SaneComponent
+    {
+    public void setFromControl();	// Ask SANE control for current value.
+    }
+
+/*
+ *	A checkbox in our dialog.
+ */
+class SaneCheckBox extends JCheckBox implements ActionListener,
+					SaneComponent
+    {
+    private Jscanimage dialog;		// That which created us.
+    private int optNum;			// Option #.
+
+	/*
+	 *	Create with given state.
+	 */
+    public SaneCheckBox(String title, Jscanimage dlg, int opt, String tip)
+	{
+	super(title, false);
+	dialog = dlg;
+	optNum = opt;
+					// Set tool tip.
+	if (tip != null && tip.length() != 0)
+		super.setToolTipText(tip);
+	addActionListener(this);	// Listen to ourself.
+	}
+
+	/*
+	 *	Update Sane device option with current setting.
+	 */
+    public void actionPerformed(ActionEvent e)
+	{
+	System.out.println("In SaneCheckBox::actionPerformed()");
+	int val = isSelected() ? 1 : 0;
+	dialog.setControlOption(optNum, val);
+	}
+
+	/*
+	 *	Update from Sane control's value.
+	 */
+    public void setFromControl()
+	{
+	int [] val = new int[1];
+	if (dialog.getSane().getControlOption(
+			dialog.getSaneHandle(), optNum, val, null)
+						== Sane.STATUS_GOOD)
+		setSelected(val[0] != 0);
+	}
+    }
+
+/*
+ *	A slider in our dialog.  This base class handles integer ranges.
+ *	It consists of a slider and a label which shows the current value.
+ */
+class SaneSlider extends JPanel implements SaneComponent, ChangeListener
+    {
+    protected Jscanimage dialog;	// That which created us.
+    protected int optNum;		// Option #.
+    protected JSlider slider;		// The slider itself.
+    protected JLabel label;		// Shows current value.
+
+	/*
+	 *	Create with given state.
+	 */
+    public SaneSlider(int min, int max, Jscanimage dlg, int opt, String tip)
+	{
+	super(new GridBagLayout());	// Create panel.
+	dialog = dlg;
+	optNum = opt;
+	GridBagConstraints c = new GridBagConstraints();
+					// Want 1 row.
+	c.gridx = GridBagConstraints.RELATIVE;
+	c.gridy = 0;
+	c.anchor = GridBagConstraints.CENTER;
+	c.fill = GridBagConstraints.HORIZONTAL;
+	c.weighty = .8;
+	c.weightx = .2;			// Give less weight to value label.
+	label = new JLabel("00", SwingConstants.RIGHT);
+	add(label, c);
+	c.weightx = .8;			// Give most weight to slider.
+	c.fill = GridBagConstraints.HORIZONTAL;
+	slider = new JSlider(JSlider.HORIZONTAL, min, max, 
+							min + (max - min)/2);
+	add(slider, c);
+					// Set tool tip.
+	if (tip != null && tip.length() != 0)
+		super.setToolTipText(tip);
+	slider.addChangeListener(this);	// Listen to ourself.
+	}
+
+	/*
+	 *	Update Sane device option.
+	 */
+    public void stateChanged(ChangeEvent e)
+	{
+	int val = slider.getValue();
+	label.setText(String.valueOf(val));
+	dialog.setControlOption(optNum, val);
+	}
+
+	/*
+	 *	Update from Sane control's value.
+	 */
+    public void setFromControl()
+	{
+	int [] val = new int[1];	// Get current SANE control value.
+	if (dialog.getSane().getControlOption(
+			dialog.getSaneHandle(), optNum, val, null)
+						== Sane.STATUS_GOOD)
+		{
+		slider.setValue(val[0]);
+		label.setText(String.valueOf(val[0]));
+		}
+	}
+    }
+
+/*
+ *	A slider with fixed-point values:
+ */
+class FixedSaneSlider extends SaneSlider
+    {
+    private static final int SCALE_MIN = -32000;
+    private static final int SCALE_MAX = 32000;
+    double min, max;			// Min, max in floating-point.
+    boolean optMM;			// Option is in millimeters, so should
+					//   be scaled to user's pref.
+    private NumberFormat format;	// For printing label.
+	/*
+	 *	Create with given fixed-point range.
+	 */
+    public FixedSaneSlider(int fixed_min, int fixed_max, boolean mm,
+					Jscanimage dlg, int opt, String tip)
+	{
+					// Create with large integer range.
+	super(SCALE_MIN, SCALE_MAX, dlg, opt, tip);
+	format = NumberFormat.getInstance();
+					// For now, show 1 decimal point.
+	format.setMinimumFractionDigits(1);
+	format.setMaximumFractionDigits(1);
+					// Store actual range.
+	min = dlg.getSane().unfix(fixed_min);
+	max = dlg.getSane().unfix(fixed_max);
+	optMM = mm;
+	}
+
+	/*
+	 *	Update Sane device option.
+	 */
+    public void stateChanged(ChangeEvent e)
+	{
+	double val = (double) slider.getValue();
+					// Convert to actual control scale.
+	val = min + ((val - SCALE_MIN)/(SCALE_MAX - SCALE_MIN)) * (max - min);
+	label.setText(format.format(optMM ? 
+					val/dialog.getUnitLength() : val));
+	dialog.setControlOption(optNum, dialog.getSane().fix(val));
+	}
+
+	/*
+	 *	Update from Sane control's value.
+	 */
+    public void setFromControl()
+	{
+	int [] ival = new int[1];	// Get current SANE control value.
+	if (dialog.getSane().getControlOption(
+			dialog.getSaneHandle(), optNum, ival, null)
+						== Sane.STATUS_GOOD)
+		{
+		double val = dialog.getSane().unfix(ival[0]);
+					// Show value with user's pref.
+		label.setText(format.format(optMM ? 
+					val/dialog.getUnitLength() : val));
+		val = SCALE_MIN + ((val - min)/(max - min)) * 
+						(SCALE_MAX - SCALE_MIN);
+		slider.setValue((int) val);
+		}
+	}
+    }
+
+/*
+ *	A Button in our dialog.
+ */
+class SaneButton extends JButton implements ActionListener
+    {
+    private Jscanimage dialog;		// That which created us.
+    private int optNum;			// Option #.
+
+	/*
+	 *	Create with given state.
+	 */
+    public SaneButton(String title, Jscanimage dlg, int opt, String tip)
+	{
+	super(title);
+	dialog = dlg;
+	optNum = opt;
+					// Set tool tip.
+	if (tip != null && tip.length() != 0)
+		super.setToolTipText(tip);
+	addActionListener(this);	// Listen to ourself.
+	}
+
+	/*
+	 *	Update Sane device option.
+	 */
+    public void actionPerformed(ActionEvent e)
+	{
+	dialog.setControlOption(optNum, 0);
+	System.out.println("In SaneButton::actionPerformed()");
+	}
+    }
+
+/*
+ *	A combo-box for showing a list of items.
+ */
+abstract class SaneComboBox extends JComboBox 
+				implements SaneComponent, ItemListener
+    {
+    protected Jscanimage dialog;	// That which created us.
+    protected int optNum;		// Option #.
+
+	/*
+	 *	Create it.
+	 */
+    public SaneComboBox(Jscanimage dlg, int opt, String tip)
+	{
+	dialog = dlg;
+	optNum = opt;
+					// Set tool tip.
+	if (tip != null && tip.length() != 0)
+		super.setToolTipText(tip);
+	addItemListener(this);
+	}
+
+	/*
+	 *	Select desired item by its text.
+	 */
+    protected void select(String text)
+	{
+	int cnt = getItemCount();
+	for (int i = 0; i < cnt; i++)
+		if (text.equals(getItemAt(i)))
+			{
+			setSelectedIndex(i);
+			break;
+			}
+	}
+
+    abstract public void setFromControl();
+    abstract public void itemStateChanged(ItemEvent e);
+    }
+
+/*
+ *	A list of strings.
+ */
+class SaneStringBox extends SaneComboBox
+    {
+
+	/*
+	 *	Create it.
+	 */
+    public SaneStringBox(Jscanimage dlg, int opt, String tip)
+	{
+	super(dlg, opt, tip);
+	}
+
+	/*
+	 *	Update from Sane control's value.
+	 */
+    public void setFromControl()
+	{
+					// Let's get the whole list.
+	SaneOption opt = dialog.getSane().getOptionDescriptor(
+					dialog.getSaneHandle(), optNum);
+	if (opt == null)
+		return;
+	removeAllItems();		// Clear list.
+					// Go through list from option.
+	for (int i = 0; opt.stringListConstraint[i] != null; i++)
+		addItem(opt.stringListConstraint[i]);
+					// Get value.
+	byte buf[] = new byte[opt.size + 1];
+	if (dialog.getSane().getControlOption(
+			dialog.getSaneHandle(), optNum, buf, null)
+						== Sane.STATUS_GOOD)
+		select(new String(buf));
+	}
+
+	/*
+	 *	An item was selected.
+	 */
+    public void itemStateChanged(ItemEvent e)
+	{
+				// Get current selection.
+	String val = (String) getSelectedItem();
+	if (val != null)
+		dialog.setControlOption(optNum, val);
+	}
+    }
+
+/*
+ *	A list of integers.
+ */
+class SaneIntBox extends SaneComboBox
+    {
+
+	/*
+	 *	Create it.
+	 */
+    public SaneIntBox(Jscanimage dlg, int opt, String tip)
+	{
+	super(dlg, opt, tip);
+	}
+
+	/*
+	 *	Update from Sane control's value.
+	 */
+    public void setFromControl()
+	{
+					// Let's get the whole list.
+	SaneOption opt = dialog.getSane().getOptionDescriptor(
+					dialog.getSaneHandle(), optNum);
+	if (opt == null)
+		return;
+	removeAllItems();		// Clear list.
+					// Go through list from option.
+	int cnt = opt.wordListConstraint[0];
+	for (int i = 0; i < cnt; i++)
+		addItem(String.valueOf(opt.wordListConstraint[i + 1]));
+					// Get value.
+	int [] val = new int[1];	// Get current SANE control value.
+	if (dialog.getSane().getControlOption(
+			dialog.getSaneHandle(), optNum, val, null)
+						== Sane.STATUS_GOOD)
+		select(String.valueOf(val[0]));
+	}
+
+	/*
+	 *	An item was selected.
+	 */
+    public void itemStateChanged(ItemEvent e)
+	{
+				// Get current selection.
+	String val = (String) getSelectedItem();
+	if (val != null)
+		try
+			{
+			Integer v = Integer.valueOf(val);
+			dialog.setControlOption(optNum, v.intValue());
+			}
+		catch (NumberFormatException ex) {  }
+	}
+    }
+
+/*
+ *	A list of fixed-point floating point numbers.
+ */
+class SaneFixedBox extends SaneComboBox
+    {
+
+	/*
+	 *	Create it.
+	 */
+    public SaneFixedBox(Jscanimage dlg, int opt, String tip)
+	{
+	super(dlg, opt, tip);
+	}
+
+	/*
+	 *	Update from Sane control's value.
+	 */
+    public void setFromControl()
+	{
+					// Let's get the whole list.
+	SaneOption opt = dialog.getSane().getOptionDescriptor(
+					dialog.getSaneHandle(), optNum);
+	if (opt == null)
+		return;
+	removeAllItems();		// Clear list.
+					// Go through list from option.
+	int cnt = opt.wordListConstraint[0];
+	for (int i = 0; i < cnt; i++)
+		addItem(String.valueOf(dialog.getSane().unfix(
+					opt.wordListConstraint[i + 1])));
+					// Get value.
+	int [] val = new int[1];	// Get current SANE control value.
+	if (dialog.getSane().getControlOption(
+			dialog.getSaneHandle(), optNum, val, null)
+						== Sane.STATUS_GOOD)
+		select(String.valueOf(dialog.getSane().unfix(val[0])));
+	}
+
+	/*
+	 *	An item was selected.
+	 */
+    public void itemStateChanged(ItemEvent e)
+	{
+				// Get current selection.
+	String val = (String) getSelectedItem();
+	if (val != null)
+		try
+			{
+			Double v = Double.valueOf(val);
+			dialog.setControlOption(optNum,
+					dialog.getSane().fix(v.doubleValue()));
+			}
+		catch (NumberFormatException ex) {  }
+	}
+    }
+
+/*
+ *	A text-entry field in our dialog.
+ */
+class SaneTextField extends JTextField implements SaneComponent
+    {
+    private Jscanimage dialog;		// That which created us.
+    private int optNum;			// Option #.
+
+	/*
+	 *	Create with given state.
+	 */
+    public SaneTextField(int width, Jscanimage dlg, int opt, String tip)
+	{
+	super(width);			// Set initial text, # chars.
+	dialog = dlg;
+	optNum = opt;
+					// Set tool tip.
+	if (tip != null && tip.length() != 0)
+		super.setToolTipText(tip);
+	}
+
+	/*
+	 *	Update Sane device option with current setting when user types.
+	 */
+    public void processKeyEvent(KeyEvent e)
+	{
+	super.processKeyEvent(e);	// Handle it normally.
+	if (e.getID() != KeyEvent.KEY_TYPED)
+		return;			// Just do it after keystroke.
+	String userText = getText();	// Get what's there, & save copy.
+	String newText = new String(userText);
+	dialog.setControlOption(optNum, newText);
+	if (!newText.equals(userText))	// Backend may have changed it.
+		setText(newText);
+	}
+
+	/*
+	 *	Update from Sane control's value.
+	 */
+    public void setFromControl()
+	{
+	byte buf[] = new byte[1024];
+	if (dialog.getSane().getControlOption(
+			dialog.getSaneHandle(), optNum, buf, null)
+						== Sane.STATUS_GOOD)
+		{
+		String text = new String(buf);
+		System.out.println("SaneTextField::setFromControl: " + text);
+		setText(text);		// Set text in field.
+		setScrollOffset(0);
+		}
+	}
+    }
diff --git a/japi/Makefile.am b/japi/Makefile.am
new file mode 100644
index 0000000..5d66e82
--- /dev/null
+++ b/japi/Makefile.am
@@ -0,0 +1,47 @@
+##  Makefile.am -- an automake template for Makefile.in file
+##  Copyright (C) 2009 Chris Bagwell and Sane Developers.
+##
+##  This file is part of the "Sane" build infra-structure.  See
+##  included LICENSE file for license information.
+
+#
+#	Makefile for a Java project with native methods.
+#
+
+V_MAJOR = @V_MAJOR@
+V_MINOR = @V_MINOR@
+V_REV = @V_REV@
+
+JAVAROOT=.
+CLASSPATH_ENV=.
+JAVAH=javah -jni -cp $(CLASSPATH_ENV)
+
+#	We'll need something in 'configure' for the Java includes.
+AM_CPPFLAGS = -I. -I$(srcdir) -I$(top_builddir)/include \
+	      -I$(top_srcdir)/include -I${JDK_HOME}/include \
+	      -I${JDK_HOME}/include/genunix
+AM_LDFLAGS = @STRICT_LDFLAGS@ -version-number $(V_MAJOR):$(V_MINOR):$(VREV)
+
+JAVA_SRC = SaneDevice.java SaneOption.java SaneRange.java\
+	   Sane.java SaneParameters.java ScanIt.java \
+	   ImageCanvas.java ImageCanvasClient.java \
+	   Test.java Jscanimage.java 
+
+dist_noinst_JAVA = $(JAVA_SRC)
+
+LIBSANE = ../backend/libsane.la
+
+EXTRA_DIST = Makefile.in README.JAVA 
+
+lib_LTLIBRARIES = libsanej.la
+
+BUILT_SOURCES = Sane.h
+CLEANFILES = Sane.h
+nodist_libsanej_la_SOURCES = Sane.h
+libsanej_la_SOURCES = Sane.c
+libsanej_la_LIBADD = $(LIBSANE)
+
+# Make sure that java classes get created before create Sane.h
+Sane.h: classdist_noinst.stamp
+	$(JAVAH) Sane
+
diff --git a/japi/Makefile.in b/japi/Makefile.in
new file mode 100644
index 0000000..550bd8d
--- /dev/null
+++ b/japi/Makefile.in
@@ -0,0 +1,738 @@
+# Makefile.in generated by automake 1.13.4 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+#
+#	Makefile for a Java project with native methods.
+#
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \	]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = japi
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+	$(top_srcdir)/mkinstalldirs $(top_srcdir)/depcomp \
+	$(dist_noinst_JAVA)
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ltoptions.m4 \
+	$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+	$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \
+	$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/byteorder.m4 \
+	$(top_srcdir)/m4/stdint.m4 $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/include/sane/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+  for p in $$list; do echo "$$p $$p"; done | \
+  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+    if (++n[$$2] == $(am__install_max)) \
+      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+    END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+  test -z "$$files" \
+    || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+    || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+         $(am__cd) "$$dir" && rm -f $$files; }; \
+  }
+am__installdirs = "$(DESTDIR)$(libdir)"
+LTLIBRARIES = $(lib_LTLIBRARIES)
+libsanej_la_DEPENDENCIES = $(LIBSANE)
+am_libsanej_la_OBJECTS = Sane.lo
+nodist_libsanej_la_OBJECTS =
+libsanej_la_OBJECTS = $(am_libsanej_la_OBJECTS) \
+	$(nodist_libsanej_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 = 
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 = 
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include/sane
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+	$(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo "  CC      " $@;
+am__v_CC_1 = 
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo "  CCLD    " $@;
+am__v_CCLD_1 = 
+SOURCES = $(libsanej_la_SOURCES) $(nodist_libsanej_la_SOURCES)
+DIST_SOURCES = $(libsanej_la_SOURCES)
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+JAVAC = javac
+am__java_sources = $(dist_noinst_JAVA)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AVAHI_CFLAGS = @AVAHI_CFLAGS@
+AVAHI_LIBS = @AVAHI_LIBS@
+AWK = @AWK@
+BACKENDS = @BACKENDS@
+BACKEND_CONFS_ENABLED = @BACKEND_CONFS_ENABLED@
+BACKEND_LIBS_ENABLED = @BACKEND_LIBS_ENABLED@
+BACKEND_MANS_ENABLED = @BACKEND_MANS_ENABLED@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DISTCLEAN_FILES = @DISTCLEAN_FILES@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+DVIPS = @DVIPS@
+DYNAMIC_FLAG = @DYNAMIC_FLAG@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPHOTO2_CPPFLAGS = @GPHOTO2_CPPFLAGS@
+GPHOTO2_LDFLAGS = @GPHOTO2_LDFLAGS@
+GPHOTO2_LIBS = @GPHOTO2_LIBS@
+GREP = @GREP@
+HAVE_GPHOTO2 = @HAVE_GPHOTO2@
+IEEE1284_LIBS = @IEEE1284_LIBS@
+INCLUDES = @INCLUDES@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_LOCKPATH = @INSTALL_LOCKPATH@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+JPEG_LIBS = @JPEG_LIBS@
+LATEX = @LATEX@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUSB_1_0_CFLAGS = @LIBUSB_1_0_CFLAGS@
+LIBUSB_1_0_LIBS = @LIBUSB_1_0_LIBS@
+LIBV4L_CFLAGS = @LIBV4L_CFLAGS@
+LIBV4L_LIBS = @LIBV4L_LIBS@
+LINKER_RPATH = @LINKER_RPATH@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LOCKPATH_GROUP = @LOCKPATH_GROUP@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINDEX = @MAKEINDEX@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MATH_LIB = @MATH_LIB@
+MKDIR_P = @MKDIR_P@
+MSGFMT = @MSGFMT@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NUMBER_VERSION = @NUMBER_VERSION@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PRELOADABLE_BACKENDS = @PRELOADABLE_BACKENDS@
+PRELOADABLE_BACKENDS_ENABLED = @PRELOADABLE_BACKENDS_ENABLED@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+RESMGR_LIBS = @RESMGR_LIBS@
+SANEI_SANEI_JPEG_LO = @SANEI_SANEI_JPEG_LO@
+SANE_CONFIG_PATH = @SANE_CONFIG_PATH@
+SCSI_LIBS = @SCSI_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CONFIG_PATH = @SNMP_CONFIG_PATH@
+SOCKET_LIBS = @SOCKET_LIBS@
+STRICT_LDFLAGS = @STRICT_LDFLAGS@
+STRIP = @STRIP@
+SYSLOG_LIBS = @SYSLOG_LIBS@
+SYSTEMD_LIBS = @SYSTEMD_LIBS@
+TIFF_LIBS = @TIFF_LIBS@
+USB_LIBS = @USB_LIBS@
+VERSION = @VERSION@
+V_MAJOR = @V_MAJOR@
+V_MINOR = @V_MINOR@
+V_REV = @V_REV@
+XGETTEXT = @XGETTEXT@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+configdir = @configdir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+effective_target = @effective_target@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+locksanedir = @locksanedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+JAVAROOT = .
+CLASSPATH_ENV = .
+JAVAH = javah -jni -cp $(CLASSPATH_ENV)
+
+#	We'll need something in 'configure' for the Java includes.
+AM_CPPFLAGS = -I. -I$(srcdir) -I$(top_builddir)/include \
+	      -I$(top_srcdir)/include -I${JDK_HOME}/include \
+	      -I${JDK_HOME}/include/genunix
+
+AM_LDFLAGS = @STRICT_LDFLAGS@ -version-number $(V_MAJOR):$(V_MINOR):$(VREV)
+JAVA_SRC = SaneDevice.java SaneOption.java SaneRange.java\
+	   Sane.java SaneParameters.java ScanIt.java \
+	   ImageCanvas.java ImageCanvasClient.java \
+	   Test.java Jscanimage.java 
+
+dist_noinst_JAVA = $(JAVA_SRC)
+LIBSANE = ../backend/libsane.la
+EXTRA_DIST = Makefile.in README.JAVA 
+lib_LTLIBRARIES = libsanej.la
+BUILT_SOURCES = Sane.h
+CLEANFILES = Sane.h
+nodist_libsanej_la_SOURCES = Sane.h
+libsanej_la_SOURCES = Sane.c
+libsanej_la_LIBADD = $(LIBSANE)
+all: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu japi/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu japi/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+	@$(NORMAL_INSTALL)
+	@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+	list2=; for p in $$list; do \
+	  if test -f $$p; then \
+	    list2="$$list2 $$p"; \
+	  else :; fi; \
+	done; \
+	test -z "$$list2" || { \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \
+	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
+	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
+	}
+
+uninstall-libLTLIBRARIES:
+	@$(NORMAL_UNINSTALL)
+	@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+	for p in $$list; do \
+	  $(am__strip_dir) \
+	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
+	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
+	done
+
+clean-libLTLIBRARIES:
+	-test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+	@list='$(lib_LTLIBRARIES)'; \
+	locs=`for p in $$list; do echo $$p; done | \
+	      sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+	      sort -u`; \
+	test -z "$$locs" || { \
+	  echo rm -f $${locs}; \
+	  rm -f $${locs}; \
+	}
+
+libsanej.la: $(libsanej_la_OBJECTS) $(libsanej_la_DEPENDENCIES) $(EXTRA_libsanej_la_DEPENDENCIES) 
+	$(AM_V_CCLD)$(LINK) -rpath $(libdir) $(libsanej_la_OBJECTS) $(libsanej_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Sane.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+classnoinst.stamp: $(am__java_sources)
+	@list1='$?'; list2=; if test -n "$$list1"; then \
+	  for p in $$list1; do \
+	    if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+	    list2="$$list2 $$d$$p"; \
+	  done; \
+	  echo '$(CLASSPATH_ENV) $(JAVAC) -d $(JAVAROOT) $(AM_JAVACFLAGS) $(JAVACFLAGS) '"$$list2"; \
+	  $(CLASSPATH_ENV) $(JAVAC) -d $(JAVAROOT) $(AM_JAVACFLAGS) $(JAVACFLAGS) $$list2; \
+	else :; fi
+	echo timestamp > $@
+
+clean-noinstJAVA:
+	-rm -f *.class classnoinst.stamp
+
+ID: $(am__tagged_files)
+	$(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	set x; \
+	here=`pwd`; \
+	$(am__define_uniq_tagged_files); \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	$(am__define_uniq_tagged_files); \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+	list='$(am__tagged_files)'; \
+	case "$(srcdir)" in \
+	  [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+	  *) sdir=$(subdir)/$(srcdir) ;; \
+	esac; \
+	for i in $$list; do \
+	  if test -f "$$i"; then \
+	    echo "$(subdir)/$$i"; \
+	  else \
+	    echo "$$sdir/$$i"; \
+	  fi; \
+	done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+	  else \
+	    test -f "$(distdir)/$$file" \
+	    || cp -p $$d/$$file "$(distdir)/$$file" \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) check-am
+all-am: Makefile $(LTLIBRARIES) classnoinst.stamp
+installdirs:
+	for dir in "$(DESTDIR)$(libdir)"; do \
+	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+	done
+install: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	if test -z '$(STRIP)'; then \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	      install; \
+	else \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+	fi
+mostlyclean-generic:
+
+clean-generic:
+	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+	-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+	clean-noinstJAVA mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-libLTLIBRARIES
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-libLTLIBRARIES
+
+.MAKE: all check install install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+	clean-libLTLIBRARIES clean-libtool clean-noinstJAVA \
+	cscopelist-am ctags ctags-am distclean distclean-compile \
+	distclean-generic distclean-libtool distclean-tags distdir dvi \
+	dvi-am html html-am info info-am install install-am \
+	install-data install-data-am install-dvi install-dvi-am \
+	install-exec install-exec-am install-html install-html-am \
+	install-info install-info-am install-libLTLIBRARIES \
+	install-man install-pdf install-pdf-am install-ps \
+	install-ps-am install-strip installcheck installcheck-am \
+	installdirs maintainer-clean maintainer-clean-generic \
+	mostlyclean mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
+	uninstall-am uninstall-libLTLIBRARIES
+
+
+# Make sure that java classes get created before create Sane.h
+Sane.h: classdist_noinst.stamp
+	$(JAVAH) Sane
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/japi/README.JAVA b/japi/README.JAVA
new file mode 100644
index 0000000..4c838f4
--- /dev/null
+++ b/japi/README.JAVA
@@ -0,0 +1,55 @@
+--
+12/17/97
+
+Most of Jscanimage's main dialog is coded, but only tested with PNM (which
+means most of the newly supported option types haven't been tried yet).
+Scanning (with PNM) does seem to work, although large files definitely take
+longer in JAVA then with "xscanimage".
+
+Main things left to do:
+	1.  Provide the "preview" dialog.
+	2.  Try it out with a real scanner, especially with large images.
+	3.  Try it on a platform other than Linux.
+
+--
+11/18/97
+
+This snapshot contains a partially functional "Jscanimage", which is intended
+to be a Java clone of "xscanimage".  Only some of the controls are implemented
+(sliders, check-boxes, text-entry), and I've only tested it using small images
+with the "pnm" backend; but, it does seem to be functional, and to output .pnm
+files.
+
+There are also some small changes to the Java API.
+
+To do (at the least):
+	1.  Handle "word list" controls.
+	2.  Handle "browse" button for file selection.
+	3.  Provide pull-down menus for choosing length units, and use them.
+	4.  Provide the "preview" dialog.
+	5.  Try it out with a real scanner, especially with large images.
+	6.  Try it on a platform other than Linux.
+
+	-- Jeff
+
+--
+10/17/97
+
+NOTE: To build the Java interface, you have to cd into this directory
+and type "make" (after running configure in the top-level directory).
+
+	--david
+--
+This is my first pass at creating a Java API for SANE.  It requires JDK 1.1.x,
+as it uses the new JNI for creating native methods.
+
+This is definitely not 100% pure Java, as it's really just a set of wrappers
+which call the actual SANE backend routines.  It's also very preliminary, so
+feel free to suggest changes to the interface or class definitions.
+
+The 'install' installs the shared library (libsanej.*), but I'm not sure yet
+what to do with the generated Java class files.  So for now, you should be
+able to run the test program after installation by typing "java Test" within
+the "japi" directory.
+
+-- Jeff Freedman (jsf@hevanet.com)
diff --git a/japi/Sane.c b/japi/Sane.c
new file mode 100644
index 0000000..1ddb4fc
--- /dev/null
+++ b/japi/Sane.c
@@ -0,0 +1,493 @@
+/* sane - Scanner Access Now Easy.
+   Copyright (C) 1997 Jeffrey S. Freedman
+   This file is part of the SANE package.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+   As a special exception, the authors of SANE give permission for
+   additional uses of the libraries contained in this release of SANE.
+
+   The exception is that, if you link a SANE library with other files
+   to produce an executable, this does not by itself cause the
+   resulting executable to be covered by the GNU General Public
+   License.  Your use of that executable is in no way restricted on
+   account of linking the SANE library code into it.
+
+   This exception does not, however, invalidate any other reasons why
+   the executable file might be covered by the GNU General Public
+   License.
+
+   If you submit changes to SANE to the maintainers to be included in
+   a subsequent release, you agree by submitting the changes that
+   those changes may be distributed with this exception intact.
+
+   If you write modifications of your own for SANE, it is your choice
+   whether to permit this exception to apply to your modifications.
+   If you do not wish that, delete this exception notice.  */
+
+/**
+ **	Sane.c - Native methods for the SANE Java API.
+ **
+ **	Written: 10/9/97 - JSF
+ **/
+
+#include "Sane.h"
+#include <sane/sane.h>
+#include <string.h>
+
+#include <stdio.h>	/* Debugging */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class:     Sane
+ * Method:    init
+ * Signature: ([I)I
+ */
+JNIEXPORT jint JNICALL Java_Sane_init
+  (JNIEnv *env, jobject jobj, jintArray versionCode)
+	{
+	jsize len;			/* Gets array length. */
+	jint *versionCodeBody;		/* Gets ->array. */
+	SANE_Int version;		/* Gets version. */
+	SANE_Status status;		/* Get SANE return. */
+
+	status = sane_init(&version, 0);
+	len = (*env)->GetArrayLength(env, versionCode);
+	versionCodeBody = (*env)->GetIntArrayElements(env, versionCode, 0);
+	if (len > 0)			/* Return version. */
+		versionCodeBody[0] = version;
+	(*env)->ReleaseIntArrayElements(env, versionCode, versionCodeBody, 0);
+	return (status);
+	}
+/*
+ * Class:     Sane
+ * Method:    exit
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_Sane_exit
+  (JNIEnv *env, jobject jobj)
+	{
+	sane_exit();
+	}
+
+
+/*
+ * Class:     Sane
+ * Method:    getDevices
+ * Signature: ([LSaneDevice;Z)I
+ */
+JNIEXPORT jint JNICALL Java_Sane_getDevicesNative
+  (JNIEnv *env, jobject jobj, jobjectArray devList, jboolean localOnly)
+	{
+					/* Gets device list. */
+	const SANE_Device **device_list;
+	SANE_Status status;		/* Gets status. */
+	int devListLen;			/* Gets length of devList. */
+	jobject devObj;			/* Gets each SaneDevice object. */
+	jclass devClass;		/* Gets SaneDevice class. */
+	jfieldID fid;			/* Gets each field ID. */
+	int i;
+
+					/* Get the list. */
+	status = sane_get_devices(&device_list, localOnly);	
+	if (status != SANE_STATUS_GOOD)
+		return (status);
+					/* Get length of Java array. */
+	devListLen = (*env)->GetArrayLength(env, devList);
+					/* Return devices to user. */
+	for (i = 0; i < devListLen - 1 && device_list[i]; i++)
+		{
+					/* Get Java object, class. */
+		devObj = (*env)->GetObjectArrayElement(env, devList, i);
+		devClass = (*env)->GetObjectClass(env, devObj);
+					/* Fill in each member. */
+		fid = (*env)->GetFieldID(env, devClass, "name",
+							"Ljava/lang/String;");
+		(*env)->SetObjectField(env, devObj, fid,
+			(*env)->NewStringUTF(env, device_list[i]->name));
+		fid = (*env)->GetFieldID(env, devClass, "vendor",
+							"Ljava/lang/String;");
+		(*env)->SetObjectField(env, devObj, fid,
+			(*env)->NewStringUTF(env, device_list[i]->vendor));
+		fid = (*env)->GetFieldID(env, devClass, "model",
+							"Ljava/lang/String;");
+		(*env)->SetObjectField(env, devObj, fid,
+			(*env)->NewStringUTF(env, device_list[i]->model));
+		fid = (*env)->GetFieldID(env, devClass, "type",
+							"Ljava/lang/String;");
+		(*env)->SetObjectField(env, devObj, fid,
+			(*env)->NewStringUTF(env, device_list[i]->type));
+		}
+					/* End list with a null. */
+	(*env)->SetObjectArrayElement(env, devList, i, 0);
+	return (status);
+	}
+
+/*
+ * Class:     Sane
+ * Method:    open
+ * Signature: (Ljava/lang/String;[J)I
+ */
+JNIEXPORT jint JNICALL Java_Sane_open
+  (JNIEnv *env, jobject jobj, jstring deviceName, jintArray handle)
+	{
+	SANE_Handle sane_handle;	/* Gets handle. */
+	jint s_handle;
+	const char *device_name;	/* Gets dev. name. */
+	int status;			/* Gets return code. */
+
+	device_name = (*env)->GetStringUTFChars(env, deviceName, 0);
+					/* Open it. */
+	status = sane_open(device_name, &sane_handle);
+	(*env)->ReleaseStringUTFChars(env, deviceName, device_name);
+					/* Return handle. */
+	s_handle = (jint) sane_handle;
+	(*env)->SetIntArrayRegion(env, handle, 0, 1, &s_handle);
+	return (status);
+	}
+
+/*
+ * Class:     Sane
+ * Method:    close
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_Sane_close
+  (JNIEnv *env, jobject jobj, jint handle)
+	{
+	sane_close((SANE_Handle) handle);
+	}
+
+/*
+ * Class:     Sane
+ * Method:    getOptionNative
+ * Signature: (IILSaneOption;)V
+ */
+JNIEXPORT void JNICALL Java_Sane_getOptionNative
+  (JNIEnv *env, jobject jobj, jint handle, jint option, jobject optObj)
+	{
+	jclass optClass;		/* Gets its class. */
+	jfieldID fid;			/* Gets each field ID. */
+	jstring str;			/* Gets strings. */
+
+					/* Get info from sane. */
+	const SANE_Option_Descriptor *sopt = sane_get_option_descriptor(
+			(SANE_Handle) handle, option);
+					/* Get class info. */
+	optClass = (*env)->GetObjectClass(env, optObj);
+					/* Fill in each member. */
+	fid = (*env)->GetFieldID(env, optClass, "name", "Ljava/lang/String;");
+	if (!sopt)			/* Failed. */
+		{			/* Set name to null. */
+		(*env)->SetObjectField(env, optObj, fid, 0);
+		return;
+		}
+					/* Return name. */
+	(*env)->SetObjectField(env, optObj, fid,
+				(*env)->NewStringUTF(env, sopt->name));
+					/* Return title. */
+	fid = (*env)->GetFieldID(env, optClass, "title", "Ljava/lang/String;");
+	str = sopt->title ? (*env)->NewStringUTF(env, sopt->title) : 0;
+	(*env)->SetObjectField(env, optObj, fid, str);
+					/* Return descr. */
+	fid = (*env)->GetFieldID(env, optClass, "desc", "Ljava/lang/String;");
+	(*env)->SetObjectField(env, optObj, fid,
+				(*env)->NewStringUTF(env, sopt->desc));
+					/* Return type. */
+	fid = (*env)->GetFieldID(env, optClass, "type", "I");
+	(*env)->SetIntField(env, optObj, fid, sopt->type);
+					/* Return unit. */
+	fid = (*env)->GetFieldID(env, optClass, "unit", "I");
+	(*env)->SetIntField(env, optObj, fid, sopt->unit);
+					/* Return size. */
+	fid = (*env)->GetFieldID(env, optClass, "size", "I");
+	(*env)->SetIntField(env, optObj, fid, sopt->size);
+					/* Return cap. */
+	fid = (*env)->GetFieldID(env, optClass, "cap", "I");
+	(*env)->SetIntField(env, optObj, fid, sopt->cap);
+					/* Return constraint_type. */
+	fid = (*env)->GetFieldID(env, optClass, "constraintType", "I");
+	(*env)->SetIntField(env, optObj, fid, sopt->constraint_type);
+	/*
+	 *	Now for the constraint itself.
+	 */
+	if (sopt->constraint_type == SANE_CONSTRAINT_RANGE)
+		{
+					/* Create range object. */
+		jclass rangeClass = (*env)->FindClass(env, "SaneRange");
+		jobject range = (*env)->AllocObject(env, rangeClass);
+					/* Fill in fields. */
+		fid = (*env)->GetFieldID(env, rangeClass, "min", "I");
+		(*env)->SetIntField(env, range, fid, 
+						sopt->constraint.range->min);
+		fid = (*env)->GetFieldID(env, rangeClass, "max", "I");
+		(*env)->SetIntField(env, range, fid, 
+						sopt->constraint.range->max);
+		fid = (*env)->GetFieldID(env, rangeClass, "quant", "I");
+		(*env)->SetIntField(env, range, fid, 
+						sopt->constraint.range->quant);
+		fid = (*env)->GetFieldID(env, optClass, "rangeConstraint",
+						"LSaneRange;");
+					/* Store range. */
+		(*env)->SetObjectField(env, optObj, fid, range);
+		}
+	else if (sopt->constraint_type == SANE_CONSTRAINT_WORD_LIST)
+		{			/* Get array of integers. */
+		jintArray wordList;
+		jint *elements;
+		int i;
+					/* First word. is the length.	*/
+		wordList = (*env)->NewIntArray(env, 
+				sopt->constraint.word_list[0]);
+					/* Copy in the integers.	*/
+		elements = (*env)->GetIntArrayElements(env, wordList, 0);
+		for (i = 0; i < sopt->constraint.word_list[0]; i++)
+			elements[i] = sopt->constraint.word_list[i];
+		(*env)->ReleaseIntArrayElements(env, wordList, elements, 0);
+					/* Set the field. */
+		fid = (*env)->GetFieldID(env, optClass, "wordListConstraint",
+									"[I");
+		(*env)->SetObjectField(env, optObj, fid, wordList);
+		}
+	else if (sopt->constraint_type == SANE_CONSTRAINT_STRING_LIST)
+		{
+		jclass stringClass = (*env)->FindClass(env, "java/lang/String");
+		jobjectArray stringList;
+		int len;		/* Gets # elements */
+		int i;
+
+		for (len = 0; sopt->constraint.string_list[len]; len++)
+			;
+		stringList = (*env)->NewObjectArray(env, len + 1, 
+							stringClass, 0);
+					/* Add each string. */
+		for (i = 0; i < len; i++)
+			{
+			(*env)->SetObjectArrayElement(env, stringList, i,
+				(*env)->NewStringUTF(env,
+					sopt->constraint.string_list[i]));
+			}
+					/* 0 at end. */
+		(*env)->SetObjectArrayElement(env, stringList, len, 0);
+					/* Set the field. */
+		fid = (*env)->GetFieldID(env, optClass, 
+			"stringListConstraint", "[Ljava/lang/String;");
+		(*env)->SetObjectField(env, optObj, fid, stringList);
+		}
+	}
+
+/*
+ * Class:     Sane
+ * Method:    getControlOption
+ * Signature: (II[I[I)I
+ */
+JNIEXPORT jint JNICALL Java_Sane_getControlOption__II_3I_3I
+  (JNIEnv *env, jobject jobj, jint handle, jint option, jintArray value, 
+						jintArray info)
+	{
+	SANE_Status status;		/* Gets status. */
+	SANE_Int i;			/* Gets info. passed back. */
+	int v;
+
+	status = sane_control_option((SANE_Handle) handle, option,
+			SANE_ACTION_GET_VALUE, &v, &i);
+	if (value)
+		(*env)->SetIntArrayRegion(env, value, 0, 1, &v);
+	if (info)
+		(*env)->SetIntArrayRegion(env, info, 0, 1, &i);
+	return (status);
+	}
+
+/*
+ * Class:     Sane
+ * Method:    getControlOption
+ * Signature: (II[B[I)I
+ */
+JNIEXPORT jint JNICALL Java_Sane_getControlOption__II_3B_3I
+  (JNIEnv *env, jobject jobj, jint handle, jint option, jbyteArray value, 
+						jintArray info)
+	{
+	SANE_Status status;		/* Gets status. */
+	SANE_Int i;			/* Gets info. passed back. */
+	char *str;
+
+	str = (*env)->GetByteArrayElements(env, value, 0);
+	status = sane_control_option((SANE_Handle) handle, option,
+			SANE_ACTION_GET_VALUE, str, &i);
+	(*env)->ReleaseByteArrayElements(env, value, str, 0);
+	if (info)
+		(*env)->SetIntArrayRegion(env, info, 0, 1, &i);
+	return (status);
+	}
+
+/*
+ * Class:     Sane
+ * Method:    setControlOption
+ * Signature: (IIII[I)I
+ */
+JNIEXPORT jint JNICALL Java_Sane_setControlOption__IIII_3I
+  (JNIEnv *env, jobject jobj, jint handle, jint option, jint action, 
+				jint value, jintArray info)
+	{
+	SANE_Status status;		/* Gets status. */
+	SANE_Int i;			/* Gets info. passed back. */
+	status = sane_control_option((SANE_Handle) handle, option, action,
+					&value, &i);
+	if (info)
+		(*env)->SetIntArrayRegion(env, info, 0, 1, &i);
+	return (status);
+	}
+
+/*
+ *	Get string length.  This exists because sometimes strings seem to be
+ *	padded with negatives.
+ */
+
+static int String_length
+	(
+	const char *str
+	)
+	{
+	const char *ptr;
+	for (ptr = str; *ptr > 0; ptr++)
+		;
+	return ((int) (ptr - str));
+	}
+
+/*
+ * Class:     Sane
+ * Method:    setControlOption
+ * Signature: (IIILjava/lang/String;[I)I
+ */
+JNIEXPORT jint JNICALL Java_Sane_setControlOption__IIILjava_lang_String_2_3I
+  (JNIEnv *env, jobject jobj, jint handle, jint option, jint action,
+				jstring value, jintArray info)
+	{
+	SANE_Status status;		/* Gets status. */
+	SANE_Int i;			/* Gets info. passed back. */
+	const char *valuep;
+	char buf[512];			/* Hope this is big enough. */
+	int len;			/* Gets string length. */
+
+	valuep = (*env)->GetStringUTFChars(env, value, 0);
+	len = String_length(valuep);
+	if (len >= sizeof(buf))
+		len = sizeof(buf) - 1;
+	strncpy(buf, valuep, len);
+	buf[len] = 0;			/* Insure it's 0-delimited. */
+	status = sane_control_option((SANE_Handle) handle, option, action,
+					(void *) &buf[0], &i);
+					/* +++++++Want to return new val? */
+	(*env)->ReleaseStringUTFChars(env, value, valuep);
+	if (info)
+		(*env)->SetIntArrayRegion(env, info, 0, 1, &i);
+	return (status);
+	}
+
+/*
+ * Class:     Sane
+ * Method:    getParameters
+ * Signature: (ILSaneParameters;)I
+ */
+JNIEXPORT jint JNICALL Java_Sane_getParameters
+  (JNIEnv *env, jobject jobj, jint handle, jobject paramsObj)
+	{
+	SANE_Status status;		/* Gets status.	*/
+	SANE_Parameters params;		/* Gets params. */
+	jclass paramsClass;		/* Gets its class. */
+	jfieldID fid;			/* Gets each field ID. */
+
+	status = sane_get_parameters((SANE_Handle) handle, &params);
+					/* Get class info. */
+	paramsClass = (*env)->GetObjectClass(env, paramsObj);
+					/* Fill in each member. */
+	fid = (*env)->GetFieldID(env, paramsClass, "format", "I");
+	(*env)->SetIntField(env, paramsObj, fid, params.format);
+	fid = (*env)->GetFieldID(env, paramsClass, "lastFrame", "Z");
+	(*env)->SetBooleanField(env, paramsObj, fid, params.last_frame);
+	fid = (*env)->GetFieldID(env, paramsClass, "bytesPerLine", "I");
+	(*env)->SetIntField(env, paramsObj, fid, params.bytes_per_line);
+	fid = (*env)->GetFieldID(env, paramsClass, "pixelsPerLine", "I");
+	(*env)->SetIntField(env, paramsObj, fid, params.pixels_per_line);
+	fid = (*env)->GetFieldID(env, paramsClass, "lines", "I");
+	(*env)->SetIntField(env, paramsObj, fid, params.lines);
+	fid = (*env)->GetFieldID(env, paramsClass, "depth", "I");
+	(*env)->SetIntField(env, paramsObj, fid, params.depth);
+	return (status);
+	}
+
+/*
+ * Class:     Sane
+ * Method:    start
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_Sane_start
+  (JNIEnv *env, jobject jobj, jint handle)
+	{
+	return (sane_start((SANE_Handle) handle));
+	}
+
+/*
+ * Class:     Sane
+ * Method:    read
+ * Signature: (I[BI[I)I
+ */
+JNIEXPORT jint JNICALL Java_Sane_read
+  (JNIEnv *env, jobject jobj, jint handle, jbyteArray data, jint maxLength,
+					jintArray length)
+	{
+	int status;
+	jbyte *dataElements;
+	int read_len;			/* # bytes read. */
+
+					/* Get actual data ptr. */
+	dataElements = (*env)->GetByteArrayElements(env, data, 0);
+					/* Do the read. */
+	status = sane_read((SANE_Handle) handle, dataElements, 
+						maxLength, &read_len);
+	(*env)->ReleaseByteArrayElements(env, data, dataElements, 0);
+					/* Return # bytes read. */
+	(*env)->SetIntArrayRegion(env, length, 0, 1, &read_len);
+	return (status);
+	}
+
+/*
+ * Class:     Sane
+ * Method:    cancel
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_Sane_cancel
+  (JNIEnv *env, jobject jobj, jint handle)
+	{
+	sane_cancel((SANE_Handle) handle);
+	}
+
+/*
+ * Class:     Sane
+ * Method:    strstatus
+ * Signature: (I)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_Sane_strstatus
+  (JNIEnv *env, jobject jobj, jint status)
+	{
+	const char *str = sane_strstatus(status);
+	return ((*env)->NewStringUTF(env, str));
+	}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/japi/Sane.java b/japi/Sane.java
new file mode 100644
index 0000000..85600e7
--- /dev/null
+++ b/japi/Sane.java
@@ -0,0 +1,144 @@
+/* sane - Scanner Access Now Easy.
+   Copyright (C) 1997 Jeffrey S. Freedman
+   This file is part of the SANE package.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+   As a special exception, the authors of SANE give permission for
+   additional uses of the libraries contained in this release of SANE.
+
+   The exception is that, if you link a SANE library with other files
+   to produce an executable, this does not by itself cause the
+   resulting executable to be covered by the GNU General Public
+   License.  Your use of that executable is in no way restricted on
+   account of linking the SANE library code into it.
+
+   This exception does not, however, invalidate any other reasons why
+   the executable file might be covered by the GNU General Public
+   License.
+
+   If you submit changes to SANE to the maintainers to be included in
+   a subsequent release, you agree by submitting the changes that
+   those changes may be distributed with this exception intact.
+
+   If you write modifications of your own for SANE, it is your choice
+   whether to permit this exception to apply to your modifications.
+   If you do not wish that, delete this exception notice.  */
+
+//
+//	Sane.java - Java version of SANE API.
+//
+//	Written: 10/9/97 - JSF
+//
+
+public class Sane
+{
+	//
+	//	Public constants:
+	//
+public static int FIXED_SCALE_SHIFT = 16;
+	//
+	//	Sane status values:
+	//
+public static int STATUS_GOOD = 0;	// everything A-OK
+public static int STATUS_UNSUPPORTED = 1;// operation is not supported
+public static int STATUS_CANCELLED = 2;	// operation was cancelled
+public static int STATUS_DEVICE_BUSY = 3;// device is busy; try again later
+public static int STATUS_INVAL = 4;	// data is invalid (includes no 
+					//   dev at open)
+public static int STATUS_EOF = 5;	// no more data available (end-of-file)
+public static int STATUS_JAMMED = 6;	// document feeder jammed
+public static int STATUS_NO_DOCS = 7;	// document feeder out of documents
+public static int STATUS_COVER_OPEN = 8;// scanner cover is open
+public static int STATUS_IO_ERROR = 9;	// error during device I/O
+public static int STATUS_NO_MEM = 10;	// out of memory
+					// access to resource has been denied
+public static int STATUS_ACCESS_DENIED = 11;
+	//
+	//	Initialize when class is loaded.
+	//
+static	{
+	System.loadLibrary("sanej");
+	}
+	//
+	//	Private methods:
+	//
+				// Get list of devices.
+private native int getDevicesNative(
+				SaneDevice[] deviceList, boolean localOnly);
+				// Get option descriptor.
+private native void getOptionNative(int handle, int option, SaneOption opt);
+	//
+	//	Public methods:
+	//
+public Sane()
+	{  }
+public int fix(double v)
+	{ return (int) ((v) * (1 << FIXED_SCALE_SHIFT)); }
+public double unfix(int v)
+	{ return (double)(v) / (1 << FIXED_SCALE_SHIFT); }
+public int versionMajor(int code)
+	{ return ((code) >> 24) &   0xff; }
+public int versionMinor(int code)
+	{ return ((code) >> 16) &   0xff; }
+public int versionBuild(int code)
+	{ return ((code) >>  0) & 0xffff; }
+	//
+	//	SANE interface.
+	//
+				// Initialize, and return STATUS_
+public native int init(int[] versionCode);
+public native void exit();	// All done.
+				// Get list of devices.
+public int getDevices(SaneDevice[] deviceList, boolean localOnly)
+	{
+				// Create objects first.
+	for (int i = 0; i < deviceList.length - 1; i++)
+		deviceList[i] = new SaneDevice();
+	return getDevicesNative(deviceList, localOnly);
+	}
+				// Open a device.
+public native int open(String deviceName, int[] handle);
+				// Close a device.
+public native void close(int handle);
+				// Get option descriptor.
+public SaneOption getOptionDescriptor(int handle, int option)
+	{
+	SaneOption opt = new SaneOption();
+	opt.name = null;
+	getOptionNative(handle, option, opt);
+	if (opt.name == null)	// Error?
+		return (null);
+	return (opt);
+	}
+				// Get each type of option:
+public native int getControlOption(int handle, int option, int [] value,
+							int [] info);
+public native int getControlOption(int handle, int option, byte [] value,
+							int [] info);
+				// Set each type of option (SET_VALUE or
+				//  SET_AUTO):
+public native int setControlOption(int handle, int option,
+				int action, int value, int [] info);
+public native int setControlOption(int handle, int option,
+				int action, String value, int [] info);
+public native int getParameters(int handle, SaneParameters params);
+public native int start(int handle);
+public native int read(int handle, byte [] data, 
+					int maxLength, int [] length);
+public native void cancel(int handle);
+public native String strstatus(int status);
+}
diff --git a/japi/SaneDevice.java b/japi/SaneDevice.java
new file mode 100644
index 0000000..dc73365
--- /dev/null
+++ b/japi/SaneDevice.java
@@ -0,0 +1,55 @@
+/* sane - Scanner Access Now Easy.
+   Copyright (C) 1997 Jeffrey S. Freedman
+   This file is part of the SANE package.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+   As a special exception, the authors of SANE give permission for
+   additional uses of the libraries contained in this release of SANE.
+
+   The exception is that, if you link a SANE library with other files
+   to produce an executable, this does not by itself cause the
+   resulting executable to be covered by the GNU General Public
+   License.  Your use of that executable is in no way restricted on
+   account of linking the SANE library code into it.
+
+   This exception does not, however, invalidate any other reasons why
+   the executable file might be covered by the GNU General Public
+   License.
+
+   If you submit changes to SANE to the maintainers to be included in
+   a subsequent release, you agree by submitting the changes that
+   those changes may be distributed with this exception intact.
+
+   If you write modifications of your own for SANE, it is your choice
+   whether to permit this exception to apply to your modifications.
+   If you do not wish that, delete this exception notice.  */
+
+//
+//	SaneDevice.java - Device Descriptor.
+//
+//	Written: 10/9/97 - JSF
+//
+
+public class SaneDevice
+{
+public String name;		// unique device name 
+public String vendor;		// device vendor string 
+public String model;		// device model name 
+public String type;		// device type (e.g., "flatbed scanner") 
+}
+
+
diff --git a/japi/SaneOption.java b/japi/SaneOption.java
new file mode 100644
index 0000000..ed460c7
--- /dev/null
+++ b/japi/SaneOption.java
@@ -0,0 +1,145 @@
+/* sane - Scanner Access Now Easy.
+   Copyright (C) 1997 Jeffrey S. Freedman
+   This file is part of the SANE package.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+   As a special exception, the authors of SANE give permission for
+   additional uses of the libraries contained in this release of SANE.
+
+   The exception is that, if you link a SANE library with other files
+   to produce an executable, this does not by itself cause the
+   resulting executable to be covered by the GNU General Public
+   License.  Your use of that executable is in no way restricted on
+   account of linking the SANE library code into it.
+
+   This exception does not, however, invalidate any other reasons why
+   the executable file might be covered by the GNU General Public
+   License.
+
+   If you submit changes to SANE to the maintainers to be included in
+   a subsequent release, you agree by submitting the changes that
+   those changes may be distributed with this exception intact.
+
+   If you write modifications of your own for SANE, it is your choice
+   whether to permit this exception to apply to your modifications.
+   If you do not wish that, delete this exception notice.  */
+
+//
+//	SaneOption.java - Sane option descriptor.
+//
+//	Written: 10/9/97 - JSF
+//
+
+public class SaneOption
+    {
+	//
+	// 	Sane option types:
+	//
+    public static final int TYPE_BOOL = 0;
+    public static final int TYPE_INT = 1;
+    public static final int TYPE_FIXED = 2;
+    public static final int TYPE_STRING = 3;
+    public static final int TYPE_BUTTON = 4;
+    public static final int TYPE_GROUP = 5;
+	//
+	//	Sane value units:
+	//
+    public static final int UNIT_NONE = 0;	// the value is unit-less 
+					//   (e.g., # of scans) 
+    public static final int UNIT_PIXEL = 1;	// value is number of pixels 
+    public static final int UNIT_BIT = 2;	// value is number of bits 
+    public static final int UNIT_MM = 3;	// value is millimeters 
+    public static final int UNIT_DPI = 4;	// value is res. in dots/inch 
+    public static final int UNIT_PERCENT = 5;// value is a percentage 
+	//
+	//	Option capabilities:
+	//
+    public static final int CAP_SOFT_SELECT = (1 << 0);
+    public static final int CAP_HARD_SELECT = (1 << 1);
+    public static final int CAP_SOFT_DETECT = (1 << 2);
+    public static final int CAP_EMULATED = (1 << 3);
+    public static final int CAP_AUTOMATIC = (1 << 4);
+    public static final int CAP_INACTIVE = (1 << 5);
+    public static final int CAP_ADVANCED = (1 << 6);
+	//
+	//	Constraints:
+	//
+    public static final int CONSTRAINT_NONE = 0;
+    public static final int CONSTRAINT_RANGE = 1;
+    public static final int CONSTRAINT_WORD_LIST = 2;
+    public static final int CONSTRAINT_STRING_LIST = 3;
+	//
+	//	Actions for controlOption():
+	//
+    public static final int ACTION_GET_VALUE = 0;
+    public static final int ACTION_SET_VALUE = 1;
+    public static final int ACTION_SET_AUTO = 2;
+
+	//
+	//	Flags passed back in 'info' field param. of
+	//	setControlOption():
+	//
+    public static final int INFO_INEXACT =		(1 << 0);
+    public static final int INFO_RELOAD_OPTIONS	=	(1 << 1);
+    public static final int INFO_RELOAD_PARAMS =	(1 << 2);
+
+	//
+	//	Class members:
+	//
+    public String name;		// name of this option (command-line name) 
+    public String title;	// title of this option (single-line) 
+    public String desc;		// description of this option (multi-line) 
+    public int type;		// how are values interpreted? (TYPE_)
+    public int unit;		// what is the (physical) unit? (UNIT_)
+    public int size;
+    public int cap;		// capabilities 
+    public int constraintType;
+				// These are a union in the "C" API:
+				// Null-terminated list:
+    public String[] stringListConstraint;
+				// First element is list-length:
+    public int[] wordListConstraint;
+    public SaneRange rangeConstraint;
+	//
+	//	Public methods:
+	//
+    public boolean is_active()
+	{ return ((cap) & CAP_INACTIVE) == 0; }
+    public boolean is_settable()
+	{ return ((cap) & CAP_SOFT_SELECT) == 0; }
+				// Return string describing units.
+				// "unitLength" is # mm. preferred.
+    public String unitString(double unitLength)	
+	{
+	switch (unit)
+		{
+	case UNIT_NONE:		return "none";
+	case UNIT_PIXEL:	return "pixel";
+	case UNIT_BIT:		return "bit";
+	case UNIT_DPI:		return "dpi";
+	case UNIT_PERCENT:	return "%";
+	case UNIT_MM:
+	  	if (unitLength > 9.9 && unitLength < 10.1)
+			return "cm";
+		else if (unitLength > 25.3 && unitLength < 25.5)
+			return "in";
+	  	return "mm";
+		}
+  	return "";
+	}
+    }
+
diff --git a/japi/SaneParameters.java b/japi/SaneParameters.java
new file mode 100644
index 0000000..4e629c4
--- /dev/null
+++ b/japi/SaneParameters.java
@@ -0,0 +1,68 @@
+/* sane - Scanner Access Now Easy.
+   Copyright (C) 1997 Jeffrey S. Freedman
+   This file is part of the SANE package.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+   As a special exception, the authors of SANE give permission for
+   additional uses of the libraries contained in this release of SANE.
+
+   The exception is that, if you link a SANE library with other files
+   to produce an executable, this does not by itself cause the
+   resulting executable to be covered by the GNU General Public
+   License.  Your use of that executable is in no way restricted on
+   account of linking the SANE library code into it.
+
+   This exception does not, however, invalidate any other reasons why
+   the executable file might be covered by the GNU General Public
+   License.
+
+   If you submit changes to SANE to the maintainers to be included in
+   a subsequent release, you agree by submitting the changes that
+   those changes may be distributed with this exception intact.
+
+   If you write modifications of your own for SANE, it is your choice
+   whether to permit this exception to apply to your modifications.
+   If you do not wish that, delete this exception notice.  */
+
+//
+//	SaneParameters.java - Sane parameters.
+//
+//	Written: 10/14/97 - JSF
+//
+
+public class SaneParameters
+{
+	//
+	//	Frame values:
+	//
+public static final int FRAME_GRAY = 0;	// band covering human visual range 
+public static final int FRAME_RGB = 1;	// pixel-interleaved 
+					//   red/green/blue bands 
+public static final int FRAME_RED = 2;	// red band only 
+public static final int FRAME_GREEN = 3;// green band only 
+public static final int FRAME_BLUE = 4;	// blue band only 
+
+	//
+	//	Class members:
+	//
+public int format;
+public boolean lastFrame;
+public int bytesPerLine;
+public int pixelsPerLine;
+public int lines;
+public int depth;
+}
diff --git a/japi/SaneRange.java b/japi/SaneRange.java
new file mode 100644
index 0000000..4790e32
--- /dev/null
+++ b/japi/SaneRange.java
@@ -0,0 +1,53 @@
+/* sane - Scanner Access Now Easy.
+   Copyright (C) 1997 Jeffrey S. Freedman
+   This file is part of the SANE package.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+   As a special exception, the authors of SANE give permission for
+   additional uses of the libraries contained in this release of SANE.
+
+   The exception is that, if you link a SANE library with other files
+   to produce an executable, this does not by itself cause the
+   resulting executable to be covered by the GNU General Public
+   License.  Your use of that executable is in no way restricted on
+   account of linking the SANE library code into it.
+
+   This exception does not, however, invalidate any other reasons why
+   the executable file might be covered by the GNU General Public
+   License.
+
+   If you submit changes to SANE to the maintainers to be included in
+   a subsequent release, you agree by submitting the changes that
+   those changes may be distributed with this exception intact.
+
+   If you write modifications of your own for SANE, it is your choice
+   whether to permit this exception to apply to your modifications.
+   If you do not wish that, delete this exception notice.  */
+
+//
+//	SaneRange.java - Sane range info.
+//
+//	Written: 10/9/97 - JSF
+//
+
+public class SaneRange
+{
+public int min;			// minimum (element) value
+public int max;			// maximum (element) value
+public int quant;		// Quantization value (0 if none)
+}
+
diff --git a/japi/ScanIt.java b/japi/ScanIt.java
new file mode 100644
index 0000000..21afba0
--- /dev/null
+++ b/japi/ScanIt.java
@@ -0,0 +1,391 @@
+/* sane - Scanner Access Now Easy.
+   Copyright (C) 1997 Jeffrey S. Freedman
+   This file is part of the SANE package.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+   As a special exception, the authors of SANE give permission for
+   additional uses of the libraries contained in this release of SANE.
+
+   The exception is that, if you link a SANE library with other files
+   to produce an executable, this does not by itself cause the
+   resulting executable to be covered by the GNU General Public
+   License.  Your use of that executable is in no way restricted on
+   account of linking the SANE library code into it.
+
+   This exception does not, however, invalidate any other reasons why
+   the executable file might be covered by the GNU General Public
+   License.
+
+   If you submit changes to SANE to the maintainers to be included in
+   a subsequent release, you agree by submitting the changes that
+   those changes may be distributed with this exception intact.
+
+   If you write modifications of your own for SANE, it is your choice
+   whether to permit this exception to apply to your modifications.
+   If you do not wish that, delete this exception notice.  */
+
+/**
+ **	ScanIt.java - Do the actual scanning for SANE.
+ **
+ **	Written: 11/3/97 - JSF
+ **/
+
+import java.util.Vector;
+import java.util.Enumeration;
+import java.awt.image.ImageProducer;
+import java.awt.image.ImageConsumer;
+import java.awt.image.ColorModel;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.BufferedWriter;
+import java.io.IOException;
+
+/*
+ *	This class uses SANE to scan an image.
+ */
+public class ScanIt implements ImageProducer
+    {
+					// # lines we incr. image height.
+    private static final int STRIP_HEIGHT = 256;
+    private Sane sane;
+    private int handle = 0;		// SANE device handle.
+    private Vector consumers = new Vector();
+					// File to write to.
+    private OutputStream outputFile = null;
+    private SaneParameters parms = new SaneParameters();
+    private ColorModel cm;		// RGB color model.
+    private int width, height;		// Dimensions.
+    private int x, y;			// Position.
+    private int image[] = null;		// Image that we build as we scan.
+    private int offset;			// Offset within image in pixels if
+					//   doing separate frames, bytes
+					//   (3/word) if RBG.
+
+	/*
+	 *	Tell consumers our status.  The scan is also terminated de-
+	 *	pending on the status.
+	 */
+    private void tellStatus(int s)
+	{
+	Enumeration next = consumers.elements();
+	while (next.hasMoreElements())
+		{
+		ImageConsumer ic = (ImageConsumer) next.nextElement();
+		ic.imageComplete(s);
+		}
+					// Done?  Stop scan.
+	if (s == ImageConsumer.STATICIMAGEDONE ||
+	    s == ImageConsumer.IMAGEERROR)
+		sane.cancel(handle);
+	}
+
+	/*
+	 *	Tell consumers the image size.
+	 */
+    private void tellDimensions(int w, int h)
+	{
+	System.out.println("tellDimensions:  " + w + ", " + h);
+	Enumeration next = consumers.elements();
+	while (next.hasMoreElements())
+		{
+		ImageConsumer ic = (ImageConsumer) next.nextElement();
+		ic.setDimensions(w, h);
+		}
+	}
+
+	/*
+	 *	Send pixels to the clients.
+	 */
+    private void tellPixels(int x, int y, int w, int h)
+	{
+/*
+	System.out.println("image length=" + image.length);
+	System.out.println("width=" + width);
+	System.out.println("tellPixels:  x="+x +" y="+y + " w="+w
+					+ " h="+h);
+ */
+	Enumeration next = consumers.elements();
+	while (next.hasMoreElements())
+		{
+		ImageConsumer ic = (ImageConsumer) next.nextElement();
+		ic.setPixels(x, y, w, h, cm, image, 0, width);
+		}
+	}
+
+	/*
+	 *	Construct.
+	 */
+    public ScanIt(Sane s, int hndl)
+	{
+	sane = s;
+	handle = hndl;
+	}
+
+	/*
+	 *	Add a consumer.
+	 */
+    public synchronized void addConsumer(ImageConsumer ic)
+	{
+	if (consumers.contains(ic))
+		return;			// Already here.
+	consumers.addElement(ic);
+	}
+
+	/*
+	 *	Is a consumer in the list?
+	 */
+    public synchronized boolean isConsumer(ImageConsumer ic)
+	{ return consumers.contains(ic); }
+
+	/*
+	 *	Remove consumer.
+	 */
+    public synchronized void removeConsumer(ImageConsumer ic)
+	{ consumers.removeElement(ic); }
+    	
+	/*
+	 *	Add a consumer and start scanning.
+	 */
+    public void startProduction(ImageConsumer ic)
+	{
+	System.out.println("In startProduction()");
+	addConsumer(ic);
+	scan();
+	}
+
+	/*
+	 *	Set file to write to.
+	 */
+    public void setOutputFile(OutputStream o)
+	{ outputFile = o; }
+
+	/*
+	 *	Ignore this:
+	 */
+    public void requestTopDownLeftRightResend(ImageConsumer ic)
+	{  }
+
+	/*
+	 *	Go to next line in image, reallocating if necessary.
+	 */
+    private void nextLine()
+	{
+	x = 0;
+	++y;
+	if (y >= height || image == null)
+		{			// Got to reallocate.
+		int oldSize = image == null ? 0 : width*height;
+		height += STRIP_HEIGHT;	// Add more lines.
+		int newSize = width*height;
+		int[] newImage = new int[newSize];
+		int i;
+		if (oldSize != 0)	// Copy old data.
+			for (i = 0; i < oldSize; i++)
+				newImage[i] = image[i];
+					// Fill new pixels with 0's, setting
+					//   alpha channel.
+		for (i = oldSize; i < newSize; i++)
+			newImage[i] = (255 << 24);
+		image = newImage;
+		System.out.println("nextLine:  newSize="+newSize);
+					// Tell clients.
+		tellDimensions(width, height);
+		}
+	}
+
+	/*
+	 *	Process a buffer of data.
+	 */
+    private boolean process(byte[] data, int readLen)
+	{
+	int prevY = y > 0 ? y : 0;	// Save current Y-coord.
+	int i;
+	switch (parms.format)
+		{
+	case SaneParameters.FRAME_RED:
+	case SaneParameters.FRAME_GREEN:
+	case SaneParameters.FRAME_BLUE:
+		System.out.println("Process RED, GREEN or BLUE");
+		int cindex = 2 - (parms.format - SaneParameters.FRAME_RED);
+					// Single frame.
+		for (i = 0; i < readLen; ++i)
+			{		// Doing a single color frame.
+			image[offset + i] |= 
+				(((int) data[i]) & 0xff) << (8*cindex);
+			++x;
+			if (x >= width)
+				nextLine();
+			}
+		break;
+	case SaneParameters.FRAME_RGB:
+		for (i = 0; i < readLen; ++i)
+			{
+			int b = 2 - (offset + i)%3;
+			image[(offset + i)/3] |= 
+				(((int) data[i]) & 0xff) << (8*b);
+			if (b == 0)
+				{
+				++x;
+				if (x >= width)
+					nextLine();
+				}
+			}
+		break;
+	case SaneParameters.FRAME_GRAY:
+		System.out.println("Process GREY");
+					// Single frame.
+		for (i = 0; i < readLen; ++i)
+			{
+			int v = ((int) data[i]) & 0xff;
+			image[offset + i] |= (v<<16) | (v<<8) | (v);
+			++x;
+			if (x >= width)
+				nextLine();
+			}
+		break;
+		}
+	offset += readLen;		// Update where we are.
+					// Show it.
+	System.out.println("PrevY = " + prevY + ", y = " + y);
+//	tellPixels(0, prevY, width, y - prevY);	
+	tellPixels(0, 0, width, height);
+	return true;
+	}
+
+	/*
+	 *	Start scanning.
+	 */
+    public void scan()
+	{
+	int dataLen = 32*1024;
+	byte [] data = new byte[dataLen];
+	int [] readLen = new int[1];
+	int frameCnt = 0;
+					// For now, use default RGB model.
+	cm = ColorModel.getRGBdefault();
+	int status;
+	image = null;
+	do				// Do each frame.
+		{
+		frameCnt++;
+		x = 0;			// Init. position.
+		y = -1;
+		offset = 0;
+		System.out.println("Reading frame #" + frameCnt);
+		status = sane.start(handle);
+		if (status != Sane.STATUS_GOOD)
+			{
+			System.out.println("start() failed.  Status= " 
+								+ status);
+			tellStatus(ImageConsumer.IMAGEERROR);
+			return;
+			}
+		status = sane.getParameters(handle, parms);
+		if (status != Sane.STATUS_GOOD)
+			{
+			System.out.println("getParameters() failed.  Status= " 
+								+ status);
+			tellStatus(ImageConsumer.IMAGEERROR);
+			return;	//++++cleanup.
+			}
+		if (frameCnt == 1)	// First time?
+			{
+			width = parms.pixelsPerLine;
+			if (parms.lines >= 0)
+				height = parms.lines - STRIP_HEIGHT + 1;
+			else		// Hand-scanner.
+				height = 0;
+			nextLine();	// Allocate image.
+			}
+		while ((status = sane.read(handle, data, dataLen, readLen))
+							== Sane.STATUS_GOOD)
+			{
+			System.out.println("Read " + readLen[0] + " bytes.");
+			if (!process(data, readLen[0]))
+				{
+				tellStatus(ImageConsumer.IMAGEERROR);
+				return;
+				}
+			}
+		if (status != Sane.STATUS_EOF)
+			{
+			System.out.println("read() failed.  Status= "
+								+ status);
+			tellStatus(ImageConsumer.IMAGEERROR);
+			return;
+			}
+		}
+	while (!parms.lastFrame);
+	height = y;			// For now, send whole image here.
+	tellDimensions(width, height);
+	tellPixels(0, 0, width, height);
+	if (outputFile != null)		// Write to file.
+		{
+		try
+			{
+			write(outputFile);
+			}
+		catch (IOException e)
+			{	//+++++++++++++++
+			System.out.println("I/O error writing file.");
+			}	
+		outputFile = null;	// Clear for next time.
+		}
+	tellStatus(ImageConsumer.STATICIMAGEDONE);
+	image = null;			// Allow buffer to be freed.
+	}
+
+	/*
+	 *	Write ppm/pnm output for last scan to a file.
+	 */
+    private void write(OutputStream out) throws IOException
+	{
+	PrintWriter pout = new PrintWriter(out);
+	BufferedWriter bout = new BufferedWriter(pout);
+	int len = width*height;		// Get # of pixels.
+	int i;
+	switch (parms.format)
+		{
+	case SaneParameters.FRAME_RED:
+	case SaneParameters.FRAME_GREEN:
+	case SaneParameters.FRAME_BLUE:
+	case SaneParameters.FRAME_RGB:
+		pout.print("P6\n# SANE data follows\n" + 
+			width + ' ' + height + "\n255\n");
+		for (i = 0; i < len; i++)
+			{
+			int pix = image[i];
+			bout.write((pix >> 16) & 0xff);
+			bout.write((pix >> 8) & 0xff);
+			bout.write(pix & 0xff);
+			}
+		break;
+	case SaneParameters.FRAME_GRAY:
+		pout.print("P5\n# SANE data follows\n" +
+			width + ' ' + height + "\n255\n");
+		for (i = 0; i < len; i++)
+			{
+			int pix = image[i];
+			bout.write(pix & 0xff);
+			}
+		break;
+		}
+
+	bout.flush();			// Flush output.
+	pout.flush();
+	}
+    }
diff --git a/japi/Test.java b/japi/Test.java
new file mode 100644
index 0000000..52a7112
--- /dev/null
+++ b/japi/Test.java
@@ -0,0 +1,175 @@
+/* sane - Scanner Access Now Easy.
+   Copyright (C) 1997 Jeffrey S. Freedman
+   This file is part of the SANE package.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+   As a special exception, the authors of SANE give permission for
+   additional uses of the libraries contained in this release of SANE.
+
+   The exception is that, if you link a SANE library with other files
+   to produce an executable, this does not by itself cause the
+   resulting executable to be covered by the GNU General Public
+   License.  Your use of that executable is in no way restricted on
+   account of linking the SANE library code into it.
+
+   This exception does not, however, invalidate any other reasons why
+   the executable file might be covered by the GNU General Public
+   License.
+
+   If you submit changes to SANE to the maintainers to be included in
+   a subsequent release, you agree by submitting the changes that
+   those changes may be distributed with this exception intact.
+
+   If you write modifications of your own for SANE, it is your choice
+   whether to permit this exception to apply to your modifications.
+   If you do not wish that, delete this exception notice.  */
+
+class Test
+{
+public static void main(String[] args)
+	{
+	Sane sane = new Sane();
+	int version[] = new int[1];	// Array to get version #.
+	int status = sane.init(version);
+	if (status != Sane.STATUS_GOOD)
+		{
+		System.out.println("getDevices() failed.  Status= " + status);
+		return;
+		}
+	System.out.println("VersionMajor =" + sane.versionMajor(version[0]));
+	System.out.println("VersionMinor =" + sane.versionMinor(version[0]));
+	System.out.println("VersionBuild =" + sane.versionBuild(version[0]));
+					// Get list of devices.
+					// Allocate room for 50.
+	SaneDevice devList[] = new SaneDevice[50];
+	status = sane.getDevices(devList, false);
+	if (status != Sane.STATUS_GOOD)
+		{
+		System.out.println("getDevices() failed.  Status= " + status);
+		return;
+		}
+	for (int i = 0; i < 50 && devList[i] != null; i++)
+		{
+		System.out.println("Device '" + devList[i].name + "' is a " +
+			devList[i].vendor + " " + devList[i].model + " " +
+			devList[i].type);
+		}
+	int handle[] = new int[1];
+	status = sane.open(devList[0].name, handle);
+	if (status != Sane.STATUS_GOOD)
+		{
+		System.out.println("open() failed.  Status= " + status);
+		return;
+		}
+	System.out.println("Open handle=" + handle[0]);
+					// Get # of device options.
+	int numDevOptions[] = new int[1];
+	status = sane.getControlOption(handle[0], 0, numDevOptions, null);
+	if (status != Sane.STATUS_GOOD)
+		{
+		System.out.println("controlOption() failed.  Status= " 
+								+ status);
+		return;
+		}
+	System.out.println("Number of device options=" + numDevOptions[0]);
+	for (int i = 0; i < numDevOptions[0]; i++)
+		{
+		SaneOption opt = sane.getOptionDescriptor(handle[0], i);
+		if (opt == null)
+			{
+			System.out.println("getOptionDescriptor() failed for "
+						+ i);
+			continue;
+			}
+		System.out.println("Option name:  " + opt.name);
+		System.out.println("Option title: " + opt.title);
+		System.out.println("Option desc:  " + opt.desc);
+		switch (opt.constraintType)
+			{
+		case SaneOption.CONSTRAINT_RANGE:
+			System.out.println("Range:  " + 
+				opt.rangeConstraint.min + ", " +
+				opt.rangeConstraint.max + ", " +
+				opt.rangeConstraint.quant);
+			break;
+		case SaneOption.CONSTRAINT_WORD_LIST:
+			System.out.print("Word list: ");
+			for (int j = 0; j < opt.wordListConstraint[0]; j++)
+				System.out.print(opt.wordListConstraint[j]);
+			System.out.println();
+			break;
+		case SaneOption.CONSTRAINT_STRING_LIST:
+			for (int j = 0; opt.stringListConstraint[j] != null;
+									j++)
+				System.out.print("String constraint: " +
+						opt.stringListConstraint[j]);
+			break;
+		default:
+			System.out.println("No constraint.");
+			break;
+			}
+		}
+	status = sane.setControlOption(handle[0], 2, 
+			SaneOption.ACTION_SET_VALUE, "../test1.pnm", null);
+	if (status != Sane.STATUS_GOOD)
+		{
+		System.out.println("setControlOption() failed.  Status= " 
+								+ status);
+		}
+	//
+	//	Main scanning loop.
+	//
+	SaneParameters parm = new SaneParameters();
+	int dataLen = 32*1024;
+	byte [] data = new byte[dataLen];
+	int [] readLen = new int[1];
+	int frameCnt = 0;
+	do
+		{
+		frameCnt++;
+		System.out.println("Reading frame #" + frameCnt);
+		status = sane.start(handle[0]);
+		if (status != Sane.STATUS_GOOD)
+			{
+			System.out.println("start() failed.  Status= " 
+								+ status);
+			return;
+			}
+		status = sane.getParameters(handle[0], parm);
+		if (status != Sane.STATUS_GOOD)
+			{
+			System.out.println("getParameters() failed.  Status= " 
+								+ status);
+			return;	//++++cleanup.
+			}
+		while ((status = sane.read(handle[0], data, dataLen, readLen))
+							== Sane.STATUS_GOOD)
+			{
+			System.out.println("Read " + readLen[0] + " bytes.");
+			// ++++++++Process data.
+			}
+		if (status != Sane.STATUS_EOF)
+			{
+			System.out.println("read() failed.  Status= "
+								+ status);
+			}
+		}
+	while (!parm.lastFrame);
+
+	sane.close(handle[0]);
+	}
+}
-- 
cgit v1.2.3