#***************************************************************************
#            kalyptusCxxToJNI.pm -  Generates *.java and *.cpp files for a JNI based
#									version of Qt/KDE java bindings
#                             -------------------
#    begin                : Sun Nov 16 12:00:00 2003
#    copyright            : (C) 2003, Richard Dale. All Rights Reserved.
#    email                : Richard_Dale@tipitina.demon.co.uk
#    author               : Richard Dale, based on the SMOKE generation code
#                            by David Faure.
#***************************************************************************/

#/***************************************************************************
# *                                                                         *
# *   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.                                   *
# *                                                                         *
#***************************************************************************/

package kalyptusCxxToJNI;

use File::Path;
use File::Basename;

use Carp;
use Ast;
use kdocAstUtil;
use kdocUtil;
use Iter;
use kalyptusDataDict;

use strict;
no strict "subs";

use vars qw/
	$libname $rootnode $outputdir $opt $debug
	$qapplicationExtras $qapplicationjniExtras $qbitmapExtras $qbitmapjniExtras
	$qlistviewExtras $qlistviewjniExtras $qlistviewitemExtras $qlistviewitemjniExtras
	$qpopupmenujniExtras $qmenudatajniExtras $qmenubarjniExtras
	$qdragobjectExtras $qdragobjectjniExtras $qdropeventExtras $qdropeventjniExtras $qmimesourceExtras $qmimesourcejniExtras
	$qtExtras $qtjniExtras $qobjectExtras $qobjectjniExtras $qimagejniExtras $qwidgetExtras $qwidgetjniExtras
	$qpixmapExtras $qpixmapjniExtras $qpaintdeviceExtras $qpaintdevicejniExtras
	$qdragobjectExtras $qdragobjectjniExtras $qiodeviceExtras $qpointarrayExtras $qpointarrayjniExtras
	$qtextcodecExtras $qtextcodecjniExtras $quridragExtras $quridragjniExtras
	$kapplicationExtras $kapplicationjniExtras $tdemainwindowExtras $tdemainwindowjniExtras
	$kcmdlineargsjniExtras $schedulerjniExtras
	$methodNumber
	%builtins %typeunion %allMethods %allTypes %enumValueToType %typedeflist %mungedTypeMap %javaImports
	%skippedClasses %skippedJniMethods %operatorNames /;

