/*
 * Electric(tm) VLSI Design System
 *
 * File: dblangjava.cpp
 * JAVA interface module
 * Written by: Steven M. Rubin, Static Free Software
 *
 * Copyright (c) 2000 Static Free Software.
 *
 * Electric(tm) 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.
 *
 * Electric(tm) 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 Electric(tm); see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, Mass 02111-1307, USA.
 *
 * Static Free Software
 * 4119 Alpine Road
 * Portola Valley, California 94028
 * info@staticfreesoft.com
 */

#include "config.h"
#if LANGJAVA

#include "global.h"
#include "dblang.h"
#include "usr.h"

#define MAXLINE 300

INTBIG          java_inited = 0;
JavaVM         *java_virtualmachine;			/* denotes a Java VM */
JNIEnv         *java_environment;				/* pointer to native method interface */    
JDK1_1InitArgs  java_vmargs;					/* JDK 1.1 VM initialization arguments */   
jclass          java_electricclass;
jclass          java_electriceoutclass;
jfieldID        java_addressID;
jfieldID        java_xarrayVID;
jobject         java_nullobject;
char           *java_arraybuffer;
INTBIG          java_arraybuffersize = 0;

char            java_outputbuffer[MAXLINE+1];
INTBIG          java_outputposition = 0;

jclass          java_classstring;
jclass          java_classint;
jclass          java_classfloat;
jclass          java_classarrayint;
jmethodID       java_midIntValue, java_midIntInit;
jmethodID       java_midFloatValue, java_midFloatInit;

jclass          java_classnodeinst;
jclass          java_classnodeproto;
jclass          java_classportarcinst;
jclass          java_classportexpinst;
jclass          java_classportproto;
jclass          java_classarcinst;
jclass          java_classarcproto;
jclass          java_classgeom;
jclass          java_classlibrary;
jclass          java_classtechnology;
jclass          java_classaid;
jclass          java_classrtnode;
jclass          java_classnetwork;
jclass          java_classcell;
jclass          java_classview;
jclass          java_classwindowpart;
jclass          java_classwindowframe;
jclass          java_classgraphics;
jclass          java_classconstraint;
jclass          java_classpolygon;
jclass          java_classxarray;

extern "C"
{
	JNIEXPORT jobject JNICALL Java_Electric_curLib(JNIEnv *env, jobject obj);
	JNIEXPORT jobject JNICALL Java_Electric_curTech(JNIEnv *env, jobject obj);
	JNIEXPORT jobject JNICALL Java_Electric_getValNodeinst(JNIEnv *env, jobject obj,
		jobject object, jstring qual);
	JNIEXPORT jobject JNICALL Java_Electric_getValNodeproto(JNIEnv *env, jobject obj,
		jobject object, jstring qual);
	JNIEXPORT jobject JNICALL Java_Electric_getValPortarcinst(JNIEnv *env, jobject obj,
		jobject object, jstring qual);
	JNIEXPORT jobject JNICALL Java_Electric_getValPortexpinst(JNIEnv *env, jobject obj,
		jobject object, jstring qual);
	JNIEXPORT jobject JNICALL Java_Electric_getValPortproto(JNIEnv *env, jobject obj,
		jobject object, jstring qual);
	JNIEXPORT jobject JNICALL Java_Electric_getValArcinst(JNIEnv *env, jobject obj,
		jobject object, jstring qual);
	JNIEXPORT jobject JNICALL Java_Electric_getValArcproto(JNIEnv *env, jobject obj,
		jobject object, jstring qual);
	JNIEXPORT jobject JNICALL Java_Electric_getValGeom(JNIEnv *env, jobject obj,
		jobject object, jstring qual);
	JNIEXPORT jobject JNICALL Java_Electric_getValLibrary(JNIEnv *env, jobject obj,
		jobject object, jstring qual);
	JNIEXPORT jobject JNICALL Java_Electric_getValTechnology(JNIEnv *env, jobject obj,
		jobject object, jstring qual);
	JNIEXPORT jobject JNICALL Java_Electric_getValAid(JNIEnv *env, jobject obj,
		jobject object, jstring qual);
	JNIEXPORT jobject JNICALL Java_Electric_getValRTNode(JNIEnv *env, jobject obj,
		jobject object, jstring qual);
	JNIEXPORT jobject JNICALL Java_Electric_getValNetwork(JNIEnv *env, jobject obj,
		jobject object, jstring qual);
	JNIEXPORT jobject JNICALL Java_Electric_getValCell(JNIEnv *env, jobject obj,
		jobject object, jstring qual);
	JNIEXPORT jobject JNICALL Java_Electric_getValView(JNIEnv *env, jobject obj,
		jobject object, jstring qual);
	JNIEXPORT jobject JNICALL Java_Electric_getValWindowpart(JNIEnv *env, jobject obj,
		jobject object, jstring qual);
	JNIEXPORT jobject JNICALL Java_Electric_getValWindowframe(JNIEnv *env, jobject obj,
		jobject object, jstring qual);
	JNIEXPORT jobject JNICALL Java_Electric_getValGraphics(JNIEnv *env, jobject obj,
		jobject object, jstring qual);
	JNIEXPORT jobject JNICALL Java_Electric_getValConstraint(JNIEnv *env, jobject obj,
		jobject object, jstring qual);
	JNIEXPORT jobject JNICALL Java_Electric_getValPolygon(JNIEnv *env, jobject obj,
		jobject object, jstring qual);
	JNIEXPORT void JNICALL Java_Electric_setVal(JNIEnv *env, jobject obj,
		jobject jobj, jstring jqual, jobject jattr, jint jbits);
	JNIEXPORT void JNICALL Java_Electric_setInd(JNIEnv *env, jobject obj,
		jobject jobj, jstring jname, jint index, jobject jattr);
	JNIEXPORT void JNICALL Java_Electric_delVal(JNIEnv *env, jobject obj,
		jobject jobj, jstring jname);
	JNIEXPORT jint JNICALL Java_Electric_initSearch(JNIEnv *env, jobject obj,
		jint lx, jint hx, jint ly, jint hy, jobject facet);
	JNIEXPORT jobject JNICALL Java_Electric_nextObject(JNIEnv *env, jobject obj,
		jint sea);
	JNIEXPORT void JNICALL Java_Electric_termSearch(JNIEnv *env, jobject obj,
		jint sea);
	JNIEXPORT jobject JNICALL Java_Electric_getAid(JNIEnv *env, jobject obj,
		jstring name);
	JNIEXPORT jint JNICALL Java_Electric_maxAid(JNIEnv *env, jobject obj);
	JNIEXPORT jobject JNICALL Java_Electric_indexAid(JNIEnv *env, jobject obj,
		jint index);
	JNIEXPORT void JNICALL Java_Electric_aidTurnOn(JNIEnv *env, jobject obj,
		jobject aid, jint catchup);
	JNIEXPORT void JNICALL Java_Electric_aidTurnOff(JNIEnv *env, jobject obj,
		jobject aid);
	JNIEXPORT void JNICALL Java_Electric_tellAid(JNIEnv *env, jobject obj,
		jobject aid, jint argc, jobjectArray jargv);
	JNIEXPORT jobject JNICALL Java_Electric_getLibrary(JNIEnv *env, jobject obj,
		jstring name);
	JNIEXPORT jobject JNICALL Java_Electric_newLibrary(JNIEnv *env, jobject obj,
		jstring libname, jstring libfile);
	JNIEXPORT void JNICALL Java_Electric_killLibrary(JNIEnv *env, jobject obj,
		jobject lib);
	JNIEXPORT void JNICALL Java_Electric_eraseLibrary(JNIEnv *env, jobject obj,
		jobject lib);
	JNIEXPORT void JNICALL Java_Electric_selectLibrary(JNIEnv *env, jobject obj,
		jobject lib);
	JNIEXPORT jobject JNICALL Java_Electric_getNodeProto(JNIEnv *env, jobject obj,
		jstring name);
	JNIEXPORT jobject JNICALL Java_Electric_newNodeProto(JNIEnv *env, jobject obj,
		jstring name, jobject lib);
	JNIEXPORT jint JNICALL Java_Electric_killNodeProto(JNIEnv *env, jobject obj,
		jobject facet);
	JNIEXPORT jobject JNICALL Java_Electric_copyNodeProto(JNIEnv *env, jobject obj,
		jobject facet, jobject lib, jstring name);
	JNIEXPORT jobject JNICALL Java_Electric_iconView(JNIEnv *env, jobject obj,
		jobject facet);
	JNIEXPORT jobject JNICALL Java_Electric_contentsView(JNIEnv *env, jobject obj,
		jobject facet);
	JNIEXPORT jobject JNICALL Java_Electric_newNodeInst(JNIEnv *env, jobject obj,
		jobject proto, jint lx, jint hx, jint ly, jint hy, jint trans, jint rot, jobject facet);
	JNIEXPORT void JNICALL Java_Electric_modifyNodeInst(JNIEnv *env, jobject obj,
		jobject node, jint dlx, jint dly, jint dhx, jint dhy, jint drot, jint dtrans);
	JNIEXPORT jint JNICALL Java_Electric_killNodeInst(JNIEnv *env, jobject obj,
		jobject node);
	JNIEXPORT jobject JNICALL Java_Electric_replaceNodeInst(JNIEnv *env, jobject obj,
		jobject node, jobject proto);
	JNIEXPORT jint JNICALL Java_Electric_nodeFunction(JNIEnv *env, jobject obj,
		jobject node);
	JNIEXPORT jint JNICALL Java_Electric_nodePolys(JNIEnv *env, jobject obj,
		jobject node);
	JNIEXPORT jobject JNICALL Java_Electric_shapeNodePoly(JNIEnv *env, jobject obj,
		jobject node, jint jindex);
	JNIEXPORT jint JNICALL Java_Electric_nodeEPolys(JNIEnv *env, jobject obj,
		jobject node);
	JNIEXPORT jobject JNICALL Java_Electric_shapeENodePoly(JNIEnv *env, jobject obj,
		jobject node, jint jindex);
	JNIEXPORT jobject JNICALL Java_Electric_makeRot(JNIEnv *env, jobject obj,
		jobject node);
	JNIEXPORT jobject JNICALL Java_Electric_makeTrans(JNIEnv *env, jobject obj,
		jobject node);
	JNIEXPORT jobject JNICALL Java_Electric_newArcInst(JNIEnv *env, jobject obj,
		jobject proto, jint wid, jint bits, jobject node1, jobject port1, jint x1, jint y1,
		jobject node2, jobject port2, jint x2, jint y2, jobject facet);
	JNIEXPORT jint JNICALL Java_Electric_modifyArcInst(JNIEnv *env, jobject obj,
		jobject arc, jint dwid, jint dx1, jint dy1, jint dx2, jint dy2);
	JNIEXPORT jint JNICALL Java_Electric_killArcInst(JNIEnv *env, jobject obj,
		jobject arc);
	JNIEXPORT jobject JNICALL Java_Electric_replaceArcInst(JNIEnv *env, jobject obj,
		jobject arc, jobject proto);
	JNIEXPORT jint JNICALL Java_Electric_arcPolys(JNIEnv *env, jobject obj,
		jobject arc);
	JNIEXPORT jobject JNICALL Java_Electric_shapeArcPoly(JNIEnv *env, jobject obj,
		jobject arc, jint jindex);
	JNIEXPORT jobject JNICALL Java_Electric_newPortProto(JNIEnv *env, jobject obj,
		jobject facet, jobject node, jobject port, jstring name);
	JNIEXPORT jobjectArray JNICALL Java_Electric_portPosition(JNIEnv *env, jobject obj,
		jobject jni, jobject jpp);
	JNIEXPORT jobject JNICALL Java_Electric_getPortProto(JNIEnv *env, jobject obj,
		jobject facet, jstring name);
	JNIEXPORT jint JNICALL Java_Electric_killPortProto(JNIEnv *env, jobject obj,
		jobject facet, jobject port);
	JNIEXPORT jint JNICALL Java_Electric_movePortProto(JNIEnv *env, jobject obj,
		jobject facet, jobject oldport, jobject newnode, jobject newport);
	JNIEXPORT jint JNICALL Java_Electric_undoABatch(JNIEnv *env, jobject obj);
	JNIEXPORT void JNICALL Java_Electric_noUndoAllowed(JNIEnv *env, jobject obj);
	JNIEXPORT jobject JNICALL Java_Electric_getView(JNIEnv *env, jobject obj,
		jstring name);
	JNIEXPORT jobject JNICALL Java_Electric_newView(JNIEnv *env, jobject obj,
		jstring name, jstring sname);
	JNIEXPORT jint JNICALL Java_Electric_killView(JNIEnv *env, jobject obj,
		jobject view);
	JNIEXPORT jobject JNICALL Java_Electric_getArcProto(JNIEnv *env, jobject obj,
		jstring name);
	JNIEXPORT jobject JNICALL Java_Electric_getCell(JNIEnv *env, jobject obj,
		jstring name);
	JNIEXPORT jobject JNICALL Java_Electric_getTechnology(JNIEnv *env, jobject obj,
		jstring name);
	JNIEXPORT jobject JNICALL Java_Electric_getPinProto(JNIEnv *env, jobject obj,
		jobject arcproto);
	JNIEXPORT jobject JNICALL Java_Electric_getNetwork(JNIEnv *env, jobject obj,
		jstring name, jobject facet);
	JNIEXPORT jstring JNICALL Java_Electric_layerName(JNIEnv *env, jobject obj,
		jobject jtech, jint jlayer);
	JNIEXPORT jint JNICALL Java_Electric_layerFunction(JNIEnv *env, jobject obj,
		jobject jtech, jint jlayer);
	JNIEXPORT jint JNICALL Java_Electric_maxDRCSurround(JNIEnv *env, jobject obj,
		jobject jtech, jobject jlib, jint jlayer);
	JNIEXPORT jint JNICALL Java_Electric_DRCMinDistance(JNIEnv *env, jobject obj,
		jobject jtech, jobject jlib, jint jlayer1, jint jlayer2, jint jconnected);
	JNIEXPORT jint JNICALL Java_Electric_DRCMinWidth(JNIEnv *env, jobject obj,
		jobject jtech, jobject jlib, jint jlayer);
	JNIEXPORT void JNICALL Java_Electric_xformPoly(JNIEnv *env, jobject obj,
		jobject jpoly, jobject jtrans);
	JNIEXPORT void JNICALL Java_Electric_freePolygon(JNIEnv *env, jobject obj,
		jobject jpoly);
	JNIEXPORT jobject JNICALL Java_Electric_getTraversalPath(JNIEnv *env, jobject obj);

	JNIEXPORT void JNICALL Java_Electric_eoutWriteOne(JNIEnv *env, jobject obj,
		jint byte);
	JNIEXPORT void JNICALL Java_Electric_eoutWriteString(JNIEnv *env, jobject obj,
		jstring string);
}

