# HG changeset patch # User John W. Eaton # Date 1353702553 18000 # Node ID acf0addfc610cd975cf6bc7dc2ec9bbb31273b60 # Parent 55014745413715b36c328a877aeafcc1c3969bf1 include Octave Forge java package in core Octave * scripts/java: New directory tree. * scripts/Makefile.am: Include java/module.mk. (JAR_FILES): New variable. (nobase_fcnfile_DATA): Include $(JAR_FILES) in the list. (all-local): Depend on $(JAR_FILES). (java/PKG_ADD, java_GEN_FCN_FILES, java/$(octave_dirstamp)): New rules. * libinterp/link-deps (LIBOCTINTERP_LINK_DEP): Include $(JAVA_LIBS) in the list. * dldfcn/__java__.h, dldfcn/__java__.cc: New files. * dldfcn/module-files (__java__.cc): New file description. * doc/interpreter/java.txi: New file. * doc/interpreter/octave.texi: Include java.texi. * doc/interpreter/java-images: New directory. * doc/interpreter/Makefile.am (JAVA_IMAGES): New variable. (IMAGES): Include $(JAVA_IMAGSES) in the list. (MUNGED_TEXI_SRC): Include java.texi in the list. * configure.ac: Check for Java libraries and tools. Include Java info in the summary message. * build-aux/common.mk (JAVA_CPPFLAGS, JAVA_LIBS): New variables. * NEWS: Update. * contributors.in: Include Martin Hepperle in the list. diff --git a/NEWS b/NEWS --- a/NEWS +++ b/NEWS @@ -97,7 +97,29 @@ ** The default name of the Octave crash dump file is now called octave-workspace instead of octave-core. - + + ** The java package from Octave Forge is now part of Octave. The + following new functions are available for interacting with Java + directly from Octave: + + java java_invoke + java2mat java_new + javaArray java_set + javaMethod java_unsigned_conversion + javaObject javaaddpath + java_convert_matrix javaclasspath + java_debug javafields + java_exit javamem + java_get javamethods + java_init javarmpath + + In addition, the following functions that use the Java interface + are now available (provided that Octave is compiled with support for + Java enabled): + + helpdlg listdlg questdlg + inputdlg msgbox warndlg + ** Other new functions added in 3.8.0: betaincinv erfcinv lines rgbplot diff --git a/build-aux/common.mk b/build-aux/common.mk --- a/build-aux/common.mk +++ b/build-aux/common.mk @@ -224,6 +224,9 @@ HDF5_LDFLAGS = @HDF5_LDFLAGS@ HDF5_LIBS = @HDF5_LIBS@ +JAVA_CPPFLAGS = @JAVA_CPPFLAGS@ +JAVA_LIBS = @JAVA_LIBS@ + LAPACK_LIBS = @LAPACK_LIBS@ LLVM_CPPFLAGS = @LLVM_CPPFLAGS@ diff --git a/configure.ac b/configure.ac --- a/configure.ac +++ b/configure.ac @@ -738,6 +738,105 @@ AC_SUBST(LLVM_LDFLAGS) AC_SUBST(LLVM_LIBS) +### Check for Java. + +warn_java= + +if test -z "$JAVA_HOME"; then + AC_CHECK_PROG(JAVA, java, java) + AC_CHECK_PROG(JAVAC, javac, javac) + AC_CHECK_PROG(JAR, jar, jar) +else + AC_PATH_PROG(JAVA, java, [], [$JAVA_HOME/bin$PATH_SEPARATOR$PATH]) + AC_PATH_PROG(JAVAC, javac, [], [$JAVA_HOME/bin$PATH_SEPARATOR$PATH]) + AC_PATH_PROG(JAR, jar, [], [$JAVA_HOME/bin$PATH_SEPARATOR$PATH]) +fi +HAVE_JAVA=no +if test -n "$JAVAC" -a -n "$JAR"; then + AC_MSG_CHECKING([for Java version]) + java_version=[`$JAVA -version 2>&1 | sed -n -e 's/^java version[^0-9"]*"\([^"]*\)"/\1/p'`] + AC_MSG_RESULT($java_version) + java_major=[`echo -n $java_version | sed -e 's/^\([0-9][0-9]*\)\.\([0-9][0-9]*\)\..*$/\1/'`] + java_minor=[`echo -n $java_version | sed -e 's/^\([0-9][0-9]*\)\.\([0-9][0-9]*\)\..*$/\2/'`] + if test $java_major -ge 1 -a $java_minor -ge 5; then + case "$canonical_host_type" in + *-msdosmsvc*) + HAVE_JAVA=yes + JAVA_LIBS=-ladvapi32 + ;; + *) + if test -z "$JAVA_HOME"; then + # This is the location of Java on an OS X box. In this + # directory we can find the various versions of a + # JavaVMs. Check for the newest version set the JAVA_HOME + # variable. + if test -d "/System/Library/Frameworks/JavaVM.framework"; then + # Sneak the -framework flag into mkoctfile via LFLAGS + LFLAGS="$LFLAGS -framework JavaVM" + JAVA_TEMP="/System/Library/Frameworks/JavaVM.framework" + JAVA_HOME="${JAVA_TEMP}/Home" + JAVA_ARCH="${JAVA_TEMP}/Libraries/libjvm_compat.dylib" + # According to: + # http://developer.apple.com/unix/crossplatform.html + # you need to explicitely set the include path + JAVA_CPPFLAGS="-I${JAVA_HOME}/include" + HAVE_JAVA=yes + # This is the Debian default path + elif test -d "/usr/lib/jvm/default-java"; then + JAVA_HOME=/usr/lib/jvm/default-java + # This is the path of java 6 on debian + elif test -d "/usr/lib/jvm/java-6-sun"; then + JAVA_HOME=//usr/lib/jvm/java-6-sun + else + JAVA_HOME=/usr/lib/jvm + fi + fi + JAVA_HOME=[`echo -n $JAVA_HOME | sed -e 's|/$||'`] + if test -z "$JAVA_ARCH"; then + if test -d "${JAVA_HOME}/jre/lib/i386"; then + JAVA_ARCH="i386"; + elif test -d "${JAVA_HOME}/jre/lib/amd64"; then + JAVA_ARCH="amd64" + elif test -d "${JAVA_HOME}/jre/lib/mac"; then + JAVA_ARCH="mac" + elif test -d "${JAVA_HOME}/jre/lib/maci"; then + JAVA_ARCH="maci" + elif test -d "${JAVA_HOME}/jre/lib/solaris"; then + JAVA_ARCH="solaris" + elif test -d "${JAVA_HOME}/jre/lib/solarisv9"; then + JAVA_ARCH="solarisv9" + fi + fi + if test -n "$JAVA_ARCH"; then + HAVE_JAVA=yes + case "$canonical_host_type" in + *-mingw* | *-cygwin*) + JAVA_LIBS=-ladvapi32 + JAVA_CPPFLAGS="-I${JAVA_HOME}/include -I${JAVA_HOME}/include/win32" + ;; + *) + JAVA_CPPFLAGS="-I${JAVA_HOME}/include -I${JAVA_HOME}/include/linux" + ;; + esac + fi + ;; + esac + if test "$HAVE_JAVA" = "yes"; then + AC_DEFINE(HAVE_JAVA, 1, + [Define to 1 if Java is available and is at least version 1.5]) + fi + else + warn_java="Java 1.5 or later not found. Octave will not be able to call Java methods." + fi +fi + +AC_SUBST(JAVAC) +AC_SUBST(JAR) +AC_SUBST(JAVA_CPPFLAGS) +AC_SUBST(JAVA_LIBS) +AC_DEFINE_UNQUOTED([JAVA_HOME], ["$JAVA_HOME"], [Java home.]) +AC_DEFINE_UNQUOTED([JAVA_ARCH], ["$JAVA_ARCH"], [Java arch.]) + ### Check for HDF5 library. save_CPPFLAGS="$CPPFLAGS" @@ -2535,6 +2634,10 @@ HDF5 CPPFLAGS: $HDF5_CPPFLAGS HDF5 LDFLAGS: $HDF5_LDFLAGS HDF5 libraries: $HDF5_LIBS + Java arch: $JAVA_ARCH + Java home: $JAVA_HOME + Java CPPFLAGS: $JAVA_CPPFLAGS + Java libraries: $JAVA_LIBS LAPACK libraries: $LAPACK_LIBS LLVM CPPFLAGS: $LLVM_CPPFLAGS LLVM LDFLAGS: $LLVM_LDFLAGS diff --git a/doc/interpreter/Makefile.am b/doc/interpreter/Makefile.am --- a/doc/interpreter/Makefile.am +++ b/doc/interpreter/Makefile.am @@ -83,11 +83,23 @@ $(srcdir)/images.mk: $(srcdir)/config-images.sh $(srcdir)/images.awk $(srcdir)/images $(srcdir)/config-images.sh $(top_srcdir) +JAVA_IMAGES = \ + java-images/image001.png \ + java-images/image002.png \ + java-images/image003.png \ + java-images/image004.png \ + java-images/image005.png \ + java-images/image006.png \ + java-images/image007.png \ + java-images/image008.png \ + java-images/image009.png + IMAGES = \ $(IMAGES_EPS) \ $(IMAGES_PDF) \ $(IMAGES_PNG) \ - $(IMAGES_TXT) + $(IMAGES_TXT) \ + $(JAVA_IMAGES) HTMLDIR_IMAGES = $(addprefix octave.html/, $(IMAGES_PNG)) @@ -123,6 +135,7 @@ interp.texi \ intro.texi \ io.texi \ + java.texi \ linalg.texi \ matrix.texi \ nonlin.texi \ diff --git a/doc/interpreter/contributors.in b/doc/interpreter/contributors.in --- a/doc/interpreter/contributors.in +++ b/doc/interpreter/contributors.in @@ -93,6 +93,7 @@ Daniel Heiserer Martin Helm Stefan Hepp +Martin Hepperle Jordi GutiƩrrez Hermoso Yozo Hida Ryan Hinton diff --git a/doc/interpreter/java-images/image001.png b/doc/interpreter/java-images/image001.png new file mode 100755 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..d5ffef6d4345c4a12336e6ca5a03eeed7e6ca750 GIT binary patch literal 14199 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 YrmUnmE@YW2)AsMm1--BuSUhi|(+tUp% zuOSZr0DgzN%N_tg=_1z|a%kk+CRf!GS!BYTb~^z;T~6|{&jsYSZm|2F-2iaf000;) z09b^P^)mp(k^tZ<1pu}d0D$_*f?Guc0H7AQ!^LTD!j+(=s8JcdF(g~g!0O&8L+dj9 z85bWkFFH2T)HrFQSPe~0=6Xk<&e7V>>=!L>0VmCeWQTGD%<=ayt~_JtIe_dqZxgyM zt7A)MUS1vwWNuDloGbHiY9FZ_3F3h6dXVe7Th34`V^ey&vG_UnylX7Bl2t2OU8T^k zb?%Fs-WBG$^gbJnfz66XGoeJs+)3;eyt1Qd;qM!c|I8fg4FpT=$xV`O;U_bUsy;?R z0b^@|!I@wzR52F%{2Dq~+G6nr?h%USVR}haN8B^S8NMbUqkI|s{>7Fb7mdx{4Vq1n zlEu%sZ9UxU0-+!N;(aKUoEaEGNfrnfaC|o`J82aRZ%pXgPWQ`A^Kn#HKJv_~Dag%D zaPJO2JPkmdFtMMq62QqQjFgQWzB+4IZG;#0vRKf>z-`4l~J;-|`dOLKjJD zq-*#!VQLL@1VWx-rWSngE*0l{iUG9d^QM|84fMH%+}>P5wbcBgv3V^y%9N(u)FGTR z;^XeabTZ_yT^uG7r&A|1*-E{H!qT6|lJ&U!;El@c>&LZkPii2sdW^tcORM!Og;JAK zySNKyuX$f!mdwE2!+#0<=~AjlI1iT^l|s#u(3>iu?jy7YVfN@#FE%|;_i^)^Vzd?0 z%R=cDH{Ne4@6q+8_O{09)z3dg zE?Jy_7ZyOLWNvj^f>c1KU|)<SAMC z_D-hd>#pd4-rksPvyifT$v*T%gOSmn#M1Cfch8KQyQ|LFBe1?2#2n)_;xwnUZu-SW zG~Fj&Y#g{+G8(Nj6wit|()e&)?>U54j%$FI*Ob61xG=ix^}U7zGb0q^ z`b48AJ=qQ_yILR-Bux$z^*rUGb@s?q1jI? zr$Cs5x9M;2d?f%a=Yb6lqmG2pMjG)!urG}Q_v$tlIwhbn9$hdzPcN(?-wkJK1pKu? zfE>JsBs8?;4MU3R>isTVxAAXWw2=Hh3fvBHr|DqibpK*$!LWr;J6JT&$n!6k+0+005XHET&24w%Ga_ZczNf8*l-hXr`;~U&KH9t zhI+HV_aZrpRsOq#jeQs{ZAq2FqHJmxogHloZt8A9H$Z46`3eX_P+W5GJHhNye=nV= zLna*x5uGZSI-!FgmoHx;+;!Ooac}4tR~8qQ%D#$H#hm+NH#{K)GFl?zUq(wlbeCVPEX8rMOYmL z6yC6&L?WAuVZLx#lMg=x7uAjLrLNRGkmM)0Adh6ipDuIz^d1JFm#yHx{~E<3cMVuq z52#vsPeHQIT4FanHxwF>>HA!yg_NE?#O=OttR~_C8>w-w7Jne+e6tLI+FZ;-`c2t7 zK(4GG+#>Ia!Xv(Aht?uch06ix@Xf4jghS3qDJdsJsBzF5Xa=CsL-{`@k`ziZtT>r0 z7T{j5LF9O&kRa!n&~S>ibq>D19@L1H02OVApa@7hhnDro%Gq6-INABa3p2SD4MZ*4na7{Yugn82 zj?g-cbuoyqy3Z(LaWox92T-~?+B&$A`Ana&1uLva)zI4UhXuDETlU@22XqUxgAONV zCWmdQ*wnH8wesd-9NPe~&FLbqkWg@!WKoNWhWK7swq{w^b)I_urL|i78%O&~9uDJP zGuLC>e_{H0hwqo0EIvJE$M(HVt*;wDc<87r4_E=-G&p7(T2(5cj=ZN)K8y!ZL_99g z?HLHYYKNMeqaqWjVTmU@>uqHpJ;qG#It|?82p9*d>6Hr&xK!OKuqHCEWxzCr6%QRGMMgX6QrJ#O71d5K%jq zYihEn{YLd?8YNk_dVEjN^UGF8($hQUW+TCSRsE<}odt#9+1T?e_j$FgC)K=H5}#3$ zDZbK0hs94jySdKsS=-!_ zIKgMe&LQM#!yqXz0zUm7_Ag}cvsG8Xn3(WyoOH~)=}jU2Rr>3%SL*+jarJGIcgc*v z7P|$t*3jFlTKA(!yxl8RD*mbV`ASW6N2rV`;)z}{2ZxBhuGlzFPxf#NlqwDp33T-r zOPQlpzc#J49ikJS&_V95g)a)>UyHm7NA;aAPRH(;`LpEVTTREXl>yNX$!cadrMg8O zbvrB=HBJg;n>jEZWsNGZniW}(tuOp~kDVq~?Mo04g*OF5O5mY4EikEe#(aH7>A|M2 zyoG5xw(sK#zgHpPaLEwy&zBAk?<_3Hk+ZcHVo8^9!Ycghge`_;&AK*K^Tk8yk&Qhn z`?Ofr>ud`4zRvyz>(pjy$GOLCqUp|eDf)L*^rNN{Vp0>mQ3y`8;M2u0v~hf$IVn1d zBo^T-o2AT&Di|~z=bFxYZvT!+ctGH!N~oe4mXCMg>YI%0YsO#Nt{5!9l4S?)906ve z%J}B}%jiTjaGZ2L-$1;6|L)2~nr*1)k|M$)5`mK&J26cx-CqPXFb360r77^L%3D&# zL{%^7i=BQ&(0SG=M#XZat>kyhxnRVVh&K`3P+E0wNZfda?ZO+PvOrZvC_B5Cpd|>F zyR#wUC~8S*N~z_G3}Ss@BI!=xU8E&Z!a^wHqd}tYtWl+gO+hq944)IzoV7}nz8_O_z3_cz&*%E4FDsy&QZP9?k18unM(IuVxpn z&y2lJsFL#)C?B!hWJZbVzxUx3*yc+9ra~Zp!y%3Vh+{`yl-8K-FCsJ~CPEOwiSQTE zKW#NfN~)cc1`N=3{!o(%A$8Qd7)Ba=U)sp3CRYIq!|{Q0!M(lyN1DQ5OuYK`r6iPt zF7(m=t`={fdYh4M5GXjRJ>y$`tL=mS*r9U|DivOshi_3Cuod~;M5qSPNI5lc>99F6 z0GrQ7k&-3nZZ<<)!dcC>IJqR;Q6ia@p}g)V^Rl#>7Ra7XIe#%o99hD=bj@@${Lf?? zKO+)O)J+{fr(vbYW-nEsvdt-_9|La833zMAMQdr`yZ8{I;HU;mpB?iFv7k zl2t?_VXWLKEYMr=bCIE3Xarfy`DoRpZ4;4SerqFqLjfq4X(z>;X$9syzBZ+!gNMD- zOnGAJzGYdU93a;nFin8YoUm7~ob;xRWZ>6tQxl83gx`O{w2ai0f`?kc(WwHz+ljNE z796%Nr|os@PFvss?y+F{k>UgU2nT{MsTlcaBMmd)7)g=c)zV@gLZyyieW_f|{G9r| zNnBR|_u1FybG;zg%HE@M(qXo)wmDdoM9h=umTMCo$eBAx(RGrPWfL>eK-+I?GjiU> z*ZWo6a1&ze^w&l@RmSwpn2jQlDwcaKpCZ1~UYs*})mSg(%q^9wMVGJIWBOVvCl!uk z!I6oQz$Xd$ikDYOrX+K5mPR;Mrkp~8%A(o1&9#E|g<&)Qpt(BueYJhp(DTLlt=zZ4 z`g|kG%e47=Da&HLx)pzDc-S5udmol*x{xH|#e84yw{_*ThlpYL#&TJ-d2H!8|+R~-K zpKO@mRD@00fK^q+D3~}WzE3fHx*XVIZkO6BR4Q!r-j{}*BoGSsLyje_Qj*pqV?oc% z^z7h`mFWoFwqkM*g=ifmI&(rQN?4k7Gc=?$QkA}_5wG*c)Vr$|pFS^44?}fc zf!FpO^H)Rdt0hS!^BEtd7Ebn4(@)v&xA@8r#7`h?LT#l@FwTZrsD{|sbei}bMjg`& z?a(sU4?VVejbqd+I<)L?1{Yy3{WuwR%@kpLw4rg#Mum@}a;|31;$)lZ=+O zHtzK*XY7xy`fCq8Nr)=DN;2jm96!&(Ix82IaSt&cP-%Pve#;cs(=leKnOFq}%^DBMz`uW6Q5*`#5g-q4l3=pa&`0+1Z#$ t4w4#dBjk+eio<0v<5u1z^49_~5YRY;MQiInGXap#j_sZ{c~?hqJ*(cRrG zNO%8GKi}v1y`E=(?B4Fzxz2T+bKWPecZjO893?p;IRF5lRFHrC5&$4zzxo|c3cUJ0 zDAS+6dJvh(D9Hc-g&)07UxZ)%XETz2sRRIc-UR?q0RX`9<<)Zq0C0f;0INs<;6XG1 zKyMfQBX$4)00LB>t3UDe@#z{^>+fn^KE3GgZW`=uq2{$GOW5x1uev1sG{TMD@P0YaZ%uYOJds=&h5`h#c%`@cY(N-7+%XflY1M({`%r8z_eg`{<$yL4*XI zgE$e5pr80A&zN$!08b#w?Usn6Wk}ulP;Y4ANc-$XM`wF@+E8mlO<>~B@%;;rfJj_b zX?s(hq++mBK&4lF_YIymcZF3JHZRH>=UYZA)vQZ+9{C#u=Tr<`=vt>g)=Tg2Y143v zova=2>A*+Tk2Ux76!+Ck%&!dfc34D|3rcIpRcytk7r!!y@9Ayu4aG<0FS&ZZ8=mi3 zY+LVWt^HazIo8`GCo9#|I~tTWd;eMNi=4}?^%YWfCqkvlmcF)u@hMzK_d~T*L+?8H zO-o}Tuxq0ZUDbs7au)2|sK3RjHr>`veQTxq( z%{_g!BVF}TMLkbH4dQX_6XRozxQgD+(e}N|?zYB@!=ui@0ci=*&4Y{g-u8N-YXp)J zjm^2OGfSip0V!mJ=BpPZQ3{9#iKJ9I*?H(QS z3UIsJhtZ4G5GRrKIsYyVj5{Ps4HL95%hHRlv;XJ>hBYx78d7k;Fx zvAJ35nf}0VL+wBZ?AfQ$zC~51w3gNm|Gaj71N_0x#$bQ5)5l)F&~KwXC5@wlVWrcz z5zeE{`2KqAbDP-w?iFoxN>6{o9VVs0!JdJRy6SeEfvy(qbuyHH&|+udaBr26^pgWz zkAs7KPt#Ca%j9VH_-O4)Z*yC3M{|E44rw1D!KdpGo)eU}o0|T;q^4adxof;TeW1H_ zpr_gSMBp<3AfTe~SVrAF!SJ`xNg~YQU8P0xP1&tEIY)5OuQRaXyna(D%zd>hX1-PR zIMkr_Hl#~iN+4*K35c(@0)zXpg7TuAf-rlZdBc{tCX_z|*1={UBm;uQqY0kk8+sRN z(Mmxvo3#mO1DEP~-^G88##l+WUKaJZs?e2D*poT$FIo-vaU*BhKdLxM2(-9-uH@6hd@* zBmzZlPjHAPy_l`*puFtPA?Gnfj`&H<*!qlF^w%x|2pYIfZJHbFsr@i_!7fTeatsH; z%yerb$JSMu`{|X}FQG)@x=|=Xf)!_15Gc`W8v4!}3QdDH;FfCrHQ{$j$kD$mm)V6$ zJCrbw*v3Zy3Pjv?-gM^NV)8^%FiGNG(LuD#K24xf7b;-=9zKEyd>k~L?9~hwOZq#Z6f?#6lsf6)Qpj^pfteO!y&o#Gi zJJl~qn`tDuS7#J#<~iaLL)n|2UD+{m_oBS#wpd1X&ewptGh=}4jEgF>5G<|B6uI&p zU;qo0Xi7luNMG1*&Xg)MJS3(P<28gE2vQX-`#zU}DTL z>0etc%&_T2Rw0x>srf(&?*bbk@ikROIx)uPz!Wr)oRMt+L=1K;5FQe>ePHE11pQwA zJ^%aW2eM%7H%C*g2pmtDzI83Cj;0poJF8)a33^oB!{$Fm{Ib?9TU6K`B?D9r{$x@Y zX7GZU3t5l4^=K2-Lmm@>;7vo$9o20Ep@?kRRGGb_BZ44cKlJrxblF4eY*HG>v1VMs ztvO4byi>XD`+pENwSTxd>~>i~t;GQKg>MOZ8?Nvqr@JvEyhF%1%K{Vp2}Mwa#|loE z;}9e%&o#u5h~#GiS=B;eP7`HvAn;NS(}cZM5GNq1?_QLFwx=6-ujGO-_oizZTOg^A z_ZB_nHwo6JBaWP2x_d@PT36^Tw@4L6beDdz{U^B1O{QmUDNS-e9?_yoTMNm-Tg7V_ z_!&s!zg;}4ltWy&Al=_gZ?xJEjKvweoVpW64I^`w?jZq#=LFD@m<|*fQ!p_DG>N5R zu00JXLa}lU1d8R6$~*W3ogz0SB!cu8-ojiniTkpNzFx1Tp`og(omDGqd!H8t6&7`d z0g74iP8h2to26lBo(y3y0X0Ge#lDwDK)MVFP24r^lEZug-^1NXFDwjB{hS&+O93(6 zHWmaJFa%o@)@5*{B#_}5FiMxvFy7IUh5j!pm(u4X#63bOpWDj_&UvaeV`O63qhyj~ z-rU91#j+y>ARrO|uw^YzD1aVc|AT^o&Qu`hK|KVx;ITf{n1bJ8)$FGMII!UNvEpDS zD3xFdteW4evw+=B_GU}&2v9zZfG7aXpu}0<-1qWm_iV84FitUGGg2?)$VYWB1x3Jy zg4QxBU})9%XyJQwF!?ArOkGHLeKPm@w2P#sy>i=WDR>PiLZoRU0eG%>=<5SP!bg`D z@v8f1nHdzG1e0aKRL{uxnyli!q{V6H1HPB4za=a$$3S2MQsOd zt{_!4(g@!RxIa7IRP`j}4f&T%2_t)gm~j=MGeck|I|#GKZ|)=nn_dWDH@JWguMN9Dp%jGE9_o-1{Vb*>8oVSkTd^cJDfh-6_*? zu9h|z`)sr0K>LH@m4Qvw7h_`pVQ|Q7FYPaK%nfiJF?e!O!u7Yg;f&J|@;jH2HD6_& zJtU?Rb$3z(jk;ki`r2p95-tw@aLSFb=!dclZM;g1x?7NK5RDfEVZ=AJ1T-Hea5S7H z5IVrm0xSYnnnJVy$WoNR@hF0l0XK{3KCBQ%2m^2D2PjFmvVqCj zK&mXev@!2e2#5kx27urXHf+9w{A@%&8z^EJ(OD%@LX|tYD-*+zS*e2k$GSBjA6MHjN6L-hq$UiaFALl(S zO-#+N_-0#wIPLWi<&m56#EK*9#Onc znzUqFCs5fF{#AXV43KS^zP>){J3)_?oxUluH}#1?IE}071X1Kmof8q59Ly zB`46*f(l}Z5^0I$=i6C29ZTLF_!9X{l*3Kl&N^SW>R`jWJUe99*BX3s_HOn8&)QSL z&I;%7<#^iZ*2L@NB}gP`0=@uqmFdhW07Dc}Sk#Ul8>qfh8;rdggBk!7DK1yzC@;z+X}2tMJZ)5f5V&%ks|sLM zN8i?m1DTJcwjI>E`Y~LL5dh_71L_pMvDbejph0{E-&1*+)w3xy9#wA$P zPjaO8Bla3Z^e4s00}Tu{bHAAgJ~ZY9m0=B zP3T`=gmBTK`yoI}?ne=_DN)3D7cwL_VU(<^=kh0Q*3vQwq8tnmRW|@BoC}*|m$2t1 z9E~l)8|}JXNoBBOOsLedH6O)7qZawK?|HU(?M4T@GEjsj)hd8U*)p^ZFu4dkdXyr@ z_vq+I$^%A23SfG7S#FM{?={)#HK~~5>zcV<7xsduXWc;-ZNLXC5Hjv*9r|VJo-)K2 z#@CSYtt&-Ks9Z`LiAgc#y9Ps{_FHMWz;BouAPuB};4nZOaiCNRfUwNV1(nDQ!Wd(g zqW`8f9=tyTh$A&#h7SM)g;DM<9_tL&4At02gro`YpokylA_aN7hDT(9Zd1~P!%D-E z`hfl(7fhS%a%}E88-epxM1x)ftW5r-vs$kr+XNWQhUBIua;1hsPaN~Ase4Ovw@gX> z_)0ZEx>N-5V&Fgh_S|Ur$1-^C1WkMcb0U>3kh}(==iP*x91+E4y9a(NSoGb_@ zO!Vwy3OQ?>A?_aO%UX6zp~qIFyrw=hU>TcRkG)8Bqlxq1(hOc@$08(b$&Kvw)L3b` zmCk{jX}*1CPwBdd0*W(7GLDh7&pICP#Otd7H-OyZMDKcWqSvU@0zN9olDNHMA9 z0E7Yp1WP<4X%-6zAjLa013*f0$VWF~@hNcW!g%(Q2zH0@kilApXUTTJvS27w(<~hg z^jvHovAhEd4tvZ|GGETKqgT zWaN$ea@-$Ci0pxRA5j`_n3`|K>7N`fT5}*JI*{*w&aLr)t;&zo^}Jx**+w( zk3oHHWdzr&^xVdE2lH$xeLYr6=-nD=y;5n5?>NotPfiw$WG~DWJu$oTz;=EV(je#9 z1H;mlo}iQ?k#I~Nr)d_?zY1uw+!`CtSDSvXRJ>Cuy<9se2;vE_0F!`GHcyZ{Wmej4 z57u#omO2=vR~l5CW=Jv9#;qs=0X!`WNc9`b%jZA}%bo(pXJ){*H`K+gb_#oa&@BWx zkPG=WiXfm#Q8WD_0H99!-HQwy7qkOT5n=?-q6xqWcV__pJ7^QJ2u$|#SRh#vzdarB zt{MnaTBo`{m|LZnt&^>D--YB@Fr|NHlP9)1f6^E z*NVelVO0rI(z+T%&kCSIziA75+Vc$Geqq7*WHHg_$zg+H;_aS@44M#)_{dM&ZTpvpq(&M|N?A=rc(;jin22OPo&KnZO^R^A62926xcf~eKl&~0mQ z@%-o;n}usf0Og5()aWOf-@}zEwsb*SwRmPi>sfzxb1-8Y=r!mDZW06w%nAUj`4Sap znkjcnni9WN_3(+2QI#@=$bdEsVjK#J6xZpXLMcFG(1J)w8ITwviT7_ZLJ(*cs4j{E zv-ilKgu^8!m9!bGD>tOgCzg&J>8~z=lO8(wFy@?vkzRtVRBmRL`wY+sXy60e1i;f} z5W6z^KA55=kdT`gife2o0r_G!IWDZTp)ZN4wuJ28k!^|Wu~w;;t|egc{E6pV0K*