BEGIN
{

# Types supported by the StackItem union
# Key: C++ type  Value: Union field of that type
%typeunion = (
    'void*' => 's_voidp',
    'bool' => 's_bool',
    'char' => 's_char',
    'uchar' => 's_uchar',
    'short' => 's_short',
    'ushort' => 's_ushort',
    'int' => 's_int',
    'uint' => 's_uint',
    'long' => 's_long',
    'ulong' => 's_ulong',
    'float' => 's_float',
    'double' => 's_double',
    'enum' => 's_enum',
    'class' => 's_class'
);

# Mapping for iterproto, when making up the munged method names
%mungedTypeMap = (
     'TQString' => '$',
     'TQString*' => '$',
     'TQString&' => '$',
     'TQCString' => '$',
     'TQCString*' => '$',
     'TQCString&' => '$',
     'TQByteArray' => '$',
     'TQByteArray&' => '$',
     'TQByteArray*' => '$',
     'char*' => '$',
     'TQCOORD*' => '?',
     'TQRgb*' => '?',
);

# Yes some of this is in kalyptusDataDict's ctypemap
# but that one would need to be separated (builtins vs normal classes)
%typedeflist =
(
   'signed char' => 'char',
   'unsigned char' => 'uchar',
   'signed short' => 'short',
   'unsigned short' => 'ushort',
   'signed' => 'int',
   'signed int' => 'int',
   'unsigned' => 'uint',
   'unsigned int' => 'uint',
   'TDEIO::filesize_t' => 'long',
   'signed long' => 'long',
   'unsigned long' => 'ulong',

# Anything that is not known is mapped to void*, so no need for those here anymore
#   'TQWSEvent*'  =>  'void*',
#   'TQDiskFont*'  =>  'void*',
#   'XEvent*'  =>  'void*',
#   'FILE*'  =>  'void*',
#   'TQUnknownInterface*'  =>  'void*',
#   'GDHandle'  =>  'void*',
#   '_NPStream*'  =>  'void*',
#   'TQTextFormat*'  =>  'void*',
#   'TQTextDocument*'  =>  'void*',
#   'TQTextCursor*'  =>  'void*',
#   'TQTextParag**'  =>  'void*',
#   'TQTextParag*'  =>  'void*',
#   'TQRemoteInterface*'  =>  'void*',
#   'TQSqlRecordPrivate*'  =>  'void*',
#   'TQTSMFI'  =>  'void*', # TQTextStream's TQTSManip
#   'const GUID&'  =>  'void*',
#   'TQWidgetMapper*'  =>  'void*',
#   'MSG*'  =>  'void*',
#   'const TQSqlFieldInfoList&'  =>  'void*', # TQSqlRecordInfo - TODO (templates)

   'TQStyleHintReturn*'  =>  'void*',
   'TQPtrCollection::Item'  =>  'void*', # to avoid a warning

   'mode_t'  =>  'long',
   'TQProcess::PID'  =>  'long',
   'size_type'  =>  'int', # TQSqlRecordInfo
   'TQt::ComparisonFlags'  =>  'uint',
   'TQt::ToolBarDock'  =>  'int', # compat thing, Qt shouldn't use it
   'TQIODevice::Offset'  =>  'ulong',
   'WState'  =>  'int',
   'WId'  =>  'ulong',
   'TQRgb'  =>  'uint',
   'ksocklen_t' => 'uint',
   'TQCOORD'  =>  'int',
   'TQTSMFI'  =>  'int',
   'TQt::WState'  =>  'int',
   'TQt::WFlags'  =>  'int',
   'TQt::HANDLE' => 'uint',
   'TQEventLoop::ProcessEventsFlags' => 'uint',
   'TQStyle::SCFlags' => 'int',
   'TQStyle::SFlags' => 'int',
   'TQ_INT16' => 'short',
   'TQ_INT32' => 'int',
   'TQ_INT64' => 'long',
   'TQ_INT8' => 'char',
   'TQ_LONG' => 'long',
   'TQ_LLONG' => 'long',
   'TQ_ULLONG' => 'long',
   'TQ_UINT16' => 'ushort',
   'TQ_UINT32' => 'uint',
   'TQ_UINT64' => 'long',
   'TQ_UINT8' => 'uchar',
   'TQ_ULONG' => 'long',
   'pid_t' => 'int',
   'size_t' => 'int',
   'pid_t' => 'int',
   'time_t' => 'int',
   'short int' => 'short',
   'unsigned long long int' => 'ulong',
   'long long int' => 'long',
   'signed long int' => 'long',
   'unsigned long int' => 'ulong',
   'int long' => 'long',
   'unsigned short int' => 'ushort',
);

%operatorNames =
(
    'operator^' => 'op_xor',
    'operator^=' => 'op_xor_assign',
    'operator<' => 'op_lt',
    'operator<<' => 'op_write',
    'operator<=' => 'op_lte',
#    'operator=' => 'op_assign',
    'operator==' => 'op_equals',
    'operator>' => 'op_gt',
    'operator>=' => 'op_gte',
    'operator>>' => 'op_read',
    'operator|' => 'op_or',
    'operator|=' => 'op_or_assign',
    'operator-' => 'op_minus',
    'operator-=' => 'op_minus_assign',
    'operator--' => 'op_decr',
    'operator!' => 'op_not',
    'operator!=' => 'op_not_equals',
    'operator/' => 'op_div',
    'operator/=' => 'op_div_assign',
    'operator()' => 'op_expr',
    'operator[]' => 'op_at',
    'operator*' => 'op_mult',
    'operator*=' => 'op_mult_assign',
    'operator&' => 'op_and',
    'operator&=' => 'op_and_assign',
    'operator+' => 'op_plus',
    'operator+=' => 'op_plus_assign',
    'operator++' => 'op_incr',
);

%skippedJniMethods =
(
	'Java_org_trinitydesktop_qt_QApplication_newTQApplication___3Ljava_lang_String_2' => 1,
	'Java_org_trinitydesktop_qt_QApplication_newTQApplication___3Ljava_lang_String_2Z' => 1,
	'Java_org_trinitydesktop_qt_QApplication_newTQApplication___3Ljava_lang_String_2I' => 1,
	'Java_org_trinitydesktop_qt_QApplication_newTQApplication___3I_3Ljava_lang_String_2' => 1,
	'Java_org_trinitydesktop_qt_QApplication_newTQApplication___3I_3Ljava_lang_String_2Z' => 1,
	'Java_org_trinitydesktop_qt_QApplication_newTQApplication___3I_3Ljava_lang_String_2I' => 1,
	'Java_org_trinitydesktop_qt_QApplication_newTQApplication__I_3Ljava_lang_String_2I' => 1,
	'Java_org_trinitydesktop_qt_QApplication_newTQApplication__I_3Ljava_lang_String_2Z' => 1,
	'Java_org_trinitydesktop_qt_QApplication_newTQApplication__I_3Ljava_lang_String_2' => 1,
	'Java_org_trinitydesktop_qt_QApplication_args__' => 1,
	'Java_org_trinitydesktop_qt_QBitmap_newTQBitmap__Lorg_trinitydesktop_qt_QPixmap_2' => 1,
	'Java_org_trinitydesktop_qt_QBitmap_newTQBitmap__Lorg_trinitydesktop_qt_QImage_2' => 1,
	'Java_org_trinitydesktop_qt_QListView_itemList' => 1,
	'Java_org_trinitydesktop_qt_QListViewItem_itemList' => 1,
	'Java_org_trinitydesktop_qt_Qt_color0' => 1,
	'Java_org_trinitydesktop_qt_Qt_color1' => 1,
	'Java_org_trinitydesktop_qt_Qt_black' => 1,
	'Java_org_trinitydesktop_qt_Qt_white' => 1,
	'Java_org_trinitydesktop_qt_Qt_darkGray' => 1,
	'Java_org_trinitydesktop_qt_Qt_lightGray' => 1,
	'Java_org_trinitydesktop_qt_Qt_gray' => 1,
	'Java_org_trinitydesktop_qt_Qt_red' => 1,
	'Java_org_trinitydesktop_qt_Qt_green' => 1,
	'Java_org_trinitydesktop_qt_Qt_blue' => 1,
	'Java_org_trinitydesktop_qt_Qt_cyan' => 1,
	'Java_org_trinitydesktop_qt_Qt_magenta' => 1,
	'Java_org_trinitydesktop_qt_Qt_yellow' => 1,
	'Java_org_trinitydesktop_qt_Qt_darkRed' => 1,
	'Java_org_trinitydesktop_qt_Qt_darkGreen' => 1,
	'Java_org_trinitydesktop_qt_Qt_darkBlue' => 1,
	'Java_org_trinitydesktop_qt_Qt_darkCyan' => 1,
	'Java_org_trinitydesktop_qt_Qt_darkMagenta' => 1,
	'Java_org_trinitydesktop_qt_Qt_darkYellow' => 1,
	'Java_org_trinitydesktop_qt_Qt_arrowCursor' => 1,
	'Java_org_trinitydesktop_qt_Qt_upArrowCursor' => 1,
	'Java_org_trinitydesktop_qt_Qt_crossCursor' => 1,
	'Java_org_trinitydesktop_qt_Qt_waitCursor' => 1,
	'Java_org_trinitydesktop_qt_Qt_ibeamCursor' => 1,
	'Java_org_trinitydesktop_qt_Qt_sizeVerCursor' => 1,
	'Java_org_trinitydesktop_qt_Qt_sizeHorCursor' => 1,
	'Java_org_trinitydesktop_qt_Qt_sizeBDiagCursor' => 1,
	'Java_org_trinitydesktop_qt_Qt_sizeFDiagCursor' => 1,
	'Java_org_trinitydesktop_qt_Qt_sizeAllCursor' => 1,
	'Java_org_trinitydesktop_qt_Qt_blankCursor' => 1,
	'Java_org_trinitydesktop_qt_Qt_splitVCursor' => 1,
	'Java_org_trinitydesktop_qt_Qt_splitHCursor' => 1,
	'Java_org_trinitydesktop_qt_Qt_pointingHandCursor' => 1,
	'Java_org_trinitydesktop_qt_Qt_forbiddenCursor' => 1,
	'Java_org_trinitydesktop_qt_Qt_qApp' => 1,
	'Java_org_trinitydesktop_qt_Qt_tqDebug' => 1,
	'Java_org_trinitydesktop_qt_Qt_tqWarning' => 1,
	'Java_org_trinitydesktop_qt_Qt_tqFatal' => 1,
	'Java_org_trinitydesktop_qt_QObject_connect__Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2' => 1,
	'Java_org_trinitydesktop_qt_QObject_connect__Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2Ljava_lang_String_2' => 1,
	'Java_org_trinitydesktop_qt_QObject_disconnect__Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2' => 1,
	'Java_org_trinitydesktop_qt_QObject_disconnect__Ljava_lang_String_2Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2' => 1,
	'Java_org_trinitydesktop_qt_QObject_emit' => 1,
	'Java_org_trinitydesktop_qt_QWidget_paintDevice' => 1,
	'Java_org_trinitydesktop_qt_QImage_bits__' => 1,
	'Java_org_trinitydesktop_qt_QImage_colorTable__' => 1,
	'Java_org_trinitydesktop_qt_QImage_scanLine__I' => 1,
	'Java_org_trinitydesktop_qt_QPixmap_paintDevice' => 1,
	'Java_org_trinitydesktop_qt_QPixmap_loadFromData___3C' => 1,
	'Java_org_trinitydesktop_qt_QPaintDevice_paintDevice' => 1,
	'Java_org_trinitydesktop_qt_QDragObject_mimeSource' => 1,
	'Java_org_trinitydesktop_qt_QPointArray_point__I_3I_3I' => 1,
	'Java_org_trinitydesktop_qt_QPointArray_setPoints__I_3S' => 1,
	'Java_org_trinitydesktop_qt_QPointArray_putPoints__II_3S' => 1,
	'Java_org_trinitydesktop_qt_QPointArray_count__' => 1,
	'Java_org_trinitydesktop_qt_QPointArray_isEmpty__' => 1,
	'Java_org_trinitydesktop_qt_QPointArray_isNull__' => 1,
	'Java_org_trinitydesktop_qt_QPointArray_resize__' => 1,
	'Java_org_trinitydesktop_qt_QPopupMenu_insertItem__Ljava_lang_String_2Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2Lorg_trinitydesktop_qt_QKeySequence_2II' => 1,
	'Java_org_trinitydesktop_qt_QPopupMenu_insertItem__Ljava_lang_String_2Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2' => 1,
	'Java_org_trinitydesktop_qt_QPopupMenu_insertItem__Lorg_trinitydesktop_qt_QIconSet_2Ljava_lang_String_2Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2' => 1,
	'Java_org_trinitydesktop_qt_QPopupMenu_insertItem__Lorg_trinitydesktop_qt_QPixmap_2Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2' => 1,
	'Java_org_trinitydesktop_qt_QPopupMenu_insertItem__Lorg_trinitydesktop_qt_QIconSet_2Lorg_trinitydesktop_qt_QPixmap_2Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2' => 1,
	'Java_org_trinitydesktop_qt_QPopupMenu_connectItem__ILorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2' => 1,
	'Java_org_trinitydesktop_qt_QPopupMenu_disconnectItem__ILorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2' => 1,
	'Java_org_trinitydesktop_qt_QMenuData_insertItem__Ljava_lang_String_2Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2Lorg_trinitydesktop_qt_QKeySequence_2II' => 1,
	'Java_org_trinitydesktop_qt_QMenuData_insertItem__Ljava_lang_String_2Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2' => 1,
	'Java_org_trinitydesktop_qt_QMenuData_insertItem__Lorg_trinitydesktop_qt_QIconSet_2Ljava_lang_String_2Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2' => 1,
	'Java_org_trinitydesktop_qt_QMenuData_insertItem__Lorg_trinitydesktop_qt_QPixmap_2Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2' => 1,
	'Java_org_trinitydesktop_qt_QMenuData_insertItem__Lorg_trinitydesktop_qt_QIconSet_2Lorg_trinitydesktop_qt_QPixmap_2Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2' => 1,
	'Java_org_trinitydesktop_qt_QMenuData_connectItem__ILorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2' => 1,
	'Java_org_trinitydesktop_qt_QMenuData_disconnectItem__ILorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2' => 1,
	'Java_org_trinitydesktop_qt_QMenuBar_insertItem__Ljava_lang_String_2Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2Lorg_trinitydesktop_qt_QKeySequence_2II' => 1,
	'Java_org_trinitydesktop_qt_QMenuBar_insertItem__Ljava_lang_String_2Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2' => 1,
	'Java_org_trinitydesktop_qt_QMenuBar_insertItem__Lorg_trinitydesktop_qt_QIconSet_2Ljava_lang_String_2Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2' => 1,
	'Java_org_trinitydesktop_qt_QMenuBar_insertItem__Lorg_trinitydesktop_qt_QPixmap_2Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2' => 1,
	'Java_org_trinitydesktop_qt_QMenuBar_insertItem__Lorg_trinitydesktop_qt_QIconSet_2Lorg_trinitydesktop_qt_QPixmap_2Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2' => 1,
	'Java_org_trinitydesktop_qt_QMenuBar_connectItem__ILorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2' => 1,
	'Java_org_trinitydesktop_qt_QMenuBar_disconnectItem__ILorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2' => 1,
	'Java_org_trinitydesktop_qt_QUriDrag_decode__Lorg_trinitydesktop_qt_QMimeSourceInterface_2_3Ljava_lang_String_2' => 1,
	'Java_org_trinitydesktop_qt_QUriDrag_decodeToUnicodeUris__Lorg_trinitydesktop_qt_QMimeSourceInterface_2_3Ljava_lang_String_2' => 1,
	'Java_org_trinitydesktop_qt_QUriDrag_decodeLocalFiles__Lorg_trinitydesktop_qt_QMimeSourceInterface_2_3Ljava_lang_String_2' => 1,
	'Java_org_trinitydesktop_koala_TDEApplication_setJavaSlotFactory' => 1,
	'Java_org_trinitydesktop_koala_TDEMainWindow_memberList' => 1,
	'Java_org_trinitydesktop_koala_TDECmdLineArgs_init__I_3Ljava_lang_String_2Ljava_lang_String_2Ljava_lang_String_2Ljava_lang_String_2Ljava_lang_String_2' => 1,
	'Java_org_trinitydesktop_koala_TDECmdLineArgs_init__I_3Ljava_lang_String_2Lorg_trinitydesktop_koala_TDEAboutData_2' => 1,
	'Java_org_trinitydesktop_koala_TDECmdLineArgs_init__I_3Ljava_lang_String_2Lorg_trinitydesktop_koala_TDEAboutData_2Z' => 1,
	'Java_org_trinitydesktop_koala_TDECmdLineArgs_init__I_3Ljava_lang_String_2Ljava_lang_String_2Ljava_lang_String_2Ljava_lang_String_2Ljava_lang_String_2Z' => 1,
	'Java_org_trinitydesktop_koala_Scheduler_connect__Ljava_lang_String_2Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2' => 1,
	'Java_org_trinitydesktop_koala_Scheduler_connect__Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2Ljava_lang_String_2' => 1,
	'Java_org_trinitydesktop_koala_Scheduler_disconnect__Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2' => 1,
	'Java_org_trinitydesktop_koala_Scheduler_disconnect' => 1,
);	
	
	$qapplicationExtras = <<EOF;
	public native String[] args();

EOF
	
	$qapplicationjniExtras = <<EOF;
static jobjectArray _args = 0;

JNIEXPORT void JNICALL
Java_org_trinitydesktop_qt_QApplication_newTQApplication___3Ljava_lang_String_2(JNIEnv *env, jobject obj, jobjectArray args)
{
	int argc = (int) env->GetArrayLength(args) + 1;
	_args = (jobjectArray) env->NewGlobalRef(args);
 	if (QtSupport::getQt(env, obj) == 0) {
 		QtSupport::setQt(env, obj, new TQApplicationJBridge(argc, QtSupport::toArgv(env, args)));
 		QtSupport::setObjectForQtKey(env, obj, QtSupport::getQt(env, obj));
 	}
	return;
}

JNIEXPORT void JNICALL
Java_org_trinitydesktop_qt_QApplication_newTQApplication___3Ljava_lang_String_2Z(JNIEnv *env, jobject obj, jobjectArray args, jboolean GUIenabled)
{
	int argc = (int) env->GetArrayLength(args) + 1;
	_args = (jobjectArray) env->NewGlobalRef(args);
 	if (QtSupport::getQt(env, obj) == 0) {
		QtSupport::setQt(env, obj, new TQApplicationJBridge(argc, QtSupport::toArgv(env, args), (bool) GUIenabled));
		QtSupport::setObjectForQtKey(env, obj, QtSupport::getQt(env, obj));
	}
 	return;
}

JNIEXPORT void JNICALL
Java_org_trinitydesktop_qt_QApplication_newTQApplication___3Ljava_lang_String_2I(JNIEnv *env, jobject obj, jobjectArray args, jint arg1)
{
	int argc = (int) env->GetArrayLength(args) + 1;
	_args = (jobjectArray) env->NewGlobalRef(args);
	if (QtSupport::getQt(env, obj) == 0) {
		QtSupport::setQt(env, obj, new TQApplicationJBridge(argc, QtSupport::toArgv(env, args), (TQApplication::Type) arg1));
		QtSupport::setObjectForQtKey(env, obj, QtSupport::getQt(env, obj));
 	}
	return;
}

JNIEXPORT jobjectArray JNICALL
Java_org_trinitydesktop_qt_QApplication_args(JNIEnv *env, jobject obj)
{
	(void) env;
	(void) obj;
	return _args;
}

EOF
	
	$qbitmapExtras = <<EOF;
	public TQBitmap(TQPixmap arg1) {
		super((Class) null);
		newTQBitmap(arg1);
	}
	private native void newTQBitmap(TQPixmap arg1);
	public TQBitmap(TQImage arg1) {
		super((Class) null);
		newTQBitmap(arg1);
	}
	private native void newTQBitmap(TQImage arg1);
	
EOF
	
	$qbitmapjniExtras = <<EOF;
JNIEXPORT void JNICALL
Java_org_trinitydesktop_qt_QBitmap_newTQBitmap__Lorg_trinitydesktop_qt_QPixmap_2(JNIEnv *env, jobject obj, jobject arg1)
{
	if (QtSupport::getQt(env, obj) == 0) {
		TQBitmap temp;
		temp = (TQPixmap&) *(TQPixmap *) QtSupport::getQt(env, arg1);
		QtSupport::setQt(env, obj, new TQBitmapJBridge(temp));
		QtSupport::setObjectForQtKey(env, obj, QtSupport::getQt(env, obj));
	}
	return;
}

JNIEXPORT void JNICALL
Java_org_trinitydesktop_qt_QBitmap_newTQBitmap__Lorg_trinitydesktop_qt_QImage_2(JNIEnv *env, jobject obj, jobject arg1)
{
	if (QtSupport::getQt(env, obj) == 0) {
		TQBitmap temp;
		temp = (TQImage&) *(TQImage *) QtSupport::getQt(env, arg1);
		QtSupport::setQt(env, obj, new TQBitmapJBridge(temp));
		QtSupport::setObjectForQtKey(env, obj, QtSupport::getQt(env, obj));
	}
	return;
}

EOF

	$qlistviewExtras = <<EOF;
	public native ArrayList itemList();

EOF
	
	$qlistviewjniExtras = <<EOF;
JNIEXPORT jobject JNICALL
Java_org_trinitydesktop_qt_QListView_itemList(JNIEnv *env, jobject obj)
{
	TQListViewItemIterator iterator((TQListView*) QtSupport::getQt(env, obj));
	return QtSupport::arrayWithTQListViewItemList(env, &iterator);
}

EOF
	$qlistviewitemExtras = <<EOF;
	public native ArrayList itemList();

EOF
	
	$qlistviewitemjniExtras = <<EOF;
JNIEXPORT jobject JNICALL
Java_org_trinitydesktop_qt_QListViewItem_itemList(JNIEnv *env, jobject obj)
{
	TQListViewItemIterator iterator((TQListViewItem*) QtSupport::getQt(env, obj));
	return QtSupport::arrayWithTQListViewItemList(env, &iterator);
}

EOF

	$qtExtras = <<EOF;
	/** This member allows a typecast of an instance which wraps a Qt instance,
		to a more specialized type. Invokes the private qtjava.dynamicCast()
		via reflection, as that method isn't part of the public TQt api */
	public static QtSupport dynamicCast(String type, QtSupport source) {
		Method		method = null;
		
		try {
			method = qtjava.class.getDeclaredMethod(	"dynamicCast",
														new Class[] { String.class, QtSupport.class } );
		} catch (NoSuchMethodException e1) {
			TQt.tqWarning("No such method : qtjava.dynamicCast()");
		}

		try {
			method.setAccessible(true);
			Object result = method.invoke(qtjava.class, new Object[] { type, source } );
			return (QtSupport) result;
		} catch (InvocationTargetException e) {
			TQt.tqWarning("Invocation failed : qtjava.dynamicCast()");
			return null;
		} catch (IllegalAccessException e) {
			TQt.tqWarning("Invocation failed : qtjava.dynamicCast()");
			return null;
		}
	}
	
	public static native TQColor color0();
	public static native TQColor color1();
	public static native TQColor black();
	public static native TQColor white();
	public static native TQColor darkGray();
	public static native TQColor gray();
	public static native TQColor lightGray();
	public static native TQColor red();
	public static native TQColor green();
	public static native TQColor blue();
	public static native TQColor cyan();
	public static native TQColor magenta();
	public static native TQColor yellow();
	public static native TQColor darkRed();
	public static native TQColor darkGreen();
	public static native TQColor darkBlue();
	public static native TQColor darkCyan();
	public static native TQColor darkMagenta();
	public static native TQColor darkYellow();
	
    // Global cursors

	public static native TQCursor arrowCursor();	// standard arrow cursor
	public static native TQCursor upArrowCursor();	// upwards arrow
	public static native TQCursor crossCursor();	// crosshair
	public static native TQCursor waitCursor();	// hourglass/watch
	public static native TQCursor ibeamCursor();	// ibeam/text entry
	public static native TQCursor sizeVerCursor();	// vertical resize
	public static native TQCursor sizeHorCursor();	// horizontal resize
	public static native TQCursor sizeBDiagCursor();	// diagonal resize (/)
	public static native TQCursor sizeFDiagCursor();	// diagonal resize (\)
	public static native TQCursor sizeAllCursor();	// all directions resize
	public static native TQCursor blankCursor();	// blank/invisible cursor
	public static native TQCursor splitVCursor();	// vertical bar with left-right
						// arrows
	public static native TQCursor splitHCursor();	// horizontal bar with up-down
						// arrows
	public static native TQCursor pointingHandCursor();	// pointing hand
	public static native TQCursor forbiddenCursor();	// forbidden cursor (slashed circle)
	public static native TQCursor whatsThisCursor();	// arrow with a question mark
	
	public static native TQApplication tqApp();
	
	public static native void tqDebug(String message);
	public static void tqDebug(String pattern, Object[] arguments) {
		tqDebug(MessageFormat.format(pattern, arguments));
	}
	
	public static native void tqWarning(String message);
	public static void tqWarning(String pattern, Object[] arguments) {
		tqWarning(MessageFormat.format(pattern, arguments));
	}
	
	public static native void tqFatal(String message);
	public static void tqFatal(String pattern, Object[] arguments) {
		tqFatal(MessageFormat.format(pattern, arguments));
	}
	
	private static String sqeezeOut(String from, char toss) {
		char[] chars = from.toCharArray();
		int len = chars.length;
		int put = 0;
		
		for (int i = 0; i < len; i++) {
			if (chars[i] != toss) {
				chars[put++] = chars[i];
			}
		}
		
		return new String(chars, 0, put);
	}
	
	/** Prepend a '2' to a signal string and remove any spaces */
	public static String TQ_SIGNAL(String signal) {
		return "2" + sqeezeOut(signal, ' ');
	}
	
	/** Prepend a '1' to a slot string and remove any spaces */
	public static String TQ_SLOT(String slot) {
		return "1" + sqeezeOut(slot, ' ');
	}
	
	/** Convert from a UTF-8 string to Unicode - the java equivalent to TQString::fromUtf8() */
	public String fromUtf8(byte[] bytes) {
		String result = null;
		
		try {
			result = new String(bytes, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			tqWarning("UTF-8 encoding not supported");
		} finally {
			return result;
		}
	}
	
EOF

	$qtjniExtras = <<EOF;
#include <qapplication.h>
#include <qstring.h>
#include <qcstring.h>

JNIEXPORT jobject JNICALL
Java_org_trinitydesktop_qt_Qt_color0(JNIEnv* env, jclass cls)
{
	(void) cls;
	return (jobject) QtSupport::objectForQtKey(env, (void*)&TQt::color0, "org.trinitydesktop.qt.TQColor");
}

JNIEXPORT jobject JNICALL
Java_org_trinitydesktop_qt_Qt_color1(JNIEnv* env, jclass cls)
{
	(void) cls;
	return (jobject) QtSupport::objectForQtKey(env, (void*)&TQt::color1, "org.trinitydesktop.qt.TQColor");
}

JNIEXPORT jobject JNICALL
Java_org_trinitydesktop_qt_Qt_black(JNIEnv* env, jclass cls)
{
	(void) cls;
	return (jobject) QtSupport::objectForQtKey(env, (void*)&TQt::black, "org.trinitydesktop.qt.TQColor");
}

JNIEXPORT jobject JNICALL
Java_org_trinitydesktop_qt_Qt_white(JNIEnv* env, jclass cls)
{
	(void) cls;
	return (jobject) QtSupport::objectForQtKey(env, (void*)&TQt::white, "org.trinitydesktop.qt.TQColor");
}

JNIEXPORT jobject JNICALL
Java_org_trinitydesktop_qt_Qt_darkGray(JNIEnv* env, jclass cls)
{
	(void) cls;
	return (jobject) QtSupport::objectForQtKey(env, (void*)&TQt::darkGray, "org.trinitydesktop.qt.TQColor");
}

JNIEXPORT jobject JNICALL
Java_org_trinitydesktop_qt_Qt_lightGray(JNIEnv* env, jclass cls)
{
	(void) cls;
	return (jobject) QtSupport::objectForQtKey(env, (void*)&TQt::lightGray, "org.trinitydesktop.qt.TQColor");
}

JNIEXPORT jobject JNICALL
Java_org_trinitydesktop_qt_Qt_gray(JNIEnv* env, jclass cls)
{
	(void) cls;
	return (jobject) QtSupport::objectForQtKey(env, (void*)&TQt::gray, "org.trinitydesktop.qt.TQColor");
}

JNIEXPORT jobject JNICALL
Java_org_trinitydesktop_qt_Qt_red(JNIEnv* env, jclass cls)
{
	(void) cls;
	return (jobject) QtSupport::objectForQtKey(env, (void*)&TQt::red, "org.trinitydesktop.qt.TQColor");
}

JNIEXPORT jobject JNICALL
Java_org_trinitydesktop_qt_Qt_green(JNIEnv* env, jclass cls)
{
	(void) cls;
	return (jobject) QtSupport::objectForQtKey(env, (void*)&TQt::green, "org.trinitydesktop.qt.TQColor");
}

JNIEXPORT jobject JNICALL
Java_org_trinitydesktop_qt_Qt_blue(JNIEnv* env, jclass cls)
{
	(void) cls;
	return (jobject) QtSupport::objectForQtKey(env, (void*)&TQt::blue, "org.trinitydesktop.qt.TQColor");
}

JNIEXPORT jobject JNICALL
Java_org_trinitydesktop_qt_Qt_cyan(JNIEnv* env, jclass cls)
{
	(void) cls;
	return (jobject) QtSupport::objectForQtKey(env, (void*)&TQt::cyan, "org.trinitydesktop.qt.TQColor");
}

JNIEXPORT jobject JNICALL
Java_org_trinitydesktop_qt_Qt_magenta(JNIEnv* env, jclass cls)
{
	(void) cls;
	return (jobject) QtSupport::objectForQtKey(env, (void*)&TQt::magenta, "org.trinitydesktop.qt.TQColor");
}

JNIEXPORT jobject JNICALL
Java_org_trinitydesktop_qt_Qt_yellow(JNIEnv* env, jclass cls)
{
	(void) cls;
	return (jobject) QtSupport::objectForQtKey(env, (void*)&TQt::yellow, "org.trinitydesktop.qt.TQColor");
}

JNIEXPORT jobject JNICALL
Java_org_trinitydesktop_qt_Qt_darkRed(JNIEnv* env, jclass cls)
{
	(void) cls;
	return (jobject) QtSupport::objectForQtKey(env, (void*)&TQt::darkRed, "org.trinitydesktop.qt.TQColor");
}

JNIEXPORT jobject JNICALL
Java_org_trinitydesktop_qt_Qt_darkGreen(JNIEnv* env, jclass cls)
{
	(void) cls;
	return (jobject) QtSupport::objectForQtKey(env, (void*)&TQt::darkGreen, "org.trinitydesktop.qt.TQColor");
}

JNIEXPORT jobject JNICALL
Java_org_trinitydesktop_qt_Qt_darkBlue(JNIEnv* env, jclass cls)
{
	(void) cls;
	return (jobject) QtSupport::objectForQtKey(env, (void*)&TQt::darkBlue, "org.trinitydesktop.qt.TQColor");
}

JNIEXPORT jobject JNICALL
Java_org_trinitydesktop_qt_Qt_darkCyan(JNIEnv* env, jclass cls)
{
	(void) cls;
	return (jobject) QtSupport::objectForQtKey(env, (void*)&TQt::darkCyan, "org.trinitydesktop.qt.TQColor");
}

JNIEXPORT jobject JNICALL
Java_org_trinitydesktop_qt_Qt_darkMagenta(JNIEnv* env, jclass cls)
{
	(void) cls;
	return (jobject) QtSupport::objectForQtKey(env, (void*)&TQt::darkMagenta, "org.trinitydesktop.qt.TQColor");
}

JNIEXPORT jobject JNICALL
Java_org_trinitydesktop_qt_Qt_darkYellow(JNIEnv* env, jclass cls)
{
	(void) cls;
	return (jobject) QtSupport::objectForQtKey(env, (void*)&TQt::darkYellow, "org.trinitydesktop.qt.TQColor");
}

JNIEXPORT jobject JNICALL
Java_org_trinitydesktop_qt_Qt_arrowCursor(JNIEnv* env, jclass cls)
{
	(void) cls;
	return (jobject) QtSupport::objectForQtKey(env, (void*)&TQt::arrowCursor, "org.trinitydesktop.qt.TQCursor");
}

JNIEXPORT jobject JNICALL
Java_org_trinitydesktop_qt_Qt_upArrowCursor(JNIEnv* env, jclass cls)
{
	(void) cls;
	return (jobject) QtSupport::objectForQtKey(env, (void*)&TQt::upArrowCursor, "org.trinitydesktop.qt.TQCursor");
}

JNIEXPORT jobject JNICALL
Java_org_trinitydesktop_qt_Qt_crossCursor(JNIEnv* env, jclass cls)
{
	(void) cls;
	return (jobject) QtSupport::objectForQtKey(env, (void*)&TQt::crossCursor, "org.trinitydesktop.qt.TQCursor");
}

JNIEXPORT jobject JNICALL
Java_org_trinitydesktop_qt_Qt_waitCursor(JNIEnv* env, jclass cls)
{
	(void) cls;
	return (jobject) QtSupport::objectForQtKey(env, (void*)&TQt::waitCursor, "org.trinitydesktop.qt.TQCursor");
}

JNIEXPORT jobject JNICALL
Java_org_trinitydesktop_qt_Qt_ibeamCursor(JNIEnv* env, jclass cls)
{
	(void) cls;
	return (jobject) QtSupport::objectForQtKey(env, (void*)&TQt::ibeamCursor, "org.trinitydesktop.qt.TQCursor");
}

JNIEXPORT jobject JNICALL
Java_org_trinitydesktop_qt_Qt_sizeVerCursor(JNIEnv* env, jclass cls)
{
	(void) cls;
	return (jobject) QtSupport::objectForQtKey(env, (void*)&TQt::sizeVerCursor, "org.trinitydesktop.qt.TQCursor");
}

JNIEXPORT jobject JNICALL
Java_org_trinitydesktop_qt_Qt_sizeHorCursor(JNIEnv* env, jclass cls)
{
	(void) cls;
	return (jobject) QtSupport::objectForQtKey(env, (void*)&TQt::sizeHorCursor, "org.trinitydesktop.qt.TQCursor");
}

JNIEXPORT jobject JNICALL
Java_org_trinitydesktop_qt_Qt_sizeBDiagCursor(JNIEnv* env, jclass cls)
{
	(void) cls;
	return (jobject) QtSupport::objectForQtKey(env, (void*)&TQt::sizeBDiagCursor, "org.trinitydesktop.qt.TQCursor");
}

JNIEXPORT jobject JNICALL
Java_org_trinitydesktop_qt_Qt_sizeFDiagCursor(JNIEnv* env, jclass cls)
{
	(void) cls;
	return (jobject) QtSupport::objectForQtKey(env, (void*)&TQt::sizeFDiagCursor, "org.trinitydesktop.qt.TQCursor");
}

JNIEXPORT jobject JNICALL
Java_org_trinitydesktop_qt_Qt_sizeAllCursor(JNIEnv* env, jclass cls)
{
	(void) cls;
	return (jobject) QtSupport::objectForQtKey(env, (void*)&TQt::sizeAllCursor, "org.trinitydesktop.qt.TQCursor");
}

JNIEXPORT jobject JNICALL
Java_org_trinitydesktop_qt_Qt_blankCursor(JNIEnv* env, jclass cls)
{
	(void) cls;
	return (jobject) QtSupport::objectForQtKey(env, (void*)&TQt::blankCursor, "org.trinitydesktop.qt.TQCursor");
}

JNIEXPORT jobject JNICALL
Java_org_trinitydesktop_qt_Qt_splitVCursor(JNIEnv* env, jclass cls)
{
	(void) cls;
	return (jobject) QtSupport::objectForQtKey(env, (void*)&TQt::splitVCursor, "org.trinitydesktop.qt.TQCursor");
}

JNIEXPORT jobject JNICALL
Java_org_trinitydesktop_qt_Qt_splitHCursor(JNIEnv* env, jclass cls)
{
	(void) cls;
	return (jobject) QtSupport::objectForQtKey(env, (void*)&TQt::splitHCursor, "org.trinitydesktop.qt.TQCursor");
}

JNIEXPORT jobject JNICALL
Java_org_trinitydesktop_qt_Qt_pointingHandCursor(JNIEnv* env, jclass cls)
{
	(void) cls;
	return (jobject) QtSupport::objectForQtKey(env, (void*)&TQt::pointingHandCursor, "org.trinitydesktop.qt.TQCursor");
}

JNIEXPORT jobject JNICALL
Java_org_trinitydesktop_qt_Qt_forbiddenCursor(JNIEnv* env, jclass cls)
{
	(void) cls;
	return (jobject) QtSupport::objectForQtKey(env, (void*)&TQt::forbiddenCursor, "org.trinitydesktop.qt.TQCursor");
}

JNIEXPORT jobject JNICALL
Java_org_trinitydesktop_qt_Qt_whatsThisCursor(JNIEnv* env, jclass cls)
{
	(void) cls;
	return (jobject) QtSupport::objectForQtKey(env, (void*)&TQt::whatsThisCursor, "org.trinitydesktop.qt.TQCursor");
}

JNIEXPORT jobject JNICALL
Java_org_trinitydesktop_qt_Qt_qApp(JNIEnv* env, jclass cls)
{
	(void) cls;
	return (jobject) QtSupport::objectForQtKey(env, tqApp, "org.trinitydesktop.qt.TQApplication");
}

JNIEXPORT void JNICALL
Java_org_trinitydesktop_qt_Qt_tqDebug(JNIEnv* env, jclass cls, jstring message)
{
static TQCString * _qstring_message = 0;
	(void) cls;
	tqDebug("%s", (const char *) QtSupport::toCharString(env, message, &_qstring_message));
	return;
}

JNIEXPORT void JNICALL
Java_org_trinitydesktop_qt_Qt_tqWarning(JNIEnv* env, jclass cls, jstring message)
{
static TQCString * _qstring_message = 0;
	(void) cls;
	tqWarning("%s", (const char *) QtSupport::toCharString(env, message, &_qstring_message));
	return;
}

JNIEXPORT void JNICALL
Java_org_trinitydesktop_qt_Qt_tqFatal(JNIEnv* env, jclass cls, jstring message)
{
static TQCString * _qstring_message = 0;
	(void) cls;
	tqFatal("%s", (const char *) QtSupport::toCharString(env, message, &_qstring_message));
	return;
}

EOF

	$qobjectExtras = <<EOF;
	/** i18n() is just a synonym of tr() for now */
    public static String i18n(String s) {
      return tr(s);
	}
	
	public native void emit(String signal, Object[] args);

	protected void emit(String signal) {
		Object[] args = new Object[0];
		emit("2" + signal.trim() + "()", args);
	}

	protected void emit(String signal, Object value) {
		Object[] args = new Object[1];
		args[0] = value;
		emit("2" + signal.trim() + "(" + value.getClass().getName() + ")", args);
	}

	protected void emit(String signal, Object value1, Object value2) {
		Object[] args = new Object[2];
		args[0] = value1;
		args[1] = value2;
		emit("2" + signal.trim() + "(" 	+ value1.getClass().getName() + ","
										+ value2.getClass().getName()
										+ ")", args);
	}

	protected void emit(String signal, Object value1, Object value2, Object value3) {
		Object[] args = new Object[3];
		args[0] = value1;
		args[1] = value2;
		args[2] = value3;
		emit("2" + signal.trim() + "("	+ value1.getClass().getName() + ","
										+ value2.getClass().getName() + ","
										+ value3.getClass().getName()
										+ ")", args);
	}

	protected void emit(String signal, Object value1, Object value2, Object value3, Object value4) {
		Object[] args = new Object[4];
		args[0] = value1;
		args[1] = value2;
		args[2] = value3;
		args[3] = value4;
		emit("2" + signal.trim() + "("	+ value1.getClass().getName() + ","
										+ value2.getClass().getName() + ","
										+ value3.getClass().getName() + ","
										+ value4.getClass().getName()
										+ ")", args);
	}

	protected void emit(String signal, boolean value) {
		Object[] args = new Object[1];
		args[0] = new Boolean(value);
		emit("2" + signal.trim() + "(boolean)", args);
	}
	
	protected void emit(String signal, char value) {
		Object[] args = new Object[1];
		args[0] = new Character(value);
		emit("2" + signal.trim() + "(char)", args);
	}
	
	protected void emit(String signal, byte value) {
		Object[] args = new Object[1];
		args[0] = new Byte(value);
		emit("2" + signal.trim() + "(byte)", args);
	}

	protected void emit(String signal, short value) {
		Object[] args = new Object[1];
		args[0] = new Short(value);
		emit("2" + signal.trim() + "(short)", args);
	}
	
	protected void emit(String signal, int value) {
		Object[] args = new Object[1];
		args[0] = new Integer(value);
		emit("2" + signal.trim() + "(int)", args);
	}
	
	protected void emit(String signal, int value1, int value2) {
		Object[] args = new Object[2];
		args[0] = new Integer(value1);
		args[1] = new Integer(value2);
		emit("2" + signal.trim() + "(int,int)", args);
	}

	protected void emit(String signal, Object value1, int value2) {
		Object[] args = new Object[2];
		args[0] = value1;
		args[1] = new Integer(value2);
		emit("2" + signal.trim() + "(" 	+ value1.getClass().getName() + ","
										+ "int"
										+ ")", args);
	}

	protected void emit(String signal, int value1, int value2, int value3) {
		Object[] args = new Object[3];
		args[0] = new Integer(value1);
		args[1] = new Integer(value2);
		args[2] = new Integer(value3);
		emit("2" + signal.trim() + "(int,int,int)", args);
	}

	protected void emit(String signal, int value1, int value2, int value3, Object value4) {
		Object[] args = new Object[4];
		args[0] = new Integer(value1);
		args[1] = new Integer(value2);
		args[2] = new Integer(value3);
		args[3] = value4;
		emit("2" + signal.trim() + "(int,int,int," + value4.getClass().getName() + ")", args);
	}

	protected void emit(String signal, int value1, Object value2, Object value3) {
		Object[] args = new Object[3];
		args[0] = new Integer(value1);
		args[1] = value2;
		args[2] = value3;
		emit("2" + signal.trim()	+ "(int,"
									+ value2.getClass().getName() + ","
									+ value3.getClass().getName()
									+ ")", args);
	}

	protected void emit(String signal, int value1, Object value2, Object value3, int value4) {
		Object[] args = new Object[4];
		args[0] = new Integer(value1);
		args[1] = value2;
		args[2] = value3;
		args[3] = new Integer(value4);
		emit("2" + signal.trim()	+ "(int,"
									+ value2.getClass().getName() + ","
									+ value3.getClass().getName()
									+ ",int)", args);
	}
	
	protected void emit(String signal, int value1, boolean value2) {
		Object[] args = new Object[2];
		args[0] = new Integer(value1);
		args[1] = new Boolean(value2);
		emit("2" + signal.trim() + "(int,boolean)", args);
	}

	protected void emit(String signal, long value) {
		Object[] args = new Object[1];
		args[0] = new Long(value);
		emit("2" + signal.trim() + "(long)", args);
	}

	protected void emit(String signal, float value) {
		Object[] args = new Object[1];
		args[0] = new Float(value);
		emit("2" + signal.trim() + "(float)", args);
	}

	protected void emit(String signal, double value) {
		Object[] args = new Object[1];
		args[0] = new Double(value);
		emit("2" + signal.trim() + "(double)", args);
	}

	protected void emit(String signal, Object value1, int value2, int value3) {
		Object[] args = new Object[3];
		args[0] = value1;
		args[1] = new Integer(value2);
		args[2] = new Integer(value3);
		emit("2" + signal.trim() + "(" + value1.getClass().getName() + ",int,int)", args);
	}	

EOF

	$qobjectjniExtras = <<EOF;
JNIEXPORT jboolean JNICALL
Java_org_trinitydesktop_qt_QObject_connect__Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2(JNIEnv* env, jclass cls, jobject sender, jstring signal, jobject receiver, jstring member)
{
	(void) cls;
	return (jboolean) QtSupport::connect(env, sender, signal, receiver, member);
}

JNIEXPORT jboolean JNICALL
Java_org_trinitydesktop_qt_QObject_connect__Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2Ljava_lang_String_2(JNIEnv* env, jobject obj, jobject sender, jstring signal, jstring member)
{
	return (jboolean) QtSupport::connect(env, sender, signal, obj, member);
}

JNIEXPORT jboolean JNICALL
Java_org_trinitydesktop_qt_QObject_disconnect__Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2(JNIEnv *env, jclass cls, jobject sender, jstring signal, jobject receiver, jstring member)
{
	(void) cls;
	return (jboolean) QtSupport::disconnect(env, sender, signal, receiver, member);
}

JNIEXPORT jboolean JNICALL
Java_org_trinitydesktop_qt_QObject_disconnect__Ljava_lang_String_2Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2(JNIEnv* env, jobject obj, jstring signal, jobject receiver, jstring member)
{
	return (jboolean) QtSupport::disconnect(env, obj, signal, receiver, member);
}

JNIEXPORT void JNICALL
Java_org_trinitydesktop_qt_QObject_emit(JNIEnv* env, jobject obj, jstring signal, jobjectArray args)
{
	QtSupport::emitJavaSignal(env, obj, signal, args);
	return;
}
	
EOF

	$qwidgetExtras = <<EOF;
	/** Internal method */
	protected native long paintDevice();

EOF

	$qwidgetjniExtras = <<EOF;
JNIEXPORT jlong JNICALL
Java_org_trinitydesktop_qt_QWidget_paintDevice(JNIEnv* env, jobject obj)
{
	return (jlong) (TQPaintDevice*)(TQWidget*) QtSupport::getQt(env, obj);
}

EOF
	
	$qimagejniExtras = <<EOF;
JNIEXPORT jbyteArray JNICALL
Java_org_trinitydesktop_qt_QImage_bits(JNIEnv *env, jobject obj)
{
static uchar * ptr = 0;
	ptr = ((TQImageJBridge*) QtSupport::getQt(env, obj))->bits();
	int len = ((TQImageJBridge*) QtSupport::getQt(env, obj))->numBytes();
	jbyteArray result = env->NewByteArray(len);
	env->SetByteArrayRegion(result, 0, len, (jbyte *) ptr);
	return result;
}

JNIEXPORT jbyteArray JNICALL
Java_org_trinitydesktop_qt_QImage_scanLine(JNIEnv *env, jobject obj, jint arg1)
{
static uchar * ptr = 0;
	ptr = ((TQImageJBridge*) QtSupport::getQt(env, obj))->scanLine(arg1);
	int len = ((TQImageJBridge*) QtSupport::getQt(env, obj))->numBytes() / ((TQImageJBridge*) QtSupport::getQt(env, obj))->height();
	jbyteArray result = env->NewByteArray(len);
	env->SetByteArrayRegion(result, 0, len, (jbyte *) ptr);
	return result;
}

JNIEXPORT jintArray JNICALL
Java_org_trinitydesktop_qt_QImage_colorTable(JNIEnv *env, jobject obj)
{
static TQRgb * ptr = 0;
	ptr = ((TQImageJBridge*) QtSupport::getQt(env, obj))->colorTable();
	int len = ((TQImageJBridge*) QtSupport::getQt(env, obj))->numColors();
	jintArray result = env->NewIntArray(len);
	env->SetIntArrayRegion(result, 0, len, (jint *) ptr);
	return result;
}

EOF

	$qpixmapExtras = <<EOF;
	public native boolean loadFromData(char[] data);
	
	/** Internal method */
	protected native long paintDevice();

EOF

	$qpixmapjniExtras = <<EOF;
JNIEXPORT jboolean JNICALL
Java_org_trinitydesktop_qt_QPixmap_loadFromData___3C(JNIEnv *env, jobject obj, jcharArray data)
{
static TQByteArray * _qbyteArray_data = 0;
	return (jboolean) ((TQPixmapJBridge*) QtSupport::getQt(env, obj))->loadFromData((uchar *) QtSupport::toUcharArray(env, data, &_qbyteArray_data), env->GetArrayLength(data), 0, 0);
}
	
JNIEXPORT jlong JNICALL
Java_org_trinitydesktop_qt_QPixmap_paintDevice(JNIEnv* env, jobject obj)
{
	return (jlong) (TQPaintDevice*)(TQPixmap*) QtSupport::getQt(env, obj);
}

EOF

	$qpaintdeviceExtras = <<EOF;
	/** Internal method */
	protected native long paintDevice();

EOF

	$qpaintdevicejniExtras = <<EOF;
JNIEXPORT jlong JNICALL
Java_org_trinitydesktop_qt_QPaintDevice_paintDevice(JNIEnv* env, jobject obj)
{
	return (jlong) (TQPaintDevice *) QtSupport::getQt(env, obj);
}

EOF

	$qdragobjectExtras = <<EOF;
	/** Internal method */
	protected native long mimeSource();

EOF
	
	$qdragobjectjniExtras = <<EOF;
JNIEXPORT jlong JNICALL
Java_org_trinitydesktop_qt_QDragObject_mimeSource(JNIEnv* env, jobject obj)
{
	return (jlong) (TQMimeSource*) (TQDragObject*) QtSupport::getQt(env, obj);
}

EOF
		
	$qdropeventExtras = <<EOF;
	/** Internal method */
	protected native long mimeSource();
	
EOF
	
	$qdropeventjniExtras = <<EOF;
JNIEXPORT jlong JNICALL
Java_org_trinitydesktop_qt_QDropEvent_mimeSource(JNIEnv* env, jobject obj)
{
	return (jlong) (TQMimeSource*) (TQDropEvent*) QtSupport::getQt(env, obj);
}

EOF
	
	$qmimesourceExtras = <<EOF;
	/** Internal method */
	protected native long mimeSource();

EOF
	
	$qmimesourcejniExtras = <<EOF;
JNIEXPORT jlong JNICALL
Java_org_trinitydesktop_qt_QMimeSource_mimeSource(JNIEnv* env, jobject obj)
{
	return (jlong) (TQMimeSource *) QtSupport::getQt(env, obj);
}

EOF
	
	$qiodeviceExtras = <<EOF;
	public static final int IO_Direct = 0x0100;		// direct access device
	public static final int IO_Sequential		= 0x0200;		// sequential access device
	public static final int IO_Combined		= 0x0300;		// combined direct/sequential
	public static final int IO_TypeMask		= 0x0f00;

// IO handling modes

	public static final int IO_Raw			= 0x0040;		// raw access (not buffered)
	public static final int IO_Async		= 0x0080;		// asynchronous mode

// IO device open modes

	public static final int IO_ReadOnly		= 0x0001;		// readable device
	public static final int IO_WriteOnly		= 0x0002;		// writable device
	public static final int IO_ReadWrite		= 0x0003;		// read+write device
	public static final int IO_Append		= 0x0004;		// append
	public static final int IO_Truncate		= 0x0008;		// truncate device
	public static final int IO_Translate		= 0x0010;		// translate CR+LF
	public static final int IO_ModeMask		= 0x00ff;

// IO device state

	public static final int IO_Open			= 0x1000;		// device is open
	public static final int IO_StateMask		= 0xf000;


// IO device status

	public static final int IO_Ok			= 0;
	public static final int IO_ReadError		= 1;		// read error
	public static final int IO_WriteError		= 2;		// write error
	public static final int IO_FatalError		= 3;		// fatal unrecoverable error
	public static final int IO_ResourceError	= 4;		// resource limitation
	public static final int IO_OpenError		= 5;		// cannot open device
	public static final int IO_ConnectError		= 5;		// cannot connect to device
	public static final int IO_AbortError		= 6;		// abort error
	public static final int IO_TimeOutError		= 7;		// time out
	public static final int IO_UnspecifiedError	= 8;		// unspecified error

EOF
	
	$qpointarrayExtras = <<EOF;
	public native int size();
	public native int count();
	public native boolean isEmpty();
	public native boolean isNull();
	public native boolean resize( int size);
	public native boolean truncate( int pos);
	public native int begin();
	public native int end();
	public native TQPoint at(int index);
	
EOF
		
	$qpointarrayjniExtras = <<EOF;
JNIEXPORT void JNICALL
Java_org_trinitydesktop_qt_QPointArray_point__I_3I_3I(JNIEnv *env, jobject obj, jint i, jintArray x, jintArray y)
{
	int argx;
	int argy;
	((TQPointArrayJBridge*) QtSupport::getQt(env, obj))->point((uint) i,  &argx,  &argy);
	env->SetIntArrayRegion(x, 0, 1, (jint *) &argx);
	env->SetIntArrayRegion(y, 0, 1, (jint *) &argy);
	return;
}

JNIEXPORT jboolean JNICALL
Java_org_trinitydesktop_qt_QPointArray_setPoints(JNIEnv *env, jobject obj, jint nPoints, jshortArray points)
{
	if (!((TQPointArrayJBridge*) QtSupport::getQt(env, obj))->resize((uint)nPoints)) {
		return JNI_FALSE;
	}

	short *	shortArray = QtSupport::toShortPtr(env, points);
	for (int index = 0; index < nPoints; index++) {
		((TQPointArrayJBridge*) QtSupport::getQt(env, obj))->setPoint(index, shortArray[index * 2], shortArray[(index * 2) + 1]);
	}
	return JNI_TRUE;
}

JNIEXPORT jboolean JNICALL
Java_org_trinitydesktop_qt_QPointArray_putPoints__II_3S(JNIEnv *env, jobject obj, jint index, jint nPoints, jshortArray points)
{
	if (	((TQPointArrayJBridge*) QtSupport::getQt(env, obj))->size() < (uint) nPoints
			&& !((TQPointArrayJBridge*) QtSupport::getQt(env, obj))->resize((uint) nPoints) )
	{
		return JNI_FALSE;
	}

	short *	shortArray = QtSupport::toShortPtr(env, points);
	for (int i = (int) index; nPoints > 0; i++, nPoints--) {
		((TQPointArrayJBridge*) QtSupport::getQt(env, obj))->setPoint(i, shortArray[i * 2], shortArray[(i * 2) + 1]);
	}
	return JNI_TRUE;
}

JNIEXPORT jint JNICALL
Java_org_trinitydesktop_qt_QPointArray_size(JNIEnv* env, jobject obj)
{
	return (jint) ((TQPointArrayJBridge*) QtSupport::getQt(env, obj))->size();
}

JNIEXPORT jint JNICALL
Java_org_trinitydesktop_qt_QPointArray_count(JNIEnv* env, jobject obj)
{
	return (jint) ((TQPointArrayJBridge*) QtSupport::getQt(env, obj))->count();
}

JNIEXPORT jboolean JNICALL
Java_org_trinitydesktop_qt_QPointArray_isEmpty(JNIEnv* env, jobject obj)
{
	return (jboolean) ((TQPointArrayJBridge*) QtSupport::getQt(env, obj))->isEmpty();
}

JNIEXPORT jboolean JNICALL
Java_org_trinitydesktop_qt_QPointArray_isNull(JNIEnv* env, jobject obj)
{
	return (jboolean) ((TQPointArrayJBridge*) QtSupport::getQt(env, obj))->isNull();
}

JNIEXPORT jboolean JNICALL
Java_org_trinitydesktop_qt_QPointArray_resize(JNIEnv* env, jobject obj, jint size)
{
	return (jboolean) ((TQPointArrayJBridge*) QtSupport::getQt(env, obj))->resize((uint) size);
}
JNIEXPORT jboolean JNICALL
Java_org_trinitydesktop_qt_QPointArray_truncate(JNIEnv *env, jobject obj, jint pos)
{
	return (jboolean) ((TQPointArrayJBridge*) QtSupport::getQt(env, obj))->truncate((uint) pos);
}

JNIEXPORT jobject JNICALL
Java_org_trinitydesktop_qt_QPointArray_at(JNIEnv * env, jobject obj, jint index)
{
	TQPoint _p= ((TQPointArrayJBridge*) QtSupport::getQt(env, obj))->at((uint) index);
	return (jobject) QtSupport::objectForQtKey(env, (void *)new TQPoint(_p.x(),_p.y()), "org.trinitydesktop.qt.TQPoint", true);
}
	
EOF

	$qpopupmenujniExtras = <<EOF;
JNIEXPORT jint JNICALL
Java_org_trinitydesktop_qt_QPopupMenu_insertItem__Ljava_lang_String_2Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2Lorg_trinitydesktop_qt_QKeySequence_2II(JNIEnv *env, jobject obj, jstring text, jobject receiver, jstring member, jobject accel, jint identifier, jint index)
{
	identifier = Java_org_trinitydesktop_qt_QPopupMenu_insertItem__Ljava_lang_String_2II(env, obj, text, identifier, index);

	if ((bool) Java_org_trinitydesktop_qt_QPopupMenu_connectItem(env, obj, identifier, receiver, member)) {
		Java_org_trinitydesktop_qt_QPopupMenu_setAccel(env, obj, accel, identifier);
	}

	return identifier;
}

JNIEXPORT jint JNICALL
Java_org_trinitydesktop_qt_QPopupMenu_insertItem__Ljava_lang_String_2Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2(JNIEnv *env, jobject obj, jstring text, jobject receiver, jstring member)
{
	jint identifier = Java_org_trinitydesktop_qt_QPopupMenu_insertItem__Ljava_lang_String_2II(env, obj, text, -1, -1);
	Java_org_trinitydesktop_qt_QPopupMenu_connectItem(env, obj, identifier, receiver, member);

	return identifier;
}

JNIEXPORT jint JNICALL
Java_org_trinitydesktop_qt_QPopupMenu_insertItem__Lorg_trinitydesktop_qt_QIconSet_2Ljava_lang_String_2Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2(JNIEnv *env, jobject obj, jobject icon, jstring text, jobject receiver, jstring member)
{
static TQString * _qstring_text = 0;
	jint identifier = Java_org_trinitydesktop_qt_QPopupMenu_insertItem__Lorg_trinitydesktop_qt_QIconSet_2Ljava_lang_String_2II(env, obj, icon, text, -1, -1);
	Java_org_trinitydesktop_qt_QPopupMenu_connectItem(env, obj, identifier, receiver, member);
	
	return identifier;
}

JNIEXPORT jint JNICALL
Java_org_trinitydesktop_qt_QPopupMenu_insertItem__Lorg_trinitydesktop_qt_QPixmap_2Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2(JNIEnv *env, jobject obj, jobject pixmap, jobject receiver, jstring member)
{
	jint identifier = Java_org_trinitydesktop_qt_QPopupMenu_insertItem__Lorg_trinitydesktop_qt_QPixmap_2II(env, obj, pixmap, -1, -1);
	Java_org_trinitydesktop_qt_QPopupMenu_connectItem(env, obj, identifier, receiver, member);

	return identifier;
}

JNIEXPORT jint JNICALL
Java_org_trinitydesktop_qt_QPopupMenu_insertItem__Lorg_trinitydesktop_qt_QIconSet_2Lorg_trinitydesktop_qt_QPixmap_2Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2(JNIEnv *env, jobject obj, jobject icon, jobject pixmap, jobject receiver, jstring member)
{
	jint identifier = Java_org_trinitydesktop_qt_QPopupMenu_insertItem__Lorg_trinitydesktop_qt_QIconSet_2Lorg_trinitydesktop_qt_QPixmap_2II(env, obj, icon, pixmap, -1, -1);
	Java_org_trinitydesktop_qt_QPopupMenu_connectItem(env, obj, identifier, receiver, member);

	return identifier;
}

JNIEXPORT jboolean JNICALL
Java_org_trinitydesktop_qt_QPopupMenu_connectItem(JNIEnv *env, jobject obj, jint identifier, jobject receiver, jstring member)
{
	JavaSlot * javaSlot = QtSupport::slotForReceiver(env, receiver, member);

	if (	((TQPopupMenuJBridge*) QtSupport::getQt(env, obj))->connectItem(	identifier,
																			javaSlot,
																			javaSlot->javaToQtSlotName(env, member) ) )
	{
		return(jboolean) JNI_TRUE;
	} else {
		return (jboolean) JNI_FALSE;
	}
}

JNIEXPORT jboolean JNICALL
Java_org_trinitydesktop_qt_QPopupMenu_disconnectItem(JNIEnv *env, jobject obj, jint identifier, jobject receiver, jstring member)
{
	JavaSlot * javaSlot = QtSupport::slotForReceiver(env, receiver, member);

	if (	((TQPopupMenuJBridge*) QtSupport::getQt(env, obj))->disconnectItem(	identifier,
																				javaSlot,
																				javaSlot->javaToQtSlotName(env, member) ) )
	{
		return(jboolean) JNI_TRUE;
	} else {
		return (jboolean) JNI_FALSE;
	}
}

EOF

	$qmenudatajniExtras = <<EOF;
JNIEXPORT jint JNICALL
Java_org_trinitydesktop_qt_QMenuData_insertItem__Ljava_lang_String_2Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2Lorg_trinitydesktop_qt_QKeySequence_2II(JNIEnv *env, jobject obj, jstring text, jobject receiver, jstring member, jobject accel, jint identifier, jint index)
{
	identifier = Java_org_trinitydesktop_qt_QMenuData_insertItem__Ljava_lang_String_2II(env, obj, text, identifier, index);

	if ((bool) Java_org_trinitydesktop_qt_QMenuData_connectItem(env, obj, identifier, receiver, member)) {
		Java_org_trinitydesktop_qt_QMenuData_setAccel(env, obj, accel, identifier);
	}

	return identifier;
}

JNIEXPORT jint JNICALL
Java_org_trinitydesktop_qt_QMenuData_insertItem__Ljava_lang_String_2Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2(JNIEnv *env, jobject obj, jstring text, jobject receiver, jstring member)
{
	jint identifier = Java_org_trinitydesktop_qt_QMenuData_insertItem__Ljava_lang_String_2II(env, obj, text, -1, -1);
	Java_org_trinitydesktop_qt_QMenuData_connectItem(env, obj, identifier, receiver, member);

	return identifier;
}

JNIEXPORT jint JNICALL
Java_org_trinitydesktop_qt_QMenuData_insertItem__Lorg_trinitydesktop_qt_QIconSet_2Ljava_lang_String_2Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2(JNIEnv *env, jobject obj, jobject icon, jstring text, jobject receiver, jstring member)
{
static TQString * _qstring_text = 0;
	jint identifier = Java_org_trinitydesktop_qt_QMenuData_insertItem__Lorg_trinitydesktop_qt_QIconSet_2Ljava_lang_String_2II(env, obj, icon, text, -1, -1);
	Java_org_trinitydesktop_qt_QMenuData_connectItem(env, obj, identifier, receiver, member);
	
	return identifier;
}

JNIEXPORT jint JNICALL
Java_org_trinitydesktop_qt_QMenuData_insertItem__Lorg_trinitydesktop_qt_QPixmap_2Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2(JNIEnv *env, jobject obj, jobject pixmap, jobject receiver, jstring member)
{
	jint identifier = Java_org_trinitydesktop_qt_QMenuData_insertItem__Lorg_trinitydesktop_qt_QPixmap_2II(env, obj, pixmap, -1, -1);
	Java_org_trinitydesktop_qt_QMenuData_connectItem(env, obj, identifier, receiver, member);

	return identifier;
}

JNIEXPORT jint JNICALL
Java_org_trinitydesktop_qt_QMenuData_insertItem__Lorg_trinitydesktop_qt_QIconSet_2Lorg_trinitydesktop_qt_QPixmap_2Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2(JNIEnv *env, jobject obj, jobject icon, jobject pixmap, jobject receiver, jstring member)
{
	jint identifier = Java_org_trinitydesktop_qt_QMenuData_insertItem__Lorg_trinitydesktop_qt_QIconSet_2Lorg_trinitydesktop_qt_QPixmap_2II(env, obj, icon, pixmap, -1, -1);
	Java_org_trinitydesktop_qt_QMenuData_connectItem(env, obj, identifier, receiver, member);

	return identifier;
}

JNIEXPORT jboolean JNICALL
Java_org_trinitydesktop_qt_QMenuData_connectItem(JNIEnv *env, jobject obj, jint identifier, jobject receiver, jstring member)
{
	JavaSlot * javaSlot = QtSupport::slotForReceiver(env, receiver, member);

	if (	((TQMenuDataJBridge*) QtSupport::getQt(env, obj))->connectItem(	identifier,
																			javaSlot,
																			javaSlot->javaToQtSlotName(env, member) ) )
	{
		return(jboolean) JNI_TRUE;
	} else {
		return (jboolean) JNI_FALSE;
	}
}

JNIEXPORT jboolean JNICALL
Java_org_trinitydesktop_qt_QMenuData_disconnectItem(JNIEnv *env, jobject obj, jint identifier, jobject receiver, jstring member)
{
	JavaSlot * javaSlot = QtSupport::slotForReceiver(env, receiver, member);

	if (	((TQMenuDataJBridge*) QtSupport::getQt(env, obj))->disconnectItem(	identifier,
																				javaSlot,
																				javaSlot->javaToQtSlotName(env, member) ) )
	{
		return(jboolean) JNI_TRUE;
	} else {
		return (jboolean) JNI_FALSE;
	}
}

EOF

	$qmenubarjniExtras = <<EOF;
JNIEXPORT jint JNICALL
Java_org_trinitydesktop_qt_QMenuBar_insertItem__Ljava_lang_String_2Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2Lorg_trinitydesktop_qt_QKeySequence_2II(JNIEnv *env, jobject obj, jstring text, jobject receiver, jstring member, jobject accel, jint identifier, jint index)
{
	identifier = Java_org_trinitydesktop_qt_QMenuBar_insertItem__Ljava_lang_String_2II(env, obj, text, identifier, index);

	if ((bool) Java_org_trinitydesktop_qt_QMenuBar_connectItem(env, obj, identifier, receiver, member)) {
		Java_org_trinitydesktop_qt_QMenuBar_setAccel(env, obj, accel, identifier);
	}

	return identifier;
}

JNIEXPORT jint JNICALL
Java_org_trinitydesktop_qt_QMenuBar_insertItem__Ljava_lang_String_2Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2(JNIEnv *env, jobject obj, jstring text, jobject receiver, jstring member)
{
	jint identifier = Java_org_trinitydesktop_qt_QMenuBar_insertItem__Ljava_lang_String_2II(env, obj, text, -1, -1);
	Java_org_trinitydesktop_qt_QMenuBar_connectItem(env, obj, identifier, receiver, member);

	return identifier;
}

JNIEXPORT jint JNICALL
Java_org_trinitydesktop_qt_QMenuBar_insertItem__Lorg_trinitydesktop_qt_QIconSet_2Ljava_lang_String_2Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2(JNIEnv *env, jobject obj, jobject icon, jstring text, jobject receiver, jstring member)
{
static TQString * _qstring_text = 0;
	jint identifier = Java_org_trinitydesktop_qt_QMenuBar_insertItem__Lorg_trinitydesktop_qt_QIconSet_2Ljava_lang_String_2II(env, obj, icon, text, -1, -1);
	Java_org_trinitydesktop_qt_QMenuBar_connectItem(env, obj, identifier, receiver, member);
	
	return identifier;
}

JNIEXPORT jint JNICALL
Java_org_trinitydesktop_qt_QMenuBar_insertItem__Lorg_trinitydesktop_qt_QPixmap_2Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2(JNIEnv *env, jobject obj, jobject pixmap, jobject receiver, jstring member)
{
	jint identifier = Java_org_trinitydesktop_qt_QMenuBar_insertItem__Lorg_trinitydesktop_qt_QPixmap_2II(env, obj, pixmap, -1, -1);
	Java_org_trinitydesktop_qt_QMenuBar_connectItem(env, obj, identifier, receiver, member);

	return identifier;
}

JNIEXPORT jint JNICALL
Java_org_trinitydesktop_qt_QMenuBar_insertItem__Lorg_trinitydesktop_qt_QIconSet_2Lorg_trinitydesktop_qt_QPixmap_2Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2(JNIEnv *env, jobject obj, jobject icon, jobject pixmap, jobject receiver, jstring member)
{
	jint identifier = Java_org_trinitydesktop_qt_QMenuBar_insertItem__Lorg_trinitydesktop_qt_QIconSet_2Lorg_trinitydesktop_qt_QPixmap_2II(env, obj, icon, pixmap, -1, -1);
	Java_org_trinitydesktop_qt_QMenuBar_connectItem(env, obj, identifier, receiver, member);

	return identifier;
}

JNIEXPORT jboolean JNICALL
Java_org_trinitydesktop_qt_QMenuBar_connectItem(JNIEnv *env, jobject obj, jint identifier, jobject receiver, jstring member)
{
	JavaSlot * javaSlot = QtSupport::slotForReceiver(env, receiver, member);

	if (	((TQMenuBarJBridge*) QtSupport::getQt(env, obj))->connectItem(	identifier,
																			javaSlot,
																			javaSlot->javaToQtSlotName(env, member) ) )
	{
		return(jboolean) JNI_TRUE;
	} else {
		return (jboolean) JNI_FALSE;
	}
}

JNIEXPORT jboolean JNICALL
Java_org_trinitydesktop_qt_QMenuBar_disconnectItem(JNIEnv *env, jobject obj, jint identifier, jobject receiver, jstring member)
{
	JavaSlot * javaSlot = QtSupport::slotForReceiver(env, receiver, member);

	if (	((TQMenuBarJBridge*) QtSupport::getQt(env, obj))->disconnectItem(	identifier,
																				javaSlot,
																				javaSlot->javaToQtSlotName(env, member) ) )
	{
		return(jboolean) JNI_TRUE;
	} else {
		return (jboolean) JNI_FALSE;
	}
}


EOF

	$quridragExtras  = <<EOF;
	public static native boolean decode(TQMimeSourceInterface e, ArrayList i);
	public static native boolean decodeToUnicodeUris(TQMimeSourceInterface e, ArrayList i);
	public static native boolean decodeLocalFiles(TQMimeSourceInterface e, ArrayList i);
	
EOF

	$quridragjniExtras = <<EOF;
JNIEXPORT jboolean JNICALL
Java_org_trinitydesktop_qt_QUriDrag_decode(JNIEnv *env, jclass cls, jobject e, jobject i)
{
static TQStrList * _qlist_i = 0;
	if (_qlist_i == 0) {
		_qlist_i = new TQStrList();
	}
	(void) cls;
	jboolean result = (jboolean) TQUriDragJBridge::decode(QtSupport::mimeSource(env, e), *_qlist_i);
	QtSupport::arrayWithTQStrList(env, _qlist_i, i);
	return result;
}

JNIEXPORT jboolean JNICALL
Java_org_trinitydesktop_qt_QUriDrag_decodeToUnicodeUris(JNIEnv *env, jclass cls, jobject e, jobject i)
{
static TQStringList * _qlist_i = 0;
	if (_qlist_i == 0) {
		_qlist_i = new TQStringList();
	}
	(void) cls;
	jboolean result = (jboolean) TQUriDragJBridge::decodeToUnicodeUris(QtSupport::mimeSource(env, e), *_qlist_i);
	QtSupport::arrayWithTQStringList(env, _qlist_i, i);
	return result;
}

JNIEXPORT jboolean JNICALL
Java_org_trinitydesktop_qt_QUriDrag_decodeLocalFiles(JNIEnv *env, jclass cls, jobject e, jobject i)
{
static TQStringList * _qlist_i = 0;
	if (_qlist_i == 0) {
		_qlist_i = new TQStringList();
	}
	(void) cls;
	jboolean result = (jboolean) TQUriDragJBridge::decodeLocalFiles(QtSupport::mimeSource(env, e), *_qlist_i);
	QtSupport::arrayWithTQStringList(env, _qlist_i, i);
	return result;
}
	
EOF

	$kapplicationExtras = <<EOF;
	/**
		Used internally by the KDE Koala Java bindings runtime
	*/
	public static native void setJavaSlotFactory();
	
EOF

	$kapplicationjniExtras = <<EOF;
#include <tdejava/TDEJavaSlot.h>

JNIEXPORT void JNICALL
Java_org_trinitydesktop_koala_TDEApplication_setJavaSlotFactory(JNIEnv* env, jclass cls)
{
	(void) env;
	(void) cls;
	JavaSlot::setJavaSlotFactory(new TDEJavaSlotFactory());
	return;
}
	
EOF
	
	$tdemainwindowExtras = <<EOF;	
	/**
 		List of members of TDEMainWindow class.
	*/
	public native ArrayList memberList();
	
	public static void RESTORE(String typeName) {
		Class	savedClass;
		
		try {
			savedClass = Class.forName(typeName);
			int n = 1;
			while (TDEMainWindow.canBeRestored(n)){
				((TDEMainWindow) savedClass.newInstance()).restore(n);
				n++;
			}
		} catch(Exception e) {
			return;
		}
		
		return;
	}
	
EOF
	
	$tdemainwindowjniExtras = <<EOF;
JNIEXPORT jobject JNICALL
Java_org_trinitydesktop_koala_TDEMainWindow_memberList(JNIEnv* env, jobject obj)
{
	return (jobject) KDESupport::arrayWithTDEMainWindowList(env, TDEMainWindow::memberList);
}

EOF
	
	$kcmdlineargsjniExtras = <<EOF;
JNIEXPORT void JNICALL
Java_org_trinitydesktop_koala_TDECmdLineArgs_init___3Ljava_lang_String_2Ljava_lang_String_2Ljava_lang_String_2Ljava_lang_String_2Ljava_lang_String_2(JNIEnv* env, jclass cls, jobjectArray args, jstring _appname, jstring programName, jstring _description, jstring _version)
{
	(void) cls;
static TQCString* _qstring__appname = 0;
static TQCString* _qstring_programName = 0;
static TQCString* _qstring__description = 0;
static TQCString* _qstring__version = 0;
	int argc = (int) env->GetArrayLength(args);
	TDECmdLineArgsJBridge::init((int) argc+1, (char**) QtSupport::toArgv(env, args), (const char*) QtSupport::toCharString(env, _appname, &_qstring__appname), (const char*) QtSupport::toCharString(env, programName, &_qstring_programName), (const char*) QtSupport::toCharString(env, _description, &_qstring__description), (const char*) QtSupport::toCharString(env, _version, &_qstring__version));
	return;
}

JNIEXPORT void JNICALL
Java_org_trinitydesktop_koala_TDECmdLineArgs_init___3Ljava_lang_String_2Ljava_lang_String_2Ljava_lang_String_2Ljava_lang_String_2Ljava_lang_String_2Z(JNIEnv* env, jclass cls, jobjectArray args, jstring _appname, jstring programName, jstring _description, jstring _version, jboolean noTDEApp)
{
	(void) cls;
static TQCString* _qstring__appname = 0;
static TQCString* _qstring_programName = 0;
static TQCString* _qstring__description = 0;
static TQCString* _qstring__version = 0;
	int argc = (int) env->GetArrayLength(args);
	TDECmdLineArgsJBridge::init(argc+1, (char**) QtSupport::toArgv(env, args), (const char*) QtSupport::toCharString(env, _appname, &_qstring__appname), (const char*) QtSupport::toCharString(env, programName, &_qstring_programName), (const char*) QtSupport::toCharString(env, _description, &_qstring__description), (const char*) QtSupport::toCharString(env, _version, &_qstring__version), (bool) noTDEApp);
	return;
}

JNIEXPORT void JNICALL
Java_org_trinitydesktop_koala_TDECmdLineArgs_init___3Ljava_lang_String_2Lorg_trinitydesktop_koala_TDEAboutData_2(JNIEnv* env, jclass cls, jobjectArray args, jobject about)
{
	(void) cls;
	int argc = (int) env->GetArrayLength(args);
	TDECmdLineArgsJBridge::init(argc+1, (char**) QtSupport::toArgv(env, args), (const TDEAboutData*) QtSupport::getQt(env, about));
	return;
}

JNIEXPORT void JNICALL
Java_org_trinitydesktop_koala_TDECmdLineArgs_init___3Ljava_lang_String_2Lorg_trinitydesktop_koala_TDEAboutData_2Z(JNIEnv* env, jclass cls, jobjectArray args, jobject about, jboolean noTDEApp)
{
	(void) cls;
	int argc = (int) env->GetArrayLength(args);
	TDECmdLineArgsJBridge::init(argc+1, (char**) QtSupport::toArgv(env, args), (const TDEAboutData*) QtSupport::getQt(env, about), (bool) noTDEApp);
	return;
}

EOF

	$schedulerjniExtras = <<EOF;
JNIEXPORT jboolean JNICALL
Java_org_trinitydesktop_koala_Scheduler_connect__Ljava_lang_String_2Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2(JNIEnv* env, jclass cls, jstring signal, jobject receiver, jstring member)
{
	(void) cls;
	JavaSlot *		javaSlot = QtSupport::slotForReceiver(env, receiver, member);
	TQString			qtSignalName(javaSlot->javaToQtSignalName(env, signal, 0));
	jboolean xret = (jboolean) SchedulerJBridge::connect((const char*) qtSignalName, (const TQObject*) javaSlot, javaSlot->javaToQtSlotName(env, member, qtSignalName));
	return xret;
}

JNIEXPORT jboolean JNICALL
Java_org_trinitydesktop_koala_Scheduler_connect__Lorg_trinitydesktop_qt_QObject_2Ljava_lang_String_2Ljava_lang_String_2(JNIEnv *env, jobject obj, jobject sender, jstring signal, jstring member)
{
	return QtSupport::connect(env, sender, signal, obj, member);
}

JNIEXPORT jboolean JNICALL
Java_org_trinitydesktop_koala_Scheduler_disconnect(JNIEnv *env, jclass cls, jobject sender, jstring signal, jobject receiver, jstring member)
{
	(void) cls;
	return QtSupport::disconnect(env, sender, signal, receiver, member);
}

EOF

}

sub javaImport($)
{
	my ( $classname ) = @_;
	my $classname_ptr = $classname . "*";
	if ( cplusplusToJava($classname_ptr) eq "" or $classname eq $main::globalSpaceClassName ) {
		return "";
	} elsif ( cplusplusToJava($classname_ptr) eq "ArrayList" ) {
		return "java.util.ArrayList";
	} elsif ( cplusplusToJava($classname_ptr) eq "Calendar" ) {
		return "java.util.Calendar";
	} elsif ( cplusplusToJava($classname_ptr) eq "StringBuffer" ) {
		return "";
	} elsif ( cplusplusToJava($classname_ptr) eq "String" ) {
		return "";
	} elsif ( cplusplusToJava($classname_ptr) eq "String[][]" ) {
		return "";
	} elsif ( cplusplusToJava($classname_ptr) eq "String[]" ) {
		return "";
	} elsif ( cplusplusToJava($classname_ptr) eq "Date" ) {
		return "java.util.Date";
	} elsif ( cplusplusToJava($classname_ptr) =~ /^[a-z]/ ) {
		return "";
	} elsif ( $classname =~ /^Q/ ) {
		return "org.trinitydesktop.qt." . $classname;
	} else {
		return "org.trinitydesktop.koala." . $classname;
	}
}
	
sub cplusplusToJava
{
	my ( $cplusplusType )  = @_;
	my $isConst = ($cplusplusType =~ /const / or $cplusplusType !~ /[*&]/ ? 1 : 0);
	$cplusplusType =~ s/const //;
	$cplusplusType =~ s/^signed//;
	my $className = $cplusplusType;
	$className =~ s/[*&]//;
	
	if ( $cplusplusType =~ /void\*|DCOPArg|DCOPRef|^MSG\s*\*|TQGfx|^Display\s*\*|TDEHTMLPart::PageSecurity|TQFileInfoList|TQValueList<TQIconDragItem>|TQValueList<TQCString>|TQValueList<TQVariant>|TQValueList<TQPixmap>|TQValueListConstIterator<TQString>|TQMap|EditMode|TQPtrList<TQPixmap>|TQPtrList<TQPoint>|TQTextFormat|TQTextCursor|TQTextDocument|TQNetworkProtocolFactoryBase|TQDomNodePrivate|TQSqlDriverCreatorBase|TQSqlFieldInfoList|TQObjectUserData|TQUObject|TQTextParag|TQWidgetMapper|TQMemArray<int>|TQBitArray|TQLayoutIterator|TQAuBucket|TQUnknownInterface|TQConnectionList/ ) {
		return ""; # Unsupported type
	} elsif ( $cplusplusType =~ /TQSignal\s*\*|TQMenuItem|TQWSEvent|TQWSDisplay|TQWSSocket|TQPaintDeviceX11Data|TQWindowsMime|TQDirectPainter|TQMember|TQDiskFont|TQGCache|TQRichText|TQWSDecoration/ && $main::qt_embedded ) {
		return ""; # Unsupported Qt/E type
	} elsif ( $cplusplusType =~ /bool/ && kalyptusDataDict::ctypemap($cplusplusType) eq "int" ) {
		return "boolean";
	} elsif ( $cplusplusType =~ /bool\s*[*&]/ ) {
		return "boolean[]";
	} elsif ( kalyptusDataDict::ctypemap($cplusplusType) =~ /^void\s*\*/ ) {
		return "int";
	} elsif ( kalyptusDataDict::ctypemap($cplusplusType) =~ /^\s*(unsigned )?int\s*\*/
				|| kalyptusDataDict::ctypemap($cplusplusType) =~ /^qt_QIntValueList\*/
				|| $cplusplusType =~ /^int[*&]$/ )
	{
		return "int[]";
	} elsif ( kalyptusDataDict::ctypemap($cplusplusType) =~ /^\s*double\s*\*/ ) {
		return "double[]";
	} elsif ( kalyptusDataDict::ctypemap($cplusplusType) =~ /^\s*(unsigned )?short\s*\*/ ) {
		return "short[]";
	} elsif ( $cplusplusType =~ /TDECmdLineOptions/ ) {
		return "String[][]";	
	} elsif ( $cplusplusType =~ /char\s*\*\*/ || $cplusplusType =~ /TQStringList/|| $cplusplusType =~ /TQStrList/) {
		return "String[]";
	} elsif ( 	kalyptusDataDict::ctypemap($cplusplusType) =~ /qt_QUrlInfoValueList\s*\*/
				|| kalyptusDataDict::ctypemap($cplusplusType) =~ /qt_QVariantValueList\s*\*/
				|| kalyptusDataDict::ctypemap($cplusplusType) =~ /qt_QIconDragItemValueList\s*\*/
				|| kalyptusDataDict::ctypemap($cplusplusType) =~ /qt_QPixmapValueList\s*\*/
				|| kalyptusDataDict::ctypemap($cplusplusType) =~ /tde_QCStringList\s*\*/
				|| kalyptusDataDict::ctypemap($cplusplusType) =~ /qt_QObjectList\s*\*/
				|| kalyptusDataDict::ctypemap($cplusplusType) =~ /qt_QDomNodeList\s*\*/
				|| kalyptusDataDict::ctypemap($cplusplusType) =~ /qt_QWidgetList\s*\*/
				|| kalyptusDataDict::ctypemap($cplusplusType) =~ /tde_KURLList\s*\*/
				|| kalyptusDataDict::ctypemap($cplusplusType) =~ /tde_TDEMainWindow\s*\*/
				|| kalyptusDataDict::ctypemap($cplusplusType) =~ /tde_KFileItemList\s*\*/
				|| kalyptusDataDict::ctypemap($cplusplusType) =~ /tde_KFileViewItemList\s*\*/
				|| kalyptusDataDict::ctypemap($cplusplusType) =~ /tde_DOMNodeList\s*\*/
				|| kalyptusDataDict::ctypemap($cplusplusType) =~ /tde_StyleSheetList\s*\*/
				|| kalyptusDataDict::ctypemap($cplusplusType) =~ /tde_MediaList\s*\*/
				|| kalyptusDataDict::ctypemap($cplusplusType) =~ /tde_OfferList\s*\*/
				|| $cplusplusType =~ /TQMemArray<TQRect>/
				|| kalyptusDataDict::ctypemap($cplusplusType) =~ /qt_QCanvasItemList\s*\*/ ) {
		return "ArrayList"
	} elsif ( $cplusplusType =~ /uchar\s*\*/ ) {
		return "char[]";
	} elsif ( $cplusplusType =~ /QC?String/ and !$isConst ) {
		return "StringBuffer"
	} elsif ( $cplusplusType =~ /(DOM::)?DOMString/ || $cplusplusType =~ /TQString/ || $cplusplusType =~ /TQCString/ || kalyptusDataDict::ctypemap($cplusplusType) =~ /^(const )?char\s*\*/ ) {
		return "String"
	} elsif ( $cplusplusType =~ /TQChar\s*[&\*]?/ || $cplusplusType =~ /^char$/ ) {
		return "char"
	} elsif ( kalyptusDataDict::ctypemap($cplusplusType) =~ /qt_QTime\s*\*/ ) {
		return "Date"
	} elsif ( kalyptusDataDict::ctypemap($cplusplusType) =~ /qt_QDateTime\s*\*/ || kalyptusDataDict::ctypemap($cplusplusType) =~ /qt_QDate\s*\*/ ) {
		return "Calendar"
	} elsif ( $cplusplusType =~ /TQPaintDevice/ ) {
		return "TQPaintDeviceInterface"
	} elsif ( $cplusplusType =~ /TQByteArray/ ) {
		return "byte[]"
	} elsif ( kalyptusDataDict::ctypemap($cplusplusType) =~ /qt_([^\*\s]*)(.*)$/ and !$skippedClasses{$className}) {
		if ( kalyptusDataDict::interfacemap($1) ne () ) {
			return $1."Interface";
        } else {
			return $1;
		}
	} elsif ( kalyptusDataDict::ctypemap($cplusplusType) =~ /tde_([^\*\s]*)(.*)$/ and !$skippedClasses{$className}) {
		if ( kalyptusDataDict::interfacemap($1) ne () ) {
			return $1."Interface";
        } else {
			return $1;
		}
	} elsif ( kalyptusDataDict::ctypemap($cplusplusType) =~ /unsigned char/ ) {
		return "short";
	} elsif ( $typedeflist{$cplusplusType} =~ /ulong|long/ ) {
		return "long";
	} elsif ( $typedeflist{$cplusplusType} =~ /uint|int/ or $cplusplusType =~ /^int\&$/ ) {
		return "int";
	} elsif ( $typedeflist{$cplusplusType} =~ /ushort|short/ ) {
		return "short";
	} elsif ( kalyptusDataDict::ctypemap($cplusplusType) =~ /(unsigned )(.*)/ ) {
		return $2;
	} else {
		my $node;
		my $item;
		if ($className =~ /^(\w+)::(\w+)$/) {
			$node = kdocAstUtil::findRef( $rootnode, $1 );
			$item = kdocAstUtil::findRef( $node, $2 ) if defined $node;
			if (defined $item && $item->{NodeType} eq 'enum') {
				return "int";
			} elsif (defined $item && ($item->{NodeType} eq 'class' || $item->{NodeType} eq 'struct')) {
				return $skippedClasses{$className} ? "" : $2;
			}
		}

		if ($className =~ /^\w+$/) {
			$item = kdocAstUtil::findRef( $rootnode, $className );
			if (defined $item && ($item->{NodeType} eq 'class' || $item->{NodeType} eq 'struct')) {
				return $skippedClasses{$className} ? "" : $className;
			}
		}
		return kalyptusDataDict::ctypemap($cplusplusType);
	}

}

sub cplusplusToJNI
{
	my ( $cplusplusType )  = @_;
	my $javaType = cplusplusToJava( $cplusplusType );
	
	if ( $cplusplusType =~ /void/ ) {
		return "void"
	} elsif ( $javaType =~ /^Calendar$/ ) {
		return "jobject"
	} elsif ( $javaType =~ /^Date$/ ) {
		return "jobject"
	} elsif ( 	$javaType =~ /ArrayList/ ) {
		return "jobjectArray"
	} elsif ( $javaType =~ /String\[\]\[\]/ ) {
		return "jobjectArray";
	} elsif ( $javaType =~ /String\[\]/ ) {
		return "jobjectArray";
	} elsif ( $javaType =~ /StringBuffer/ ) {
		return "jobject";
	} elsif ( $javaType =~ /^String$/ ) {
		return "jstring";
	} elsif ( $javaType =~ /boolean\[\]/ ) {
		return "jbooleanArray";
	} elsif ( $javaType =~ /char\[\]/ ) {
		return "jcharArray";
	} elsif ( $javaType =~ /byte\[\]/ ) {
		return "jbyteArray";
	} elsif ( $javaType =~ /short\[\]/ ) {
		return "jshortArray";
	} elsif ( $javaType =~ /int\[\]/ ) {
		return "jintArray";
	} elsif ( $javaType =~ /double\[\]/ ) {
		return "jdoubleArray";
	} elsif ( $javaType =~ /^Q/ ) {
		return "jobject";
	} elsif ( $javaType =~ /^[A-Z]/ ) {
		return "jobject";
	} elsif ( $javaType =~ /^boolean\s*/ ) {
		return "jboolean";
	} elsif ( $javaType =~ /^byte\s*/ ) {
		return "jbyte";
	} elsif ( $javaType =~ /^char\s*/ ) {
		return "jchar";
	} elsif ( $javaType =~ /^short\s*/ ) {
		return "jshort";
	} elsif ( $javaType =~ /^int\s*/ ) {
		return "jint";
	} elsif ( $javaType =~ /^long\s*/ ) {
		return "jlong";
	} elsif ( $javaType =~ /^float\s*/ ) {
		return "jfloat";
	} elsif ( $javaType =~ /^double\s*/ ) {
		return "jdouble";
	} else {
		return "";
	}

}

sub cplusplusToJNISignature
{
	my ( $cplusplusType )  = @_;
	my $javaType = cplusplusToJava( $cplusplusType );
	
	if ( $javaType =~ /^Calendar$/ ) {
		return "Ljava_util_Calendar_2"
	} elsif ( $javaType eq 'Date' ) {
		return "Ljava_util_Date_2"
	} elsif ( 	$javaType =~ /ArrayList/ ) {
		return "Ljava_util_ArrayList_2"
	} elsif ( $javaType =~ /String\[\]\[\]/ ) {
		return "_3_3Ljava_lang_String_2";
	} elsif ( $javaType =~ /String\[\]/ ) {
		return "_3Ljava_lang_String_2";
	} elsif ( $javaType =~ /StringBuffer/ ) {
		return "Ljava_lang_StringBuffer_2";
	} elsif ( $javaType eq 'String' ) {
		return "Ljava_lang_String_2";
	} elsif ( $javaType =~ /boolean\[\]/ ) {
		return "_3Z";
	} elsif ( $javaType =~ /char\[\]/ ) {
		return "_3C";
	} elsif ( $javaType =~ /byte\[\]/ ) {
		return "_3B";
	} elsif ( $javaType =~ /short\[\]/ ) {
		return "_3S";
	} elsif ( $javaType =~ /int\[\]/ ) {
		return "_3I";
	} elsif ( $javaType =~ /double\[\]/ ) {
		return "_3D";
	} elsif ( $javaType =~ /^Q/ ) {
		return "Lorg_trinitydesktop_qt_$javaType"."_2";
	} elsif ( $javaType =~ /^[A-Z]/ ) {
		return "Lorg_trinitydesktop_koala_$javaType"."_2";
	} elsif ( $javaType =~ /^boolean\s*/ ) {
		return "Z";
	} elsif ( $javaType =~ /^byte\s*/ ) {
		return "B";
	} elsif ( $javaType =~ /^char\s*/ ) {
		return "C";
	} elsif ( $javaType =~ /^short\s*/ ) {
		return "S";
	} elsif ( $javaType =~ /^int\s*/ ) {
		return "I";
	} elsif ( $javaType =~ /^long\s*/ ) {
		return "J";
	} elsif ( $javaType =~ /^float\s*/ ) {
		return "F";
	} elsif ( $javaType =~ /^double\s*/ ) {
		return "D";
	} else {
		return "";
	}

}

sub jniArgTocplusplus
{
	my ( $cplusplusType, $argName )  = @_;
	my $jniLocal = ''; # output
	my $jniArg = ''; # output
	my $jniCleanup = ''; # output
	
	my $javaType = cplusplusToJava( $cplusplusType );
	my $jniType = cplusplusToJNI( $cplusplusType );
 	
	if ( $javaType =~ /^Calendar$/ ) {
		my $dateclass = $cplusplusType =~ /TQDateTime/ ? "TQDateTime" : "TQDate";
		$jniLocal = "static $dateclass* _qdate_$argName = 0;\n";
		if ( $cplusplusType =~ /[\*]/ ) {
			$jniArg = "($cplusplusType) QtSupport::to$dateclass(env, $argName, &_qdate_$argName)";
		} else {
			$jniArg = "($cplusplusType)*($dateclass*) QtSupport::to$dateclass(env, $argName, &_qdate_$argName)";
		}
	} elsif ( $javaType =~ /^Date$/ ) {
		$jniLocal = "static TQTime* _qtime_$argName = 0;\n";
		if ( $cplusplusType =~ /[\*]/ ) {
			$jniArg = "($cplusplusType) QtSupport::toTQTime(env, $argName, &_qtime_$argName)";
		} else {
			$jniArg = "($cplusplusType)*(TQTime*) QtSupport::toTQTime(env, $argName, &_qtime_$argName)";
		}
	} elsif ( 	$javaType =~ /ArrayList/ ) {
		if ( $cplusplusType =~ /KFileItemList/ ) {
			$jniLocal ="static KFileItemList* _qlist_$argName = 0;\n";
			if ( $cplusplusType =~ /[\*]/ ) {
				$jniArg = "($cplusplusType) KDESupport::toKFileItemList(env, $argName, &_qlist_$argName)";
			} else {
				$jniArg = "($cplusplusType)*(TQStrList*) KDESupport::toKFileItemList(env, $argName, &_qlist_$argName)";
			}
		} elsif ( $cplusplusType =~ /QCStringList/ ) {
			$jniLocal ="static QCStringList* _qlist_$argName = 0;\n";
			if ( $cplusplusType =~ /[\*]/ ) {
				$jniArg = "($cplusplusType) KDESupport::toQCStringList(env, $argName, &_qlist_$argName)";
			} else {
				$jniArg = "($cplusplusType)*(QCStringList*) KDESupport::toQCStringList(env, $argName, &_qlist_$argName)";
			}
		} elsif ( $cplusplusType =~ /KURL::List/ ) {
			$jniLocal ="static KURL::List* _qlist_$argName = 0;\n";
			if ( $cplusplusType =~ /[\*]/ ) {
				$jniArg = "($cplusplusType) KDESupport::toKURLList(env, $argName, &_qlist_$argName)";
			} else {
				$jniArg = "($cplusplusType)*(KURL::List*) KDESupport::toKURLList(env, $argName, &_qlist_$argName)";
			}
		}
	} elsif ( $javaType =~ /String\[\]\[\]/ ) {
		if ( $cplusplusType =~ /TDECmdLineOptions/ ) {
			$jniArg = "(TDECmdLineOptions*) KDESupport::toTDECmdLineOptions(env, $argName)";
		}
	} elsif ( $javaType =~ /String\[\]/ ) {
		if ( $cplusplusType =~ /TQStringList/ ) {
			$jniLocal ="static TQStringList* _qlist_$argName = 0;\n";
			if ( $cplusplusType =~ /[\*]/ ) {
				$jniArg = "($cplusplusType) QtSupport::toTQStringList(env, $argName, &_qlist_$argName)";
			} else {
				$jniArg = "($cplusplusType)*(TQStringList*) QtSupport::toTQStringList(env, $argName, &_qlist_$argName)";
			}
		} elsif ( $cplusplusType =~ /TQStrList/ ) {
			$jniLocal ="static TQStrList* _qlist_$argName = 0;\n";
			if ( $cplusplusType =~ /[\*]/ ) {
				$jniArg = "($cplusplusType) QtSupport::toTQStrList(env, $argName, &_qlist_$argName)";
			} else {
				$jniArg = "($cplusplusType)*(TQStrList*) QtSupport::toTQStrList(env, $argName, &_qlist_$argName)";
			}
		} elsif ( $cplusplusType =~ /char\s*\*\*/ ) {
			$jniArg = "($cplusplusType) QtSupport::toStringArray(env, $argName)";
		}
	} elsif ( $javaType =~ /StringBuffer/ ) {
		if ( $cplusplusType =~ /TQCString/ ) {
			$jniLocal = "static TQCString* _qcstring_$argName = 0;\n";
			$jniLocal .= "\tif (_qcstring_$argName == 0) {\n";
			$jniLocal .= "\t\t_qcstring_$argName = new TQCString();\n";
			$jniLocal .= "\t}\n";
			if ( $cplusplusType =~ /[\*]/ ) {
				$jniArg = "($cplusplusType) _qcstring_$argName";
			} else {
				$jniArg = "($cplusplusType)*(TQCString*) _qcstring_$argName";
			}
			$jniCleanup = "\tQtSupport::fromTQCStringToStringBuffer(env, _qcstring_$argName, $argName);\n";
		} else {
			$jniLocal ="static TQString* _qstring_$argName = 0;\n";
			if ( $cplusplusType =~ /[\*]/ ) {
				$jniArg = "($cplusplusType) QtSupport::toTQStringFromStringBuffer(env, $argName, &_qstring_$argName)";
			} else {
				$jniArg = "($cplusplusType)*(TQString*) QtSupport::toTQStringFromStringBuffer(env, $argName, &_qstring_$argName)";
			}
			$jniCleanup = "\tQtSupport::fromTQStringToStringBuffer(env, _qstring_$argName, $argName);\n";
		}
	} elsif ( $javaType =~ /^String$/ ) {
		if ( $cplusplusType =~ /TQString/ ) {
			$jniLocal ="static TQString* _qstring_$argName = 0;\n";
			if ( $cplusplusType =~ /[\*]/ ) {
				$jniArg = "($cplusplusType) QtSupport::toTQString(env, $argName, &_qstring_$argName)";
			} else {
				$jniArg = "($cplusplusType)*(TQString*) QtSupport::toTQString(env, $argName, &_qstring_$argName)";
			}
		} elsif ( $cplusplusType =~ /TQCString/ ) {
			$jniLocal ="static TQCString* _qcstring_$argName = 0;\n";
			if ( $cplusplusType =~ /[\*]/ ) {
				$jniArg = "($cplusplusType) QtSupport::toTQCString(env, $argName, &_qcstring_$argName)";
			} else {
				$jniArg = "($cplusplusType)*(TQCString*) QtSupport::toTQCString(env, $argName, &_qcstring_$argName)";
			}
		} elsif ( $cplusplusType =~ /DOMString/ ) {
			$jniLocal ="static DOM::DOMString* _domstring_$argName = 0;\n";
			if ( $cplusplusType =~ /[\*]/ ) {
				$jniArg = "(DOM::DOMString*) KDESupport::toDOMString(env, $argName, &_domstring_$argName)";
			} else {
				$jniArg = "(DOM::DOMString)*(DOM::DOMString*) KDESupport::toDOMString(env, $argName, &_domstring_$argName)";
			}
		} else {
			$jniLocal ="static TQCString* _qstring_$argName = 0;\n";
			$jniArg = "($cplusplusType) ". ($cplusplusType =~ /[\&]/ ? "*(char*)" : "") . "QtSupport::toCharString(env, $argName, &_qstring_$argName)";
		}	
	} elsif ( $javaType =~ /boolean\[\]/ ) {
		$jniLocal ="\tbool* _bool_$argName = QtSupport::toBooleanPtr(env, $argName);\n";
		$jniArg = " ($cplusplusType) " . ($cplusplusType =~ /[\*]/ ? "" : "*") . "_bool_$argName";
		$jniCleanup = "\tenv->SetBooleanArrayRegion($argName, 0, 1, (jboolean*) _bool_$argName);\n";
	} elsif ( $javaType =~ /char\[\]/ ) {
		$jniLocal ="static TQByteArray* _qbytearray_$argName = 0;\n";
		$jniArg = "($cplusplusType) QtSupport::toUcharArray(env, $argName, &_qbytearray_$argName)";
	} elsif ( $javaType =~ /byte\[\]/ ) {
		$jniLocal = "static TQByteArray* _qbyteArray_$argName = 0;\n";
		if ( $cplusplusType =~ /[\*]/ ) {
			$jniArg = "($cplusplusType) QtSupport::toTQByteArray(env, $argName, &_qbyteArray_$argName)";
		} else {
			$jniArg = "($cplusplusType)*(TQByteArray*) QtSupport::toTQByteArray(env, $argName, &_qbyteArray_$argName)";
		}
	} elsif ( $javaType =~ /short\[\]/ ) {
		$jniLocal ="\tshort* _short_$argName = QtSupport::toShortPtr(env, $argName);\n";
		$jniArg = " ($cplusplusType) " . ($cplusplusType =~ /[\*]/ ? "" : "*") . "_short_$argName";
		$jniCleanup = "\tenv->SetShortArrayRegion($argName, 0, 1, (jshort*) _short_$argName);\n";
	} elsif ( $javaType =~ /int\[\]/ ) {
		if ( $cplusplusType =~ /TQValueList/ ) {
			$jniLocal = "static TQValueList<int>* _qlist_$argName = 0;\n";
			$jniArg = "($cplusplusType) QtSupport::toTQIntValueList(env, $argName, &_qlist_$argName)";
		} else {
			$jniLocal ="\tint* _int_$argName = QtSupport::toIntPtr(env, $argName);\n";
			$jniArg = " ($cplusplusType) " . ($cplusplusType =~ /[\*]/ ? "" : "*") . "_int_$argName";
			$jniCleanup = "\tenv->SetIntArrayRegion($argName, 0, 1, (jint *) _int_$argName);\n";
		}
	} elsif ( $javaType =~ /double\[\]/ ) {
		$jniLocal ="\tdouble* _double_$argName = QtSupport::toDoublePtr(env, $argName);\n";
		$jniArg = " ($cplusplusType) " . ($cplusplusType =~ /[\*]/ ? "" : "*") . "_double_$argName";
		$jniCleanup = "\tenv->SetDoubleArrayRegion($argName, 0, 1, (jdouble*) _double_$argName);\n";
	} elsif ( $javaType =~ /^TQPaintDeviceInterface$/ ) {
		$jniArg = "($cplusplusType) QtSupport::paintDevice(env, $argName)";
	} elsif ( $javaType =~ /^TQMimeSourceInterface$/ ) {
		$jniArg = "($cplusplusType) QtSupport::mimeSource(env, $argName)";
	} elsif ( $javaType =~ /^[A-Z]/ ) {
		( my $className = $cplusplusType ) =~ s/[&*]//g;
		$jniArg = (($cplusplusType !~ /[\*]/ or $cplusplusType =~ /\*\&/) ? "($cplusplusType)*" : "") . "($className*) QtSupport::getQt(env, $argName)";
	} elsif ( $javaType =~ /^boolean\s*/ ) {
		$jniArg = "($cplusplusType) $argName";
	} elsif ( $javaType =~ /^byte\s*/ ) {
		$jniArg = "($cplusplusType) $argName";
	} elsif	( $javaType =~ /^char\s*/ ) {	
		if ( $cplusplusType =~ /TQChar/ ) {
			$jniLocal = "static TQChar* _qchar_$argName = 0;\n";
			if ( $cplusplusType =~ /[\*]/ ) {
				$jniArg = "($cplusplusType) QtSupport::toTQChar(env, $argName, &_qchar_$argName)";
			} else {
				$jniArg = "($cplusplusType)*(TQChar*) QtSupport::toTQChar(env, $argName, &_qchar_$argName)";
			}
		} else {
			$jniArg = "($cplusplusType) $argName";
		}
	} elsif ( $javaType =~ /^short\s*/ ) {
		$jniArg = "($cplusplusType) $argName";
	} elsif ( $javaType =~ /^int\s*/ ) {
		$jniArg = "($cplusplusType) $argName";
	} elsif ( $javaType =~ /^long\s*/ ) {
		$jniArg = "($cplusplusType) $argName";
	} elsif ( $javaType =~ /^float\s*/ ) {
		$jniArg = "($cplusplusType) $argName";
	} elsif ( $javaType =~ /^double\s*/ ) {
		$jniArg = "($cplusplusType) $argName";
	} else {
		;
	}
	
	return ($jniLocal, $jniArg, $jniCleanup);
}

sub jniToReturnValue($$$)
{
	my ( $cplusplusType, $functionCall, $jniCleanups )  = @_;
	my $jniLocal = ''; # output
	my $returnCall = ''; # output
	
	my $javaType = cplusplusToJava( $cplusplusType );
	my $const = ($cplusplusType =~ /const / ? "const " : "");
	
	if ( $cplusplusType =~ /void/ ) {
		$returnCall = "\t$functionCall;\n\treturn;\n";
		$returnCall = "\t$functionCall;\n$jniCleanups\treturn;\n";
	} elsif ( $javaType =~ /^Calendar$/ ) {
		$cplusplusType =~ /(TQDateTime|TQDate)\s*(\*)?&?\s*$/;
		$jniLocal = "\t$1 $2 _qdate;\n";
		$returnCall = "\t_qdate = $functionCall;\n$jniCleanups";
		$returnCall .= "\treturn (jobject) QtSupport::from$1(env, ($1*) " . ($2 eq "\*" ? "" : "&") . "_qdate);\n";
	} elsif ( $javaType =~ /^Date$/ ) {
		$cplusplusType =~ /(TQTime)\s*(\*)?&?\s*$/;
		$jniLocal = "\t$1 $2 _qtime;\n";
		$returnCall = "\t_qtime = $functionCall;\n$jniCleanups";
		$returnCall .= "\treturn (jobject) QtSupport::fromTQTime(env, ($1*) " . ($2 eq "\*" ? "" : "&") . "_qtime);\n";
	} elsif ( 	$javaType =~ /ArrayList/ || $javaType =~ /String\[\]/ ) {
		if ( $cplusplusType !~ /\*/ ) {
			$const = "";
		}
		$cplusplusType =~ /(const )?([^\&]*)(\*)?&?/;
		$jniLocal = "\t$const$2 $3 _qlist;\n";
		$returnCall = "\t_qlist = $functionCall;\n$jniCleanups";
		if ( $cplusplusType =~ /(TQStrList|TQStringList|TQCanvasItemList|TQWidgetList|TQDomNodeList|TQObjectList)\s*([\*\&])?\s*$/ ) {
			$returnCall .= "\treturn (jobject) QtSupport::arrayWith$1(env, ($1*) " . ($2 eq "\*" ? "" : "&") . "_qlist);\n";
		} elsif ( $cplusplusType =~ /DOM::(NodeList|StyleSheetList|MediaList)\s*([\*\&])?\s*$/ ) {
			$returnCall .= "\treturn (jobject) KDESupport::arrayWith$1(env, (DOM::$1 *) " . ($2 eq "\*" ? "" : "&") . "_qlist);\n";
		} elsif ( $cplusplusType =~ /(QCStringList|KFileItemList|KFileViewItemList)\s*([\*\&])?\s*$/ ) {
			$returnCall .= "\treturn (jobject) KDESupport::arrayWith$1(env, ($1*) " . ($2 eq "\*" ? "" : "&") . "_qlist);\n";
		} elsif ( $cplusplusType =~ /(TDETrader::OfferList)\s*([\*\&])?\s*$/ ) {
			$returnCall .= "\treturn (jobject) KDESupport::arrayWithOfferList(env, ($1*) " . ($2 eq "\*" ? "" : "&") . "_qlist);\n";
		} elsif ( $cplusplusType =~ /(KURL::List)\s*([\*\&])?\s*$/ ) {
			$returnCall .= "\treturn (jobject) KDESupport::arrayWithKURLList(env, ($1*) " . ($2 eq "\*" ? "" : "&") . "_qlist);\n";
		} elsif ( $cplusplusType =~ /TQValueList<TQIconDragItem>\s*([\*\&])?\s*$/ ) {
			$returnCall .= "\treturn (jobject) QtSupport::arrayWithTQIconDragItemList(env, (TQValueList<TQIconDragItem>*) " . ($1 eq "\*" ? "" : "&") . "_qlist);\n";
		} elsif ( $cplusplusType =~ /TQMemArray<TQRect>\s*([\*\&])?\s*$/ ) {
			$returnCall .= "\treturn (jobject) QtSupport::arrayWithTQRectList(env, (TQMemArray<TQRect>*) " . ($1 eq "\*" ? "" : "&") . "_qlist);\n";
		}	
	} elsif ( $javaType =~ /String\[\]/ ) {
		; # Do nothing, string arrays are ArrayLists as return values
	} elsif ( $javaType =~ /String/ || $javaType =~ /StringBuffer/ ) {
		if ( $cplusplusType =~ /TQString(\s*\*)?/ ) {
			$jniLocal = "\tTQString $1 _qstring;\n";
			$returnCall = "\t_qstring = $functionCall;\n$jniCleanups";
			$returnCall .= "\treturn QtSupport::fromTQString(env, " . ($cplusplusType =~ /\*/ ? "" : "&") . "_qstring);\n";
		} elsif ($cplusplusType =~ /TQCString(\s*\*)?/) {
			$jniLocal = "\tTQCString $1 _qstring;\n";
			$returnCall = "\t_qstring = $functionCall;\n$jniCleanups";
			$returnCall .= "\treturn QtSupport::fromTQCString(env, " . ($cplusplusType =~ /\*/ ? "" : "&") . "_qstring);\n";
		} elsif ($cplusplusType =~ /DOM::DOMString(\s*\*)?/) {
			$jniLocal = "\tDOM::DOMString $1 _qstring;\n";
			$returnCall = "\t_qstring = $functionCall;\n$jniCleanups";
			$returnCall .= "\treturn KDESupport::fromDOMString(env, " . ($cplusplusType =~ /\*/ ? "" : "&") . "_qstring);\n";
		} else {
			$jniLocal = "\t$cplusplusType _qstring;\n";
			$returnCall = "\t_qstring = $functionCall;\n$jniCleanups";
			$returnCall .= "\treturn QtSupport::fromCharString(env, (char *) _qstring);\n";
		}
	} elsif ( $javaType =~ /boolean\[\]/ ) {
		;
	} elsif ( $cplusplusType =~ /uchar\s*\*/ ) {
		;
	} elsif ( $javaType =~ /char\[\]/ ) {
		;
	} elsif ( $javaType =~ /byte\[\]/ ) {
		$jniLocal = "\tTQByteArray " . ($cplusplusType =~ /\*/ ? "*" : "") . "_qbyteArray;\n";
		$returnCall = "\t_qbyteArray = $functionCall;\n$jniCleanups";
		$returnCall .= "\treturn QtSupport::fromTQByteArray(env, " . ($cplusplusType =~ /\*/ ? "" : "&") . "_qbyteArray);\n";
	} elsif ( $javaType =~ /short\[\]/ ) {
		;
	} elsif ( $javaType =~ /int\[\]/ && $cplusplusType !~ /\&/ ) {
		if ( $cplusplusType =~ /(int\*|TQRgb\*)/ ) {
			$jniLocal = "\t$1 _qint;\n";
			$returnCall = "\t_qint = $functionCall;\n$jniCleanups";
			$returnCall .= "\treturn QtSupport::fromIntPtr(env, (int*)_qint);\n";
		} else {
			$jniLocal = "\tTQValueList<int> _qintArray;\n";
			$returnCall = "\t_qintArray = $functionCall;\n$jniCleanups";
			$returnCall .= "\treturn QtSupport::fromTQIntValueList(env, &_qintArray);\n";
		}
	} elsif ( $javaType =~ /double\[\]/ ) {
		;
	} elsif ( $javaType =~ /^[A-Z]/ ) {
		my $className = $cplusplusType;
		$className =~ s/[\*\&]|const //g;
		$returnCall = "\tjobject xret = QtSupport::objectForQtKey(env, (void*)";
		my $fullyQualifiedReturnType = ($javaType =~ /^Q/ ? "org.trinitydesktop.qt.$javaType" : "org.trinitydesktop.koala.$javaType");
		if ($cplusplusType =~ /\*/) {
			$returnCall .= "$functionCall, \"$fullyQualifiedReturnType\");\n";
		} elsif ($cplusplusType =~ /\&/) {
			$returnCall .= "($className *) &$functionCall, \"$fullyQualifiedReturnType\");\n";
		} else {
			$returnCall .= "new $className($functionCall), \"$fullyQualifiedReturnType\", TRUE);\n";
		}
		$returnCall .= "$jniCleanups\treturn xret;\n";
	} elsif ( $javaType =~ /^char\s*/ ) {
		if ( $cplusplusType =~ /(TQChar)(\s*\*)?\s*$/ ) {
			$jniLocal = "\t$const$1 $2 _qchar;\n";
			$returnCall = "\t_qchar = $functionCall;\n$jniCleanups";
			$returnCall .= "\treturn (jchar) QtSupport::fromTQChar(env, (TQChar*) " . ($cplusplusType =~ /\*/ ? "" : "&") . "_qchar);\n";
		} else {
			$returnCall = "\tjchar xret = (jchar) $functionCall;\n$jniCleanups";
			$returnCall .= "\treturn xret;\n";
		}
	} elsif ( $javaType =~ /int\[\]/ && $cplusplusType =~ /\&/ ) {
		$returnCall = "\tjint xret = (jint) $functionCall;\n$jniCleanups";
		$returnCall .= "\treturn xret;\n";
	} elsif ( $javaType =~ /(^boolean|^byte|^short|^int|^long|^float|^double)/ ) {
		$returnCall = "\tj$1 xret = (j$1) $functionCall;\n$jniCleanups";
		$returnCall .= "\treturn xret;\n";
	}
		
	return ($jniLocal, $returnCall);
}

sub writeDoc
{
	( $libname, $rootnode, $outputdir, $opt ) = @_;

	print STDERR "Starting writeDoc for $libname...\n";

	$debug = $main::debuggen;

	mkpath( $outputdir ) unless -f $outputdir;

	# Define TQPtrCollection::Item, for resolveType
	unless ( kdocAstUtil::findRef( $rootnode, "TQPtrCollection::Item" ) ) {
		my $cNode = kdocAstUtil::findRef( $rootnode, "TQPtrCollection" );
		warn "TQPtrCollection not found" if (!$cNode);
		my $node = Ast::New( 'Item' );
		$node->AddProp( "NodeType", "Forward" );
		$node->AddProp( "Source", $cNode->{Source} ) if ($cNode);
		kdocAstUtil::attachChild( $cNode, $node ) if ($cNode);
		$node->AddProp( "Access", "public" );
	}

	print STDERR "Preparsing...\n";

	# Preparse everything, to prepare some additional data in the classes and methods
	Iter::LocalCompounds( $rootnode, sub { preParseClass( shift ); } );

	# Have a look at each class again, to propagate CanBeCopied
	Iter::LocalCompounds( $rootnode, sub { propagateCanBeCopied( shift ); } );

	# Write out smokedata.cpp
	writeSmokeDataFile($rootnode);

	print STDERR "Writing *.java...\n";

	# Generate *java file for each class
	Iter::LocalCompounds( $rootnode, sub { writeClassDoc( shift ); } );

	print STDERR "Done.\n";
}

=head2 preParseClass
	Called for each class
=cut
sub preParseClass
{
	my( $classNode ) = @_;
	my $className = join( "::", kdocAstUtil::heritage($classNode) );

	if( $#{$classNode->{Kids}} < 0 ||
	    $classNode->{Access} eq "private" ||
	    $classNode->{Access} eq "protected" || # e.g. TQPixmap::TQPixmapData
	    exists $classNode->{Tmpl} ||
	    # Don't generate standard bindings for TQString, this class is handled as a native type
	    $className eq 'TQString' ||
	    $className eq 'TQConstString' ||
	    $className eq 'TQCString' ||
	    # Don't map classes which are really arrays
	    $className eq 'TQStringList' ||
            $className eq 'TQCanvasItemList' ||
            $className eq 'TQWidgetList' ||
            $className eq 'TQObjectList' ||
	    $className eq 'TQStrList' ||
	    # Those are template related
        $className eq 'TQTSManip' || # cause compiler errors with several gcc versions
	    $className eq 'TQIconFactory' ||
	    $className eq 'TQGDict' ||
	    $className eq 'TQGList' ||
	    $className eq 'TQGVector' ||
	    $className eq 'TQStrIList' ||
	    $className eq 'TQStrIVec' ||
	    $className eq 'TQByteArray' ||
	    $className eq 'TQBitArray' ||
	    $className eq 'TQWExtra' ||
	    $className eq 'TQTLWExtra' ||
	    $className eq 'TQMetaEnum::Item' ||
	    $className eq 'TQWidgetContainerPlugin' ||
	    $className eq 'TQGArray::array_data' ||
	    $className eq 'KBookmarkMenu::DynMenuInfo' ||
	    $className eq 'TDECompletionMatches' ||
	    $className eq 'KDEDesktopMimeType::Service' ||
	    $className eq 'TDEGlobalSettings::KMouseSettings' ||
	    $className eq 'KMimeType::Format' ||
	    $className eq 'KNotifyClient::Instance' ||
	    $className eq 'KParts::Plugin::PluginInfo' ||
	    $className eq 'KProtocolInfo::ExtraField' ||
	    $className eq 'KXMLGUIClient::StateChange' ||
	    $className eq 'TDEIconTheme' ||
	    $className eq 'KEditListBox::CustomEditor' ||
		$className eq 'TDEIO::KBookmarkMenuNSImporter' ||
	    $className eq 'KPerDomainSettings' ||
	    $className eq 'TDEApplicationPropsPlugin' ||
	    $className eq 'KPrinter' ||
	    $className eq 'KPty' ||
	    $className eq 'KOpenWithHandler' ||
	    $className eq 'KFileOpenWithHandler' ||
	    $className eq 'KBindingPropsPlugin' ||
	    $className eq 'KPropsDlgPlugin' ||
	    $className eq 'KFileSharePropsPlugin' ||
	    $className eq 'KBookmarkMenuNSImporter' ||
	    $className eq 'KDevicePropsPlugin' ||
	    $className eq 'KWin::WindowInfo' ||
	    $className eq 'KDEDModule' ||
	    $className eq 'KFileMetaInfoProvider' ||
	    $className eq 'KFileMimeTypeInfo' ||
	    $className eq 'KExecPropsPlugin' ||
	    $className eq 'KFilePermissionsPropsPlugin' ||
	    $className eq 'KImageFilePreview' ||
	    $className eq 'KBookmarkManager' ||
	    $className eq 'KBookmarkNotifier' ||
	    $className eq 'KOCRDialogFactory' ||
	    $className eq 'KExtendedBookmarkOwner' ||
	    $className eq 'TDESharedPixmap' ||
	    $className eq 'TDESocket' ||
	    $className eq 'KLibrary' ||
	    $className eq 'KScanDialogFactory' ||
	    $className eq 'KDictSpellingHighlighter' ||
		$className eq 'KPropertiesDialog' ||
	    $className eq 'ProgressItem' ||
	    $className eq 'TDEIO::ChmodInfo' ||
	    $className eq 'TDEIO::MetaData' ||
	    $className eq 'KFileMimeTypeInfo::ItemInfo' ||
	    $className eq 'TDEIO::UDSAtom' ||
	    $className eq 'tdehtml::DrawContentsEvent' || # the tdehtml:: classes build, but don't link
	    $className eq 'tdehtml::MouseDoubleClickEvent' ||
	    $className eq 'tdehtml::MouseMoveEvent' ||
	    $className eq 'tdehtml::MousePressEvent' ||
	    $className eq 'tdehtml::MouseReleaseEvent' ||
	    $className eq 'tdehtml::MouseEvent' ||
	    $className eq 'KURL::List' ||
	    $className eq 'KWin::Info' ||
	    $className eq 'TerminalInterface' ||
	    $className =~ /.*Private$/ || # Ignore any classes which aren't for public consumption
	    $className =~ /.*Impl$/ ||
	    $className =~ /.*Internal.*/ ||
#	    $classNode->{Deprecated} ||
	    $classNode->{NodeType} eq 'union'  # Skip unions for now, e.g. TQPDevCmdParam	  
	) {
	    print STDERR "Skipping $className\n" if ($debug);
	    print STDERR "Skipping union $className\n" if ( $classNode->{NodeType} eq 'union');
	    $skippedClasses{$className} = 1;
	    delete $classNode->{Compound}; # Cheat, to get it excluded from Iter::LocalCompounds
	    return;
	}

	my $signalCount = 0;
	my $eventHandlerCount = 0;
	my $defaultConstructor = 'none'; #  none, public, protected or private. 'none' will become 'public'.
	my $constructorCount = 0; # total count of _all_ ctors
	# If there are ctors, we need at least one public/protected one to instanciate the class
	my $hasPublicProtectedConstructor = 0;
	# We need a public dtor to destroy the object --- ### aren't protected dtors ok too ??
	my $hasPublicDestructor = 1; # by default all classes have a public dtor!
	#my $hasVirtualDestructor = 0;
	my $hasDestructor = 0;
	my $hasPrivatePureVirtual = 0;
	my $hasCopyConstructor = 0;
	my $hasPrivateCopyConstructor = 0;
	# Note: no need for hasPureVirtuals. $classNode{Pure} has that.

        my $doPrivate = $main::doPrivate;
	$main::doPrivate = 1;
	# Look at each class member (looking for methods and enums in particular)
	Iter::MembersByType ( $classNode, undef,
		sub {

	my( $classNode, $m ) = @_;
	my $name = $m->{astNodeName};

	if( $m->{NodeType} eq "method" ) {
	    if ( $m->{ReturnType} eq 'typedef' # TQFile's EncoderFn/DecoderFn callback, very badly parsed
	       ) {
		$m->{NodeType} = 'deleted';
		next;
	    }

	    print STDERR "preParseClass: looking at $className\::$name  $m->{Params}\n" if ($debug);

	    if ( $name eq $classNode->{astNodeName} ) {
		if ( $m->{ReturnType} =~ /~/  ) {
		    # A destructor
		    $hasPublicDestructor = 0 if $m->{Access} ne 'public';
		    #$hasVirtualDestructor = 1 if ( $m->{Flags} =~ "v" && $m->{Access} ne 'private' );
		    $hasDestructor = 1;
		} else {
		    # A constructor
		    $constructorCount++;
		    $defaultConstructor = $m->{Access} if ( $m->{Params} eq '' );
		    $hasPublicProtectedConstructor = 1 if ( $m->{Access} ne 'private' );

		    # Copy constructor?
		    if ( $#{$m->{ParamList}} == 0 ) {
			my $theArgType = @{$m->{ParamList}}[0]->{ArgType};
			if ($theArgType =~ /$className\s*\&/) {
			    $hasCopyConstructor = 1;
			    $hasPrivateCopyConstructor = 1 if ( $m->{Access} eq 'private' );
			}
		    }
		    # Hack the return type for constructors, since constructors return an object pointer
		    $m->{ReturnType} = $className."*";
		}
	    }

	    if ( $name =~ /~$classNode->{astNodeName}/ && $m->{Access} ne "private" ) { # not used
		$hasPublicDestructor = 0 if $m->{Access} ne 'public';
		#$hasVirtualDestructor = 1 if ( $m->{Flags} =~ "v" );
		$hasDestructor = 1;
	    }

	    if ( $m->{Flags} =~ "p" && $m->{Access} =~ /private/ ) {
                $hasPrivatePureVirtual = 1; # ouch, can't inherit from that one
	    }

	    # All we want from private methods is to check for virtuals, nothing else
	    next if ( $m->{Access} =~ /private/ );

		# Don't generate code for deprecated methods, 
		# or where the code won't compile/link for obscure reasons. Or even obvious reasons..
		if ( ($classNode->{astNodeName} eq 'KCharSelectTable' and $name eq 'paintCell')
			|| ($classNode->{astNodeName} eq 'KAnimWidget' and $name eq 'KAnimWidget' and @{$m->{ParamList}} == 2)
			|| ($classNode->{astNodeName} eq 'KDCOPActionProxy' and $name eq 'actions')
			|| ($classNode->{astNodeName} eq 'KFileDialog' and $name eq 'addDirEntry')
			|| ($classNode->{astNodeName} eq 'KFileDialog' and $name eq 'getDirEntry')
			|| ($classNode->{astNodeName} eq 'KFileView' and $name eq 'selectionMode')
			|| ($classNode->{astNodeName} eq 'KFind' and $name eq 'KFind' and @{$m->{ParamList}} == 4)
			|| ($classNode->{astNodeName} eq 'TDEGlobalAccel' and $name eq 'setEnabled')
			|| ($classNode->{astNodeName} eq 'KCharsets' and $name eq 'encodingsForLanguage')
			|| ($classNode->{astNodeName} eq 'KInputDialog' and $name eq 'getInteger')
			|| ($classNode->{astNodeName} eq 'TDEIO' and $name eq 'buildHTMLErrorString')
			|| ($classNode->{astNodeName} eq 'TDEIO' and $name eq 'calculateRemainingSeconds')
			|| ($classNode->{astNodeName} eq 'SlaveBase' and $name eq 'checkCachedAuthentication')
			|| ($classNode->{astNodeName} eq 'SlaveBase' and $name eq 'cacheAuthentication')
			|| ($classNode->{astNodeName} eq 'KInputDialog' and $name eq 'getDouble')
			|| ($classNode->{astNodeName} eq 'TDEToolBar' and $name eq 'enable')
			|| ($classNode->{astNodeName} eq 'TDEAccel' and $name eq 'insert' and @{$m->{ParamList}} == 2)
			|| ($classNode->{astNodeName} eq 'TDEAccel' and $name eq 'autoupdate')
			|| ($classNode->{astNodeName} eq 'TDEAccel' and $name eq 'getAutoUpdate')
			|| ($classNode->{astNodeName} eq 'TDEStdAccel' and $name eq 'insert')
			|| ($classNode->{astNodeName} eq 'KBookmarkMenu' and $name eq 'invalid')
			|| ($classNode->{astNodeName} eq 'KCharsets' and $name eq 'languages')
			|| ($classNode->{astNodeName} eq 'KCombiView' and $name eq 'setDropOptions')
			|| ($classNode->{astNodeName} eq 'KFileMetaInfoItem' and $name eq 'unit')
			|| ($classNode->{astNodeName} eq 'TDEInstance' and $name eq 'charsets')
			|| ($classNode->{astNodeName} eq 'TDEInstance' and $name eq 'TDEInstance' and $m->{Access} =~ /protected/)
			|| ($classNode->{astNodeName} eq 'KKey' and $name eq 'isValidQt')
			|| ($classNode->{astNodeName} eq 'KKey' and $name eq 'isValidNative')
			|| ($classNode->{astNodeName} eq 'KKeySequence' and $name eq 'init')
			|| ($classNode->{astNodeName} eq 'KKeySequence' and $name eq 'setTriggerOnRelease')
			|| ($classNode->{astNodeName} eq 'KEMailSettings' and $name eq 'getExtendedSetting')
			|| ($classNode->{astNodeName} eq 'KEMailSettings' and $name eq 'setExtendedSetting')
			|| ($classNode->{astNodeName} eq 'TDEHTMLSettings' and $name eq 'fallbackAccessKeysAssignments')
			|| ($classNode->{astNodeName} eq 'KProtocolManager' and $name eq 'defaultConnectTimeout')
			|| ($classNode->{astNodeName} eq 'KMD5' and $name eq 'transform')
			|| ($classNode->{astNodeName} eq 'KSSLCertificate' and $name eq 'operator!=')
			|| ($classNode->{astNodeName} eq 'KSSLPKCS7' and $name eq 'validate')
			|| ($classNode->{astNodeName} eq 'KSSLPKCS7' and $name eq 'revalidate')
			|| ($classNode->{astNodeName} eq 'KSSLSession' and $name eq 'KSSLSession' and @{$m->{ParamList}} == 1)
			|| ($classNode->{astNodeName} eq 'KSimpleFileFilter' and $name eq 'nameFilters')
			|| ($classNode->{astNodeName} eq 'KTabWidget' and $name eq 'isTabReorderingEnabled')
			|| ($classNode->{astNodeName} eq 'KTabWidget' and $name eq 'hoverCloseButton')
			|| ($classNode->{astNodeName} eq 'KTar' and $name eq 'writeFile_impl')

			# Various methods to skip in Qt/E (Qt 2.3.x)
			|| ($main::qt_embedded
				&& ( ($classNode->{astNodeName} eq 'TQUriDrag' and $name =~ /^decode$|decodeLocalFiles|decodeToUnicodeUris/)
				|| ($classNode->{astNodeName} eq 'TQApplication' and $name =~ /^qwsSetCustomColors|^setArgs$|^winMouseButtonUp|^winFocus|^winMouseButtonUP$|^winVersion$/)
				|| ($classNode->{astNodeName} eq 'TQPrinter' and $name =~ /^setIdle$|^setActive$/)
				|| ($classNode->{astNodeName} eq 'TQDragObject' and $name eq 'dragLink')
				|| ($classNode->{astNodeName} eq 'TQFont' and $name eq 'qwsRenderToDisk')
				|| ($classNode->{astNodeName} eq 'TQFontInfo' and $name eq 'font')
				|| ($classNode->{astNodeName} eq 'TQLineEdit' and $name eq 'getSelection')
				|| ($classNode->{astNodeName} eq 'TQMainWindow' and $name eq 'toolBars')
				|| ($classNode->{astNodeName} eq 'TQMovie' and $name eq 'setDisplayWidget')
				|| ($classNode->{astNodeName} eq 'TQMetaObject' and $name =~ /^new_metaenum_item$|^new_metaaccess$/)
				|| ($classNode->{astNodeName} eq 'TQPainter' and $name eq 'pos')
				|| ($classNode->{astNodeName} eq 'TQPixmap' and $name =~ /^allocCell$|^clut$|^freeCell|^hbm|^isMultiCellPixmap|^multiCellPixmap|^multiCellBitmap|^multiCellHandle|^multiCellOffset|^numCols/)
				|| ($name eq 'handle')
				|| ($name eq 'resetInputContext')
				|| ($name eq 'propagateUpdates')
				|| ($name eq 'bytesPerLine')
				|| ($name eq 'scanLine')
				|| ($name eq 'hPal')
				|| ($name eq 'copyX11Data')
				|| ($name eq 'getX11Data')
				|| ($name eq 'setX11Data')
				|| ($name eq 'realizePal')
				|| ($name eq 'qwsDisplay')
				|| ($name eq 'fixport')
				|| ($name eq 'hack_strrchr')
				|| ($name eq 'hack_strchr')
				|| ($name eq 'hack_strstr') ) )			
						
			|| ($name eq 'virtual_hook')
			|| ($name =~ /_TDEShared_/)
			|| ($name eq 'qObject')
			|| ($name =~ /argv/)
			|| ($name =~ /argc/)
			|| ($name eq 'qt_emit')
			|| ($name eq 'qt_invoke')
			|| ($name eq 'qt_cast')
			|| ($name eq 'qt_property')
			|| ($name eq 'staticMetaObject')
			# Assume only Qt classes have tr() and trUtf8() in their TQ_OBJECT macro
			|| ($classNode->{astNodeName} !~ /^Q/ and $name eq 'tr')
			|| ($classNode->{astNodeName} !~ /^Q/ and $name eq 'trUtf8')
				|| $name eq 'trUtf8'
				|| $m->{Deprecated} ) {
		    $m->{NodeType} = 'deleted';
			next;
		}
			    
		my $argId = 0;
	    my $firstDefaultParam;
	    foreach my $arg ( @{$m->{ParamList}} ) {
		# Look for first param with a default value
		if ( defined $arg->{DefaultValue} && !defined $firstDefaultParam ) {
		    $firstDefaultParam = $argId;
		}

		if ( $arg->{ArgType} eq '...' # refuse a method with variable arguments
		     or $arg->{ArgType} eq 'image_io_handler' # TQImage's callback
		     or $arg->{ArgType} eq 'DecoderFn' # TQFile's callback
		     or $arg->{ArgType} eq 'EncoderFn' # TQFile's callback
		     or $arg->{ArgType} =~ /bool \(\*\)\(TQObject/ # TQMetaObject's ctor
		     or $arg->{ArgType} eq 'QtStaticMetaObjectFunction' # TQMetaObjectCleanUp's ctor with func pointer
		     or $arg->{ArgType} eq 'const TQTextItem&' # ref to a private class in 3.2.0b1
		     or $arg->{ArgType} eq 'FILE*' # won't be able to handle that I think
		     or $arg->{ArgType} eq 'const KKeyNative&' #
		) {
		    $m->{NodeType} = 'deleted';
		}
		else
		{
		    # Resolve type in full, e.g. for TQSessionManager::RestartHint
		    # (TQSessionManagerJBridge doesn't inherit TQSessionManager)
		    $arg->{ArgType} = kalyptusDataDict::resolveType($arg->{ArgType}, $classNode, $rootnode);
		    registerType( $arg->{ArgType} );
		    $argId++;
		}
	    }
	    $m->AddProp( "FirstDefaultParam", $firstDefaultParam );
	    $m->{ReturnType} = kalyptusDataDict::resolveType($m->{ReturnType}, $classNode, $rootnode) if ($m->{ReturnType});
	    registerType( $m->{ReturnType} );
	}
	elsif( $m->{NodeType} eq "enum" ) {
		if ( ! $m->{astNodeName} ) {
			$m->{Access} = 'protected';
		}
		my $fullEnumName = $className."::".$m->{astNodeName};
		if ( ($fullEnumName eq 'KMimeType::Format' and $name eq 'compression')
				|| $m->{Deprecated} ) {
		    $m->{NodeType} = 'deleted';
			next;
		}
	    
		$classNode->{enumerations}{$m->{astNodeName}} = $fullEnumName;
#		if $m->{astNodeName} and $m->{Access} ne 'private';
#		if $m->{astNodeName} ;

	    # Define a type for this enum
	    registerType( $fullEnumName );

	    # Remember that it's an enum
	    findTypeEntry( $fullEnumName )->{isEnum} = 1;
 	}
	elsif( $m->{NodeType} eq 'var' ) {
	    my $varType = $m->{Type};
	    # We are interested in public static vars, like TQColor::blue
	    if ( $varType =~ s/static\s+// && $m->{Access} ne 'private'
			&& $className."::".$m->{astNodeName} ne "KSpell::modalListText" )
	    {
		$varType =~ s/const\s+(.*)\s*&/$1/;
		$varType =~ s/\s*$//;
		print STDERR "var: $m->{astNodeName} '$varType'\n" if ($debug);

		# Register the type
		registerType( $varType );

	    } else {
		# To avoid duplicating the above test, we just get rid of any other var
		$m->{NodeType} = 'deleted';
	    }
	}
		},
		undef
	);
	$main::doPrivate = $doPrivate;

	print STDERR "$className: ctor count: $constructorCount, hasPublicProtectedConstructor: $hasPublicProtectedConstructor, hasCopyConstructor: $hasCopyConstructor:, defaultConstructor: $defaultConstructor, hasPublicDestructor: $hasPublicDestructor, hasPrivatePureVirtual:$hasPrivatePureVirtual\n" if ($debug);

	# Note that if the class has _no_ constructor, the default ctor applies. Let's even generate it.
	if ( !$constructorCount && $defaultConstructor eq 'none' && !$hasPrivatePureVirtual ) {
	    # Create a method node for the constructor
	    my $methodNode = Ast::New( $classNode->{astNodeName} );
	    $methodNode->AddProp( "NodeType", "method" );
	    $methodNode->AddProp( "Flags", "" );
	    $methodNode->AddProp( "Params", "" );
            $methodNode->AddProp( "ParamList", [] );
	    kdocAstUtil::attachChild( $classNode, $methodNode );

	    # Hack the return type for constructors, since constructors return an object pointer
	    $methodNode->AddProp( "ReturnType", $className."*" );
	    registerType( $className."*" );
	    $methodNode->AddProp( "Access", "public" ); # after attachChild
	    $defaultConstructor = 'public';
	    $hasPublicProtectedConstructor = 1;
	}

	# Also, if the class has no explicit destructor, generate a default one.
	if ( !$hasDestructor && !$hasPrivatePureVirtual ) {
	    my $methodNode = Ast::New( "$classNode->{astNodeName}" );
	    $methodNode->AddProp( "NodeType", "method" );
	    $methodNode->AddProp( "Flags", "" );
	    $methodNode->AddProp( "Params", "" );
	    $methodNode->AddProp( "ParamList", [] );
	    kdocAstUtil::attachChild( $classNode, $methodNode );

	    $methodNode->AddProp( "ReturnType", "~" );
	    $methodNode->AddProp( "Access", "public" );
	}

	# If we have a private pure virtual, then the class can't be instanciated (e.g. TQCanvasItem)
	# Same if the class has only private constructors (e.g. TQInputDialog)
	$classNode->AddProp( "CanBeInstanciated", $hasPublicProtectedConstructor 
#												&& !$hasPrivatePureVirtual
												&& (!$classNode->{Pure} or $classNode->{astNodeName} eq 'TQValidator')
												&& !($classNode->{NodeType} eq 'namespace')
												&& ($classNode->{astNodeName} !~ /^DrawContentsEvent$|^MouseEvent$|^MouseDoubleClickEvent$|^MouseMoveEvent$|^MouseReleaseEvent$|^MousePressEvent$/)
												&& ($classNode->{astNodeName} !~ /TQMetaObject|TQDragObject|Slave|CopyJob|KMdiChildFrm|KNamedCommand/) );

	# We will derive from the class only if it has public or protected constructors.
	# (_Even_ if it has pure virtuals. But in that case the *.cpp class can't be instantiated either.)
	$classNode->AddProp( "BindingDerives", $hasPublicProtectedConstructor );

	# We need a public dtor to destroy the object --- ### aren't protected dtors ok too ??
	$classNode->AddProp( "HasPublicDestructor", $hasPublicDestructor );

	# Hack for TQAsyncIO. We don't implement the "if a class has no explicit copy ctor,
	# then all of its member variables must be copiable, otherwise the class isn't copiable".
	$hasPrivateCopyConstructor = 1 if ( $className eq 'TQAsyncIO' );

	# Remember if this class can't be copied - it means all its descendants can't either
	$classNode->AddProp( "CanBeCopied", !$hasPrivateCopyConstructor );
	$classNode->AddProp( "HasCopyConstructor", $hasCopyConstructor );
}

sub propagateCanBeCopied($)
{
	my $classNode = shift;
	my $className = join( "::", kdocAstUtil::heritage($classNode) );
	my @super = superclass_list($classNode);
	# A class can only be copied if none of its ancestors have a private copy ctor.
	for my $s (@super) {
	    if (!$s->{CanBeCopied}) {
		$classNode->{CanBeCopied} = 0;
		print STDERR "$classNode->{astNodeName} cannot be copied\n" if ($debug);
		last;
	    }
	}

	# Prepare the {case} dict for the class
	prepareCaseDict( $classNode );
}

=head2 writeClassDoc

	Called by writeDoc for each class to be written out

=cut

sub writeClassDoc
{
	my( $node ) = @_;
	my $className = join( "::", kdocAstUtil::heritage($node) );
	my $javaClassName = $node->{astNodeName};
	# Makefile doesn't like '::' in filenames, so use __
	my $fileName  = $node->{astNodeName};
#	my $fileName  = join( "__", kdocAstUtil::heritage($node) );
	print "Enter: $className\n" if $debug;
	
	my $typeprefix = ($className =~ /^Q/ ? "qt_" : "tde_");
	my $packagename = ($typeprefix eq 'qt_' ? "org.trinitydesktop.qt" : "org.trinitydesktop.koala");
	
	# Write out the *.java file
	my $classFile = "$outputdir/$fileName.java";
	open( CLASS, ">$classFile" ) || die "Couldn't create $classFile\n";
	print STDERR "Writing $fileName.java\n" if ($debug);
	
	print CLASS "//Auto-generated by $0. DO NOT EDIT.\n";
	
	print CLASS "package $packagename;\n\n";
	
	# And write out the *.cpp file
	my $jniFile = "$outputdir/$fileName.cpp";
	open( JNISOURCE, ">$jniFile" ) || die "Couldn't create $jniFile\n";
	print STDERR "Writing $fileName.cpp\n" if ($debug);
	
	print JNISOURCE "//Auto-generated by $0. DO NOT EDIT.\n";

	my %javaMethods = ();
	my %jniMethods = ();
	my $jniCode;
	my %addImport = ();
	my %addInclude = ();
	
	my @ancestors = ();
	my @ancestor_nodes = ();
	Iter::Ancestors( $node, $rootnode, undef, undef, sub { 
				my ( $ances, $name, $type, $template ) = @_;
				if ( $name ne "TQMemArray" and $name ne "TQSqlFieldInfoList" ) {
					push @ancestor_nodes, $ances;
					push @ancestors, $name;
				}
			},
			undef
		);
        
	my ($methodCode, $interfaceCode, $signalCode, $jbridgeCode) = generateAllMethods( $node, $#ancestors + 1, 
																		\%javaMethods, \%jniMethods, 
																		$node, 
																		($node->{NodeType} eq 'namespace' ? 0 : 1), 
																		\%addImport, \%addInclude );

	my $signalFile = "$outputdir/$fileName" . "Signals.java";
	if ( $signalCode ne '' ) {
		open( SIGNALS, ">$signalFile" ) || die "Couldn't create $signalFile\n";
		print SIGNALS "//Auto-generated by $0. DO NOT EDIT.\n";
 		print SIGNALS "package $packagename;\n\n";
	}
	
	my $tempMethodNumber = $methodNumber;
	
	# Add method calls for the interfaces implemented by the class
	foreach my $ancestor_node ( @ancestor_nodes ) {
		if ( kalyptusDataDict::interfacemap($ancestor_node->{astNodeName}) ne () && ($#ancestors > 0) ) {
			my ($meth, $interf, $sig, $jbridge) = generateAllMethods( $ancestor_node, 0, \%javaMethods, \%jniMethods, $node, 0, \%addImport, \%addInclude );
			$methodCode .= $meth;
			$jbridgeCode .= $jbridge;
		}
	}

		
	if ( $className eq 'Qt' or $className eq 'KDE' ) {
		my $globalSpace = kdocAstUtil::findRef( $rootnode, $main::globalSpaceClassName );
		my ($meth, $interf, $sig, $jbridge) = generateAllMethods( $globalSpace, 0, \%javaMethods, \%jniMethods, $node, 0, \%addImport, \%addInclude );
		$methodCode .= $meth;
		$jbridgeCode .= $jbridge;
	}
	
	
	$jbridgeCode .= virtualMethodCallbacks( $node );
	
	$methodNumber = $tempMethodNumber;
		
	if ( $className eq 'Qt' ) {
	    print CLASS "import java.io.*;\n";
	    print CLASS "import java.text.MessageFormat;\n";
	    print CLASS "import java.lang.reflect.*;\n";
	} else {
		if ( $className eq 'TQListView' or $className eq 'TQListViewItem' or $className eq 'TQUriDrag' ) {
			# Special case these two classes as they have methods that use ArrayList added as 'extras'
	    	print CLASS "import java.util.ArrayList;\n";
		}
	    print CLASS "import org.trinitydesktop.qt.TQt;\n";
	}
	
	if ( kalyptusDataDict::interfacemap($javaClassName) ne () ) {
		my $interfaceFile = "$outputdir/" . kalyptusDataDict::interfacemap($javaClassName) . ".java";
		open( INTERFACE, ">$interfaceFile" ) || die "Couldn't create $interfaceFile\n";
		print INTERFACE "//Auto-generated by $0. DO NOT EDIT.\n";
 		print INTERFACE "package $packagename;\n\n";
	}
	
	foreach my $imp (keys %addImport) {
	    die if $imp eq '';
		# Ignore any imports for classes in the same package as the current class
		if ($imp !~ /$packagename/) {
	    	print CLASS "import $imp;\n";
	    	print INTERFACE "import $imp;\n";
	    	print SIGNALS "import $imp;\n" unless $signalCode eq '';;
		}
	}	
	
	if ( kalyptusDataDict::interfacemap($javaClassName) ne () ) {
		print INTERFACE "\npublic interface " . kalyptusDataDict::interfacemap($javaClassName) . " {\n";
		print INTERFACE $interfaceCode;
		print INTERFACE "}\n";
		close INTERFACE;
	}
	
	my $classdec;
	if ($node->{NodeType} eq 'namespace') {
		$classdec = "public class $javaClassName {\n";
	} elsif ( $#ancestors < 0 ) {
		$classdec = "public class $javaClassName implements QtSupport";
		if ( kalyptusDataDict::interfacemap($javaClassName) ne () ) {
			$classdec .= ", " . kalyptusDataDict::interfacemap($javaClassName);
		}

		$classdec .= " {\n\tprivate long _qt;\n";
		$classdec .= "\tprivate boolean _allocatedInJavaWorld = true;\n";
		$classdec .= "\tprotected $javaClassName(Class dummy){}\n\n";
	} else {
		$classdec = "public class $javaClassName extends ";
		my $ancestor;
		foreach $ancestor ( @ancestors ) {
			if ( kalyptusDataDict::interfacemap($ancestor) eq () or $ancestor eq @ancestors[$#ancestors] ) {
				$ancestor =~ s/^.*:://;
				$classdec .= "$ancestor ";
				if ( $typeprefix ne 'qt_' and $ancestor =~ /^Q/ ) {
					print CLASS "import org.trinitydesktop.qt.$ancestor;\n";
				}
				last;
			}
		}

		my @implements = ();
		if ( $#ancestors >= 1 ) {
			foreach $ancestor ( @ancestors ) {
				if ( kalyptusDataDict::interfacemap($ancestor) ne () ) {
					push(@implements, kalyptusDataDict::interfacemap($ancestor));
				}
			}
	    }
	
		if ($#implements >= 0) {
			$classdec .= "implements ";
			$classdec .= join(", ", @implements);
		}
		
		$classdec .= " {\n";
		$classdec .= "\tprotected $javaClassName(Class dummy){super((Class) null);}\n";
	}
		
	print CLASS "\n";
	if ( $javaClassName !~ /^Q/ or $signalCode ne '' ) {
		my $signalLink = '';
 		if ( $signalCode ne '' ) {
			print SIGNALS "\npublic interface $javaClassName" . "Signals {\n";
			print SIGNALS $signalCode;
			print SIGNALS "}\n";
			close SIGNALS;

			$signalLink = " See {\@link $javaClassName" . "Signals} for signals emitted by $javaClassName\n";
		}
		my $docnode = $node->{DocNode};
		print CLASS "/**\n";
		if ( defined $docnode ) { 
			print CLASS printJavadocComment( $docnode, "", "", $signalLink ) . "\n" 
		} else {
			print CLASS $signalLink;
		}
		print CLASS "*/\n";
	}
	
	print CLASS $classdec;
    print CLASS $methodCode;
	
	my %jniNames;
	my $name;
	foreach my $methodName (keys %jniMethods) {
	    die if $methodName eq '';
		$name = $methodName;
		$name =~ s/(.*[^_])__[^1].*/$1/;
		$name =~ s/(.*[^_])__$/$1/;
		if (defined $jniNames{$name}) {
			$jniNames{$name}++;
		} else {
			$jniNames{$name} = 1;
		}
	}	
	
	# Add the JNI functions sorted by name. And with the correct
	# signature minus the arg types if name not duplicated
	foreach my $methodName (sort keys %jniMethods) {
	    die if $methodName eq '';
		my $methodCode = $jniMethods{$methodName};
		$methodName =~ s/(.*[^_])__[^1].*/$1/;
		$methodName =~ s/(.*[^_])__$/$1/;
		if ($jniNames{$methodName} == 1) {
			$methodCode =~ s/__\(/\(/;
			$methodCode =~ s/__[^1][^\(]*\(/\(/;
		}
		$jniCode .= $methodCode;
	}	
	
	if ( $className eq 'Qt' ) {
		if ($main::qt_embedded) {
			$qtExtras =~ s/public static native TQCursor whatsThisCursor\(\);//;
			$qtjniExtras =~ s/JNIEXPORT jobject JNICALL\nJava_org_trinitydesktop_qt_Qt_whatsThisCursor[^}]*}//;
		}
		print CLASS $qtExtras;
		$jniCode .= $qtjniExtras;
	} elsif ( $className eq 'TQApplication' ) {
		print CLASS $qapplicationExtras;
		$jniCode .= $qapplicationjniExtras;
	} elsif ( $className eq 'TQBitmap' ) {
		print CLASS $qbitmapExtras;
		$jniCode .= $qbitmapjniExtras;
	} elsif ( $className eq 'TQDropEvent' ) {
		print CLASS $qdropeventExtras;
		$jniCode .= $qdropeventjniExtras;
	} elsif ( $className eq 'TQDragObject' ) {
		print CLASS $qdragobjectExtras;
		$jniCode .= $qdragobjectjniExtras;
	} elsif ( $className eq 'TQObject' ) {
		print CLASS $qobjectExtras;
		$jniCode .= $qobjectjniExtras;
	} elsif ( $className eq 'TQImage' ) {
		$jniCode .= $qimagejniExtras;
	} elsif ( $className eq 'TQListView' ) {
		print CLASS $qlistviewExtras;
		$jniCode .= $qlistviewjniExtras;
	} elsif ( $className eq 'TQListViewItem' ) {
		print CLASS $qlistviewitemExtras;
		$jniCode .= $qlistviewitemjniExtras;
	} elsif ( $className eq 'TQMenuBar' ) {
		if ($main::qt_embedded) {
			$qmenubarjniExtras =~ s/jobject accel/jlong accel/;
		}
		$jniCode .= $qmenubarjniExtras;
	} elsif ( $className eq 'TQMenuData' ) {
		if ($main::qt_embedded) {
			$qmenudatajniExtras =~ s/jobject accel/jlong accel/;
		}
		$jniCode .= $qmenudatajniExtras;
	} elsif ( $className eq 'TQMimeSource' ) {
		print CLASS $qmimesourceExtras;
		$jniCode .= $qmimesourcejniExtras;
	} elsif ( $className eq 'TQPopupMenu' ) {
		if ($main::qt_embedded) {
			$qpopupmenujniExtras =~ s/jobject accel/jlong accel/;
		}
		$jniCode .= $qpopupmenujniExtras;
	} elsif ( $className eq 'TQWidget' ) {
		print CLASS $qwidgetExtras;
		$jniCode .= $qwidgetjniExtras;
	} elsif ( $className eq 'TQPaintDevice' ) {
		print CLASS $qpaintdeviceExtras;
		$jniCode .= $qpaintdevicejniExtras;
	} elsif ( $className eq 'TQPixmap' ) {
		print CLASS $qpixmapExtras;
		$jniCode .= $qpixmapjniExtras;
	} elsif ( $className eq 'TQIODevice' ) {
		print CLASS $qiodeviceExtras;
	} elsif ( $className eq 'TQPointArray' ) {
		print CLASS $qpointarrayExtras;
		$jniCode .= $qpointarrayjniExtras;
	} elsif ( $className eq 'TQUriDrag' ) {
		print CLASS $quridragExtras;
		$jniCode .= $quridragjniExtras;
	} elsif ( $className eq 'TDECmdLineArgs' ) {
		$jniCode .= $kcmdlineargsjniExtras;
	} elsif ( $className eq 'TDEIO::Scheduler' ) {
		$jniCode .= $schedulerjniExtras;
	} elsif ( $className eq 'TDEApplication' ) {
		print CLASS $kapplicationExtras;
		$jniCode .= $kapplicationjniExtras;
	} elsif ( $className eq 'TDEMainWindow' ) {
		print CLASS $tdemainwindowExtras;
		$jniCode .= $tdemainwindowjniExtras;
	}
	
    print CLASS "}\n";
	close CLASS;
	
	foreach my $incl (keys %addInclude) {
	    die if $incl eq '';
	    print JNISOURCE "#include <$incl>\n";
	}	
	
	print JNISOURCE "\n";
	print JNISOURCE "#include <qtjava/QtSupport.h>\n";
	
	if ($jniCode =~ /JavaSlot/) {
		print JNISOURCE "#include <qtjava/JavaSlot.h>\n";
	}
	
	if ( $typeprefix eq "qt_" ) {
		print JNISOURCE "#include <qtjava/$javaClassName" . ".h>\n";
	} else {
		print JNISOURCE "#include <tdejava/TDESupport.h>\n";
		print JNISOURCE "#include <tdejava/$javaClassName" . ".h>\n";
	}
	
	if ($javaClassName eq 'TDEIO') {
		# Hack: namespaces can be defined in several source files, which doesn't work, so this..
		print JNISOURCE "#include <tdeio/job.h>\n";
		print JNISOURCE "#include <tdeio/davjob.h>\n";
		print JNISOURCE "#include <tdeio/metainfojob.h>\n";
		print JNISOURCE "#include <tdeio/previewjob.h>\n";
		print JNISOURCE "#include <tdeio/paste.h>\n";
	}
	
	print JNISOURCE "\n";
	
	if ($jbridgeCode ne '' && $node->{CanBeInstanciated}) {
		print JNISOURCE "class $javaClassName" . "JBridge : public $className\n";
		print JNISOURCE "{\npublic:\n";
		print JNISOURCE $jbridgeCode;
		print JNISOURCE "};\n\n"
	}
	print JNISOURCE $jniCode;
	close JNISOURCE;
}


# Generate the prototypes for a method (one per arg with a default value)
# Helper for makeprotos
sub iterproto($$$$$) {
    my $classidx = shift; # to check if a class exists
    my $method = shift;
    my $proto = shift;
    my $idx = shift;
    my $protolist = shift;

    my $argcnt = scalar @{ $method->{ParamList} } - 1;
    if($idx > $argcnt) {
	push @$protolist, $proto;
	return;
    }
    if(defined $method->{FirstDefaultParam} and $method->{FirstDefaultParam} <= $idx) {
	push @$protolist, $proto;
    }

    my $arg = $method->{ParamList}[$idx]->{ArgType};

    my $typeEntry = findTypeEntry( $arg );
    my $realType = $typeEntry->{realType};

    # A scalar ?
    $arg =~ s/\bconst\b//g;
    $arg =~ s/\s+//g;
    if($typeEntry->{isEnum} || $allTypes{$realType}{isEnum} || exists $typeunion{$realType} || exists $mungedTypeMap{$arg})
    {
	my $id = '$'; # a 'scalar
	$id = '?' if $arg =~ /[*&]{2}/;
	$id = $mungedTypeMap{$arg} if exists $mungedTypeMap{$arg};
	iterproto($classidx, $method, $proto . $id, $idx + 1, $protolist);
	return;
    }

    # A class ?
    if(exists $classidx->{$realType}) {
	iterproto($classidx, $method, $proto . '#', $idx + 1, $protolist);
	return;
    }

    # A non-scalar (reference to array or hash, undef)
    iterproto($classidx, $method, $proto . '?', $idx + 1, $protolist);
    return;
}

# Generate the prototypes for a method (one per arg with a default value)
sub makeprotos($$$) {
    my $classidx = shift;
    my $method = shift;
    my $protolist = shift;
    iterproto($classidx, $method, $method->{astNodeName}, 0, $protolist);
}

# Return the string containing the signature for this method (without return type).
# If the 2nd arg is not the size of $m->{ParamList}, this method returns a
# partial signature (this is used to handle default values).
sub methodSignature($$) {
    my $method = shift;
    my $last = shift;
    my $sig = $method->{astNodeName};
    my @argTypeList;
    my $argId = 0;
    foreach my $arg ( @{$method->{ParamList}} ) {
	last if $argId > $last;
	push @argTypeList, $arg->{ArgType};
	$argId++;
    }
    $sig .= "(". join(", ",@argTypeList) .")";
    $sig .= " const" if $method->{Flags} =~ "c";
    return $sig;
}

# Return the string containing the java signature for this method (without return type).
# If the 2nd arg is not the size of $m->{ParamList}, this method returns a
# partial signature (this is used to handle default values).
sub javaMethodSignature($$) {
    my $method = shift;
    my $last = shift;
    my $sig = $method->{astNodeName};
    my @argTypeList;
    my $argId = 0;
    foreach my $arg ( @{$method->{ParamList}} ) {
	$argId++;
	last if $argId > $last;
	push @argTypeList, "arg" . "$argId ". cplusplusToJava( $arg->{ArgType} );
    }
    $sig .= "(". join(", ",@argTypeList) .")";
    return $sig;
}

# Return the string containing the JNI signature for this method (without return type).
# If the 2nd arg is not the size of $m->{ParamList}, this method returns a
# partial signature (this is used to handle default values).
sub jniMethodSignature($$$$$) {
    my $method = shift;
	my $methodname = shift;
    my $last = shift;
	my $javaClassName = shift;
	my $javaArgList = shift;
	
	my $sig = ($javaClassName =~ /^Q/ ? "Java_org_trinitydesktop_qt_" : "Java_org_trinitydesktop_koala_");
    $sig .= $javaClassName . "_";
	$methodname =~ s/_/_1/g;
	$sig .= $methodname . "__";
    my @argTypeList;
    my @argList;
	my $javaStatic = ($method->{Flags} =~ "s" or $method->{Parent}->{NodeType} eq 'namespace');
	push @argTypeList, "JNIEnv*";
	push @argTypeList, ($javaStatic ? "jclass" : "jobject");
	push @argList, "JNIEnv* env";
	push @argList, ($javaStatic ? "jclass cls" : "jobject obj");
    my $argId = 0;
    foreach my $arg ( @{$method->{ParamList}} ) {
	$argId++;
	last if $argId > $last;
	push @argTypeList, cplusplusToJNI( $arg->{ArgType} );
	push @argList, cplusplusToJNI( $arg->{ArgType} ) . " " . $javaArgList->[$argId - 1];
	$sig .= cplusplusToJNISignature( $arg->{ArgType} );
    }
	my $call = $sig;
    $sig .= "(" . join(", ",@argTypeList) .")";
    $call .= "(" . join(", ",@argList) .")";
    return ( $sig, $call );
}

sub coerce_type($$$$) {
    #my $m = shift;
    my $union = shift;
    my $var = shift;
    my $type = shift;
    my $new = shift; # 1 if this is a return value, 0 for a normal param

    my $typeEntry = findTypeEntry( $type );
    my $realType = $typeEntry->{realType};

    my $unionfield = $typeEntry->{typeId};
#    die "$type" unless defined( $unionfield );
	if ( ! defined( $unionfield ) ) {
		print STDERR "type field not defined: $type\n";
		return "";
	}
	
    $unionfield =~ s/t_/s_/;

    $type =~ s/\s+const$//; # for 'char* const'
    $type =~ s/\s+const\s*\*$/\*/; # for 'char* const*'

    my $code = "$union.$unionfield = ";
    if($type =~ /&$/) {
	$code .= "(void*)&$var;\n";
    } elsif($type =~ /\*$/) {
	$code .= "(void*)$var;\n";
    } else {
	if ( $unionfield eq 's_class' 
		or ( $unionfield eq 's_voidp' and $type ne 'void*' )
		or $type eq 'TQString' ) { # hack
	    $type =~ s/^const\s+//;
	    if($new) {
	        $code .= "(void*)new $type($var);\n";
	    } else {
	        $code .= "(void*)&$var;\n";
	    }
	} else {
	    $code .= "$var;\n";
	}
    }

    return $code;
}

# Generate the list of args casted to their real type, e.g.
# (TQObject*)x[1].s_class,(TQEvent*)x[2].s_class,x[3].s_int
sub makeCastedArgList
{
    my @castedList;
    my $i = 1; # The args start at x[1]. x[0] is the return value
    my $arg;
    foreach $arg (@_) {
	my $type = $arg;
	my $cast;

	my $typeEntry = findTypeEntry( $type );
	my $unionfield = $typeEntry->{typeId};
#	die "$type" unless defined( $unionfield );
	if ( ! defined( $unionfield ) ) {
		print STDERR "type field not defined: $type\n";
		return "";
	}
	$unionfield =~ s/t_/s_/;

	$type =~ s/\s+const$//; # for 'char* const'
	$type =~ s/\s+const\s*\*$/\*/; # for 'char* const*'

	my $v .= " arg$i";
	if($type =~ /&$/) {
	    $cast = "*($type *)";
	} elsif($type =~ /\*$/) {
	    $cast = "($type)";
        } elsif($type =~ /\(\*\)\s*\(/) { # function pointer ... (*)(...)
            $cast = "($type)";
	} else {
	    if ( $unionfield eq 's_class'
		or ( $unionfield eq 's_voidp' and $type ne 'void*' )
		or $type eq 'TQString' ) { # hack
	        $cast = "*($type *)";
	    } else {
	        $cast = "($type)";
	    }
	}
	push @castedList, "$type$v";
	$i++;
    }
    return @castedList;
}

# Adds the header for node $1 to be included in $2 if not already there
# Prints out debug stuff if $3
sub addIncludeForClass($$$)
{
    my ( $node, $addInclude, $debugMe ) = @_;
    my $sourcename = $node->{Source}->{astNodeName};
    if ( $sourcename !~ s!.*(tdeio/|tdeparts/|dom/|tdeabc/|ksettings/|kjs/|tdetexteditor/|tdeprint/|tdesu/)(.*)!$1$2!m ) {
    	$sourcename =~ s!.*/(.*)!$1!m;
	}
#    die "Empty source name for $node->{astNodeName}" if ( $sourcename eq '' );
    return if ( $sourcename eq '' );
    unless ( defined $addInclude->{$sourcename} ) {
	print "  Including $sourcename\n" if ($debugMe);
	$addInclude->{$sourcename} = 1;
    }
    else { print "  $sourcename already included.\n" if ($debugMe); }
}

sub checkIncludesForObject($$)
{
    my $type = shift;
    my $addInclude = shift;

    my $debugCI = 0; #$debug
    #print "checkIncludesForObject $type\n";
    $type =~ s/const\s+//;
    my $it = $type;
    if (!($it and exists $typeunion{$it}) and $type !~ /\*/ and $type ne ""
         #and $type !~ /&/  # in fact we also want refs, due to the generated code
        ) {
	$type =~ s/&//;
	print "  Detecting an object by value/ref: $type\n" if ($debugCI);
	my $node = kdocAstUtil::findRef( $rootnode, $type );
	if ($node) {
	    addIncludeForClass( $node, $addInclude, $debugCI );
	}
	else { print " No header found for $type\n" if ($debugCI); }
    }
}



# Adds the import for node $1 to be imported in $2 if not already there
# Prints out debug stuff if $3
sub addImportForClass($$$)
{
    my ( $node, $addImport, $debugMe ) = @_;
    my $importname = javaImport( $node->{astNodeName} );
#	print "  Importing $importname for node name: " . $node->{astNodeName} . "\n";
	# No import needed, so return
    return if ( $importname eq '' );
    unless ( defined $addImport->{$importname} ) {
	print "  Importing $importname\n" if ($debugMe);
	$addImport->{$importname} = 1;
	if ( kalyptusDataDict::interfacemap($node->{astNodeName}) ) {
		$addImport->{$importname . "Interface"} = 1;
	}
    }
    else { print "  $importname already imported.\n" if ($debugMe); }
}

sub checkImportsForObject($$)
{
    my $type = shift;
    my $addImport = shift;

    my $debugCI = 0; #$debug
    # print "checkImportsForObject $type\n";
    $type =~ s/const\s+//;
    my $it = $type;
    if (!($it and exists $typeunion{$it}) and $type ne ""
         #and $type !~ /&/  # in fact we also want refs, due to the generated code
        ) {
	$type =~ s/&//;
	$type =~ s/[*]//;
	print "  Detecting an object by value/ref: $type\n" if ($debugCI);
	my $node = kdocAstUtil::findRef( $rootnode, $type );
	if ($node and $node->{NodeType} eq "class" ) {
		print "  NodeType: " . $node->{NodeType} . "\n" if ($debugCI);
	    addImportForClass( $node, $addImport, $debugCI );
	}
	else {
		if ( cplusplusToJava($it) eq 'ArrayList' ) {
			$addImport->{"java.util.ArrayList"} = 1;
		} else {
			print " No import found for $type\n" if ($debugCI); 
		} 
 	}
    }
}

sub generateVirtualMethod($$$$$)
{
    # Generating methods for $class.
    # $m: method node. $methodClass: the node of the class in which the method is really declared
    # (can be different from $class when the method comes from a super class)
    # This is important because of $allMethods, which has no entry for class::method in that case.

    my( $classNode, $signature, $m, $methodClass, $addImport ) = @_;
    my $methodCode = '';                    # output
    my $returnType = $m->{ReturnType};
    return ('', '') if $returnType eq '~'; # skip destructors

    my $className = $classNode->{astNodeName};
    my $flags = $m->{Flags};
    my @argList = @{$m->{ParamList}};

    print "generateVirtualMethod $className: $signature  ($m->{Access})\n" if ($debug);

    # Detect objects returned by value
    checkImportsForObject( $returnType, $addImport ) if ($returnType ne 'void');

    # Generate a matching virtual method in the x_ class
    $methodCode .= "\tvirtual $returnType $m->{astNodeName}(";
    my $i = 0;
    foreach my $arg ( @argList ) {
        $methodCode .= ", " if $i++;
        $methodCode .= $arg->{ArgType};
        $methodCode .= " x$i";

	# Detect objects passed by value
	checkImportsForObject( $arg->{ArgType}, $addImport );
    }
    $methodCode .= ") ";
    $methodCode .= "const " if ($flags =~ "c");
    $methodCode .= "\{\n";

    # Now the code of the method
    my $this = $classNode->{BindingDerives} > 0 ? "this" : "xthis";

    $i++; # Now the number of args
    $methodCode .= "\tSmoke::StackItem x[$i];\n";
    $i = 1;
    for my $arg (@argList) {
	$methodCode .= "\t";
	$methodCode .= coerce_type("x[$i]", "x$i", $arg->{ArgType}, 0);
	$i++;
    }

    my $sig = $methodClass->{astNodeName} . "::" . $signature;
    my $idx = $allMethods{$sig};
#    die "generateVirtualMethod: $className: No method found for $sig\n" if !defined $idx;
	if ( !defined $idx ) {
		print STDERR "generateVirtualMethod: $className: No method found for $sig\n";
		return "";
	}
	
    if($flags =~ "p") { # pure virtual
	$methodCode .= "\t${libname}_Smoke->binding->callMethod($idx, (void*)$this, x, true /*pure virtual*/);\n";
    } else {
	$methodCode .= "\tif(${libname}_Smoke->binding->callMethod($idx, (void*)$this, x)) ";
    }

    $returnType = undef if ($returnType eq 'void');
    if($returnType) {
	my $arg = $returnType;
	my $it = $arg;
	my $cast;
	my $v = "x[0]";
	my $indent = ($flags =~ "p") ? "\t" : "";
	if($it and exists $typeunion{$it}) {
	    $v .= ".$typeunion{$it}";
	    $cast = "($arg)";
	    $methodCode .= "${indent}return $cast$v;\n";
	} else {
	    $v .= ".s_class";
	    if($arg =~ s/&//) {
		$cast = "*($arg *)";
		$methodCode .= "${indent}return $cast$v;\n";
	    } elsif($arg !~ /\*/) {
		unless($flags =~ "p") {
		    $indent = "\t    ";
		    $methodCode .= "{\n";
		}
		# we assume it's a new thing, and handle it
		$methodCode .= "${indent}$arg *xptr = ($arg *)$v;\n";
		$methodCode .= "${indent}$arg xret(*xptr);\n";
		$methodCode .= "${indent}delete xptr;\n";
		$methodCode .= "${indent}return xret;\n";
		$methodCode .= "\t}\n" unless $flags =~ "p";
	    } else {
		$cast = "($arg)";
		$methodCode .= "${indent}return $cast$v;\n";
	    }
	}
    } else {
	$methodCode .= "\t" if $flags =~ "p";
	$methodCode .= "return;\n";
    }
    if($flags =~ "p") {
	$methodCode .= "\t// ABSTRACT\n";
	$methodCode .= "    }\n";
	return ( $methodCode );
    }
    $methodCode .= "\t";
    if($returnType) {
	$methodCode .= "return ";
    }
    $methodCode .= "$this\->$methodClass->{astNodeName}\::$m->{astNodeName}(";
    $i = 0;
    for my $arg (@argList) {
	$methodCode .= ", " if $i++;
	$methodCode .= "x$i";
    }
    $methodCode .= ");\n";
    $methodCode .= "\t}\n";
    return ( $methodCode );
}

sub generateMethod($$$$$$$$$)
{
    my( $classNode, $m, $addImport, $addInclude, $ancestorCount, $javaMethods, $jniMethods, $mainClassNode, $generateConstructors ) = @_;	# input
    my $methodCode = '';	# output
    my $interfaceCode = '';	# output
    my $signalCode = '';	# output
    my $jbridgeCode = '';	# output
	
    my $jniCode;
    my $name = $m->{astNodeName}; # method name
    
	my @heritage = kdocAstUtil::heritage($classNode);
    my $className  = join( "::", @heritage );
    
	@heritage = kdocAstUtil::heritage($mainClassNode);
	my $mainClassName  = join( "::", @heritage );

	# The javaClassName might be 'TQWidget', while currentClassName is 'TQRangeControl'
	# and the TQRangeControl methods are being copied into TQWidget.    
	my $javaClassName  = $mainClassNode->{astNodeName};
    my $currentClassName  = $classNode->{astNodeName};
	
	my $bridgeClassName;
	if ($classNode->{astNodeName} eq $main::globalSpaceClassName) {
		$bridgeClassName  = "";
	} elsif (!$mainClassNode->{CanBeInstanciated}) {
		$bridgeClassName  = $className;
	} else {
		$bridgeClassName  = $mainClassNode->{astNodeName} . "JBridge";
	}
	
	my $firstUnknownArgType = 99;
    my $returnType = $m->{ReturnType};

    # Don't use $className here, it's never the fully qualified (A::B) name for a ctor.
    my $isConstructor = ($name eq $classNode->{astNodeName} );
    my $isDestructor = ($returnType eq '~');

    # Don't generate anything for destructors, or constructors for namespaces
    return if $isDestructor 
			or ($classNode->{NodeType} eq 'namespace' and $isConstructor)
			or (!$mainClassNode->{CanBeInstanciated} and $m->{Access} =~ /protected/);
    
	# Rename operator methods 'op_...'
	if ( $name =~ /^operator.*/ ) {
		$methodNumber++;
		$name =~ s/ //;
		if (! exists $operatorNames{$name} ) {
			return;
		}
		$name = $operatorNames{$name};
	}
	
	if ($classNode->{astNodeName} eq $main::globalSpaceClassName) {
		my $sourcename = $m->{Source}->{astNodeName};
		# Only put Global methods which came from sources beginning with q into class Qt
		# Skip any methods in qstring.h/qcstring.h apart from TQByteArray compress/uncompress
		if ($javaClassName eq 'Qt' 
		and ( $sourcename !~ /\/q[^\/]*$/ or ($sourcename =~ /string.h$/ and $name !~ /[Cc]ompress/) )) {
			return;
		}
		# ..and any other global methods into KDE
		if ($javaClassName eq 'KDE' and $m->{Source}->{astNodeName} =~ /\/q[^\/]*$/) {
			return;
		}

		if ( $sourcename !~ s!.*(tdeio/|tdeparts/|dom/|tdeabc/|ksettings/|kjs/|tdetexteditor/|tdeprint/|tdesu/)(.*)!$1$2!m ) {
			$sourcename =~ s!.*/(.*)!$1!m;
		}
		if ( $sourcename eq '' ) {
			return;
		}
		$addInclude->{$sourcename} = 1;
	}
	
    if ($returnType eq 'void') {
    	$returnType = undef;
	} else {
	    # Detect objects returned by value
    	checkImportsForObject( $returnType, $addImport );
    	checkIncludesForObject( $returnType, $addInclude );
	}
	
	my $hasDuplicateSignature = 0;
	my $isStatic = $m->{Flags} =~ "s";
	my $isPure = $m->{Flags} =~ "p";
	
    return if ( $m->{SkipFromSwitch} && $m->{Flags} !~ "p" ); 

#    # Skip internal methods, which return unknown types
#    # Hmm, the C# bindings have a list of those too.
#    return if ( $returnType =~ m/TQGfx\s*\*/ );
#    return if ( $returnType eq 'CGContextRef' );
#    return if ( $returnType eq 'TQWSDisplay *' );
#    # This stuff needs callback, or **
#    return if ( $name eq 'defineIOHandler' or $name eq 'qt_init_internal' );
#    # Skip casting operators, but not == < etc.
#    return if ( $name =~ /operator \w+/ );
#    # TQFile's EncoderFn/DecoderFn
#    return if ( $name =~ /set[ED][ne]codingFunction/ );
#    # How to implement this? (TQXmlDefaultHandler/TQXmlEntityResolver::resolveEntity, needs A*&)
#    return if ( $name eq 'resolveEntity' and $className =~ /^TQXml/ );
#    return if ( $className eq 'TQBitArray' && $m->{Access} eq 'protected' );

    #print STDERR "Tests passed, generating.\n";


    my $argId = 0;

    my @argTypeList=();
    my @javaArgTypeList=();
    my @javaArgList = ();
    my @jniArgList = ();
    my @jniArgLocals = ();
    my @jniCleanups = ();
    my @namedArgTypeList=();
	
    foreach my $arg ( @{$m->{ParamList}} ) {
		$argId++;
	
		if ( $arg->{ArgName} =~ /^super$|^int$|^env$|^cls$|^obj$|^byte$/ ) {
			$arg->{ArgName} = "";
		}

		if ( $arg->{ArgName} =~ /^short$|^long$/ ) {
			# Oops looks like a parser error
			$arg->{ArgType} = $arg->{ArgName};
			$arg->{ArgName} = "";
		}
	
	print STDERR "  Param ".$arg->{astNodeName}." type: ".$arg->{ArgType}." name:".$arg->{ArgName}." default: ".$arg->{DefaultValue}." java: ".cplusplusToJava($arg->{ArgType})."\n" if ($debug);
		
	my $argType = $arg->{ArgType};
	my $namedArgType;
	my $javaArgType;
	my $javaArg;
	my $jniArg;
	my $jniLocal;
	my $jniCleanup;
	my $argName;
	
	if ( cplusplusToJava($argType) eq "" && $firstUnknownArgType > $argId ) {
		$firstUnknownArgType = $argId;
	}
	
	$javaArg = ($arg->{ArgName} eq "" ? "arg" . $argId : $arg->{ArgName});
	$namedArgType = $argType . " " . $javaArg;
	$javaArgType = cplusplusToJava($argType) . " " . $javaArg;
	($jniLocal, $jniArg, $jniCleanup) = jniArgTocplusplus($argType, $javaArg);
	
	push @argTypeList, $argType;
	push @javaArgTypeList, $javaArgType;
	push @javaArgList, $javaArg;
	push @jniArgLocals, $jniLocal;
	push @jniCleanups, $jniCleanup;
	push @jniArgList, $jniArg;
	push @namedArgTypeList, $namedArgType;
	
	# Detect objects passed by value
	checkImportsForObject( $argType, $addImport );
	checkIncludesForObject( $argType, $addInclude );
    }

	if ( $name eq 'TQApplication' or ($javaClassName eq 'TDECmdLineArgs' and $name eq 'init' and scalar(@javaArgList) > 1) ) {
		# Junk the 'int argc' parameter
		shift @javaArgTypeList;
		shift @javaArgList;
	}

    my @castedArgList = makeCastedArgList( @argTypeList );
     
    # We iterate as many times as we have default params
    my $firstDefaultParam = $m->{FirstDefaultParam};
    $firstDefaultParam = scalar(@argTypeList) unless defined $firstDefaultParam;
    my $iterationCount = scalar(@argTypeList) - $firstDefaultParam;

	my $jniReturnType = cplusplusToJNI($m->{ReturnType});
	# ArrayLists are jobjectArrays in args, but jobjects in return types
	$jniReturnType =~ s/jobjectArray/jobject/;
	
	my $javaReturnType = cplusplusToJava($m->{ReturnType});
	if ( $javaReturnType =~ s/StringBuffer/String/ ) {
		$jniReturnType =~ s/jobject/jstring/;
	} elsif ( $javaReturnType =~ s/String\[\]/ArrayList/ ) {
		$addImport->{"java.util.ArrayList"} = 1;
	}
	
	if ($m->{ReturnType} =~ /^int\&/) {
		$javaReturnType = 'int';
		$jniReturnType =~ s/jintArray/jint/;
	}
	
	if ($javaReturnType eq "") {
		$firstUnknownArgType = 0;
	}

    print STDERR "  ". ($iterationCount+1). " iterations for $name\n" if ($debug);
	
	my $javaSignature = javaMethodSignature( $m, @argTypeList );
	
	if ( defined $javaMethods->{$javaSignature} ) {
		$hasDuplicateSignature = 1;
	}
	
	my $docnode = $m->{DocNode};
	if ( $firstUnknownArgType >= 0 && $m->{Access} !~ /signals/ && ! $hasDuplicateSignature
		&& defined $docnode && ($generateConstructors || !$isConstructor) ) 
	{
		my $javadocComment = printJavadocComment( $docnode, "", "\t", "" );
		$methodCode .=  "\t/**" . $javadocComment . "*/\n" unless $javadocComment =~ /^\s*$/;
	}

    while($iterationCount >= 0) {
	
	$javaMethods->{$javaSignature} = 1;

	local($") = ",";
	
	if($firstUnknownArgType <= scalar(@argTypeList) || $hasDuplicateSignature || ($name =~ /^qObject$/) || $m->{Access} =~ /dcop/ ) {
		if ( $firstUnknownArgType <= scalar(@argTypeList) || $m->{Access} =~ /dcop/ ) {
			my $failedConversion = "\t// " . $m->{ReturnType} . " $name(@castedArgList[0..$#argTypeList]); >>>> NOT CONVERTED\n";
			if ( $m->{Access} =~ /signals/ ) {
				$signalCode .= $failedConversion;
			} else {
				$methodCode .= $failedConversion;
			}
		}
	} else {

#	    $jniCode .= "\tcase $methodNumber: ";
#	    if ($flags =~ "s" || $isConstructor) { # static or constructor
#	        $jniCode .= "$bridgeClassName\::";
#	    } else {
#	        $jniCode .= "xself->"
#	    }
#	    $jniCode .= "x_$methodNumber(args);";
#	    $jniCode .= "\tbreak;\n";

		if ($name eq 'find' and $javaClassName eq 'TQButtonGroup') {
			# Can't override a static method find() in TQWidget
			$name = "findButton";
		} elsif ( $name eq 'null' ) {
			$name = "nil";
		} elsif ( $name eq 'form' and $javaClassName =~ /^HTML/ ) {
			$name = "formElement";
		} elsif ( $name eq 'wait' and $javaClassName eq 'TDEProcess' ) {
			$name = "waitThread";
		} elsif ( $name eq 'finalize' and $javaClassName eq 'KMD5' ) {
			$name = "finalizeDigest";
		} elsif ( $name eq 'icon' and $javaClassName eq 'TQMessageBox' ) {
			$name = "iconId";
		} elsif ( $name eq 'icon' and $javaClassName eq 'KURLBarItemDialog' ) {
			$name = "iconName";
		} elsif ( $name eq 'iconText' and $javaClassName eq 'TDEToolBar' ) {
			$name = "iconTextId";
		} elsif ( $name eq 'reset' and $javaClassName eq 'KExtendedSocket' ) {
			$name = "resetSocket";
		} elsif ( $name eq 'palette' and $javaClassName eq 'KPaletteTable' ) {
			$name = "paletteName";
		} elsif ( $name eq 'size' and $javaClassName eq 'KAnimWidget' ) {
			$name = "iconSize";
		} elsif ( $name eq 'size' and $javaClassName eq 'TDEFontCombo' ) {
			$name = "pointSize";
		} elsif ($javaSignature eq "icon()" and $javaClassName eq 'TDEIconButton') {
			$name = "iconName";
		} elsif ($javaSignature eq "close()" and $javaClassName eq 'KDirOperator') {
			$name = "closeLoading";
		} elsif ($javaSignature eq "font()" and $javaClassName eq 'KCharSelect') {
			$name = "fontName";
		} elsif ($javaSignature eq "layout()" and $javaReturnType eq 'void') {
			$name = "updateLayout";
		} elsif ( $name eq 'sorting' and $javaReturnType eq 'boolean' ) {
			$name = "sortOnInsert";
		} elsif ($javaSignature eq "statusBar()" and $javaClassName =~ /^K/ ) {
	    	$name = "kstatusBar";
		} elsif ($javaSignature eq "menuBar()" and $javaClassName =~ /^K/ ) {
	    	$name = "kmenuBar";
		} elsif ( $name eq 'addLabel' and $javaClassName eq 'TQTableHeader' ) {
			$name = "addHeaderLabel";
		}

	    my $javaparams = join( ", ", @javaArgTypeList );
		my ( $jniSignature, $jniCall ) = jniMethodSignature( $m, 
															($isConstructor ? "new$name" : $name), 
															@argTypeList, $javaClassName, \@javaArgList );
			    
		my $cplusplusparams;
		my $i = 0;
		for my $arg (@argTypeList) {
			$cplusplusparams .= "," if $i++;
			$cplusplusparams .= "arg" . $i;
		}
	
	    if ($isConstructor) {
			if ( $generateConstructors && $mainClassNode->{CanBeInstanciated} ) {
	        	$jbridgeCode .= "\t$bridgeClassName(@castedArgList[0..$#argTypeList]) : $className($cplusplusparams) {};\n";
	        	
				$methodCode .= "\tpublic $javaClassName($javaparams) {\n";
				if ( $ancestorCount > 0 ) {
	        		$methodCode .= "\t\tsuper((Class) null);\n"
				}
				$methodCode .= "\t\tnew$javaClassName(@javaArgList[0..$#javaArgTypeList]);\n";
				$methodCode .= "\t}\n";
	    		$methodCode .= "\tprivate native void new$javaClassName($javaparams);\n";
	    		
				$jniCode = "JNIEXPORT void JNICALL\n";
	    		$jniCode .=  "$jniCall\n";
	    		$jniCode .= "{\n";
	    		$jniCode .= join( "", @jniArgLocals );
				$jniCode .= "\tif (QtSupport::getQt(env, obj) == 0) {\n";
	    		$jniCode .= "\t\tQtSupport::setQt(env, obj, new $bridgeClassName(" . join( ", ", @jniArgList ). "));\n";
	    		$jniCode .= "\t\tQtSupport::setObjectForQtKey(env, obj, QtSupport::getQt(env, obj));\n";
	    		$jniCode .= join( "", @jniCleanups );
	    		$jniCode .= "\t}\n\treturn;\n}\n\n";
				
				# Look for args which are are a TQQbject/slot string pair and replace with a java proxy slot
				if ($jniCode =~ s/QtSupport::getQt\(env, (receiver|recvr|pObjSlot)\), \(const char\*\) QtSupport::toCharString\(env, (member|slot|psMethodSlot), \&_qstring_(member|slot|psMethodSlot)\)/QtSupport::slotForReceiver(env, $1, $2), "1invoke()"/) {
					$jniCode =~ s/static TQCString\* _qstring_(member|slot|psMethodSlot) = 0;\n//;
				}
				
				$jniSignature =~ /^([^\)]*)\(.*/;
				if ($skippedJniMethods{$1}) {
					# Don't generate code for jni methods added as 'extras'
					$jniMethods->{$jniSignature} = "";
				} else {
					$jniMethods->{$jniSignature} = $jniCode;
				}
			}
	    } else {
			my $access = $m->{Access};
			$access =~ s/_slots//;
			
			if ( $access eq 'public' or $access eq 'protected' ) {
				if ( $name =~ /^takeItem$|^setPixmap$|^clearCell$|^setItem$|^item$|^minimumSize$/
					or $name =~ /^stepUp$|^stepDown$|^sectionFormattedText$|^addNumber$|^removeLastNumber$/
					or $name =~ /^cancel$|^setSource$|^paintCell$|^updateContents$|^sizeHint$|^setFocusSection$/
					or $name =~ /^event$|^eventFilter$|^copy$|^detach$|^showEvent$|^format$|^encodedData$/
					or $name =~ /^styleChange$|^insertItem$|^setStatus$|^setState$|^minimumSizeHint$/
					or $name =~ /^bytesPerLine$|^paintBranches$|^scanLine$|^ensureCursorVisible$|^setCursor$/
					or $name =~ /^updateGeometry$|^setState$|^exec$|^pixmap$|^areaPoints$|^draw$|^writeDir$/ ) {
					# These methods are public in some places, but protected in others,
					# so make them all public.
					$access = "public";
				}
				
				$methodCode .= "\t" . $access . (($isStatic or $classNode->{NodeType} eq 'namespace') ? " static " : " ") . "native ";
#	    		$methodCode .= ( $m->{Flags} =~ "v" || $isStatic ? "" : "final " );

				my $altReturnType = undef;
				if ($name =~ /^xForm$/ ) {
	    			$javaReturnType = "Object";
				} elsif ($javaSignature eq "layout()" and $javaReturnType ne 'void') {
	    			$altReturnType = "TQLayout";
				} elsif ($javaSignature eq "defaultFactory()" and $javaReturnType eq 'TQSqlEditorFactory') {
	    			$javaReturnType = "TQEditorFactory";
				} elsif ($javaSignature =~ /^bits|^scanLine/) {
	    			$javaReturnType = "byte[]";
				} elsif ($javaSignature eq "at()" and $javaClassName eq 'KFilterDev') {
	    			$javaReturnType = "long";
				} elsif ($javaSignature =~ /copyTo/ and $javaClassName eq "TDEDesktopFile" ) {
	    			$altReturnType = "TDEConfig";
				}
				
				if ( defined $altReturnType ) {
					checkImportsForObject( $altReturnType, $addImport );
					$javaReturnType = $altReturnType;
				}
	    		$methodCode .= $javaReturnType;
	    		$methodCode .= " $name($javaparams);\n";
				
				if ($access eq 'public' and !$isStatic) {
	    			$interfaceCode .= "\t\t$javaReturnType $name($javaparams);\n";
				}
				
				my $methodName = $m->{astNodeName};
				# Hack to stop calling super for TQWidget::polish() from looping
				if (	$m->{Access} =~ /public/ 
						&& $returnType eq '' 
						&& $m->{Flags} =~ "v" 
						&& $cplusplusparams eq ''
						&& $bridgeClassName  ne $className ) 
				{
					$methodName = "public_" . $m->{astNodeName};
	    			$jbridgeCode .= "\t";
	    			$jbridgeCode .= "void $methodName() {\n";
	    			$jbridgeCode .= "\t\t$className" . "::" . $m->{astNodeName} . "();\n";
	    			$jbridgeCode .= "\t\treturn;\n";
	    			$jbridgeCode .= "\t}\n";
				}
				
				if ($m->{Access} =~ /protected/) {
					$methodName = "protected_" . $m->{astNodeName};
	    			$jbridgeCode .= (($isStatic or $classNode->{NodeType} eq 'namespace') ? "\tstatic " : "\t");
					if ( $returnType eq '' ) {
	    				$jbridgeCode .= "void $methodName(@castedArgList[0..$#argTypeList]) {\n";
	    				$jbridgeCode .= "\t\t$className" . "::" . $m->{astNodeName} . "($cplusplusparams);\n";
	    				$jbridgeCode .= "\t\treturn;\n";
					} else {
	    				$jbridgeCode .= "$returnType $methodName(@castedArgList[0..$#argTypeList]) {\n";
	    				$jbridgeCode .= "\t\treturn ($returnType) $className" . "::" . $m->{astNodeName} . "($cplusplusparams);\n";
					}
	    			$jbridgeCode .= "\t}\n";
				
				}
				
				$jniCode = "JNIEXPORT $jniReturnType JNICALL\n";
				$jniCode .=  "$jniCall\n";
				$jniCode .= "{\n";
				my $selfstring;
				if ( $isStatic or $classNode->{NodeType} eq 'namespace' ) {
					$selfstring = $bridgeClassName . "::" . $methodName;
				} else {
					if ($m->{Access} =~ /protected/ || $methodName =~ /^public_/) {
						$selfstring = "(($bridgeClassName*) QtSupport::getQt(env, obj))->$methodName";
					} else {
						$selfstring = "(($className*)" . ($mainClassName eq $className ? "" : "($mainClassName*)") . " QtSupport::getQt(env, obj))->" . $m->{astNodeName};
					}
				}
				my ($locals, $fcall) = jniToReturnValue( $m->{ReturnType}, "$selfstring(" . join( ", ", @jniArgList ). ")", join( "", @jniCleanups ) );
				# Add dummy statements to avoid compiler warnings if needed
				$locals .= ($jniSignature =~ /jclass/ ? "\t(void) cls;\n" : "");
				$locals .= ($fcall !~ /env/ ? "\t(void) env;\n" : "");

				my $slotArgType = '';
				if ($name eq 'insertAnimatedWidget' or $name eq 'connectStatus' or $name eq 'disconnectStatus') {
					$slotArgType = 'int';
				} elsif ($name eq 'connectResize' or $name eq 'disconnectResize') {
					$slotArgType = 'const TQSize&';
				} elsif ($name eq 'connectUpdate' or $name eq 'disconnectUpdate') {
					$slotArgType = 'const TQRect&';
				}
				# Look for args which are are a TQQbject/slot string pair and replace with a java proxy slot
				
				$locals .= join( "", @jniArgLocals );
				
				if ($fcall =~ s/QtSupport::getQt\(env, (receiver|recvr|pObjSlot)\), \(const char\*\) QtSupport::toCharString\(env, (member|slot|psMethodSlot), \&_qstring_(member|slot|psMethodSlot)\)/QtSupport::slotForReceiver(env, $1, $2), "1invoke($slotArgType)"/) {
					$locals =~ s/static TQCString\* _qstring_(member|slot|psMethodSlot) = 0;\n//;
				}
				
				$jniCode .= $locals;
				
				if ($name eq 'readBlock') {
					$interfaceCode =~ s/String /StringBuffer /;
					$methodCode =~ s/String /StringBuffer /;
					$jniCode =~ s/jstring/jobject/;
					$jniCode =~ /(jlong|jint) (\w+)\)/;
					my $arg2 = $2;
					$jniCode =~ s/_qstring_(\w+) = 0;\n/_qstring_$1 = 0;\n\tif \(_qstring_$1 == 0\) { _qstring_$1 = new TQCString\(\); }\n\t_qstring_$1->resize\(\(uint\) $arg2\);\n/;
					my $arg1 = $1;
					$fcall =~ s/QtSupport::toCharString\([^\)]*\)/_qstring_$arg1->data()/;
					$fcall =~ s/return xret;/QtSupport::fromTQCStringToStringBuffer(env, _qstring_$arg1, $arg1);\n\treturn xret;/;
				}

				$jniCode .= $fcall;
				$jniCode .= "}\n\n";
				
				if ($isPure && $m->{Access} =~ /protected/) {
					# Can't do a lot with implementing these, so give up
					$jniCode = "";
					$jbridgeCode = "";
				}
				
				$jniSignature =~ /^([^\)]*)\(.*/;
				if ($skippedJniMethods{$1}) {
					# Don't generate code for jni methods added as 'extras'
					$jniMethods->{$jniSignature} = "";
				} else {
					$jniMethods->{$jniSignature} = $jniCode;
				}
			} else {
				if ( $access =~ /signals/ )  {
					my $docnode = $m->{DocNode};
					if ( defined $docnode ) {
						my $javadocComment = printJavadocComment( $docnode, "", "\t", "" );
						$signalCode .=  "\t/**" . $javadocComment . "*/\n" unless $javadocComment =~ /^\s*$/;
					}
	    			$signalCode .= "\tvoid $name($javaparams);\n";
				}
			}
	    }
    }

	pop @argTypeList;
	pop @javaArgTypeList;
	pop @javaArgList;
	pop @jniArgList;
	pop @jniArgLocals;
	pop @jniCleanups;
	
	$javaSignature = javaMethodSignature( $m, @argTypeList );
	$hasDuplicateSignature = (defined $javaMethods->{$javaSignature} ? 1 : 0);
	
	$methodNumber++;
	$iterationCount--;
    } # Iteration loop

    return ( $methodCode, $interfaceCode, $signalCode, $jbridgeCode );
}


sub generateEnum($$$)
{
    my( $classNode, $m, $generateAnonymous ) = @_;	# input
    my $methodCode = '';	# output

    my @heritage = kdocAstUtil::heritage($classNode);
    my $className  = join( "::", @heritage );
    my $javaClassName  = $classNode->{astNodeName};

	if ( ($generateAnonymous and $m->{astNodeName} ) or (! $generateAnonymous and ! $m->{astNodeName}) ) {
		return;
	}
	
	if ( defined $m->{DocNode} ) {
		my $javadocComment = printJavadocComment( $m->{DocNode}, "", "\t", "" );
		$methodCode .=  "\t/**" . $javadocComment . "*/\n" unless $javadocComment =~ /^\s*$/;
	}
	
	my @enums = split(",", $m->{Params});
	my $enumCount = 0;
	foreach my $enum ( @enums ) {
		$enum =~ s/\s//g;
		$enum =~ s/::/./g;
		$enum =~ s/\(mode_t\)//;
		if ( $enum =~ /(.*)=([-0-9]+)$/ ) {
			$methodCode .= "\tpublic static final int $1 = $2;\n";
			$enumCount = $2;
			$enumCount++;
		} elsif ( $enum =~ /(.*)=(.*)/ ) {
			$methodCode .= "\tpublic static final int $1 = $2;\n";
		} else {
			$methodCode .= "\tpublic static final int $enum = $enumCount;\n";
			$enumCount++;
		}
	}
		
	$methodCode .= "\n";
	$methodNumber++;
		
    return ( $methodCode );
}

sub generateVar($$$)
{
    my( $classNode, $m, $addImport ) = @_;	# input
    my $methodCode = '';	# output
    my $interfaceCode = '';	# output

    my @heritage = kdocAstUtil::heritage($classNode);
    my $className  = join( "::", @heritage );
    my $javaClassName  = $classNode->{astNodeName};

    my $name = $m->{astNodeName};
    my $varType = $m->{Type};
    $varType =~ s/static\s//;
    $varType =~ s/const\s+(.*)\s*&/$1/;
    $varType =~ s/\s*$//;
    my $fullName = "$className\::$name";

    checkImportsForObject( $varType, $addImport );

#    die "Invalid index for $fullName: $classNode->{case}{$fullName} instead of $methodNumber" if $classNode->{case}{$fullName} != $methodNumber;
#    $methodCode .= "    static void x_$methodNumber(Smoke::Stack x) {\n";
#    $methodCode .= "\tx[0].s_class = (void*)new $varType($fullName);\n";
#    $methodCode .= "    }\n";
    
#	if ( ($name !~ /^null$/) && (cplusplusToJava($varType) ne "") ) {
	if ( ($name !~ /^null$/) && (cplusplusToJava($varType) ne "" ) ) {
#		$interfaceCode .= "\t\t". cplusplusToJava($varType) . " $name();\n";
	
#		$methodCode .= "\tpublic native static ". cplusplusToJava($varType) . " $name();\n";
    }

	$methodNumber++;
    return ( $methodCode, $interfaceCode );
}

## Called by writeClassDoc
sub generateAllMethods($$$$$$$$)
{
    my ($classNode, $ancestorCount, $javaMethods, $jniMethods, $mainClassNode, $generateConstructors, $addImport, $addInclude) = @_;
    my $methodCode = '';
	my $interfaceCode = '';
    my $signalCode = '';
    my $jbridgeCode = '';
    $methodNumber = 0;
    #my $className = $classNode->{astNodeName};
    my $className = join( "::", kdocAstUtil::heritage($classNode) );
	my $javaClassName = $mainClassNode->{astNodeName};
    my $jniClassName = ($classNode->{astNodeName} =~ /^Q/ ? "Java_org_trinitydesktop_qt_" : "Java_org_trinitydesktop_koala_") . $classNode->{astNodeName};
	# If the C++ class had multiple inheritance, then the code for all but one of the
	# parents must be copied into the code for javaClassName. Hence, for TQWidget current
	# classname might be TQPaintDevice, as its methods are needed in TQWidget.
	my $currentClassName = join( ".", kdocAstUtil::heritage($classNode) );

    my $sourcename = $classNode->{Source}->{astNodeName};
    
	if ( $sourcename !~ s!.*(tdeio/|tdeparts/|dom/|tdeabc/|ksettings/|kjs/|tdetexteditor/|tdeprint/|tdesu/)(.*)!$1$2!m ) {
    	$sourcename =~ s!.*/(.*)!$1!m;
	}
#    die "Empty source name for $classNode->{astNodeName} $classNode->{Source}->{astNodeName}" if ( $sourcename eq '' );
	
	if ($classNode->{astNodeName} ne $main::globalSpaceClassName && $sourcename ne '') {
    	$addInclude->{$sourcename} = 1;
#		my $s;
#        for my $sn( @{$classNode->{Sources}} ) {
#    	if ( ($s = $sn->{astNodeName}) !~ s!.*(tdeio/|tdeparts/|dom/|tdeabc/|ksettings/|kjs/|tdetexteditor/|tdeprint/|tdesu/)(.*)!$1$2!m ) {
#    		$s =~ s!.*/(.*)!$1!m;
#		}
#		$addInclude->{$s} = 1;
#        }
	}
	
    $addImport->{"org.trinitydesktop.qt.QtSupport"} = 1;
	
    # Do all enums first, anonymous ones and then named enums
    Iter::MembersByType ( $classNode, undef,
			  sub {	my ($classNode, $methodNode ) = @_;
				
	if ( $methodNode->{NodeType} eq 'enum' and $currentClassName eq $javaClassName ) {
	    my ($meth) = generateEnum( $classNode, $methodNode, 1 );
	    $methodCode .= $meth;
	}
				}, undef );
				
    Iter::MembersByType ( $classNode, undef,
			  sub {	my ($classNode, $methodNode ) = @_;
				
	if ( $methodNode->{NodeType} eq 'enum' and $currentClassName eq $javaClassName ) {
	    my ($meth) = generateEnum( $classNode, $methodNode, 0 );
	    $methodCode .= $meth;
	}
				}, undef );

    # Then all static vars
    Iter::MembersByType ( $classNode, undef,
			  sub {	my ($classNode, $methodNode ) = @_;
				
	if ( $methodNode->{NodeType} eq 'var' and $currentClassName eq $javaClassName ) {
	    my ($meth, $interface) = generateVar( $classNode, $methodNode, $addImport );
	    $methodCode .= $meth;
#	    $interfaceCode .= $interface;
	}
				}, undef );

    # Then all methods
    Iter::MembersByType ( $classNode, undef,
			  sub {	my ($classNode, $methodNode ) = @_;

        if ( $methodNode->{NodeType} eq 'method' ) {
	    	my ($meth, $interf, $signals, $jbridge) = generateMethod( $classNode, $methodNode, $addImport, $addInclude, $ancestorCount, $javaMethods, $jniMethods, $mainClassNode, $generateConstructors );
	    	$methodCode .= $meth;
			$interfaceCode .= $interf;
			$signalCode .= $signals;
	    	$jbridgeCode .= $jbridge;
#	    	$jniCode .= $jni;
		}
			      }, undef );
    
	# Virtual methods
#    if ($classNode->{BindingDerives}) {
#	my %virtualMethods;
#	allVirtualMethods( $classNode, \%virtualMethods );

#	for my $sig (sort keys %virtualMethods) {
#            my ($meth) = generateVirtualMethod( $classNode, $sig, $virtualMethods{$sig}{method}, $virtualMethods{$sig}{class}, \%addImport );
#	    $methodCode .= $meth;
#	}
#    }

    # Destructor
    # "virtual" is useless, if the base class has a virtual destructor then the x_* class too.
    #if($classNode->{HasVirtualDestructor} and $classNode->{HasDestructor}) {
    #	$methodCode .= "    virtual ~$bridgeClassName() {}\n";
    #}
    # We generate a dtor though, because we might want to add stuff into it
	
    if ($currentClassName eq $javaClassName and $classNode->{CanBeInstanciated} and $classNode->{HasPublicDestructor}) {
    	if ( $generateConstructors ) {
			my $jniCode;
			my $jniSignature;
			
			$jbridgeCode .= "\t~$className" . "JBridge() {QtSupport::qtKeyDeleted(this);}\n";
			$methodCode .= "\t/** Deletes the wrapped C++ instance */\n";
			$methodCode .= "\tprotected native void finalize() throws InternalError;\n";
			
			$jniSignature = $jniClassName . "_finalize";
			$jniCode = "JNIEXPORT void JNICALL\n$jniSignature(JNIEnv* env, jobject obj)\n{";

			if ( is_kindof($classNode, 'TQCheckListItem') ) {
				$jniCode .= "\n\tif (QtSupport::allocatedInJavaWorld(env, obj) && ((TQCheckListItem*)($className*)QtSupport::getQt(env, obj))->parent() == 0 && ((TQCheckListItem*)($className*)QtSupport::getQt(env, obj))->listView() == 0) {\n";
			} elsif ( $classNode->{astNodeName} =~ /^KFileTreeViewToolTip$/ ) {
				$jniCode .= "\n\tif (QtSupport::allocatedInJavaWorld(env, obj) && (($className*)QtSupport::getQt(env, obj))->parentWidget() == 0) {\n";
			} elsif ( is_kindof($classNode, 'TQTableItem')) {
				$jniCode .= "\n\tif (QtSupport::allocatedInJavaWorld(env, obj) && ((TQTableItem*)($className*)QtSupport::getQt(env, obj))->table() == 0) {\n";
			} elsif ( is_kindof($classNode, 'TQPopupMenu')) {
				if ($main::qt_embedded) {
					$jniCode .= "\n\tif (QtSupport::allocatedInJavaWorld(env, obj) && ((TQPopupMenu*)($className*)QtSupport::getQt(env, obj))->parentWidget() == 0) {\n";
				} else {
					$jniCode .= "\n\tif (QtSupport::allocatedInJavaWorld(env, obj) && ((TQPopupMenu*)($className*)QtSupport::getQt(env, obj))->parentWidget(false) == 0) {\n";
				}
			} elsif ( is_kindof($classNode, 'TQListViewItem') ) {
				$jniCode .= "\n\tif (QtSupport::allocatedInJavaWorld(env, obj) && ((TQListViewItem*)($className*)QtSupport::getQt(env, obj))->parent() == 0 && ((TQListViewItem*)($className*)QtSupport::getQt(env, obj))->listView() == 0) {\n";
			} elsif ( is_kindof($classNode, 'TQIconViewItem')) {
				$jniCode .= "\n\tif (QtSupport::allocatedInJavaWorld(env, obj) && ((TQIconViewItem*)($className*)QtSupport::getQt(env, obj))->iconView() == 0) {\n";
			} elsif ( is_kindof($classNode, 'TQLayoutItem')) {
				$jniCode .= "\n\tif (QtSupport::allocatedInJavaWorld(env, obj) && ((TQLayoutItem*)($className*)QtSupport::getQt(env, obj))->layout() == 0 && ((TQLayoutItem*)($className*)QtSupport::getQt(env, obj))->widget() == 0 && ((TQLayoutItem*)($className*)QtSupport::getQt(env, obj))->spacerItem() == 0) {\n";
			} elsif ( $classNode->{astNodeName} =~ /^KSpell$|^KReplace$/ ) {
				$jniCode .= "\n\tif (QtSupport::allocatedInJavaWorld(env, obj)) {\n";
			} elsif ( $classNode->{astNodeName} =~ /^TQWidget$/  || defined kdocAstUtil::findOverride( $rootnode, $classNode, "parentWidget" ) ) {
				if ($main::qt_embedded) {
					$jniCode .= "\n\tif (QtSupport::allocatedInJavaWorld(env, obj) && ((TQWidget*)($className*)QtSupport::getQt(env, obj))->parentWidget() == 0) {\n";
				} else {
					$jniCode .= "\n\tif (QtSupport::allocatedInJavaWorld(env, obj) && ((TQWidget*)($className*)QtSupport::getQt(env, obj))->parentWidget(true) == 0) {\n";
				}
			} elsif ( $classNode->{astNodeName} =~ /^TQObject$/  || defined kdocAstUtil::findOverride( $rootnode, $classNode, "parent" ) ) {
				$jniCode .= "\n\tif (QtSupport::allocatedInJavaWorld(env, obj) && (($className*)QtSupport::getQt(env, obj))->parent() == 0) {\n";
			} else {
				$jniCode .= "\n\tif (QtSupport::allocatedInJavaWorld(env, obj)) {\n";
			}
			
			if ($classNode->{astNodeName} !~ /^Q.*Style$/) {
				$jniCode .= "\t\tdelete ($className*)QtSupport::getQt(env, obj);\n";
			}
			
			$jniCode .= "\t\tQtSupport::setQt(env, obj, 0);\n\t}\n\treturn;\n}\n\n";
			$jniMethods->{$jniSignature} = $jniCode;
    
#			$interfaceCode .= "\t\tvoid dispose();\n";
			$methodCode .= "\t/** Delete the wrapped C++ instance ahead of finalize() */\n";
			$methodCode .= "\tpublic native void dispose();\n";
    
#			$interfaceCode .= "\t\tboolean isDisposed();\n";
			$methodCode .= "\t/** Has the wrapped C++ instance been deleted? */\n";
			$methodCode .= "\tpublic native boolean isDisposed();\n";
			

			$jniSignature = $jniClassName . "_dispose";
			$jniCode = "JNIEXPORT void JNICALL\n$jniSignature(JNIEnv* env, jobject obj)\n{";
			$jniCode .= "\n\t$jniClassName" . "_finalize(env, obj);\n\treturn;\n}\n\n";
			$jniMethods->{$jniSignature} = $jniCode;
			
			$jniSignature = $jniClassName . "_isDisposed";
			$jniCode = "JNIEXPORT jboolean JNICALL\n$jniSignature(JNIEnv* env, jobject obj)\n{";
			$jniCode .= "\n\treturn (QtSupport::getQt(env, obj) == 0);\n}\n\n";
			$jniMethods->{$jniSignature} = $jniCode;
		}
#	die "$className destructor: methodNumber=$methodNumber != case entry=".$classNode->{case}{"~$className()"}."\n"
#	     if $methodNumber != $classNode->{case}{"~$className()"};
			$methodNumber++;
    }
                                                               
    return ( $methodCode, $interfaceCode, $signalCode, $jbridgeCode );
}

sub virtualMethodCallbacks
{
	my( $node ) = @_;
	my $jbridgeCode = ''; # output
	my %allmem = ();
	my $key;

	my $m;
	my $name;
	my $isTQObject = is_kindof($node, 'TQObject');
	
	kdocAstUtil::allMembers( \%allmem, $node );

	foreach $key (keys (%allmem)) {
		$m = $allmem{$key};
		$name = $m->{astNodeName} ;
		my $type = $m->{NodeType};
		my $docnode = $m->{DocNode};
		my $parent = $m->{Parent};
		
		if (	$type eq "method" && ($m->{Flags} =~ "v" || $name =~ /^.*Event$/) && !$m->{SkipFromSwitch}
				&& $m->{Access} =~ /public|protected/
				&& $name !~ /qwsEvent/ && $name !~ /x11Event/ && $name !~ /winEvent/ 
				&& $name !~ /macEvent/ && $name !~ /movableDropEvent/ ) 
		{
			my @argTypeList = ();
			my @castedArgList;
			my $i = 0;
			my $cplusplusparams;
			foreach my $arg ( @{$m->{ParamList}} ) {
				my $argType = $arg->{ArgType};
				push @argTypeList, $argType;
				$cplusplusparams .= "," if $i++;
				$cplusplusparams .= "arg" . $i;
			}

			my $qobjectType = $node->{astNodeName};
			$qobjectType =~ s/(.*)\*.*$/$1/;
			$qobjectType =~ s/^([^Q].*)/org.trinitydesktop.koala.$1/;
			$qobjectType =~ s/^(Q.*)/org.trinitydesktop.qt.$1/;
			if( $m->{ReturnType} eq 'void' && $#argTypeList eq 0 
				&& cplusplusToJNISignature( @argTypeList[0] ) =~ /Lorg_trinitydesktop/
				&& $isTQObject )
			{
				@castedArgList = makeCastedArgList( @argTypeList );
				my $eventType = cplusplusToJava( @argTypeList[0] );
				$eventType =~ s/(.*)\*.*$/$1/;
				$eventType =~ s/^([^Q].*)/org.trinitydesktop.koala.$1/;
				$eventType =~ s/^(Q.*)/org.trinitydesktop.qt.$1/;
				$jbridgeCode .= "\tvoid $name(@castedArgList[0..$#argTypeList]) {\n";
				$jbridgeCode .= "\t\tif (!QtSupport::eventDelegate(this,\"$name\",(void*)" . (@argTypeList[0] =~ /\*/ ? "" : "&") . "arg1,\"$eventType\")) {\n";
				$jbridgeCode .= "\t\t\t" . $parent->{astNodeName} . "::" . "$name(arg1);\n";
				$jbridgeCode .= "\t\t}\n";
				$jbridgeCode .= "\t\treturn;\n\t}\n";
			} elsif( $name =~ /eventFilter$/ and $isTQObject and $#argTypeList eq 1) {
				$jbridgeCode .= "\tbool eventFilter(TQObject* object,TQEvent* event) {\n";
				$jbridgeCode .= "\t\tif (!QtSupport::eventFilterDelegate(this,\"$qobjectType\",object,event)) {\n";
				$jbridgeCode .= "\t\t\treturn " . $parent->{astNodeName} . "::eventFilter(object,event);\n";
				$jbridgeCode .= "\t\t} else {\n";
				$jbridgeCode .= "\t\t\treturn TRUE;\n";
				$jbridgeCode .= "\t\t}\n\t}\n";
			} elsif( $name =~ /^fixup$/ and $node->{astNodeName} eq 'TQValidator' ) {
				$jbridgeCode .= "\tTQValidator::State validate(TQString& input,int& pos) const\n";
				$jbridgeCode .= "\t{\n";
				$jbridgeCode .= "\t\treturn (TQValidator::State) QtSupport::validateDelegate((TQValidator*)this,input,pos);\n";
				$jbridgeCode .= "\t}\n";
				$jbridgeCode .= "\tvoid fixup(TQString& input) const\n";
				$jbridgeCode .= "\t{\n";
				$jbridgeCode .= "\t\tQtSupport::fixupDelegate((TQValidator*) this, input);\n";
				$jbridgeCode .= "\t\treturn;\n\t}\n";
			} elsif( $m->{ReturnType} eq 'void' and $#argTypeList eq -1 and $isTQObject) {
				$jbridgeCode .= "\tvoid $name() {\n";
				$jbridgeCode .= "\t\tif (!QtSupport::voidDelegate(this,\"$qobjectType\",\"$name\")) {\n";
				$jbridgeCode .= "\t\t\t" . $parent->{astNodeName} . "::$name();\n";
				$jbridgeCode .= "\t\t}\n";
				$jbridgeCode .= "\t\treturn;\n\t}\n";
			} elsif( cplusplusToJava( $m->{ReturnType} ) eq 'boolean' and $#argTypeList eq -1 and $isTQObject ) {
				$jbridgeCode .= "\t" . $m->{ReturnType} . " $name() {\n";
				$jbridgeCode .= "\t\treturn QtSupport::booleanDelegate(this,\"$name\");\n";
				$jbridgeCode .= "\t}\n";
			}
		}
	}
	
	return $jbridgeCode;
}

# Return 0 if the class has no virtual dtor, 1 if it has, 2 if it's private
sub hasVirtualDestructor($)
{
    my ( $classNode ) = @_;
    my $className = join( "::", kdocAstUtil::heritage($classNode) );
    return if ( $skippedClasses{$className} );

    my $parentHasIt;
    # Look at ancestors, and (recursively) call hasVirtualDestructor for each
    # It's enough to have one parent with a prot/public virtual dtor
    Iter::Ancestors( $classNode, $rootnode, undef, undef, sub {
                     my $vd = hasVirtualDestructor( $_[0] );
                     $parentHasIt = $vd unless $parentHasIt > $vd;
                    } );
    return $parentHasIt if $parentHasIt; # 1 or 2

    # Now look in $classNode - including private methods
    my $doPrivate = $main::doPrivate;
    $main::doPrivate = 1;
    my $result;
    Iter::MembersByType ( $classNode, undef,
		sub {	my ($classNode, $m ) = @_;
			return unless( $m->{NodeType} eq "method" && $m->{ReturnType} eq '~' );

			if ( $m->{Flags} =~ /[vp]/ ) {
			    if ( $m->{Access} =~ /private/ ) {
				$result=2; # private virtual
			    } else {
				$result=1; # [protected or public] virtual
			    }
			}
		},
		undef
	);
    $main::doPrivate = $doPrivate;
    $result=0 if (!defined $result);
    return $result;
}

=head2 allVirtualMethods

	Parameters: class node, dict

	Adds to the dict, for all method nodes that are virtual, in this class and in parent classes :
        {method} the method node, {class} the class node (the one where the virtual is implemented)

=cut

sub allVirtualMethods($$)
{
    my ( $classNode, $virtualMethods ) = @_;
    my $className = join( "::", kdocAstUtil::heritage($classNode) );
    return if ( $skippedClasses{$className} );

    # Look at ancestors, and (recursively) call allVirtualMethods for each
    # This is done first, so that virtual methods that are reimplemented as 'private'
    # can be removed from the list afterwards (below)
    Iter::Ancestors( $classNode, $rootnode, undef, undef, sub {
			 allVirtualMethods( @_[0], $virtualMethods );
		     }, undef
		   );

    # Now look for virtual methods in $classNode - including private ones
    my $doPrivate = $main::doPrivate;
    $main::doPrivate = 1;
    Iter::MembersByType ( $classNode, undef,
		sub {	my ($classNode, $m ) = @_;
			# Only interested in methods, and skip destructors
			return unless( $m->{NodeType} eq "method" && $m->{ReturnType} ne '~' );

			my $signature = methodSignature( $m, $#{$m->{ParamList}} );
			print STDERR $signature . " ($m->{Access})\n" if ($debug);

			# A method is virtual if marked as such (v=virtual p=pure virtual)
			# or if a parent method with same signature was virtual
			if ( $m->{Flags} =~ /[vp]/ or defined $virtualMethods->{$signature} ) {
			    if ( $m->{Access} =~ /private/ ) {
				if ( defined $virtualMethods->{$signature} ) { # remove previously defined
				    delete $virtualMethods->{$signature};
				}
				# else, nothing, just ignore private virtual method
			    } else {
				$virtualMethods->{$signature}{method} = $m;
				$virtualMethods->{$signature}{class} = $classNode;
			    }
			}
		},
		undef
	);
    $main::doPrivate = $doPrivate;
}

# Known typedef? If so, apply it.
sub applyTypeDef($)
{
    my $type = shift;
    # Parse 'const' in front of it, and '*' or '&' after it
    my $prefix = $type =~ s/^const\s+// ? 'const ' : '';
    my $suffix = $type =~ s/\s*([\&\*]+)$// ? $1 : '';

    if (exists $typedeflist{$type}) {
	return $prefix.$typedeflist{$type}.$suffix;
    }
    return $prefix.$type.$suffix;
}

# Register type ($1) into %allTypes if not already there
sub registerType($$) {
    my $type = shift;
    #print "registerType: $type\n" if ($debug);

    $type =~ s/\s+const$//; # for 'char* const'
    $type =~ s/\s+const\s*\*$/\*/; # for 'char* const*'

    return if ( $type eq 'void' or $type eq '' or $type eq '~' );
    die if ( $type eq '...' );     # ouch

    # Let's register the real type, not its known equivalent
    #$type = applyTypeDef($type);

    # Enum _value_ -> get corresponding type
    if (exists $enumValueToType{$type}) {
	$type = $enumValueToType{$type};
    }

    # Already in allTypes
    if(exists $allTypes{$type}) {
        return;
    }

    die if $type eq 'TQTextEdit::UndoRedoInfo::Type';
    die if $type eq '';

    my $realType = $type;

    # Look for references (&) and pointers (* or **)  - this will not handle *& correctly.
    # We do this parsing here because both the type list and iterproto need it
    if($realType =~ s/&$//) {
	$allTypes{$type}{typeFlags} = 'Smoke::tf_ref';
    }
    elsif($realType ne 'void*' && $realType =~ s/\*$//) {
	$allTypes{$type}{typeFlags} = 'Smoke::tf_ptr';
    }
    else {
	$allTypes{$type}{typeFlags} = 'Smoke::tf_stack';
    }

    if ( $realType =~ s/^const\s+// ) { # Remove 'const'
	$allTypes{$type}{typeFlags} .= ' | Smoke::tf_const';
    }

    # Apply typedefs, and store the resulting type.
    # For instance, if $type was TQ_UINT16&, realType will be ushort
    $allTypes{$type}{realType} = applyTypeDef( $realType );

    # In the first phase we only create entries into allTypes.
    # The values (indexes) are calculated afterwards, once the list is full.
    $allTypes{$type}{index} = -1;
    #print STDERR "Register $type. Realtype: $realType\n" if($debug);
}

# Get type from %allTypes
# This returns a hash with {index}, {isEnum}, {typeFlags}, {realType}
# (and {typeId} after the types array is written by writeSmokeDataFile)
sub findTypeEntry($) {
    my $type = shift;
    my $typeIndex = -1;
    $type =~ s/\s+const$//; # for 'char* const'
    $type =~ s/\s+const\s*\*$/\*/; # for 'char* const*'

    return undef if ( $type =~ '~' or $type eq 'void' or $type eq '' );

    # Enum _value_ -> get corresponding type
    if (exists $enumValueToType{$type}) {
	$type = $enumValueToType{$type};
    }

    die "type not known: $type" unless defined $allTypes{$type};
    return $allTypes{ $type };
}

# List of all java super-classes for a given class, via single inheritance. 
# Excluding any which are mapped onto interfaces to avoid multiple inheritance.
sub direct_superclass_list($)
{
    my $classNode = shift;
    my @super;
	my $has_ancestor = 0;
	my $direct_ancestor = undef;
	my $name;
	
    Iter::Ancestors( $classNode, $rootnode, undef, undef, sub {
			( $direct_ancestor, $name ) = @_;
			if ($name =~ /TQMemArray|TQSqlFieldInfoList/) {
				# Template classes, give up for now..
				$has_ancestor = 1;
			} elsif (kalyptusDataDict::interfacemap($name) eq "") {
				push @super, $direct_ancestor;
				push @super, direct_superclass_list( $direct_ancestor );
				$has_ancestor = 1;
			}
		     }, undef );
	
	if (! $has_ancestor and defined $direct_ancestor) {
		push @super, $direct_ancestor;
    	push @super, direct_superclass_list( $direct_ancestor );
	}
	
	return @super;
}

# List of all super-classes for a given class
sub superclass_list($)
{
    my $classNode = shift;
    my @super;
    Iter::Ancestors( $classNode, $rootnode, undef, undef, sub {
			push @super, @_[0];
			push @super, superclass_list( @_[0] );
		     }, undef );
    return @super;
}

sub is_kindof($$)
{
    my $classNode = shift;
	my $className = shift;
	
	if ($classNode->{astNodeName} eq $className) {
		return 1;
	}
	
	my @superclasses = superclass_list($classNode);
	foreach my $ancestor (@superclasses) {
		if ($ancestor->{astNodeName} eq $className) {
			return 1;
		}
	}
	
	return 0;
}

# Store the {case} dict in the class Node (method signature -> index in the "case" switch)
# This also determines which methods should NOT be in the switch, and sets {SkipFromSwitch} for them
sub prepareCaseDict($) {

     my $classNode = shift;
     my $className = join( "::", kdocAstUtil::heritage($classNode) );
     $classNode->AddProp("case", {});
     my $methodNumber = 0;

     # First look at all enums for this class
     Iter::MembersByType ( $classNode, undef,
		sub {	my ($classNode, $m ) = @_;

	next unless $m->{NodeType} eq 'enum';
	foreach my $val ( @{$m->{ParamList}} ) {
	    my $fullEnumName = "$className\::".$val->{ArgName};
	    print STDERR "Enum: $fullEnumName -> case $methodNumber\n" if ($debug);
	    $classNode->{case}{$fullEnumName} = $methodNumber;
	    $enumValueToType{$fullEnumName} = "$className\::$m->{astNodeName}";
	    $methodNumber++;
	}
		      }, undef );

     # Check for static vars
     Iter::MembersByType ( $classNode, undef,
		sub {	my ($classNode, $m ) = @_;

	    next unless $m->{NodeType} eq 'var';
	    my $name = "$className\::".$m->{astNodeName};			
	    print STDERR "Var: $name -> case $methodNumber\n" if ($debug);
	    $classNode->{case}{$name} = $methodNumber;
	    $methodNumber++;

		      }, undef );


     # Now look at all methods for this class
     Iter::MembersByType ( $classNode, undef,
		sub {	my ($classNode, $m ) = @_;

	next unless $m->{NodeType} eq 'method';
	my $name = $m->{astNodeName};
        my $isConstructor = ($name eq $classNode->{astNodeName} );
	if ($isConstructor and ($m->{ReturnType} eq '~')) # destructor
	{
	    # Remember whether we'll generate a switch entry for the destructor
	    $m->{SkipFromSwitch} = 1 unless ($classNode->{CanBeInstanciated} and $classNode->{HasPublicDestructor});
	    next;
	}

        # Don't generate bindings for protected methods (incl. signals) if
        # we're not deriving from the C++ class. Only take public and public_slots
        my $ok = ( $classNode->{BindingDerives} or $m->{Access} =~ /public/ ) ? 1 : 0;

        # Don't generate bindings for pure virtuals - we can't call them ;)
        $ok = 0 if ( $ok && $m->{Flags} =~ "p" );

        # Bugfix for Qt-3.0.4: those methods are NOT implemented (report sent).
        $ok = 0 if ( $ok && $className eq 'TQLineEdit' && ( $name eq 'setPasswordChar' || $name eq 'passwordChar' ) );
        $ok = 0 if ( $ok && $className eq 'TQWidgetItem' && $name eq 'widgetSizeHint' );

        if ( !$ok )
        {
	    #print STDERR "Skipping $className\::$name\n" if ($debug);
	    $m->{SkipFromSwitch} = 1;
	    next;
	}

	my @args = @{ $m->{ParamList} };
	my $last = $m->{FirstDefaultParam};
	$last = scalar @args unless defined $last;
	my $iterationCount = scalar(@args) - $last;
	while($iterationCount >= 0) {
	    my $sig = methodSignature( $m, $#args );
	    $classNode->{case}{$sig} = $methodNumber;
	    #print STDERR "prepareCaseDict: registered case number $methodNumber for $sig in $className()\n" if ($debug);
	    pop @args;
	    $iterationCount--;
	    $methodNumber++;
	}
		    }, undef );

    # Add the destructor, at the end
    if ($classNode->{CanBeInstanciated} and $classNode->{HasPublicDestructor}) {
        $classNode->{case}{"~$className()"} = $methodNumber;
	# workaround for ~Sub::Class() being seen as Sub::~Class()
	$classNode->{case}{"~$classNode->{astNodeName}()"} = $methodNumber;
	#print STDERR "prepareCaseDict: registered case number $methodNumber for ~$className()\n" if ($debug);
    }
}

sub writeSmokeDataFile($) {
    my $rootnode = shift;

    # Make list of classes
    my %allImports; # list of all header files for all classes
    my @classlist;
    push @classlist, ""; # Prepend empty item for "no class"
    my %enumclasslist;
    Iter::LocalCompounds( $rootnode, sub {
	my $classNode = $_[0];
	my $className = join( "::", kdocAstUtil::heritage($classNode) );
	
	return if $classNode->{NodeType} eq 'namespace';
	
	push @classlist, $className;
	$enumclasslist{$className}++ if keys %{$classNode->{enumerations}};
	$classNode->{ClassIndex} = $#classlist;
	addImportForClass( $classNode, \%allImports, undef );
    } );

    my %classidx = do { my $i = 0; map { $_ => $i++ } @classlist };

    my $file = "$outputdir/smokedata.cpp";
#    open OUT, ">$file" or die "Couldn't create $file\n";

#    foreach my $incl (sort{ 
#                           return 1 if $a=~/qmotif/;  # move qmotif* at bottom (they include dirty X11 headers)
#                           return -1 if $b=~/qmotif/;
#			   return -1 if substr($a,0,1) eq 'q' and substr($b,0,1) ne 'q'; # move Qt headers on top
#			   return 1 if substr($a,0,1) ne 'q' and substr($b,0,1) eq 'q';			   
#                           $a cmp $b
#                          } keys %allIncludes) {
#	die if $imp eq '';
#	print OUT "import $imp;\n";
#    }	

#    print OUT "\n";

    print STDERR "Writing ${libname}_cast function\n" if ($debug);

    # Prepare descendants information for each class
    my %descendants; # classname -> list of descendant nodes
    Iter::LocalCompounds( $rootnode, sub {
	my $classNode = shift;
	# Get _all_ superclasses (up any number of levels)
	# and store that $classNode is a descendant of $s
	my @super = superclass_list($classNode);
	for my $s (@super) {
	    my $superClassName = join( "::", kdocAstUtil::heritage($s) );
	    Ast::AddPropList( \%descendants, $superClassName, $classNode );
	}
    } );

    # Iterate over all classes, to write the xtypecast function
    Iter::LocalCompounds( $rootnode, sub {
	my $classNode = shift;
	my $className = join( "::", kdocAstUtil::heritage($classNode) );
	# @super will contain superclasses, the class itself, and all descendants
	my @super = superclass_list($classNode);
	push @super, $classNode;
        if ( defined $descendants{$className} ) {
	    push @super, @{$descendants{$className}};
	}
	my $cur = $classidx{$className};
	
	return if $classNode->{NodeType} eq 'namespace';

#	print OUT "      case $cur:\t//$className\n";
#	print OUT "\tswitch(to) {\n";
#	$cur = -1;
#	my %casevalues;
#	for my $s (@super) {
#		my $superClassName = join( "::", kdocAstUtil::heritage($s) );
#		next if !defined $classidx{$superClassName}; # inherits from unknown class, see below
#		next if $classidx{$superClassName} == $cur;    # shouldn't happen in Qt
#		next if $s->kdocAstUtil::inheritsAsVirtual($classNode); # can't cast from a virtual base class
#		$cur = $classidx{$superClassName}; # KDE has MI with diamond shaped cycles (cf. KXMLGUIClient)
#		next if $casevalues{$cur};         # ..so skip any duplicate parents
#		print OUT "\t  case $cur: return (void*)($superClassName*)($className*)xptr;\n";
#		$casevalues{$cur} = 1;
#	}
#	print OUT "\t  default: return xptr;\n";
#	print OUT "\t}\n";
    } );
#    print OUT "      default: return xptr;\n";
#    print OUT "    }\n";
#    print OUT "}\n\n";


    # Write inheritance array
    # Imagine you have "Class : public super1, super2"
    # The inheritlist array will get 3 new items: super1, super2, 0
    my %inheritfinder;  # key = (super1, super2) -> data = (index in @inheritlist). This one allows reuse.
    my %classinherit;   # we store that index in %classinherit{className}
    # We don't actually need to store inheritlist in memory, we write it
    # directly to the file. We only need to remember its current size.
    my $inheritlistsize = 1;

#    print OUT "// Group of class IDs (0 separated) used as super class lists.\n";
#    print OUT "// Classes with super classes have an index into this array.\n";
#    print OUT "static short ${libname}_inheritanceList[] = {\n";
#    print OUT "\t0,\t// 0: (no super class)\n";
    Iter::LocalCompounds( $rootnode, sub {
	my $classNode = shift;
	my $className = join( "__", kdocAstUtil::heritage($classNode) );
	
	return if $classNode->{NodeType} eq 'namespace';
	
	print STDERR "inheritanceList: looking at $className\n" if ($debug);

	# Make list of direct ancestors
	my @super;
	Iter::Ancestors( $classNode, $rootnode, undef, undef, sub {
			     my $superClassName = join( "::", kdocAstUtil::heritage($_[0]) );
			     push @super, $superClassName;
		    }, undef );
	# Turn that into a list of class indexes
	my $key = '';
	foreach my $superClass( @super ) {
	    if (defined $classidx{$superClass}) {
		$key .= ', ' if ( length $key > 0 );
		$key .= $classidx{$superClass};
	    }
	}
	if ( $key ne '' ) {
	    if ( !defined $inheritfinder{$key} ) {
		print OUT "\t";
		my $index = $inheritlistsize; # Index of first entry (for this group) in inheritlist
		foreach my $superClass( @super ) {
		    if (defined $classidx{$superClass}) {
			print OUT "$classidx{$superClass}, ";
			$inheritlistsize++;
		    }
		}
		$inheritlistsize++;
		my $comment = join( ", ", @super );
		print OUT "0,\t// $index: $comment\n";
		$inheritfinder{$key} = $index;
	    }
	    $classinherit{$className} = $inheritfinder{$key};
	} else { # No superclass
	    $classinherit{$className} = 0;
	}
    } );
#    print OUT "};\n\n";


#    print OUT "// These are the xenum functions for manipulating enum pointers\n";
    for my $className (keys %enumclasslist) {
	my $c = $className;
	$c =~ s/::/__/g;
#	print OUT "void xenum_$c\(Smoke::EnumOperation, Smoke::Index, void*&, long&);\n";
    }
#    print OUT "\n";
#    print OUT "// Those are the xcall functions defined in each x_*.cpp file, for dispatching method calls\n";
    my $firstClass = 1;
    for my $className (@classlist) {
	if ($firstClass) {
	    $firstClass = 0;
	    next;
	}
	my $c = $className;   # make a copy
	$c =~ s/::/__/g;
#	print OUT "void xcall_$c\(Smoke::Index, void*, Smoke::Stack);\n";
    }
#    print OUT "\n";

    # Write class list afterwards because it needs offsets to the inheritance array.
#    print OUT "// List of all classes\n";
#    print OUT "// Name, index into inheritanceList, method dispatcher, enum dispatcher, class flags\n";
#    print OUT "static Smoke::Class ${libname}_classes[] = {\n";
    my $firstClass = 1;
    Iter::LocalCompounds( $rootnode, sub {
	my $classNode = shift;
	my $className = join( "__", kdocAstUtil::heritage($classNode) );
	
	return if $classNode->{NodeType} eq 'namespace';

	if ($firstClass) {
	    $firstClass = 0;
	    print OUT "\t{ 0L, 0, 0, 0, 0 }, \t// 0 (no class)\n";
	}
	my $c = $className;
	$c =~ s/::/__/g;
	my $xcallFunc = "xcall_$c";
	my $xenumFunc = "0";
	$xenumFunc = "xenum_$c" if exists $enumclasslist{$className};
	# %classinherit needs Foo__Bar, not Foo::Bar?
	die "problem with $className" unless defined $classinherit{$c};

	my $xClassFlags = 0;
	$xClassFlags .= "|Smoke::cf_constructor" if $classNode->{CanBeInstanciated}; # correct?
	$xClassFlags .= "|Smoke::cf_deepcopy" if $classNode->{CanBeCopied}; # HasCopyConstructor would be wrong (when it's private)
	$xClassFlags .= "|Smoke::cf_virtual" if hasVirtualDestructor($classNode) == 1;
	# $xClassFlags .= "|Smoke::cf_undefined" if ...;
	$xClassFlags =~ s/0\|//; # beautify
#	print OUT "\t{ \"$className\", $classinherit{$c}, $xcallFunc, $xenumFunc, $xClassFlags }, \t//$classidx{$className}\n";
    } );
#    print OUT "};\n\n";


#    print OUT "// List of all types needed by the methods (arguments and return values)\n";
#    print OUT "// Name, class ID if arg is a class, and TypeId\n";
#    print OUT "static Smoke::Type ${libname}_types[] = {\n";
    my $typeCount = 0;
    $allTypes{''}{index} = 0; # We need an "item 0"
    for my $type (sort keys %allTypes) {
	$allTypes{$type}{index} = $typeCount;      # Register proper index in allTypes
	if ( $typeCount == 0 ) {
#	    print OUT "\t{ 0, 0, 0 },\t//0 (no type)\n";
	    $typeCount++;
	    next;
	}
	my $isEnum = $allTypes{$type}{isEnum};
	my $typeId;
	my $typeFlags = $allTypes{$type}{typeFlags};
	my $realType = $allTypes{$type}{realType};
	die "$type" if !defined $typeFlags;
#	die "$realType" if $realType =~ /\(/;
	# First write the name
#	print OUT "\t{ \"$type\", ";
	# Then write the classId (and find out the typeid at the same time)
	if(exists $classidx{$realType}) { # this one first, we want t_class for TQBlah*
	    $typeId = 't_class';
#	    print OUT "$classidx{$realType}, ";
	}
	elsif($type =~ /&$/ || $type =~ /\*$/) {
	    $typeId = 't_voidp';
#	    print OUT "0, "; # no classId
	}
	elsif($isEnum || $allTypes{$realType}{isEnum}) {
	    $typeId = 't_enum';
	    if($realType =~ /(.*)::/) {
		my $c = $1;
		if($classidx{$c}) {
#		    print OUT "$classidx{$c}, ";
		} else {
#		    print OUT "0 /* unknown class $c */, ";
		}
	    } else {
#		print OUT "0 /* unknown $realType */, "; # no classId
	    }
	}
	else {
	    $typeId = $typeunion{$realType};
	    if (defined $typeId) {
		$typeId =~ s/s_/t_/; # from s_short to t_short for instance
	    }
	    else {
		# Not a known class - ouch, this happens quite a lot
		# (private classes, typedefs, template-based types, etc)
		if ( $skippedClasses{$realType} ) {
#		    print STDERR "$realType has been skipped, using t_voidp for it\n";
		} else {
		    unless( $realType =~ /</ ) { # Don't warn for template stuff...
			print STDERR "$realType isn't a known type (type=$type)\n";
		    }
		}
		$typeId = 't_voidp'; # Unknown -> map to a void *
	    }
#	    print OUT "0, "; # no classId
	}
	# Then write the flags
	die "$type" if !defined $typeId;
#	print OUT "Smoke::$typeId | $typeFlags },";
#	print OUT "\t//$typeCount\n";
	$typeCount++;
	# Remember it for coerce_type
	$allTypes{$type}{typeId} = $typeId;
    }
#    print OUT "};\n\n";


    my %arglist; # registers the needs for argumentList (groups of type ids)
    my %methods;
    # Look for all methods and all enums, in all classes
    # And fill in methods and arglist. This loop writes nothing to OUT.
    Iter::LocalCompounds( $rootnode, sub {
	my $classNode = shift;
	my $className = join( "::", kdocAstUtil::heritage($classNode) );
	print STDERR "writeSmokeDataFile: arglist: looking at $className\n" if ($debug);

	Iter::MembersByType ( $classNode, undef,
		sub {	my ($classNode, $m ) = @_;

	my $methName = $m->{astNodeName};
	# For destructors, get a proper signature that includes the '~'
	if ( $m->{ReturnType} eq '~' )
	{
	    $methName = '~' . $methName ;
	    # Let's even store that change, otherwise we have to do it many times
	    $m->{astNodeName} = $methName;
	}
	
	if( $m->{NodeType} eq "enum" ) {

	    foreach my $enum ( @{$m->{ParamList}} ) {
		my $enumName = $enum->{ArgName};
	        $methods{$enumName}++;
	    }

        } elsif ( $m->{NodeType} eq 'var' ) {

	    $methods{$m->{astNodeName}}++;

	} elsif( $m->{NodeType} eq "method" ) {

	    $methods{$methName}++;
	    my @protos;
	    makeprotos(\%classidx, $m, \@protos);

	    #print "made @protos from $className $methName $m->{Signature})\n" if ($debug);
	    for my $p (@protos) {
		$methods{$p}++;
		my $argcnt = 0;
		$argcnt = length($1) if $p =~ /([\$\#\?]+)/;
		my $sig = methodSignature($m, $argcnt-1);
		# Store in a class hash named "proto", a proto+signature => method association
		$classNode->{proto}{$p}{$sig} = $m;
		#$classNode->{signature}{$sig} = $p;
		# There's probably a way to do this better, but this is the fastest way
		# to get the old code going: store classname into method
		$m->{class} = $className;
	    }

	    my $firstDefaultParam = $m->{FirstDefaultParam};
	    $firstDefaultParam = scalar(@{ $m->{ParamList} }) unless defined $firstDefaultParam;
	    my $argNames = '';
	    my $args = '';
	    for(my $i = 0; $i < @{ $m->{ParamList} }; $i++) {
		$args .= ', ' if $i;
		$argNames .= ', ' if $i;
		my $argType = $m->{ParamList}[$i]{ArgType};
		my $typeEntry = findTypeEntry( $argType );
		$args .= defined $typeEntry ? $typeEntry->{index} : 0;
		$argNames .= $argType;

		if($i >= ($firstDefaultParam - 1)) {
		    #print "arglist entry: $args\n";
		    $arglist{$args} = $argNames;
		}
		
	    }
	    # create an entry for e.g. "arg0,arg1,arg2" where argN is index in allTypes of type for argN
	    # The value, $argNames, is temporarily stored, to be written out as comment
	    # It gets replaced with the index in the next loop.
	    #print "arglist entry : $args\n";
	    $arglist{$args} = $argNames;
	}
		    }, # end of sub
	undef
       );
    });


    $arglist{''} = 0;
    # Print arguments array
#    print OUT "static Smoke::Index ${libname}_argumentList[] = {\n";
    my $argListCount = 0;
    for my $args (sort keys %arglist) {
	my @dunnohowtoavoidthat = split(',',$args);
	my $numTypes = $#dunnohowtoavoidthat;
	if ($args eq '') {
#	    print OUT "\t0,\t//0  (void)\n";
	} else {
	    # This is a nice trick : args can be written in one go ;)
#	    print OUT "\t$args, 0,\t//$argListCount  $arglist{$args}  \n";
	}
	$arglist{$args} = $argListCount;      # Register proper index in argList
	$argListCount += $numTypes + 2;       # Move forward by as much as we wrote out
    }
#    print OUT "};\n\n";

    $methods{''} = 0;
    my @methodlist = sort keys %methods;
    my %methodidx = do { my $i = 0; map { $_ => $i++ } @methodlist };

#    print OUT "// Raw list of all methods, using munged names\n";
#    print OUT "static const char *${libname}_methodNames[] = {\n";
    my $methodNameCount = $#methodlist;
    for my $m (@methodlist) {
#	print OUT qq(    "$m",\t//$methodidx{$m}\n);
    }
#    print OUT "};\n\n";

#    print OUT "// (classId, name (index in methodNames), argumentList index, number of args, method flags, return type (index in types), xcall() index)\n";
#    print OUT "static Smoke::Method ${libname}_methods[] = {\n";
    my @methods;
    %allMethods = ();
    my $methodCount = 0;
    # Look at all classes and all enums again
    Iter::LocalCompounds( $rootnode, sub {
	my $classNode = shift;
	my $className = join( "::", kdocAstUtil::heritage($classNode) );
	return if $classNode->{NodeType} eq 'namespace';
	
	my $classIndex = $classidx{$className};
	print STDERR "writeSmokeDataFile: methods: looking at $className\n" if ($debug);

	Iter::MembersByType ( $classNode, undef,
		sub {	my ($classNode, $m ) = @_;

	if( $m->{NodeType} eq "enum" ) {

	    foreach my $enum ( @{$m->{ParamList}} ) {
		my $enumName = $enum->{ArgName};
		my $fullEnumName = "$className\::$enumName";
		my $sig = "$className\::$enumName\()";
		my $xmethIndex = $methodidx{$enumName};
		die "'Method index' for enum $sig not found" unless defined $xmethIndex;
		my $typeId = findTypeEntry( $fullEnumName )->{index};
		die "enum has no {case} value in $className: $fullEnumName" unless defined $classNode->{case}{$fullEnumName};
#		print OUT "\t{$classIndex, $xmethIndex, 0, 0, Smoke::mf_static, $typeId, $classNode->{case}{$fullEnumName}},\t//$methodCount $fullEnumName (enum)\n";
		$allMethods{$sig} = $methodCount;
		print STDERR "Added entry for " . $sig . " into \$allMethods\n" if ($debug);
		$methods[$methodCount] = {
				c => $classIndex,
				methIndex => $xmethIndex,
				argcnt => '0',
				args => 0,
				retTypeIndex => 0,
				idx => $classNode->{case}{$fullEnumName}
			       };
		$methodCount++;
	    }

	} elsif( $m->{NodeType} eq 'var' ) {

	    my $name = $m->{astNodeName};
	    my $fullName = "$className\::$name";
	    my $sig = "$fullName\()";
	    my $xmethIndex = $methodidx{$name};
	    die "'Method index' for var $sig not found" unless defined $xmethIndex;
	    my $varType = $m->{Type};
	    $varType =~ s/static\s//;
	    $varType =~ s/const\s+(.*)\s*&/$1/;
	    $varType =~ s/\s*$//;
	    my $typeId = findTypeEntry( $varType )->{index};
	    die "var has no {case} value in $className: $fullName" unless defined $classNode->{case}{$fullName};
#	    print OUT "\t{$classIndex, $xmethIndex, 0, 0, Smoke::mf_static, $typeId, $classNode->{case}{$fullName}},\t//$methodCount $fullName (static var)\n";
            $allMethods{$sig} = $methodCount;
	    print STDERR "Added entry for " . $sig . " into \$allMethods\n" if ($debug);
	    $methods[$methodCount] = {
				c => $classIndex,
				methIndex => $xmethIndex,
				argcnt => '0',
				args => 0,
				retTypeIndex => 0,
				idx => $classNode->{case}{$fullName}
			       };
	    $methodCount++;


	} elsif( $m->{NodeType} eq "method" ) {

	    # We generate a method entry only if the method is in the switch() code
	    # BUT: for pure virtuals, they need to have a method entry, even though they
	    # do NOT have a switch code.
	    return if ( $m->{SkipFromSwitch} && $m->{Flags} !~ "p" );

	    # No switch code for destructors if we didn't derive from the class (e.g. it has private ctors only)
    	    return if ( $m->{ReturnType} eq '~' && ! ( $classNode->{BindingDerives} and $classNode->{HasPublicDestructor}) );

            # Is this sorting really important?
	    #for my $m (sort {$a->{name} cmp $b->{name}} @{ $self->{$c}{method} }) {

	    my $methName = $m->{astNodeName};
	    my $def = $m->{FirstDefaultParam};
	    $def = scalar(@{ $m->{ParamList} }) unless defined $def;
	    my $last = scalar(@{ $m->{ParamList} }) - 1;
	    #print STDERR "writeSmokeDataFile: methods: generating for method $methName, def=$def last=$last\n" if ($debug);

	    while($last >= ($def-1)) {
		last if $last < -1;
		my $args = [ @{ $m->{ParamList} }[0..$last] ];
		my $sig = methodSignature($m, $last);
		#my $methodSig = $classNode->{signature}{$sig}; # Munged signature
		#print STDERR "writeSmokeDataFile: methods: sig=$className\::$sig methodSig=$methodSig\n" if ($debug);
		#my $methodIndex = $methodidx{$methodSig};
		#die "$methodSig" if !defined $methodIndex;

		my $methodIndex = $methodidx{$methName};
		die "$methName" if !defined $methodIndex;
		my $case = $classNode->{case}{$sig};
		my $typeEntry = findTypeEntry( $m->{ReturnType} );
		my $retTypeIndex = defined $typeEntry ? $typeEntry->{index} : 0;

		my $i = 0;
		my $t = '';
		for my $arg (@$args) {
		    $t .= ', ' if $i++;
		    my $typeEntry = findTypeEntry( $arg->{ArgType} );
		    $t .= defined $typeEntry ? $typeEntry->{index} : 0;
		}
		my $arglist = $t eq '' ? 0 : $arglist{$t};
		die "arglist for $t not found" unless defined $arglist;
		if ( $m->{Flags} =~ "p" ) {
		    # Pure virtuals don't have a {case} number, that's normal
		    die if defined $case;
		    $case = -1; # This remains -1, not 0 !
		} else {
			;
#		    die "$className\::$methName has no case number for sig=$sig" unless defined $case;
		}
		my $argcnt = $last + 1;
		my $methodFlags = '0';
		$methodFlags .= "|Smoke::mf_static" if $m->{Flags} =~ "s";
		$methodFlags .= "|Smoke::mf_const" if $m->{Flags} =~ "c"; # useful?? probably not
		$methodFlags =~ s/0\|//; # beautify
		
#		print OUT "\t{$classIndex, $methodIndex, $arglist, $argcnt, $methodFlags, $retTypeIndex, $case},\t//$methodCount $className\::$sig";
#		print OUT " [pure virtual]" if ( $m->{Flags} =~ "p" ); # explain why $case = -1 ;)
#		print OUT "\n";
		
		$allMethods{$className . "::" . $sig} = $methodCount;
		$methods[$methodCount] = {
					  c => $classIndex,
					  methIndex => $methodIndex,
					  argcnt => $argcnt,
					  args => $arglist,
					  retTypeIndex => $retTypeIndex,
					  idx => $case
					 };
		$methodCount++;
		$last--;
	    } # while
	} # if method
      } ); # Method Iter
    } ); # Class Iter
#    print OUT "};\n\n";

    my @protos;
    Iter::LocalCompounds( $rootnode, sub {
	my $classNode = shift;
	my $className = join( "::", kdocAstUtil::heritage($classNode) );
	
	return if $classNode->{NodeType} eq 'namespace';
	
	my $classIndex = $classidx{$className};
	print STDERR "writeSmokeDataFile: protos: looking at $className\n" if ($debug);

	Iter::MembersByType ( $classNode, undef,
		sub {	my ($classNode, $m ) = @_;

	if( $m->{NodeType} eq "enum" ) {
	    foreach my $enum ( @{$m->{ParamList}} ) {
		my $enumName = $enum->{ArgName};
		my $sig = "$className\::$enumName\()";
		my $xmeth = $allMethods{$sig};
		die "'Method' for enum $sig not found" unless defined $xmeth;
		my $xmethIndex = $methodidx{$enumName};
		die "'Method index' for enum $enumName not found" unless defined $xmethIndex;
		push @protos, {
			       methIndex => $xmethIndex,
			       c => $classIndex,
			       over => {
					$sig => {
						 sig => $sig,
						}
				       },
			       meth => $xmeth
			      };
	    }

	} elsif( $m->{NodeType} eq 'var' ) {

	    my $name = $m->{astNodeName};
	    my $fullName = "$className\::$name";
	    my $sig = "$fullName\()";
	    my $xmeth = $allMethods{$sig};
	    die "'Method' for var $sig not found" unless defined $xmeth;
	    my $xmethIndex = $methodidx{$name};
	    die "'Method index' for var $name not found" unless defined $xmethIndex;
	    push @protos, {
			       methIndex => $xmethIndex,
			       c => $classIndex,
			       over => {
					$sig => {
						 sig => $sig,
						}
				       },
			       meth => $xmeth
			  };

	}
		    });

	for my $p (keys %{ $classNode->{proto} }) {
	    # For each prototype
	    my $scratch = { %{ $classNode->{proto}{$p} } }; # sig->method association
	    # first, grab all the superclass voodoo
	    for my $supNode (superclass_list($classNode)) {
		my $i = $supNode->{proto}{$p};
		next unless $i;
		for my $k (keys %$i) {
		    $scratch->{$k} = $i->{$k} unless exists $scratch->{$k};
		}
	    }

	    # Ok, now we have a full list
	    #if(scalar keys %$scratch > 1) {
		#print STDERR "Overload: $p (@{[keys %$scratch]})\n" if ($debug);
	    #}
	    my $xmethIndex = $methodidx{$p};
	    my $classIndex = $classidx{$className};
	    for my $sig (keys %$scratch) {
		#my $xsig = $scratch->{$sig}{class} . "::" . $sig;
		my $xsig = $className . "::" . $sig;
		$scratch->{$sig}{sig} = $xsig;
		delete $scratch->{$sig}
		    if $scratch->{$sig}{Flags} =~ "p" # pure virtual
			or not exists $allMethods{$xsig};
	    }
	    push @protos, {
		methIndex => $xmethIndex,
		c => $classIndex,
		over => $scratch
	    } if scalar keys %$scratch;
	}
    });

    my @protolist = sort { $a->{c} <=> $b->{c} || $a->{methIndex} <=> $b->{methIndex} } @protos;
#for my $abc (@protos) {
#print "$abc->{methIndex}.$abc->{c}\n";
#}

    print STDERR "Writing methodmap table\n" if ($debug);
    my @resolve = ();
#    print OUT "// Class ID, munged name ID (index into methodNames), method def (see methods) if >0 or number of overloads if <0\n";
    my $methodMapCount = 1;
#    print OUT "static Smoke::MethodMap ${libname}_methodMaps[] = {\n";
#    print OUT "\t{ 0, 0, 0 },\t//0 (no method)\n";
    for my $cur (@protolist) {
	if(scalar keys %{ $cur->{over} } > 1) {
#	    print OUT "\t{$cur->{c}, $cur->{methIndex}, -@{[1+scalar @resolve]}},\t//$methodMapCount $classlist[$cur->{c}]\::$methodlist[$cur->{methIndex}]\n";
	    $methodMapCount++;
	    for my $k (keys %{ $cur->{over} }) {
	        my $p = $cur->{over}{$k};
	        my $xsig = $p->{class} ? "$p->{class}\::$k" : $p->{sig};
	        push @resolve, { k => $k, p => $p, cur => $cur, id => $allMethods{$xsig} };
	    }
	    push @resolve, 0;
	} else {
	    for my $k (keys %{ $cur->{over} }) {
	        my $p = $cur->{over}{$k};
	        my $xsig = $p->{class} ? "$p->{class}\::$k" : $p->{sig};
#	        print OUT "\t{$cur->{c}, $cur->{methIndex}, $allMethods{$xsig}},\t//$methodMapCount $classlist[$cur->{c}]\::$methodlist[$cur->{methIndex}]\n";
	        $methodMapCount++;
	    }
	}
    }
#    print OUT "};\n\n";


    print STDERR "Writing ambiguousMethodList\n" if ($debug);
#    print OUT "static Smoke::Index ${libname}_ambiguousMethodList[] = {\n";
#    print OUT "    0,\n";
    for my $r (@resolve) {
	unless($r) {
#	    print OUT "    0,\n";
	    next;
	}
	my $xsig = $r->{p}{class} ? "$r->{p}{class}\::$r->{k}" : $r->{p}{sig};
	die "ambiguousMethodList: no method found for $xsig\n" if !defined $allMethods{$xsig};
#	print OUT "    $allMethods{$xsig},  // $xsig\n";
    }
#    print OUT "};\n\n";

#    print OUT "extern \"C\" { // needed?\n";
#    print OUT "    void init_${libname}_Smoke();\n";
#    print OUT "}\n";
#    print OUT "\n";
#    print OUT "Smoke* qt_Smoke = 0L;\n";
#    print OUT "\n";
#    print OUT "// Create the Smoke instance encapsulating all the above.\n";
#    print OUT "void init_${libname}_Smoke() {\n";
#    print OUT "    qt_Smoke = new Smoke(\n";
#    print OUT "        ${libname}_classes, ".$#classlist.",\n";
#    print OUT "        ${libname}_methods, $methodCount,\n";
#    print OUT "        ${libname}_methodMaps, $methodMapCount,\n";
#    print OUT "        ${libname}_methodNames, $methodNameCount,\n";
#    print OUT "        ${libname}_types, $typeCount,\n";
#    print OUT "        ${libname}_inheritanceList,\n";
#    print OUT "        ${libname}_argumentList,\n";
#    print OUT "        ${libname}_ambiguousMethodList,\n";
#    print OUT "        ${libname}_cast );\n";
#    print OUT "}\n";
#    close OUT;

#print "@{[keys %allMethods ]}\n";
}
=head2 printJavadocComment

	Parameters: docnode filehandle

	Converts a kdoc comment to javadoc format.
	@ref's are converted to @link's; @p's and @em's are converted
	to inline HTML.

=cut

sub printJavadocComment($$$$)
{
	my( $docnode, $name, $indent, $signalLink ) = @_;

	my $node;
	my $returntext = '';
	foreach $node ( @{$docnode->{Text}} ) {
		next if $node->{NodeType} ne "DocText" and $node->{NodeType} ne "ListItem" 
		and $node->{NodeType} ne "Param";
		my $line = '';
		
		if ($node->{NodeType} eq "Param") {
			if ($node->{Name} !~ /argc/) {
				$line = "\@param " . $node->{Name} . " " . $node->{astNodeName};
			}
		} else {
			$line = $node->{astNodeName};
		}
		$line =~ s/argc, ?argv/args/g;
		$line =~ s/int argc, ?char ?\* ?argv(\[\])?/String[] args/g;
		$line =~ s/int argc, ?char ?\*\* ?argv/String[] args/g;
		if ($node->{NodeType} eq "Param") {
			$line =~ s/(const )?QC?StringList(\s*&)?/String[]/g;
		} else {
			$line =~ s/(const )?QC?StringList(\s*&)?/ArrayList/g;
		}
		$line =~ s/NodeList|TDETrader::OfferList/ArrayList/g;
		$line =~ s/(const )?TQDate(Time)?(\s*&)?/Calendar/g;
		$line =~ s/(const )?TQTime([^r])/Date$1/g;
		$line =~ s/TQString::null/null/g;
		$line =~ s/(const )?QC?String(\s*&)?/String/g;
		$line =~ s/TQByteArray/byte[]/g;
		$line =~ s/(const )?TDECmdLineOptions\s*(\w+)\[\]/String[][] $2/;
		$line =~ s/TDECmdLineLastOption//g;
		$line =~ s/virtual //g;
		$line =~ s/~\w+\(\)((\s*{\s*})|;)//g;
		$line =~ s/0L/null/g;
		$line =~ s/(\([^\)]*\))\s*:\s*\w+\([^\)]*\)/$1/g;
		$line =~ s/\(void\)//g;
		$line =~ s/const char/String/g;
		$line =~ s/const (\w+)\&/$1/g;
		$line =~ s/bool/boolean/g;
		$line =~ s/TQ_SLOT\(\s*([^\)]*)\) ?\)/TQ_SLOT("$1)")/g;
		$line =~ s/TQ_SIGNAL\(\s*([^\)]*)\) ?\)/TQ_SIGNAL("$1)")/g;
		$line =~ s/TQ_OBJECT\n//g;
		$line =~ s/class\s+([\w]+)\s*:\s*public/public class $1 implements/g;
		$line =~ s/public\s*(slots)?:\n/public /g;
		$line =~ s/([^0-9"]\s*)\*(\s*[^0-9"-])/$1$2/g;
		$line =~ s/^(\s*)\*/$1/g;
		$line =~ s/\n \*/\n /g;
		$line =~ s/\@ref\s+([\w]+)::([\w]+)\s*(\([^\)]*\))(\.)?/{\@link $1#$2}$4/g;
		$line =~ s/\@ref\s+#([\w:]+)(\(\))?/{\@link #$1}/g;
		$line =~ s/\@ref\s+([\w]+)\s*(\([^\)]*\))/{\@link #$1}/g;
		$line =~ s/\@ref\s+([\w]+)::([\w]+)/{\@link $1#$2}/g;
		$line =~ s/\@ref\s+([a-z][\w]+)/{\@link #$1}/g;
		$line =~ s/\@ref\s+([\w]+)/{\@link $1}/g;
		while ($line =~ /\@c\s+([\w#\\\.<>]+)/ ) {
			my $code = $1;
			$code =~ s!<!&lt;!g;
			$code =~ s!>!&gt;!g;
			$code =~ s!\\#!#!g;
			$line =~ s!\@c\s+([\w#\\\.<>]+)!<code>$code</code>!;
		}
		$line =~ s!\@em\s+(\w+)!<b>$1</b>!g;
		$line =~ s!\@p\s+([\w\._]*)!<code>$1</code>!g;
		$line =~ s!\\paragraph\s+[\w]+\s([\w]+)!<li><b>$1</b></li>!g;
		$line =~ s!\\b\s+([\w -]+)\\n!<li><b>$1</b></li>!g;
		$line =~ s!\\c\s+([\w\@&\\?;-]+)!<code>$1</code>!g;
		$line =~ s!\\p\s+([\w\@]+)!<pre>$1</pre>!g;
		$line =~ s!\\li\s+([\w\@]+)!<li>$1</li>!g;
		$line =~ s!<b>([\w\t \(\)-]*:?)</b>\\n!<li><b>$1</b></li>!g;
		$line =~ s!static_cast<\s*([\w\.]*)\s*>!($1)!g;
		if ($name ne "") {
			$line =~ s/\@link #/\@link $name\#/g;
		}
		
		if ($node->{NodeType} eq "ListItem") {
			$line =~ s/^/\n<li>\n/;
			$line =~ s!$!\n</li>!;
			$line =~ s/\n/\n$indent\t/g;
		} else {
			$line =~ s/^/$indent/;
			$line =~ s/\n/\n$indent/g;
		}
		
		$line =~ s/\n/\n$indent/g;
		$returntext .= $line;
	}
	
	$returntext .= $signalLink;
	
	if ( defined $docnode->{Returns} ) {
		my $text = $docnode->{Returns};
		$text =~ s/TQString::null/null/g;
		$returntext .=  "\t\t\@return $text\n";
	}
		
	if ( defined $docnode->{Author} ) { 
		$returntext .= "\t\t\@author " . $docnode->{Author} . "\n" 
	}
		
	if ( defined $docnode->{Version} ) {
		my $versionStr = $docnode->{Version};
		$versionStr =~ s/\$\s*Id:([^\$]*) Exp \$/$1/;
		$returntext .= "\t\t\@version $versionStr\n";
	}
		
	if ( defined $docnode->{ClassShort} ) { 
		my $shortText = $docnode->{ClassShort};
		$shortText =~ s![\*\n]! !g;
		$returntext .= "\t\t\@short $shortText\n";
	}
	
	if ( defined $docnode->{See} ) {
		foreach my $text ( @{$docnode->{See}} ) {
			next if ($text =~ /TQString|^\s*and\s*$|^\s*$|^[^\w]*$/);
			$text =~ s/TDEIO:://g;
			$text =~ s/KParts:://g;
			$text =~ s/bool/boolean/g;
			$text =~ s/::/#/g;
			$text =~ s/->/#/g;
			$text =~ s/\./#/g;
			$text =~ s/\(\)//g;
			$text =~ s/^\s*([a-z].*)/#$1/g;
			$text =~ s/^\s*Q/org.trinitydesktop.qt.Q/g;
#			$text =~ s/^\s*K/org.trinitydesktop.koala.K/g;
			$returntext .= "\t\t\@see $text\n";
		}
	}	

	$returntext =~ s/DOM#([A-Z])/$1/g;
	$returntext =~ s/TDEIO#([A-Z])/$1/g;
	$returntext =~ s/KParts#([A-Z])/$1/g;
	$returntext =~ s/const\s+(\w+)\s*\&/$1/g;
	$returntext =~ s/TQChar/char/g;
	$returntext =~ s/TQStringList/ArrayList/g;
	$returntext =~ s/([Aa]) ArrayList/$1n ArrayList/g;
	$returntext =~ s/TQString/String/g;
	$returntext =~ s/TDECmdLineOptions/String[][]/;
	$returntext =~ s!\\note!<b>Note:<\b>!g;
	$returntext =~ s!\\(code|verbatim)!<pre>!g;
	$returntext =~ s!\\(endcode|endverbatim)!</pre>!g;
	$returntext =~ s!\\addtogroup\s+[\w]+\s+"([^"\@]+)"\s+\@{!<li><b>$1</b></li>!g;
	$returntext =~ s![\\\@]relates\s+([a-z][\w]*)!{\@link #$1}!g;
	$returntext =~ s![\\\@]relates\s+(\w+)::(\w+)!{\@link $1#$2}!g;
	$returntext =~ s![\\\@]relates\s+(#?\w+)!{\@link $1}!g;
	$returntext =~ s!\\c\s+([\w\@&\\?";-]+)!<code>$1</code>!g;
	$returntext =~ s!\@p\s+([\w\._]*)!<code>$1</code>!g;
	$returntext =~ s!\@a\s+([:\w]+)!<b>$1</b>!g;
	$returntext =~ s![\@\\]b\s+[:\w]!<b>$1</b>!g;
	$returntext =~ s/};/}/g;
	$returntext =~ s/::/./g;
	$returntext =~ s/->/./g;
	
	$returntext =~ s/\s*$//;
	return $returntext . "\n" . $indent;
}

1;