static JNINativeMethod electricmethods[] =
{
	/***************** DATABASE EXAMINATION ROUTINES *****************/
	{"curLib",
		"()LCOM/staticfreesoft/electric$library;",
		(void *)Java_Electric_curLib},
	{"curTech",
		"()LCOM/staticfreesoft/electric$technology;",
		(void *)Java_Electric_curTech},
	{"getVal",
		"(LCOM/staticfreesoft/electric$nodeinst;Ljava/lang/String;)Ljava/lang/Object;",
		(void *)Java_Electric_getValNodeinst},
	{"getVal",
		"(LCOM/staticfreesoft/electric$nodeproto;Ljava/lang/String;)Ljava/lang/Object;",
		(void *)Java_Electric_getValNodeproto},
	{"getVal",
		"(LCOM/staticfreesoft/electric$portarcinst;Ljava/lang/String;)Ljava/lang/Object;",
		(void *)Java_Electric_getValPortarcinst},
	{"getVal",
		"(LCOM/staticfreesoft/electric$portexpinst;Ljava/lang/String;)Ljava/lang/Object;",
		(void *)Java_Electric_getValPortexpinst},
	{"getVal",
		"(LCOM/staticfreesoft/electric$portproto;Ljava/lang/String;)Ljava/lang/Object;",
		(void *)Java_Electric_getValPortproto},
	{"getVal",
		"(LCOM/staticfreesoft/electric$arcinst;Ljava/lang/String;)Ljava/lang/Object;",
		(void *)Java_Electric_getValArcinst},
	{"getVal",
		"(LCOM/staticfreesoft/electric$arcproto;Ljava/lang/String;)Ljava/lang/Object;",
		(void *)Java_Electric_getValArcproto},
	{"getVal",
		"(LCOM/staticfreesoft/electric$geom;Ljava/lang/String;)Ljava/lang/Object;",
		(void *)Java_Electric_getValGeom},
	{"getVal",
		"(LCOM/staticfreesoft/electric$library;Ljava/lang/String;)Ljava/lang/Object;",
		(void *)Java_Electric_getValLibrary},
	{"getVal",
		"(LCOM/staticfreesoft/electric$technology;Ljava/lang/String;)Ljava/lang/Object;",
		(void *)Java_Electric_getValTechnology},
	{"getVal",
		"(LCOM/staticfreesoft/electric$aid;Ljava/lang/String;)Ljava/lang/Object;",
		(void *)Java_Electric_getValAid},
	{"getVal",
		"(LCOM/staticfreesoft/electric$rtnode;Ljava/lang/String;)Ljava/lang/Object;",
		(void *)Java_Electric_getValRTNode},
	{"getVal",
		"(LCOM/staticfreesoft/electric$network;Ljava/lang/String;)Ljava/lang/Object;",
		(void *)Java_Electric_getValNetwork},
	{"getVal",
		"(LCOM/staticfreesoft/electric$cell;Ljava/lang/String;)Ljava/lang/Object;",
		(void *)Java_Electric_getValCell},
	{"getVal",
		"(LCOM/staticfreesoft/electric$view;Ljava/lang/String;)Ljava/lang/Object;",
		(void *)Java_Electric_getValView},
	{"getVal",
		"(LCOM/staticfreesoft/electric$windowpart;Ljava/lang/String;)Ljava/lang/Object;",
		(void *)Java_Electric_getValWindowpart},
	{"getVal",
		"(LCOM/staticfreesoft/electric$windowframe;Ljava/lang/String;)Ljava/lang/Object;",
		(void *)Java_Electric_getValWindowframe},
	{"getVal",
		 "(LCOM/staticfreesoft/electric$graphics;Ljava/lang/String;)Ljava/lang/Object;",
		 (void *)Java_Electric_getValGraphics},
	{"getVal",
		"(LCOM/staticfreesoft/electric$constraint;Ljava/lang/String;)Ljava/lang/Object;",
		(void *)Java_Electric_getValConstraint},
	{"getVal",
		"(LCOM/staticfreesoft/electric$polygon;Ljava/lang/String;)Ljava/lang/Object;",
		(void *)Java_Electric_getValPolygon},
	{"setVal",
		"(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;I)V",
		(void *)Java_Electric_setVal},
	{"setInd",
		"(Ljava/lang/Object;Ljava/lang/String;ILjava/lang/Object;)V",
		(void *)Java_Electric_setInd},
	{"delVal",
		"(Ljava/lang/Object;Ljava/lang/String;)V",
		(void *)Java_Electric_delVal},
	{"initSearch",
		"(IIIILCOM/staticfreesoft/electric$nodeproto;)I",
		(void *)Java_Electric_initSearch},
	{"nextObject",
		"(I)Ljava/lang/Object;",
		(void *)Java_Electric_nextObject},
	{"termSearch",
		"(I)V",
		(void *)Java_Electric_termSearch},

	/***************** AID ROUTINES *****************/
	{"getAid",
		"(Ljava/lang/String;)LCOM/staticfreesoft/electric$aid;",
		(void *)Java_Electric_getAid},
	{"maxAid",
		"()I",
		(void *)Java_Electric_maxAid},
	{"indexAid",
		"(I)LCOM/staticfreesoft/electric$aid;",
		(void *)Java_Electric_indexAid},
	{"aidTurnOn",
		"(LCOM/staticfreesoft/electric$aid;I)V",
		(void *)Java_Electric_aidTurnOn},
	{"aidTurnOff",
		"(LCOM/staticfreesoft/electric$aid;)V",
		(void *)Java_Electric_aidTurnOff},
	{"tellAid",
		"(LCOM/staticfreesoft/electric$aid;I[Ljava/lang/String;)V",
		(void *)Java_Electric_tellAid},

	/***************** LIBRARY ROUTINES *****************/
	{"getLibrary",
		"(Ljava/lang/String;)LCOM/staticfreesoft/electric$library;",
		(void *)Java_Electric_getLibrary},
	{"newLibrary",
		"(Ljava/lang/String;Ljava/lang/String;)LCOM/staticfreesoft/electric$library;",
		(void *)Java_Electric_newLibrary},
	{"killLibrary",
		"(LCOM/staticfreesoft/electric$library;)V",
		(void *)Java_Electric_killLibrary},
	{"eraseLibrary",
		"(LCOM/staticfreesoft/electric$library;)V",
		(void *)Java_Electric_eraseLibrary},
	{"selectLibrary",
		"(LCOM/staticfreesoft/electric$library;)V",
		(void *)Java_Electric_selectLibrary},

	/***************** NODEPROTO ROUTINES *****************/
	{"getNodeProto",
		"(Ljava/lang/String;)LCOM/staticfreesoft/electric$nodeproto;",
		(void *)Java_Electric_getNodeProto},
	{"newNodeProto",
		"(Ljava/lang/String;LCOM/staticfreesoft/electric$library;)LCOM/staticfreesoft/electric$nodeproto;",
		(void *)Java_Electric_newNodeProto},
	{"killNodeProto",
		"(LCOM/staticfreesoft/electric$nodeproto;)I",
		(void *)Java_Electric_killNodeProto},
	{"copyNodeProto",
		"(LCOM/staticfreesoft/electric$nodeproto;LCOM/staticfreesoft/electric$library;Ljava/lang/String;)LCOM/staticfreesoft/electric$nodeproto;",
		(void *)Java_Electric_copyNodeProto},
	{"iconView",
		"(LCOM/staticfreesoft/electric$nodeproto;)LCOM/staticfreesoft/electric$nodeproto;",
		(void *)Java_Electric_iconView},
	{"contentsView",
		"(LCOM/staticfreesoft/electric$nodeproto;)LCOM/staticfreesoft/electric$nodeproto;",
		(void *)Java_Electric_contentsView},

	/***************** NODEINST ROUTINES *****************/
	{"newNodeInst",
		"(LCOM/staticfreesoft/electric$nodeproto;IIIIIILCOM/staticfreesoft/electric$nodeproto;)LCOM/staticfreesoft/electric$nodeinst;",
		(void *)Java_Electric_newNodeInst},
	{"modifyNodeInst",
		"(LCOM/staticfreesoft/electric$nodeinst;IIIIII)V",
		(void *)Java_Electric_modifyNodeInst},
	{"killNodeInst",
		"(LCOM/staticfreesoft/electric$nodeinst;)I",
		(void *)Java_Electric_killNodeInst},
	{"replaceNodeInst",
		"(LCOM/staticfreesoft/electric$nodeinst;LCOM/staticfreesoft/electric$nodeproto;)LCOM/staticfreesoft/electric$nodeinst;",
		(void *)Java_Electric_replaceNodeInst},
	{"nodeFunction",
		"(LCOM/staticfreesoft/electric$nodeinst;)I",
		(void *)Java_Electric_nodeFunction},
	{"nodePolys",
		"(LCOM/staticfreesoft/electric$nodeinst;)I",
		(void *)Java_Electric_nodePolys},
	{"shapeNodePoly",
		"(LCOM/staticfreesoft/electric$nodeinst;I)LCOM/staticfreesoft/electric$polygon;",
		(void *)Java_Electric_shapeNodePoly},
	{"nodeEPolys",
		"(LCOM/staticfreesoft/electric$nodeinst;)I",
		(void *)Java_Electric_nodeEPolys},
	{"shapeENodePoly",
		"(LCOM/staticfreesoft/electric$nodeinst;I)LCOM/staticfreesoft/electric$polygon;",
		(void *)Java_Electric_shapeENodePoly},
	{"makeRot",
		"(LCOM/staticfreesoft/electric$nodeinst;)LCOM/staticfreesoft/electric$xarray;",
		(void *)Java_Electric_makeRot},
	{"makeTrans",
		"(LCOM/staticfreesoft/electric$nodeinst;)LCOM/staticfreesoft/electric$xarray;",
		(void *)Java_Electric_makeTrans},

	/***************** ARCINST ROUTINES *****************/
	{"newArcInst",
		"(LCOM/staticfreesoft/electric$arcproto;IILCOM/staticfreesoft/electric$nodeinst;LCOM/staticfreesoft/electric$portproto;IILCOM/staticfreesoft/electric$nodeinst;LCOM/staticfreesoft/electric$portproto;IILCOM/staticfreesoft/electric$nodeproto;)LCOM/staticfreesoft/electric$arcinst;",
		(void *)Java_Electric_newArcInst},
	{"modifyArcInst",
		 "(LCOM/staticfreesoft/electric$arcinst;IIIII)I",
		 (void *)Java_Electric_modifyArcInst},
	{"killArcInst",
		"(LCOM/staticfreesoft/electric$arcinst;)I",
		(void *)Java_Electric_killArcInst},
	{"replaceArcInst",
		 "(LCOM/staticfreesoft/electric$arcinst;LCOM/staticfreesoft/electric$arcproto;)LCOM/staticfreesoft/electric$arcinst;",
		 (void *)Java_Electric_replaceArcInst},
	{"arcPolys",
		"(LCOM/staticfreesoft/electric$arcinst;)I",
		(void *)Java_Electric_arcPolys},
	{"shapeArcPoly",
		"(LCOM/staticfreesoft/electric$arcinst;I)LCOM/staticfreesoft/electric$polygon;",
		(void *)Java_Electric_shapeArcPoly},

	/***************** PORTPROTO ROUTINES *****************/
	{"newPortProto",
		"(LCOM/staticfreesoft/electric$nodeproto;LCOM/staticfreesoft/electric$nodeinst;LCOM/staticfreesoft/electric$portproto;Ljava/lang/String;)LCOM/staticfreesoft/electric$portproto;",
		(void *)Java_Electric_newPortProto},
	{"portPosition",
		"(LCOM/staticfreesoft/electric$nodeinst;LCOM/staticfreesoft/electric$portproto;)[Ljava/lang/Integer;",
		(void *)Java_Electric_portPosition},
	{"getPortProto",
		"(LCOM/staticfreesoft/electric$nodeproto;Ljava/lang/String;)LCOM/staticfreesoft/electric$portproto;",
		(void *)Java_Electric_getPortProto},
	{"killPortProto",
		"(LCOM/staticfreesoft/electric$nodeproto;LCOM/staticfreesoft/electric$portproto;)I",
		(void *)Java_Electric_killPortProto},
	{"movePortProto",
		"(LCOM/staticfreesoft/electric$nodeproto;LCOM/staticfreesoft/electric$portproto;LCOM/staticfreesoft/electric$nodeinst;LCOM/staticfreesoft/electric$portproto;)I",
		(void *)Java_Electric_movePortProto},

	/***************** CHANGE CONTROL ROUTINES *****************/
	{"undoABatch",
		"()I",
		(void *)Java_Electric_undoABatch},
	{"noUndoAllowed",
		 "()V",
		 (void *)Java_Electric_noUndoAllowed},

	/***************** VIEW ROUTINES *****************/
	{"getView",
		"(Ljava/lang/String;)LCOM/staticfreesoft/electric$view;",
		(void *)Java_Electric_getView},
	{"newView",
		"(Ljava/lang/String;Ljava/lang/String;)LCOM/staticfreesoft/electric$view;",
		(void *)Java_Electric_newView},
	{"killView",
		"(LCOM/staticfreesoft/electric$view;)I",
		(void *)Java_Electric_killView},

	/***************** MISCELLANEOUS ROUTINES *****************/
	{"getArcProto",
		"(Ljava/lang/String;)LCOM/staticfreesoft/electric$arcproto;",
		(void *)Java_Electric_getArcProto},
	{"getCell",
		"(Ljava/lang/String;)LCOM/staticfreesoft/electric$cell;",
		(void *)Java_Electric_getCell},
	{"getTechnology",
		"(Ljava/lang/String;)LCOM/staticfreesoft/electric$technology;",
		(void *)Java_Electric_getTechnology},
	{"getPinProto",
		"(LCOM/staticfreesoft/electric$arcproto;)LCOM/staticfreesoft/electric$nodeproto;",
		(void *)Java_Electric_getPinProto},
	{"getNetwork",
		"(Ljava/lang/String;LCOM/staticfreesoft/electric$nodeproto;)LCOM/staticfreesoft/electric$network;",
		(void *)Java_Electric_getNetwork},
	{"layerName",
		"(LCOM/staticfreesoft/electric$technology;I)Ljava/lang/String;",
		(void *)Java_Electric_layerName},
	{"layerFunction",
		"(LCOM/staticfreesoft/electric$technology;I)I",
		(void *)Java_Electric_layerFunction},
	{"maxDRCSurround",
		"(LCOM/staticfreesoft/electric$technology;LCOM/staticfreesoft/electric$library;I)I",
		(void *)Java_Electric_maxDRCSurround},
	{"DRCMinDistance",
		"(LCOM/staticfreesoft/electric$technology;LCOM/staticfreesoft/electric$library;III)I",
		(void *)Java_Electric_DRCMinDistance},
	{"DRCMinWidth",
		"(LCOM/staticfreesoft/electric$technology;LCOM/staticfreesoft/electric$library;I)I",
		(void *)Java_Electric_DRCMinWidth},
	{"xformPoly",
		"(LCOM/staticfreesoft/electric$polygon;LCOM/staticfreesoft/electric$xarray;)V",
		(void *)Java_Electric_xformPoly},
	{"freePolygon",
		"(LCOM/staticfreesoft/electric$polygon;)V",
		(void *)Java_Electric_freePolygon},
	{"getTraversalPath",
		"()[LCOM/staticfreesoft/electric$nodeinst;",
		(void *)Java_Electric_getTraversalPath}
};