0gnr`gO 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 diff --git a/doc/interpreter/java-images/image005.png b/doc/interpreter/java-images/image005.png new file mode 100755 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..a443b7e054d71c9120a56ac2ff36253053c381c1 GIT binary patch literal 14327 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 diff --git a/doc/interpreter/java-images/image006.png b/doc/interpreter/java-images/image006.png new file mode 100755 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..3cf5e8fea3758c0b5a7f101a1f93e6cb3e813c52 GIT binary patch literal 13754 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 diff --git a/doc/interpreter/java-images/image007.png b/doc/interpreter/java-images/image007.png new file mode 100755 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..c9658c727e30a0278afdab266b7fb833b02baba0 GIT binary patch literal 14931 zc$`&vbzIZ$_x4~gYJ^f7jfymk?h+9NBm|^kG}7G-4kZn`LqY*Tx@&ZIcXvw1eyE@C z^Ljn}!PuL7_c`}&jSam2P5+3U?EVGA zT$omqxqKNV9kGu+=g(chTV zyd$G-TU+^SsIO~$sAqn9DmycU1PXg8BZ)#?^!0b@YN-v4O%04poE#l?5BIsgj~^WB zL0zK`cDHE+Jg%-zJEu;AvIZ9S?xdfIPtGn^wQrO+_hq#oHT5rer4G!m42}%6)3n`c zc@>QgbWIL+o4aPH8+(4Q9vbg!ofsW(iEfnCjvO1R2}o+09PPQ-+#j2qt0*a`8M|q& zuN>-Yy*fS0uUlK6I^4fQ=>=BKO!R*%>_AD%-5a=E#_86IxTY@2Kuo~=RF-`re%AGo}`z4$pXGu+)Z&|i~YJcDV_ zI?&yCc7EKpayPfK)!Ef{ad}(c+CA3YIwKy_0Jkl@7$2BtAwzzY| zul89{O)D@e^XB$qyu0h>?s9Uh>9vl6lXnvX|7+CkwM|qLP$d2O=5B7h^H)>f^l00} zWdBPA#qs{0(Se@fzK+qJmcfCJk&&MM0puO(dbGE#ue*P2xFhph?%nP6SYKCKT5?fo zm6uO|ZsyHI-#}Qwa9>y5b9nNn%Jzxrww!_@L%1Hs=NUsI^YMWW6_qzA6l!#^V~#vi z2LRw7e)U{R%{|#@RtOoj6dfrJ3_9{e7+miQoX!rOm``prpY7j-Nh^)-y*dE12Nz>O(!x26feD~uh2)EVa!S!xY!$tASn>6DjytJ zjhTciRX5x9_4w1fPc$HqNsL?bQ?zCo9}q8et(LBzJUxZnqv4P#D>3LB?ebkM@tbu8 zv#MypqF>kYA3}PK5OEAHuf<#n0BEg{yo}Uw2O((QisE!ZSu{1Y*2pqR)p*jDiT%2R zX}^UIjqjk09NF##?y0PCzvI+8&TKUu_%ey&0Pp4aCi#&2?-|1dO*-rc@8DqMFbbTm zZ1h2^#ol84VLM9F)r0ZzD3t>Ubebe-jk`vBvas2xvVuUps6s{R1k&x$*Dk=p@9FLr zFhvDOopC9EEEs{f2>+z*zH&P6&SODzZW3DK+Xxd7(Se6UCjrJ@#+4m+0j_G?YvW?` zivf7sAlJ^3SoZpK6?4N-_5Drhm)F5IH>_NU_l@k%5VCI3IA?@cStc;h&>Do$ zFd`M^k~bo2=lp1x2RIJ9QrqA3UkfnwXj<|I0^@@v8($NJ_ks)&tJPpQ7)W^NTvZbLi?>HHz&ROc#evve8VO^0_8KU~p*g0>%m5MO8x3g-h40<=B^NFCNMUi&Bp zf-7a_KNR54Z_z$@=JHNrds1z;cif?`*`oQRmtxO##r7WN z4h;~4XeF`G@OWM9!Hl}yhT>g()e`O32E^s74{uLArm@efb{z}>6yjX8FVQ`ehlt4} zjR>PKKVTy4PY<88z|bI9SP))Y1*XBOjL%#^bSNaffL&ZCwNvyn+D^b_Mky6`fcIRF zq`P{OmXFIOUt!WVoR4Ru8OBbLtU@qdyYKpbrkc%Ci{xZk6A^Vodub2~q*u0f*|e+@ zJuz5s9Pjs%BES@>pLTPyadZm|zp z!r)C-gdGALu!w>d(IC$LgPc?l+^4WQ|6o-_dju5B1E~OHOv%Z@MB5fSi%Z;0i!|-* zidqSODSlL}?6;|zai-ne-bU~MGT!FJ3L`}j$PmJtG#rdHh#5Bqx3^K%z@q11IVLt# z7a9+Zj|*6go8yp@oP8t3uuewJ=B1lWeLHUB)eOo(zp=eZs~>sIm$s zYeRiuH;Wdl78vhUg?i3Kzyzt_lO2zuo|B`e2XLk$-TWUdpYVw!!+RhYYYEap$pn!7Eze1yX$vPl7SgLIW#pPK@B#BtAEYD~onEy6TqwY>lY$82xUCsSnu-nU zVNVLUrMfBFnTRdN1wXia@#>ZzjXwE22)LTlxn}<%`DuVlsIV?Wo^H{*?^@U~Mz9o# zQ-Q3$_o?BJ!;Fz}>^!5@U?NEcNp%#&68c3aO%AeP6yGSEES2wNvxK4CZ!CD?fX35q2n;<=Do^uoRceyLGPuCfo5`W#>=1mul=6!8541bYkI zlpdcz;5_r1$pj8S5KD(y%ir`~&~EX8!7Q?n9MR;vvfSavf^Q?FR&FO=fcybQtHnY- z-uTGX?eW}nBVNbq^VI5h^n{SJr?)qPF@~WPL6LzH$e9^3ymP^11xL+thRLH7Je$bN zB8<8?3h@}S)GEIoFTC%i;kc}~=TDNW<8K^rf+T>*XJ{gzE?SL)3#SjgE{zw9vNuuh zLv0PJ{d(2QSL{7AC7QWzUXb)K!#zEpo));UywO~frh}D1ApQ_BF{xn^nAq$7_c@HP z=ZZ>T@E{2$Cr`%O(+XZp^b_I@9%o5bOZ#dAjU`3+bN8V(5=$FT<;oDHdUm!IAA&VLAm%$>V) zuw5N#G}$1??PUCL>#wiQ7s7Vf22$hMhd+Jxe2VGH{AeQpiLK@%Ptdl4`_(ZEXBmx*wUMdzxc2QWla*gh&aR)GRpMp-`0dIEwt_& zEhoB0-te%muGq1{>eODE`w>47-)TP2@5Md$i-%sCh&p{X6l}BKh7yq|v8Q&U1yX_6 zh!05_-VC zVCPe0W^pNg@=@XPZkta>fLq~B!kDv`0K=C6Ag>1*VhoFp$P2u*XIt1WCT#y^0 zzjMFZc7Eq!=aK2TeB|N5K~BH&564Sp_VbjbN5~@JQKf(Of^m*cErhBPCi>av z6WTLo#QeMw!U$nax4Q}`#}Ss&uTAes$1BKu4xw0Rc>~T<3-}iJ5}ptE5KwL|A3;{^ zjb4f4-%L>}==zJcSnu$G<^oziS9&)dh(oeY+ojy{2{yls+zuC;k>+Y0xu!XA31Mm9 zkVL4aWuS7Pd2pB_6(O}Ji!aR zZtKWFu{LHnB%19nRq|vK55Rj3)K`~lPPtTSsieaVg74j;aEr$ldrvsOJa+p0W2v+( zGdVkA8SL9VLxLW(nj)e|Qs=QKqH#2vqV+08MHoB)RlMQX$y+(GXlMy~zweqm(0Frn z8|)O$c|wJTIAjzD=YI1y#O(EHYcf;iM5=+{p6F*z-2suV=2hu!j=agdIp7L7jX}2^AdsHfqaNmIvdqPCLnT zmRkR)gXN3Tp=-A%QqwC_-FjsLpL5fvg=>Rz|>`N}8SrNidLk1rLc)aa zydI>Tkdp5Dba18y90Atmq=csLDZHRFiEjh2m_OQ++S;On$&|zV-%vezeTg=c=zGH{ zr0;kG0G+(YYx+%sYw0j=mIpN465f)LjNLd(U~uE_oh52IOr_^=@HL`B`XUY(&(oso zPr;Lwd4}3dNX*^K_P0GhxZ>wtx@UUp;)}N7R_=pSG!FyFH7n)+yHf2;cx$cg`jsKV@c#%w~PIST(Z$GO} z@2fcRYzca0$5J+LF)tQknEQEQCC-;?Uwg@88VI^plkEqV$l;r(1!9<6TdhIUI4qSk zw`T5pjz_0X^%JFFiDY9uAA&!s!!@LfC#{jRzxYe@oBhwTSu0BvV6cXiPh9?`mwy2I zeqB>y3ZvpWQadsIDh>_dkA_hY5)h#TmnI&4Y7VI6gHq|w0v?z}>CeX7+dc>aAtUlk zDRk7COc0Q!fa8Szu; zC&;=dAYK?J4v-t>4n`guxbGusNA4&(QQLVbxk&$O7!A{uz(hyfRJwg{qcEI4Rx4t zv;DJX40~P?$*U}|2Je7Ry{XG1n)@cAevQ-aYUK9|46}5KS&PXk07;W)L9qYYkr;=h z?#wQFTb{iG8%fp$2r6&ZkK9YoF5WFYcHDXW2YyWgaj!4^m ze=B(d;!Pz6nn=?RCYuwo{4HTC^+I>xg>I36chdVC^3hc$fYXMI2xEICs)rNU51yAM zkN{XX4kbZ@lC<2xmd35TTamaJK>@f567>GI;uOL0*f|->mtg5tVb*)1%lqPDFITee zed$OBaco#!#W3#IO75luuOQnB=^^cLi3|*wEy-1MYW307%B0v?-(|_MN(}AE-hxL6 z`6dW(7q6(5xpIS|f!OjX7(dVq<7Z!`zoQG6PN4?ROv%0Sz?;RwrZfAjZ(8{wCyf82 zCCXh~&R3y8MMGnOpmlqsE~wi7V)tjiw6~<_6zZoR2a&Az$K?q0WsN!&0&@S!WeYkh zIwDz{?OFAZaIGvhDoMx>aeFCab!H-zQSGuT=7-1W+j0^>mmt_EReB9+HXWEaWLsK; zyuA2CnVN{vuL4Ut8w(c~S8}&8)7p;tp&5U}F;%c%y~JYPLxcMleUmZUbb7D z6-s>#`7V2|^zgo`Ovxo^0id;3rJr4WWFU9tqEcN%}=Dj88Yo*slHDjbCsVO?do0rE+ua+1G~Fqr(TgHgxtJPA=FQ6qLrZT?_Hx6(RicN1u+Aft&le*b@Atj;I*>M4UfL zl{lF#`Ni!b0^4LUB7#JztAYpRIucAs-bzWXayx$M^Y7-1t8T_1Vsd*VGw1(Cc17P zEi^wei%rAd7dM1s8+;56A=zZ!60(t#5nYKN^J(jmQMd<`PWN*6y8nQ(NpiESj`)OP z-IrvxrC0RZA;osfU09mIEnqj&Gg|e+i6)V~WEU5^9X>q$+AhZ+G>Bs4DVMdwOfr9S;Ba#wPbd%@L= z>E=pvwoqIC$&j&F?^M`*Gg>{J`^Sd>G&+Baw=cLxd92F~Ki%CnG;U6|nPWasN~2|3 z_@Vowz3DI|Lp8cNt{5!{L$ZhIk2B*lzg5}p4o1yBt|(OckyG~={8Hy$PC26P0fF2G zLw}Wb2fv0q`43_A?Ip+Duu4>LPmZm+Sf;I4Qbxp5&ERm!!!b_6fN~n?jlr$1|2Brk zTztwvZY+K^dABw9HQt)>Z9eDcsBVw%oExba1*fZPA~;E~mw>YH`)=>Y`RN68p3DF3 zx3i?a#;fbzJs~!cl!BJF#(}&228NcL$+P33u}=g%KP?CR$gY*n(paIf$wu(WZ12j7 z@b3M`P|0gg0NV4@01-_|A%{Mr&iGk%pXae#n)m~yGA$A&K*-Y`FQx~B2c1oTdFgLt zS2I0)kL#_|MMCN(%27Disb=?HB)Wt$dbR&XD|N}Q$evp7153=e9qoqpj`@1|Vxjq@ z*NcKH$82#9PKq^*CS_PR9uTq}ROxq`!tY5l@$_`vZ$bU>!5z$I*&Gpv1Fmax^qb{= zy3wHd+F}jLC`}7{eXCI@nmJcCZePTMwpNBU*g*3qD5)8o#w*Q~hKyz;+yvA7gplTq zmy&nTND*_nD(5PWWuz&kzrEaOG+w>|O0M61Q*QDp1<*nS_wQZ*%B~3-e{ZQY>r>to z_ikmMofvwvhMo-dw?_H7A4-9U)A=t$j={Nh!tuc`lza46(KVr%_fd~K@*Aog7ok+J&++R!Ua5>p6EPL955oyI9Vk}V=xR@A@ZPj;CZ zuQ!ANtFm$e-2(M|s^?$7S(J{DoaRNaJ)>u!sgGWYxYa<2fju`M=h`|COG4HG(~*Dg z#gI)8nxmeeq?(YUe5fdY^)4SdEuy3bwa$Gos)?7a_e6iN+vW+Hg#qC`DC3cq^9%=0 zCLb3X%s_~O%DvtY+oA^JrxHFKh7sU&G2weX>Ghk#tSI|xnPeEPjQS5ARQ9cpi6Y!zJ<2t> zt@9T!oLZJ|Qxy7}snHedWzPdo;b$P+9?G5And)t^i z#kw31jT0Ji(UrI>&LBLqk7bUuL;qcBVHI)0o9?ZKt+c7}s+3ns5xA=m8WcJCdFr`i zvn8S&WY^c*jk6hNe&`N#9`)xW4m>^mYn17Fc=!N}3Z6)Wa_-00d=l0fI2a5z&cAVe zAY0Zw(kHj+XI#|_t@Yy$%|L0>g$r+VGacdlH&W@%0XuI%r)^ zKMQo-dOYTFSJD&IqB#Ldb6lE&CHVUe4rzdc=#t@k{{r*+`|VW4m!;9KKZ&8-JHw$O zjix!TiIzFL46ZoOqqTaipxRUNF8|#*zT(->Y)(xryKh`~iVdxY&Z@;9TMNEJcO-LD zF<~}yG+c`^ghPOuGr*rzoR}dQ>uA#Tjio<%VuvX`Wz+lx`EJTi54v0@&mHAn$P00_ zBK)(hsoHo~nsBcYKT~eGyuqw^(#m-=f>CO>dTm2kYd12LU*shC#rPZA{}mTLb}Nyf z!&E+bs%`$C`VF=tdWh^c+k-t`C*M1x&R6lzu3j+!|10}!=?Xas!N*+I@dlJ}pLd>A z+J2own3vongLyC(K16evAJVC9;nM(YWdEv&JRYq#gmdTCn!g-XhVfD{AEI}}3EK!( zJI$Q}rUZn@DavsuVVeI6S2%ZQ+!Bv;{6MT~!pH)Pl|gMUOl%?dyyjE|WF|d+J%I0% zb1~oJr~%el1gjy7lclhQ?}7ov3CrFqaD2qLKp)iT1p4%5ez0%wxBJX_N6C4A*vD!f ze^7x1WzM%a*9mw@Ij=4}+?R+p4KlF&RfKSN zwp7(c*6yHZGsMj)lAZMGQJJ^Lv|oCxgx}S|oh;DX+s~hlw@lFGS4>%bS($T8Sxi`r zbGGx^`+Bd!Z}|lrLuBH9cQ<_}0>d-I?->=X-J=I1_Ql_zMfI}YqJ-9C@1>=n1in+e z%#u|6>+_Fw?mmVpI8}KxD0@<&6&>3$EZu&- z7t+B(G^BN8{68SQbVgq%ydnp?ij+nl#s=kB60suUT&BgvT zv_cw)fKxmee3`7RP>96OWv=}_iyLIQh1pq9s`!EP&w)0(Ydc3;Est#}N8$JF&F%Lo zgq;=s#y$NI@Z61CK|p+QP@lxBaxj}GS^hnPmapfJu?TlWe%dqyYBKPkY^gAMmp5d1 z2digAl*98EjF;r1@001Fe%Xg-A;jpji&`T^U@ZaYc$$%N`mE&NDiHs^x+Mrc*xi-r z_^KoLSO-i&!6929@m3p$)YfCaHJ$6)ic7k?0Lnby(H#2N;jMv~mK!qr+5Bl~2m3Tf zMdxqb*{p#PPHwjC-OSmo3$&^}zoR62Ao3xiSUuVt~8SHrTbXn{m#7}t%ld&+6_lG3muC@XcRPl1fk zm3x%S8hbLc>P!+K{d>FqRr8j(j<^3us*T0QtdwbikJaCgu91+kAT8bL@y0JY?YE+9 zXxaNuu`}uM$X5Me3GA0Qbm2xP>3@i?WjIn;U9G37sk}1CraQ(2;d9*!?KKyLEp+&t z;sJ}}XVI)bb9eqIR1>Uh>md0?7Izu&6D#tFm4D7q*lAksWuapm>HF^7(lnA z!=(R^V9V}K`GWeL#*Dh_=Zuo$@=g{)Q0#T6)2#XWcWsz%Otr^?x}I&+1nO*I$-oOD z8Hc$fY9RN>`QVc1$j!5IUXcH3o`%>jgU$z?%IMSalE#2~tGsnQpvxPQvLdYeKw41= zC~!+iY%Hq&+Iskv{~%fO`YEfiWuGYH})r;$}*T>T*1CI@R&TUHPT)C>cs_P|4oh%Q`T;bgf_EzO`v5V0XtVoU2=&J^r`Zk;$ zl5>pODSr+MFNI(7U1$_wN}H+yn8nQ-A*GC0#ecU}c|q-Xr`vZZ%~+K9YG|nbo!?=J zo^20gy}<7x{k;=8ESZfgwPuw2)YM-BCR1qaPDcHq&mIO~F`GoflAgJJ0ZP6Lqfb~$ zWD439>z?p`*7Gk{jo_OswcH;KJ{g9Le!mS((w(-)Aut;!J)1SIJ;!QJ0@Y2*SSIaY0;I zef%gM^c;Hj6b(EKz+$Y{n>wza%$SDzUgJ{l91Kr`tpu(5_EQVJLwnGbLlaYkiI{QY zj~ckkX7!jou`Z9r9RCSEh}HrAlL-4cm?2E)o!}M)k{|}_HU@lEUEfx!7$$<7xiM%l2G?!_Oc1CP1M84R+ zG11a+(ZZvE6jm&IYM6+c82^IxI158dg)Ji|yUlM0e#TgzV`` z9#Fs2ksv`?`dnTXa2$$X`&E&9fOVmm=!63z3@#Nm@9LF)y&B}cZ-ZddDi6+~IjgJQ zuGiUFW=642!D1>b((LWws&cDE*&@bW$5tT>!@lc$1>vkaaJcbB*KfkOOEy{*kAJSv z8oja(&Eyxqwa1(iNfpW_ft?taQ>CReTG5O#+bXnD_(P9G_HQ?g{l&+s(Dt^T@zb8SJmT7zEP1{lGrfy^vLGOj*4z@ zbvDWEPQzOG6**!$kD!OY%@t4D-;0_16IyQR*5 zHU{<;p|128qCwY7_ZB!)z%Mp`wWZZj?6Q7ug3GKyyxQY|2?vPRk-(C*eDqNKwqw=& zv~pc{)_QP`tYyJcr`eK}CU}Wz$r|tN?G}Gm;jvziBaGLxz~*i8?%mJ*K1v?#6#>cX zMm8hCGp?UeF)j9iQ3*f{qILx?ClZ5E6rBe><0T4popp7c>sP}@MowONV&SlT?R7km z8iOunv55@H$Vm4v5;xQ3Y0JUNtS7I)$!}N=kW3Bc^m1Hpl=DA&2YN4Qf@Pqo$+)nD zR8dh&U>@iGGeGR+whW76E;d=N&j%|il^7l*NAc`dm8tcw&XDyPgPHUKuVf4yY)wv?#px%`M{4S7UR+k=BZz8C{n8po+~vkg&i-MW0zX-HyzgM=N#9?$=)<3w*I|gg zzxC^R>Dq|p4AfWYw;qf4+-O1jQ}gASaA-aY;k*!}4^mpI{+QvMyKpxfa`SBF9Q>~_ zvl3*exwv9U7~sAcf_HxS<&ehT#+y?T=Hk(bvzN}DyCvZ2mmSj<4g6*!oDXr&_=8L4 z6on!p2y9M#8bQ8Z>|mg2-rIM0!Hd+|8kZ>myFrgPj%)F6s+C*O|BY5E`jdV7*b=^y0EKqT~3}KGCjB=4e(H>e& z$|R}jp03A3;79hjYxq>t{<83gqoTn-ZvtcgS?N9rj8pO1ZyiKMih_HR8iir{pCx`< z5C)mb@k!swi6rOB6NvxU!kW*{-9GUR_HkUp6RR|qrFFnky3VaR+s?V(XX&YMvo8{} z>Fax%?rjBI-Vwnp;+(q#h(@>LVH6+z?LC83uX*g2-!z{W zH4s!pyYA3}`5)4*YM-BfAG^iT@Oetg%ORSX*EqrF(u0m2!FX}bF5(q z^tEpMtAI20#zoveI#_BlZa%wgvl{44G3)orccut>gyc%pdPz-0koeFe4?W40b=&{v z(mexApPmxX);SuZA;h9c>r-!o0+tePFc55b+FCCe=mv`MdCkjky7z)&{`nLw zw>IABNDH;xP}Diiu%bTy;`KCl!jlK4Fw+aGq6Y@W@gtG>#U!VA@AA^^ z0ODCm$z`w2cB@*uAb_JuWBaJUK^YJ?Lg`KOVP2&MNXvtDzdA+*wKq0(Y;9XVR=vOG zBia&bI_$S@00xU7TJxGk5MnuKI+DzxX#e&u&kCHV&!2Fe?XeGQ-a9O_6U`kU4SYTT z9qJVRfliMw`HA17!8NN=gGC$lXLe&M7SfkM_GKEZHIuWK7+dbrm^H+Ucn9W;0PQ5B zQ#7&tja{_0?!o$v%jn{F`ibD_gEOAq)K6{jIvaK*5e`!?_rKZX7!wJtT6_a;+0#+| z&ZA}!<(-INQyJ?rWI=zVgs6K%M3ct$RY}|SOBpq zxdQP4Z%BaNK7R)&JHK$wZA=f%AxC)kCi-1zq31x#Ji~bGi0~*8Ex8spFuK-R3-U0DvOY9KHKpa?DnQWyQt?Y zCc$L?|9s5!fM&no!LtC;F=PEXTlx?;u1FKpUn8b!QP(q5#6JnDb1vmrLGOJLbA4~X zs;kYfaR0GbiN3o2(X&AnNl3BCnF^hbTG>s>Sw3P|a?)I>LbINg&2IKvk zzfH}lBQcx$aY27M0fFa#c6tvUZ#p*GX1vfn+&_y1bOC?6$g-UseDc3~cFXQshE02SvEHL7F}`|)d@@C|!QwaxXH!-qiXgbKvS_!Cp>TJ{xey#tt={Ze}r?Y$aU14_} z^Zwg=BPaePF=^Ozx|axAp5ME+kwYviU%q+yqjgtK$h-9vP-Cx|(KDbBE+y1&!uZYisIL@~3FCE0Gum&Gs z*&j-BGH0R1uhg7;tKA3;tpBcfZ3g735hG4tu7c6K^$Fb!i0>}D+TCBu_+fLk4=pg4KgcC)I%$O)I(qDrkOf6k(d7^KdaPM#okeN|L`55|?V zAwQ4vLpAOrTg>w{+X{oI?3;px_U8Si$9YlB7A*6%AJi8L$MH*QuixAZ9TVif_TYr- z-&GA(aB8}IzG+Q-gLO$B+;^VZXCJ&Ib|0UN>E2wAD1gZ-;_%Khj?UHTs07u9l7TB+ zeEODivecf`5GBvlk`XMBJ|bRo%o%u|(ucg%TKx$FKEn!O2WG>tcj7xN}W-Mx%vEPuqP z&<~v#2>6s<{%ZPiq~`F<)j+$25>Zx7oHIKZ-w*F8PQjiC`jhzRu7*!h=E;-@2TH6l z$w`*;>y2_83e>TU()9#q^4HW*apjjn+hPZ6bx&YVzS*^uzh9uWP8^iaGwhmoTS>>< zD2b*+B$9#DIY+wquP72gfug~-FLa@v;XX&J)Nc17ta9=7+lBm5Ik+uY_xaOLs$+U4 zhmKqGHW;HG)Ov2*UFA)-h{ODPVt#d3HOV#x?9HTWPSpJB3IB2z#^^0496q_x+H~Q! z{56S?Lrv-KOV%5A`BO<6dLKm5Pc@E;^*J0O$#64bH`~+s8drvX)&gb>!trr2p`Y2s zIFsMOlm1xw{XJ__ZY3o!Q&lFr;pd=_c>IigQ2+-VG#`E^+&wVy+c1O2>HBpfJ$Sw> zp2RehKHS4Pxo=jU6z|K=2Dm*Nz~1b+?sxm?5Mc?H1aOt0($r?XF39Nz@a`|%$OVGIjz=P25n5CXbg9rYyw;jhi~%hvgU zIa;C@G?lV(G{`tL#M-lihEB2NkFy&Xh>PF;hw|?~K{;I}ic(%l&LJg4Nk3m1M330< zSj%aj9=|zNM-;hvw2t6x;R$xe+uJph-V>V(Q{@0O@D&{>-V;4I;z4WFa`1-%;_S&?gw91wZ7*r&9A`&gVXY#y!n&1#%J0 ze)=cR9tDFgWHQSy(d}9)_dVs)_{`$l7W8qx_r*6X~FSLM(b@Z~}BB_fIfBz=s)>2Hf zBs^?b*}eA7!Z(m^phJ2QW#T`Heu6-swB~t0*96%7(kT{8X|({j|9K^&`26QHc;Np5 DDl5iw diff --git a/doc/interpreter/java-images/image008.png b/doc/interpreter/java-images/image008.png new file mode 100755 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0132fb753e79d4dce0fb8fe8c14f1c8c506277c1 GIT binary patch literal 13497 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 I4>2D94_ZKbZ2$lO diff --git a/doc/interpreter/java-images/image009.png b/doc/interpreter/java-images/image009.png new file mode 100755 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..25ab16174c52fcc8f45f80f29428687214570a3e GIT binary patch literal 11198 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 diff --git a/doc/interpreter/java.txi b/doc/interpreter/java.txi new file mode 100644 --- /dev/null +++ b/doc/interpreter/java.txi @@ -0,0 +1,1705 @@ +@c Copyright (C) 2010-2012 Martin Hepperle +@c +@c This file is part of Octave. +@c +@c Octave is free software; you can redistribute it and/or modify it +@c under the terms of the GNU General Public License as published by the +@c Free Software Foundation; either version 3 of the License, or (at +@c your option) any later version. +@c +@c Octave is distributed in the hope that it will be useful, but WITHOUT +@c ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +@c FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +@c for more details. +@c +@c You should have received a copy of the GNU General Public License +@c along with Octave; see the file COPYING. If not, see +@c . + +@node Java Interface +@chapter Java Interface + +@cindex using Octave with Java +@cindex Java, using with Octave +@cindex calling Java from Octave +@cindex Java, calling from Octave +@cindex calling Octave from Java +@cindex Octave, calling from Java + +The @code{java} package is designed for calling Java from Octave. +If you want to call Octave from Java, you might want to use a library like +@code{javaOctave} (@url{http://kenai.com/projects/javaOctave}) or +@code{joPas} (@url{http://jopas.sourceforge.net}). + +@menu +* Available Functions:: +* FAQ - Frequently asked Questions:: +@end menu + +@node Available Functions +@section Available Functions + +@menu +* javaclasspath:: +* javaaddpath:: +* javarmpath:: +* javamem:: +* javaArray:: +* javaObject:: +* java_new:: +* javaMethod:: +* java_invoke:: +* java_get:: +* java_set:: +* javamethods:: +* javafields:: +* msgbox:: +* errordlg:: +* helpdlg:: +* inputdlg:: +* listdlg:: +* questdlg:: +* warndlg:: +@end menu + +@node javaclasspath +@subsection javaclasspath +@findex javaclasspath +@anchor{doc-javaclasspath} +@c - index - +@cindex classpath, displaying +@cindex classpath, dynamic +@cindex dynamic classpath +@cindex classpath, static +@cindex static classpath +@c - index - + +@deftypefn {Function file} {} javaclasspath +@deftypefnx {Function file} {@var{STATIC} =} javaclasspath +@deftypefnx {Function file} {[@var{STATIC}, @var{DYNAMIC}] =} javaclasspath +@deftypefnx {Function file} {@var{PATH} =} javaclasspath (@var{WHAT}) + +Return the class path of the Java virtual machine as a cell array of strings. + +If called without an input parameter: +@itemize +@item If no output variable is given, the result is simply printed +to the standard output. +@item If one output variable @var{STATIC} is given, the result is +the static classpath. +@item If two output variables @var{STATIC} and @var{DYNAMIC} are +given, the first variable will contain the static classpath, +the second will be filled with the dynamic claspath. +@end itemize + +If called with a single input parameter @var{WHAT}: +@itemize +If no output parameter is given: +@item The result is printed to the standard output similar to the call without input parameter.@* +If the output parameter @var{PATH} is used: +@item If @var{WHAT} is '-static' the static classpath is returned. +@item If @var{WHAT} is '-dynamic' the dynamic classpath is returned. +@item If @var{WHAT} is '-all' the static and the dynamic classpath +are returned in a single cell array. +@end itemize + +For the example two entries have been added to the static classpath using the file @code{classpath.txt}. + +Example: +@example +Octave > javaclasspath('-all') + STATIC JAVA PATH + + z:/someclasses.jar + z:/classdir/classfiles + + DYNAMIC JAVA PATH + - empty - + +Octave > javaaddpath('z:/dynamic'); +Octave > ps = javaclasspath('-all') +ps = +@{ + [1,1] = z:/someclasses.jar + [1,2] = z:/classdir/classfiles + [1,3] = z:/dynamic +@} +@end example + +@seealso{@ref{doc-javaaddpath,,javaaddpath}, + @ref{doc-javarmpath,,javarmpath}, + @ref{doc-FAQ,,How to make Java classes available to Octave?}} +@end deftypefn + +@c ------------------------------------------------------------------------ +@node javaaddpath +@subsection javaaddpath +@anchor{doc-javaaddpath} +@c - index - +@findex javaaddpath +@cindex classpath, adding new path +@cindex path, adding to classpath +@cindex classpath, dynamic +@cindex dynamic classpath, adding new path +@c - index - + +@deftypefn {Function File} {} javaaddpath (@var{PATH}) + +Add @var{PATH} to the dynamic class path of the Java virtual machine. @var{PATH} can be either a directory where .class files can be found, or a .jar file containing Java classes. In both cases the directory or file must exist. + +Example: + +This example adds a Java archive and a directory containing @var{.class} files to the @var{classpath} and displays the current @var{classpath} list. + +@example +Octave > javaaddpath('C:/java/myclasses.jar'); +Octave > javaaddpath('C:/java/classes'); +Octave > javaclasspath; +ans = +@{ + [1,1] = C:\java\myclasses.jar + [1,2] = C:\java\classes +@} +@end example +@seealso{@ref{doc-javaclasspath,,javaclasspath}, @ref{doc-javarmpath,,javarmpath}, + @ref{doc-FAQ,,How to make Java classes available to Octave?}} +@end deftypefn + +@c ------------------------------------------------------------------------ +@node javarmpath +@subsection javarmpath +@anchor{doc-javarmpath} +@c - index - +@cindex classpath, removing path +@cindex path, removing from classpath +@c - index - + +@deftypefn {Function File} {} javarmpath (@var{PATH}) +Remove @var{PATH} from the dynamic class path of the Java virtual machine. @var{PATH} can be either a directory where .class files can be found, or a .jar file containing Java classes. + +Example: This example removes one of the directories added in the example for the @code{javaaddpath} function. + +@example +Octave > javarmpath('C:/java/classes'); +Octave > javaclasspath +@{ + [1,1] = C:\java\myclasses.jar +@} +@end example + +@seealso{@ref{doc-javaaddpath,,javaaddpath}, @ref{doc-javaclasspath,,javaclasspath}, + @ref{doc-FAQ,,How to make Java classes available to Octave?}} +@end deftypefn + +@c ------------------------------------------------------------------------ +@node javamem +@subsection javamem +@anchor{doc-javamem} +@c - index - +@cindex memory, displaying Java memory status +@c - index - + +@deftypefn {Function File} {} javamem +@deftypefnx {Function File} {[@var{JMEM}] =} javamem + +Show current memory status of the java virtual machine (JVM) +& run garbage collector. + +When no return argument is given the info is echoed to the screen. +Otherwise, cell array @var{JMEM} contains @var{Maximum}, @var{Total}, and +@var{Free} memory (in bytes). + +All java-based routines are run in the JVM's shared memory pool, +a dedicated and separate part of memory claimed by the JVM from +your computer's total memory (which comprises physical RAM and +virtual memory / swap space on hard disk). + +The maximum available memory can be set using the file @code{java.opts} +(in the same subdirectory where @code{javaaddpath.m} lives, see +@samp{which javaaddpath}. Usually that is: @* +[/usr]/share/Octave/packages/java-1.2.8. + +@code{java.opts} is a plain text file. It can contain memory related +options, starting with @code{-X}. +In the following exmaple, the first line specifies the initial +memory size in megabytes, the second line specifies the requested +maximum size: +@example +-Xms64m +-Xmx512m +@end example +You can adapt these values if your system has limited available +physical memory. When no @code{java.opts} file is present, the default +assignments are depending on system hardware and Java version. +Typically these are an initial memory size of @math{RAM/64} and +a maximum memory size of @math{min(RAM/4, 1GB)}, where @var{RAM} +is the amount of installed memory. + +In the output of javamem @var{Total memory} is what the operating +system has currently assigned to the JVM and depends on actual +and active memory usage. +@var{Free memory} is self-explanatory. During operation of java-based +Octave functions the amounts of Total and Free memory will vary, +due to java's own cleaning up and your operating system's memory +management. + +Example: +@example +Octave > javamem +Java virtual machine (JVM) memory info: +Maximum available memory: 247 MB; + (...running garbage collector...) +OK, current status: +Total memory in virtual machine: 15 MB; +Free memory in virtual machine: 15 MB; +2 CPUs available. + +Octave > [MEM] = javamem() +MEM = +@{ + [1,1] = 259522560 + [2,1] = 16318464 + [3,1] = 16085576 +@} +@end example + +@seealso{@ref{doc-FAQ,,How can I handle memory limitations?}} +@end deftypefn + +@c ------------------------------------------------------------------------ +@node javaArray +@subsection javaArray +@anchor{doc-javaArray} +@c - index - +@cindex array, creating a Java array +@c - index - + +@deftypefn {Function File} {ARRAY =} javaArray (@var{CLASS}, [@var{M}, @var{N}, ...]) +@deftypefnx {Function File} {ARRAY =} javaArray (@var{CLASS}, @var{M}, @var{N}, ...) + +Create a Java array of size @code{[M, N, ...]} with elements of class @var{CLASS}. @var{CLASS} can be a Java object representing a class or a string containing the fully qualified class name. +The generated array is uninitialized, all elements are set to null if @var{CLASS} is a reference type, or to a default value (usually 0) if @var{CLASS} is a primitive type. + +Example: This example creates a (2 x 2) array of Java @var{String} objects and assigns a value to one of the elements. Finally it displays the type of @var{a}. +@example +Octave > a = javaArray('java.lang.String', 2, 2); +Octave > a(1,1) = 'Hello'; +Octave > a +a = + +@end example +@end deftypefn + +@c ------------------------------------------------------------------------ +@node javaObject +@subsection javaObject +@anchor{doc-javaObject} +@c - index - +@cindex object, creating a Java object +@c - index - + +@deftypefn {Function File} {OBJECT =} javaObject (@var{CLASS}, [@var{ARG1}, ..., @var{ARGN}]) + +Create a Java object of class @var{CLASS}, by calling the class constructor with the given arguments @var{ARG1}, ..., @var{ARGN}. The @var{CLASS} name should be given in fully qualified string form (including any package prefix). In Matlab you should avoid to use the import statement and the short form of object creation. + +Example: This example demonstrates two ways to create a Java @code{StringBuffer} object. The first variant creates an uninitialized @var{StringBuffer} object, while the second variant calls a constructor with the given initial @code{String}. Then it displays the type of @code{o}, and finally the content of the @code{StringBuffer} object is displayed by using its @code{toString} method. + +@example +Octave > o = javaObject('java.lang.StringBuffer'); +Octave > o = javaObject('java.lang.StringBuffer', 'Initial'); +Octave > o +o = + +Octave > o.toString +ans = Initial +@end example + +Equivalent to the @code{java_new} function. +For compatibility with Matlab it is recommended to use the @code{javaObject} function. + +@seealso{@ref{doc-java_new,,java_new}} +@end deftypefn + +@c ------------------------------------------------------------------------ +@node java_new +@subsection java_new +@anchor{doc-java_new} +@c - index - +@cindex object, creating a Java object +@c - index - + +@deftypefn {Function File} {OBJECT =} java_new (@var{CLASS}, [@var{ARG1}, ..., @var{ARGN}]) + +Create a Java object of class @var{CLASS}, by calling the class constructor with the given arguments @var{ARG1}, ..., @var{ARGN}. +Equivalent to the @code{javaObject} function. +For compatibility with Matlab it is recommended to use the @code{javaObject} function. + +Example: +@example +Octave > o = java_new('java.lang.StringBuffer', 'Initial'); +Octave > o +o = + +Octave > o.toString +ans = Initial +@end example + +@seealso{@ref{doc-javaObject,,javaObject}} +@end deftypefn + +@c ------------------------------------------------------------------------ +@node javaMethod +@subsection javaMethod +@anchor{doc-javaMethod} +@c - index - +@cindex method, invoking a method of a Java object +@c - index - + +@deftypefn {Function File} {RET =} javaMethod (@var{NAME}, @var{OBJECT}[, @var{ARG1}, ..., @var{ARGN}]) + +Invoke the method @var{NAME} on the Java object @var{OBJECT} with the arguments @var{ARG1}, ... For static methods, @var{OBJECT} can be a string representing the fully qualified name of the corresponding class. The function returns the result of the method invocation. +When @var{OBJECT} is a regular Java object, the structure-like indexing can be used as a shortcut syntax. For instance, the two statements in the example are equivalent. + +Example: +@example +Octave > ret = javaMethod("method1", x, 1.0, "a string") +Octave > ret = x.method1(1.0, "a string") +@end example + +@seealso{@ref{doc-javamethods,,javamethods}} +@end deftypefn + +@c ------------------------------------------------------------------------ +@node java_invoke +@subsection java_invoke +@anchor{doc-java_invoke} +@c - index - +@cindex method, invoking a method of a Java object +@c - index - + +@deftypefn {Function File} {RET =} java_invoke (@var{OBJECT}, @var{NAME}[, @var{ARG1}, ..., @var{ARGN}]) + +Invoke the method @var{NAME} on the Java object @var{OBJECT} with the arguments @var{ARG1}, ... For static methods, @var{OBJECT} can be a string representing the fully qualified name of the corresponding class. The function returns the result of the method invocation. Equivalent to the @code{javaMethod} function. When @var{OBJECT} is a regular Java object, the structure-like indexing can be used as a shortcut syntax. For instance, the two statements in the example are equivalent. + +Example: +@example +Octave > ret = java_invoke(x, "method1", 1.0, "a string") +Octave > ret = x.method1(1.0, "a string") +@end example + +@seealso{@ref{doc-javamethods,,javamethods}} +@end deftypefn + +@c ------------------------------------------------------------------------ +@node java_get +@subsection java_get +@anchor{doc-java_get} +@c - index - +@cindex field, returning value of Java object field +@c - index - + +@deftypefn {Function File} {VAL =} java_get (@var{OBJECT}, @var{NAME}) + +Get the value of the field @var{NAME} of the Java object @var{OBJECT}. For static fields, @var{OBJECT} can be a string representing the fully qualified name of the corresponding class. + +When @var{OBJECT} is a regular Java object, the structure-like indexing can be used as a shortcut syntax. For instance, the two statements in the example are equivalent + +Example: +@example +Octave > java_get(x, "field1") +Octave > x.field1 +@end example + +@seealso{@ref{doc-javafields,,javafields}, + @ref{doc-java_set,,java_set}} +@end deftypefn + +@c ------------------------------------------------------------------------ +@node java_set +@subsection java_set +@anchor{doc-java_set} +@c - index - +@cindex field, setting value of Java object field +@c - index - + +@deftypefn {Function File} {OBJECT =} java_set (@var{OBJECT}, @var{NAME}, @var{VALUE}) + +Set the value of the field @var{NAME} of the Java object @var{OBJECT} to @var{VALUE}. For static fields, @var{OBJECT} can be a string representing the fully qualified named of the corresponding Java class. +When @var{OBJECT} is a regular Java object, the structure-like indexing can be used as a shortcut syntax. For instance, the two statements in the example are equivalent + +Example: +@example +Octave > java_set(x, "field1", val) +Octave > x.field1 = val +@end example + +@seealso{@ref{doc-javafields,,javafields}, + @ref{doc-java_get,,java_get}} +@end deftypefn + +@c ------------------------------------------------------------------------ +@node javamethods +@subsection javamethods +@anchor{doc-javamethods} +@c - index - +@cindex methods, displaying available methods of a Java object +@c - index - + +@deftypefn {Function File} {M =} javamethods (@var{CLASSNAME}) +@deftypefnx {Function File} {M =} javamethods (@var{OBJECT}) + +Given a string with a Java class name @var{CLASSNAME} or a regular Java object @var{OBJECT}, this function returns a cell array containing descriptions of all methods of the Java class @var{CLASSNAME} respectively the class of @var{OBJECT}. + +Examples: The first example shows how the methods of a class can be queried, while the second example works with the methods of a concrete instance of a class. Note that creation of a @code{java.lang.Double} object requires an initializer (in the example the value 1.2). +@example +Octave > m = javamethods('java.lang.Double'); +Octave > size(m) +ans = + 1 30 + +Octave > m@{7@} +ans = double longBitsToDouble(long) + +Octave > o = javaObject('java.lang.Double', 1.2); +Octave > m = javamethods(o); +Octave > size(m) +ans = + 1 30 + +Octave > m@{7@} +ans = double longBitsToDouble(long) +@end example + +@seealso{@ref{doc-javafields,,javafields}, + @ref{doc-java_invoke,,java_invoke}} +@end deftypefn + +@c ------------------------------------------------------------------------ +@node javafields +@subsection javafields +@anchor{doc-javafields} +@c - index - +@cindex fields, displaying available fields of a Java object +@c - index - + +@deftypefn {Function File} {F =} javafields (@var{CLASSNAME}) +@deftypefnx {Function File} {F =} javafields (@var{OBJECT}) + +Given a string with a Java class name @var{CLASSNAME} or a regular Java object @var{OBJECT}, this function returns a cell array containing the descriptions for all fields of the Java class @var{CLASSNAME} respectively the class of @var{OBJECT}. + +Examples: + +The first example shows how the fields of a class can be queried without creating an instance of the class. +@example +Octave > f = javafields('java.lang.Double'); +Octave > size(f) +ans = + 1 10 + +Octave > f@{7@} +ans = public static final int java.lang.Double.MAX_EXPONENT +@end example + +The second example works with the fields of an instance of a class. Note that creation of a @code{java.lang.Double} object requires an initializer (in the example a value of 1.2 is specified). +@example +Octave > o = javaObject('java.lang.Double', 1.2); +Octave > f = javafields(o); +Octave > size(f) +ans = + 1 10 + +Octave > f@{7@} +ans = public static final int java.lang.Double.MAX_EXPONENT +@end example + +@seealso{@ref{doc-java_set,,java_set}, + @ref{doc-java_get,,java_get}} +@end deftypefn + +@c ------------------------------------------------------------------------ +@node msgbox +@subsection msgbox +@anchor{doc-msgbox} +@c - index - +@cindex dialog, displaying a warning dialog +@c - index - + +@deftypefn {Function File} {F =} msgbox (@var{MESSAGE}) +@deftypefnx {Function File} {F =} msgbox (@var{MESSAGE}, @var{TITLE}) +@deftypefnx {Function File} {F =} msgbox (@var{MESSAGE}, @var{TITLE}, @var{ICON}) + +Displays a @var{MESSAGE} using a dialog box. The parameter @var{TITLE} can be used to optionally decorate the dialog caption. +The third optional parameter @var{ICON} can be either @code{'error'}, @code{'help'} or @code{'warn'} +and selectes the corresponding icon. +If it is omitted, no icon is shown. + +Examples: The first example shows a dialog box without a caption text, whereas the second example specifies a caption text of its own. +The third example also demonstrates how a character +according to the @TeX{} symbol set can be specified. It is important to include a space character +after the symbol code and how to embed a newline character (ASCII code 10) into the string. + +@example +Octave > msgbox('This is an important message'); +Octave > msgbox('Do not forget to feed the cat.', 'Remember'); +Octave > msgbox(['I \heartsuit Octave!',10, ... + ' Even if I hate it sometimes.'], ... + 'I Confess','warn'); +@end example + +@c @image{java-images/image003} + +@seealso{@ref{doc-errordlg,,errordlg}, + @ref{doc-helpdlg,,helpdlg}, + @ref{doc-warndlg,,warndlg}} +@end deftypefn + +@c ------------------------------------------------------------------------ +@node errordlg +@subsection errordlg +@anchor{doc-errordlg} +@c - index - +@cindex dialog, displaying an error dialog +@c - index - + +@deftypefn {Function File} {F =} errordlg (@var{MESSAGE}) +@deftypefnx {Function File} {F =} errordlg (@var{MESSAGE}, @var{TITLE}) + +Displays the @var{MESSAGE} using an error dialog box. The @var{TITLE} can be used optionally to decorate the dialog caption instead of the default title "Error Dialog". + +Examples: The first example shows a dialog box with default caption, whereas the second example specifies a its own caption +@example +Octave > errordlg('Oops, an expected error occured'); +@end example +@c @image{java-images/image001 +@example +Octave > errordlg('Another error occured', 'Oops'); +@end example + +@seealso{@ref{doc-helpdlg,,helpdlg}, + @ref{doc-inputdlg,,inputdlg}, + @ref{doc-listdlg,,listdlg}, + @ref{doc-questdlg,,questdlg}, + @ref{doc-warndlg,,warndlg}} +@end deftypefn + +@c ------------------------------------------------------------------------ +@node helpdlg +@subsection helpdlg +@anchor{doc-helpdlg} +@c - index - +@cindex dialog, displaying a help dialog +@c - index - + +@deftypefn {Function File} {F =} helpdlg (@var{MESSAGE}) +@deftypefnx {Function File} {F =} helpdlg (@var{MESSAGE}, @var{TITLE}) + +Displays the @var{MESSAGE} using a help dialog box. The help message can consist of multiple lines, separated by a newline character. The @var{TITLE} can be used optionally to decorate the dialog caption bar instead of the default title "Help Dialog". + +Examples: The first example shows a dialog box with default caption, whereas the next two examples specify their own caption. Note that if the backslash escape notation is used in a double quoted string, it is immediately replaced by Octave with a newline. +If it is contained in a single quoted string, it is not replaced by Octave, +but later by the dialog function. + +@example +Octave > helpdlg('This is a short notice'); +Octave > helpdlg(['line #1',10,'line #2'], 'Inventory'); +Octave > helpdlg("1 eel\n9 buckazoids\n2 peas", 'Inventory'); +@end example + +@c @image{java-images/image004} + +@seealso{@ref{doc-errordlg,,errordlg}, + @ref{doc-inputdlg,,inputdlg}, + @ref{doc-listdlg,,listdlg}, + @ref{doc-questdlg,,questdlg}, + @ref{doc-warndlg,,warndlg}} +@end deftypefn + +@c ------------------------------------------------------------------------ +@node inputdlg +@subsection inputdlg +@anchor{doc-inputdlg} +@c - index - +@cindex dialog, displaying an input dialog +@c - index - + +@deftypefn {Function File} {C =} inputdlg (@var{PROMPT}) +@deftypefnx {Function File} {C =} inputdlg (@var{PROMPT}, @var{TITLE}) +@deftypefnx {Function File} {C =} inputdlg (@var{PROMPT}, @var{TITLE}, @var{ROWSCOLS}) +@deftypefnx {Function File} {C =} inputdlg (@var{PROMPT}, @var{TITLE}, @var{ROWSCOLS}, @var{DEFAULTS}) + +Returns the user's inputs from a multi-textfield dialog box in form of a cell array of strings. If the user closed the dialog with the Cancel button, en empty cell array is returned. This can be checked with the @var{isempty} function. The first argument @var{PROMPT} is mandatory. It is a cell array with strings labeling each text field. The optional string @var{TITLE} can be used as the caption of the dialog. The size of the text fields can be defined by the argument @var{ROWSCOLS}, which can be either a scalar to define the number of columns used for each text field, a vector to define the number of rows for each text field individually, or a matrix to define the number of rows and columns for each text field individually. It is possible to place default values into the text fields by supplying a cell array of strings for the argument @var{DEFAULTS}. + +Examples: The first example shows a simple usage of the input dialog box without defaults. +@example +Octave > prompt = @{'Width','Height','Depth'@}; +Octave > dims = inputdlg(prompt, 'Enter Box Dimensions'); +Octave > volume = str2num(dims@{1@}) * ... + str2num(dims@{2@}) * str2num(dims@{3@}); +@end example + +@c @image{java-images/image005} + +The second example shows the application of a scalar for the number of rows and a cell array with default values. +@example +Octave > prompt = @{'Width', 'Height', 'Depth'@}; +Octave > defaults = @{'1.1', '2.2', '3.3'@}; +Octave > title = 'Enter Box Dimensions'; +Octave > dims = inputdlg(prompt, title, 1, defaults); +Octave > dims +dims = +@{ + [1,1] = 1.1 + [2,1] = 2.2 + [3,1] = 3.3 +@} +@end example + +@c @image{java-images/image006} + +The third example shows the application of row height and column width specification.. +@example +Octave > prompt = @{'Width', 'Height', 'Depth'@}; +Octave > defaults = @{'1.1', '2.2', '3.3'@}; +Octave > rc = [1,10; 2,20; 3,30]; +Octave > title = 'Enter Box Dimensions'; +Octave > dims = inputdlg(prompt, title, rc, defaults); +@end example + +@c @image{java-images/image007} + +@seealso{@ref{doc-errordlg,,errordlg}, + @ref{doc-helpdlg,,helpdlg}, + @ref{doc-listdlg,,listdlg}, + @ref{doc-questdlg,,questdlg}, + @ref{doc-warndlg,,warndlg}} +@end deftypefn + +@c ------------------------------------------------------------------------ +@node listdlg +@subsection listdlg +@anchor{doc-listdlg} +@c - index - +@cindex dialog, displaying a list dialog +@c - index - + +@deftypefn {Function File} {[SEL, OK] =} listdlg (@var{KEY}, @var{VALUE}[, @var{KEY}, @var{VALUE}, ...]) + +This function returns the inputs from a list dialog box. The result is returned as a vector of indices and a flag. The vector @var{SEL} contains the 1-based indices of all list items selected by the user. The flag @var{OK} is 1 if the user closed the dialog with the OK Button, otherwise it is 0 and @var{SEL} is empty.. The arguments of this function are specified in the form of @var{KEY}, @var{VALUE} pairs. At least the @code{'ListString'} argument pair must be specified. It is also possible to preselect items in the list in order to provide a default selection. + +The @var{KEY} and @var{VALUE} pairs can be selected from the following list: + +@table @code +@item ListString +a cell array of strings comprising the content of the list. +@item SelectionMode +can be either @code{'single'} or @code{'multiple'}. +@item ListSize +a vector with two elements @code{[width, height]} defining the size of the list field in pixels. +@item InitialValue +a vector containing 1-based indices of preselected elements. +@item Name +a string to be used as the dialog caption. +@item PromptString +a cell array of strings to be displayed above the list field. +@item OKString +a string used to label the OK button. +@item CancelString +a string used to label the Cancel button. +@end table + +Example: +@example +Octave > [s,ok] = listdlg('ListString', ... + @{'An item', 'another', 'yet another'@}, ... + 'Name', 'Selection Dialog', ... + 'SelectionMode', 'Multiple', ... + 'PromptString',['Select an item...',10,'...or multiple items']); + +Octave > imax = length(s); +Octave > for i=1:1:imax +Octave > disp(s(i)); +Octave > end +@end example + +@c @image{java-images/image002} + +@seealso{@ref{doc-errordlg,,errordlg}, + @ref{doc-helpdlg,,helpdlg}, + @ref{doc-inputdlg,,inputdlg}, + @ref{doc-questdlg,,questdlg}, + @ref{doc-warndlg,,warndlg}} +@end deftypefn + +@c ------------------------------------------------------------------------ +@node questdlg +@subsection questdlg +@anchor{doc-questdlg} +@c - index - +@cindex dialog, displaying a question dialog +@c - index - + +@deftypefn {Function File} {C =} questdlg (@var{MESSAGE}, @var{TITLE}) +@deftypefnx {Function File} {C =} questdlg (@var{MESSAGE}, @var{TITLE}, @var{DEFAULT}) +@deftypefnx {Function File} {C =} questdlg (@var{MESSAGE}, @var{TITLE}, @var{BTN1}, @var{BTN2}, @var{DEFAULT}) +@deftypefnx {Function File} {C =} questdlg (@var{MESSAGE}, @var{TITLE}, @var{BTN1}, @var{BTN2}, @var{BTN3}, @var{DEFAULT}) + +Displays the @var{MESSAGE} using a question dialog box with a caption @var{TITLE}. The dialog contains two or three buttons which all close the dialog. It returns the caption of the activated button. + +If only @var{MESSAGE} and @var{TITLE} are specified, three buttons with the default captions "Yes", +"No", "Cancel" are used. +The string @var{DEFAULT} identifies the default button, which is activated by pressing the ENTER key. It must match one of the strings given in @var{BTN1}, @var{BTN2} or @var{BTN3}. If only two button captions @var{BTN1} and @var{BTN2} are specified, the dialog will have only these two buttons. + + +Examples: The first example shows a dialog box with two buttons, whereas the next example demonstrates the use of three buttons. +@example +Octave > questdlg('Select your gender', 'Sex', ... + 'Male', 'Female', 'Female'); +@end example + +@c @image{java-images/image008} + +@example +Octave > questdlg('Select your gender', 'Sex', ... + 'Male', 'dont know', 'Female', 'Female'); +@end example + +@c @image{java-images/image009} + +@seealso{@ref{doc-errordlg,,errordlg}, + @ref{doc-helpdlg,,helpdlg}, + @ref{doc-inputdlg,,inputdlg}, + @ref{doc-listdlg,,listdlg}, + @ref{doc-warndlg,,warndlg}} +@end deftypefn + +@c ------------------------------------------------------------------------ +@node warndlg +@subsection warndlg +@anchor{doc-warndlg} +@c - index - +@cindex dialog, displaying a warning dialog +@c - index - + +@deftypefn {Function File} {F =} warndlg (@var{MESSAGE}) +@deftypefnx {Function File} {F =} warndlg (@var{MESSAGE}, @var{TITLE}) + +Displays a @var{MESSAGE} using a warning dialog box. The @var{TITLE} can be used optionally to decorate the dialog caption instead of the default title "Warning Dialog". + +Examples: The first example shows a dialog box with default caption, whereas the second example specifies a caption text of its own. The second example also demonstrates how a character +according to the @TeX{} symbol set can be specified. It is important to include a space character +after the symbol code. The \n character can be used to start a new line. +The third example shows an alternate way to embed the newline character (the newline character has the ASCII code 10) into the string. +Please refer to the Octave manual for the difference between single and double quoted +strings. + +@example +Octave > warndlg('An expected warning occured'); +Octave > warndlg('I \heartsuit Octave!\nEven if I hate her sometimes.', ... + 'Confession'); +Octave > warndlg(['I \heartsuit Octave!',10, ... + ' Even if I hate her sometimes.'], ... + 'I Confess'); +@end example + +@c @image{java-images/image003} + +@seealso{@ref{doc-errordlg,,errordlg}, + @ref{doc-helpdlg,,helpdlg}, + @ref{doc-inputdlg,,inputdlg}, + @ref{doc-listdlg,,listdlg}, + @ref{doc-questdlg,,questdlg}} +@end deftypefn + +@c ------------------------------------------------------------------------ +@node FAQ - Frequently asked Questions +@section FAQ - Frequently asked Questions + +@menu +* How to distinguish between Octave and Matlab?:: +* How to make Java classes available?:: +* How to create an instance of a Java class?:: +* How can I handle memory limitations?:: +* How to compile the java package in Octave?:: +* Which @TeX{} symbols are implemented in the dialog functions?:: +@end menu + +@c ------------------------------------------------------------------------ +@node How to distinguish between Octave and Matlab? +@subsection How to distinguish between Octave and Matlab? +@anchor{doc-FAQ} +@c - index - +@cindex Octave and Matlab, how to distinguish between +@c - index - + +Octave and Matlab are very similar, but handle Java slightly different. Therefore it may be necessary to detect the environment and use the appropriate functions. The following function can be used to detect the environment. Due to the persistent variable it can be called repeatedly without a heavy performance hit. + +Example: +@example +%% +%% Return: true if the environment is Octave. +%% +function ret = isOctave + persistent retval; % speeds up repeated calls + + if isempty(retval) + retval = (exist('Octave_VERSION','builtin') > 0); + end + + ret = retval; +end +@end example + +@c ------------------------------------------------------------------------ +@node How to make Java classes available? +@subsection How to make Java classes available to Octave? +@c - index - +@cindex classpath, setting +@cindex classpath, difference between static and dynamic +@cindex static classpath +@cindex dynamic classpath +@cindex @code{classpath.txt} +@cindex classes, making available to Octave +@c - index - + +Java finds classes by searching a @var{classpath}. This is a list of Java archive files and/or directories containing class files. +In Octave and Matlab the @var{classpath} is composed of two parts: +@itemize +@item the @var{static classpath} is initialized once at startup of the JVM, and +@item the @var{dynamic classpath} which can be modified at runtime. +@end itemize +Octave searches the @var{static classpath} first, then the @var{dynamic classpath}. +Classes appearing in the @var{static} as well as in the @var{dynamic classpath} will therefore be found in the @var{static classpath} and loaded from this location. +@* +Classes which shall be used regularly or must be available to all users should be +added to the @var{static classpath}. +The @var{static classpath} is populated once from the contents of a plain text file named @code{classpath.txt} when the Java Virtual Machine starts. This file contains one line for each individual classpath to be added to the @var{static classpath}. +These lines can identify single class files, directories containing class files or Java archives with complete class file hierarchies. +Comment lines starting with a @code{#} or a @code{%} character are ignored. + +The search rules for the file @code{classpath.txt} are: +@itemize +@item First, Octave searches for the file @code{classpath.txt} in your home directory, +If such a file is found, it is read and defines the initial @var{static classpath}. +Thus it is possible to build an initial static classpath on a 'per user' basis. + +@item Next, Octave looks for another file @code{classpath.txt} in the package installation directory. +This is where @code{javaclasspath.m} resides, usually something like @code{...\share\Octave\packages\java-1.2.8}. +You can find this directory by executing the command +@example +pkg list +@end example +If this file exists, its contents is also appended to the static classpath. +Note that the archives and class directories defined in this file will affect all users. +@end itemize + +Classes which are used only by a specific script should be placed in the @var{dynamic classpath}. This portion of the classpath can be modified at runtime using the @code{javaaddpath} and @code{javarmpath} functions. + +Example: +@example +Octave > base_path = 'C:/Octave/java_files'; + +Octave > % add two JARchives to the dynamic classpath +Octave > javaaddpath([base_path, '/someclasses.jar']); +Octave > javaaddpath([base_path, '/moreclasses.jar']); + +Octave > % check the dynamic classpath +Octave > p = javaclasspath; +Octave > disp(p@{1@}); +C:/Octave/java_files/someclasses.jar +Octave > disp(p@{2@}); +C:/Octave/java_files/moreclasses.jar + +Octave > % remove the first element from the classpath +Octave > javarmpath([base_path, '/someclasses.jar']); +Octave > p = javaclasspath; +Octave > disp(p@{1@}); +C:/Octave/java_files/moreclasses.jar + +Octave > % provoke an error +Octave > disp(p@{2@}); +error: A(I): Index exceeds matrix dimension. +@end example + +Another way to add files to the @var{dynamic classpath} exclusively for your user account is to use the file @code{.octaverc} which is stored in your home directory. +All Octave commands in this file are executed each time you start a new instance of Octave. +The following example adds the directory @code{octave} to Octave's search path and +the archive @code{myclasses.jar} in this directory to the Java search path. +@example +% content of .octaverc: +addpath('~/octave'); +javaaddpath('~/octave/myclasses.jar'); +@end example + +@c ------------------------------------------------------------------------ +@node How to create an instance of a Java class? +@subsection How to create an instance of a Java class? +@c - index - +@cindex object, how to create +@cindex instance, how to create +@c - index - + +If your code shall work under Octave as well as Matlab you should use the function @code{javaObject} to create Java objects. The function @code{java_new} is Octave specific and does not exist in the Matlab environment. + +Example 1, suitable for Octave but not for Matlab: +@example + Passenger = java_new('package.FirstClass', row, seat); +@end example + +Example 2, which works in Octave as well as in Matlab: +@example + Passenger = javaObject('package.FirstClass', row, seat); +@end example + +@c ------------------------------------------------------------------------ +@node How can I handle memory limitations? +@subsection How can I handle memory limitations? +@cindex memory, limitations + +In order to execute Java code Octave creates a Java Virtual Machine (JVM). Such a JVM allocates a fixed amount of initial memory and may expand this pool up to a fixed maximum memory limit. The default values depend on the Java version (see @ref{doc-javamem,,javamem}). +The memory pool is shared by all Java objects running in the JVM. +This strict memory limit is intended mainly to avoid that runaway applications inside web browsers or in enterprise servers can consume all memory and crash the system. +When the maximum memory limit is hit, Java code will throw exceptions so that applications will fail or behave unexpectedly. + +In Octave as well as in Matlab, you can specify options for the creation of the JVM inside a file named @code{java.opts}. +This is a text file where you can enter lines containing @code{-X} and @code{-D} options handed to the JVM during initialization. + +In Octave, the Java options file must be located in the directory where @code{javaclasspath.m} resides, i.e. the package installation directory, usually something like @var{...\share\Octave\packages\java-1.2.8}. You can find this directory by executing +@example +pkg list +@end example + +In Matlab, the options file goes into the @var{MATLABROOT/bin/ARCH} directory or in your personal Matlab startup directory (can be determined by a @samp{pwd} command). @var{MATLABROOT} is the Matlab root directory and @var{ARCH} is your system architecture, which you find by issuing the commands @samp{matlabroot} respectively @samp{computer('arch')}. + +The @code{-X} options allow you to increase the maximum amount of memory available to the JVM to 256 Megabytes by adding the following line to the @code{java.opts} file: +@example +-Xmx256m +@end example + +The maximum possible amount of memory depends on your system. On a Windows system with 2 Gigabytes main memory you should be able to set this maximum to about 1 Gigabyte. + +If your application requires a large amount of memory from the beginning, you can also specify the initial amount of memory allocated to the JVM. Adding the following line to the @code{java.opts} file starts the JVM with 64 Megabytes of initial memory: +@example +-Xms64m +@end example + +For more details on the available @code{-X} options of your Java Virtual Machine issue the command @samp{java -X} at the operating system command prompt and consult the Java documentation. + + +The @code{-D} options can be used to define system properties which can then be used by Java classes inside Octave. System properties can be retrieved by using the @code{getProperty()} methods of the @code{java.lang.System} class. The following example line defines the property @var{MyProperty} and assigns it the string @code{12.34}. +@example +-DMyProperty=12.34 +@end example +The value of this property can then be retrieved as a string by a Java object or in Octave: +@example +Octave > javaMethod('java.lang.System', 'getProperty', 'MyProperty'); +ans = 12.34 +@end example + +@seealso{@ref{doc-javamem,,javamem}} + +@c ------------------------------------------------------------------------ +@node How to compile the java package in Octave? +@subsection How to compile the java package in Octave? +@c - index - +@cindex package, how to compile? +@cindex compiling the java package, how? +@cindex java package, how to compile? +@cindex java package, how to install? +@cindex java package, how to uninstall? +@c - index - + +Most Octave installations come with the @var{java} package pre-installed. In case you want to replace this package with a more recent version, you must perform the following steps: + +@c --------- +@menu +* Uninstall the currently installed package @var{java}:: +* Make sure that the build environment is configured properly:: +* Compile and install the package in Octave:: +* Test the java package installation:: +@end menu + +@node Uninstall the currently installed package @var{java} +@subsubsection Uninstall the currently installed package @var{java} +Check whether the @var{java} package is already installed by issuing +the @code{pkg list} command: +@example +Octave > pkg list +Package Name | Version | Installation directory +--------------+---------+----------------------- + java *| 1.2.8 | /home/octavio/octave/java-1.2.8 +Octave > +@end example + +@noindent +If the @var{java} package appears in the list you must uninstall it first by issuing the command +@example +Octave > pkg uninstall java +Octave > pkg list +@end example + +Now the java package should not be listed anymore. If you have used the @var{java} package during the current session of Octave, you have to exit and restart Octave before you can uninstall the package. This is because the system keeps certain libraries in memory after they have been loaded once. + +@c --------- +@node Make sure that the build environment is configured properly +@subsubsection Make sure that the build environment is configured properly +The installation process requires that the environment variable @code{JAVA_HOME} points to the Java Development Kit (JDK) on your computer. + +@itemize @bullet +@item +Note that JDK is not equal to JRE (Java Runtime Environment). The JDK home directory contains subdirectories with include, library and executable files which are required to compile the @var{java} package. These files are not part of the JRE, so you definitely need the JDK. +@item +Do not use backslashes but ordinary slashes in the path. +@end itemize + +Set the environment variable @code{JAVA_HOME} according to your local JDK installation. Please adapt the path in the following examples according to the JDK installation on your system.@* +If you are using a Windows system that might be: +@example +Octave > setenv("JAVA_HOME","C:/Java/jdk1.6.0_21"); +@end example +Note, that on both system types, Windows as well as Linux, you must use the forward slash '/' as the separator, not the backslash '\'. + +If you are using a Linux system this would look probably more like: +@example +Octave > setenv("JAVA_HOME","/usr/local/jdk1.6.0_21"); +@end example + +@c --------- +@node Compile and install the package in Octave +@subsubsection Compile and install the package in Octave +If you have for example saved the package archive on your @var{z:} drive the command would be: +@example +Octave> pkg install -verbose z:/java-1.2.8.tar.gz +@end example +or if you have Linux and the package file is stored in your home directory: +@example +Octave > pkg install -verbose ~/java-1.2.8.tar.gz +@end example +The option @code{-verbose} will produce some lengthy output, which should not show any errors +(maybe a few warnings at best). + +You can then produce a list of all installed packages: +@example +Octave > pkg list +@end example + +This list of packages should now include the package @var{java}: +@example +Octave > pkg list +Package Name | Version | Installation directory +--------------+---------+----------------------- + java *| 1.2.8 | /home/octavio/octave/java-1.2.8 +Octave > +@end example + +@c --------- +@node Test the java package installation +@subsubsection Test the java package installation + +The following code creates a Java string object, which however is automatically converted to an Octave string: +@example +Octave > s = javaObject('java.lang.String', 'Hello OctaveString') +s = Hello OctaveString +@end example + +Note that the java package automatically transforms the Java String object to an Octave string. This means that you cannot apply Java String methods to the result. + +This "auto boxing" scheme seems to be implemented for the following Java classes: +@itemize @bullet +@item +java.lang.Integer +@item +java.lang.Double +@item +java.lang.Boolean +@item +java.lang.String +@end itemize + +If you instead create an object for which no "auto-boxing" is implemented, @code{javaObject} returns the genuine Java object: +@example +Octave > v = javaObject('java.util.Vector') +v = + +Octave > v.add(12); +Octave > v.get(0) +ans = 12 +@end example + +If you have created such a Java object, you can apply all methods of the Java class to the returned object. Note also that for some objects you must specify an initializer: +@example +% not: +Octave > d = javaObject('java.lang.Double') +error: [java] java.lang.NoSuchMethodException: java.lang.Double +% but: +Octave > d = javaObject('java.lang.Double',12.34) +d = 12.340 +@end example + +@c ------------------------------------------------------------------------ +@node Which @TeX{} symbols are implemented in the dialog functions? +@subsection Which @TeX{} symbols are implemented in the dialog functions? +@c - index - +@cindex symbols, translation table +@cindex @TeX{} symbols, translation table +@cindex translation table for @TeX{} symbols +@c - index - + +The dialog functions contain a translation table for @TeX{} like symbol codes. Thus messages and labels can be tailored to show some common mathematical symbols or Greek characters. No further @TeX{} formatting codes are supported. The characters are translated to their Unicode equivalent. However, not all characters may be displayable on your system. This depends on the font used by the Java system on your computer. + +Each @TeX{} symbol code must be terminated by a space character to make it distinguishable from the surrounding text. Therefore the string @samp{\alpha =12.0} will produce the desired result, whereas @samp{\alpha=12.0} would produce the literal text @var{'\alpha=12.0'}. + +@seealso{@ref{doc-errordlg,,errordlg}, + @ref{doc-helpdlg,,helpdlg}, + @ref{doc-inputdlg,,inputdlg}, + @ref{doc-listdlg,,listdlg}, + @ref{doc-msgbox,,msgbox}, + @ref{doc-questdlg,,questdlg}, + @ref{doc-warndlg,,warndlg}} + +@need 5000 +@c --------------------------------- +@ifhtml +@float Table +The table below shows each @TeX{} character code and the corresponding Unicode character: +@multitable @columnfractions 0.18 0.1 0.05 0.18 0.1 0.05 0.18 0.1 +@item \alpha +@tab 'Ī±' +@tab +@tab \beta +@tab 'Ī²' +@tab +@tab \gamma +@tab 'Ī³' +@c ---------- +@item \delta +@tab 'Ī“' +@tab +@tab \epsilon +@tab 'Īµ' +@tab +@tab \zeta +@tab 'Ī¶' +@c ---------- +@item \eta +@tab 'Ī·' +@tab +@tab \theta +@tab 'Īø' +@tab +@tab \vartheta +@tab 'Ļ‘' +@c ---------- +@item \iota +@tab 'Ī¹' +@tab +@tab \kappa +@tab 'Īŗ' +@tab +@tab \lambda +@tab 'Ī»' +@c ---------- +@item \mu +@tab 'Ī¼' +@tab +@tab \nu +@tab 'Ī½' +@tab +@tab \xi +@tab 'Ī¾' +@c ---------- +@item \pi +@tab 'Ļ€' +@tab +@tab \rho +@tab 'Ļ' +@tab +@tab \sigma +@tab 'Ļƒ' +@c ---------- +@item \varsigma +@tab 'Ļ‚' +@tab +@tab \tau +@tab 'Ļ„' +@tab +@tab \phi +@tab 'Ļ†' +@c ---------- +@item \chi +@tab 'Ļ‡' +@tab +@tab \psi +@tab 'Ļˆ' +@tab +@tab \omega +@tab 'Ļ‰' +@c ---------- +@item \upsilon +@tab 'Ļ…' +@tab +@tab \Gamma +@tab 'Ī“' +@tab +@tab \Delta +@tab 'Ī”' +@c ---------- +@item \Theta +@tab 'Ī˜' +@tab +@tab \Lambda +@tab 'Ī›' +@tab +@tab \Pi +@tab 'Ī ' +@c ---------- +@item \Xi +@tab 'Īž' +@tab +@tab \Sigma +@tab 'Ī£' +@tab +@tab \Upsilon +@tab 'Ī„' +@c ---------- +@item \Phi +@tab 'Ī¦' +@tab +@tab \Psi +@tab 'ĪØ' +@tab +@tab \Omega +@tab 'Ī©' +@c ---------- +@item \Im +@tab 'ā„‘' +@tab +@tab \Re +@tab 'ā„œ' +@tab +@tab \leq +@tab 'ā‰¤' +@c ---------- +@item \geq +@tab 'ā‰„' +@tab +@tab \neq +@tab 'ā‰ ' +@tab +@tab \pm +@tab 'Ā±' +@c ---------- +@item \infty +@tab 'āˆž' +@tab +@tab \partial +@tab 'āˆ‚' +@tab +@tab \approx +@tab 'ā‰ˆ' +@c ---------- +@item \circ +@tab 'āˆ˜' +@tab +@tab \bullet +@tab 'ā€¢' +@tab +@tab \times +@tab 'Ɨ' +@c ---------- +@item \sim +@tab '~' +@tab +@tab \nabla +@tab 'āˆ‡' +@tab +@tab \ldots +@tab 'ā€¦' +@c ---------- +@item \exists +@tab 'āˆƒ' +@tab +@tab \neg +@tab 'Ā¬' +@tab +@tab \aleph +@tab 'ā„µ' +@c ---------- +@item \forall +@tab 'āˆ€' +@tab +@tab \cong +@tab 'ā‰…' +@tab +@tab \wp +@tab 'ā„˜' +@c ---------- +@item \propto +@tab 'āˆ' +@tab +@tab \otimes +@tab 'āŠ—' +@tab +@tab \oplus +@tab 'āŠ•' +@c ---------- +@item \oslash +@tab 'āŠ˜' +@tab +@tab \cap +@tab 'āˆ©' +@tab +@tab \cup +@tab 'āˆŖ' +@c ---------- +@item \ni +@tab 'āˆ‹' +@tab +@tab \in +@tab 'āˆˆ' +@tab +@tab \div +@tab 'Ć·' +@c ---------- +@item \equiv +@tab 'ā‰”' +@tab +@tab \int +@tab 'āˆ«' +@tab +@tab \perp +@tab 'āŠ„' +@c ---------- +@item \wedge +@tab 'āˆ§' +@tab +@tab \vee +@tab 'āˆØ' +@tab +@tab \supseteq +@tab 'āŠ‡' +@c ---------- +@item \supset +@tab 'āŠƒ' +@tab +@tab \subseteq +@tab 'āŠ†' +@tab +@tab \subset +@tab 'āŠ‚' +@c ---------- +@item \clubsuit +@tab 'ā™£' +@tab +@tab \spadesuit +@tab 'ā™ ' +@tab +@tab \heartsuit +@tab 'ā™„' +@c ---------- +@item \diamondsuit +@tab 'ā™¦' +@tab +@tab \copyright +@tab 'Ā©' +@tab +@tab \leftarrow +@tab 'ā†' +@c ---------- +@item \uparrow +@tab 'ā†‘' +@tab +@tab \rightarrow +@tab 'ā†’' +@tab +@tab \downarrow +@tab 'ā†“' +@c ---------- +@item \leftrightarrow +@tab 'ā†”' +@tab +@tab \updownarrow +@tab 'ā†•' +@tab +@c ---------- +@end multitable +@caption{@TeX{} character codes and the resulting symbols.} +@end float +@end ifhtml +@c --------------------------------- +@iftex +@float Table +The table below shows each @TeX{} character code and the corresponding Unicode character: +@multitable @columnfractions 0.18 0.1 0.05 0.18 0.1 0.05 0.18 0.1 +@headitem @TeX{} code +@tab Symbol +@tab +@tab @TeX{} code +@tab Symbol +@tab +@tab @TeX{} code +@tab Symbol +@c ---------- +@item \alpha +@tab '@math{\alpha}' +@tab +@tab \beta +@tab '@math{\beta}' +@tab +@tab \gamma +@tab '@math{\gamma}' +@c ---------- +@item \delta +@tab '@math{\delta}' +@tab +@tab \epsilon +@tab '@math{\epsilon}' +@tab +@tab \zeta +@tab '@math{\zeta}' +@c ---------- +@item \eta +@tab '@math{\eta}' +@tab +@tab \theta +@tab '@math{\theta}' +@tab +@tab \vartheta +@tab '@math{\vartheta}' +@c ---------- +@item \iota +@tab '@math{\iota}' +@tab +@tab \kappa +@tab '@math{\kappa}' +@tab +@tab \lambda +@tab '@math{\lambda}' +@c ---------- +@item \mu +@tab '@math{\mu}' +@tab +@tab \nu +@tab '@math{\nu}' +@tab +@tab \xi +@tab '@math{\xi}' +@c ---------- +@item \pi +@tab '@math{\pi}' +@tab +@tab \rho +@tab '@math{\rho}' +@tab +@tab \sigma +@tab '@math{\sigma}' +@c ---------- +@item \varsigma +@tab '@math{\varsigma}' +@tab +@tab \tau +@tab '@math{\tau}' +@tab +@tab \phi +@tab '@math{\phi}' +@c ---------- +@item \chi +@tab '@math{\chi}' +@tab +@tab \psi +@tab '@math{\psi}' +@tab +@tab \omega +@tab '@math{\omega}' +@c ---------- +@item \upsilon +@tab '@math{\upsilon}' +@tab +@tab \Gamma +@tab '@math{\Gamma}' +@tab +@tab \Delta +@tab '@math{\Delta}' +@c ---------- +@item \Theta +@tab '@math{\Theta}' +@tab +@tab \Lambda +@tab '@math{\Lambda}' +@tab +@tab \Pi +@tab '@math{\Pi}' +@c ---------- +@item \Xi +@tab '@math{\Xi}' +@tab +@tab \Sigma +@tab '@math{\Sigma}' +@tab +@tab \Upsilon +@tab '@math{\Upsilon}' +@c ---------- +@item \Phi +@tab '@math{\Phi}' +@tab +@tab \Psi +@tab '@math{\Psi}' +@tab +@tab \Omega +@tab '@math{\Omega}' +@c ---------- +@item \Im +@tab '@math{\Im}' +@tab +@tab \Re +@tab '@math{\Re}' +@tab +@tab \leq +@tab '@math{\leq}' +@c ---------- +@item \geq +@tab '@math{\geq}' +@tab +@tab \neq +@tab '@math{\neq}' +@tab +@tab \pm +@tab '@math{\pm}' +@c ---------- +@item \infty +@tab '@math{\infty}' +@tab +@tab \partial +@tab '@math{\partial}' +@tab +@tab \approx +@tab '@math{\approx}' +@c ---------- +@item \circ +@tab '@math{\circ}' +@tab +@tab \bullet +@tab '@math{\bullet}' +@tab +@tab \times +@tab '@math{\times}' +@c ---------- +@item \sim +@tab '@math{\sim}' +@tab +@tab \nabla +@tab '@math{\nabla}' +@tab +@tab \ldots +@tab '@math{\ldots}' +@c ---------- +@item \exists +@tab '@math{\exists}' +@tab +@tab \neg +@tab '@math{\neg}' +@tab +@tab \aleph +@tab '@math{\aleph}' +@c ---------- +@item \forall +@tab '@math{\forall}' +@tab +@tab \cong +@tab '@math{\cong}' +@tab +@tab \wp +@tab '@math{\wp}' +@c ---------- +@item \propto +@tab '@math{\propto}' +@tab +@tab \otimes +@tab '@math{\otimes}' +@tab +@tab \oplus +@tab '@math{\oplus}' +@c ---------- +@item \oslash +@tab '@math{\oslash}' +@tab +@tab \cap +@tab '@math{\cap}' +@tab +@tab \cup +@tab '@math{\cup}' +@c ---------- +@item \ni +@tab '@math{\ni}' +@tab +@tab \in +@tab '@math{\in}' +@tab +@tab \div +@tab '@math{\div}' +@c ---------- +@item \equiv +@tab '@math{\equiv}' +@tab +@tab \int +@tab '@math{\int}' +@tab +@tab \perp +@tab '@math{\perp}' +@c ---------- +@item \wedge +@tab '@math{\wedge}' +@tab +@tab \vee +@tab '@math{\vee}' +@tab +@tab \supseteq +@tab '@math{\supseteq}' +@c ---------- +@item \supset +@tab '@math{\supset}' +@tab +@tab \subseteq +@tab '@math{\subseteq}' +@tab +@tab \subset +@tab '@math{\subset}' +@c ---------- +@item \clubsuit +@tab '@math{\clubsuit}' +@tab +@tab \spadesuit +@tab '@math{\spadesuit}' +@tab +@tab \heartsuit +@tab '@math{\heartsuit}' +@c ---------- +@item \diamondsuit +@tab '@math{\diamondsuit}' +@tab +@tab \copyright +@tab '@math{\copyright}' +@tab +@tab \leftarrow +@tab '@math{\leftarrow}' +@c ---------- +@item \uparrow +@tab '@math{\uparrow}' +@tab +@tab \rightarrow +@tab '@math{\rightarrow}' +@tab +@tab \downarrow +@tab '@math{\downarrow}' +@c ---------- +@item \leftrightarrow +@tab '@math{\leftrightarrow}' +@tab +@tab \updownarrow +@tab '@math{\updownarrow}' +@tab +@c ---------- +@end multitable +@caption{@TeX{} character codes and the resulting symbols.} +@end float +@end iftex +@c --------------------------------- diff --git a/doc/interpreter/octave.texi b/doc/interpreter/octave.texi --- a/doc/interpreter/octave.texi +++ b/doc/interpreter/octave.texi @@ -177,6 +177,7 @@ * Object Oriented Programming:: * GUI Development:: * System Utilities:: +* Java Interface:: * Packages:: * Dynamically Linked Functions:: * Test and Demo Functions:: @@ -909,6 +910,7 @@ @include oop.texi @include gui.texi @include system.texi +@include java.texi @include package.texi @c maybe add again later, if anyone every writes any really interesting diff --git a/libinterp/dldfcn/__java__.cc b/libinterp/dldfcn/__java__.cc new file mode 100644 --- /dev/null +++ b/libinterp/dldfcn/__java__.cc @@ -0,0 +1,2039 @@ +/* Copyright (C) 2007 Michael Goffioul +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; If not, see . +*/ + +#include "__java__.h" + +#include "parse.h" +#include "Cell.h" +#include "file-stat.h" +#include "file-ops.h" +#include "cmd-edit.h" +#ifdef __WIN32__ +#include +#endif +#include "load-path.h" +#include "oct-env.h" +#include "oct-shlib.h" +#include "oct-env.h" + +#include +#include +#include +#include + +#include + +typedef jint (JNICALL *JNI_CreateJavaVM_t) (JavaVM **pvm, JNIEnv **penv, void *args); +typedef jint (JNICALL *JNI_GetCreatedJavaVMs_t) (JavaVM **pvm, jsize bufLen, jsize *nVMs); + +extern "C" JNIEXPORT jboolean JNICALL Java_org_octave_Octave_call + (JNIEnv *, jclass, jstring, jobjectArray, jobjectArray); +extern "C" JNIEXPORT void JNICALL Java_org_octave_OctaveReference_doFinalize + (JNIEnv *, jclass, jint); +extern "C" JNIEXPORT void JNICALL Java_org_octave_Octave_doInvoke + (JNIEnv *, jclass, jint, jobjectArray); +extern "C" JNIEXPORT void JNICALL Java_org_octave_Octave_doEvalString + (JNIEnv *, jclass, jstring); +extern "C" JNIEXPORT jboolean JNICALL Java_org_octave_Octave_needThreadedInvokation + (JNIEnv *, jclass); + +static octave_value _java_new ( const octave_value_list& args ); +static octave_value _java_invoke ( const octave_value_list& args ); + +static JavaVM *jvm = 0; +static bool jvm_attached = false; + +// Need to keep hold of the shared library handle until exit. +static octave_shlib jvm_lib; + +static std::map listener_map; +static std::map octave_ref_map; +static int octave_java_refcount = 0; +static long octave_thread_ID = -1; + +bool Vjava_convert_matrix = false; +bool Vjava_unsigned_conversion = true; +bool Vjava_debug = false; + +class JVMArgs +{ +public: + JVMArgs () + { + vm_args.version = JNI_VERSION_1_2; + vm_args.nOptions = 0; + vm_args.options = 0; + vm_args.ignoreUnrecognized = false; + } + + ~JVMArgs () + { + clean (); + } + + JavaVMInitArgs* to_args () + { + update (); + return &vm_args; + } + + void add (const std::string& opt) + { + java_opts.push_back (opt); + } + + void read_java_opts (const std::string& filename) + { + std::ifstream js (filename.c_str ()); + + if (! js.bad () && ! js.fail ()) + { + std::string line; + + while (! js.eof () && ! js.fail ()) + { + std::getline (js, line); + if (line.length () > 2 && + (line.find ("-D") == 0 || line.find ("-X") == 0)) + java_opts.push_back (line); + else if (line.length () > 0 && Vjava_debug) + std::cerr << "invalid JVM option, skipping: " << line << std::endl; + } + } + } + +private: + void clean () + { + if (vm_args.options != 0) + { + for (int i=0; i 0) + { + int index = 0; + + vm_args.nOptions = java_opts.size (); + vm_args.options = (JavaVMOption*) malloc (sizeof (JavaVMOption) * vm_args.nOptions); + for (std::list::const_iterator it = java_opts.begin (); it != java_opts.end (); ++it) + { + if (Vjava_debug) + std::cout << *it << std::endl; + vm_args.options[index++].optionString = strdup ((*it).c_str ()); + } + java_opts.clear (); + } + } + +private: + JavaVMInitArgs vm_args; + std::list java_opts; +}; + +static dim_vector compute_array_dimensions (JNIEnv* jni_env, jobject obj); + +#ifdef __WIN32__ +static std::string read_registry_string (const std::string& key, const std::string& value) +{ + HKEY hkey; + DWORD len; + std::string retval = ""; + + if (! RegOpenKeyEx (HKEY_LOCAL_MACHINE, key.c_str (), 0, KEY_READ, &hkey)) + { + if (! RegQueryValueEx (hkey, value.c_str (), 0, 0, 0, &len)) + { + retval.resize (len); + if (RegQueryValueEx (hkey, value.c_str (), 0, 0, (LPBYTE)&retval[0], &len)) + retval = ""; + else if (retval[len-1] == '\0') + retval.resize (--len); + } + RegCloseKey (hkey); + } + return retval; +} + +static std::string get_module_filename (HMODULE hMod) +{ + int n = 1024; + std::string retval(n, '\0'); + bool found = false; + + while (n < 65536) + { + int status = GetModuleFileName(hMod, &retval[0], n); + + if (status < n) + { + retval.resize(n); + found = true; + break; + } + else + { + n *= 2; + retval.resize(n); + } + } + return (found ? retval : ""); +} + +static void set_dll_directory (const std::string& dir = "") +{ + typedef BOOL (WINAPI *dllfcn_t) (LPCTSTR path); + + static dllfcn_t dllfcn = NULL; + static bool first = true; + + if (! dllfcn && first) + { + HINSTANCE hKernel32 = GetModuleHandle ("kernel32"); + dllfcn = reinterpret_cast (GetProcAddress (hKernel32, "SetDllDirectoryA")); + first = false; + } + + if (dllfcn) + dllfcn (dir.empty () ? NULL : dir.c_str ()); +} +#endif + +static std::string get_module_path(const std::string& name, bool strip_name = true) +{ + std::string retval; + + retval = octave_env::make_absolute (load_path::find_file (name), +#ifdef HAVE_OCTAVE_32 + octave_env::getcwd ()); +#else + octave_env::get_current_directory ()); +#endif + + if (! retval.empty () && strip_name) + { + size_t pos = retval.rfind (file_ops::dir_sep_str () + name); + + if (pos != std::string::npos) + retval.resize (pos); + else + throw std::string("No module path in ")+retval; + } + else + throw std::string("Could not find file ")+name; + + return retval; +} + +static std::string initial_java_dir (bool arch_dependent = false) +{ + static std::string path1; + static std::string path2; + + if (arch_dependent) + { + if (path1.empty ()) + path1 = get_module_path ("__java__.oct", true); + return path1; + } + else + { + if (path2.empty ()) + path2 = get_module_path ("javaclasspath.m", true); + return path2; + } +} + +/* + * Read the content of a file filename (usually "classpath.txt") + * + * Returns a string with all lines concatenated and separated + * by the path separator character. + * The return string also starts with a path separator so that + * it can be appended easily to a base classpath. + * + * The file "classpath.txt" must contain single lines, each + * with a classpath. + * Comment lines starting with a '#' or a '%' in column 1 are allowed. + * + * On Windiows the usual path separator is a ';', on Unix a ':'. + * + * Created: 28 Aug 2010 Martin Hepperle + */ +static std::string read_classpath_txt (const std::string& filepath) +{ + std::string classpath; + + std::ifstream fs (filepath.c_str ()); + + if (! fs.bad () && ! fs.fail ()) + { + std::string line; + + while (! fs.eof () && ! fs.fail ()) + { + std::getline (fs, line); + if (line.length () > 1 ) + { + if ( (line.at(0) == '#') || + (line.at(0) == '%') ) + { + // this is a comment line: skip + } + else + { + // prepend separator character + classpath.append(dir_path::path_sep_str()); + // append content of line without trailing blanks + int iLast = line.find_last_not_of(' '); + classpath.append(file_ops::tilde_expand(line.substr(0,iLast+1))); + } + } + } + } + return ( classpath ); +} + + +static std::string initial_class_path () +{ + std::string retval = initial_java_dir (); + + // find octave.jar file + if (! retval.empty ()) + { + std::string jar_file = retval + file_ops::dir_sep_str () + "octave.jar"; + file_stat jar_exists (jar_file); + + if (jar_exists) + { + // initialize static classpath to octave.jar + retval = jar_file; + + /* + * The base classpath has been set. + * Try to find the optional file "classpath.txt" in two places. + * The users classes will take precedence over the settings + * defined in the package directory + */ + std::string str_filename = "classpath.txt"; + std::string cp_file; + file_stat cp_exists; + /* + * Try to read the file "classpath.txt" in the user's home directory + */ + cp_file = file_ops::tilde_expand ( "~" + file_ops::dir_sep_str () + str_filename ); + cp_exists = file_stat(cp_file); + if (cp_exists) + { + /* + * The file "classpath.txt" has been found: add its contents to the static classpath + */ + std::string theClassPath = read_classpath_txt (cp_file); + retval.append(theClassPath); + } + /* + * Try to read a file "classpath.txt" in the package directory + */ + cp_file = initial_java_dir () + file_ops::dir_sep_str () + str_filename; + cp_exists = file_stat(cp_file); + if (cp_exists) + { + /* + * The file "classpath.txt" has been found: add its contents to the static classpath + */ + std::string theClassPath = read_classpath_txt (cp_file); + retval.append(theClassPath); + } + } + else + { + throw std::string("octave jar does not exist: ") + jar_file; + } + } + else + { + throw std::string("initial java dir is empty"); + } + + return retval; +} + +static void initialize_jvm () +{ + JNIEnv *current_env; + + if (jvm) return; + + const char *static_locale = setlocale(LC_ALL, NULL); + const std::string locale(static_locale); + +#if defined (__WIN32__) + + HMODULE hMod = GetModuleHandle("jvm.dll"); + std::string jvm_lib_path; + std::string old_cwd; + + if (hMod == NULL) + { + // In windows, find the location of the JRE from the registry + // and load the symbol from the dll. + std::string key, value; + + key = "software\\javasoft\\java runtime environment"; + + value = octave_env::getenv ("JAVA_VERSION"); + if (value.empty ()) + { + value = "Currentversion"; + std::string regval = read_registry_string (key,value); + if (regval.empty ()) + throw std::string ("unable to find Java Runtime Environment: ")+key+"::"+value; + value = regval; + } + + key = key + "\\" + value; + value = "RuntimeLib"; + jvm_lib_path = read_registry_string (key,value); + if (jvm_lib_path.empty()) + throw std::string ("unable to find Java Runtime Environment: ")+key+"::"+value; + + std::string jvm_bin_path; + + value = "JavaHome"; + jvm_bin_path = read_registry_string (key, value); + if (! jvm_bin_path.empty ()) + { + jvm_bin_path = (jvm_bin_path + std::string ("\\bin")); +#ifdef HAVE_OCTAVE_32 + old_cwd = octave_env::getcwd (); +#else + old_cwd = octave_env::get_current_directory (); +#endif + set_dll_directory (jvm_bin_path); + octave_env::chdir (jvm_bin_path); + } + } + else + { + // JVM seems to be already loaded, better to use that DLL instead + // of looking in the registry, to avoid opening a different JVM. + jvm_lib_path = get_module_filename(hMod); + if (jvm_lib_path.empty()) + throw std::string ("unable to find Java Runtime Environment"); + } + +#else + + std::string jvm_lib_path = JAVA_HOME+std::string("/jre/lib/")+JAVA_ARCH+"/server/libjvm.so"; + +#endif + + jsize nVMs = 0; + +# if !defined (__APPLE__) && !defined (__MACH__) + + octave_shlib lib (jvm_lib_path); + if (!lib) + throw std::string("unable to load Java Runtime Environment from ")+jvm_lib_path; + +#if defined (__WIN32__) + set_dll_directory (); + if (! old_cwd.empty ()) + octave_env::chdir (old_cwd); +#endif + + JNI_CreateJavaVM_t create_vm = (JNI_CreateJavaVM_t)lib.search("JNI_CreateJavaVM"); + JNI_GetCreatedJavaVMs_t get_vm = (JNI_GetCreatedJavaVMs_t)lib.search("JNI_GetCreatedJavaVMs"); + if (!create_vm) + throw std::string("unable to find JNI_CreateJavaVM in ")+jvm_lib_path; + if (!get_vm) + throw std::string("unable to find JNI_GetCreatedJavaVMs in ")+jvm_lib_path; + + if (get_vm(&jvm, 1, &nVMs) == 0 && nVMs > 0) + +#else + + // FIXME: There exists a problem on the Mac platform that + // octave_shlib lib (jvm_lib_path) + // doesn't work with 'not-bundled' *.oct files. + + if (JNI_GetCreatedJavaVMs(&jvm, 1, &nVMs) == 0 && nVMs > 0) + +#endif + + { + // At least one JVM exists, try to attach to it + + switch (jvm->GetEnv((void**)¤t_env, JNI_VERSION_1_2)) + { + case JNI_EDETACHED: + // Attach the current thread + JavaVMAttachArgs vm_args; + vm_args.version = JNI_VERSION_1_2; + vm_args.name = (char*)"octave"; + vm_args.group = NULL; + if (jvm->AttachCurrentThread((void**)¤t_env, &vm_args) < 0) + throw std::string("JVM internal error, unable to attach octave to existing JVM"); + break; + case JNI_EVERSION: + throw std::string("JVM internal error, the required JNI version is not supported"); + break; + case JNI_OK: + // Don't do anything, the current thread is already attached to JVM + break; + } + + jvm_attached = true; + //printf("JVM attached\n"); + } + else + { + // No JVM exists, create one + + JVMArgs vm_args; + + vm_args.add ("-Djava.class.path=" + initial_class_path ()); + vm_args.add ("-Doctave.java.path=" + initial_java_dir (true)); + vm_args.add ("-Xrs"); + vm_args.add ("-Djava.system.class.loader=org.octave.OctClassLoader"); + vm_args.read_java_opts (initial_java_dir (false) + file_ops::dir_sep_str () + "java.opts"); + +# if !defined (__APPLE__) && !defined (__MACH__) + + if (create_vm (&jvm, ¤t_env, vm_args.to_args ()) != JNI_OK) + throw std::string("unable to start Java VM in ")+jvm_lib_path; + //printf("JVM created\n"); + } + + jvm_lib = lib; + +#else + + if (JNI_CreateJavaVM (&jvm, reinterpret_cast(¤t_env), + vm_args.to_args ()) != JNI_OK) + throw std::string("unable to start Java VM in ")+jvm_lib_path; + + } + +#endif + + setlocale(LC_ALL, locale.c_str()); +} + +static void terminate_jvm(void) +{ + if (jvm) + { + if (jvm_attached) + jvm->DetachCurrentThread (); + else + jvm->DestroyJavaVM (); + jvm = 0; + jvm_attached = false; + + if (jvm_lib) + jvm_lib.close (); + } +} + +std::string jstring_to_string (JNIEnv* jni_env, jstring s) +{ + std::string retval; + if (jni_env) + { + const char *cstr = jni_env->GetStringUTFChars (s, 0); + retval = cstr; + jni_env->ReleaseStringUTFChars (s, cstr); + } + return retval; +} + +std::string jstring_to_string (JNIEnv* jni_env, jobject obj) +{ + std::string retval; + if (jni_env && obj) + { + jclass_ref cls (jni_env, jni_env->FindClass ("java/lang/String")); + if (cls) + { + if (jni_env->IsInstanceOf (obj, cls)) + retval = jstring_to_string (jni_env, reinterpret_cast (obj)); + } + } + return retval; +} + +static octave_value check_exception (JNIEnv* jni_env) +{ + octave_value retval; + jthrowable_ref ex (jni_env, jni_env->ExceptionOccurred ()); + + if (ex) + { + if (Vjava_debug) + jni_env->ExceptionDescribe (); + jni_env->ExceptionClear (); + + jclass_ref jcls (jni_env, jni_env->GetObjectClass (ex)); + jmethodID mID = jni_env->GetMethodID (jcls, "toString", "()Ljava/lang/String;"); + jstring_ref js (jni_env, reinterpret_cast (jni_env->CallObjectMethod (ex, mID))); + std::string msg = jstring_to_string (jni_env, js); + + error ("[java] %s", msg.c_str ()); + } + else + retval = Matrix (); + return retval; +} + +static jclass find_octave_class (JNIEnv *jni_env, char *name) +{ + static std::string class_loader; + static jclass uiClass = 0; + + jclass jcls = jni_env->FindClass (name); + + if (jcls == 0) + { + jni_env->ExceptionClear (); + + if (! uiClass) + { + if (class_loader.empty ()) + { + jclass_ref syscls (jni_env, jni_env->FindClass ("java/lang/System")); + jmethodID mID = jni_env->GetStaticMethodID (syscls, "getProperty", "(Ljava/lang/String;)Ljava/lang/String;"); + jstring_ref js (jni_env, jni_env->NewStringUTF ("octave.class.loader")); + js = reinterpret_cast (jni_env->CallStaticObjectMethod (syscls, mID, jstring (js))); + class_loader = jstring_to_string (jni_env, jstring (js)); + std::replace (class_loader.begin(), class_loader.end (), '.', '/'); + } + + jclass_ref uicls (jni_env, jni_env->FindClass (class_loader.c_str ())); + + if (! uicls) + { + jni_env->ExceptionClear (); + + /* Try the netbeans way */ + std::replace (class_loader.begin(), class_loader.end (), '/', '.'); + jclass_ref jcls2 (jni_env, jni_env->FindClass ("org/openide/util/Lookup")); + jmethodID mID = jni_env->GetStaticMethodID (jcls2, "getDefault", "()Lorg/openide/util/Lookup;"); + jobject_ref lObj (jni_env, jni_env->CallStaticObjectMethod (jcls2, mID)); + mID = jni_env->GetMethodID (jcls2, "lookup", "(Ljava/lang/Class;)Ljava/lang/Object;"); + jclass_ref cLoaderCls (jni_env, jni_env->FindClass ("java/lang/ClassLoader")); + jobject_ref cLoader (jni_env, jni_env->CallObjectMethod (lObj, mID, jclass (cLoaderCls))); + mID = jni_env->GetMethodID (cLoaderCls, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;"); + jstring_ref js (jni_env, jni_env->NewStringUTF (class_loader.c_str ())); + uicls = reinterpret_cast (jni_env->CallObjectMethod (cLoader, mID, jstring (js))); + } + + if (uicls) + uiClass = reinterpret_cast (jni_env->NewGlobalRef (jclass (uicls))); + } + + if (uiClass) + { + jmethodID mID = jni_env->GetStaticMethodID (uiClass, "findClass", "(Ljava/lang/String;)Ljava/lang/Class;"); + jstring_ref js (jni_env, jni_env->NewStringUTF (name)); + jcls = reinterpret_cast (jni_env->CallStaticObjectMethod (uiClass, mID, jstring (js))); + } + } + return jcls; +} + +static dim_vector compute_array_dimensions (JNIEnv* jni_env, jobject obj) +{ + jobjectArray_ref jobj (jni_env, reinterpret_cast (obj)); + jclass_ref jcls (jni_env, jni_env->GetObjectClass (obj)); + jclass_ref ccls (jni_env, jni_env->GetObjectClass (jcls)); + jmethodID isArray_ID = jni_env->GetMethodID (ccls, "isArray", "()Z"), + getComponentType_ID = jni_env->GetMethodID (ccls, "getComponentType", "()Ljava/lang/Class;"); + dim_vector dv (1, 1); + int idx = 0; + + jobj.detach (); + while (jcls && jni_env->CallBooleanMethod (jcls, isArray_ID)) + { + int len = (jobj ? jni_env->GetArrayLength (jobj) : 0); + if (idx >= dv.length ()) + dv.resize (idx+1); + dv (idx) = len; + jcls = reinterpret_cast (jni_env->CallObjectMethod (jcls, getComponentType_ID)); + jobj = (len > 0 ? reinterpret_cast (jni_env->GetObjectArrayElement (jobj, 0)) : 0); + idx++; + } + return dv; +} + +static jobject make_java_index (JNIEnv* jni_env, const octave_value_list& idx) +{ + jclass_ref ocls (jni_env, jni_env->FindClass ("[I")); + jobjectArray retval = jni_env->NewObjectArray (idx.length (), ocls, 0); + for (int i=0; iNewIntArray (v.length ())); + jint *buf = jni_env->GetIntArrayElements (i_array, 0); + for (int k=0; kReleaseIntArrayElements (i_array, buf, 0); + jni_env->SetObjectArrayElement (retval, i, i_array); + check_exception (jni_env); + if (error_state) + break; + } + else + break; + } + return retval; +} + +static octave_value get_array_elements (JNIEnv* jni_env, jobject jobj, const octave_value_list& idx) +{ + octave_value retval; + jobject_ref resObj (jni_env); + jobject_ref java_idx (jni_env, make_java_index (jni_env, idx)); + + if (! error_state) + { + jclass_ref helperClass (jni_env, find_octave_class (jni_env, (char*)"org/octave/ClassHelper")); + jmethodID mID = jni_env->GetStaticMethodID (helperClass, "arraySubsref", "(Ljava/lang/Object;[[I)Ljava/lang/Object;"); + resObj = jni_env->CallStaticObjectMethod (helperClass, mID, jobj, jobject (java_idx)); + } + + if (resObj) + retval = box (jni_env, resObj); + else + retval = check_exception (jni_env); + + return retval; +} + +static octave_value set_array_elements (JNIEnv* jni_env, jobject jobj, const octave_value_list& idx, const octave_value& rhs) +{ + octave_value retval; + jclass_ref rhsCls (jni_env); + jobject_ref resObj (jni_env), rhsObj (jni_env); + jobject_ref java_idx (jni_env, make_java_index (jni_env, idx)); + + if (! error_state && unbox (jni_env, rhs, rhsObj, rhsCls)) + { + jclass_ref helperClass (jni_env, find_octave_class (jni_env, (char*)"org/octave/ClassHelper")); + jmethodID mID = jni_env->GetStaticMethodID (helperClass, "arraySubsasgn", + "(Ljava/lang/Object;[[ILjava/lang/Object;)Ljava/lang/Object;"); + resObj = jni_env->CallStaticObjectMethod (helperClass, mID, + jobj, jobject (java_idx), jobject (rhsObj)); + } + + if (resObj) + retval = box (jni_env, resObj); + else + retval = check_exception (jni_env); + + return retval; +} + +static string_vector get_invoke_list (JNIEnv* jni_env, jobject jobj) +{ + std::list name_list; + if (jni_env) + { + jclass_ref cls (jni_env, jni_env->GetObjectClass (jobj)); + jclass_ref ccls (jni_env, jni_env->GetObjectClass (cls)); + jmethodID getMethods_ID = jni_env->GetMethodID (ccls, "getMethods", "()[Ljava/lang/reflect/Method;"), + getFields_ID = jni_env->GetMethodID (ccls, "getFields", "()[Ljava/lang/reflect/Field;"); + jobjectArray_ref mList (jni_env, reinterpret_cast (jni_env->CallObjectMethod (cls, getMethods_ID))), + fList (jni_env, reinterpret_cast (jni_env->CallObjectMethod (cls, getFields_ID))); + int mLen = jni_env->GetArrayLength (mList), fLen = jni_env->GetArrayLength (fList); + jclass_ref mCls (jni_env, jni_env->FindClass ("java/lang/reflect/Method")), + fCls (jni_env, jni_env->FindClass ("java/lang/reflect/Field")); + jmethodID m_getName_ID = jni_env->GetMethodID (mCls, "getName", "()Ljava/lang/String;"), + f_getName_ID = jni_env->GetMethodID (fCls, "getName", "()Ljava/lang/String;"); + for (int i=0; iGetObjectArrayElement (mList, i)); + jstring_ref methName (jni_env, reinterpret_cast (jni_env->CallObjectMethod (meth, m_getName_ID))); + name_list.push_back (jstring_to_string (jni_env, methName)); + } + for (int i=0; iGetObjectArrayElement (fList, i)); + jstring_ref fieldName (jni_env, reinterpret_cast (jni_env->CallObjectMethod (field, f_getName_ID))); + name_list.push_back (jstring_to_string (jni_env, fieldName)); + } + } + + string_vector v (name_list); + return v.sort (true); +} + +static octave_value convert_to_string (JNIEnv *jni_env, jobject java_object, bool force, char type) +{ + octave_value retval; + + if (jni_env && java_object) + { + jclass_ref cls (jni_env, jni_env->FindClass ("java/lang/String")); + if (jni_env->IsInstanceOf (java_object, cls)) + retval = octave_value (jstring_to_string (jni_env, java_object), type); + else if (force) + { + cls = jni_env->FindClass ("[Ljava/lang/String;"); + if (jni_env->IsInstanceOf (java_object, cls)) + { + jobjectArray array = reinterpret_cast (java_object); + int len = jni_env->GetArrayLength (array); + Cell c (len, 1); + for (int i=0; i (jni_env->GetObjectArrayElement (array, i))); + if (js) + c(i) = octave_value (jstring_to_string (jni_env, js), type); + else + { + c(i) = check_exception (jni_env); + if (error_state) + break; + } + } + retval = octave_value (c); + } + else + { + cls = jni_env->FindClass ("java/lang/Object"); + jmethodID mID = jni_env->GetMethodID (cls, "toString", "()Ljava/lang/String;"); + jstring_ref js (jni_env, reinterpret_cast (jni_env->CallObjectMethod (java_object, mID))); + if (js) + retval = octave_value (jstring_to_string (jni_env, js), type); + else + retval = check_exception (jni_env); + } + } + else + error ("unable to convert Java object to string"); + } + + return retval; +} + +#define TO_JAVA(obj) dynamic_cast((obj).internal_rep()) + +octave_value box (JNIEnv* jni_env, jobject jobj, jclass jcls) +{ + octave_value retval; + jclass_ref cls (jni_env); + + if (! jobj) + retval = Matrix (); + + if (retval.is_undefined ()) + { + cls = jni_env->FindClass ("java/lang/Integer"); + if (jni_env->IsInstanceOf (jobj, cls)) + { + jmethodID m = jni_env->GetMethodID (cls, "intValue", "()I"); + retval = jni_env->CallIntMethod (jobj, m); + } + } + + if (retval.is_undefined ()) + { + cls = jni_env->FindClass ("java/lang/Double"); + if (jni_env->IsInstanceOf (jobj, cls)) + { + jmethodID m = jni_env->GetMethodID (cls, "doubleValue", "()D"); + retval = jni_env->CallDoubleMethod (jobj, m); + } + } + + if (retval.is_undefined ()) + { + cls = jni_env->FindClass ("java/lang/Boolean"); + if (jni_env->IsInstanceOf (jobj, cls)) + { + jmethodID m = jni_env->GetMethodID (cls, "booleanValue", "()Z"); + // MH retval = jni_env->CallBooleanMethod (jobj, m); + retval = (jni_env->CallBooleanMethod (jobj, m) ? true : false); + } + } + + if (retval.is_undefined ()) + { + cls = jni_env->FindClass ("java/lang/String"); + if (jni_env->IsInstanceOf (jobj, cls)) + { + retval = jstring_to_string (jni_env, jobj); + } + } + + if (retval.is_undefined () && Vjava_convert_matrix) + { + cls = find_octave_class (jni_env, (char*)"org/octave/Matrix"); + if (jni_env->IsInstanceOf (jobj, cls)) + { + jmethodID mID = jni_env->GetMethodID (cls, "getDims", "()[I"); + jintArray_ref iv (jni_env, reinterpret_cast (jni_env->CallObjectMethod (jobj, mID))); + jint *iv_data = jni_env->GetIntArrayElements (jintArray (iv), 0); + dim_vector dims; + dims.resize (jni_env->GetArrayLength (jintArray (iv))); + for (int i=0; iReleaseIntArrayElements (jintArray (iv), iv_data, 0); + mID = jni_env->GetMethodID (cls, "getClassName", "()Ljava/lang/String;"); + jstring_ref js (jni_env, reinterpret_cast (jni_env->CallObjectMethod (jobj, mID))); + std::string s = jstring_to_string (jni_env, js); + if (s == "double") + { + NDArray m (dims); + mID = jni_env->GetMethodID (cls, "toDouble", "()[D"); + jdoubleArray_ref dv (jni_env, reinterpret_cast (jni_env->CallObjectMethod (jobj, mID))); + jni_env->GetDoubleArrayRegion (dv, 0, m.length (), m.fortran_vec ()); + retval = m; + } + else if (s == "byte") + { + if (Vjava_unsigned_conversion) + { + uint8NDArray m (dims); + mID = jni_env->GetMethodID (cls, "toByte", "()[B"); + jbyteArray_ref dv (jni_env, reinterpret_cast (jni_env->CallObjectMethod (jobj, mID))); + jni_env->GetByteArrayRegion (dv, 0, m.length (), (jbyte*)m.fortran_vec ()); + retval = m; + } + else + { + int8NDArray m (dims); + mID = jni_env->GetMethodID (cls, "toByte", "()[B"); + jbyteArray_ref dv (jni_env, reinterpret_cast (jni_env->CallObjectMethod (jobj, mID))); + jni_env->GetByteArrayRegion (dv, 0, m.length (), (jbyte*)m.fortran_vec ()); + retval = m; + } + } + else if (s == "integer") + { + if (Vjava_unsigned_conversion) + { + uint32NDArray m (dims); + mID = jni_env->GetMethodID (cls, "toInt", "()[I"); + jintArray_ref dv (jni_env, reinterpret_cast (jni_env->CallObjectMethod (jobj, mID))); + jni_env->GetIntArrayRegion (dv, 0, m.length (), (jint*)m.fortran_vec ()); + retval = m; + } + else + { + int32NDArray m (dims); + mID = jni_env->GetMethodID (cls, "toInt", "()[I"); + jintArray_ref dv (jni_env, reinterpret_cast (jni_env->CallObjectMethod (jobj, mID))); + jni_env->GetIntArrayRegion (dv, 0, m.length (), (jint*)m.fortran_vec ()); + retval = m; + } + } + } + } + + if (retval.is_undefined ()) + { + cls = find_octave_class (jni_env, (char*)"org/octave/OctaveReference"); + if (jni_env->IsInstanceOf (jobj, cls)) + { + jmethodID mID = jni_env->GetMethodID (cls, "getID", "()I"); + int ID = jni_env->CallIntMethod (jobj, mID); + std::map::iterator it = octave_ref_map.find (ID); + + if (it != octave_ref_map.end ()) + retval = it->second; + } + } + + if (retval.is_undefined ()) + retval = octave_value (new octave_java (jobj, jcls)); + + return retval; +} + +octave_value box_more (JNIEnv* jni_env, jobject jobj, jclass jcls) +{ + octave_value retval = box (jni_env, jobj, jcls); + + if (retval.class_name () == "octave_java") + { + retval = octave_value (); + + jclass_ref cls (jni_env); + + if (retval.is_undefined ()) + { + cls = jni_env->FindClass ("[D"); + if (jni_env->IsInstanceOf (jobj, cls)) + { + jdoubleArray jarr = reinterpret_cast (jobj); + int len = jni_env->GetArrayLength (jarr); + if (len > 0) + { + Matrix m (1, len); + jni_env->GetDoubleArrayRegion (jarr, 0, len, m.fortran_vec ()); + retval = m; + } + else + retval = Matrix (); + } + } + + if (retval.is_undefined ()) + { + cls = jni_env->FindClass ("[[D"); + if (jni_env->IsInstanceOf (jobj, cls)) + { + jobjectArray jarr = reinterpret_cast (jobj); + int rows = jni_env->GetArrayLength (jarr), cols = 0; + if (rows > 0) + { + Matrix m; + for (int r = 0; r < rows; r++) + { + jdoubleArray_ref row (jni_env, reinterpret_cast (jni_env->GetObjectArrayElement (jarr, r))); + if (m.length () == 0) + { + cols = jni_env->GetArrayLength (row); + m.resize (cols, rows); + } + jni_env->GetDoubleArrayRegion (row, 0, cols, m.fortran_vec () + r * cols); + } + retval = m.transpose (); + } + else + retval = Matrix(); + } + } + + if (retval.is_undefined ()) + { + cls = jni_env->FindClass ("[Ljava/lang/String;"); + if (jni_env->IsInstanceOf (jobj, cls)) + { + jobjectArray jarr = reinterpret_cast (jobj); + int len = jni_env->GetArrayLength (jarr); + Cell m(len, 1); + for (int i=0; i (jni_env->GetObjectArrayElement (jarr, i))); + m(i) = jstring_to_string (jni_env, js); + } + retval = m; + } + } + } + + if (retval.is_undefined ()) + retval = octave_value (new octave_java (jobj, jcls)); + + return retval; +} + +int unbox (JNIEnv* jni_env, const octave_value& val, jobject_ref& jobj, jclass_ref& jcls) +{ + int found = 1; + + if (val.class_name () == "octave_java") + { + octave_java *ovj = TO_JAVA (val); + jobj = ovj->to_java (); + jobj.detach (); + jcls = jni_env->GetObjectClass (jobj); + } + else if (val.is_string ()) + { + std::string s = val.string_value (); + jobj = jni_env->NewStringUTF (s.c_str ()); + jcls = jni_env->GetObjectClass (jobj); + } + else if (val.is_bool_scalar ()) + { + bool bval = val.bool_value (); + jclass_ref bcls (jni_env, jni_env->FindClass ("java/lang/Boolean")); + jfieldID fid = jni_env->GetStaticFieldID (bcls, "TYPE", "Ljava/lang/Class;"); + jmethodID mid = jni_env->GetMethodID (bcls, "", "(Z)V"); + jcls = reinterpret_cast (jni_env->GetStaticObjectField (bcls, fid)); + jobj = jni_env->NewObject (bcls, mid, bval); + } + else if (val.is_real_scalar ()) + { + double dval = val.double_value (); + jclass_ref dcls (jni_env, jni_env->FindClass ("java/lang/Double")); + jfieldID fid = jni_env->GetStaticFieldID (dcls, "TYPE", "Ljava/lang/Class;"); + jmethodID mid = jni_env->GetMethodID (dcls, "", "(D)V"); + jcls = reinterpret_cast (jni_env->GetStaticObjectField (dcls, fid)); + jobj = jni_env->NewObject (dcls, mid, dval); + } + else if (val.is_empty ()) + { + jobj = 0; + //jcls = jni_env->FindClass ("java/lang/Object"); + jcls = 0; + } + else if (!Vjava_convert_matrix && ((val.is_real_matrix () && (val.rows() == 1 || val.columns() == 1)) || val.is_range ())) + { + Matrix m = val.matrix_value (); + jdoubleArray dv = jni_env->NewDoubleArray (m.length ()); + //for (int i=0; iSetDoubleArrayRegion (dv, 0, m.length (), m.fortran_vec ()); + jobj = dv; + jcls = jni_env->GetObjectClass (jobj); + } + else if (Vjava_convert_matrix && (val.is_matrix_type () || val.is_range()) && val.is_real_type ()) + { + jclass_ref mcls (jni_env, find_octave_class (jni_env, (char*)"org/octave/Matrix")); + dim_vector dims = val.dims (); + jintArray_ref iv (jni_env, jni_env->NewIntArray (dims.length ())); + jint *iv_data = jni_env->GetIntArrayElements (jintArray (iv), 0); + for (int i=0; iReleaseIntArrayElements (jintArray (iv), iv_data, 0); + if (val.is_double_type ()) + { + NDArray m = val.array_value (); + jdoubleArray_ref dv (jni_env, jni_env->NewDoubleArray (m.length ())); + jni_env->SetDoubleArrayRegion (jdoubleArray (dv), 0, m.length (), m.fortran_vec ()); + jmethodID mID = jni_env->GetMethodID (mcls, "", "([D[I)V"); + jobj = jni_env->NewObject (jclass (mcls), mID, jdoubleArray (dv), jintArray (iv)); + jcls = jni_env->GetObjectClass (jobj); + } + else if (val.is_int8_type ()) + { + int8NDArray m = val.int8_array_value (); + jbyteArray_ref bv (jni_env, jni_env->NewByteArray (m.length ())); + jni_env->SetByteArrayRegion (jbyteArray (bv), 0, m.length (), (jbyte*)m.fortran_vec ()); + jmethodID mID = jni_env->GetMethodID (mcls, "", "([B[I)V"); + jobj = jni_env->NewObject (jclass (mcls), mID, jbyteArray (bv), jintArray (iv)); + jcls = jni_env->GetObjectClass (jobj); + } + else if (val.is_uint8_type ()) + { + uint8NDArray m = val.uint8_array_value (); + jbyteArray_ref bv (jni_env, jni_env->NewByteArray (m.length ())); + jni_env->SetByteArrayRegion (jbyteArray (bv), 0, m.length (), (jbyte*)m.fortran_vec ()); + jmethodID mID = jni_env->GetMethodID (mcls, "", "([B[I)V"); + jobj = jni_env->NewObject (jclass (mcls), mID, jbyteArray (bv), jintArray (iv)); + jcls = jni_env->GetObjectClass (jobj); + } + else if (val.is_int32_type ()) + { + int32NDArray m = val.int32_array_value (); + jintArray_ref v (jni_env, jni_env->NewIntArray (m.length ())); + jni_env->SetIntArrayRegion (jintArray (v), 0, m.length (), (jint*)m.fortran_vec ()); + jmethodID mID = jni_env->GetMethodID (mcls, "", "([I[I)V"); + jobj = jni_env->NewObject (jclass (mcls), mID, jintArray (v), jintArray (iv)); + jcls = jni_env->GetObjectClass (jobj); + } + else + { + found = 0; + error ("cannot convert matrix of type `%s'", val.class_name ().c_str ()); + } + } + else if (val.is_cellstr ()) + { + Cell cellStr = val.cell_value (); + jclass_ref scls (jni_env, jni_env->FindClass ("java/lang/String")); + jobjectArray array = jni_env->NewObjectArray (cellStr.length (), scls, 0); + for (int i=0; iNewStringUTF (cellStr(i).string_value().c_str())); + jni_env->SetObjectArrayElement (array, i, jstr); + } + jobj = array; + jcls = jni_env->GetObjectClass (jobj); + } + else + { + jclass rcls = find_octave_class (jni_env, (char*)"org/octave/OctaveReference"); + jmethodID mID = jni_env->GetMethodID (rcls, "", "(I)V"); + int ID = octave_java_refcount++; + + jobj = jni_env->NewObject (rcls, mID, ID); + jcls = rcls; + octave_ref_map[ID] = val; + } + + return found; +} + +int unbox (JNIEnv* jni_env, const octave_value_list& args, jobjectArray_ref& jobjs, jobjectArray_ref& jclss) +{ + int found = 1; + jclass_ref ocls (jni_env, jni_env->FindClass ("java/lang/Object")); + jclass_ref ccls (jni_env, jni_env->FindClass ("java/lang/Class")); + + if (! jobjs) + jobjs = jni_env->NewObjectArray (args.length (), ocls, 0); + if (! jclss) + jclss = jni_env->NewObjectArray (args.length (), ccls, 0); + for (int i=0; iSetObjectArrayElement (jobjs, i, jobj); + jni_env->SetObjectArrayElement (jclss, i, jcls); + } + + return found; +} + + +static long get_current_thread_ID(JNIEnv *jni_env) +{ + if (jni_env) + { + jclass_ref cls (jni_env, jni_env->FindClass ("java/lang/Thread")); + jmethodID mID = jni_env->GetStaticMethodID (cls, "currentThread", "()Ljava/lang/Thread;"); + jobject_ref jthread (jni_env, jni_env->CallStaticObjectMethod (cls, mID)); + if (jthread) + { + jclass_ref jth_cls (jni_env, jni_env->GetObjectClass (jthread)); + mID = jni_env->GetMethodID (jth_cls, "getId", "()J"); + long result = jni_env->CallLongMethod (jthread, mID); + //printf("current java thread ID = %ld\n", result); + return result; + } + } + return -1; +} + +static int java_event_hook (void) +{ + JNIEnv *current_env = octave_java::thread_jni_env (); + + if (current_env) + { + jclass_ref cls (current_env, find_octave_class (current_env, (char*)"org/octave/Octave")); + jmethodID mID = current_env->GetStaticMethodID (cls, "checkPendingAction", "()V"); + current_env->CallStaticVoidMethod (cls, mID); + } + return 0; +} + +static void initialize_java (void) +{ + if (! jvm) + { + try + { + initialize_jvm (); + + JNIEnv *current_env = octave_java::thread_jni_env (); + + octave_java::register_type (); + command_editor::add_event_hook (java_event_hook); + octave_thread_ID = get_current_thread_ID (current_env); + //printf("octave thread ID=%ld\n", octave_thread_ID); + } + catch (std::string msg) + { + error (msg.c_str ()); + } + } +} + +DEFUN_DLD (java_init, args, , "") +{ + + octave_value retval; + + retval = 0; + initialize_java (); + if (! error_state) + retval = 1; + + return retval; +} + +DEFUN_DLD (java_exit, args, , "") +{ + octave_value retval; + + terminate_jvm (); + + return retval; +} + +DEFUN_DLD (java_new, args, , + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{obj} =} java_new (@var{name}, @var{arg1}, ...)\n\ +Create a Java object of class @var{name}, by calling the class constructor with the\n\ +arguments @var{arg1}, ...\n\ +\n\ +@example\n\ + x = java_new (\"java.lang.StringBuffer\", \"Initial string\")\n\ +@end example\n\ +\n\ +@seealso{java_invoke, java_get, java_set}\n\ +@end deftypefn") +{ + return _java_new ( args ); +} + + +DEFUN_DLD (javaObject, args, , + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{obj} =} javaObject (@var{name}, @var{arg1}, ...)\n\ +Create a Java object of class @var{name}, by calling the class constructor with the\n\ +arguments @var{arg1}, ...\n\ +The first example creates an unitialized object, \ +while the second example supplies an initializer argument.\n\ +\n\ +@example\n\ + x = javaObject (\"java.lang.StringBuffer\")\n\ + x = javaObject (\"java.lang.StringBuffer\", \"Initial string\")\n\ +@end example\n\ +\n\ +@seealso{java_invoke, java_new, java_get, java_set}\n\ +@end deftypefn") +{ + return _java_new ( args ); +} + +// internally called from java_new and javaObject for backward compatibility +static octave_value _java_new ( const octave_value_list& args ) +{ + octave_value retval; + + initialize_java (); + if (! error_state) + { + JNIEnv *current_env = octave_java::thread_jni_env (); + + if (args.length () > 0) + { + std::string name = args(0).string_value (); + if (! error_state) + { + octave_value_list tmp; + for (int i=1; i 1) + { + // swap first two arguments + octave_value_list tmp; + tmp(0) = args(1); + tmp(1) = args(0); + // copy remaining arguments + for (int i=2; i 1) + { + std::string name = args(1).string_value (); + if (! error_state) + { + octave_value_list tmp; + for (int i=2; ido_java_invoke (current_env, name, tmp); + } + else if (args(0).is_string ()) + { + std::string cls = args(0).string_value (); + retval = octave_java::do_java_invoke (current_env, cls, name, tmp); + } + else + error ("java_invoke: first argument must be a Java object or a string"); + } + else + error ("java_invoke: second argument must be a string"); + } + else + print_usage (); + } + + return retval; +} + +DEFUN_DLD (java_get, args, , + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{val} =} java_get (@var{obj}, @var{name})\n\ +Get the value of the field @var{name} of the Java object @var{obj}. For\n\ +static fields, @var{obj} can be a string representing the fully qualified\n\ +name of the corresponding class.\n\ +\n\ +When @var{obj} is a regular Java object, the structure-like indexing can be used\n\ +as a shortcut syntax. For instance, the two following statements are equivalent\n\ +\n\ +@example\n\ + java_get (x, \"field1\")\n\ + x.field1\n\ +@end example\n\ +\n\ +@seealso{java_set, java_invoke, java_new}\n\ +@end deftypefn") +{ + octave_value retval; + + initialize_java (); + if (! error_state) + { + JNIEnv *current_env = octave_java::thread_jni_env (); + + if (args.length () == 2) + { + std::string name = args(1).string_value (); + if (! error_state) + { + if (args(0).class_name () == "octave_java") + { + octave_java *jobj = TO_JAVA (args(0)); + retval = jobj->do_java_get (current_env, name); + } + else if (args(0).is_string ()) + { + std::string cls = args(0).string_value (); + retval = octave_java::do_java_get (current_env, cls, name); + } + else + error ("java_get: first argument must be a Java object or a string"); + } + else + error ("java_get: second argument must be a string"); + } + else + print_usage (); + } + + return retval; +} + +DEFUN_DLD (java_set, args, , + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{obj} =} java_set (@var{obj}, @var{name}, @var{val})\n\ +Set the value of the field @var{name} of the Java object @var{obj} to @var{val}.\n\ +For static fields, @var{obj} can be a string representing the fully qualified named\n\ +of the corresponding Java class.\n\ +\n\ +When @var{obj} is a regular Java object, the structure-like indexing can be used as\n\ +a shortcut syntax. For instance, the two following statements are equivalent\n\ +\n\ +@example\n\ + java_set (x, \"field1\", val)\n\ + x.field1 = val\n\ +@end example\n\ +\n\ +@seealso{java_get, java_invoke, java_new}\n\ +@end deftypefn") +{ + octave_value retval; + + initialize_java (); + if (! error_state) + { + JNIEnv *current_env = octave_java::thread_jni_env (); + + if (args.length () == 3) + { + std::string name = args(1).string_value (); + if (! error_state) + { + if (args(0).class_name () == "octave_java") + { + octave_java *jobj = TO_JAVA (args(0)); + retval = jobj->do_java_set (current_env, name, args(2)); + } + else if (args(0).is_string ()) + { + std::string cls = args(0).string_value (); + retval = octave_java::do_java_set (current_env, cls, name, args(2)); + } + else + error ("java_set: first argument must be a Java object or a string"); + } + else + error ("java_set: second argument must be a string"); + } + else + print_usage (); + } + + return retval; +} + +DEFUN_DLD (java2mat, args, , "") +{ + octave_value_list retval; + + initialize_java (); + if (! error_state) + { + JNIEnv *current_env = octave_java::thread_jni_env (); + + if (args.length () == 1) + { + if (args(0).class_name () == "octave_java") + { + octave_java *jobj = TO_JAVA (args(0)); + retval(0) = box_more (current_env, jobj->to_java (), 0); + } + else + retval(0) = args(0); + } + else + print_usage (); + } + + return retval; +} + +DEFUN_DLD (__java__, args, , "") +{ + return octave_value (); +} + +DEFUN_DLD (java_convert_matrix, args, nargout, "") +{ + return SET_INTERNAL_VARIABLE (java_convert_matrix); +} + +DEFUN_DLD (java_unsigned_conversion, args, nargout, "") +{ + return SET_INTERNAL_VARIABLE (java_unsigned_conversion); +} + +DEFUN_DLD (java_debug, args, nargout, "") +{ + return SET_INTERNAL_VARIABLE (java_debug); +} + +JNIEXPORT jboolean JNICALL Java_org_octave_Octave_call + (JNIEnv *env, jclass, jstring funcName, jobjectArray argin, jobjectArray argout) +{ + std::string fname = jstring_to_string (env, funcName); + int nargout = env->GetArrayLength (argout); + int nargin = env->GetArrayLength (argin); + octave_value_list varargin, varargout; + + for (int i=0; iGetObjectArrayElement (argin, i), 0); + varargout = feval (fname, varargin, nargout); + + if (! error_state) + { + jobjectArray_ref out_objs (env, argout), out_clss (env); + + out_objs.detach (); + if (unbox (env, varargout, out_objs, out_clss)) + return true; + } + + return false; +} + +JNIEXPORT void JNICALL Java_org_octave_OctaveReference_doFinalize + (JNIEnv *env, jclass, jint ID) +{ + octave_ref_map.erase (ID); +} + +JNIEXPORT void JNICALL Java_org_octave_Octave_doInvoke + (JNIEnv *env, jclass, jint ID, jobjectArray args) +{ + std::map::iterator it = octave_ref_map.find (ID); + + if (it != octave_ref_map.end ()) + { + octave_value val = it->second; + int len = env->GetArrayLength (args); + octave_value_list oct_args; + + for (int i=0; iGetObjectArrayElement (args, i)); + oct_args(i) = box (env, jobj, 0); + if (error_state) + break; + } + + if (! error_state) + { + BEGIN_INTERRUPT_WITH_EXCEPTIONS; + + if (val.is_function_handle ()) + { + octave_function *fcn = val.function_value (); + feval (fcn, oct_args); + } + else if (val.is_cell () && val.length () > 0 && + (val.rows () == 1 || val.columns() == 1) && + val.cell_value()(0).is_function_handle ()) + { + Cell c = val.cell_value (); + octave_function *fcn = c(0).function_value (); + + for (int i=1; iGetEnv ((void**)&env, JNI_VERSION_1_2); + + return env; +} + +octave_value_list octave_java::subsref(const std::string& type, const std::list& idx, int nargout) +{ + octave_value_list retval; + int skip = 1; + + JNIEnv *current_env = thread_jni_env (); + + switch (type[0]) + { + case '.': + if (type.length () > 1 && type[1] == '(') + { + octave_value_list ovl; + count++; + ovl(0) = octave_value (this); + ovl(1) = (idx.front ())(0); + std::list::const_iterator it = idx.begin (); + ovl.append (*++it); + retval = feval (std::string ("java_invoke"), ovl, 1); + skip++; + } + else + { + octave_value_list ovl; + count++; + ovl(0) = octave_value (this); + ovl(1) = (idx.front ())(0); + retval = feval (std::string ("java_get"), ovl, 1); + } + break; + case '(': + if (current_env) + retval = get_array_elements (current_env, to_java (), idx.front ()); + break; + default: + error ("subsref: Java object cannot be indexed with %c", type[0]); + break; + } + + if (idx.size () > 1 && type.length () > 1) + retval = retval(0).next_subsref (nargout, type, idx, skip); + + return retval; +} + +octave_value octave_java::subsasgn (const std::string& type, const std::list&idx, const octave_value &rhs) +{ + octave_value retval; + + JNIEnv *current_env = thread_jni_env (); + + switch (type[0]) + { + case '.': + if (type.length () == 1) + { + // field assignment + octave_value_list ovl; + count++; + ovl(0) = octave_value (this); + ovl(1) = (idx.front ())(0); + ovl(2) = rhs; + feval ("java_set", ovl, 0); + if (! error_state) + { + count++; + retval = octave_value (this); + } + } + else if (type.length () > 2 && type[1] == '(') + { + std::list new_idx; + std::list::const_iterator it = idx.begin (); + new_idx.push_back (*it++); + new_idx.push_back (*it++); + octave_value_list u = subsref (type.substr (0, 2), new_idx, 1); + if (! error_state) + { + std::list next_idx (idx); + next_idx.erase (next_idx.begin ()); + next_idx.erase (next_idx.begin ()); + u(0).subsasgn (type.substr (2), next_idx, rhs); + if (! error_state) + { + count++; + retval = octave_value (this); + } + } + } + else if (type[1] == '.') + { + octave_value_list u = subsref (type.substr (0, 1), idx, 1); + if (! error_state) + { + std::list next_idx (idx); + next_idx.erase (next_idx.begin ()); + u(0).subsasgn (type.substr (1), next_idx, rhs); + if (! error_state) + { + count++; + retval = octave_value (this); + } + } + } + else + error ("invalid indexing/assignment on Java object"); + break; + case '(': + if (current_env) + { + set_array_elements (current_env, to_java (), idx.front (), rhs); + if (! error_state) + { + count++; + retval = octave_value (this); + } + } + break; + default: + error ("Java object cannot be indexed with %c", type[0]); + break; + } + + return retval; +} + +string_vector octave_java::map_keys (void) const +{ + JNIEnv *current_env = thread_jni_env (); + + if (current_env) + return get_invoke_list (current_env, to_java ()); + else + return string_vector (); +} + +octave_value octave_java::convert_to_str_internal (bool, bool force, char type) const +{ + JNIEnv *current_env = thread_jni_env (); + + if (current_env) + return convert_to_string (current_env, to_java (), force, type); + else + return octave_value (""); +} + +octave_value octave_java::do_java_invoke (JNIEnv* jni_env, const std::string& name, + const octave_value_list& args) +{ + octave_value retval; + + if (jni_env) + { + jobjectArray_ref arg_objs (jni_env), arg_types (jni_env); + if (unbox (jni_env, args, arg_objs, arg_types)) + { + jclass_ref helperClass (jni_env, find_octave_class (jni_env, (char*)"org/octave/ClassHelper")); + jmethodID mID = jni_env->GetStaticMethodID (helperClass, "invokeMethod", + "(Ljava/lang/Object;Ljava/lang/String;[Ljava/lang/Object;[Ljava/lang/Class;)Ljava/lang/Object;"); + jstring_ref methName (jni_env, jni_env->NewStringUTF (name.c_str ())); + jobjectArray_ref resObj (jni_env, reinterpret_cast (jni_env->CallStaticObjectMethod (helperClass, mID, + to_java (), jstring (methName), jobjectArray (arg_objs), jobjectArray (arg_types)))); + if (resObj) + retval = box (jni_env, resObj); + else + retval = check_exception (jni_env); + } + } + return retval; +} + +octave_value octave_java:: do_java_invoke (JNIEnv* jni_env, const std::string& class_name, + const std::string& name, const octave_value_list& args) +{ + octave_value retval; + + if (jni_env) + { + jobjectArray_ref arg_objs (jni_env), arg_types (jni_env); + if (unbox (jni_env, args, arg_objs, arg_types)) + { + jclass_ref helperClass (jni_env, find_octave_class (jni_env, (char*)"org/octave/ClassHelper")); + jmethodID mID = jni_env->GetStaticMethodID (helperClass, "invokeStaticMethod", + "(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;[Ljava/lang/Class;)Ljava/lang/Object;"); + jstring_ref methName (jni_env, jni_env->NewStringUTF (name.c_str ())); + jstring_ref clsName (jni_env, jni_env->NewStringUTF (class_name.c_str ())); + jobject_ref resObj (jni_env, jni_env->CallStaticObjectMethod (helperClass, mID, + jstring (clsName), jstring (methName), jobjectArray (arg_objs), jobjectArray (arg_types))); + if (resObj) + retval = box (jni_env, resObj); + else + retval = check_exception (jni_env); + } + } + return retval; +} + +octave_value octave_java::do_java_create (JNIEnv* jni_env, const std::string& name, const octave_value_list& args) +{ + octave_value retval; + + if (jni_env) + { + jobjectArray_ref arg_objs (jni_env), arg_types (jni_env); + if (unbox (jni_env, args, arg_objs, arg_types)) + { + jclass_ref helperClass (jni_env, find_octave_class (jni_env, (char*)"org/octave/ClassHelper")); + jmethodID mID = jni_env->GetStaticMethodID (helperClass, "invokeConstructor", + "(Ljava/lang/String;[Ljava/lang/Object;[Ljava/lang/Class;)Ljava/lang/Object;"); + jstring_ref clsName (jni_env, jni_env->NewStringUTF (name.c_str ())); + jobject_ref resObj (jni_env, jni_env->CallStaticObjectMethod (helperClass, mID, + jstring (clsName), jobjectArray (arg_objs), jobjectArray (arg_types))); + if (resObj) + retval = box (jni_env, resObj); + else + check_exception (jni_env); + } + } + return retval; +} + +octave_value octave_java::do_java_get (JNIEnv* jni_env, const std::string& name) +{ + octave_value retval; + + if (jni_env) + { + jclass_ref helperClass (jni_env, find_octave_class (jni_env, (char*)"org/octave/ClassHelper")); + jmethodID mID = jni_env->GetStaticMethodID (helperClass, "getField", + "(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;"); + jstring_ref fName (jni_env, jni_env->NewStringUTF (name.c_str ())); + jobject_ref resObj (jni_env, jni_env->CallStaticObjectMethod (helperClass, mID, + to_java (), jstring (fName))); + if (resObj) + retval = box (jni_env, resObj); + else + retval = check_exception (jni_env); + } + return retval; +} + +octave_value octave_java::do_java_get (JNIEnv* jni_env, const std::string& class_name, const std::string& name) +{ + octave_value retval; + + if (jni_env) + { + jclass_ref helperClass (jni_env, find_octave_class (jni_env, (char*)"org/octave/ClassHelper")); + jmethodID mID = jni_env->GetStaticMethodID (helperClass, "getStaticField", + "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;"); + jstring_ref cName (jni_env, jni_env->NewStringUTF (class_name.c_str ())); + jstring_ref fName (jni_env, jni_env->NewStringUTF (name.c_str ())); + jobject_ref resObj (jni_env, jni_env->CallStaticObjectMethod (helperClass, mID, + jstring (cName), jstring (fName))); + if (resObj) + retval = box (jni_env, resObj); + else + retval = check_exception (jni_env); + } + return retval; +} + +octave_value octave_java::do_java_set (JNIEnv* jni_env, const std::string& name, const octave_value& val) +{ + octave_value retval; + + if (jni_env) + { + jobject_ref jobj (jni_env); + jclass_ref jcls (jni_env); + + if (unbox (jni_env, val, jobj, jcls)) + { + jclass_ref helperClass (jni_env, find_octave_class (jni_env, (char*)"org/octave/ClassHelper")); + jmethodID mID = jni_env->GetStaticMethodID (helperClass, "setField", + "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)V"); + jstring_ref fName (jni_env, jni_env->NewStringUTF (name.c_str ())); + jni_env->CallStaticObjectMethod (helperClass, mID, to_java (), jstring (fName), jobject (jobj)); + check_exception (jni_env); + } + } + return retval; +} + +octave_value octave_java::do_java_set (JNIEnv* jni_env, const std::string& class_name, const std::string& name, const octave_value& val) +{ + octave_value retval; + + if (jni_env) + { + jobject_ref jobj (jni_env); + jclass_ref jcls (jni_env); + + if (unbox (jni_env, val, jobj, jcls)) + { + jclass_ref helperClass (jni_env, find_octave_class (jni_env, (char*)"org/octave/ClassHelper")); + jmethodID mID = jni_env->GetStaticMethodID (helperClass, "setStaticField", + "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Object;)V"); + jstring_ref cName (jni_env, jni_env->NewStringUTF (class_name.c_str ())); + jstring_ref fName (jni_env, jni_env->NewStringUTF (name.c_str ())); + jni_env->CallStaticObjectMethod (helperClass, mID, jstring (cName), jstring (fName), jobject (jobj)); + check_exception (jni_env); + } + } + return retval; +} diff --git a/libinterp/dldfcn/__java__.h b/libinterp/dldfcn/__java__.h new file mode 100755 --- /dev/null +++ b/libinterp/dldfcn/__java__.h @@ -0,0 +1,272 @@ +/* Copyright (C) 2007 Michael Goffioul +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; If not, see . +*/ + +#ifndef __JAVA__H__ +#define __JAVA__H__ + +#include "oct.h" +#include "config.h" +#ifndef OCTAVE_EXPORT +#include "oct-dlldefs.h" +#endif // OCTAVE_EXPORT +#include + +#ifdef JAVAPKG_BUILD +# define JAVAPKG_API OCTAVE_EXPORT +#else +# define JAVAPKG_API OCTAVE_IMPORT +#endif + +template +class java_local_ref +{ +public: + java_local_ref (JNIEnv *_env) + : jobj (0), detached (false), env (_env) + { } + + java_local_ref (JNIEnv *_env, T obj) + : jobj (obj), detached (false), env (_env) + { } + + ~java_local_ref (void) + { + release (); + } + + T& operator= (T obj) + { + release (); + jobj = obj; + detached = false; + return jobj; + } + operator bool () const { return (jobj != 0); } + operator T () { return jobj; } + + void detach () { detached = true; } + +private: + void release (void) + { + if (env && jobj && ! detached) + env->DeleteLocalRef (jobj); + jobj = 0; + } + + java_local_ref (void) + : jobj (0), detached (false), env (0) + { } + + +protected: + T jobj; + bool detached; + JNIEnv *env; +}; + +typedef java_local_ref jobject_ref; +typedef java_local_ref jclass_ref; +typedef java_local_ref jstring_ref; +typedef java_local_ref jobjectArray_ref; +typedef java_local_ref jintArray_ref; +typedef java_local_ref jbyteArray_ref; +typedef java_local_ref jdoubleArray_ref; +typedef java_local_ref jthrowable_ref; + +extern JAVAPKG_API std::string jstring_to_string (JNIEnv* jni_env, jstring s); +extern JAVAPKG_API std::string jstring_to_string (JNIEnv* jni_env, jobject obj); +extern JAVAPKG_API octave_value box (JNIEnv* jni_env, jobject jobj, jclass jcls = 0); +extern JAVAPKG_API octave_value box_more (JNIEnv* jni_env, jobject jobj, jclass jcls = 0); +extern JAVAPKG_API int unbox (JNIEnv* jni_env, const octave_value& val, jobject_ref& jobj, jclass_ref& jcls); +extern JAVAPKG_API int unbox (JNIEnv* jni_env, const octave_value_list& args, jobjectArray_ref& jobjs, jobjectArray_ref& jclss); + +extern JAVAPKG_API bool Vjava_convert_matrix; +extern JAVAPKG_API bool Vjava_unsigned_conversion; +extern JAVAPKG_API bool Vjava_debug; + +class JAVAPKG_API octave_java : public octave_base_value +{ +public: + octave_java (void) + : java_object (0), java_class (0) + { } + + octave_java (const octave_java& jobj) + : java_object (0), java_class (0) + { + init (jobj.java_object, jobj.java_class); + } + + octave_java (jobject obj, jclass cls = 0) + : java_object (0) + { + init (obj, cls); + } + + ~octave_java (void) + { + release (); + } + + jobject to_java () const { return java_object; } + jclass to_class () const { return java_class; } + std::string java_class_name () const { return java_type; } + + octave_base_value* clone(void) const { return new octave_java(*this); } + octave_base_value* empty_clone(void) const { return new octave_java(); } + + bool is_defined(void) const { return true; } + + bool is_map (void) const { return true; } + + string_vector map_keys(void) const; + + dim_vector dims(void) const; + + void print(std::ostream& os, bool pr_as_read_syntax = false) const + { + os << ""; + newline(os); + } + + void print_raw(std::ostream& os, bool pr_as_read_syntax = false) const + { + print(os, pr_as_read_syntax); + } + + octave_value_list subsref (const std::string& type, const std::list& idx, int nargout); + + octave_value subsref (const std::string& type, + const std::list& idx) + { + octave_value_list retval = subsref (type, idx, 1); + return (retval.length () > 0 ? retval(0) : octave_value ()); + } + + octave_value subsasgn (const std::string& type, const std::list& idx, const octave_value& rhs); + + octave_value convert_to_str_internal (bool pad, bool force, char type) const; + + bool is_string (void) const + { + JNIEnv *current_env = thread_jni_env (); + + if (current_env && java_object) + { + jclass_ref cls (current_env, current_env->FindClass ("java/lang/String")); + return current_env->IsInstanceOf (java_object, cls); + } + return false; + } + + static JNIEnv* thread_jni_env (void); + + octave_value do_java_invoke (JNIEnv* jni_env, const std::string& name, + const octave_value_list& args); + + octave_value do_java_invoke (const std::string& name, const octave_value_list& args) + { return do_java_invoke(thread_jni_env (), name, args); } + + static octave_value do_java_invoke (JNIEnv* jni_env, const std::string& class_name, + const std::string& name, const octave_value_list& args); + + static octave_value do_java_invoke (const std::string& class_name, + const std::string& name, const octave_value_list& args) + { return do_java_invoke(thread_jni_env (), class_name, name, args); } + + static octave_value do_java_create (JNIEnv* jni_env, const std::string& name, + const octave_value_list& args); + + static octave_value do_java_create (const std::string& name, const octave_value_list& args) + { return do_java_create (thread_jni_env (), name, args); } + + octave_value do_java_get (JNIEnv* jni_env, const std::string& name); + + octave_value do_java_get (const std::string& name) + { return do_java_get (thread_jni_env (), name); } + + static octave_value do_java_get (JNIEnv* jni_env, const std::string& class_name, + const std::string& name); + + static octave_value do_java_get (const std::string& class_name, const std::string& name) + { return do_java_get (thread_jni_env (), class_name, name); } + + octave_value do_java_set (JNIEnv* jni_env, const std::string& name, const octave_value& val); + + octave_value do_java_set (const std::string& name, const octave_value& val) + { return do_java_set (thread_jni_env (), name, val); } + + static octave_value do_java_set (JNIEnv* jni_env, const std::string& class_name, + const std::string& name, const octave_value& val); + + static octave_value do_java_set (const std::string& class_name, const std::string& name, + const octave_value& val) + { return do_java_set (thread_jni_env (), class_name, name, val); } + +private: + void init (jobject jobj, jclass jcls) + { + JNIEnv *current_env = thread_jni_env (); + + if (current_env) + { + if (jobj) + java_object = current_env->NewGlobalRef (jobj); + if (jcls) + java_class = reinterpret_cast (current_env->NewGlobalRef (jcls)); + else if (java_object) + { + jclass_ref ocls (current_env, current_env->GetObjectClass (java_object)); + java_class = reinterpret_cast (current_env->NewGlobalRef (jclass (ocls))); + } + + if (java_class) + { + jclass_ref clsCls (current_env, current_env->GetObjectClass (java_class)); + jmethodID mID = current_env->GetMethodID (clsCls, "getCanonicalName", "()Ljava/lang/String;"); + jobject_ref resObj (current_env, current_env->CallObjectMethod (java_class, mID)); + java_type = jstring_to_string (current_env, resObj); + } + } + } + + void release () + { + JNIEnv *current_env = thread_jni_env (); + + if (current_env) + { + if (java_object) + current_env->DeleteGlobalRef (java_object); + if (java_class) + current_env->DeleteGlobalRef (java_class); + java_object = 0; + java_class = 0; + } + } + +private: + DECLARE_OCTAVE_ALLOCATOR + + DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA + + jobject java_object; + jclass java_class; + std::string java_type; +}; + +#endif /* __JAVA__H__ */ diff --git a/libinterp/dldfcn/module-files b/libinterp/dldfcn/module-files --- a/libinterp/dldfcn/module-files +++ b/libinterp/dldfcn/module-files @@ -5,6 +5,7 @@ __glpk__.cc|$(GLPK_CPPFLAGS)|$(GLPK_LDFLAGS)|$(GLPK_LIBS) __init_fltk__.cc|$(GRAPHICS_CFLAGS) $(FT2_CPPFLAGS)|$(GRAPHICS_LDFLAGS) $(FT2_LDFLAGS)|$(GRAPHICS_LIBS) $(FT2_LIBS) __init_gnuplot__.cc +__java__.cc|$(JAVA_CPPFLAGS)||$(JAVA_LIBS) __magick_read__.cc|$(MAGICK_CPPFLAGS)|$(MAGICK_LDFLAGS)|$(MAGICK_LIBS) __voronoi__.cc|$(QHULL_CPPFLAGS)|$(QHULL_LDFLAGS)|$(QHULL_LIBS) amd.cc|$(SPARSE_XCPPFLAGS)|$(SPARSE_XLDFLAGS)|$(SPARSE_XLIBS) diff --git a/libinterp/link-deps.mk b/libinterp/link-deps.mk --- a/libinterp/link-deps.mk +++ b/libinterp/link-deps.mk @@ -17,6 +17,7 @@ $(X11_LIBS) \ $(CARBON_LIBS) \ $(LLVM_LIBS) \ + $(JAVA_LIBS) \ $(LAPACK_LIBS) LIBOCTINTERP_LINK_OPTS = \ diff --git a/scripts/Makefile.am b/scripts/Makefile.am --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -36,6 +36,8 @@ IMAGES = +JAR_FILES = + ## Read subdirs to set all variables above include @ftp/module.mk include audio/module.mk @@ -46,6 +48,7 @@ include help/module.mk include image/module.mk include io/module.mk +include java/module.mk include linear-algebra/module.mk include miscellaneous/module.mk include optimization/module.mk @@ -68,16 +71,16 @@ include testfun/module.mk include time/module.mk -nobase_fcnfile_DATA = $(FCN_FILES) $(GEN_FCN_FILES) +nobase_fcnfile_DATA = $(FCN_FILES) $(GEN_FCN_FILES) $(JAR_FILES) image_DATA = $(IMAGES) FCN_FILES_IN = $(GEN_FCN_FILES:.m=.in) if AMCOND_BUILD_DOCS -all-local: $(GEN_FCN_FILES) $(PKG_ADD_FILES) .DOCSTRINGS +all-local: $(GEN_FCN_FILES) $(PKG_ADD_FILES) $(JAR_FILES) .DOCSTRINGS else -all-local: $(GEN_FCN_FILES) $(PKG_ADD_FILES) +all-local: $(GEN_FCN_FILES) $(PKG_ADD_FILES) $(JAR_FILES) endif octave_dirstamp = $(am__leading_dot)dirstamp @@ -118,6 +121,10 @@ $(srcdir)/mk-pkg-add $(srcdir) $(io_FCN_FILES) -- $(io_GEN_FCN_FILES) > $@-t mv $@-t $@ +java/PKG_ADD: $(java_FCN_FILES) $(java_GEN_FCN_FILES) java/$(octave_dirstamp) mk-pkg-add + $(srcdir)/mk-pkg-add $(srcdir) $(java_FCN_FILES) -- $(java_GEN_FCN_FILES) > $@-t + mv $@-t $@ + linear-algebra/PKG_ADD: $(linear_algebra_FCN_FILES) $(linear_algebra_GEN_FCN_FILES) linear-algebra/$(octave_dirstamp) mk-pkg-add $(srcdir)/mk-pkg-add $(srcdir) $(linear_algebra_FCN_FILES) -- $(linear_algebra_GEN_FCN_FILES) > $@-t mv $@-t $@ @@ -211,6 +218,7 @@ $(help_GEN_FCN_FILES): help/$(octave_dirstamp) $(image_GEN_FCN_FILES): image/$(octave_dirstamp) $(io_GEN_FCN_FILES): io/$(octave_dirstamp) +$(java_GEN_FCN_FILES): java/$(octave_dirstamp) $(linear_algebra_GEN_FCN_FILES): linear-algebra/$(octave_dirstamp) $(miscellaneous_GEN_FCN_FILES): miscellaneous/$(octave_dirstamp) $(optimization_GEN_FCN_FILES): optimization/$(octave_dirstamp) @@ -260,6 +268,9 @@ io/$(octave_dirstamp): $(MKDIR_P) io : > io/$(octave_dirstamp) +java/$(octave_dirstamp): + $(MKDIR_P) java + : > java/$(octave_dirstamp) linear-algebra/$(octave_dirstamp): $(MKDIR_P) linear-algebra : > linear-algebra/$(octave_dirstamp) diff --git a/scripts/java/dlgtest.m b/scripts/java/dlgtest.m new file mode 100644 --- /dev/null +++ b/scripts/java/dlgtest.m @@ -0,0 +1,255 @@ +% +% Install the java package. +% Test the dlg... functions of the java package. +% +% Author: Martin Hepperle +% Version August 2010 +% +function dlgtest ( reinstall ) + + % Windows example paths + if ispc() + % NOTE: do NOT use backslashes as separator, only forward slashes! + pkgpath = 'z:/java-1.2.8.tar.gz'; + java_home = getenv ("JAVA_HOME"); + elseif isunix() + % Linux example paths + pkgpath = '~/java-1.2.8.tar.gz'; + java_home = getenv ("JAVA_HOME"); + else + pkgpath = 'unknown'; + java_home = 'unknown'; + end + + if nargin<1 + disp('usage: dlgtest ( reinstall )'); + disp( 'where: reinstall = 0 : do not reinstall java package'); + disp([' reinstall = 1 : reinstall java package from ', pkgpath, ... + ', using Java JDK from ', java_home]); + return + end + + if ! exist (java_home, "dir") + disp(['Java JDK home directory ', java_home,' does not exist.']); + disp('Please adapt java_home in dlgtest.m.'); + return; + end + + if reinstall == 1 + if ! exist (pkgpath, "file") + disp(['Package file ', pkgpath, ' does not exist.']); + disp('Please adapt pkgpath in dlgtest.m.'); + return; + end + end + + page_screen_output(0); + + if reinstall == 1 + disp('- uninstalling package java'); + pkg uninstall java + + disp(['- installing package java from ',pkgpath]); + disp([' using JDK from ',java_home]); + setenv('JAVA_HOME',java_home) + %% pkg does not understand variables as arguments? + eval(['pkg install ', pkgpath]) + disp('Done.'); + end + + page_screen_output(1); + + answer = 1; + while (answer > 0 ) + + disp(''); + disp('0 ... STOP'); + disp('1 ... listdlg tests'); + disp('2 ... errordlg tests'); + disp('3 ... warndlg tests'); + disp('4 ... helpdlg tests'); + disp('5 ... inputdlg tests'); + disp('6 ... TeX code tests'); + + answer = str2num(input ('Run which test? [0] > ','s')); + + disp(''); + + switch answer + case 1 + test_listdlg(); + case 2 + test_errordlg(); + case 3 + test_warndlg(); + case 4 + test_helpdlg(); + case 5 + test_inputdlg(); + case 6 + test_TeXCodes(); + end + end + + % d = javaObject('javax.swing.JDialog'); + % cp = d.getContentPane; + % b = javaObject('javax.swing.JButton','OK'); + % cp.add(b); + % d.pack; + % d.setVisible(true); + + + page_screen_output(1); + +end + +function test_listdlg + + %----------------------------------------------- + disp('- test listdlg with selectionmode single. No caption, no prompt.'); + itemlist = {'An item \\alpha', 'another', 'yet another'}; + s = listdlg ( 'ListString',itemlist, 'SelectionMode','Single' ); + imax = length(s); + for i=1:1:imax + disp(['Selected: ',num2str(i),': ', itemlist{s(i)}]); + end + + %----------------------------------------------- + disp('- test listdlg with selectionmode and preselection. Has caption and two lines prompt.'); + s = listdlg ( 'ListString',itemlist, ... + 'SelectionMode','Multiple', ... + 'Name','Selection Dialog', ... + 'InitialValue',[1,2,3,4], + 'PromptString',{'Select an item...', '...or multiple items'} ); + imax = length(s); + for i=1:1:imax + disp(['Selected: ',num2str(i),': ', itemlist{s(i)}]); + end + +end + +function test_errordlg + %----------------------------------------------- + disp('- test errordlg with prompt only.'); + errordlg('Oops, an expected error occured'); + %----------------------------------------------- + disp('- test errordlg with prompt and caption.'); + errordlg('Oops another error','This is a very long and informative caption'); +end + +function test_warndlg + %----------------------------------------------- + disp('- test warndlg with prompt only.'); + warndlg('Oh, a warning occured'); + %----------------------------------------------- + disp('- test warndlg with prompt and caption.'); + warndlg('Oh, No...','This is the last Warning'); +end + +function test_helpdlg + %----------------------------------------------- + disp('- test helpdlg with a help message only.'); + helpdlg("Below, you should see 3 lines:\nline #1\nline #2, and\nline #3."); + %----------------------------------------------- + disp('- test helpdlg with help message and caption.'); + helpdlg('You should see a single line.','A help dialog'); +end + +function test_inputdlg + %----------------------------------------------- + disp('- test inputdlg with prompt and caption only.'); + prompt = {'Width','Height','Depth'}; + dims = inputdlg ( prompt, 'Enter Box Dimensions' ); + if isempty(dims) + helpdlg('Canceled by user', 'Information'); + else + volume = str2num(dims{1}) * str2num(dims{2}) * str2num(dims{3}); + surface = 2 * (str2num(dims{1}) * str2num(dims{2}) + ... + str2num(dims{2}) * str2num(dims{3}) + ... + str2num(dims{1}) * str2num(dims{3})); + helpdlg(sprintf('Results:\nVolume = %.3f\nSurface = %.3f', volume, surface), 'Box Dimensions'); + end + + %----------------------------------------------- + disp('- test inputdlg with prescribed scalar (2 lines per text field) and defaults.'); + prompt = {'Width','Height','Depth'}; + default = {'1.1','2.2','3.3'}; + rc = 2; + dims = inputdlg ( prompt, 'Enter Box Dimensions',rc,default ); + if isempty(dims) + helpdlg('Canceled by user', 'Information'); + else + volume = str2num(dims{1}) * str2num(dims{2}) * str2num(dims{3}); + surface = 2 * (str2num(dims{1}) * str2num(dims{2}) + ... + str2num(dims{2}) * str2num(dims{3}) + ... + str2num(dims{1}) * str2num(dims{3})); + helpdlg(sprintf('Results:\nVolume = %.3f\nSurface = %.3f', volume, surface), 'Box Dimensions'); + end + %----------------------------------------------- + disp('- test inputdlg with prescribed vector [1,2,3] for # of lines per text field and defaults.'); + prompt = {'Width','Height','Depth'}; + default = {'1.10', '2.10', '3.10'}; + rc = [1,2,3]; % NOTE: must be an array + dims = inputdlg ( prompt, 'Enter Box Dimensions',rc,default ); + if isempty(dims) + helpdlg('Canceled by user', 'Information'); + else + volume = str2num(dims{1}) * str2num(dims{2}) * str2num(dims{3}); + surface = 2 * (str2num(dims{1}) * str2num(dims{2}) + ... + str2num(dims{2}) * str2num(dims{3}) + ... + str2num(dims{1}) * str2num(dims{3})); + helpdlg(sprintf('Results:\nVolume = %.3f\nSurface = %.3f', volume, surface), 'Box Dimensions'); + end + %----------------------------------------------- + disp('- test inputdlg with prescribed row by column sizes and defaults.'); + prompt = {'Width','Height','Depth'}; + default = {'1.10', '2.20', '3.30'}; + rc = [1,10; 2,20; 3,30]; % NOTE: must be an array + dims = inputdlg ( prompt, 'Enter Box Dimensions',rc,default ); + if isempty(dims) + helpdlg('Canceled by user', 'Information'); + else + volume = str2num(dims{1}) * str2num(dims{2}) * str2num(dims{3}); + surface = 2 * (str2num(dims{1}) * str2num(dims{2}) + ... + str2num(dims{2}) * str2num(dims{3}) + ... + str2num(dims{1}) * str2num(dims{3})); + helpdlg(sprintf('Results:\nVolume = %.3f\nSurface = %.3f', volume, surface), 'Box Dimensions'); + end +end + +%% show a table of TeX symbol codes and the resulting Unicode character +function test_TeXCodes + %----------------------------------------------- + disp('- test TeX code to Unicode translation.'); + + msgbox ( ['\\alpha = ''\alpha '' \\beta = ''\beta '' \\gamma = ''\gamma ''', 10, ... + '\\delta = ''\delta '' \\epsilon = ''\epsilon '' \\zeta = ''\zeta ''', 10, ... + '\\eta = ''\eta '' \\theta = ''\theta '' \\vartheta = ''\vartheta ''', 10, ... + '\\iota = ''\iota '' \\kappa = ''\kappa '' \\lambda = ''\lambda ''', 10, ... + '\\mu = ''\mu '' \\nu = ''\nu '' \\xi = ''\xi ''', 10, ... + '\\pi = ''\pi '' \\rho = ''\rho '' \\sigma = ''\sigma ''', 10, ... + '\\varsigma = ''\varsigma '' \\tau = ''\tau '' \\phi = ''\phi ''', 10, ... + '\\chi = ''\chi '' \\psi = ''\psi '' \\omega = ''\omega ''', 10, ... + '\\upsilon = ''\upsilon '' \\Gamma = ''\Gamma '' \\Delta = ''\Delta ''', 10, ... + '\\Theta = ''\Theta '' \\Lambda = ''\Lambda '' \\Pi = ''\Pi ''', 10, ... + '\\Xi = ''\Xi '' \\Sigma = ''\Sigma '' \\Upsilon = ''\Upsilon ''', 10, ... + '\\Phi = ''\Phi '' \\Psi = ''\Psi '' \\Omega = ''\Omega ''', 10, ... + '\\Im = ''\Im '' \\Re = ''\Re '' \\leq = ''\leq ''', 10, ... + '\\geq = ''\geq '' \\neq = ''\neq '' \\pm = ''\pm ''', 10, ... + '\\infty = ''\infty '' \\partial = ''\partial '' \\approx = ''\approx ''', 10, ... + '\\circ = ''\circ '' \\bullet = ''\bullet '' \\times = ''\times ''', 10, ... + '\\sim = ''\sim '' \\nabla = ''\nabla '' \\ldots = ''\ldots ''', 10, ... + '\\exists = ''\exists '' \\neg = ''\neg '' \\aleph = ''\aleph ''', 10, ... + '\\forall = ''\forall '' \\cong = ''\cong '' \\wp = ''\wp ''', 10, ... + '\\propto = ''\propto '' \\otimes = ''\otimes '' \\oplus = ''\oplus ''', 10, ... + '\\oslash = ''\oslash '' \\cap = ''\cap '' \\cup = ''\cup ''', 10, ... + '\\ni = ''\ni '' \\in = ''\in '' \\div = ''\div ''', 10, ... + '\\equiv = ''\equiv '' \\int = ''\int '' \\perp = ''\perp ''', 10, ... + '\\wedge = ''\wedge '' \\vee = ''\vee '' \\supseteq = ''\supseteq ''', 10, ... + '\\supset = ''\supset '' \\subseteq = ''\subseteq '' \\subset = ''\subset ''', 10, ... + '\\clubsuit = ''\clubsuit '' \\spadesuit = ''\spadesuit '' \\heartsuit = ''\heartsuit ''', 10, ... + '\\diamondsuit = ''\diamondsuit '' \\copyright = ''\copyright '' \\leftarrow = ''\leftarrow ''', 10, ... + '\\uparrow = ''\uparrow '' \\rightarrow = ''\rightarrow '' \\downarrow = ''\downarrow ''', 10, ... + '\\leftrightarrow = ''\leftrightarrow '' \\updownarrow = ''\updownarrow '''], ... + 'TeX symbol code table Test'); +end diff --git a/scripts/java/errordlg.m b/scripts/java/errordlg.m new file mode 100644 --- /dev/null +++ b/scripts/java/errordlg.m @@ -0,0 +1,37 @@ +## Copyright (C) 2010 Martin Hepperle +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; If not, see . + +## -*- texinfo -*- +## @deftypefn {Function file} {@var{P} =} errordlg (@var{MESSAGE} [,@var{TITLE}]) +## +## Displays the @var{MESSAGE} using an error dialog box. +## The @var{TITLE} can be used optionally to decorate the dialog caption. +## The return value is always 1. +## +## @end deftypefn +## @seealso{helpdlg, inputdlg, listdlg, questdlg, warndlg} + +function ret = errordlg(message,varargin) + + switch length (varargin) + case 0 + title = "Error Dialog"; + otherwise + title = varargin{1}; + endswitch + + ret = java_invoke ("org.octave.JDialogBox", "errordlg", message, title); + +endfunction diff --git a/scripts/java/helpdlg.m b/scripts/java/helpdlg.m new file mode 100644 --- /dev/null +++ b/scripts/java/helpdlg.m @@ -0,0 +1,38 @@ +## Copyright (C) 2010 Martin Hepperle +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; If not, see . + +## -*- texinfo -*- +## @deftypefn {Function file} {@var{P} =} helpdlg (@var{MESSAGE} [,@var{TITLE}]) +## +## Displays a @var{MESSAGE} in a help dialog box. +## The help message can have multiple lines, separated by a newline character '\n'. +## The @var{TITLE} can be used optionally to decorate the dialog caption. +## The return value is always 1. +## +## @end deftypefn +## @seealso{errordlg, inputdlg, listdlg, questdlg, warndlg} + +function ret = helpdlg(message,varargin) + + switch length (varargin) + case 0 + title = "Help Dialog"; + otherwise + title = varargin{1}; + endswitch + + ret = java_invoke ("org.octave.JDialogBox", "helpdlg", message, title); + +endfunction diff --git a/scripts/java/inputdlg.m b/scripts/java/inputdlg.m new file mode 100644 --- /dev/null +++ b/scripts/java/inputdlg.m @@ -0,0 +1,106 @@ +## Copyright (C) 2010 Martin Hepperle +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; If not, see . + +## -*- texinfo -*- +## @deftypefn {Function file} {@var{P} =} inputdlg (@var{PROMPT} [,@var{TITLE} [,@var{ROWSCOLS}, @var{DEFAULTS}]]) +## +## Returns the user's inputs from a multi-textfield dialog box in form of a cell array of strings. +## If the dialog is closed by the Cancel button, an empty cell array is returned. +## +## @table @samp +## @item PROMPT +## The first argument @var{PROMPT} is mandatory. +## It is a cell array with strings labeling each textfield. +## @item TITLE +## The optional string @var{TITLE} can be used as the caption of the dialog. +## @item ROWSCOLS +## The size of the text fields can be defined by the argument @var{ROWSCOLS}, +## which can have three forms: +## - a scalar value which defines the number of rows used for each text field. +## - a vector which defines the individual number of rows used for each text field. +## - a matrix which defines the individual number of rows and columns used for each text field. +## @item DEFAULTS +## It is possible to place default values into the text fields by supplying +## the a cell array of strings or number for the argument @var{DEFAULTS}. +## @end table +## +## @end deftypefn +## @seealso{errordlg, helpdlg, listdlg, questdlg, warndlg} + +function varargout = inputdlg(prompt,varargin) + + switch length (varargin) + case 0 + title = "Input Dialog"; + lineNo = 1; + defaults = cellstr(cell(size(prompt))); + case 1 + title = varargin{1}; + lineNo = 1; + defaults = cellstr(cell(size(prompt))); + case 2 + title = varargin{1}; + lineNo = varargin{2}; + defaults = cellstr(cell(size(prompt))); + otherwise + title = varargin{1}; + lineNo = varargin{2}; + defaults = varargin{3}; + end + + + % specification of text field sizes as in Matlab + % Matlab requires a matrix for lineNo, not a cell array... + % rc = [1,10; 2,20; 3,30]; + % c1 c2 + % r1 1 10 first text field is 1x10 + % r2 2 20 second text field is 2x20 + % r3 3 30 third text field is 3x30 + if isscalar(lineNo) + % only scalar value in lineTo, copy from lineNo and add defaults + rowscols = zeros(size(prompt)(2),2); + % cols + rowscols(:,2) = 25; + rowscols(:,1) = lineNo; + elseif isvector(lineNo) + % only one column in lineTo, copy from vector lineNo and add defaults + rowscols = zeros(size(prompt)(2),2); + % rows from colum vector lineNo, columns are set to default + rowscols(:,2) = 25; + rowscols(:,1) = lineNo(:); + elseif ismatrix(lineNo) + if (size(lineNo)(1) == size(prompt)(2)) && (size(lineNo)(2) == 2) + % (rows x columns) match, copy array lineNo + rowscols = lineNo; + end + else + % dunno + disp('inputdlg: unknown form of lineNo argument.'); + lineNo + end + + % convert numeric values in defaults cell array to strings + defs = cellfun(@num2str,defaults,'UniformOutput',false); + rc = arrayfun(@num2str,rowscols,'UniformOutput',false); + + user_inputs = java_invoke ("org.octave.JDialogBox", "inputdlg", prompt, title, rc, defs); + + if isempty(user_inputs) + varargout{1} = {}; % empty + else + varargout{1} = cellstr (user_inputs); + end + +end diff --git a/scripts/java/java.m b/scripts/java/java.m new file mode 100755 --- /dev/null +++ b/scripts/java/java.m @@ -0,0 +1,19 @@ +## Copyright (C) 2010 Martin Hepperle +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; If not, see . + +## -*- texinfo -*- +## Please enter @code{doc java} to view the documentation for +## the package @code{java}. +## diff --git a/scripts/java/javaArray.m b/scripts/java/javaArray.m new file mode 100644 --- /dev/null +++ b/scripts/java/javaArray.m @@ -0,0 +1,48 @@ +## Copyright (C) 2007 Michael Goffioul +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; If not, see . + +## -*- texinfo -*- +## @deftypefn {Function file} {@var{a} =} javaArray (@var{class},@var{[M,N,...]}) +## @deftypefnx {Function file} {@var{a} =} javaArray (@var{class},@var{M},@var{N},...) +## +## Creates a Java array of size [@var{M},@var{N},...] with elements of +## class @var{class}. @var{class} can be a Java object representing a class +## or a string containing the fully qualified class name. +## +## The generated array is uninitialized, all elements are set to null +## if @var{class} is a reference type, or to a default value (usually 0) +## if @var{class} is a primitive type. +## +## @example +## a = javaArray ("java.lang.String", 2, 2); +## a(1,1) = "Hello"; +## @end example +## +## @end deftypefn + +function [ ret ] = javaArray (class_name, varargin) + + switch length (varargin) + case 0 + error ("missing array size"); + case 1 + dims = varargin{1}; + otherwise + dims = [varargin{:}]; + endswitch + + ret = java_invoke ("org.octave.ClassHelper", "createArray", class_name, dims); + +endfunction diff --git a/scripts/java/javaaddpath.m b/scripts/java/javaaddpath.m new file mode 100644 --- /dev/null +++ b/scripts/java/javaaddpath.m @@ -0,0 +1,44 @@ +## Copyright (C) 2007 Michael Goffioul +## Copyright (C) 2010 Martin Hepperle +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; If not, see . + +## -*- texinfo -*- +## @deftypefn {Function file} {} javaaddpath (@var{path}) +## +## Adds @var{path} to the dynamic class path of the Java virtual +## machine. @var{path} can be either a directory where .class files +## can be found, or a .jar file containing Java classes. +## +## @end deftypefn +## @seealso{javaclasspath} + +function javaaddpath (class_path) + + if (nargin != 1) + print_usage (); + else + % MH 30-08-2010: added tilde_expand to allow for specification of user's home + new_path = canonicalize_file_name (tilde_expand (class_path)); + if (exist (new_path, "dir")) + if (! strcmp (new_path (end), filesep)) + new_path = [new_path, filesep]; + endif + elseif (! exist (new_path, "file")) + error ("invalid Java classpath: %s", class_path); + endif + success = java_invoke ("org.octave.ClassHelper", "addClassPath", new_path); + endif + +endfunction diff --git a/scripts/java/javaclasspath.m b/scripts/java/javaclasspath.m new file mode 100644 --- /dev/null +++ b/scripts/java/javaclasspath.m @@ -0,0 +1,106 @@ +## Copyright (C) 2007 Michael Goffioul, 2010 Martin Hepperle +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; If not, see . + +## -*- texinfo -*- +## @deftypefn {Function file} {} javaclasspath +## @deftypefnx {Function file} {@var{STATIC} =} javaclasspath +## @deftypefnx {Function file} {[@var{STATIC}, @var{DYNAMIC}] =} javaclasspath +## @deftypefnx {Function file} {@var{PATH} =} javaclasspath (@var{WHAT}) +## +## Returns the class path of the Java virtual machine in +## the form of a cell array of strings. +## +## If called without input parameter:@* +## @itemize +## @item If no output variable is given, the result is simply printed +## on the standard output. +## @item If one output variable @var{STATIC} is given, the result is +## the static classpath. +## @item If two output variables @var{STATIC} and @var{DYNAMIC} are +## given, the first variable will contain the static classpath, +## the second will be filled with the dynamic claspath. +## @end itemize +## +## If called with a single input parameter @var{WHAT}:@* +## @itemize +## @item If @var{WHAT} is '-static' the static classpath is returned. +## @item If @var{WHAT} is '-dynamic' the dynamic classpath is returned. +## @item If @var{WHAT} is '-all' the static and the dynamic classpath +## are returned in a single cell array +## @end itemize +## @end deftypefn +## @seealso{javaaddpath,javarmpath} + +function varargout = javaclasspath (which) + + % dynamic classpath + dynamic_path = java_invoke ("org.octave.ClassHelper", "getClassPath"); + dynamic_path_list = strsplit (dynamic_path, pathsep ()); + + % static classpath + static_path = java_invoke ('java.lang.System', 'getProperty', 'java.class.path'); + static_path_list = strsplit (static_path, pathsep ()); + if (length (static_path_list) > 1) + % remove first element (which is .../octave.jar) + static_path_list = static_path_list(2:length (static_path_list)); + else + static_path_list = {}; + end + + switch nargin + case 0 + switch nargout + case 0 + disp_path_list ( 'STATIC', static_path_list ) + disp(''); + disp_path_list ( 'DYNAMIC', dynamic_path_list ) + case 1 + varargout{1} = cellstr (dynamic_path_list); + case 2 + varargout{1} = cellstr (dynamic_path_list); + varargout{2} = cellstr (static_path_list); + endswitch + + case 1 + switch nargout + case 0 + if (strcmp (which, '-static') == 1) + disp_path_list ( 'STATIC', static_path_list ) + elseif (strcmp (which, '-dynamic') == 1) + disp_path_list ( 'DYNAMIC', dynamic_path_list ) + end + case 1 + if (strcmp (which, '-static') == 1) + varargout{1} = cellstr (static_path_list); + elseif (strcmp (which, '-dynamic') == 1) + varargout{1} = cellstr (dynamic_path_list); + elseif (strcmp (which, '-all') == 1) + varargout{1} = cellstr ([static_path_list, dynamic_path_list]); + end + endswitch + endswitch + +end +# +# Display cell array of paths +# +function disp_path_list ( which, path_list ) + printf (' %s JAVA PATH\n\n', which); + if (length (path_list) > 0) + printf (' %s\n', path_list{:}); + else + printf (' - empty -\n'); + endif +end diff --git a/scripts/java/javafields.m b/scripts/java/javafields.m new file mode 100755 --- /dev/null +++ b/scripts/java/javafields.m @@ -0,0 +1,44 @@ +## Copyright (C) 2007 Michael Goffioul +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; If not, see . + +## -*- texinfo -*- +## @deftypefn {Function file} {@var{P} =} javafields (@var{class}) +## +## Returns the fields of a Java object in the form of a cell +## array of strings. If no output variable is +## given, the result is simply printed on the standard output. +## +## @end deftypefn +## @seealso{javamethods} + +function varargout = javafields(classname) + + if (nargin != 1) + print_usage (); + else + c_methods = java_invoke ("org.octave.ClassHelper", "getFields",classname); + method_list = strsplit (c_methods, ';'); + + switch nargout + case 0 + if (! isempty (method_list)) + disp(method_list); + endif + case 1 + varargout{1} = cellstr (method_list); + endswitch + endif + +endfunction diff --git a/scripts/java/javamem.m b/scripts/java/javamem.m new file mode 100644 --- /dev/null +++ b/scripts/java/javamem.m @@ -0,0 +1,84 @@ +## Copyright (C) 2010 Philip Nienhuis, +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} javamem +## @deftypefnx {Function File} [@var{jmem}] = javamem +## Show current memory status of the Java virtual machine (JVM) +## & run garbage collector. +## +## When no return argument is given the info is echoed to the screen. +## Otherwise, output cell array @var{jmem} contains Maximum, Total, +## and Free memory (in bytes). +## +## All Java-based routines are run in the JVM's shared memory pool, +## a dedicated and separate part of memory claimed by the JVM from +## your computer's total memory (which comprises physical RAM and +## virtual memory / swap space on hard disk). +## +## The maximum available memory can be set using the file java.opts +## (in the same subdirectory where javaaddpath.m lives, see +## "which javaaddpath". Usually that is: @* +## [/usr]/share/octave/packages/java-. +## +## java.opts is a plain text file, one option per line. The +## default initial memory size and default maximum memory size (which +## are both system dependent) can be overridden like so: @* +## -Xms64m @* +## -Xmx512m @* +## (in megabytes in this example.) +## You can adapt these values to your own requirements if your system +## has limited available physical memory or when you get Java memory +## errors. +## +## "Total memory" is what the operating system has currently assigned +## to the JVM and depends on actual and active memory usage. +## "Free memory" is self-explanatory. During operation of Java-based +## octave functions the amounts of Total and Free memory will vary, +## due to Java's own cleaning up and your operating system's memory +## management. +## +## @end deftypefn + +## Author: Philip Nienhuis +## Created: 2010-03-25 +## Updates: +## 2010-03-26 Changed name to javamem & indentation to double spaces +## 2010-08-25 Corrected text on java memory assignments +## 2010-09-05 Further overhauled help text + +function [ j_mem ] = javamem () + + rt = java_invoke ('java.lang.Runtime', 'getRuntime'); + rt.gc; + jmem = cell (3, 1); + jmem{1} = rt.maxMemory ().doubleValue (); + jmem{2} = rt.totalMemory ().doubleValue (); + jmem{3} = rt.freeMemory ().doubleValue (); + + if (nargout < 1) + printf ("\nJava virtual machine (JVM) memory info:\n"); + printf ("Maximum available memory: %5d MiB;\n", jmem{1} / 1024 / 1024); + printf (" (...running garbage collector...)\n"); + printf ("OK, current status:\n"); + printf ("Total memory in virtual machine: %5d MiB;\n", jmem{2} / 1024 / 1024); + printf ("Free memory in virtual machine: %5d MiB;\n", jmem{3} / 1024 / 1024); + printf ("%d CPUs available.\n", rt.availableProcessors ()); + else + j_mem = jmem; + endif + +endfunction diff --git a/scripts/java/javamethods.m b/scripts/java/javamethods.m new file mode 100755 --- /dev/null +++ b/scripts/java/javamethods.m @@ -0,0 +1,44 @@ +## Copyright (C) 2007 Michael Goffioul +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; If not, see . + +## -*- texinfo -*- +## @deftypefn {Function file} {@var{P} =} javamethods (@var{class}) +## +## Returns the methods of a Java object in the form of a cell +## array of strings. If no output variable is +## given, the result is simply printed on the standard output. +## +## @end deftypefn +## @seealso{methods} + +function varargout = javamethods (classname) + + if (nargin != 1) + print_usage (); + else + c_methods = java_invoke ("org.octave.ClassHelper", "getMethods", classname); + method_list = strsplit (c_methods, ';'); + + switch nargout + case 0 + if (! isempty (method_list)) + disp(method_list); + endif + case 1 + varargout{1} = cellstr (method_list); + endswitch + endif + +endfunction diff --git a/scripts/java/javarmpath.m b/scripts/java/javarmpath.m new file mode 100755 --- /dev/null +++ b/scripts/java/javarmpath.m @@ -0,0 +1,45 @@ +## Copyright (C) 2007 Michael Goffioul +## Copyright (C) 2010 Martin Hepperle +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; If not, see . + +## -*- texinfo -*- +## @deftypefn {Function file} {} javarmpath (@var{path}) +## +## Removes @var{path} from the dynamic class path of the Java virtual +## machine. @var{path} can be either a directory where .class files +## can be found, or a .jar file containing Java classes. +## +## @end deftypefn +## @seealso{javaaddpath,javaclasspath} + +function javarmpath (class_path) + + if (nargin != 1) + print_usage (); + else + % MH 30-08-2010: added tilde_expand to allow for specification of user's home + old_path = canonicalize_file_name (tilde_expand(class_path)); + if (exist (old_path, "dir")) + if (! strcmp (old_path (end), filesep)) + old_path = [old_path, filesep]; + end + end + success = java_invoke ('org.octave.ClassHelper', 'removeClassPath', old_path); + if (! success) + disp (['Warning: ', old_path, ' not found in Java classpath.', 10]); + end + end + +end diff --git a/scripts/java/listdlg.m b/scripts/java/listdlg.m new file mode 100644 --- /dev/null +++ b/scripts/java/listdlg.m @@ -0,0 +1,126 @@ +## Copyright (C) 2010 Martin Hepperle +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; If not, see . + +## -*- texinfo -*- +## @deftypefn {Function file} {@var{[SEL,OK]} =} listdlg (@var{KEY} ,@var{VALUE} [, @var{KEY} ,@var{VALUE}, ...]]) +## +## Returns the user's inputs from a list dialog box in form of a vector of +## selection indices SEL and a flag OK indicating how the user closed the dialog box. +## The returned flag OK is 1 if the user closed the box with the OK button, +## otherwise it is 0 and SEL is empty. +## The indices in SEL are 1 based, i.e. the first list item carries the index 1. +## +## The arguments are specified in form of @var{KEY}, @var{VALUE} pairs. +## At least the 'ListString' argument pair must be specified. +## +## @var{KEY}s and @var{VALUE}s pairs can be selected from the following list: +## +## @table @samp +## @item ListString +## a cell array of strings comprising the content of the list. +## @item SelectionMode +## can be either @samp{Single} or @samp{Multiple}. +## @item ListSize +## a vector with two elements [width, height] defining the size of the list field in pixels. +## @item InitialValue +## a vector containing 1-based indices of preselected elements. +## @item Name +## a string to be used as the dialog caption. +## @item PromptString +## a cell array of strings to be displayed above the list field. +## @item OKString +## a string used to label the OK button. +## @item CancelString +## a string used to label the Cancel button. +## @end table +## +## Example: +## +## @example +## [sel, ok] = listdlg ( 'ListString',@{'An item', 'another', 'yet another'@}, 'SelectionMode','Multiple' ); +## if ok == 1 +## imax = length(sel); +## for i=1:1:imax +## disp(sel(i)); +## end +## end +## @end example +## +## @end deftypefn +## @seealso{errordlg, helpdlg, inputdlg, questdlg, warndlg} + +function varargout = listdlg(varargin) + + if nargin < 2 + print_usage (); + return; + end + + listcell = {''}; + selmode = 'single'; + listsize = [300,160]; % vector! + initialvalue = [1]; % vector! + name = ''; + prompt = {''}; + okstring = 'OK'; + cancelstring = 'Cancel'; + + % handle key, value pairs + for i=1:2:nargin-1 + if strcmp(varargin{i},'ListString') + listcell = varargin{i+1}; + elseif strcmp(varargin{i},'SelectionMode') + selmode = varargin{i+1}; + elseif strcmp(varargin{i},'ListSize') + listsize = varargin{i+1}; + elseif strcmp(varargin{i},'InitialValue') + initialvalue = varargin{i+1}; + elseif strcmp(varargin{i},'Name') + name = varargin{i+1}; + elseif strcmp(varargin{i},'PromptString') + prompt = varargin{i+1}; + elseif strcmp(varargin{i},'OKString') + okstring = varargin{i+1}; + elseif strcmp(varargin{i},'CancelString') + cancelstring = varargin{i+1}; + end + end + + % make sure prompt strings are a cell array + if ! iscell(prompt) + prompt = {prompt}; + end + + % make sure listcell strings are a cell array + if ! iscell(listcell) + listcell = {listcell}; + end + + + % transform matrices to cell arrays of strings + listsize = arrayfun(@num2str,listsize,'UniformOutput',false); + initialvalue = arrayfun(@num2str,initialvalue,'UniformOutput',false); + + ret = java_invoke ('org.octave.JDialogBox', 'listdlg', listcell, ... + selmode, listsize, initialvalue, name, prompt, ... + okstring, cancelstring ); + if length(ret) > 0 + varargout = {ret, 1}; + else + varargout = {{}, 0}; + end + + +end diff --git a/scripts/java/module.mk b/scripts/java/module.mk new file mode 100644 --- /dev/null +++ b/scripts/java/module.mk @@ -0,0 +1,78 @@ +FCN_FILE_DIRS += java + +EXTRA_DIST += java/octave.jar + +java_FCN_FILES = \ + java/dlgtest.m \ + java/errordlg.m \ + java/helpdlg.m \ + java/inputdlg.m \ + java/java.m \ + java/javaArray.m \ + java/javaaddpath.m \ + java/javaclasspath.m \ + java/javafields.m \ + java/javamem.m \ + java/javamethods.m \ + java/javarmpath.m \ + java/listdlg.m \ + java/msgbox.m \ + java/questdlg.m \ + java/warndlg.m + +FCN_FILES += $(java_FCN_FILES) + +PKG_ADD_FILES += java/PKG_ADD + +DIRSTAMP_FILES += java/$(octave_dirstamp) + +JAR_FILES += java/octave.jar + +org_octave_dir = org/octave + +JAVA_SRC = \ + $(org_octave_dir)/ClassHelper.java \ + $(org_octave_dir)/OctClassLoader.java \ + $(org_octave_dir)/Octave.java \ + $(org_octave_dir)/OctaveReference.java \ + $(org_octave_dir)/Matrix.java \ + $(org_octave_dir)/JDialogBox.java \ + $(org_octave_dir)/DlgListener.java \ + $(org_octave_dir)/TeXtranslator.java \ + $(org_octave_dir)/TeXcode.java + +JAVA_CLASSES = $(JAVA_SRC:.java=.class) + +JAVA_IMAGES = \ + $(org_octave_dir)/images/question.png \ + $(org_octave_dir)/images/error.png \ + $(org_octave_dir)/images/warning.png \ + $(org_octave_dir)/images/information.png \ + $(org_octave_dir)/images/octave.png + +java_JAVA_SRC = $(addprefix java/, $(JAVA_SRC)) + +java_JAVA_CLASSES = $(addprefix java/, $(JAVA_CLASSES)) + +java_JAVA_IMAGES = $(addprefix java/, $(JAVA_IMAGES)) + +java_JAVA_IMAGES_src = $(addprefix $(srcdir)/java/, $(JAVA_IMAGES)) + +java_JAVA_CLASSES_src = $(addprefix $(srcdir)/java/, $(java_JAVA_CLASSES)) + +%.class : %.java + $(MKDIR_P) java/$(org_octave_dir) + ( cd $(srcdir)/java; $(JAVAC) -source 1.3 -target 1.3 -d $(abs_builddir)/java $(org_octave_dir)/$(. + +## -*- texinfo -*- +## @deftypefn {Function file} {@var{P} =} msgbox (@var{MESSAGE} [,@var{TITLE} [,@var{ICON}]]) +## +## Displays the @var{MESSAGE} using a message dialog. +## The @var{TITLE} is an optional string, which can be used to decorate the dialog caption. +## The @var{ICON} can be used optionally to select a dialog icon. +## It can be one of @code{'error'}, @code{'help'} or @code{'warn'}. +## The return value is always 1. +## +## @end deftypefn +## @seealso{helpdlg, questdlg, warndlg} + +function ret = msgbox(message,varargin) + + switch length (varargin) + case 0 + title = ""; + dlg = 'emptydlg'; + case 1 + title = varargin{1}; + dlg = 'emptydlg'; + otherwise + % two or more arguments + title = varargin{1}; + icon = varargin{2}; + if strcmp(icon,'error') == 1 + dlg = 'errordlg'; + elseif strcmp(icon,'help') == 1 + dlg = 'helpdlg'; + elseif strcmp(icon,'warn') == 1 + dlg = 'warndlg'; + else + dlg = 'emptydlg'; + end + endswitch + + ret = java_invoke ('org.octave.JDialogBox', dlg, message, title ); + +endfunction diff --git a/scripts/java/org/octave/ClassHelper.java b/scripts/java/org/octave/ClassHelper.java new file mode 100644 --- /dev/null +++ b/scripts/java/org/octave/ClassHelper.java @@ -0,0 +1,955 @@ +/* Copyright (C) 2007 Michael Goffioul + ** + ** This program is free software; you can redistribute it and/or modify + ** it under the terms of the GNU General Public License as published by + ** the Free Software Foundation; either version 2 of the License, or + ** (at your option) any later version. + ** + ** This program is distributed in the hope that it will be useful, + ** but WITHOUT ANY WARRANTY; without even the implied warranty of + ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ** GNU General Public License for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with this program; If not, see . + */ + +package org.octave; + +import java.lang.reflect.*; + +public class ClassHelper +{ + private static OctClassLoader loader; + + static + { + ClassLoader l = ClassHelper.class.getClassLoader (); + loader = ( l instanceof OctClassLoader ? ( OctClassLoader ) l : + new OctClassLoader ( l ) ); + } + + + /** + * Add the given path to the classpath. + * @param name String - path to addd to the classpath + * @return boolean - true if the given path exists and was added to the classpath. + * @throws Exception + */ + public static boolean addClassPath ( String name ) + throws Exception + { + boolean found = false; + java.io.File f = new java.io.File ( name ); + if ( f.exists () ) + { + loader.addClassPath ( name ); + found = true; + } + return ( found ); + } + + + // new -MH- + /** + * + * @param name String - path to remove from classpath. + * @return boolean - true if the given path existed in the classpath before it was removed. + * @throws Exception + */ + public static boolean removeClassPath ( String name ) + throws Exception + { + boolean found = false; + java.io.File f = new java.io.File ( name ); + java.net.URL urlToRemove = f.toURI ().toURL (); + // save urls in current class path + java.net.URL[] urls = loader.getURLs (); + + // create a completely new class loader because java.net.URLClassLoader has no removeClassPath() method + ClassLoader l = ClassHelper.class.getClassLoader (); + loader = ( l instanceof OctClassLoader ? ( OctClassLoader ) l : + new OctClassLoader ( l ) ); + + // add the previous urls back, except for the one + for ( int i = 0; i < urls.length; i++ ) + { + java.net.URL url = urls[i]; + if ( !url.equals ( urlToRemove ) ) + { + loader.addURL ( url ); + } + else + { + // path to remove + found = true; + } + } + + return ( found ); + } + + + public static String getClassPath () + { + StringBuffer buf = new StringBuffer (); + String pathSep = System.getProperty ( "path.separator" ); + java.net.URL[] urls = loader.getURLs (); + + for ( int i = 0; i < urls.length; i++ ) + { + try + { + java.io.File f = new java.io.File ( urls[i].toURI () ); + if ( buf.length () > 0 ) + { + buf.append ( pathSep ); + } + buf.append ( f.toString () ); + } + catch ( java.net.URISyntaxException ex ) + {} + } + return buf.toString (); + } + + + // new -MH- + // return list of methods for given class name + public static String getMethods ( String classname ) + throws ClassNotFoundException + { + return ( getMethods ( Class.forName ( classname ) ) ); + } + + + // new -MH- + // return list of methods for given class instance + public static String getMethods ( Object obj ) + throws ClassNotFoundException + { + return ( getMethods ( obj.getClass () ) ); + } + + + // new -MH- + // return list of methods for given class + public static String getMethods ( Class klass ) + { + StringBuffer sb = new StringBuffer (); + + Method theMethod[] = klass.getMethods (); + for ( int i = 0; i < theMethod.length; i++ ) + { + if ( i > 0 ) + { + sb.append ( ";" ); + } + sb.append ( theMethod[i].getReturnType ().getCanonicalName () ); + sb.append ( " " ); + sb.append ( theMethod[i].getName () ); + sb.append ( "(" ); + + Class theParameter[] = theMethod[i].getParameterTypes (); + for ( int j = 0; j < theParameter.length; j++ ) + { + if ( j > 0 ) + { + sb.append ( ", " ); + } + sb.append ( theParameter[j].getCanonicalName () ); + } + sb.append ( ")" ); + + Class theExceptions[] = theMethod[i].getExceptionTypes (); + if ( theExceptions.length > 0 ) + { + sb.append ( " throws " ); + for ( int j = 0; j < theExceptions.length; j++ ) + { + if ( j > 0 ) + { + sb.append ( ", " ); + } + sb.append ( theExceptions[j].getCanonicalName () ); + } + } + } + + return ( sb.toString () ); + } + + + // new -MH- + // return list of fields for given class + public static String getFields ( Class klass ) + { + StringBuffer sb = new StringBuffer (); + + Field theField[] = klass.getFields (); + for ( int i = 0; i < theField.length; i++ ) + { + if ( i > 0 ) + { + sb.append ( ";" ); + } + sb.append ( theField[i].toString () ); + } + + return ( sb.toString () ); + } + + + // new -MH- + // return list of fields for given class name + public static String getFields ( String classname ) + throws ClassNotFoundException + { + return ( getFields ( Class.forName ( classname ) ) ); + } + + + // new -MH- + // return list of fields for given class instance + public static String getFields ( Object obj ) + throws ClassNotFoundException + { + return ( getFields ( obj.getClass () ) ); + } + + + public static Method findMethod ( Class cls, String name, Class[] argTypes ) + { + try + { + return cls.getMethod ( name, argTypes ); + } + catch ( Exception e ) + { + Method[] mList = cls.getMethods (); + Method m; + for ( int i = 0; i < mList.length; i++ ) + { + m = mList[i]; + if ( m.getName ().equals ( name ) && + m.getParameterTypes ().length == argTypes.length && + isCallableFrom ( m, argTypes ) ) + { + return m; + } + } + return null; + } + } + + + public static Constructor findConstructor ( Class cls, Class[] argTypes ) + { + try + { + return cls.getConstructor ( argTypes ); + } + catch ( Exception e ) + { + Constructor[] cList = cls.getConstructors (); + //System.out.println("# constructors: " + cList.length); + Constructor c; + for ( int i = 0; i < cList.length; i++ ) + { + //System.out.println("Considering constructor: " + cList[i]); + c = cList[i]; + if ( c.getParameterTypes ().length == argTypes.length && + isCallableFrom ( c, argTypes ) ) + { + return c; + } + } + return null; + } + } + + + private static Object invokeMethod ( Method m, Object target, Object[] args ) + throws Exception + { + try + { + return m.invoke ( target, args ); + } + catch ( IllegalAccessException ex ) + { + String mName = m.getName (); + Class[] pTypes = m.getParameterTypes (); + Class currClass = target.getClass (); + + while ( currClass != null ) + { + try + { + Method meth = currClass.getMethod ( mName, pTypes ); + if ( !meth.equals ( m ) ) + { + return meth.invoke ( target, args ); + } + } + catch ( NoSuchMethodException ex2 ) + {} + catch ( IllegalAccessException ex2 ) + {} + + Class[] ifaceList = currClass.getInterfaces (); + for ( int i = 0; i < ifaceList.length; i++ ) + { + try + { + Method meth = ifaceList[i].getMethod ( mName, pTypes ); + return meth.invoke ( target, args ); + } + catch ( NoSuchMethodException ex2 ) + {} + catch ( IllegalAccessException ex2 ) + {} + } + + currClass = currClass.getSuperclass (); + } + + throw ex; + } + } + + + public static Object invokeMethod ( Object target, String name, + Object[] args, Class[] argTypes ) + throws Throwable + { + Method m = findMethod ( target.getClass (), name, argTypes ); + if ( m != null ) + { + try + { + Object result = invokeMethod ( m, target, + castArguments ( args, argTypes, + m.getParameterTypes () ) ); + return result; + } + catch ( InvocationTargetException ex ) + { + throw ex.getCause (); + } + } + else + { + throw new NoSuchMethodException ( name ); + } + } + + + public static Object invokeStaticMethod ( String cls, String name, + Object[] args, Class[] argTypes ) + throws Throwable + { + Method m = findMethod ( Class.forName ( cls, true, loader ), name, + argTypes ); + if ( m != null ) + { + try + { + Object result = m.invoke ( null, + castArguments ( args, argTypes, + m.getParameterTypes () ) ); + return result; + } + catch ( InvocationTargetException ex ) + { + throw ex.getCause (); + } + } + else + { + throw new NoSuchMethodException ( name ); + } + } + + + public static Object invokeConstructor ( String cls, Object[] args, + Class[] argTypes ) + throws Throwable + { + Constructor c = findConstructor ( Class.forName ( cls, true, loader ), + argTypes ); + if ( c != null ) + { + try + { + Object result = c.newInstance ( castArguments ( args, argTypes, + c.getParameterTypes () ) ); + return result; + } + catch ( InvocationTargetException ex ) + { + throw ex.getCause (); + } + } + else + { + throw new NoSuchMethodException ( cls ); + } + } + + + public static Object getField ( Object target, String name ) + throws Throwable + { + try + { + Field f = target.getClass ().getField ( name ); + return f.get ( target ); + } + catch ( NoSuchFieldException ex ) + { + try + { + return invokeMethod ( target, name, new Object[0], new Class[0] ); + } + catch ( NoSuchMethodException ex2 ) + { + throw ex; + } + } + } + + + public static Object getStaticField ( String cls, String name ) + throws Throwable + { + try + { + Field f = Class.forName ( cls, true, loader ).getField ( name ); + return f.get ( null ); + } + catch ( NoSuchFieldException ex ) + { + try + { + return invokeStaticMethod ( cls, name, new Object[0], new Class[0] ); + } + catch ( NoSuchMethodException ex2 ) + { + throw ex; + } + } + } + + + public static void setField ( Object target, String name, Object value ) + throws Exception + { + Field f = target.getClass ().getField ( name ); + f.set ( target, castArgument ( value, value.getClass (), f.getType () ) ); + } + + + public static void setStaticField ( String cls, String name, Object value ) + throws Exception + { + Field f = Class.forName ( cls, true, loader ).getField ( name ); + f.set ( null, castArgument ( value, value.getClass (), f.getType () ) ); + } + + + private static boolean isCallableFrom ( Method m, Class[] argTypes ) + { + Class[] expTypes = m.getParameterTypes (); + for ( int i = 0; i < argTypes.length; i++ ) + { + if ( !isCallableFrom ( expTypes[i], argTypes[i] ) ) + { + return false; + } + } + return true; + } + + + private static boolean isCallableFrom ( Constructor c, Class[] argTypes ) + { + Class[] expTypes = c.getParameterTypes (); + for ( int i = 0; i < argTypes.length; i++ ) + { + if ( !isCallableFrom ( expTypes[i], argTypes[i] ) ) + { + return false; + } + } + return true; + } + + + private static boolean isCallableFrom ( Class expCls, Class argCls ) + { + //System.out.println("isCallableFrom: "+expCls.getCanonicalName() + " <=? " + argCls.getCanonicalName()); + if ( argCls == null ) + { + return!expCls.isPrimitive (); + } + else if ( expCls.isAssignableFrom ( argCls ) ) + { + return true; + } + else if ( ( isNumberClass ( expCls ) || isBooleanClass ( expCls ) ) && + isNumberClass ( argCls ) ) + { + return true; + } + else if ( isCharClass ( expCls ) && argCls.equals ( Character.class ) ) + { + /* + modified into a more strict check to avoid char to string matching + to avoid matching method signatureslike + java_method(char) with octave_call('a String') + Date: 28-08-2010 + Author: Martin Hepperle + */ + return true; + } + else if ( isStringClass ( expCls ) && argCls.equals ( String.class ) ) + { + /* + added for strict String to String matching + java_method(String) with octave_call('a String') + but not + java_method(char) with octave_call('a String') + Date: 28-08-2010 + Author: Martin Hepperle + */ + return true; + } + else if ( expCls.isArray () && argCls.isArray () && + isCallableFrom ( expCls.getComponentType (), + argCls.getComponentType () ) ) + { + return true; + } + else if ( expCls.equals ( Object.class ) && argCls.isPrimitive () ) + { + return true; + } + else + { + return false; + } + } + + + private static boolean isNumberClass ( Class cls ) + { + return ( + cls.equals ( Integer.TYPE ) || + cls.equals ( Integer.class ) || + cls.equals ( Short.TYPE ) || + cls.equals ( Short.class ) || + cls.equals ( Long.TYPE ) || + cls.equals ( Long.class ) || + cls.equals ( Float.TYPE ) || + cls.equals ( Float.class ) || + cls.equals ( Double.TYPE ) || + cls.equals ( Double.class ) + ); + } + + + private static boolean isBooleanClass ( Class cls ) + { + return ( + cls.equals ( Boolean.class ) || + cls.equals ( Boolean.TYPE ) + ); + } + + + private static boolean isCharClass ( Class cls ) + { + return ( + cls.equals ( Character.class ) || + cls.equals ( Character.TYPE ) + ); + } + + + /** + * Check whether the supplied class is a String class. + * + * Added for more strict char/string mathicng of method signatures + * Date: 28-08-2010 + * Author: Martin Hepperle + * @param cls Class - the class to check + * @return boolean - true if clas is of class java.lang.String + */ + private static boolean isStringClass ( Class cls ) + { + return ( + cls.equals ( String.class ) + ); + } + + + private static Object[] castArguments ( Object[] args, Class[] argTypes, + Class[] expTypes ) + { + for ( int i = 0; i < args.length; i++ ) + { + args[i] = castArgument ( args[i], argTypes[i], expTypes[i] ); + } + return args; + } + + + private static Object castArgument ( Object obj, Class type, Class expType ) + { + // System.out.println("expType:"+expType.getCanonicalName() + " <= type:" + type.getCanonicalName()); + if ( type == null || expType.isAssignableFrom ( type ) ) + { + return obj; + } + else if ( isNumberClass ( expType ) ) + { + if ( expType.equals ( Integer.TYPE ) || expType.equals ( Integer.class ) ) + { + return new Integer ( ( ( Number ) obj ).intValue () ); + } + else if ( expType.equals ( Double.TYPE ) || expType.equals ( Double.class ) ) + { + return new Double ( ( ( Number ) obj ).doubleValue () ); + } + else if ( expType.equals ( Short.TYPE ) || expType.equals ( Short.class ) ) + { + return new Short ( ( ( Number ) obj ).shortValue () ); + } + else if ( expType.equals ( Long.TYPE ) || expType.equals ( Long.class ) ) + { + return new Long ( ( ( Number ) obj ).longValue () ); + } + } + else if ( isBooleanClass ( expType ) ) + { + return new Boolean ( ( ( Number ) obj ).intValue () != 0 ); + } + else if ( isCharClass ( expType ) ) + { + String s = obj.toString (); + if ( s.length () != 1 ) + { + throw new ClassCastException ( "cannot cast " + s + " to character" ); + } + return new Character ( s.charAt ( 0 ) ); + } + else if ( expType.isArray () && type.isArray () ) + { + return castArray ( obj, type.getComponentType (), + expType.getComponentType () ); + } + else if ( type.isPrimitive () ) + { + return obj; + } + return null; + } + + + private static Object castArray ( Object obj, Class elemType, + Class elemExpType ) + { + int len = Array.getLength ( obj ); + Object result = Array.newInstance ( elemExpType, len ); + for ( int i = 0; i < len; i++ ) + { + Array.set ( result, i, + castArgument ( Array.get ( obj, i ), elemType, elemExpType ) ); + } + return result; + } + + + private static int getArrayClassNDims ( Class cls ) + { + if ( cls != null && cls.isArray () ) + { + return ( 1 + getArrayClassNDims ( cls.getComponentType () ) ); + } + else + { + return 0; + } + } + + + private static Class getArrayElemClass ( Class cls ) + { + if ( cls.isArray () ) + { + return getArrayElemClass ( cls.getComponentType () ); + } + else + { + return cls; + } + } + + + private static Object getArrayElements ( Object array, int[][] idx, + int offset, + int ndims, Class elemType ) + { + if ( offset >= ndims ) + { + Object elem = Array.get ( array, idx[offset][0] ); + if ( offset < idx.length - 1 ) + { + return getArrayElements ( elem, idx, offset + 1, ndims, elemType ); + } + else + { + return elem; + } + } + else + { + Class compType = elemType.getComponentType (); + Object retval = Array.newInstance ( compType, idx[offset].length ); + for ( int i = 0; i < idx[offset].length; i++ ) + { + Object elem = Array.get ( array, idx[offset][i] ); + if ( offset < idx.length - 1 ) + { + elem = getArrayElements ( elem, idx, offset + 1, ndims, compType ); + } + Array.set ( retval, i, elem ); + } + return retval; + } + } + + + public static Object arraySubsref ( Object obj, int[][] idx ) + throws Exception + { + if ( !obj.getClass ().isArray () ) + { + throw new IllegalArgumentException ( "not a Java array" ); + } + + if ( idx.length == 1 ) + { + if ( idx[0].length == 1 ) + { + return Array.get ( obj, idx[0][0] ); + } + else + { + Object retval = Array.newInstance ( obj.getClass (). + getComponentType (), + idx[0].length ); + for ( int i = 0; i < idx[0].length; i++ ) + { + Array.set ( retval, i, Array.get ( obj, idx[0][i] ) ); + } + return retval; + } + } + else + { + int[] dims = new int[idx.length]; + for ( int i = 0; i < idx.length; i++ ) + { + dims[i] = idx[i].length; + } + + if ( dims.length != getArrayClassNDims ( obj.getClass () ) ) + { + throw new IllegalArgumentException ( "index size mismatch" ); + } + + /* resolve leading singletons */ + Object theObj = obj; + int offset = 0; + while ( dims[offset] == 1 ) + { + theObj = Array.get ( theObj, idx[offset][0] ); + offset = offset + 1; + if ( offset >= dims.length ) + { + return theObj; + } + } + if ( offset > 0 ) + { + int[][] new_idx = new int[idx.length - offset][]; + System.arraycopy ( idx, offset, new_idx, 0, idx.length - offset ); + return arraySubsref ( theObj, new_idx ); + } + + /* chop trailing singletons */ + int ndims = dims.length; + while ( ndims > 1 && dims[ndims - 1] == 1 ) + { + ndims--; + } + + /* create result array */ + Class elemClass = theObj.getClass (); + for ( int i = 0; i <= ( dims.length - ndims ); i++ ) + { + elemClass = elemClass.getComponentType (); + } + Object retval = Array.newInstance ( elemClass, dims[0] ); + + /* fill-in array */ + for ( int i = 0; i < idx[0].length; i++ ) + { + Object elem = getArrayElements ( Array.get ( theObj, idx[0][i] ), + idx, 1, ndims, elemClass ); + Array.set ( retval, i, elem ); + } + + return retval; + } + } + + + private static Object setArrayElements ( Object array, int[][] idx, + int offset, int ndims, Object rhs ) + throws Exception + { + if ( offset >= ndims ) + { + if ( offset < idx.length - 1 ) + { + setArrayElements ( Array.get ( array, idx[offset][0] ), idx, + offset + 1, ndims, rhs ); + } + else + { + Array.set ( array, idx[offset][0], rhs ); + } + return array; + } + else + { + for ( int i = 0; i < idx[offset].length; i++ ) + { + if ( offset < idx.length - 1 ) + { + setArrayElements ( Array.get ( array, idx[offset][i] ), idx, + offset + 1, ndims, Array.get ( rhs, i ) ); + } + else + { + Array.set ( array, idx[offset][i], Array.get ( rhs, i ) ); + } + } + return array; + } + } + + + public static Object arraySubsasgn ( Object obj, int[][] idx, Object rhs ) + throws Exception + { + if ( !obj.getClass ().isArray () ) + { + throw new IllegalArgumentException ( "not a Java array" ); + } + + if ( idx.length == 1 ) + { + if ( idx[0].length == 1 ) + { + Array.set ( obj, idx[0][0], rhs ); + } + else + { + for ( int i = 0; i < idx[0].length; i++ ) + { + Array.set ( obj, idx[0][i], Array.get ( rhs, i ) ); + } + } + return obj; + } + else + { + int[] dims = new int[idx.length]; + for ( int i = 0; i < idx.length; i++ ) + { + dims[i] = idx[i].length; + } + + if ( dims.length != getArrayClassNDims ( obj.getClass () ) ) + { + throw new IllegalArgumentException ( "index size mismatch" ); + } + + /* resolve leading singletons */ + Object theObj = obj; + int offset = 0; + while ( dims[offset] == 1 && offset < ( dims.length - 1 ) ) + { + theObj = Array.get ( theObj, idx[offset][0] ); + offset = offset + 1; + } + if ( offset > 0 ) + { + int[][] new_idx = new int[idx.length - offset][]; + System.arraycopy ( idx, offset, new_idx, 0, idx.length - offset ); + arraySubsasgn ( theObj, new_idx, rhs ); + return obj; + } + + /* chop trailing singletons */ + int ndims = dims.length; + while ( ndims > 1 && dims[ndims - 1] == 1 ) + { + ndims--; + } + + for ( int i = 0; i < idx[0].length; i++ ) + { + setArrayElements ( Array.get ( theObj, idx[0][i] ), idx, 1, ndims, + Array.get ( rhs, i ) ); + } + + return obj; + } + } + + + public static Object createArray ( Object cls, int[] dims ) + throws Exception + { + Class theClass; + if ( cls instanceof Class ) + { + theClass = ( Class ) cls; + } + else if ( cls instanceof String ) + { + theClass = Class.forName ( ( String ) cls, true, loader ); + } + else + { + throw new IllegalArgumentException ( "invalid class specification " + + cls ); + } + + return Array.newInstance ( theClass, dims ); + } + + + public static Object createArray ( Object cls, int length ) + throws Exception + { + return createArray ( cls, new int[] + {length} ); + } + +} diff --git a/scripts/java/org/octave/DlgListener.java b/scripts/java/org/octave/DlgListener.java new file mode 100755 --- /dev/null +++ b/scripts/java/org/octave/DlgListener.java @@ -0,0 +1,159 @@ +/* + ** Copyright (C) 2010 Martin Hepperle + ** + ** This program is free software; you can redistribute it and/or modify + ** it under the terms of the GNU General Public License as published by + ** the Free Software Foundation; either version 2 of the License, or + ** (at your option) any later version. + ** + ** This program is distributed in the hope that it will be useful, + ** but WITHOUT ANY WARRANTY; without even the implied warranty of + ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ** GNU General Public License for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with this program; If not, see . + */ + +package org.octave; + +import java.awt.event.*; +import javax.swing.*; + +/** + *