static JNINativeMethod electriceoutmethods[] =
{
	{"write",
		"(I)V",
		(void *)Java_Electric_eoutWriteOne},
	{"ewrite",
		"(Ljava/lang/String;)V",
		(void *)Java_Electric_eoutWriteString}
};

/* prototypes for local routines */
jint JNICALL java_vfprintf(FILE *fp, const char *format, va_list args);
void JNICALL java_exit(jint code);
jobject java_makeobject(INTBIG addr, INTBIG type);
jobject java_getval(jobject obj, INTBIG type, jstring jname);
char *java_describeobject(jobject obj);
void java_addcharacter(char chr);
void java_getobjectaddrtype(jobject obj, INTBIG *addr, INTBIG *type);
INTSML java_allocarraybuffer(INTBIG size);
jobject java_makejavaobject(INTBIG addr, INTBIG type, jclass javaclass, INTBIG desttype);
INTSML java_reportexceptions(void);

/****************************** ELECTRIC INTERFACE ******************************/

/*
 * Routine to free all memory associated with this module.
 */
void java_freememory(void)
{
	if (java_arraybuffersize > 0)
		efree((char *)java_arraybuffer);
}

void java_init(void)
{
	char *userclasspath, *usersettings, pathsep, *properties[10];
	INTBIG ac;

	if (java_inited != 0) return;
	java_inited = 1;

	/* request a JAVA version */
	java_vmargs.version = 0x00010001;
	if (JNI_GetDefaultJavaVMInitArgs(&java_vmargs) != 0)
	{
		ttyputerr(_("Cannot initialize Java VM"));
		return;
	}

	/* include the location of the Electric class file */
#ifdef WIN32
	pathsep = ';';
#else
	pathsep = ':';
#endif
	(void)initinfstr();
	(void)addstringtoinfstr(java_vmargs.classpath);
	(void)addtoinfstr(pathsep);
	(void)addtoinfstr('.');
	userclasspath = egetenv("CLASSPATH");
	if (userclasspath != 0)
	{
		(void)addtoinfstr(pathsep);
		(void)addstringtoinfstr(userclasspath);
	}
	(void)addtoinfstr(pathsep);
	(void)addstringtoinfstr(el_libdir);
	(void)addstringtoinfstr("java");
	(void)allocstring(&java_vmargs.classpath, returninfstr(), db_cluster);

	/* set java properties */
	ac = 0;
	properties[ac++] = "java.compiler=NONE";

	/* special case for PAR router */
	usersettings = egetenv("ELECTRIC_PARDIR");
	if (usersettings != 0)
	{
		properties[ac++] = usersettings;
	} else
	{
		(void)initinfstr();
		(void)addstringtoinfstr("config.dir=");
		(void)addstringtoinfstr(el_libdir);
		(void)addstringtoinfstr("prouter");
		properties[ac++] = returninfstr();
	}
	properties[ac] = 0;
	java_vmargs.properties = properties;

	/* set overrides */
	java_vmargs.vfprintf = java_vfprintf;
	java_vmargs.exit = java_exit;

	/* load and initialize a Java VM, return a JNI interface pointer in env */
	if (JNI_CreateJavaVM(&java_virtualmachine, (void **)&java_environment, &java_vmargs) != 0)
	{
		ttyputerr(_("Cannot create Java VM"));
		return;
	}

	/* get the basic Electric class and register native methods */
	java_electricclass = java_environment->FindClass("COM/staticfreesoft/electric");
	if (java_electricclass == 0) return;
	if (java_environment->RegisterNatives(java_electricclass, electricmethods,
		sizeof(electricmethods)/sizeof(JNINativeMethod)) < 0)
			ttyputerr(_("Failed to register native interfaces"));

	/* override the "write" method of out "eout" class */
	java_electriceoutclass = java_environment->FindClass("COM/staticfreesoft/electric$eout");
	if (java_electriceoutclass == 0) return;
	if (java_environment->RegisterNatives(java_electriceoutclass, electriceoutmethods, 2) < 0)
		ttyputerr(_("Failed to register output interface"));
	jobject object = java_environment->AllocObject(java_electriceoutclass);
	jmethodID mid = java_environment->GetMethodID(java_electriceoutclass, "takeover", "()V");
	java_environment->CallVoidMethod(object, mid);

	/* get the attribute pointer to the "address" field on each class */
	java_addressID = java_environment->GetFieldID(java_electricclass, "address", "I");

	/* create the null object */
	java_nullobject = java_environment->AllocObject(java_electricclass);
	java_environment->SetIntField(java_nullobject, java_addressID, -1);
	java_environment->NewGlobalRef(java_nullobject);

	/* get the basic subclasses */
	java_classstring = java_environment->FindClass("java/lang/String");
	if (java_classstring == 0) return;
	java_classint = java_environment->FindClass("java/lang/Integer");
	if (java_classint == 0) return;
	java_classfloat = java_environment->FindClass("java/lang/Float");
	if (java_classfloat == 0) return;
	java_classarrayint = java_environment->FindClass("[I");
	if (java_classarrayint == 0) return;

	/* get the methods on the basic subclasses */
	java_midIntValue = java_environment->GetMethodID(java_classint, "intValue", "()I");
	java_midFloatValue = java_environment->GetMethodID(java_classfloat, "floatValue", "()F");
	java_midIntInit = java_environment->GetMethodID(java_classint, "<init>", "(I)V");
	java_midFloatInit = java_environment->GetMethodID(java_classfloat, "<init>", "(F)V");

	/* get the basic Electric subclasses */
	java_classnodeinst = java_environment->FindClass("COM/staticfreesoft/electric$nodeinst");
	if (java_classnodeinst == 0) return;
	java_classnodeproto = java_environment->FindClass("COM/staticfreesoft/electric$nodeproto");
	if (java_classnodeproto == 0) return;
	java_classportarcinst = java_environment->FindClass("COM/staticfreesoft/electric$portarcinst");
	if (java_classportarcinst == 0) return;
	java_classportexpinst = java_environment->FindClass("COM/staticfreesoft/electric$portexpinst");
	if (java_classportexpinst == 0) return;
	java_classportproto = java_environment->FindClass("COM/staticfreesoft/electric$portproto");
	if (java_classportproto == 0) return;
	java_classarcinst = java_environment->FindClass("COM/staticfreesoft/electric$arcinst");
	if (java_classarcinst == 0) return;
	java_classarcproto = java_environment->FindClass("COM/staticfreesoft/electric$arcproto");
	if (java_classarcproto == 0) return;
	java_classgeom = java_environment->FindClass("COM/staticfreesoft/electric$geom");
	if (java_classgeom == 0) return;
	java_classlibrary = java_environment->FindClass("COM/staticfreesoft/electric$library");
	if (java_classlibrary == 0) return;
	java_classtechnology = java_environment->FindClass("COM/staticfreesoft/electric$technology");
	if (java_classtechnology == 0) return;
	java_classaid = java_environment->FindClass("COM/staticfreesoft/electric$aid");
	if (java_classaid == 0) return;
	java_classrtnode = java_environment->FindClass("COM/staticfreesoft/electric$rtnode");
	if (java_classrtnode == 0) return;
	java_classnetwork = java_environment->FindClass("COM/staticfreesoft/electric$network");
	if (java_classnetwork == 0) return;
	java_classcell = java_environment->FindClass("COM/staticfreesoft/electric$cell");
	if (java_classcell == 0) return;
	java_classview = java_environment->FindClass("COM/staticfreesoft/electric$view");
	if (java_classview == 0) return;
	java_classwindowpart = java_environment->FindClass("COM/staticfreesoft/electric$windowpart");
	if (java_classwindowpart == 0) return;
	java_classwindowframe = java_environment->FindClass("COM/staticfreesoft/electric$windowframe");
	if (java_classwindowframe == 0) return;
	java_classgraphics = java_environment->FindClass("COM/staticfreesoft/electric$graphics");
	if (java_classgraphics == 0) return;
	java_classconstraint = java_environment->FindClass("COM/staticfreesoft/electric$constraint");
	if (java_classconstraint == 0) return;
	java_classpolygon = java_environment->FindClass("COM/staticfreesoft/electric$polygon");
	if (java_classpolygon == 0) return;
	java_classxarray = java_environment->FindClass("COM/staticfreesoft/electric$xarray");
	if (java_classxarray == 0) return;

	/* get the attribute pointer to the fields on the XARRAY class */
	java_xarrayVID = java_environment->GetFieldID(java_classxarray, "v", "[I");
}

void java_evaluate(char *str)
{
	char *evaluation;
	INTBIG type;

	/* evaluate the string */
	evaluation = java_query(str, &type);
	if (evaluation == 0) return;
	switch (type)
	{
		case METHODRETURNSVOID:
			ttyputmsg("(void)");
			break;
		case METHODRETURNSOBJECT:
			ttyputmsg("(object)%s", evaluation);
			break;
		case METHODRETURNSBOOLEAN:
			ttyputmsg("(boolean)%s", evaluation);
			break;
		case METHODRETURNSBYTE:
			ttyputmsg("(byte)%s", evaluation);
			break;
		case METHODRETURNSCHAR:
			ttyputmsg("(char)%s", evaluation);
			break;
		case METHODRETURNSSHORT:
			ttyputmsg("(short)%s", evaluation);
			break;
		case METHODRETURNSINT:
			ttyputmsg("(int)%s", evaluation);
			break;
		case METHODRETURNSLONG:
			ttyputmsg("(long)%s", evaluation);
			break;
		case METHODRETURNSFLOAT:
			ttyputmsg("(float)%s", evaluation);
			break;
		case METHODRETURNSDOUBLE:
			ttyputmsg("(double)%s", evaluation);
			break;
	}
}

char *java_query(char *str, INTBIG *methodreturntype)
{
	char *pt, *methodName, *thisMethodName, *className, *returnClassName;
	static char resultString[100];
	jclass theClass, classClz, methodClass, returnClass, returnClassClz;
	static jclass modifierClass = 0;
	REGISTER INTBIG len, i, gotMethod;
	char sig[300], *sigpt;
	int modifiers;
	jfloat fvalue;
	jlong lvalue;
	jdouble dvalue;
	jboolean bvalue;
	jobject ovalue;
	jboolean isCopy;
	jmethodID getmethodsmid, mid;
	jobjectArray methodlist, methodParams;
	jobject thisMethod;
	jstring jMethodName, jReturnClassName;

	/* parse string into CLASS.METHOD (must be static and take no parameters) */
	className = str;
	while (*className == ' ' || *className == '\t') className++;
	len = strlen(className);
	for(i=len-1; i>0; i--)
		if (className[i] == '.') break;
	if (i == 0)
	{
		ttyputerr(_("Cannot determine class and method of '%s'"), str);
		return(0);
	}
	methodName = &className[i+1];
	className[i] = 0;
	for(pt = className; *pt != 0; pt++) if (*pt == '.') *pt = '/';

	/* find the class */
	theClass = java_environment->FindClass(className);
	if (theClass == 0)
	{
		ttyputerr(_("Cannot find class '%s'"), className);
		className[i] = '.';
		return(0);
	}
	className[i] = '.';

	/* get the list of methods on "theClass" */
	classClz = java_environment->GetObjectClass(theClass);
	getmethodsmid = java_environment->GetMethodID(classClz, "getMethods",
		"()[Ljava/lang/reflect/Method;");
	methodlist = (jobjectArray)java_environment->CallObjectMethod(theClass, getmethodsmid, NULL);

	/* look at all methods */
	len = java_environment->GetArrayLength(methodlist);
	for(i=0; i<len; i++)
	{
		/* get a method */
		thisMethod = java_environment->GetObjectArrayElement(methodlist, i);

		/* get the method's name */
		methodClass = java_environment->GetObjectClass(thisMethod);
		mid = java_environment->GetMethodID(methodClass, "getName", "()Ljava/lang/String;");
		jMethodName = (jstring)java_environment->CallObjectMethod(thisMethod, mid, NULL);
		thisMethodName = (char *)java_environment->GetStringUTFChars(jMethodName, &isCopy);
		gotMethod = strcmp(methodName, thisMethodName);
		if (isCopy == JNI_TRUE)
			java_environment->ReleaseStringUTFChars((jstring)jMethodName, thisMethodName);
		if (gotMethod != 0) continue;

		/* found method "thisMethod"...it must have zero parameters */
		mid = java_environment->GetMethodID(methodClass, "getParameterTypes", "()[Ljava/lang/Class;");
		methodParams = (jobjectArray)java_environment->CallObjectMethod(thisMethod, mid, NULL);
		if (java_environment->GetArrayLength(methodParams) != 0) continue;

		/* the method must be static */
		mid = java_environment->GetMethodID(methodClass, "getModifiers", "()I");
		modifiers = java_environment->CallIntMethod(thisMethod, mid, NULL);
		if (modifierClass == 0)
			modifierClass = java_environment->FindClass("java/lang/reflect/Modifier");
		mid = java_environment->GetStaticMethodID(modifierClass, "isStatic", "(I)Z");
		if (java_environment->CallStaticBooleanMethod(modifierClass, mid, modifiers) == false) continue;

		/* get the return type of the method */
		mid = java_environment->GetMethodID(methodClass, "getReturnType", "()Ljava/lang/Class;");
		returnClass = (jclass)java_environment->CallObjectMethod(thisMethod, mid, NULL);
		returnClassClz = java_environment->GetObjectClass(returnClass);
		mid = java_environment->GetMethodID(returnClassClz, "toString", "()Ljava/lang/String;");
		jReturnClassName = (jstring)java_environment->CallObjectMethod(returnClass, mid, NULL);
		returnClassName = (char *)java_environment->GetStringUTFChars(jReturnClassName, &isCopy);

		/* convert that return-type to a signature */
		sigpt = sig;
		*sigpt++ = '(';
		*sigpt++ = ')';
		if (strcmp(returnClassName, "void") == 0)
		{
			*sigpt++ = 'V';
			*methodreturntype = METHODRETURNSVOID;
		} else if (strncmp(returnClassName, "class ", 6) == 0)
		{
			*sigpt++ = 'L';
			for(pt = &returnClassName[6]; *pt != 0; pt++)
				if (*pt == '.') *sigpt++ = '/'; else
					*sigpt++ = *pt;
			*sigpt++ = ';';
			*methodreturntype = METHODRETURNSOBJECT;
		} else if (strcmp(returnClassName, "boolean") == 0)
		{
			*sigpt++ = 'Z';
			*methodreturntype = METHODRETURNSBOOLEAN;
		} else if (strcmp(returnClassName, "byte") == 0)
		{
			*sigpt++ = 'B';
			*methodreturntype = METHODRETURNSBYTE;
		} else if (strcmp(returnClassName, "char") == 0)
		{
			*sigpt++ = 'C';
			*methodreturntype = METHODRETURNSCHAR;
		} else if (strcmp(returnClassName, "short") == 0)
		{
			*sigpt++ = 'S';
			*methodreturntype = METHODRETURNSSHORT;
		} else if (strcmp(returnClassName, "int") == 0)
		{
			*sigpt++ = 'I';
			*methodreturntype = METHODRETURNSINT;
		} else if (strcmp(returnClassName, "long") == 0)
		{
			*sigpt++ = 'J';
			*methodreturntype = METHODRETURNSLONG;
		} else if (strcmp(returnClassName, "float") == 0)
		{
			*sigpt++ = 'F';
			*methodreturntype = METHODRETURNSFLOAT;
		} else if (strcmp(returnClassName, "double") == 0)
		{
			*sigpt++ = 'D';
			*methodreturntype = METHODRETURNSDOUBLE;
		} else
		{
			ttyputerr(_("%s returns unrecognized type '%s'"), str, returnClassName);
			return(0);
		}
		*sigpt = 0;
		if (isCopy == JNI_TRUE)
			java_environment->ReleaseStringUTFChars((jstring)jReturnClassName, returnClassName);

		mid = java_environment->GetStaticMethodID(theClass, methodName, sig);
		if (mid == 0)
		{
			ttyputerr(_("Error getting method pointer to %s (signature '%s')"), str, sig);
			return(0);
		}

		/* run the method and print the result */
		switch (*methodreturntype)
		{
			case METHODRETURNSVOID:
				java_environment->CallStaticVoidMethod(theClass, mid);
				if (java_reportexceptions() != 0) return(0);
				return("");
			case METHODRETURNSOBJECT:
				ovalue = java_environment->CallStaticObjectMethod(theClass, mid);
				if (java_reportexceptions() != 0) return(0);
				return(java_describeobject(ovalue));
			case METHODRETURNSBOOLEAN:
				bvalue = java_environment->CallStaticBooleanMethod(theClass, mid);
				if (java_reportexceptions() != 0) return(0);
				sprintf(resultString, "%s", bvalue ? _("True") : _("False"));
				return(resultString);
			case METHODRETURNSBYTE:
				i = java_environment->CallStaticByteMethod(theClass, mid);
				if (java_reportexceptions() != 0) return(0);
				sprintf(resultString, "%d", i);
				return(resultString);
			case METHODRETURNSCHAR:
				i = java_environment->CallStaticCharMethod(theClass, mid);
				if (java_reportexceptions() != 0) return(0);
				sprintf(resultString, "'%c'", i);
				return(resultString);
			case METHODRETURNSSHORT:
				i = java_environment->CallStaticShortMethod(theClass, mid);
				if (java_reportexceptions() != 0) return(0);
				sprintf(resultString, "%d", i);
				return(resultString);
			case METHODRETURNSINT:
				i = java_environment->CallStaticIntMethod(theClass, mid);
				if (java_reportexceptions() != 0) return(0);
				sprintf(resultString, "%ld", i);
				return(resultString);
			case METHODRETURNSLONG:
				lvalue = java_environment->CallStaticLongMethod(theClass, mid);
				if (java_reportexceptions() != 0) return(0);
				sprintf(resultString, "%ld", lvalue);
				return(resultString);
			case METHODRETURNSFLOAT:
				fvalue = java_environment->CallStaticFloatMethod(theClass, mid);
				if (java_reportexceptions() != 0) return(0);
				sprintf(resultString, "%g", fvalue);
				return(resultString);
			case METHODRETURNSDOUBLE:
				dvalue = java_environment->CallStaticDoubleMethod(theClass, mid);
				if (java_reportexceptions() != 0) return(0);
				sprintf(resultString, "%g", dvalue);
				return(resultString);
		}
	}
	ttyputerr(_("Cannot find static method '%s' that takes no parameters"), str);
	return(0);
}

INTSML java_reportexceptions(void)
{
	if (java_environment->ExceptionOccurred() == NULL) return(0);
	java_environment->ExceptionDescribe();
	java_environment->ExceptionClear();
	return(1);
}

/****************************** ELECTRIC DATABASE EXAMINATION ROUTINES ******************************/

JNIEXPORT jobject JNICALL Java_Electric_curLib(JNIEnv *env, jobject obj)
{
	jobject jlib;

	/* convert C result to Java */
	jlib = java_makeobject((INTBIG)el_curlib, VLIBRARY);
	return(jlib);
}

JNIEXPORT jobject JNICALL Java_Electric_curTech(JNIEnv *env, jobject obj)
{
	jobject jtech;

	/* convert C result to Java */
	jtech = java_makeobject((INTBIG)el_curtech, VTECHNOLOGY);
	return(jtech);
}

JNIEXPORT jobject JNICALL Java_Electric_getValNodeinst(JNIEnv *env, jobject obj,
	jobject jobj, jstring jname)
{
	return(java_getval(jobj, VNODEINST, jname));
}

JNIEXPORT jobject JNICALL Java_Electric_getValNodeproto(JNIEnv *env, jobject obj,
	jobject jobj, jstring jname)
{
	return(java_getval(jobj, VNODEPROTO, jname));
}

JNIEXPORT jobject JNICALL Java_Electric_getValPortarcinst(JNIEnv *env, jobject obj,
	jobject jobj, jstring jname)
{
	return(java_getval(jobj, VPORTARCINST, jname));
}

JNIEXPORT jobject JNICALL Java_Electric_getValPortexpinst(JNIEnv *env, jobject obj,
	jobject jobj, jstring jname)
{
	return(java_getval(jobj, VPORTEXPINST, jname));
}

JNIEXPORT jobject JNICALL Java_Electric_getValPortproto(JNIEnv *env, jobject obj,
	jobject jobj, jstring jname)
{
	return(java_getval(jobj, VPORTPROTO, jname));
}

JNIEXPORT jobject JNICALL Java_Electric_getValArcinst(JNIEnv *env, jobject obj,
	jobject jobj, jstring jname)
{
	return(java_getval(jobj, VARCINST, jname));
}

JNIEXPORT jobject JNICALL Java_Electric_getValArcproto(JNIEnv *env, jobject obj,
	jobject jobj, jstring jname)
{
	return(java_getval(jobj, VARCPROTO, jname));
}

JNIEXPORT jobject JNICALL Java_Electric_getValGeom(JNIEnv *env, jobject obj,
	jobject jobj, jstring jname)
{
	return(java_getval(jobj, VGEOM, jname));
}

JNIEXPORT jobject JNICALL Java_Electric_getValLibrary(JNIEnv *env, jobject obj,
	jobject jobj, jstring jname)
{
	return(java_getval(jobj, VLIBRARY, jname));
}

JNIEXPORT jobject JNICALL Java_Electric_getValTechnology(JNIEnv *env, jobject obj,
	jobject jobj, jstring jname)
{
	return(java_getval(jobj, VTECHNOLOGY, jname));
}

JNIEXPORT jobject JNICALL Java_Electric_getValAid(JNIEnv *env, jobject obj,
	jobject jobj, jstring jname)
{
	return(java_getval(jobj, VAID, jname));
}

JNIEXPORT jobject JNICALL Java_Electric_getValRTNode(JNIEnv *env, jobject obj,
	jobject jobj, jstring jname)
{
	return(java_getval(jobj, VRTNODE, jname));
}

JNIEXPORT jobject JNICALL Java_Electric_getValNetwork(JNIEnv *env, jobject obj,
	jobject jobj, jstring jname)
{
	return(java_getval(jobj, VNETWORK, jname));
}

JNIEXPORT jobject JNICALL Java_Electric_getValCell(JNIEnv *env, jobject obj,
	jobject jobj, jstring jname)
{
	return(java_getval(jobj, VCELL, jname));
}

JNIEXPORT jobject JNICALL Java_Electric_getValView(JNIEnv *env, jobject obj,
	jobject jobj, jstring jname)
{
	return(java_getval(jobj, VVIEW, jname));
}

JNIEXPORT jobject JNICALL Java_Electric_getValWindowpart(JNIEnv *env, jobject obj,
	jobject jobj, jstring jname)
{
	return(java_getval(jobj, VWINDOWPART, jname));
}

JNIEXPORT jobject JNICALL Java_Electric_getValWindowframe(JNIEnv *env, jobject obj,
	jobject jobj, jstring jname)
{
	return(java_getval(jobj, VWINDOWFRAME, jname));
}

JNIEXPORT jobject JNICALL Java_Electric_getValGraphics(JNIEnv *env, jobject obj,
	jobject jobj, jstring jname)
{
	return(java_getval(jobj, VGRAPHICS, jname));
}

JNIEXPORT jobject JNICALL Java_Electric_getValConstraint(JNIEnv *env, jobject obj,
	jobject jobj, jstring jname)
{
	return(java_getval(jobj, VCONSTRAINT, jname));
}

JNIEXPORT jobject JNICALL Java_Electric_getValPolygon(JNIEnv *env, jobject obj,
	jobject jobj, jstring jname)
{
	return(java_getval(jobj, VPOLYGON, jname));
}

jobject java_getval(jobject jobj, INTBIG type, jstring jname)
{
	const char *name;
	jboolean isCopy;
	jobject retval;
	INTBIG addr;
	REGISTER VARIABLE *var;

	/* convert Java parameters to C */
	if (jobj == 0) return(java_nullobject);
	addr = java_environment->GetIntField(jobj, java_addressID);
	name = java_environment->GetStringUTFChars(jname, &isCopy);

	/* make the Electric call */
	var = getval(addr, type, -1, (char *)name);
	if (isCopy == JNI_TRUE) java_environment->ReleaseStringUTFChars(jname, name);

	/* convert C result to Java */
	if (var == NOVARIABLE) return(java_nullobject);
	retval = java_makeobject(var->addr, var->type);
	return(retval);
}

JNIEXPORT void JNICALL Java_Electric_setVal(JNIEnv *env, jobject obj,
	jobject jobj, jstring jname, jobject jattr, jint jbits)
{
	const char *name;
	jboolean isCopy;
	INTBIG addr, type, bits, newaddr, newtype;

	/* convert Java parameters to C */
	if (jobj == 0) return;
	if (jattr == 0) return;
	java_getobjectaddrtype(jobj, &addr, &type);
	name = java_environment->GetStringUTFChars(jname, &isCopy);
	java_getobjectaddrtype(jattr, &newaddr, &newtype);
	bits = jbits;

	/* make the Electric call */
	(void)setval(addr, type, (char *)name, newaddr, newtype|bits);
	if (isCopy == JNI_TRUE) java_environment->ReleaseStringUTFChars(jname, name);
}

JNIEXPORT void JNICALL Java_Electric_setInd(JNIEnv *env, jobject obj,
	jobject jobj, jstring jname, jint jindex, jobject jattr)
{
	const char *name;
	jboolean isCopy;
	INTBIG addr, type, index, newaddr, newtype;

	/* convert Java parameters to C */
	if (jobj == 0) return;
	if (jattr == 0) return;
	java_getobjectaddrtype(jobj, &addr, &type);
	name = java_environment->GetStringUTFChars(jname, &isCopy);
	index = jindex;
	java_getobjectaddrtype(jattr, &newaddr, &newtype);

	/* make the Electric call */
	(void)setind(addr, type, (char *)name, index, newaddr);
	if (isCopy == JNI_TRUE) java_environment->ReleaseStringUTFChars(jname, name);
}

JNIEXPORT void JNICALL Java_Electric_delVal(JNIEnv *env, jobject obj,
	jobject jobj, jstring jname)
{
	const char *name;
	jboolean isCopy;
	INTBIG addr, type;

	/* convert Java parameters to C */
	if (jobj == 0) return;
	java_getobjectaddrtype(jobj, &addr, &type);
	name = java_environment->GetStringUTFChars(jname, &isCopy);

	/* make the Electric call */
	(void)delval(addr, type, (char *)name);
	if (isCopy == JNI_TRUE) java_environment->ReleaseStringUTFChars(jname, name);
}