Implements button click actions for dialog box functions

+ * + *

Copyright (c) 2010 Martin Hepperle

+ * + * @author Martin Hepperle + * @version 1.0 + */ +public class DlgListener + extends WindowAdapter implements ActionListener, KeyListener +{ + // the parent frame of the dialog + JDialogBox m_Parent; + + public DlgListener ( JDialogBox d ) + { + m_Parent = d; + } + + + // + // --- extension of the WindowAdapter class --- + // + /** + * Called when the user clicks the close button on the window frame. + * + * @param e WindowEvent + */ + public void windowClosing ( WindowEvent e ) + { + m_Parent.closeDialog ( JDialogBox.CLOSE_CANCEL ); + } + + public void windowOpened( WindowEvent e ) + { + m_Parent.setFocus(); + } + + + // + // --- implementation of the ActionListener interface --- + // + /** + * Called when the user clicks a button in the dialog. + * Closes the dialog when either a button with an + * action command OK, CANCEL or NO is pressed. + * + * @param e ActionEvent + */ + public void actionPerformed ( ActionEvent e ) + { + if ( e.getActionCommand ().equals ( "OK" ) ) + { + m_Parent.closeDialog ( JDialogBox.CLOSE_OK ); + } + else if ( e.getActionCommand ().equals ( "CANCEL" ) ) + { + m_Parent.closeDialog ( JDialogBox.CLOSE_CANCEL ); + } + else if ( e.getActionCommand ().equals ( "NO" ) ) + { + m_Parent.closeDialog ( JDialogBox.CLOSE_NO ); + } + else if ( e.getActionCommand ().equals ( "SELALL" ) ) + { + m_Parent.SelectAll (); + } + } + + + // + // --- implementation of the KeyListener interface --- + // + /** + * Closes the dialog when the ENTER or ESCAPE keys are released. + * + * @param e KeyEvent + */ + public void keyTyped ( KeyEvent e ) + { + if ( e.getKeyCode () == KeyEvent.VK_ESCAPE ) + { + m_Parent.closeDialog ( JDialogBox.CLOSE_CANCEL ); + } + } + + + /** + * @param e KeyEvent + */ + public void keyPressed ( KeyEvent e ) + { + if ( e.getSource ().getClass ().equals ( JTextArea.class ) ) + { + JTextArea ta = ( JTextArea ) e.getSource (); + if ( e.getKeyCode () == KeyEvent.VK_ENTER ) + { + char c[] = ta.getText ().toCharArray (); + int nLines = 1; + for ( int i = 0; i < c.length; i++ ) + { + if ( c[i] == '\n' ) + { + nLines++; + } + } + + if ( nLines >= ta.getRows () ) + { + e.consume (); + } + } + else if ( e.getKeyCode () == KeyEvent.VK_TAB ) + { + e.consume (); + + if ( ( e.getModifiersEx () & KeyEvent.SHIFT_DOWN_MASK ) == + KeyEvent.SHIFT_DOWN_MASK ) + { + ta.transferFocusBackward(); + } + else + { + ta.transferFocus (); + } + } + } + } + + + /** + * @param e KeyEvent + */ + public void keyReleased ( KeyEvent e ) + { + } +} diff --git a/scripts/java/org/octave/JDialogBox.java b/scripts/java/org/octave/JDialogBox.java new file mode 100755 --- /dev/null +++ b/scripts/java/org/octave/JDialogBox.java @@ -0,0 +1,986 @@ + /* + ** Copyright (C) 2010 Martin Hepperle + ** + ** This program is free software; you can redistribute it and/or modify + ** it under the terms of the GNU General Public License as published by + ** the Free Software Foundation; either version 2 of the License, or + ** (at your option) any later version. + ** + ** This program is distributed in the hope that it will be useful, + ** but WITHOUT ANY WARRANTY; without even the implied warranty of + ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ** GNU General Public License for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with this program; If not, see . + */ + +package org.octave; + +import java.net.*; +import java.util.*; + +import java.awt.*; +import javax.swing.*; + +/** + *

Implementation of various dialog box functions

+ * + *

The following functions are provided for being called via + * Octave script files:

+ *
    + *
  • errordlg
  • + *
  • helpdlg
  • + *
  • inputdlg
  • + *
+ * + *

Copyright (c) 2010 Martin Hepperle

+ * + * @author Martin Hepperle + * @version 1.0 + */ +public class JDialogBox +{ + public static final int CLOSE_OK = 1; + public static final int CLOSE_NO = 2; + public static final int CLOSE_CANCEL = 3; + + // dialog type + public static int FLAG_LABEL = 1; + public static int FLAG_TEXT = 2; + public static int FLAG_INPUT = 4; + public static int FLAG_LIST = 8; + // icon selection + public static int FLAG_QUESTION = 32; + public static int FLAG_ERROR = 64; + public static int FLAG_WARNING = 128; + public static int FLAG_INFORMATION = 256; + + public static int DLG_QUEST = FLAG_QUESTION | FLAG_TEXT; + public static int DLG_INPUT = FLAG_QUESTION | FLAG_INPUT; + public static int DLG_LIST = FLAG_QUESTION | FLAG_LIST; + + private final static String m_OK = "OK"; + private final static String m_Yes = "Yes"; + private final static String m_No = "No"; + private final static String m_Cancel = "Cancel"; + + private JButton m_ButtonNO; + private JButton m_ButtonOK; + private JButton m_ButtonCANCEL; + private JButton m_Focus; + private JTextArea m_TextField[]; + private JList m_List; + private JFrame m_ParentFrame; + private int m_CloseMethod; + + // ------------------------------------ + // implementation of listdlg function + // ------------------------------------ + + /** + * + * @param listcell String[] - a array of strings, one for each list entry + * @param selmode String + * @param sizecell Object[] + * @param initialcell Object[] + * @param name String + * @param promptcell String[] + * @param okstring String + * @param cancelstring String + * @return String[] + */ + public static int[] listdlg ( String[] listcell, + String selmode, + Object[] sizecell, + Object[] initialcell, + String name, + String[] promptcell, + String okstring, + String cancelstring ) + { + JDialogBox d = new JDialogBox (); + d.genericdlg ( promptcell, listcell, name, selmode, + DLG_LIST, + sizecell, initialcell, okstring, null, cancelstring ); + return ( d.getSelectedIndices () ); + } + + + // ------------------------------------ + // implementation of inputdlg function + // ------------------------------------- + + /** + * Implements a variation of the inputdlg function. + * + * @param prompt String[] - an array of text strings to be used as labels. + * @param title String - a text string to be used to label the dialog caption. + * @param RowsCols int - defines the width of the text fields in columns. + * @param defaults Object[] - an array of text strings or numbers to be + * placed into the text fields as default values. + * @return String[] - an array of text strings containing the content of the + * text fields. + */ + public static String[] inputdlg ( String[] prompt, + String title, + Object[] RowsCols, + Object[] defaults ) + { + JDialogBox d = new JDialogBox (); + d.genericdlg ( prompt, null, title, "on", + FLAG_INPUT | FLAG_QUESTION, + RowsCols, defaults, m_OK, null, m_Cancel ); + return ( d.getInput () ); + } + + + /** + * Extract the current content from the text fields of an inputdlg. + * + * @return String[] - the text contained in the fields of an inputdlg. + * null if the dialog was cancelled. + */ + private String[] getInput () + { + String s[] = null; + + if ( m_CloseMethod == CLOSE_OK ) + { + s = new String[m_TextField.length]; + + for ( int i = 0; i < s.length; i++ ) + { + s[i] = new String ( m_TextField[i].getText () ); + } + } + + return ( s ); + } + + + private String getResult () + { + String s = null; + + if ( m_CloseMethod == CLOSE_OK ) + { + s = m_ButtonOK.getText (); + } + else if ( m_CloseMethod == CLOSE_CANCEL ) + { + s = m_ButtonCANCEL.getText (); + } + else + { + s = m_ButtonNO.getText (); + } + + return ( s ); + } + + + /** + * Extract the current content from the text fields of an inputdlg. + * + * @return String[] - the text contained in the fields of an inputdlg. + * null if the dialog was cancelled. + */ + private String[] getSelection () + { + String s[] = null; + + if ( m_CloseMethod == CLOSE_OK ) + { + int selection[] = m_List.getSelectedIndices (); + + s = new String[selection.length]; + + for ( int i = 0; i < s.length; i++ ) + { + + // s[i] = new String ( Integer.toString(selection[i]) ); + s[i] = ( m_List.getSelectedValues ()[i] ).toString (); + } + } + + return ( s ); + } + + + private int[] getSelectedIndices () + { + int s[] = null; + + if ( m_CloseMethod == CLOSE_OK ) + { + s = m_List.getSelectedIndices (); + for ( int i = 0; i < s.length; i++ ) + { + + // translate to 1 based indices + s[i] = s[i] + 1; + } + } + + return ( s ); + } + + + public void SelectAll () + { + if ( null != m_List ) + { + m_List.setSelectionInterval ( 0, m_List.getModel ().getSize () - 1 ); + } + } + + + // ------------------------------------- + // implementation of helpdlg function + // ------------------------------------- + + /** + * Implements a simple helpdlg with default text and caption. Not very useful. + * + * Octave > helpdlg('helpstring','title') + * + * Called via helpdlg.m. + * + * @param helpstring String - a message string to be presented to the user. + * The string can have embedded newline (\n) characters to break the message + * into multiple lines. + * @param title String - a text string to be used to label the dialog caption. + * @return int - always 1 + */ + public static int helpdlg ( String helpstring, String title ) + { + JDialogBox d = new JDialogBox (); + String s[] = new String[1]; + s[0] = helpstring; + return ( d.genericdlg ( s, null, title, "on", + FLAG_TEXT | FLAG_INFORMATION, null, null, + m_OK, null, m_Cancel ) ); + } + + + // ------------------------------------- + // implementation of emptydlg function + // ------------------------------------- + + /** + * Implements a simple helpdlg with default text and caption. Not very useful. + * + * Octave > emptydlg('messagestring','title') + * + * Called via dlgbox.m. + * + * @param messagestring String - a message string to be presented to the user. + * The string can have embedded newline (\n) characters to break the message + * into multiple lines. + * @param title String - a text string to be used to label the dialog caption. + * @return int - always 1 + */ + public static int emptydlg ( String helpstring, String title ) + { + JDialogBox d = new JDialogBox (); + String s[] = new String[1]; + s[0] = helpstring; + return ( d.genericdlg ( s, null, title, "on", + FLAG_TEXT, null, null, + m_OK, null, m_Cancel ) ); + } + + + // ------------------------------------------- + // implementation of questdlg related functions + // ------------------------------------------- + + /** + * Implements a simple questdlg with default text and caption. Not very useful. + * + * @param question String - the question to be presented + * @param title String - the caption + * @param options String[] - 'str1', 'str2', 'str3', 'default' + * @return String - the caption of the button pressed by the user + */ + public static String questdlg ( String question, + String title, + String[] options ) + { + JDialogBox d = new JDialogBox (); + String s[] = new String[1]; + s[0] = question; + d.genericdlg ( s, options, title, "on", + DLG_QUEST, null, null, + options[0], options[1], options[2] ); + return ( d.getResult () ); + } + + + // ------------------------------------- + // implementation of errordlg function + // ------------------------------------- + + /** + * Implements a simple errordlg with default text and caption. Not very useful. + * + * @param errorstring String - the error message to display. + * @param dlgname String - the caption of the dialog box. + * @return int - always 1 + */ + public static int errordlg ( String errorstring, String dlgname ) + { + JDialogBox d = new JDialogBox (); + String s[] = new String[1]; + s[0] = errorstring; + return ( d.genericdlg ( s, null, dlgname, "on", FLAG_TEXT | FLAG_ERROR, + null, null, + m_OK, null, m_Cancel ) ); + } + + + // ------------------------------------------- + // implementation of warndlg related functions + // ------------------------------------------- + + /** + * Implements a simple warndlg with default text and caption. Not very useful. + * + * Called via warndlg.m. + * + * @param errorstring String - the message to be presented to the user. + * @param dlgname String - the caption of the dialog box. + * @return int - always 1 + */ + public static int warndlg ( String errorstring, String dlgname ) + { + JDialogBox d = new JDialogBox (); + String s[] = new String[1]; + s[0] = errorstring; + return ( d.genericdlg ( s, null, dlgname, "on", FLAG_TEXT | FLAG_WARNING, + null, null, + m_OK, null, m_Cancel ) ); + } + + + // ------------------------------------- + // generic dlg function + // ------------------------------------- + /** + * A generic dialog creation and display function. + * + * @param message String[] + * @param list String[] + * @param caption String + * @param on String + * @param flag int + * @param RowsCols Object[] + * @param defaults Object[] + * @param okstring String + * @param nostring String + * @param cancelstring String + * @return int + */ + public int genericdlg ( String message[], + String list[], + String caption, + String on, + int flag, + Object[] RowsCols, + Object[] defaults, + String okstring, + String nostring, + String cancelstring ) + { + TeXtranslator theTranslator = new TeXtranslator (); + setSystemLnF ( true ); + + caption = theTranslator.replace ( caption ); + + m_ButtonNO = null; + m_ButtonOK = null; + m_ButtonCANCEL = null; + + // create a modal dialog with an empty frame as its parent + m_ParentFrame = new JFrame (); + + // --- trick to bring dialog to the front + // In Windows, the dialog is not brought to the foreground, but hidden + // behind the Octave window as long as the parent frame is not visible. + // To avoid that the frame is visible, we move it outside of the screen. + m_ParentFrame.setBounds ( Toolkit.getDefaultToolkit ().getScreenSize (). + width + 100, + Toolkit.getDefaultToolkit ().getScreenSize (). + height + 100, 1, 1 ); + m_ParentFrame.setVisible ( true ); + //-- end of trick + + JDialog dlg; + dlg = new JDialog ( m_ParentFrame ); + dlg.setTitle ( caption ); + + dlg.setModal ( true ); + dlg.setDefaultCloseOperation ( JDialog.DISPOSE_ON_CLOSE ); + + DlgListener theListener = new DlgListener ( this ); + + Container d = dlg.getContentPane (); + d.setLayout ( new BorderLayout ( 8, 8 ) ); + + // spacer + d.add ( new JLabel ( " " ), BorderLayout.NORTH ); + d.add ( new JLabel ( " " ), BorderLayout.EAST ); + + JPanel p = new JPanel (); + + if ( FLAG_LABEL == ( FLAG_LABEL & flag ) ) + { + // a single line label + JLabel l = new JLabel ( theTranslator.replace ( message[0] ) ); + p.add ( l ); + } + else if ( FLAG_TEXT == ( FLAG_TEXT & flag ) ) + { + String msg = theTranslator.replace ( message[0] ); + // a multi-line text display for helpdlg + StringTokenizer st = new StringTokenizer ( msg, "\n" ); + + int nRows = ( null == RowsCols ) ? 1 : + Integer.parseInt ( RowsCols[0].toString () ); + nRows = Math.max ( nRows, st.countTokens () ); + int nCols = Math.max ( 1, msg.length () / nRows ); + + p.setLayout ( new GridLayout ( message.length, 1 ) ); + JTextArea ta = new JTextArea ( msg, nRows, nCols ); + ta.setEditable ( false ); + ta.setFocusable ( false ); + ta.setOpaque ( false ); + // replace ugly monospaced font + ta.setFont ( p.getFont () ); + p.add ( ta ); + } + else if ( FLAG_INPUT == ( FLAG_INPUT & flag ) ) + { + // a multi label/textfield entry dialog for inputdlg + GridBagConstraints gbc = new GridBagConstraints (); + gbc.insets.top = 4; + gbc.insets.left = 8; + gbc.gridx = 0; + gbc.anchor = GridBagConstraints.NORTHWEST; + + p.setLayout ( new GridBagLayout () ); + m_TextField = new JTextArea[message.length]; + + // default values + int nRows = 1; + int nCols = 10; + + for ( int i = 0; i < message.length; i++ ) + { + String msg = theTranslator.replace ( message[i] ); + JLabel l = new JLabel ( msg ); + l.setHorizontalAlignment ( Label.LEFT ); + gbc.gridy = 2 * i; + p.add ( l, gbc ); + /** + * @todo CHECK handling of RowsCols for inputdlg + */ + if ( RowsCols != null ) + { + if ( RowsCols.length == 2 * message.length ) + { + nRows = Integer.parseInt ( RowsCols[i].toString () ); + nCols = Integer.parseInt ( RowsCols[RowsCols.length / 2 + + i].toString () ); + } + } + + m_TextField[i] = new JTextArea ( "", Math.max ( nRows, 1 ), nCols ); + // avoid resizing + m_TextField[i].setPreferredSize ( new Dimension ( Math.max ( nRows, + 1 ), nCols ) ); + m_TextField[i].setAutoscrolls ( false ); + m_TextField[i].setFont ( p.getFont () ); + m_TextField[i].setBorder ( new javax.swing.border.EtchedBorder () ); + m_TextField[i].addKeyListener ( theListener ); + + gbc.gridy = 2 * i + 1; + p.add ( m_TextField[i], gbc ); + } + + if ( defaults != null ) + { + if ( defaults.length == message.length ) + { + for ( int i = 0; i < message.length; i++ ) + { + String def = theTranslator.replace ( defaults[i].toString () ); + m_TextField[i].setText ( def ); + } + } + } + } + else if ( DLG_LIST == ( DLG_LIST & flag ) ) + { + GridBagConstraints gbc = new GridBagConstraints (); + gbc.insets.top = 4; + gbc.insets.left = 8; + gbc.gridx = 0; + gbc.anchor = GridBagConstraints.NORTHWEST; + + p.setLayout ( new GridBagLayout () ); + + for ( int i = 0; i < message.length; i++ ) + { + // a single line label + String msg = theTranslator.replace ( message[i] ); + JLabel l = new JLabel ( msg ); + gbc.gridy = i; + p.add ( l, gbc ); + } + + String lst[] = new String[list.length]; + + for ( int i = 0; i < list.length; i++ ) + { + lst[i] = theTranslator.replace ( list[i] ); + } + m_List = new JList ( lst ); + + // replace ugly monospaced font + m_List.setFont ( p.getFont () ); + + m_List.setMinimumSize ( new Dimension ( Math.max ( 1, + Integer.parseInt ( RowsCols[0].toString () ) ), + Math.max ( 1, + Integer.parseInt ( RowsCols[1].toString () ) ) ) ); + m_List.setPreferredSize ( new Dimension ( Math.max ( 1, + Integer.parseInt ( RowsCols[1].toString () ) ), + Math.max ( 1, + Integer.parseInt ( RowsCols[0].toString () ) ) ) ); + m_List.setBorder ( new javax.swing.border.EtchedBorder () ); + + gbc.gridy = message.length; + gbc.fill = GridBagConstraints.HORIZONTAL; + p.add ( m_List, gbc ); + + if ( on.toLowerCase ().equals ( "single" ) ) + { + // single selection list + m_List.setSelectionMode ( ListSelectionModel.SINGLE_SELECTION ); + + m_List.setSelectedIndex ( Integer.parseInt ( + defaults[0].toString () ) - 1 ); + } + else + { + // multiple selection possible + m_List.setSelectionMode ( ListSelectionModel. + MULTIPLE_INTERVAL_SELECTION ); + + int selection[] = new int[defaults.length]; + for ( int i = 0; i < defaults.length; i++ ) + { + selection[i] = Integer.parseInt ( defaults[i].toString () ) - 1; + } + m_List.setSelectedIndices ( selection ); + + JButton b = new JButton ( "Select All" ); + b.setActionCommand ( "SELALL" ); + b.addActionListener ( theListener ); + gbc.gridy = message.length + 1; + gbc.fill = GridBagConstraints.HORIZONTAL; + p.add ( b, gbc ); + } + + } + + // prepare icon, if any + String sIconFile = null; + String sIconResource = null; + Icon theIcon = null; + + if ( FLAG_ERROR == ( FLAG_ERROR & flag ) ) + { + sIconFile = "images/error.png"; + // Java for Windows + sIconResource = "OptionPane.errorIcon"; + // Java for Linux does not offer these standard icons... + } + else if ( FLAG_WARNING == ( FLAG_WARNING & flag ) ) + { + sIconFile = "images/warning.png"; + // Java for Windows + sIconResource = "OptionPane.warningIcon"; + // Java for Linux does not offer these standard icons... + } + else if ( FLAG_QUESTION == ( FLAG_QUESTION & flag ) ) + { + sIconFile = "images/question.png"; + // Java for Windows + sIconResource = "OptionPane.questionIcon"; + // Java for Linux does not offer these standard icons... + } + else if ( FLAG_INFORMATION == ( FLAG_INFORMATION & flag ) ) + { + sIconFile = "images/information.png"; + // Java for Windows + sIconResource = "OptionPane.informationIcon"; + // Java for Linux does not offer these standard icons... + } + + // first try to find the UIManager specific icon to fit look and feel + // Note: the Windows XP look and feel offers 50 icons. + if ( sIconResource != null ) + { + UIDefaults df = UIManager.getLookAndFeelDefaults (); + theIcon = df.getIcon ( sIconResource ); + } + + // fallback on bitmap image resource if icon was not found + if ( theIcon == null && + sIconFile != null ) + { + URL theResource = JDialogBox.class.getResource ( sIconFile ); + if ( theResource != null ) + { + theIcon = new ImageIcon ( theResource ); + } + } + + if ( theIcon != null ) + { + // dummy panel to provide space around icon + JPanel pi = new JPanel ( new GridLayout ( 1, 3 ) ); + pi.add ( new JLabel () ); + pi.add ( new JLabel ( theIcon ) ); + pi.add ( new JLabel () ); + d.add ( pi, BorderLayout.WEST ); + + // use Octave icon if available. otherwise use dialog icon + Icon theOctaveIcon = getOctaveIcon (); + prepareFrameIcon ( m_ParentFrame, + theOctaveIcon == null ? theIcon : theOctaveIcon ); + } + + d.add ( p, BorderLayout.CENTER ); + + // button bar (2 rows of 3 columns each + + p = new JPanel (); + p.setLayout ( new java.awt.GridLayout ( 2, 3 ) ); + + // spacer row + p.add ( new JLabel () ); + p.add ( new JLabel () ); + p.add ( new JLabel () ); + + if ( DLG_QUEST == ( DLG_QUEST & flag ) ) + { + // questdlg with empty option[2]: only two buttons + if ( nostring.length () < 1 ) + { + // spacer: left + p.add ( new JLabel () ); + } + } + else + { + // spacer: left + p.add ( new JLabel () ); + } + + m_ButtonOK = new JButton ( theTranslator.replace ( okstring ) ); + m_ButtonOK.setActionCommand ( "OK" ); + m_ButtonOK.addActionListener ( theListener ); + m_Focus = m_ButtonOK; + p.add ( m_ButtonOK ); + + if ( DLG_QUEST == ( DLG_QUEST & flag ) ) + { + // questdlg with empty option[2]: only two buttons + if ( nostring.length () > 01 ) + { + // questdlg has three buttons + m_ButtonNO = new JButton ( theTranslator.replace ( nostring ) ); + m_ButtonNO.setActionCommand ( "NO" ); + m_ButtonNO.addActionListener ( theListener ); + p.add ( m_ButtonNO ); + if ( DLG_QUEST == ( DLG_QUEST & flag ) ) + { + // select default button + if ( list[3].equals ( nostring ) ) + { + m_Focus = m_ButtonNO; + } + } + } + } + + if ( DLG_INPUT == ( DLG_INPUT & flag ) || + DLG_LIST == ( DLG_LIST & flag ) || + DLG_QUEST == ( DLG_QUEST & flag ) ) + { + m_ButtonCANCEL = new JButton ( theTranslator.replace ( cancelstring ) ); + m_ButtonCANCEL.setActionCommand ( "CANCEL" ); + m_ButtonCANCEL.addActionListener ( theListener ); + p.add ( m_ButtonCANCEL ); + if ( DLG_QUEST == ( DLG_QUEST & flag ) ) + { + // select default button + if ( list[3].equals ( cancelstring ) ) + { + m_Focus = m_ButtonCANCEL; + } + } + } + else + { + // spacer: right + p.add ( new JLabel () ); + } + + d.add ( p, BorderLayout.SOUTH ); + dlg.pack (); + + dlg.addWindowListener ( theListener ); + + if ( on.equals ( "on" ) ) + { + m_ParentFrame.setAlwaysOnTop ( true ); + } + + // center dialog on screen + Dimension dlgSize = dlg.getSize (); + Dimension screenSize = Toolkit.getDefaultToolkit ().getScreenSize (); + + dlg.setLocation ( ( screenSize.width - dlgSize.width ) / 2, + ( screenSize.height - dlgSize.height ) / 2 ); + + dlg.setVisible ( true ); + dlg.requestFocus (); + + m_ParentFrame.setVisible ( false ); + + return ( 1 ); + } + + + /** + * + * @return Icon - null if icon was not found + */ + private Icon getOctaveIcon () + { + Icon theIcon = null; + URL theResource = JDialogBox.class.getResource ( "images/octave.png" ); + if ( theResource != null ) + { + theIcon = new ImageIcon ( theResource ); + } + return theIcon; + } + + + /** + * Replace the standard Java frame icon with an Octave Icon. + * + * @param theFrame Frame - the Frame to decorate + * @param theIcon Icon - the icon to use if octave icon is not found. + */ + private void prepareFrameIcon ( Frame theFrame, Icon theIcon ) + { + // prepare icon for upper left corner of Frame window + // maybe there is a simpler way to achieve this + int w = theIcon.getIconWidth (); + int h = theIcon.getIconHeight (); + // Frame must be made displayable by packing it for createImage() to succeed + theFrame.pack (); + Image theImage = theFrame.createImage ( w, h ); + theIcon.paintIcon ( theFrame, theImage.getGraphics (), 0, 0 ); + theFrame.setIconImage ( theImage ); + } + + + /** + * Select Look and Feel + * + * @param bSystemLnF boolean - if true, the current systesm Look&Feel is used, + * otherwise the Swing/Metal cross platform Look&Feel is used. + */ + private void setSystemLnF ( boolean bSystemLnF ) + { + try + { + if ( bSystemLnF ) + { + // switch from Swing LnF to local system LnF + UIManager.setLookAndFeel ( UIManager. + getSystemLookAndFeelClassName () ); + } + else + { + // use Swing LnF + UIManager.setLookAndFeel ( UIManager. + getCrossPlatformLookAndFeelClassName () ); + } + } + catch ( Exception exception ) + { + exception.printStackTrace (); + } + } + + + /** + * Called when the dialog is closed. Allows for specific cleanup actions. + * + * @param closeMethod int - OctaveDialog.CLOSE_OK, OctaveDialog.CLOSE_CANCEL + */ + public void closeDialog ( int closeMethod ) + { + m_CloseMethod = closeMethod; + m_ParentFrame.dispose (); + } + + + public void setFocus () + { + if ( null != m_Focus ) + { + m_Focus.requestFocus (); + m_ParentFrame.getRootPane ().setDefaultButton ( m_Focus ); + m_ParentFrame.setAlwaysOnTop ( true ); + } + } + + + /** + * Tests the dialogs + * + * @param args String[] - not used. + */ + public static void main ( String[] args ) + { + TeXtranslator t = new TeXtranslator(); + + if(false) + { + // find out key names of icon UI resources + UIDefaults df = UIManager.getLookAndFeelDefaults (); + + for ( Enumeration e = df.keys (); e.hasMoreElements (); ) + { + String s = e.nextElement ().toString (); + + if ( s.toLowerCase ().contains ( "icon" ) ) + { + System.out.println ( s ); + } + } + } + + try + { + Class[] argTypes = new Class[1]; + argTypes[0] = String.class; + + java.lang.reflect.Constructor c = ClassHelper.findConstructor ( java.lang.StringBuffer.class, + argTypes ); + Object argValues[] = new Object[1]; + argValues[0] = new String("initial value"); + Object sb = c.newInstance(argValues); + System.out.println(sb.toString()); + + ClassHelper.invokeMethod(sb,"append",argValues,argTypes); + System.out.println(sb.toString()); + + argValues = new Object[2]; + argTypes = new Class[2]; + argTypes[0] = Integer.class; + argTypes[1] = String.class; + argValues[0] = new Integer(0); + argValues[1] = new String("inserted"); + + ClassHelper.invokeMethod(sb,"insert",argValues,argTypes); + System.out.println(sb.toString()); + } + catch ( Throwable e ) + {} + + if ( true ) + { + return; + } + + helpdlg ( "If you need help\nyou should ask for help\nif someone is around\notherwise you are on your own.", + "Information" ); + + String[] options = new String[4]; + options[0] = "Yeah \\vartheta is too low"; + options[1] = "Maybe"; + options[2] = "Nay \\vartheta is too high"; + options[3] = "Maybe"; + + System.out.println ( questdlg ( "Is it too cold?", "Temperature", options ) ); + + // test variants of errordlg + // does not affect layering of dialog + errordlg ( "Background error!", "Error" ); + + // test variants of helpdlg + + // test variants of inputdlg + String prompt[] = new String[2]; + prompt[0] = "Question 1"; + prompt[1] = "Question 2"; + String defaults[] = new String[2]; + defaults[0] = "1.1"; + defaults[1] = "2.2"; + String title = "Enter values"; + + Integer rc[] = new Integer[2 * 2]; + rc[0] = new Integer ( 1 ); + rc[1] = new Integer ( 2 ); + rc[2] = new Integer ( 10 ); + rc[3] = new Integer ( 20 ); + + inputdlg ( prompt, title, rc, defaults ); + + String listcell[] = new String[4]; + listcell[0] = "a \\alpha"; + listcell[1] = "b \\beta"; + listcell[2] = "c \\gamma"; + listcell[3] = "d \\delta"; + + Integer size[] = new Integer[2]; + size[0] = new Integer ( 80 ); + size[1] = new Integer ( 100 ); + + Integer initial[] = new Integer[2]; + initial[0] = new Integer ( 4 ); + initial[1] = new Integer ( 2 ); + + String promptcell[] = new String[2]; + promptcell[0] = "Select something"; + promptcell[1] = "(or even more than one thing)"; + + int idx[] = listdlg ( listcell, + "Multiple", + size, + initial, + "name", + promptcell, + "okstring", + "cancelstring" ); + + if ( idx != null ) + { + for ( int i = 0; i < idx.length; i++ ) + { + System.out.println ( idx[i] ); + } + } + } +} diff --git a/scripts/java/org/octave/Matrix.java b/scripts/java/org/octave/Matrix.java new file mode 100644 --- /dev/null +++ b/scripts/java/org/octave/Matrix.java @@ -0,0 +1,355 @@ +/* Copyright (C) 2007 Michael Goffioul +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; If not, see . +*/ + +package org.octave; + +import java.nio.*; +import java.text.DecimalFormat; + +public class Matrix +{ + private int[] dims; + private Buffer data; + private Object cache = null; + + public Matrix() + { + this(new double[0], new int[] {0, 0}); + } + + public Matrix(double[] data) + { + this(data, new int[] {1, data.length}); + } + + public Matrix(double[][] data) + { + int m = data.length; + int n = (m > 0 ? data[0].length : 0); + int idx = 0; + double[] buf = new double[m*n]; + + for (int j=0; j 0 ? data[0].length : 0); + int p = (n > 0 ? data[0][0].length : 0); + int idx = 0; + double[] buf = new double[m*n*p]; + + for (int k=0; k= dims.length ? -1 : dims[index]); + } + + public int[] getDims() + { + return dims; + } + + public String getClassName() + { + if (data instanceof DoubleBuffer) + return "double"; + else if (data instanceof IntBuffer) + return "integer"; + else if (data instanceof ByteBuffer) + return "byte"; + else + return "unknown"; + } + + public String toString() + { + if (dims == null || data == null) + return "null"; + + String s = ""; + + if (dims.length == 2 && dims[0] == 1 && dims[1] <= 5) + { + if (data instanceof DoubleBuffer) + { + DoubleBuffer b = (DoubleBuffer)data; + DecimalFormat fmt = new DecimalFormat("0.0000 "); + for (int i=0; i 0) + for (int j=0; j 0) + for (int k=0; k 0) + for (int j=0; j val) + val = buf[i]; + } + else if (data instanceof ByteBuffer) + { + byte[] buf = ((ByteBuffer)data).array(); + for (int i=0; i val) + val = buf[i]; + } + else + System.out.println("Warning: cannot compute max value for array of type `" + getClassName() + "'"); + + return val; + } +} diff --git a/scripts/java/org/octave/OctClassLoader.java b/scripts/java/org/octave/OctClassLoader.java new file mode 100644 --- /dev/null +++ b/scripts/java/org/octave/OctClassLoader.java @@ -0,0 +1,68 @@ +/* Copyright (C) 2007 Michael Goffioul +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; If not, see . +*/ + +package org.octave; + +import java.io.File; + +public class OctClassLoader extends java.net.URLClassLoader +{ + public OctClassLoader () + { + super (new java.net.URL[0]); + } + + public OctClassLoader (ClassLoader parent) + { + super (new java.net.URL[0], parent); + } + + protected Class findClass (String name) throws ClassNotFoundException + { + //System.out.println ("Looking for class " + name); + return super.findClass (name); + } + + protected String findLibrary (String libname) + { + // Look dynamically into java.library.path, because Sun VM does + // not do it (seems to cache initial java.library.path instead) + + String[] paths = System.getProperty ("java.library.path").split (File.pathSeparator); + + libname = System.mapLibraryName (libname); + for (int i=0; i. +*/ + +package org.octave; + +import java.util.*; + +public class Octave +{ + static + { + System.load (System.getProperty ("octave.java.path") + java.io.File.separator + "__java__.oct"); + } + + private static Object notifyObject = null; + private static Object[] args = null; + private static LinkedList invokeList = new LinkedList(); + private static LinkedList waitList = new LinkedList(); + + public native static boolean call (String name, Object[] argin, Object[] argout); + public native static void doInvoke(int ID, Object[] args); + public native static void doEvalString(String cmd); + public native static boolean needThreadedInvokation(); + + public static void checkPendingAction() + { + if (notifyObject != null) + { + synchronized(notifyObject) + { + if (notifyObject instanceof OctaveReference) + doInvoke(((OctaveReference)notifyObject).getID(), args); + else if (notifyObject instanceof String) + doEvalString((String)notifyObject); + notifyObject.notifyAll(); + } + notifyObject = null; + args = null; + } + + Object obj; + Object[] objArgs; + + while (true) + { + obj = null; + objArgs = null; + + synchronized (invokeList) + { + if (invokeList.size() > 0) + { + obj = invokeList.remove(); + if (obj instanceof OctaveReference) + objArgs = (Object[])invokeList.remove(); + } + } + + if (obj != null) + { + if (obj instanceof Runnable) + ((Runnable)obj).run(); + else if (obj instanceof OctaveReference) + doInvoke(((OctaveReference)obj).getID(), objArgs); + else if (obj instanceof String) + doEvalString((String)obj); + } + else + break; + } + /* + synchronized(invokeList) + { + while (invokeList.size() > 0) + { + Object obj = invokeList.remove(); + if (obj instanceof Runnable) + ((Runnable)obj).run(); + if (obj instanceof OctaveReference) + { + Object[] objArgs = (Object[])invokeList.remove(); + doInvoke(((OctaveReference)obj).getID(), objArgs); + } + else if (obj instanceof String) + doEvalString((String)obj); + } + } + */ + } + + private static void checkWaitState() + { + if (waitList.size() > 0) + { + Object wObj = waitList.getFirst(); + synchronized (wObj) + { + wObj.notifyAll(); + } + } + } + + public static void invokeAndWait(OctaveReference ref, Object[] invokeArgs) + { + if (needThreadedInvokation()) + { + synchronized(ref) + { + notifyObject = ref; + args = invokeArgs; + try { checkWaitState(); ref.wait(); } + catch (InterruptedException e) {} + } + } + else + doInvoke(ref.getID(), invokeArgs); + } + + public static void evalAndWait(String cmd) + { + if (needThreadedInvokation()) + { + synchronized(cmd) + { + notifyObject = cmd; + args = null; + try { checkWaitState(); cmd.wait(); } + catch (InterruptedException e) {} + } + } + else + doEvalString(cmd); + } + + public static void invokeLater(Runnable r) + { + if (needThreadedInvokation()) + synchronized(invokeList) + { + invokeList.add(r); + checkWaitState(); + } + else + r.run(); + } + + public static void invokeLater(OctaveReference ref, Object[] invokeArgs) + { + if (needThreadedInvokation()) + synchronized(invokeList) + { + invokeList.add(ref); + invokeList.add(invokeArgs); + checkWaitState(); + } + else + doInvoke(ref.getID(), invokeArgs); + } + + public static void evalLater(String cmd) + { + if (needThreadedInvokation()) + synchronized(invokeList) + { + invokeList.add(cmd); + checkWaitState(); + } + else + doEvalString(cmd); + } + + public static void waitFor(Object wObj) + { + waitList.add(0, wObj); + synchronized (wObj) + { + while (waitList.size() > 0 && waitList.getFirst() == wObj) + { + try { wObj.wait(); } + catch (InterruptedException e) {} + checkPendingAction(); + } + } + } + + public static void endWaitFor(Object obj) + { + boolean isCurrentWaitObject = (waitList.size() > 0 && waitList.getFirst() == obj); + + waitList.remove(obj); + if (needThreadedInvokation() && isCurrentWaitObject) + synchronized (obj) + { + obj.notifyAll(); + } + } + + public static Object do_test (String name, Object arg0) throws Exception + { + Object[] argin = new Object[] { arg0 }; + Object[] argout = new Object[1]; + if (call (name, argin, argout)) + return argout[0]; + throw new Exception ("octave call failed"); + } +} diff --git a/scripts/java/org/octave/OctaveReference.java b/scripts/java/org/octave/OctaveReference.java new file mode 100644 --- /dev/null +++ b/scripts/java/org/octave/OctaveReference.java @@ -0,0 +1,63 @@ +/* Copyright (C) 2007 Michael Goffioul +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; If not, see . +*/ + +package org.octave; + +public class OctaveReference +{ + static + { + System.load (System.getProperty ("octave.java.path") + java.io.File.separator + "__java__.oct"); + } + + private int ID; + + public OctaveReference(int ID) + { + this.ID = ID; + } + + private native static void doFinalize(int ID); + + protected void finalize() throws Throwable + { + doFinalize(this.ID); + } + + public String toString() + { + return (""); + } + + public int getID() + { + return this.ID; + } + + public Object invoke(Object[] args) + { + //System.out.println("OctaveReference::invoke"); + Octave.doInvoke(this.ID, args); + return null; + } + + public synchronized Object invokeAndWait(Object[] args) + { + //System.out.println("OctaveReference::invokeandWait"); + Octave.invokeAndWait(this, args); + return null; + } +} diff --git a/scripts/java/org/octave/TeXcode.java b/scripts/java/org/octave/TeXcode.java new file mode 100755 --- /dev/null +++ b/scripts/java/org/octave/TeXcode.java @@ -0,0 +1,35 @@ +/** + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; If not, see . + * + * A class to hold a TeX character code -> Unicode translation pair. + * + *

Copyright (c) 2010 Martin Hepperle

+ * + * @author Martin Hepperle + * @version 1.0 + */ +package org.octave; + +public class TeXcode +{ + protected String tex; + protected char ucode; + + public TeXcode ( String t, char u ) + { + tex = t; + ucode = u; + } +} diff --git a/scripts/java/org/octave/TeXtranslator.java b/scripts/java/org/octave/TeXtranslator.java new file mode 100755 --- /dev/null +++ b/scripts/java/org/octave/TeXtranslator.java @@ -0,0 +1,264 @@ +/** + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; If not, see . + * + * + * A primitive TeX character translator. + * Provides methods to translate a subset of TeX symbol strings + * into their aequivalent Unicode representation. + * + * Note that not all Unicode character sets contain all these characters. + * Suitable Windows fonts are e.g.:
+ * - Lucida Sans Unicode
+ * - Arial Unicode MS
+ * - MS Mincho
+ * + *

Copyright (c) 2010 Martin Hepperle

+ * + * @author Martin Hepperle + * @version 1.0 + */ +package org.octave; + +public class TeXtranslator +{ + private TeXcode m_texTable[] = + { + // lower case + new TeXcode ( "alpha", '\u03B1' ), + new TeXcode ( "beta", '\u03B2' ), + new TeXcode ( "gamma", '\u03B3' ), + new TeXcode ( "delta", '\u03B4' ), + new TeXcode ( "epsilon", '\u03B5' ), + new TeXcode ( "zeta", '\u03B6' ), + new TeXcode ( "eta", '\u03B7' ), + new TeXcode ( "theta", '\u03B8' ), + new TeXcode ( "vartheta", '\u03D1' ), + new TeXcode ( "iota", '\u03B9' ), + new TeXcode ( "kappa", '\u03BA' ), + new TeXcode ( "lambda", '\u03BB' ), + new TeXcode ( "mu", '\u03BC' ), + new TeXcode ( "nu", '\u03BD' ), + new TeXcode ( "xi", '\u03BE' ), + new TeXcode ( "pi", '\u03C0' ), + new TeXcode ( "rho", '\u03C1' ), + new TeXcode ( "sigma", '\u03C3' ), + new TeXcode ( "varsigma", '\u03C2' ), + new TeXcode ( "tau", '\u03C4' ), + new TeXcode ( "phi", '\u03C6' ), + new TeXcode ( "chi", '\u03C7' ), + new TeXcode ( "psi", '\u03C8' ), + new TeXcode ( "omega", '\u03C9' ), + new TeXcode ( "upsilon", '\u03C5' ), + // upper case + new TeXcode ( "Gamma", '\u0393' ), + new TeXcode ( "Delta", '\u0394' ), + new TeXcode ( "Theta", '\u0398' ), + new TeXcode ( "Lambda", '\u039B' ), + new TeXcode ( "Pi", '\u03A0' ), + new TeXcode ( "Xi", '\u039E' ), + new TeXcode ( "Sigma", '\u03A3' ), + new TeXcode ( "Upsilon", '\u03A5' ), + new TeXcode ( "Phi", '\u03A6' ), + new TeXcode ( "Psi", '\u03A8' ), + new TeXcode ( "Omega", '\u03A9' ), + // complex + new TeXcode ( "Im", '\u2111' ), + new TeXcode ( "Re", '\u211c' ), + // special + new TeXcode ( "leq", '\u2264' ), + new TeXcode ( "geq", '\u2265' ), + new TeXcode ( "neq", '\u2260' ), + new TeXcode ( "pm", '\u00B1' ), + new TeXcode ( "infty", '\u221E' ), + new TeXcode ( "partial", '\u2202' ), + new TeXcode ( "approx", '\u2248' ), + new TeXcode ( "circ", '\u2218' ), + new TeXcode ( "bullet", '\u2022' ), + new TeXcode ( "times", '\u00D7' ), + new TeXcode ( "sim", '\u007E' ), + new TeXcode ( "nabla", '\u2207' ), + new TeXcode ( "ldots", '\u2026' ), + new TeXcode ( "exists", '\u2203' ), + new TeXcode ( "neg", '\u00AC' ), + new TeXcode ( "aleph", '\u2135' ), + new TeXcode ( "forall", '\u2200' ), + new TeXcode ( "cong", '\u2245' ), + new TeXcode ( "wp", '\u2118' ), + new TeXcode ( "propto", '\u221D' ), + new TeXcode ( "otimes", '\u2297' ), + new TeXcode ( "oplus", '\u2295' ), + new TeXcode ( "oslash", '\u2298' ), + new TeXcode ( "cap", '\u2229' ), + new TeXcode ( "cup", '\u222A' ), + new TeXcode ( "ni", '\u220B' ), + new TeXcode ( "in", '\u2208' ), + new TeXcode ( "div", '\u00F7' ), + new TeXcode ( "equiv", '\u2261' ), + new TeXcode ( "int", '\u222B' ), + new TeXcode ( "perp", '\u22A5' ), + new TeXcode ( "wedge", '\u2227' ), + new TeXcode ( "vee", '\u2228' ), + // sets + new TeXcode ( "supseteq", '\u2287' ), + new TeXcode ( "supset", '\u2283' ), + new TeXcode ( "subseteq", '\u2286' ), + new TeXcode ( "subset", '\u2282' ), + // cards + new TeXcode ( "clubsuit", '\u2663' ), + new TeXcode ( "spadesuit", '\u2660' ), + new TeXcode ( "heartsuit", '\u2665' ), + new TeXcode ( "diamondsuit", '\u2666' ), + new TeXcode ( "copyright", '\u00A9' ), + // arrows + new TeXcode ( "leftarrow", '\u2190' ), + new TeXcode ( "uparrow", '\u2191' ), + new TeXcode ( "rightarrow", '\u2192' ), + new TeXcode ( "downarrow", '\u2193' ), + new TeXcode ( "leftrightarrow", '\u2194' ), + new TeXcode ( "updownarrow", '\u2195' ), + }; + + public TeXtranslator () + { + /* DEBUG: output table to file + try + { + java.io.PrintWriter pwTeX = new java.io.PrintWriter ( "z:/tex.txt", + "UTF-8" ); + java.io.PrintWriter pwHTML = new java.io.PrintWriter ( "z:/html.txt", + "UTF-8" ); + java.io.PrintWriter pwOctave = new java.io.PrintWriter ( "z:/octave.txt", + "UTF-8" ); + pwOctave.print ( "msgbox ( [" ); + int i = 0; + for ( int k = 0; k < m_texTable.length; k++ ) + { + if ( i++ == 0 ) + { + pwTeX.print ( "@item " ); + pwHTML.print ( "@item " ); + pwOctave.print ( " '" ); + } + else + { + pwTeX.print ( "@tab " ); + pwHTML.print ( "@tab " ); + pwOctave.print ( " " ); + } + pwTeX.println ( "\\" + m_texTable[k].tex ); + pwTeX.println ( "@tab '@math{\\" + m_texTable[k].tex + "}'" ); + pwHTML.println ( "\\" + m_texTable[k].tex ); + pwHTML.println ( "@tab '" + m_texTable[k].ucode + "'" ); + pwOctave.print ( "\\\\" + m_texTable[k].tex+" " ); + pwOctave.print ( " = ''\\" + m_texTable[k].tex + " ''" ); + if ( i == 3 ) + { + pwTeX.println ( "@c ----------" ); + pwHTML.println ( "@c ----------" ); + pwOctave.println ( "', 10, ..." ); + i=0; + } + else + { + pwTeX.println ( "@tab" ); + pwHTML.println ( "@tab" ); + pwOctave.print ( " " ); + } + } + pwOctave.print ( "']);" ); + pwTeX.close (); + pwHTML.close (); + pwOctave.close (); + } + catch ( Exception e ) + { + ; + } + /* */ + } + + + /* + NOT YET TRANSLATED + o + rfloor + lceil + lfloor + cdot + prime + 0 + rceil + surd + mid + varpi + langle + rangle + */ + + public String replace ( String s ) + { + StringBuffer sb = new StringBuffer ( s ); + // append trailing blank + sb.append ( ' ' ); + + int i = 0; + do + { + /* 26 08 2010 MH szatt search at index i */ + i = sb.indexOf ( "\\", i ); + if ( i > -1 ) + { + int j = sb.indexOf ( " ", i ); + if ( j > i ) + { + String token = sb.substring ( i + 1, j ); + + for ( int k = 0; k < m_texTable.length; k++ ) + { + if ( m_texTable[k].tex.equals ( token ) ) + { + sb.replace ( i, j + 1, + Character.toString ( m_texTable[k].ucode ) ); + break; + } + } + if ( sb.charAt ( i ) == '\\' ) + { + // backslash sztill there: not found + if ( sb.charAt ( i + 1 ) == 'n' ) + { + // newline + sb.replace ( i, i + 2, "\n" ); + } + else if ( sb.charAt ( i + 1 ) == '\\' ) + { + // backslash + sb.replace ( i, i + 2, "\\" ); + } + } + /* 26 08 2010 MH + advance i to avoid deadlock in case of incorrect escape + sequences like \\\\alpha (double backslash) or + \\bogus (unknown escape sequence) + */ + i++; + } + } + } + while ( i > -1 ); + // finall: remove trailing blank + return ( sb.substring ( 0, sb.length () - 1 ).toString () ); + } +} diff --git a/scripts/java/org/octave/images/error.png b/scripts/java/org/octave/images/error.png new file mode 100755 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..75fe9106973d938e3b7849f7dd1916dd674d72ba GIT binary patch literal 1205 zc$~#ji%(Nm82@hHrEP3Qy0)-!A#513AZ3sdWbwA;O=Zxs&^SP7s2~Oq#EDwrQen_y zT`_B*KwQUbz)%@knA;%UATKA$B%{jIMbw!v#~gE8(j|klB$BxDSSu)8>3ryei92#nP$HR;L75gT*psXSJtJN>WtNg>Q0o@T0m1; zZMKjZl_g~sgQcYOWX%mr5&%Kx=<`xm0SpGi69A!5h}digz~=ywk&!PTy4U@RI zGXP#py1P+G2x@6THrqJB7ue!2VWCc^TLEx5 z90xB!WF%|y>hGF|7r1`U_k&*2{aJ*(GnNK3 zGqNv{x{(>eO47D(uxp0d02bj3~ZI!3LJ#Yhr3P7^GB!ggM70Z!N@O_fZ9N zv-MSZy?b1NJzYH0M6BRw#p1o3csc3S=pDP`k6&vNd@Ev2WF8NjTYpNh1X)$PCU(h;%!QXNZs(%BTxXlvq&S1;TvO1YY9 tr|Bk1k0^TUPu$}keX609HU?2N0Ws;HWLGTB1>ra@ocD)4hB}-f* zN`mv#O3D+9QW+dm@{>{(JaZG%Q-e|yQz{EjrrIztFop&Agt+opuugf?>V4mM=G$)h zDLi5soEm!t=DzE1dsQkJ!0vKSyWwTNNFqnVV{i5C{Jb`-7I$R3URCMe5^j1~l>aok z|8>LC_cKjyODas`(LODxb6zm@Nr2o0p2=@oA|5(!{J7lho^I`nZ1o-dQq^4U_w<*& zpVjfI!sxcR`#rtbNA60CdA;r%l{`ya`(e?vHyxo5?JJ+BmpxD6b72d5U@hRsrm~i= z^<`=BLz|LkN$R`!B?>reUS#QB6H=JLE8V~y_sE0CidAVoZ^5$|y<0*B&tkRD3T8hI zce$Ghsv%lPg9N|J@|18ZO-{LUMgPigS21 zj|vn%i<6(sll~+)@{yD32L8~8cI!VbvAwGd4FA8I&3*%^qLLuL;Q#an3^mtJzW~N> zsi%u$NX4xrjU@sMECS3+*?^=Svx?D5OVqaUOg1RQ?wa7+-mbloIn`tfXFs(NVL z(0J7-@OH1I(0WD&#+K_0!tTonZ%1;WsF8UxM5k$k zz3(M^{~3}{jcqqnKFTE8f;HZ2IWpmq?t#+>JFYV{FdWKvu!(lurtohH2hah$2~R%@ z3Leb|nPIMAF#WWW#D0(o_Zj@+{h1^Gfb`cf|G6Y8^07Tp5u~VLzH96328bFq{Zc_w zu$q5Nt%^ERG=)K$T@EnF=`u2@3OO(Y#w=lE5jYBQe##=-CC-aVpw3Tt>b>E)*lDQq z4`^tI9`1}31v}qfHe#liQRHKPPoQB6`Wl-z7`}X9%AnBjLHdEfx#ZxG$lk{-#7cq7hv==c)I$ztaD0e0su9Tqz(W8 diff --git a/scripts/java/org/octave/images/octave.png b/scripts/java/org/octave/images/octave.png new file mode 100755 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..030f44d2584ef9f0cfaec03d68ebd16642fe1302 GIT binary patch literal 1463 zc$^(m2~<-@6n+0gAcUlXEV5Wl5fDL95ELrq{78t2Y+(zF6ax}A2`IAb@gPWLvn(Ql zwU%(iMoIxwR6xW)0izXK(c)56h=@wvSZkwX`stiA^UlnBGxxsx<`waMcQ9yXGyq`m zxa3R1vUZQldpno;WH_ z6d;O<$=-ic54Pp1e zry}rpvsa2Bc+Tt~33_q^dBRZzmY@|65N#B}@Vwn&1T!-bG0TWRz#g~AL0JALd<=nC z2W1+8Z9K5&4U!RY2x-hA*pLQ$rosLM%&XSMB5N@+mLSa!B;o?}%^F4_;LYe3AaFVY zum8~*N8tN3t{&n07hz*PbUoJbLvZk2YBQo|ASj(Pi$|bR!SqM)o1#V|YAMnt$vB9! zWe98{A>@kvUi5_oxmF-(c@I~|p&KzH5x75vhaU{GP~3C3JpdZlcx+Zs)}v^J!p456 zl{*}BG9Ls2fsfDNIZK~9E~O;cngEATc*twYNK(Hh#@_utFc7PaB_*lX3pkB{^$8^j zDJi!GB8?l*8z(-S=+niM)P#KKt^Ht~LQ{{RpKe-MFxui=nqbx(Tc7iUSr;;-46-(A zoLsv>+)F0|nlie4qs$_@t68h)Sg)R*3S!>i5~%B7M9YJh*-ZAR6KDhidUl^OC^xC2Hhw>DkF;cyuCySxl`Fz;8?8c5}O%v_VS zw!wav+Ghm?90(lflmw-t!nS~Z*0DNU`E9xqA3fCDTglu; z(xpn7oK-P(N249{WtEM(23OjDS#zb!NfBV}s~?sN(SO_-qv5t83yQ7EW#zo;jF{+* z&!ToZ`5PNg`e|z!lB`~~=NWNrJ8>gJ%h?y399)kTzMxF!8(Pj}VVZjR2iv}(aamDq zwVAmAl5?#^S%os*SsM4qj#XtqUUs?QV1~Kgq8$D*M}K^$ey?Mg>n-c*V!{r0n;F#v zQq6U@<;x~4{QNWhuNCG}c|4vd;Y18Sew$%-^)K07h9bYtPk~a;x8%sUUrK2>LteT7GA8N zISaj?DP_+caUGY!PSyXfb6N2=p)JlM`cmqgnw{c}_7jl5tR(}V;4eW7^?_Z9r>!hI{r0BJaGkSP}b zysN&e-F~&nOEc}T0XWfA-V}AlopftDc)m(4q3Y-q74D-E*xE7^mmWcbnekE;+%l`S zUl7tvsIydnAfMq%huvy7gJl#TREQT6E9)YK7omFkE)`N^43Ri+^$h}F1K iN#O48R#sN-o`7k=qr&T7xzciAY4ALK+0EO9dH(_6kXd;E diff --git a/scripts/java/org/octave/images/question.png b/scripts/java/org/octave/images/question.png new file mode 100755 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..3098763a86700200907fe01a2adb0b8820ee6451 GIT binary patch literal 1778 zc$~#ljX%{_7=NyN>Ed2)ADdLG?q*Fj(_N+6+Sb(zw~>#~(#xdVDy^v-p;hYVEu>JA zmn7vS8;Q|XRIay$66$J9tD8cM66Gc7yWibEvGaM(dCupY=lP!R`JR_ZXD551!4v}` z60VRfb78%dtztfxZR3|lD_O_eX1mgss37{l*s3_~G0H$Mvk3J5%Lf8?hyBUV4;if+NreJsv;0@RTy6B2zj%S=!ycGo zW5I6E0-sHVzVf0yo0WcBt^{nox_4X2FJ7hlwqM`Bcxc;+u(r7H zzvCkwo{H2Y9C@4=)t+?pX>v@*>DaE6<6UP?bf?Dkq@Cj zt`*_>W!zArtQe}RC@(?9HB?Z)+N8ufqRPAwYh(0B_?w{f=~ z>IO77;(inUyoVMwTAR`KCmyum?^Zng3y<2Md4Tpuc%s46$LMHB=M!{2MRzB9p5dQv z^!A|dA3X0v|8u;2fq{Mu4&c=whF)WM2qVK79l@JXjE!M@9Pi$NEivvrhuLFb_P98? z;{PpVqwBDZNT*}PGF!L3De`Q4?x~W)!F9QcG@-7e*z=BfW^mqgF=N)K>sY5=-P%$l zlCE7lS#D$!C%7d0x?~?i6%w)iDyRE3G7A^3~=4WI`%NlL+(wG)entt$Tq8{-?PLpg3=m*V{zRvc}X{PI(%}yIF zD6dgdC9$bHne_CWMNv`3#S<1snbc%RtvLQ^`Yi%>;SG9{(qMtY*WYK$R{ww@e*OEN z!}Cs7$=UC2leOyM;mH~G)%Dd6%gck3S|b-9|I}P{%fV&BJuRv?lM^@Jy)0x}VVv)e zyh-7bM)DAFNr!)$Q!*r8EGaGQUn)@ewa4T-L{;u&0Us-Z($mc)Go`Oe7kybe(?ahr z1H-6IT7eW(=&tcRCM+!MQT4s~tw!M-;)J$Q#JHv99V`9isj2?{N~M^4vay-V6Geye zd`MPi;#^jC$iR7VBQIAgK;9k=f1zrcS!}A5+pCyLBIy+&B~zqBF>ieYNBQ4oQ}k>q zg#AU;+q7hAj)^QtNS(E^Yufzhy#gb<2)hXV79ktSLb_4~t$(YXvf}pIzB!Zf&D-C0 z%zrtBMYa)A=F&B$UzCYC{)rs-^oe37Kb)hctriIib}bv%k688QOHF>HS+lw3wVCb$Su-z-GgY?4r^`4x@^JUfpR`JUF5PHylK-=+n@OrRw=v9`k)su0yVNOu zL&0<&W4N%`b0a@rX)2e;+O07bNfY%HM>=<#ld+DQ+p~3&P1zIpVoNP%Gp`8oMRwz-jX>xl)c0%QoSm6Irclo*~dpKmOCxWTjCk~FUDV` AV*mgE diff --git a/scripts/java/org/octave/images/warning.png b/scripts/java/org/octave/images/warning.png new file mode 100755 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..3c7edfb31faf7dba138ec6d3014dfa4bd91dbb8d GIT binary patch literal 1508 zc$~$Qi&Ila6o>cTn*+MYQbuGh=@`}Ml_;r6|F_9)u93*xw*H?U(ub}bLPyM^V{#t+1*33 z$W0uU0}BAa3EwP@h8~AoY>h!%6>{_NPz#y$>;+~fS6C>yL_(2NAwhZo5CTBD*%JNg4NRdi zF;s3YHBT@}>LfuSZSClsiDo7_WA`wEVgv@#Cmz$v%Bb$k=h@jOLi~5FC_%9aie<9Uj#Z)qgP76G17NE56xwwWnln z9N8Fznk)!G+5P?m^4Q+`)%xjkj!KQbdAmlXwmDr7;f2SmQKM;t(X=!~$~0MmDk`C6 z9Qej|o?y%x6R-SYKWkj8Yi7-vJg*Pi&&(-*Jin;5&HnyF>r36JVM1UuGoqrgwst0* z)Yv_BHFSB|(UCFK|GPi{eX9xpY-hMMczfZg`KQ|Y z#_r&$kWJ^D0gdaAO*__5a-RSbcPm36MfHzB)$Zbugfxo+Y@> z)9Z_iUv1A>jW+kq#1GSJ4rmn?IaEPu0u+mon3=Y zo;Ee$Sy&?ksPzEgv~e5F9g- zAMX@WjtJ=(4w4;`nmn*M3BYdNA9V~I8MQg1D`fPeQwua?#&k^`4cseV*nP@UB5 z*4JLz;J5%es^Pz<{q>?#wl(b-W47pA&BpbY{ED;S*egyoeSYOxTzw5QS{ILAd8%r5 zOBpI@b%2*eSkF6)xkcg5o4-bUD}NS@f}kM!0p4B@Ity~TkNGuL*NGJsD_dmtspq@8 zMs{daf>nKuLRc#J{%%x3WTpq46_$6}i+8?jBvy9h!JTW(0+{{aZ+x9=+e7_3j8i^2 zxfbaGLRMH@6`aD+!=Wo~{LQS{6Z-?cdJrBODeaIX75oP~Ex-c+ diff --git a/scripts/java/questdlg.m b/scripts/java/questdlg.m new file mode 100644 --- /dev/null +++ b/scripts/java/questdlg.m @@ -0,0 +1,81 @@ +## Copyright (C) 2010 Martin Hepperle +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; If not, see . + +## -*- texinfo -*- +## @deftypefn {Function file} {@var{P} =} questdlg (@var{MESSAGE}, @var{TITLE}) +## @deftypefnx {Function file} @var{P} = questdlg (@var{MESSAGE}, @var{TITLE}, @var{DEFAULT}) +## @deftypefnx {Function file} @var{P} = questdlg (@var{MESSAGE}, @var{TITLE}, @var{BTN1}, @var{BTN2}, @var{DEFAULT}) +## @deftypefnx {Function file} @var{P} = questdlg (@var{MESSAGE}, @var{TITLE}, @var{BTN1}, @var{BTN2}, @var{BTN3}, @var{DEFAULT}) +## +## Displays the @var{MESSAGE} using a question dialog box. +## The dialog contains two or three buttons which all close the dialog. +## It returns the caption of the activated button. +## +## The @var{TITLE} can be used optionally to decorate the dialog caption. +## The string @var{DEFAULT} identifies the default button, +## which is activated by pressing the ENTER key. +## It must match one of the strings given in @var{BTN1}, @var{BTN2} or @var{BTN3}. +## +## If only @var{MESSAGE} and @var{TITLE} are specified, three buttons with +## the default captions "Yes", "No", "Cancel" are used. +## +## If only two button captions @var{BTN1} and @var{BTN2} are specified, +## the dialog will have only these two buttons. +## +## @end deftypefn +## @seealso{errordlg, helpdlg, inputdlg, listdlg, warndlg} + +function ret = questdlg(question,varargin) + + if length(varargin) < 1 + print_usage(); + end + + options{1} = 'Yes'; % button1 + options{2} = 'No'; % button2 + options{3} = 'Cancel'; % button3 + options{4} = 'Yes'; % default + + + switch length(varargin) + case 1 + % title was given + title = varargin{1}; + case 2 + % title and default button string + title = varargin{1}; + options{4} = varargin{2}; % default + case 4 + % title, two buttons and default button string + title = varargin{1}; + options{1} = varargin{2}; % button1 + options{2} = ''; % not used, no middle button + options{3} = varargin{3}; % button3 + options{4} = varargin{4}; % default + case 5 + % title, three buttons and default button string + title = varargin{1}; + options{1} = varargin{2}; % button1 + options{2} = varargin{3}; % button2 + options{3} = varargin{4}; % button3 + options{4} = varargin{5}; % default + otherwise + print_usage(); + end + + + ret = java_invoke ('org.octave.JDialogBox', 'questdlg', question, title, options); + +end diff --git a/scripts/java/warndlg.m b/scripts/java/warndlg.m new file mode 100644 --- /dev/null +++ b/scripts/java/warndlg.m @@ -0,0 +1,36 @@ +## Copyright (C) 2010 Martin Hepperle +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; If not, see . + +## -*- texinfo -*- +## @deftypefn {Function file} {@var{P} =} warndlg (@var{MESSAGE} [,@var{TITLE}]) +## +## Displays the @var{MESSAGE} using a warning dialog box. +## The @var{TITLE} can be used optionally to decorate the dialog caption. +## +## @end deftypefn +## @seealso{helpdlg, inputdlg, listdlg, questiondlg} + +function ret = warndlg(message,varargin) + + switch length (varargin) + case 0 + title = 'Warning Dialog'; + otherwise + title = varargin{1}; + endswitch + + ret = java_invoke ('org.octave.JDialogBox', 'warndlg', message, title); + +endfunction