JNIEXPORT jint JNICALL Java_Electric_initSearch(JNIEnv *env, jobject obj,
	jint jlx, jint jhx, jint jly, jint jhy, jobject jfacet)
{
	NODEPROTO *facet;
	INTBIG sea, lx, hx, ly, hy;
	jint jsea;

	/* convert Java parameters to C */
	lx = jlx;   hx = jhx;
	ly = jly;   hy = jhy;
	if (jfacet == 0) return(0);
	facet = (NODEPROTO *)java_environment->GetIntField(jfacet, java_addressID);

	/* make the Electric call */
	sea = initsearch(lx, hx, ly, hy, facet);

	/* convert C result to Java */
	jsea = sea;
	return(jsea);
}

JNIEXPORT jobject JNICALL Java_Electric_nextObject(JNIEnv *env, jobject obj,
	jint jsea)
{
	GEOM *geom;
	jobject jgeom;
	INTBIG sea;

	/* convert Java parameters to C */
	if (jsea == 0) return(java_nullobject);
	sea = jsea;

	/* make the Electric call */
	geom = nextobject(sea);

	/* convert C result to Java */
	jgeom = java_makeobject((INTBIG)geom, VGEOM);
	return(jgeom);
}

JNIEXPORT void JNICALL Java_Electric_termSearch(JNIEnv *env, jobject obj,
	jint jsea)
{
	INTBIG sea;

	/* convert Java parameters to C */
	if (jsea == 0) return;
	sea = jsea;

	/* make the Electric call */
	termsearch(sea);
}

/****************************** ELECTRIC AID ROUTINES ******************************/

JNIEXPORT jobject JNICALL Java_Electric_getAid(JNIEnv *env, jobject obj,
	jstring jname)
{
	jboolean isCopy;
	char *name;
	AIDENTRY *aid;
	jobject jaid;

	/* convert Java parameters to C */
	name = (char *)java_environment->GetStringUTFChars(jname, &isCopy);

	/* make the Electric call */
	aid = getaid(name);
	if (isCopy == JNI_TRUE) java_environment->ReleaseStringUTFChars(jname, name);

	/* convert C result to Java */
	jaid = java_makeobject((INTBIG)aid, VAID);
	return(jaid);
}

JNIEXPORT jint JNICALL Java_Electric_maxAid(JNIEnv *env, jobject obj)
{
	jint jmaxaid;

	/* convert C result to Java */
	jmaxaid = el_maxaid;
	return(jmaxaid);
}

JNIEXPORT jobject JNICALL Java_Electric_indexAid(JNIEnv *env, jobject obj,
	jint jindex)
{
	INTBIG index;
	AIDENTRY *aid;
	jobject jaid;

	/* convert Java parameters to C */
	index = jindex;

	/* make the Electric call */
	if (index < 0 || index >= el_maxaid) aid = NOAID; else aid = &el_aids[index];

	/* convert C result to Java */
	jaid = java_makeobject((INTBIG)aid, VAID);
	return(jaid);
}

JNIEXPORT void JNICALL Java_Electric_aidTurnOn(JNIEnv *env, jobject obj,
	jobject jaid, jint jnocatchup)
{
	AIDENTRY *aid;
	INTSML nocatchup;

	/* convert Java parameters to C */
	if (jaid == 0) return;
	aid = (AIDENTRY *)java_environment->GetIntField(jaid, java_addressID);
	nocatchup = (INTSML)jnocatchup;

	/* make the Electric call */
	aidturnon(aid, nocatchup);
}

JNIEXPORT void JNICALL Java_Electric_aidTurnOff(JNIEnv *env, jobject obj,
	jobject jaid)
{
	AIDENTRY *aid;

	/* convert Java parameters to C */
	if (jaid == 0) return;
	aid = (AIDENTRY *)java_environment->GetIntField(jaid, java_addressID);

	/* make the Electric call */
	aidturnoff(aid, 1);
}

JNIEXPORT void JNICALL Java_Electric_tellAid(JNIEnv *env, jobject obj,
	jobject jaid, jint jargc, jobjectArray jargv)
{
	jboolean *isCopy;
	char **argv;
	jstring str;
	INTSML argc, i;
	AIDENTRY *aid;

	/* convert Java parameters to C */
	if (jaid == 0) return;
	if (jargc == 0) return;
	aid = (AIDENTRY *)java_environment->GetIntField(jaid, java_addressID);
	argc = (INTSML)jargc;
	isCopy = (jboolean *)emalloc(argc * (sizeof (jboolean)), el_tempcluster);
	argv = (char **)emalloc(argc * (sizeof (char *)), el_tempcluster);
	for(i=0; i<argc; i++)
	{
		str = (jstring)java_environment->GetObjectArrayElement(jargv, i);
		argv[i] = (char *)java_environment->GetStringUTFChars(str, &isCopy[i]);
	}

	/* make the Electric call */
	tellaid(aid, argc, argv);
	for(i=0; i<argc; i++)
	{
		str = (jstring)java_environment->GetObjectArrayElement(jargv, i);
		if (isCopy[i] == JNI_TRUE) java_environment->ReleaseStringUTFChars(str, argv[i]);
	}
	efree((char *)isCopy);
	efree((char *)argv);
}

/****************************** ELECTRIC LIBRARY ROUTINES ******************************/

JNIEXPORT jobject JNICALL Java_Electric_getLibrary(JNIEnv *env, jobject obj,
	jstring jname)
{
	jboolean isCopy;
	char *name;
	LIBRARY *lib;
	jobject jlib;

	/* convert Java parameters to C */
	name = (char *)java_environment->GetStringUTFChars(jname, &isCopy);

	/* make the Electric call */
	lib = getlibrary(name);
	if (isCopy == JNI_TRUE) java_environment->ReleaseStringUTFChars(jname, name);

	/* convert C result to Java */
	jlib = java_makeobject((INTBIG)lib, VLIBRARY);
	return(jlib);
}

JNIEXPORT jobject JNICALL Java_Electric_newLibrary(JNIEnv *env, jobject obj,
	jstring jlibname, jstring jlibfile)
{
	jboolean isCopy1, isCopy2;
	char *libname, *libfile;
	LIBRARY *lib;
	jobject jlib;

	/* convert Java parameters to C */
	libname = (char *)java_environment->GetStringUTFChars(jlibname, &isCopy1);
	libfile = (char *)java_environment->GetStringUTFChars(jlibfile, &isCopy2);

	/* make the Electric call */
	lib = newlibrary(libname, libfile);
	if (isCopy1 == JNI_TRUE) java_environment->ReleaseStringUTFChars(jlibname, libname);
	if (isCopy2 == JNI_TRUE) java_environment->ReleaseStringUTFChars(jlibfile, libfile);

	/* convert C result to Java */
	jlib = java_makeobject((INTBIG)lib, VLIBRARY);
	return(jlib);
}

JNIEXPORT void JNICALL Java_Electric_killLibrary(JNIEnv *env, jobject obj,
	jobject jlib)
{
	LIBRARY *lib;

	/* convert Java parameters to C */
	if (jlib == 0) return;
	lib = (LIBRARY *)java_environment->GetIntField(jlib, java_addressID);

	/* make the Electric call */
	killlibrary(lib);
}

JNIEXPORT void JNICALL Java_Electric_eraseLibrary(JNIEnv *env, jobject obj,
	jobject jlib)
{
	LIBRARY *lib;

	/* convert Java parameters to C */
	if (jlib == 0) return;
	lib = (LIBRARY *)java_environment->GetIntField(jlib, java_addressID);

	/* make the Electric call */
	eraselibrary(lib);
}

JNIEXPORT void JNICALL Java_Electric_selectLibrary(JNIEnv *env, jobject obj,
	jobject jlib)
{
	LIBRARY *lib;

	/* convert Java parameters to C */
	if (jlib == 0) return;
	lib = (LIBRARY *)java_environment->GetIntField(jlib, java_addressID);

	/* make the Electric call */
	selectlibrary(lib);
}

/****************************** ELECTRIC LIBRARY ROUTINES ******************************/

JNIEXPORT jobject JNICALL Java_Electric_getNodeProto(JNIEnv *env, jobject obj,
	jstring jname)
{
	jboolean isCopy;
	char *name;
	NODEPROTO *np;
	jobject jnp;

	/* convert Java parameters to C */
	name = (char *)java_environment->GetStringUTFChars(jname, &isCopy);

	/* make the Electric call */
	np = getnodeproto(name);
	if (isCopy == JNI_TRUE) java_environment->ReleaseStringUTFChars(jname, name);

	/* convert C result to Java */
	jnp = java_makeobject((INTBIG)np, VNODEPROTO);
	return(jnp);
}

JNIEXPORT jobject JNICALL Java_Electric_newNodeProto(JNIEnv *env, jobject obj,
	jstring jname, jobject jlib)
{
	jboolean isCopy;
	char *name;
	NODEPROTO *np;
	LIBRARY *lib;
	jobject jnp;

	/* convert Java parameters to C */
	name = (char *)java_environment->GetStringUTFChars(jname, &isCopy);
	if (jlib == 0) return(java_nullobject);
	lib = (LIBRARY *)java_environment->GetIntField(jlib, java_addressID);

	/* make the Electric call */
	np = newnodeproto(name, lib);
	if (np != NONODEPROTO) endobjectchange((INTBIG)np, VNODEPROTO);
	if (isCopy == JNI_TRUE) java_environment->ReleaseStringUTFChars(jname, name);

	/* convert C result to Java */
	jnp = java_makeobject((INTBIG)np, VNODEPROTO);
	return(jnp);
}

JNIEXPORT jint JNICALL Java_Electric_killNodeProto(JNIEnv *env, jobject obj,
	jobject jfacet)
{
	INTSML ret;
	jint jret;
	NODEPROTO *facet;

	/* convert Java parameters to C */
	if (jfacet == 0) return(1);
	facet = (NODEPROTO *)java_environment->GetIntField(jfacet, java_addressID);

	/* make the Electric call */
	startobjectchange((INTBIG)facet, VNODEPROTO);
	ret = killnodeproto(facet);

	/* convert C result to Java */
	jret = ret;
	return(jret);
}

JNIEXPORT jobject JNICALL Java_Electric_copyNodeProto(JNIEnv *env, jobject obj,
	jobject jfacet, jobject jlib, jstring jname)
{
	jboolean isCopy;
	char *name;
	NODEPROTO *np, *facet;
	LIBRARY *lib;
	jobject jnp;

	/* convert Java parameters to C */
	if (jfacet == 0) return(java_nullobject);
	if (jlib == 0) return(java_nullobject);
	facet = (NODEPROTO *)java_environment->GetIntField(jfacet, java_addressID);
	lib = (LIBRARY *)java_environment->GetIntField(jlib, java_addressID);
	name = (char *)java_environment->GetStringUTFChars(jname, &isCopy);

	/* make the Electric call */
	np = copynodeproto(facet, lib, name);
	if (np != NONODEPROTO) endobjectchange((INTBIG)np, VNODEPROTO);
	if (isCopy == JNI_TRUE) java_environment->ReleaseStringUTFChars(jname, name);

	/* convert C result to Java */
	jnp = java_makeobject((INTBIG)np, VNODEPROTO);
	return(jnp);
}

JNIEXPORT jobject JNICALL Java_Electric_iconView(JNIEnv *env, jobject obj,
	jobject jfacet)
{
	jobject jiconfacet;
	NODEPROTO *facet, *iconfacet;

	/* convert Java parameters to C */
	if (jfacet == 0) return(java_nullobject);
	facet = (NODEPROTO *)java_environment->GetIntField(jfacet, java_addressID);

	/* make the Electric call */
	iconfacet = iconview(facet);

	/* convert C result to Java */
	jiconfacet = java_makeobject((INTBIG)iconfacet, VNODEPROTO);
	return(jiconfacet);
}

JNIEXPORT jobject JNICALL Java_Electric_contentsView(JNIEnv *env, jobject obj,
	jobject jfacet)
{
	jobject jcontentsfacet;
	NODEPROTO *facet, *contentsfacet;

	/* convert Java parameters to C */
	if (jfacet == 0) return(java_nullobject);
	facet = (NODEPROTO *)java_environment->GetIntField(jfacet, java_addressID);

	/* make the Electric call */
	contentsfacet = contentsview(facet);

	/* convert C result to Java */
	jcontentsfacet = java_makeobject((INTBIG)contentsfacet, VNODEPROTO);
	return(jcontentsfacet);
}

/****************************** ELECTRIC NODEINST ROUTINES ******************************/

JNIEXPORT jobject JNICALL Java_Electric_newNodeInst(JNIEnv *env, jobject obj,
	jobject jproto, jint jlx, jint jhx, jint jly, jint jhy, jint jtrans, jint jrot, jobject jfacet)
{
	jobject jni;
	NODEINST *ni;
	NODEPROTO *facet, *proto;
	INTBIG lx, hx, ly, hy;
	INTSML rot, trans;

	/* convert Java parameters to C */
	if (jproto == 0) return(java_nullobject);
	if (jfacet == 0) return(java_nullobject);
	proto = (NODEPROTO *)java_environment->GetIntField(jproto, java_addressID);
	lx = jlx;   hx = jhx;
	ly = jly;   hy = jhy;
	trans = (INTSML)jtrans;
	rot = (INTSML)jrot;
	facet = (NODEPROTO *)java_environment->GetIntField(jfacet, java_addressID);

	/* make the Electric call */
	ni = newnodeinst(proto, lx, hx, ly, hy, trans, rot, facet);
	if (ni != NONODEINST) endobjectchange((INTBIG)ni, VNODEINST);

	/* convert C result to Java */
	jni = java_makeobject((INTBIG)ni, VNODEINST);
	return(jni);
}

JNIEXPORT void JNICALL Java_Electric_modifyNodeInst(JNIEnv *env, jobject obj,
	jobject jni, jint jdlx, jint jdly, jint jdhx, jint jdhy, jint jdrot, jint jdtrans)
{
	NODEINST *ni;
	INTBIG dlx, dhx, dly, dhy;
	INTSML drot, dtrans;

	/* convert Java parameters to C */
	if (jni == 0) return;
	ni = (NODEINST *)java_environment->GetIntField(jni, java_addressID);
	dlx = jdlx;   dhx = jdhx;
	dly = jdly;   dhy = jdhy;
	drot = (INTSML)jdrot;
	dtrans = (INTSML)jdtrans;

	/* make the Electric call */
	startobjectchange((INTBIG)ni, VNODEINST);
	modifynodeinst(ni, dlx, dly, dhx, dhy, drot, dtrans);
	endobjectchange((INTBIG)ni, VNODEINST);
}

JNIEXPORT jint JNICALL Java_Electric_killNodeInst(JNIEnv *env, jobject obj,
	jobject jni)
{
	NODEINST *ni;
	INTSML ret;
	jint jret;

	/* convert Java parameters to C */
	if (jni == 0) return(1);
	ni = (NODEINST *)java_environment->GetIntField(jni, java_addressID);

	/* make the Electric call */
	startobjectchange((INTBIG)ni, VNODEINST);
	ret = killnodeinst(ni);

	/* convert C result to Java */
	jret = ret;
	return(jret);
}

JNIEXPORT jobject JNICALL Java_Electric_replaceNodeInst(JNIEnv *env, jobject obj,
	jobject jni, jobject jproto)
{
	NODEINST *ni, *newni;
	NODEPROTO *proto;
	jobject jnewni;

	/* convert Java parameters to C */
	if (jni == 0) return(java_nullobject);
	if (jproto == 0) return(java_nullobject);
	ni = (NODEINST *)java_environment->GetIntField(jni, java_addressID);
	proto = (NODEPROTO*)java_environment->GetIntField(jproto, java_addressID);

	/* make the Electric call */
	startobjectchange((INTBIG)ni, VNODEINST);
	newni = replacenodeinst(ni, proto, 0);
	if (newni != NONODEINST) endobjectchange((INTBIG)newni, VNODEINST);

	/* convert C result to Java */
	jnewni = java_makeobject((INTBIG)newni, VNODEINST);
	return(jnewni);
}

JNIEXPORT jint JNICALL Java_Electric_nodeFunction(JNIEnv *env, jobject obj,
	jobject jni)
{
	NODEINST *ni;
	INTSML fun;
	jint jfun;
	char *dummy;

	/* convert Java parameters to C */
	if (jni == 0) return(0);
	ni = (NODEINST *)java_environment->GetIntField(jni, java_addressID);

	/* make the Electric call */
	fun = nodefunction(ni, &dummy);

	/* convert C result to Java */
	jfun = fun;
	return(jfun);
}

JNIEXPORT jint JNICALL Java_Electric_nodePolys(JNIEnv *env, jobject obj,
	jobject jni)
{
	NODEINST *ni;
	INTBIG count;
	jint jcount;

	/* convert Java parameters to C */
	if (jni == 0) return(0);
	ni = (NODEINST *)java_environment->GetIntField(jni, java_addressID);

	/* make the Electric call */
	count = nodepolys(ni, 0);

	/* convert C result to Java */
	jcount = count;
	return(jcount);
}

JNIEXPORT jobject JNICALL Java_Electric_shapeNodePoly(JNIEnv *env, jobject obj,
	jobject jni, jint jindex)
{
	NODEINST *ni;
	INTSML index;
	jobject jpoly;
	POLYGON *poly;

	/* convert Java parameters to C */
	if (jni == 0) return(java_nullobject);
	ni = (NODEINST *)java_environment->GetIntField(jni, java_addressID);
	index = (INTSML)jindex;

	/* make the Electric call */
	poly = allocpolygon(4, db_cluster);
	shapenodepoly(ni, index, poly);

	/* convert C result to Java */
	jpoly = java_makeobject((INTBIG)poly, VPOLYGON);
	return(jpoly);
}

JNIEXPORT jint JNICALL Java_Electric_nodeEPolys(JNIEnv *env, jobject obj,
	jobject jni)
{
	NODEINST *ni;
	INTBIG count;
	jint jcount;

	/* convert Java parameters to C */
	if (jni == 0) return(0);
	ni = (NODEINST *)java_environment->GetIntField(jni, java_addressID);

	/* make the Electric call */
	count = nodeEpolys(ni, 0);

	/* convert C result to Java */
	jcount = count;
	return(jcount);
}

JNIEXPORT jobject JNICALL Java_Electric_shapeENodePoly(JNIEnv *env, jobject obj,
	jobject jni, jint jindex)
{
	NODEINST *ni;
	INTSML index;
	jobject jpoly;
	POLYGON *poly;

	/* convert Java parameters to C */
	if (jni == 0) return(java_nullobject);
	ni = (NODEINST *)java_environment->GetIntField(jni, java_addressID);
	index = (INTSML)jindex;

	/* make the Electric call */
	poly = allocpolygon(4, db_cluster);
	shapeEnodepoly(ni, index, poly);

	/* convert C result to Java */
	jpoly = java_makeobject((INTBIG)poly, VPOLYGON);
	return(jpoly);
}

JNIEXPORT jobject JNICALL Java_Electric_makeRot(JNIEnv *env, jobject obj,
	jobject jni)
{
	NODEINST *ni;
	XARRAY trans;
	jobject object;
	jintArray vArray;

	/* convert Java parameters to C */
	if (jni == 0) return(java_nullobject);
	ni = (NODEINST *)java_environment->GetIntField(jni, java_addressID);

	/* make the Electric call */
	makerot(ni, trans);

	/* convert C result to Java */
	object = java_environment->AllocObject(java_classxarray);
	vArray = java_environment->NewIntArray(9);
	java_environment->SetIntArrayRegion(vArray, 0, 9, &trans[0][0]);
	java_environment->SetObjectField(object, java_xarrayVID, (jobject)vArray);
	return(object);
}

JNIEXPORT jobject JNICALL Java_Electric_makeTrans(JNIEnv *env, jobject obj,
	jobject jni)
{
	NODEINST *ni;
	XARRAY trans;
	jobject object;
	jintArray vArray;

	/* convert Java parameters to C */
	if (jni == 0) return(java_nullobject);
	ni = (NODEINST *)java_environment->GetIntField(jni, java_addressID);

	/* make the Electric call */
	maketrans(ni, trans);

	/* convert C result to Java */
	object = java_environment->AllocObject(java_classxarray);
	vArray = java_environment->NewIntArray(9);
	java_environment->SetIntArrayRegion(vArray, 0, 9, &trans[0][0]);
	java_environment->SetObjectField(object, java_xarrayVID, (jobject)vArray);
	return(object);
}

/****************************** ELECTRIC ARCINST ROUTINES ******************************/

JNIEXPORT jobject JNICALL Java_Electric_newArcInst(JNIEnv *env, jobject obj,
	jobject jproto, jint jwid, jint jbits, jobject jni1, jobject jpp1, jint jx1, jint jy1,
	jobject jni2, jobject jpp2, jint jx2, jint jy2, jobject jfacet)
{
	jobject jai;
	ARCINST *ai;
	NODEPROTO *facet;
	NODEINST *ni1, *ni2;
	PORTPROTO *pp1, *pp2;
	ARCPROTO *proto;
	INTBIG wid, bits, x1, y1, x2, y2;

	/* convert Java parameters to C */
	if (jproto == 0) return(java_nullobject);
	if (jni1 == 0 || jpp1 == 0) return(java_nullobject);
	if (jni2 == 0 || jpp2 == 0) return(java_nullobject);
	if (jfacet == 0) return(java_nullobject);
	proto = (ARCPROTO *)java_environment->GetIntField(jproto, java_addressID);
	wid = jwid;   bits = jbits;
	ni1 = (NODEINST *)java_environment->GetIntField(jni1, java_addressID);
	pp1 = (PORTPROTO *)java_environment->GetIntField(jpp1, java_addressID);
	x1 = jx1;   y1 = jy1;
	ni2 = (NODEINST *)java_environment->GetIntField(jni2, java_addressID);
	pp2 = (PORTPROTO *)java_environment->GetIntField(jpp2, java_addressID);
	x2 = jx2;   y2 = jy2;
	facet = (NODEPROTO *)java_environment->GetIntField(jfacet, java_addressID);

	/* make the Electric call */
	ai = newarcinst(proto, wid, bits, ni1, pp1, x1, y1, ni2, pp2, x2, y2, facet);
	if (ai != NOARCINST) endobjectchange((INTBIG)ai, VARCINST);

	/* convert C result to Java */
	jai = java_makeobject((INTBIG)ai, VARCINST);
	return(jai);
}

JNIEXPORT jint JNICALL Java_Electric_modifyArcInst(JNIEnv *env, jobject obj,
	jobject jai, jint jdwid, jint jdx1, jint jdy1, jint jdx2, jint jdy2)
{
	ARCINST *ai;
	INTBIG dwid, dx1, dy1, dx2, dy2;
	INTSML ret;
	jint jret;

	/* convert Java parameters to C */
	if (jai == 0) return(1);
	ai = (ARCINST *)java_environment->GetIntField(jai, java_addressID);
	dwid = jdwid;
	dx1 = jdx1;   dy1 = jdy1;
	dx2 = jdx2;   dy2 = jdy2;

	/* make the Electric call */
	startobjectchange((INTBIG)ai, VARCINST);
	ret = modifyarcinst(ai, dwid, dx1, dy1, dx2, dy2);
	endobjectchange((INTBIG)ai, VARCINST);

	/* convert C result to Java */
	jret = ret;
	return(jret);
}

JNIEXPORT jint JNICALL Java_Electric_killArcInst(JNIEnv *env, jobject obj,
	jobject jai)
{
	ARCINST *ai;
	INTSML ret;
	jint jret;

	/* convert Java parameters to C */
	if (jai == 0) return(1);
	ai = (ARCINST *)java_environment->GetIntField(jai, java_addressID);

	/* make the Electric call */
	startobjectchange((INTBIG)ai, VARCINST);
	ret = killarcinst(ai);

	/* convert C result to Java */
	jret = ret;
	return(jret);
}

JNIEXPORT jobject JNICALL Java_Electric_replaceArcInst(JNIEnv *env, jobject obj,
	jobject jai, jobject jap)
{
	ARCINST *ai, *newai;
	ARCPROTO *ap;
	jobject jnewai;

	/* convert Java parameters to C */
	if (jai == 0) return(java_nullobject);
	if (jap == 0) return(java_nullobject);
	ai = (ARCINST *)java_environment->GetIntField(jai, java_addressID);
	ap = (ARCPROTO *)java_environment->GetIntField(jap, java_addressID);

	/* make the Electric call */
	startobjectchange((INTBIG)ai, VARCINST);
	newai = replacearcinst(ai, ap);
	if (newai != NOARCINST) endobjectchange((INTBIG)newai, VARCINST);

	/* convert C result to Java */
	jnewai = java_makeobject((INTBIG)newai, VARCINST);
	return(jnewai);
}

JNIEXPORT jint JNICALL Java_Electric_arcPolys(JNIEnv *env, jobject obj,
	jobject jai)
{
	ARCINST *ai;
	INTBIG count;
	jint jcount;

	/* convert Java parameters to C */
	if (jai == 0) return(0);
	ai = (ARCINST *)java_environment->GetIntField(jai, java_addressID);

	/* make the Electric call */
	count = arcpolys(ai);

	/* convert C result to Java */
	jcount = count;
	return(jcount);
}

JNIEXPORT jobject JNICALL Java_Electric_shapeArcPoly(JNIEnv *env, jobject obj,
	jobject jai, jint jindex)
{
	ARCINST *ai;
	INTSML index;
	jobject jpoly;
	POLYGON *poly;

	/* convert Java parameters to C */
	if (jai == 0) return(java_nullobject);
	ai = (ARCINST *)java_environment->GetIntField(jai, java_addressID);
	index = (INTSML)jindex;

	/* make the Electric call */
	poly = allocpolygon(4, db_cluster);
	shapearcpoly(ai, index, poly);

	/* convert C result to Java */
	jpoly = java_makeobject((INTBIG)poly, VPOLYGON);
	return(jpoly);

}

/****************************** ELECTRIC PORTPROTO ROUTINES ******************************/

JNIEXPORT jobject JNICALL Java_Electric_newPortProto(JNIEnv *env, jobject obj,
	jobject jnp, jobject jni, jobject jpp, jstring jname)
{
	NODEPROTO *np;
	jboolean isCopy;
	NODEINST *ni;
	PORTPROTO *pp, *newpp;
	char *name;
	jobject jnewpp;

	/* convert Java parameters to C */
	if (jnp == 0) return(java_nullobject);
	if (jni == 0) return(java_nullobject);
	if (jpp == 0) return(java_nullobject);
	np = (NODEPROTO *)java_environment->GetIntField(jnp, java_addressID);
	ni = (NODEINST *)java_environment->GetIntField(jni, java_addressID);
	pp = (PORTPROTO *)java_environment->GetIntField(jpp, java_addressID);
	name = (char *)java_environment->GetStringUTFChars(jname, &isCopy);

	/* make the Electric call */
	newpp = newportproto(np, ni, pp, name);
	if (isCopy == JNI_TRUE) java_environment->ReleaseStringUTFChars(jname, name);

	/* convert C result to Java */
	jnewpp = java_makeobject((INTBIG)newpp, VPORTPROTO);
	return(jnewpp);
}

JNIEXPORT jobjectArray JNICALL Java_Electric_portPosition(JNIEnv *env, jobject obj,
	jobject jni, jobject jpp)
{
	NODEINST *ni;
	PORTPROTO *pp;
	INTBIG x, y;
	jobjectArray retarray;

	/* convert Java parameters to C */
	if (jni == 0) return((jobjectArray)java_nullobject);
	if (jpp == 0) return((jobjectArray)java_nullobject);
	ni = (NODEINST *)java_environment->GetIntField(jni, java_addressID);
	pp = (PORTPROTO *)java_environment->GetIntField(jpp, java_addressID);

	/* make the Electric call */
	portposition(ni, pp, &x, &y);

	/* convert C result to Java */
	retarray = java_environment->NewObjectArray(2, java_classint, NULL);
	java_environment->SetObjectArrayElement(retarray, 0, java_makeobject(x, VINTEGER));
	java_environment->SetObjectArrayElement(retarray, 1, java_makeobject(y, VINTEGER));
	return(retarray);
}

JNIEXPORT jobject JNICALL Java_Electric_getPortProto(JNIEnv *env, jobject obj,
	jobject jnp, jstring jname)
{
	NODEPROTO *np;
	PORTPROTO *pp;
	jboolean isCopy;
	char *name;
	jobject jpp;

	/* convert Java parameters to C */
	if (jnp == 0) return(java_nullobject);
	np = (NODEPROTO *)java_environment->GetIntField(jnp, java_addressID);
	name = (char *)java_environment->GetStringUTFChars(jname, &isCopy);

	/* make the Electric call */
	pp = getportproto(np, name);
	if (isCopy == JNI_TRUE) java_environment->ReleaseStringUTFChars(jname, name);

	/* convert C result to Java */
	jpp = java_makeobject((INTBIG)pp, VPORTPROTO);
	return(jpp);
}

JNIEXPORT jint JNICALL Java_Electric_killPortProto(JNIEnv *env, jobject obj,
	jobject jnp, jobject jpp)
{
	NODEPROTO *np;
	PORTPROTO *pp;
	INTSML ret;
	jint jret;

	/* convert Java parameters to C */
	if (jnp == 0) return(1);
	if (jpp == 0) return(1);
	np = (NODEPROTO *)java_environment->GetIntField(jnp, java_addressID);
	pp = (PORTPROTO *)java_environment->GetIntField(jpp, java_addressID);

	/* make the Electric call */
	ret = killportproto(np, pp);

	/* convert C result to Java */
	jret = ret;
	return(jret);
}

JNIEXPORT jint JNICALL Java_Electric_movePortProto(JNIEnv *env, jobject obj,
	jobject jnp, jobject joldpp, jobject jni, jobject jpp)
{
	NODEPROTO *np;
	NODEINST *ni;
	PORTPROTO *pp, *oldpp;
	INTSML ret;
	jint jret;

	/* convert Java parameters to C */
	if (jnp == 0) return(1);
	if (joldpp == 0) return(1);
	if (jni == 0) return(1);
	if (jpp == 0) return(1);
	np = (NODEPROTO *)java_environment->GetIntField(jnp, java_addressID);
	oldpp = (PORTPROTO *)java_environment->GetIntField(joldpp, java_addressID);
	ni = (NODEINST *)java_environment->GetIntField(jni, java_addressID);
	pp = (PORTPROTO *)java_environment->GetIntField(jpp, java_addressID);

	/* make the Electric call */
	ret = moveportproto(np, oldpp, ni, pp);

	/* convert C result to Java */
	jret = ret;
	return(jret);
}

/****************************** ELECTRIC CHANGE CONTROL ROUTINES ******************************/

JNIEXPORT jint JNICALL Java_Electric_undoABatch(JNIEnv *env, jobject obj)
{
	AIDENTRY *aid;
	INTSML ret;
	jint jret;

	/* make the Electric call */
	ret = undoabatch(&aid);

	/* convert C result to Java */
	jret = ret;
	return(jret);
}

JNIEXPORT void JNICALL Java_Electric_noUndoAllowed(JNIEnv *env, jobject obj)
{
	/* make the Electric call */
	noundoallowed();
}

/****************************** ELECTRIC VIEW ROUTINES ******************************/

JNIEXPORT jobject JNICALL Java_Electric_getView(JNIEnv *env, jobject obj,
	jstring jname)
{
	jboolean isCopy;
	char *name;
	VIEW *view;
	jobject jview;

	/* convert Java parameters to C */
	name = (char *)java_environment->GetStringUTFChars(jname, &isCopy);

	/* make the Electric call */
	view = getview(name);
	if (isCopy == JNI_TRUE) java_environment->ReleaseStringUTFChars(jname, name);

	/* convert C result to Java */
	jview = java_makeobject((INTBIG)view, VVIEW);
	return(jview);
}

JNIEXPORT jobject JNICALL Java_Electric_newView(JNIEnv *env, jobject obj,
	jstring jname, jstring jsname)
{
	jboolean isCopy1, isCopy2;
	char *name, *sname;
	VIEW *view;
	jobject jview;

	/* convert Java parameters to C */
	name = (char *)java_environment->GetStringUTFChars(jname, &isCopy1);
	sname = (char *)java_environment->GetStringUTFChars(jsname, &isCopy2);

	/* make the Electric call */
	view = newview(name, sname);
	if (isCopy1 == JNI_TRUE) java_environment->ReleaseStringUTFChars(jname, name);
	if (isCopy2 == JNI_TRUE) java_environment->ReleaseStringUTFChars(jsname, sname);

	/* convert C result to Java */
	jview = java_makeobject((INTBIG)view, VVIEW);
	return(jview);
}

JNIEXPORT jint JNICALL Java_Electric_killView(JNIEnv *env, jobject obj,
	jobject jview)
{
	VIEW *view;
	INTSML ret;
	jint jret;

	/* convert Java parameters to C */
	if (jview == 0) return(1);
	view = (VIEW *)java_environment->GetIntField(jview, java_addressID);

	/* make the Electric call */
	ret = killview(view);

	/* convert C result to Java */
	jret = ret;
	return(jret);
}

/****************************** ELECTRIC MISCELLANEOUS ROUTINES ******************************/

JNIEXPORT jobject JNICALL Java_Electric_getArcProto(JNIEnv *env, jobject obj,
	jstring jname)
{
	jboolean isCopy;
	char *name;
	ARCPROTO *ap;
	jobject jap;

	/* convert Java parameters to C */
	name = (char *)java_environment->GetStringUTFChars(jname, &isCopy);

	/* make the Electric call */
	ap = getarcproto(name);
	if (isCopy == JNI_TRUE) java_environment->ReleaseStringUTFChars(jname, name);

	/* convert C result to Java */
	jap = java_makeobject((INTBIG)ap, VARCPROTO);
	return(jap);
}

JNIEXPORT jobject JNICALL Java_Electric_getCell(JNIEnv *env, jobject obj,
	jstring jname)
{
	jboolean isCopy;
	char *name;
	CELL *cell;
	jobject jcell;

	/* convert Java parameters to C */
	name = (char *)java_environment->GetStringUTFChars(jname, &isCopy);

	/* make the Electric call */
	cell = getcell(name);
	if (isCopy == JNI_TRUE) java_environment->ReleaseStringUTFChars(jname, name);

	/* convert C result to Java */
	jcell = java_makeobject((INTBIG)cell, VCELL);
	return(jcell);
}

JNIEXPORT jobject JNICALL Java_Electric_getTechnology(JNIEnv *env, jobject obj,
	jstring jname)
{
	jboolean isCopy;
	char *name;
	TECHNOLOGY *tech;
	jobject jtech;

	/* convert Java parameters to C */
	name = (char *)java_environment->GetStringUTFChars(jname, &isCopy);

	/* make the Electric call */
	tech = gettechnology(name);
	if (isCopy == JNI_TRUE) java_environment->ReleaseStringUTFChars(jname, name);

	/* convert C result to Java */
	jtech = java_makeobject((INTBIG)tech, VTECHNOLOGY);
	return(jtech);
}

JNIEXPORT jobject JNICALL Java_Electric_getPinProto(JNIEnv *env, jobject obj,
	jobject jap)
{
	ARCPROTO *ap;
	NODEPROTO *np;
	jobject jnp;

	/* convert Java parameters to C */
	if (jap == 0) return(java_nullobject);
	ap = (ARCPROTO *)java_environment->GetIntField(jap, java_addressID);

	/* make the Electric call */
	np = getpinproto(ap);

	/* convert C result to Java */
	jnp = java_makeobject((INTBIG)np, VNODEPROTO);
	return(jnp);
}

JNIEXPORT jobject JNICALL Java_Electric_getNetwork(JNIEnv *env, jobject obj,
	jstring jname, jobject jnp)
{
	NETWORK *net;
	NODEPROTO *np;
	jobject jnet;
	jboolean isCopy;
	char *name;

	/* convert Java parameters to C */
	if (jnp == 0) return(java_nullobject);
	name = (char *)java_environment->GetStringUTFChars(jname, &isCopy);
	np = (NODEPROTO *)java_environment->GetIntField(jnp, java_addressID);

	/* make the Electric call */
	net = getnetwork(name, np);
	if (isCopy == JNI_TRUE) java_environment->ReleaseStringUTFChars(jname, name);

	/* convert C result to Java */
	jnet = java_makeobject((INTBIG)net, VNETWORK);
	return(jnet);
}

JNIEXPORT jstring JNICALL Java_Electric_layerName(JNIEnv *env, jobject obj,
	jobject jtech, jint jlayer)
{
	TECHNOLOGY *tech;
	INTSML layer;
	char *name;
	jstring jname;

	/* convert Java parameters to C */
	if (jtech == 0) return(0);
	tech = (TECHNOLOGY *)java_environment->GetIntField(jtech, java_addressID);
	layer = (INTSML)jlayer;

	/* make the Electric call */
	name = layername(tech, layer);

	/* convert C result to Java */
	jname = java_environment->NewStringUTF(name);
	return(jname);
}

JNIEXPORT jint JNICALL Java_Electric_layerFunction(JNIEnv *env, jobject obj,
	jobject jtech, jint jlayer)
{
	TECHNOLOGY *tech;
	INTSML layer;
	INTBIG fun;
	jint jfun;

	/* convert Java parameters to C */
	if (jtech == 0) return(0);
	tech = (TECHNOLOGY *)java_environment->GetIntField(jtech, java_addressID);
	layer = (INTSML)jlayer;

	/* make the Electric call */
	fun = layerfunction(tech, layer);

	/* convert C result to Java */
	jfun = fun;
	return(jfun);
}

JNIEXPORT jint JNICALL Java_Electric_maxDRCSurround(JNIEnv *env, jobject obj,
	jobject jtech, jobject jlib, jint jlayer)
{
	TECHNOLOGY *tech;
	LIBRARY *lib;
	INTSML layer;
	INTBIG dist;
	jint jdist;

	/* convert Java parameters to C */
	if (jtech == 0 || jlib == 0) return(0);
	tech = (TECHNOLOGY *)java_environment->GetIntField(jtech, java_addressID);
	lib = (LIBRARY *)java_environment->GetIntField(jlib, java_addressID);
	layer = (INTSML)jlayer;

	/* make the Electric call */
	dist = maxdrcsurround(tech, lib, layer);

	/* convert C result to Java */
	jdist = dist;
	return(jdist);
}

JNIEXPORT jint JNICALL Java_Electric_DRCMinDistance(JNIEnv *env, jobject obj,
	jobject jtech, jobject jlib, jint jlayer1, jint jlayer2, jint jconnected)
{
	TECHNOLOGY *tech;
	LIBRARY *lib;
	INTSML layer1, layer2, connected;
	INTBIG dist;
	jint jdist;

	/* convert Java parameters to C */
	if (jtech == 0 || jlib == 0) return(0);
	tech = (TECHNOLOGY *)java_environment->GetIntField(jtech, java_addressID);
	lib = (LIBRARY *)java_environment->GetIntField(jlib, java_addressID);
	layer1 = (INTSML)jlayer1;
	layer2 = (INTSML)jlayer2;
	connected = (INTSML)jconnected;

	/* make the Electric call */
	dist = drcmindistance(tech, lib, layer1, layer2, connected);

	/* convert C result to Java */
	jdist = dist;
	return(jdist);
}

JNIEXPORT jint JNICALL Java_Electric_DRCMinWidth(JNIEnv *env, jobject obj,
	jobject jtech, jobject jlib, jint jlayer)
{
	TECHNOLOGY *tech;
	LIBRARY *lib;
	INTSML layer;
	INTBIG dist;
	jint jdist;

	/* convert Java parameters to C */
	if (jtech == 0 || jlib == 0) return(0);
	tech = (TECHNOLOGY *)java_environment->GetIntField(jtech, java_addressID);
	lib = (LIBRARY *)java_environment->GetIntField(jlib, java_addressID);
	layer = (INTSML)jlayer;

	/* make the Electric call */
	dist = drcminwidth(tech, lib, layer);

	/* convert C result to Java */
	jdist = dist;
	return(jdist);
}

JNIEXPORT void JNICALL Java_Electric_xformPoly(JNIEnv *env, jobject obj,
	jobject jpoly, jobject jtrans)
{
	XARRAY trans;
	POLYGON *poly;
	INTBIG i;
	jintArray vArray;

	/* convert Java parameters to C */
	if (jpoly == 0 || jtrans == 0) return;
	poly = (POLYGON *)java_environment->GetIntField(jpoly, java_addressID);
	vArray = (jintArray)java_environment->GetObjectField(jtrans, java_xarrayVID);
	java_environment->GetIntArrayRegion(vArray, 0, 9, &trans[0][0]);

	/* make the Electric call */
	for(i=0; i<poly->count; i++)
		xform(poly->xv[i], poly->yv[i], &poly->xv[i], &poly->yv[i], trans);
}

JNIEXPORT void JNICALL Java_Electric_freePolygon(JNIEnv *env, jobject obj,
	jobject jpoly)
{
	POLYGON *poly;

	/* convert Java parameters to C */
	if (jpoly == 0) return;
	poly = (POLYGON *)java_environment->GetIntField(jpoly, java_addressID);

	/* make the Electric call */
	freepolygon(poly);
}

JNIEXPORT jobject JNICALL Java_Electric_getTraversalPath(JNIEnv *env, jobject obj)
{
	NODEINST **nilist;
	INTSML depth, i;
	jobjectArray retarray;

	/* make the Electric call */
	gettraversalpath(&nilist, &depth);

	/* convert C result to Java */
	retarray = java_environment->NewObjectArray((depth+1), java_classnodeinst, NULL);
	for(i=0; i<depth; i++)
		java_environment->SetObjectArrayElement(retarray, i,
			java_makeobject((INTBIG)nilist[i], VNODEINST));
	java_environment->SetObjectArrayElement(retarray, depth,
		java_makeobject((INTBIG)NONODEINST, VNODEINST));
	return(retarray);
}

/****************************** SUPPORT ******************************/

/*
 * Helper routine to buffer characters that are sent to standard output.
 * Writes a line when carriage-return is typed.
 */
void java_addcharacter(char chr)
{
	if (chr != '\n')
		java_outputbuffer[java_outputposition++] = chr;

	if (chr == '\n' || java_outputposition >= MAXLINE)
	{
		if (java_outputposition == 0)
			java_outputbuffer[java_outputposition++] = ' ';
		java_outputbuffer[java_outputposition] = 0;
		ttyputmsg("%s", java_outputbuffer);
		java_outputposition = 0;
	}
}

/*
 * Routine that is called when a single character is written to the
 * standard output.
 */
JNIEXPORT void JNICALL Java_Electric_eoutWriteOne(JNIEnv *env, jobject obj,
	jint byte)
{
	java_addcharacter((char)byte);
}

/*
 * Routine that is called when a string is written to the
 * standard output.
 */
JNIEXPORT void JNICALL Java_Electric_eoutWriteString(JNIEnv *env, jobject obj,
	jstring jstr)
{
	char *str;
	INTBIG i, len;
	jboolean isCopy;

	str = (char *)java_environment->GetStringUTFChars(jstr, &isCopy);
	len = strlen(str);
	for(i=0; i<len; i++) java_addcharacter(str[i]);
	if (isCopy == JNI_TRUE) java_environment->ReleaseStringUTFChars(jstr, str);
}

jint JNICALL java_vfprintf(FILE *fp, const char *format, va_list args)
{
	us_ttyprint(0, (char *)format, args);
	return(1);
}

/*
 * Coroutine that is called when Java exits.
 */
void JNICALL java_exit(jint code)
{
	ttyputmsg(_("Exiting JAVA with code %d"), code);
}

/*
 * Routine to convert a Java object "obj" into a string that describes it.
 */
char *java_describeobject(jobject obj)
{
	static char descr[100];
	REGISTER char *pt;
	INTBIG addr, type;

	if (obj == 0) return("NULL");
	java_getobjectaddrtype(obj, &addr, &type);
	switch (type)
	{
		case VINTEGER:
			sprintf(descr, "Integer(%ld)", addr);
			return(descr);

		case VFLOAT:
			sprintf(descr, "Float(%f)", castfloat(addr));
			return(descr);

		case VSTRING:
			pt = (char *)addr;
			if (java_allocarraybuffer(strlen(pt) + 1) != 0) return("NULL");
			strcpy(java_arraybuffer, pt);
			return(java_arraybuffer);

		case VNODEINST:
			sprintf(descr, "Nodeinst(%ld)", addr);
			return(descr);

		case VNODEPROTO:
			sprintf(descr, "Nodeproto(%ld)", addr);
			return(descr);

		case VPORTARCINST:
			sprintf(descr, "Portarcinst(%ld)", addr);
			return(descr);

		case VPORTEXPINST:
			sprintf(descr, "Portexpinst(%ld)", addr);
			return(descr);

		case VPORTPROTO:
			sprintf(descr, "Portproto(%ld)", addr);
			return(descr);

		case VARCINST:
			sprintf(descr, "Arcinst(%ld)", addr);
			return(descr);

		case VARCPROTO:
			sprintf(descr, "Arcproto(%ld)", addr);
			return(descr);

		case VGEOM:
			sprintf(descr, "Geom(%ld)", addr);
			return(descr);

		case VLIBRARY:
			sprintf(descr, "Library(%ld)", addr);
			return(descr);

		case VTECHNOLOGY:
			sprintf(descr, "Technology(%ld)", addr);
			return(descr);

		case VAID:
			sprintf(descr, "Aid(%ld)", addr);
			return(descr);

		case VRTNODE:
			sprintf(descr, "RTnode(%ld)", addr);
			return(descr);

		case VNETWORK:
			sprintf(descr, "Network(%ld)", addr);
			return(descr);

		case VCELL:
			sprintf(descr, "Cell(%ld)", addr);
			return(descr);

		case VVIEW:
			sprintf(descr, "View(%ld)", addr);
			return(descr);

		case VWINDOWPART:
			sprintf(descr, "Windowpart(%ld)", addr);
			return(descr);

		case VWINDOWFRAME:
			sprintf(descr, "Windowframe(%ld)", addr);
			return(descr);

		case VGRAPHICS:
			sprintf(descr, "Graphics(%ld)", addr);
			return(descr);

		case VPOLYGON:
			sprintf(descr, "Polygon(%ld)", addr);
			return(descr);

		case VCONSTRAINT:
			sprintf(descr, "Constraint(%ld)", addr);
			return(descr);
	}
	return(_("UNKNOWN"));
}

/*
 * Routine to ensure that the global "java_arraybuffer" has at least "size" bytes in
 * it.  Returns nonzero on error.
 */
INTSML java_allocarraybuffer(INTBIG size)
{
	if (size <= java_arraybuffersize) return(0);
	if (java_arraybuffersize > 0)
		efree((char *)java_arraybuffer);
	java_arraybuffersize = 0;
	java_arraybuffer = (char *)emalloc(size, db_cluster);
	if (java_arraybuffer == 0) return(1);
	java_arraybuffersize = size;
	return(0);
}

/*
 * Routine to convert the Java object "obj" into an "address/type" pair
 * in "addr" and "type".
 */
void java_getobjectaddrtype(jobject obj, INTBIG *addr, INTBIG *type)
{
	char *rstr;
	jboolean isCopy;
	INTBIG arrlen, i;
	jint *jarrdata;

	/* defaults */
	*addr = 0;
	*type = VUNKNOWN;

	/* Integer */
	if (java_environment->IsInstanceOf(obj, java_classint))
	{
		*addr = java_environment->CallIntMethod(obj, java_midIntValue);
		*type = VINTEGER;
		return;
	}

	/* Float */
	if (java_environment->IsInstanceOf(obj, java_classfloat))
	{
		*addr = castint(java_environment->CallFloatMethod(obj, java_midFloatValue));
		*type = VFLOAT;
		return;
	}

	/* String */
	if (java_environment->IsInstanceOf(obj, java_classstring))
	{
		rstr = (char *)java_environment->GetStringUTFChars((jstring)obj, &isCopy);
		(void)initinfstr();
		(void)addstringtoinfstr(rstr);
		if (isCopy == JNI_TRUE)
			java_environment->ReleaseStringUTFChars((jstring)obj, rstr);
		*addr = (INTBIG)returninfstr();
		*type = VSTRING;
		return;
	}

	/* the Electric classes */
	if (java_environment->IsInstanceOf(obj, java_classnodeinst))
	{
		*addr = java_environment->GetIntField(obj, java_addressID);
		*type = VNODEINST;
		return;
	}
	if (java_environment->IsInstanceOf(obj, java_classnodeproto))
	{
		*addr = java_environment->GetIntField(obj, java_addressID);
		*type = VNODEPROTO;
		return;
	}
	if (java_environment->IsInstanceOf(obj, java_classportarcinst))
	{
		*addr = java_environment->GetIntField(obj, java_addressID);
		*type = VPORTARCINST;
		return;
	}
	if (java_environment->IsInstanceOf(obj, java_classportexpinst))
	{
		*addr = java_environment->GetIntField(obj, java_addressID);
		*type = VPORTEXPINST;
		return;
	}
	if (java_environment->IsInstanceOf(obj, java_classportproto))
	{
		*addr = java_environment->GetIntField(obj, java_addressID);
		*type = VPORTPROTO;
		return;
	}
	if (java_environment->IsInstanceOf(obj, java_classarcinst))
	{
		*addr = java_environment->GetIntField(obj, java_addressID);
		*type = VARCINST;
		return;
	}
	if (java_environment->IsInstanceOf(obj, java_classarcproto))
	{
		*addr = java_environment->GetIntField(obj, java_addressID);
		*type = VARCPROTO;
		return;
	}
	if (java_environment->IsInstanceOf(obj, java_classgeom))
	{
		*addr = java_environment->GetIntField(obj, java_addressID);
		*type = VGEOM;
		return;
	}
	if (java_environment->IsInstanceOf(obj, java_classlibrary))
	{
		*addr = java_environment->GetIntField(obj, java_addressID);
		*type = VLIBRARY;
		return;
	}
	if (java_environment->IsInstanceOf(obj, java_classtechnology))
	{
		*addr = java_environment->GetIntField(obj, java_addressID);
		*type = VTECHNOLOGY;
		return;
	}
	if (java_environment->IsInstanceOf(obj, java_classaid))
	{
		*addr = java_environment->GetIntField(obj, java_addressID);
		*type = VAID;
		return;
	}
	if (java_environment->IsInstanceOf(obj, java_classrtnode))
	{
		*addr = java_environment->GetIntField(obj, java_addressID);
		*type = VRTNODE;
		return;
	}
	if (java_environment->IsInstanceOf(obj, java_classnetwork))
	{
		*addr = java_environment->GetIntField(obj, java_addressID);
		*type = VNETWORK;
		return;
	}
	if (java_environment->IsInstanceOf(obj, java_classcell))
	{
		*addr = java_environment->GetIntField(obj, java_addressID);
		*type = VCELL;
		return;
	}
	if (java_environment->IsInstanceOf(obj, java_classview))
	{
		*addr = java_environment->GetIntField(obj, java_addressID);
		*type = VVIEW;
		return;
	}
	if (java_environment->IsInstanceOf(obj, java_classwindowpart))
	{
		*addr = java_environment->GetIntField(obj, java_addressID);
		*type = VWINDOWPART;
		return;
	}
	if (java_environment->IsInstanceOf(obj, java_classwindowframe))
	{
		*addr = java_environment->GetIntField(obj, java_addressID);
		*type = VWINDOWFRAME;
		return;
	}
	if (java_environment->IsInstanceOf(obj, java_classgraphics))
	{
		*addr = java_environment->GetIntField(obj, java_addressID);
		*type = VGRAPHICS;
		return;
	}
	if (java_environment->IsInstanceOf(obj, java_classconstraint))
	{
		*addr = java_environment->GetIntField(obj, java_addressID);
		*type = VCONSTRAINT;
		return;
	}
	if (java_environment->IsInstanceOf(obj, java_classpolygon))
	{
		*addr = java_environment->GetIntField(obj, java_addressID);
		*type = VPOLYGON;
		return;
	}

	/* int arrays */
	if (java_environment->IsInstanceOf(obj, java_classarrayint))
	{
		arrlen = java_environment->GetArrayLength((jintArray)obj);
		jarrdata = java_environment->GetIntArrayElements((jintArray)obj, &isCopy);
		if (java_allocarraybuffer(arrlen*SIZEOFINTBIG) != 0) return;
		for(i=0; i<arrlen; i++)
			((INTBIG *)java_arraybuffer)[i] = jarrdata[i];
		if (isCopy == JNI_TRUE)
			java_environment->ReleaseIntArrayElements((jintArray)obj, jarrdata, JNI_ABORT);
		*addr = (INTBIG)java_arraybuffer;
		*type = VINTEGER | VISARRAY | (arrlen << VLENGTHSH);
		return;
	}
}

/*
 * Routine to create a Java object that describes object "addr" of type
 * "type".
 */
jobject java_makeobject(INTBIG addr, INTBIG type)
{
	jobject object;

	/* create an object of type "object" */
	switch (type&VTYPE)
	{
		case VINTEGER:
		case VSHORT:
			object = java_makejavaobject(addr, type, java_classint, VINTEGER);
			break;
		case VFLOAT:
			object = java_makejavaobject(addr, type, java_classfloat, VFLOAT);
			break;
		case VSTRING:
			object = java_environment->NewStringUTF((char *)addr);
			break;
		case VNODEINST:
			object = java_makejavaobject(addr, type, java_classnodeinst, VNODEINST);
			break;
		case VNODEPROTO:
			object = java_makejavaobject(addr, type, java_classnodeproto, VNODEPROTO);
			break;
		case VPORTARCINST:
			object = java_makejavaobject(addr, type, java_classportarcinst, VPORTARCINST);
			break;
		case VPORTEXPINST:
			object = java_makejavaobject(addr, type, java_classportexpinst, VPORTEXPINST);
			break;
		case VPORTPROTO:
			object = java_makejavaobject(addr, type, java_classportproto, VPORTPROTO);
			break;
		case VARCINST:
			object = java_makejavaobject(addr, type, java_classarcinst, VARCINST);
			break;
		case VARCPROTO:
			object = java_makejavaobject(addr, type, java_classarcproto, VARCPROTO);
			break;
		case VGEOM:
			object = java_makejavaobject(addr, type, java_classgeom, VGEOM);
			break;
		case VLIBRARY:
			object = java_makejavaobject(addr, type, java_classlibrary, VLIBRARY);
			break;
		case VTECHNOLOGY:
			object = java_makejavaobject(addr, type, java_classtechnology, VTECHNOLOGY);
			break;
		case VAID:
			object = java_makejavaobject(addr, type, java_classaid, VAID);
			break;
		case VRTNODE:
			object = java_makejavaobject(addr, type, java_classrtnode, VRTNODE);
			break;
		case VNETWORK:
			object = java_makejavaobject(addr, type, java_classnetwork, VNETWORK);
			break;
		case VCELL:
			object = java_makejavaobject(addr, type, java_classcell, VCELL);
			break;
		case VVIEW:
			object = java_makejavaobject(addr, type, java_classview, VVIEW);
			break;
		case VWINDOWPART:
			object = java_makejavaobject(addr, type, java_classwindowpart, VWINDOWPART);
			break;
		case VWINDOWFRAME:
			object = java_makejavaobject(addr, type, java_classwindowframe, VWINDOWFRAME);
			break;
		case VGRAPHICS:
			object = java_makejavaobject(addr, type, java_classgraphics, VGRAPHICS);
			break;
		case VCONSTRAINT:
			object = java_makejavaobject(addr, type, java_classconstraint, VCONSTRAINT);
			break;
		case VPOLYGON:
			object = java_makejavaobject(addr, type, java_classpolygon, VPOLYGON);
			break;
		default:
			object = java_nullobject;
			break;
	}
	return(object);
}

jobject java_makejavaobject(INTBIG addr, INTBIG type, jclass javaclass, INTBIG desttype)
{
	VARIABLE myvar;
	REGISTER INTBIG i, len;
	jobjectArray objArray;
	jobject object, subobject;

	if ((type&VISARRAY) != 0)
	{
		myvar.addr = addr;   myvar.type = type;
		len = getlength(&myvar);
		objArray = java_environment->NewObjectArray(len, javaclass, NULL);
		for(i=0; i<len; i++)
		{
			subobject = java_makeobject(((INTBIG *)addr)[i], desttype);
			java_environment->SetObjectArrayElement(objArray, i, subobject);
		}
		object = (jobject)objArray;
	} else
	{
		object = java_environment->AllocObject(javaclass);
		if ((type&VTYPE) == VFLOAT)
		{
			java_environment->CallVoidMethod(object, java_midFloatInit, (jfloat)castfloat(addr));
		} else if ((type&VTYPE) == VINTEGER || (type&VTYPE) == VSHORT)
		{
			java_environment->CallVoidMethod(object, java_midIntInit, (jint)addr);
		} else
		{
			java_environment->SetIntField(object, java_addressID, addr);
		}
	}
	return(object);
}

#endif
