├── documentation
├── Report.pdf
├── figures
│ ├── jni-flow.pdf
│ ├── sequence.pdf
│ ├── tut1-scr1.png
│ └── tut2-scr1.png
├── Report.bib
├── dirtree.ins
├── dirtree.sty
├── dirtree.tex
├── dirtree.dtx
├── splncs.bst
├── tcilatex.tex
└── Report.tex
├── tutorial1
├── res
│ ├── values
│ │ └── strings.xml
│ └── layout
│ │ └── main.xml
├── project.properties
├── jni
│ ├── Android.mk
│ └── tutorial1.c
├── AndroidManifest.xml
└── src
│ └── com
│ └── android
│ └── tutorial1
│ └── Tutorial1Activity.java
├── tutorial2
├── res
│ ├── values
│ │ └── strings.xml
│ └── layout
│ │ └── main.xml
├── project.properties
├── jni
│ ├── Android.mk
│ └── tutorial2.c
├── AndroidManifest.xml
└── src
│ └── com
│ └── android
│ └── tutorial2
│ └── Tutorial2Activity.java
├── tutorial3
├── res
│ ├── menu
│ │ └── menu.xml
│ ├── values
│ │ └── strings.xml
│ └── layout
│ │ └── main.xml
├── project.properties
├── jni
│ ├── Android.mk
│ └── tutorial3.c
├── src
│ └── com
│ │ └── android
│ │ └── tutorial3
│ │ ├── CustomService.java
│ │ ├── Tutorial3Service.java
│ │ └── Tutorial3Activity.java
└── AndroidManifest.xml
├── .gitignore
└── README
/documentation/Report.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thoeni/ndk-tutorials/HEAD/documentation/Report.pdf
--------------------------------------------------------------------------------
/documentation/figures/jni-flow.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thoeni/ndk-tutorials/HEAD/documentation/figures/jni-flow.pdf
--------------------------------------------------------------------------------
/documentation/figures/sequence.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thoeni/ndk-tutorials/HEAD/documentation/figures/sequence.pdf
--------------------------------------------------------------------------------
/documentation/figures/tut1-scr1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thoeni/ndk-tutorials/HEAD/documentation/figures/tut1-scr1.png
--------------------------------------------------------------------------------
/documentation/figures/tut2-scr1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thoeni/ndk-tutorials/HEAD/documentation/figures/tut2-scr1.png
--------------------------------------------------------------------------------
/tutorial1/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Tutorial1Activity
4 | Call to native
5 | Callback trigger
6 |
7 |
--------------------------------------------------------------------------------
/tutorial2/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Tutorial2Activity
4 | Start the random routine
5 | Stop the random routine
6 |
7 |
--------------------------------------------------------------------------------
/tutorial3/res/menu/menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/tutorial3/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Tutorial2Activity
4 | Start the random routine
5 | Stop the random routine
6 | Start Service
7 | Stop Service
8 | Force init() from Activity
9 |
10 |
--------------------------------------------------------------------------------
/tutorial1/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system edit
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 | #
10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12 |
13 | # Project target.
14 | target=android-16
15 |
--------------------------------------------------------------------------------
/tutorial2/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system edit
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 | #
10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12 |
13 | # Project target.
14 | target=android-16
15 |
--------------------------------------------------------------------------------
/tutorial3/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system edit
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 | #
10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12 |
13 | # Project target.
14 | target=android-16
15 |
--------------------------------------------------------------------------------
/tutorial1/res/layout/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
15 |
16 |
18 |
19 |
--------------------------------------------------------------------------------
/tutorial2/res/layout/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
15 |
16 |
18 |
19 |
--------------------------------------------------------------------------------
/tutorial1/jni/Android.mk:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2009 The Android Open Source Project
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | #
15 | LOCAL_PATH:= $(call my-dir)
16 |
17 | include $(CLEAR_VARS)
18 |
19 | LOCAL_MODULE := tutorial1
20 | LOCAL_CFLAGS := -Werror
21 | LOCAL_SRC_FILES := tutorial1.c
22 | LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog
23 |
24 | include $(BUILD_SHARED_LIBRARY)
25 |
--------------------------------------------------------------------------------
/tutorial2/jni/Android.mk:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2009 The Android Open Source Project
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | #
15 | LOCAL_PATH:= $(call my-dir)
16 |
17 | include $(CLEAR_VARS)
18 |
19 | LOCAL_MODULE := tutorial2
20 | LOCAL_CFLAGS := -Werror
21 | LOCAL_SRC_FILES := tutorial2.c
22 | LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog
23 |
24 | include $(BUILD_SHARED_LIBRARY)
25 |
--------------------------------------------------------------------------------
/tutorial3/jni/Android.mk:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2009 The Android Open Source Project
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | #
15 | LOCAL_PATH:= $(call my-dir)
16 |
17 | include $(CLEAR_VARS)
18 |
19 | LOCAL_MODULE := tutorial3
20 | LOCAL_CFLAGS := -Werror
21 | LOCAL_SRC_FILES := tutorial3.c
22 | LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog
23 |
24 | include $(BUILD_SHARED_LIBRARY)
25 |
--------------------------------------------------------------------------------
/tutorial3/src/com/android/tutorial3/CustomService.java:
--------------------------------------------------------------------------------
1 | package com.android.tutorial3;
2 |
3 | import android.util.Log;
4 |
5 | public class CustomService extends Tutorial3Service {
6 |
7 | static final String TAG = "CustomService";
8 |
9 | @Override
10 | public void callback1() {
11 | // super.callback1();
12 | Log.d(TAG, "callback1() executed.");
13 | }
14 |
15 | @Override
16 | public int callback2(int param0, float param1, String param2) {
17 | Log.d(TAG, "callback2(int, float, String) executed: int "+param0+", float "+param1+", String "+param2);
18 | // return super.callback2(param0, param1, param2);
19 | return 0;
20 | }
21 |
22 | @Override
23 | public void callback3(String param0) {
24 | // super.callback3(param0);
25 | Log.d(TAG, "callback3(String) executed: String "+param0);
26 | }
27 |
28 | @Override
29 | public float callback4(float param0) {
30 | Log.d(TAG, "callback4(float) executed: float "+param0);
31 | // return super.callback4(param0);
32 | return 0;
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/documentation/Report.bib:
--------------------------------------------------------------------------------
1 | % This file was created with JabRef 2.7b.
2 | % Encoding: UTF-8
3 |
4 | @MISC{marakanajni,
5 | author = {Aleksandar Gargenta},
6 | title = {JNI Reference Example},
7 | month = {Oct.},
8 | year = {2012},
9 | __markedentry = {[thoeni:1]},
10 | url = {http://marakana.com/s/jni_reference,1292/index.html}
11 | }
12 |
13 | @BOOK{learningandroid,
14 | title = {Learning Android},
15 | publisher = {O'Reilly},
16 | year = {2011},
17 | author = {Gargenta, M.},
18 | owner = {thoeni},
19 | timestamp = {2012.11.07}
20 | }
21 |
22 | @BOOK{liang1999jni,
23 | title = {The Java Native Interface},
24 | publisher = {Addison-Wesley},
25 | year = {1999},
26 | author = {Liang, S},
27 | isbn = {0-201-32577-2},
28 | url = {http://books.google.it/books?id=NFnBRcu8DHEC}
29 | }
30 |
31 | @BOOK{programmingandroid,
32 | title = {Programming Android},
33 | publisher = {O'Reilly},
34 | year = {2011},
35 | author = {Mednieks and Dornin and Meike and Nakamura},
36 | owner = {thoeni},
37 | timestamp = {2012.11.07}
38 | }
39 |
40 |
--------------------------------------------------------------------------------
/tutorial3/res/layout/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
24 |
25 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/documentation/dirtree.ins:
--------------------------------------------------------------------------------
1 | %% `dirtree.ins.ins'
2 | %%
3 | %% Docstrip installation instruction file for docstyle `dirtree'
4 | %%
5 | %% Jean-C\^ome Charpentier (jcc)
6 | %%
7 | %% January 25, 2006
8 |
9 | \def\batchfile{dirtree.ins}
10 | \input docstrip.tex
11 | \keepsilent
12 | \Msg{*** Generating the `dirtree' package ***}
13 | \askforoverwritefalse
14 | \generate{\file{dirtree.tex}{\from{dirtree.dtx}{tex}}}
15 | \generate{\file{dirtree.sty}{\from{dirtree.dtx}{latex-wrapper}}}
16 | %
17 | \ifToplevel{%
18 | \Msg{***********************************************************}
19 | \Msg{*}
20 | \Msg{* To finish the installation you have to move the files}
21 | \Msg{* dirtree.sty and dirtree.tex in a directory/folder searched by TeX.}
22 | \Msg{*}
23 | \Msg{* To produce the documentation, run the file `dirtree.dtx'}
24 | \Msg{* through LaTeX.}
25 | \Msg{*}
26 | \Msg{* If you require the commented code, desactivating the}
27 | \Msg{* OnlyDescription macro, you must recompile, execute:}
28 | \Msg{* `makeindex -s gind.ist dirtree'}
29 | \Msg{* `makeindex -s gglo.ist -o dirtree.gls dirtree.glo'}
30 | \Msg{* and recompile.}
31 | \Msg{*}
32 | \Msg{***********************************************************}
33 | }
34 |
35 | \endinput
36 | %%
37 | %% End of file `dirtree.ins'
38 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | tutorial1/.classpath
2 | tutorial1/.project
3 | tutorial1/bin/
4 | tutorial1/build.xml
5 | tutorial1/gen/
6 | tutorial1/libs/
7 | tutorial1/local.properties
8 | tutorial1/obj/
9 | tutorial1/proguard-project.txt
10 | tutorial1/res/drawable-hdpi/
11 | tutorial1/res/drawable-ldpi/
12 | tutorial1/res/drawable-mdpi/
13 | tutorial1/res/drawable-xhdpi/
14 | tutorial2/.classpath
15 | tutorial2/.project
16 | tutorial2/bin/
17 | tutorial2/build.xml
18 | tutorial2/gen/
19 | tutorial2/libs/
20 | tutorial2/local.properties
21 | tutorial2/obj/
22 | tutorial2/proguard-project.txt
23 | tutorial2/res/drawable-hdpi/
24 | tutorial2/res/drawable-ldpi/
25 | tutorial2/res/drawable-mdpi/
26 | tutorial2/res/drawable-xhdpi/
27 | tutorial3/.classpath
28 | tutorial3/.project
29 | tutorial3/bin/
30 | tutorial3/build.xml
31 | tutorial3/gen/
32 | tutorial3/libs/
33 | tutorial3/local.properties
34 | tutorial3/obj/
35 | tutorial3/proguard-project.txt
36 | tutorial3/res/drawable-hdpi/
37 | tutorial3/res/drawable-ldpi/
38 | tutorial3/res/drawable-mdpi/
39 | tutorial3/res/drawable-xhdpi/
40 | tutorial3/.externalToolBuilders/
41 | documentation/Makefile
42 | documentation/Report.aux
43 | documentation/Report.bbl
44 | documentation/Report.bib.bak
45 | documentation/Report.blg
46 | documentation/Report.log
47 | documentation/Report.synctex.gz
48 | tutorial1/lint.xml
49 |
--------------------------------------------------------------------------------
/tutorial3/src/com/android/tutorial3/Tutorial3Service.java:
--------------------------------------------------------------------------------
1 | package com.android.tutorial3;
2 |
3 | import android.app.Service;
4 | import android.content.Intent;
5 | import android.os.IBinder;
6 | import android.util.Log;
7 |
8 | public class Tutorial3Service extends Service {
9 | static final String TAG = "Tutorial3Service";
10 | //Testare questo:
11 | public int recipe;
12 |
13 | @Override
14 | public void onCreate() {
15 | super.onCreate();
16 | init();
17 | Log.d(TAG, "onCreated");
18 | }
19 |
20 | @Override
21 | public int onStartCommand(Intent intent, int flags, int startId) {
22 | Log.d(TAG, "onStarted");
23 | return super.onStartCommand(intent, flags, startId);
24 | }
25 |
26 | @Override
27 | public void onDestroy() {
28 | super.onDestroy();
29 | Log.d(TAG, "onDestroy");
30 | }
31 |
32 | @Override
33 | public IBinder onBind(Intent intent) {
34 | return null;
35 | }
36 |
37 | public native void init();
38 |
39 | public native void foo1();
40 |
41 | public native void foo2();
42 |
43 | public void callback1() {
44 | }
45 |
46 | public int callback2(int param0, float param1, String param2) {
47 | return 0;
48 | }
49 |
50 | public void callback3(String param0) {
51 | }
52 |
53 | public float callback4(final float param0) {
54 | return param0;
55 | }
56 |
57 | //Provare a inizializzare variabili qui sotto..
58 | static {
59 | System.loadLibrary("tutorial3");
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/tutorial1/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
20 |
21 |
25 |
26 |
28 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/tutorial2/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
20 |
21 |
25 |
26 |
28 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/tutorial3/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
20 |
21 |
25 |
26 |
27 |
29 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/README:
--------------------------------------------------------------------------------
1 | ################################# MASTER BRANCH ###############################
2 | Tutorial1: Contains a very basic example of how a JNI callback to a Java Static
3 | method works
4 | Tutorial2: Contains an example to explore some possibilities of JNI callbacks
5 | ran within a native thread, properly attached to the current JVM.
6 | The callbacks go from native code to Android Activity, and interact
7 | with the UI
8 | Tutorial3: Contains an example where the native code calls back to an Android
9 | Service. In this example the Service called "Tutorial3Service" just
10 | loads the native shared library and permits a custom service which
11 | extends it to override callback methods.
12 | ###############################################################################
13 |
14 | The full package consists of 3 tutorials to explore JNI calls into Android
15 | environment, through the ndk development kit.
16 |
17 | How to make it work:
18 |
19 | 0- Clone the tutorials into your folder
20 |
21 | 1- Create a new project in Eclipse from the existing sample source
22 | In Eclipse:
23 | Click File > New Android Project...
24 | Select the Create project from existing source radio button.
25 | Select any API level above Android 1.5
26 | In the Location field, click Browse... and select the proper tutorialX dir.
27 | Click Finish.
28 |
29 | 2- On the command line:
30 | Change to the /tutorials/tutorialX directory.
31 | Run the following command to generate a build.xml file:
32 | android update project -p .
33 | Compile the native code using the ndk-build command.
34 | cd /tutorials/tutorialX
35 | /ndk-build
36 |
37 | 4- In Eclipse: after you launched the emulator, run project as Android App
38 |
--------------------------------------------------------------------------------
/documentation/dirtree.sty:
--------------------------------------------------------------------------------
1 | %%
2 | %% This is file `dirtree.sty',
3 | %% generated with the docstrip utility.
4 | %%
5 | %% The original source files were:
6 | %%
7 | %% dirtree.dtx (with options: `latex-wrapper')
8 | %%
9 | %% IMPORTANT NOTICE:
10 | %%
11 | %% For the copyright see the source file.
12 | %%
13 | %% Any modified versions of this file must be renamed
14 | %% with new filenames distinct from dirtree.sty.
15 | %%
16 | %% For distribution of the original source see the terms
17 | %% for copying and modification in the file dirtree.dtx.
18 | %%
19 | %% This generated file may be distributed as long as the
20 | %% original source files, as listed above, are part of the
21 | %% same distribution. (The sources need not necessarily be
22 | %% in the same archive or directory.)
23 | %%
24 | %% Package `dirtree.dtx'
25 | %% -----------------------------------------------
26 | %% Copyright (C) 2004-2006 Jean-C\^ome Charpentier
27 | %% -----------------------------------------------
28 | %%
29 | %% This work may be distributed and/or modified under the
30 | %% conditions of the LaTeX Project Public License, either version 1.3
31 | %% of this license or (at your option) any later version.
32 | %% The latest version of this license is in
33 | %% http://www.latex-project.org/lppl.txt
34 | %% and version 1.3 or later is part of all distributions of LaTeX
35 | %% version 2003/12/01 or later.
36 | %%
37 | %% See CTAN archives in directory macros/latex/base/lppl.txt.
38 | %%
39 | %% CONTENTS:
40 | %% This work consists of the files dirtree.ins and dirtree.dtx.
41 | %% Derived files are dirtree.tex and dirtree.sty.
42 | %%
43 | %% DESCRIPTION:
44 | %% dirtree is a package displaying directory trees.
45 | %%
46 | \def\fileversion{0.2}
47 | \def\filedate{2006/01/25}
48 | \NeedsTeXFormat{LaTeX2e}[1995/06/01]
49 | \ProvidesPackage{dirtree}[\filedate\space v\fileversion\space
50 | package wrapper for dirtree]
51 | \newcommand*\DT@fromsty{}
52 | \input{dirtree.tex}
53 | \ProvidesFile{dirtree.tex}
54 | [\filedate\space v\fileversion\space `dirtree' (jcc)]
55 | \endinput
56 | %%
57 | %% End of file `dirtree.sty'.
58 |
--------------------------------------------------------------------------------
/tutorial1/src/com/android/tutorial1/Tutorial1Activity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2007 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.android.tutorial1;
18 |
19 | import android.app.Activity;
20 | import android.os.Bundle;
21 | import android.os.Handler;
22 | import android.view.View;
23 | import android.widget.TextView;
24 |
25 | public class Tutorial1Activity extends Activity implements Runnable {
26 |
27 | private TextView output;
28 | private Handler handler;
29 |
30 | public void onCreate(Bundle savedInstanceState) {
31 | super.onCreate(savedInstanceState);
32 | super.setContentView(R.layout.main);
33 | output = (TextView)super.findViewById(R.id.output);
34 | this.handler = new Handler();
35 | }
36 |
37 | @Override
38 | public void onResume() {
39 | super.onResume();
40 | this.handler.post(this);
41 | }
42 |
43 | @Override
44 | public void onPause() {
45 | super.onPause();
46 | //TODO: Check this
47 | this.handler.removeCallbacks(this);
48 | }
49 |
50 | public void button0(View v){
51 | output.setText(foo1("testString"));
52 | }
53 |
54 | public void button1(View v){
55 | foo2();
56 | }
57 |
58 | public void run() {
59 | // this.handler.postDelayed(this, 2000);
60 | }
61 |
62 | public native String foo1(String message);
63 | public native void foo2();
64 |
65 | public void foo3Callback() {
66 | String message = "foo3Callback called back by foo2";
67 | output.setText(message);
68 | }
69 |
70 | static {
71 | System.loadLibrary("tutorial1");
72 | }
73 | }
--------------------------------------------------------------------------------
/tutorial1/jni/tutorial1.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2009 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | // OpenGL ES 2.0 code
18 | #include
19 | #include
20 |
21 | #include
22 | #include
23 | #include
24 |
25 | #define LOG_TAG "tutorial1"
26 | #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
27 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
28 |
29 | jstring Java_com_android_tutorial1_Tutorial1Activity_foo1(JNIEnv* env,
30 | jobject thiz, jstring message) {
31 | //To print out a char* we have to convert the jstring to char*
32 | const char *nativeString = (*env)->GetStringUTFChars(env, message, 0);
33 | LOGI("foo1 called! Input parameter: %s", nativeString);
34 | //Then we have to release the memory allocated for the string
35 | (*env)->ReleaseStringUTFChars(env, message, nativeString);
36 | return (*env)->NewStringUTF(env, "JNI call J2C performed!");
37 | }
38 |
39 | void Java_com_android_tutorial1_Tutorial1Activity_foo2(JNIEnv* env,
40 | jobject thiz) {
41 | LOGI("foo2 called!");
42 | //Get class from the calling object
43 | jclass clazz = (*env)->GetObjectClass(env, thiz);
44 | if (!clazz) {
45 | LOGE("callback_handler: failed to get object Class");
46 | goto failure;
47 | }
48 | //Get the methodID from the class which the calling object belongs
49 | jmethodID method = (*env)->GetMethodID(env, clazz, "foo3Callback", "()V");
50 | if (!method) {
51 | LOGE("callback_handler: failed to get method ID");
52 | goto failure;
53 | }
54 | //Call the method on the calling object, defined by the methodID
55 | (*env)->CallVoidMethod(env, thiz, method);
56 |
57 | failure: return;
58 | }
59 |
--------------------------------------------------------------------------------
/tutorial3/src/com/android/tutorial3/Tutorial3Activity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2007 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.android.tutorial3;
18 |
19 | import android.app.Activity;
20 | import android.content.Intent;
21 | import android.os.Bundle;
22 | import android.os.Handler;
23 | import android.view.Menu;
24 | import android.view.MenuItem;
25 | import android.view.View;
26 |
27 | public class Tutorial3Activity extends Activity implements Runnable {
28 |
29 | static Handler handler;
30 |
31 | // The three following variables have been declared static to be accessed
32 | // from within the static runnable callback methods run() below.
33 | static int int0;
34 | static float float0;
35 | static String string0;
36 |
37 | public void onCreate(Bundle savedInstanceState) {
38 | super.onCreate(savedInstanceState);
39 | super.setContentView(R.layout.main);
40 | // Debug.startMethodTracing();
41 | handler = new Handler();
42 | }
43 |
44 | @Override
45 | public void onResume() {
46 | super.onResume();
47 | handler.post(this);
48 | }
49 |
50 | @Override
51 | public void onPause() {
52 | super.onPause();
53 | handler.removeCallbacks(this);
54 | // Debug.stopMethodTracing();
55 | }
56 |
57 | public void button0(View v) {
58 | foo1();
59 | }
60 |
61 | public void button1(View v) {
62 | foo2();
63 | }
64 |
65 | /*
66 | * Native functions to start the daemon, and stop it.
67 | */
68 |
69 | public native void foo1();
70 |
71 | public native void foo2();
72 |
73 | public void run() {
74 | // handler.postDelayed(this, 2000);
75 | }
76 |
77 | @Override
78 | public boolean onCreateOptionsMenu(Menu menu) {
79 | getMenuInflater().inflate(R.menu.menu, menu);
80 | // return super.onCreateOptionsMenu(menu);
81 | return true;
82 | }
83 |
84 | @Override
85 | public boolean onOptionsItemSelected(MenuItem item) {
86 | Intent intent = new Intent(this, CustomService.class);
87 |
88 | switch (item.getItemId()) {
89 | case R.id.item_start_service:
90 | startService(intent);
91 | return true;
92 | case R.id.item_stop_service:
93 | stopService(intent);
94 | return true;
95 | default:
96 | return false;
97 | }
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/tutorial2/src/com/android/tutorial2/Tutorial2Activity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2007 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.android.tutorial2;
18 |
19 | import android.app.Activity;
20 | import android.os.Bundle;
21 | import android.os.Handler;
22 | import android.view.View;
23 | import android.widget.TextView;
24 |
25 | public class Tutorial2Activity extends Activity implements Runnable {
26 |
27 | private TextView output;
28 | private Handler handler;
29 |
30 | // The three following variables have been declared as global to be
31 | // accessed from within the runnable callback methods run() below.
32 | int int0;
33 | float float0;
34 | String string0;
35 |
36 | public void onCreate(Bundle savedInstanceState) {
37 | super.onCreate(savedInstanceState);
38 | super.setContentView(R.layout.main);
39 | output = (TextView) findViewById(R.id.output);
40 | init();
41 | handler = new Handler();
42 | }
43 |
44 | @Override
45 | public void onResume() {
46 | super.onResume();
47 | handler.post(this);
48 | }
49 |
50 | @Override
51 | public void onPause() {
52 | super.onPause();
53 | // TODO: Check this
54 | handler.removeCallbacks(this);
55 | }
56 |
57 | public void button0(View v) {
58 | foo1();
59 | }
60 |
61 | public void button1(View v) {
62 | foo2();
63 | }
64 |
65 | /*
66 | * Callback methods are declared as static, because we want a native
67 | * function to call them asynchronously, with no reference to the current
68 | * object. Therefore our native functions will rely only on the Activity
69 | * class, and on its static methods.
70 | *
71 | * For each callback method, we declare a (static, for the same reason as
72 | * before) Runnable object, that will be able to interact with the User
73 | * Interface from within the thread call. If we don't pass through this
74 | * mechanism, an exception will be thrown, because by default only the
75 | * generating thread can access to the View object, and not other threads
76 | * (as the *randomCaller wants to do, from native code.
77 | */
78 |
79 | public void callback1() {
80 | System.out.println("callback1 called");
81 | handler.post(callback1Thread);
82 | }
83 |
84 | Runnable callback1Thread = new Runnable() {
85 | @Override
86 | public void run() {
87 | output.setText("callback 1, no params");
88 | }
89 | };
90 |
91 | public int callback2(int param0, float param1, String param2) {
92 | System.out.println("callback2 called, params are: " + param0 + " "
93 | + param1 + " " + param2);
94 | int0 = param0;
95 | float0 = param1;
96 | string0 = param2;
97 | handler.post(callback2Thread);
98 | return 0;
99 | }
100 |
101 | Runnable callback2Thread = new Runnable() {
102 | @Override
103 | public void run() {
104 | output.setText("callback 2, params are: " + int0 + ", " + float0
105 | + ", " + string0);
106 | }
107 | };
108 |
109 | public void callback3(String param0) {
110 | System.out.println("callback 3, param is: " + param0);
111 | string0 = param0;
112 | handler.post(callback3Thread);
113 | }
114 |
115 | Runnable callback3Thread = new Runnable() {
116 | @Override
117 | public void run() {
118 | output.setText("callback 3, param is: " + string0);
119 | }
120 | };
121 |
122 | public float callback4(float param0) {
123 | System.out.println("callback 4, param is: " + param0);
124 | float0 = param0;
125 | handler.post(callback4Thread);
126 | return param0;
127 | }
128 |
129 | Runnable callback4Thread = new Runnable() {
130 | @Override
131 | public void run() {
132 | output.setText("callback 4, param is: " + float0);
133 | }
134 | };
135 |
136 | public void run() {
137 |
138 | }
139 |
140 | public native void init();
141 |
142 | public native void foo1();
143 |
144 | public native void foo2();
145 |
146 | static {
147 | System.loadLibrary("tutorial2");
148 | }
149 | }
150 |
--------------------------------------------------------------------------------
/documentation/dirtree.tex:
--------------------------------------------------------------------------------
1 | %%
2 | %% This is file `dirtree.tex',
3 | %% generated with the docstrip utility.
4 | %%
5 | %% The original source files were:
6 | %%
7 | %% dirtree.dtx (with options: `tex')
8 | %%
9 | %% IMPORTANT NOTICE:
10 | %%
11 | %% For the copyright see the source file.
12 | %%
13 | %% Any modified versions of this file must be renamed
14 | %% with new filenames distinct from dirtree.tex.
15 | %%
16 | %% For distribution of the original source see the terms
17 | %% for copying and modification in the file dirtree.dtx.
18 | %%
19 | %% This generated file may be distributed as long as the
20 | %% original source files, as listed above, are part of the
21 | %% same distribution. (The sources need not necessarily be
22 | %% in the same archive or directory.)
23 | %%
24 | %% Package `dirtree.dtx'
25 | %% -----------------------------------------------
26 | %% Copyright (C) 2004-2006 Jean-C\^ome Charpentier
27 | %% -----------------------------------------------
28 | %%
29 | %% This work may be distributed and/or modified under the
30 | %% conditions of the LaTeX Project Public License, either version 1.3
31 | %% of this license or (at your option) any later version.
32 | %% The latest version of this license is in
33 | %% http://www.latex-project.org/lppl.txt
34 | %% and version 1.3 or later is part of all distributions of LaTeX
35 | %% version 2003/12/01 or later.
36 | %%
37 | %% See CTAN archives in directory macros/latex/base/lppl.txt.
38 | %%
39 | %% CONTENTS:
40 | %% This work consists of the files dirtree.ins and dirtree.dtx.
41 | %% Derived files are dirtree.tex and dirtree.sty.
42 | %%
43 | %% DESCRIPTION:
44 | %% dirtree is a package displaying directory trees.
45 | %%
46 | \def\fileversion{0.2}
47 | \def\filedate{2006/01/25}
48 | \message{`dirtree' v\fileversion, \filedate\space (jcc)}
49 | \edef\DTAtCode{\the\catcode`\@}
50 | \catcode`\@=11
51 | \long\def\LOOP#1\REPEAT{%
52 | \def\ITERATE{#1\relax\expandafter\ITERATE\fi}%
53 | \ITERATE
54 | \let\ITERATE\relax
55 | }
56 | \let\REPEAT=\fi
57 | \expandafter\ifx\csname DT@fromsty\endcsname\relax
58 | \def\@namedef#1{\expandafter\def\csname #1\endcsname}
59 | \def\@nameuse#1{\csname #1\endcsname}
60 | \long\def\@gobble#1{}
61 | \fi
62 | \def\@nameedef#1{\expandafter\edef\csname #1\endcsname}
63 | \newdimen\DT@offset \DT@offset=0.2em
64 | \newdimen\DT@width \DT@width=1em
65 | \newdimen\DT@sep \DT@sep=0.2em
66 | \newdimen\DT@all
67 | \DT@all=\DT@offset
68 | \advance\DT@all \DT@width
69 | \advance\DT@all \DT@sep
70 | \newdimen\DT@rulewidth \DT@rulewidth=0.4pt
71 | \newdimen\DT@dotwidth \DT@dotwidth=1.6pt
72 | \newdimen\DTbaselineskip \DTbaselineskip=\baselineskip
73 | \newcount\DT@counti
74 | \newcount\DT@countii
75 | \newcount\DT@countiii
76 | \newcount\DT@countiv
77 | \def\DTsetlength#1#2#3#4#5{%
78 | \DT@offset=#1\relax
79 | \DT@width=#2\relax
80 | \DT@sep=#3\relax
81 | \DT@all=\DT@offset
82 | \advance\DT@all by\DT@width
83 | \advance\DT@all by\DT@sep
84 | \DT@rulewidth=#4\relax
85 | \DT@dotwidth=#5\relax
86 | }
87 | \expandafter\ifx\csname DT@fromsty\endcsname\relax
88 | \def\DTstyle{\tt}
89 | \def\DTstylecomment{\rm}
90 | \else
91 | \def\DTstyle{\ttfamily}
92 | \def\DTstylecomment{\rmfamily}
93 | \fi
94 | \def\DTcomment#1{%
95 | \kern\parindent\dotfill
96 | {\DTstylecomment{#1}}%
97 | }
98 | \def\dirtree#1{%
99 | \let\DT@indent=\parindent
100 | \parindent=\z@
101 | \let\DT@parskip=\parskip
102 | \parskip=\z@
103 | \let\DT@baselineskip=\baselineskip
104 | \baselineskip=\DTbaselineskip
105 | \let\DT@strut=\strut
106 | \def\strut{\vrule width\z@ height0.7\baselineskip depth0.3\baselineskip}%
107 | \DT@counti=\z@
108 | \let\next\DT@readarg
109 | \next#1\@nil
110 | \dimen\z@=\hsize
111 | \advance\dimen\z@ -\DT@offset
112 | \advance\dimen\z@ -\DT@width
113 | \setbox\z@=\hbox to\dimen\z@{%
114 | \hsize=\dimen\z@
115 | \vbox{\@nameuse{DT@body@1}}%
116 | }%
117 | \dimen\z@=\ht\z@
118 | \advance\dimen0 by\dp\z@
119 | \advance\dimen0 by-0.7\baselineskip
120 | \ht\z@=0.7\baselineskip
121 | \dp\z@=\dimen\z@
122 | \par\leavevmode
123 | \kern\DT@offset
124 | \kern\DT@width
125 | \box\z@
126 | \endgraf
127 | \DT@countii=\@ne
128 | \DT@countiii=\z@
129 | \dimen3=\dimen\z@
130 | \@namedef{DT@lastlevel@1}{-0.7\baselineskip}%
131 | \loop
132 | \ifnum\DT@countii<\DT@counti
133 | \advance\DT@countii \@ne
134 | \advance\DT@countiii \@ne
135 | \dimen\z@=\@nameuse{DT@level@\the\DT@countii}\DT@all
136 | \advance\dimen\z@ by\DT@offset
137 | \advance\dimen\z@ by-\DT@all
138 | \leavevmode
139 | \kern\dimen\z@
140 | \DT@countiv=\DT@countii
141 | \count@=\z@
142 | \LOOP
143 | \advance\DT@countiv \m@ne
144 | \ifnum\@nameuse{DT@level@\the\DT@countiv} >
145 | \@nameuse{DT@level@\the\DT@countii}\relax
146 | \else
147 | \count@=\@ne
148 | \fi
149 | \ifnum\count@=\z@
150 | \REPEAT
151 | \edef\DT@hsize{\the\hsize}%
152 | \count@=\@nameuse{DT@level@\the\DT@countii}\relax
153 | \dimen\z@=\count@\DT@all
154 | \advance\hsize by-\dimen\z@
155 | \setbox\z@=\vbox{\@nameuse{DT@body@\the\DT@countii}}%
156 | \hsize=\DT@hsize
157 | \dimen\z@=\ht\z@
158 | \advance\dimen\z@ by\dp\z@
159 | \advance\dimen\z@ by-0.7\baselineskip
160 | \ht\z@=0.7\baselineskip
161 | \dp\z@=\dimen\z@
162 | \@nameedef{DT@lastlevel@\the\DT@countii}{\the\dimen3}%
163 | \advance\dimen3 by\dimen\z@
164 | \advance\dimen3 by0.7\baselineskip
165 | \dimen\z@=\@nameuse{DT@lastlevel@\the\DT@countii}\relax
166 | \advance\dimen\z@ by-\@nameuse{DT@lastlevel@\the\DT@countiv}\relax
167 | \advance\dimen\z@ by0.3\baselineskip
168 | \ifnum\@nameuse{DT@level@\the\DT@countiv} <
169 | \@nameuse{DT@level@\the\DT@countii}\relax
170 | \advance\dimen\z@ by-0.5\baselineskip
171 | \fi
172 | \kern-0.5\DT@rulewidth
173 | \hbox{\vbox to\z@{\vss\hrule width\DT@rulewidth height\dimen\z@}}%
174 | \kern-0.5\DT@rulewidth
175 | \kern-0.5\DT@dotwidth
176 | \vrule width\DT@dotwidth height0.5\DT@dotwidth depth0.5\DT@dotwidth
177 | \kern-0.5\DT@dotwidth
178 | \vrule width\DT@width height0.5\DT@rulewidth depth0.5\DT@rulewidth
179 | \kern\DT@sep
180 | \box\z@
181 | \endgraf
182 | \repeat
183 | \parindent=\DT@indent
184 | \parskip=\DT@parskip
185 | \DT@baselineskip=\baselineskip
186 | \let\strut\DT@strut
187 | }
188 | \def\DT@readarg.#1 #2. #3\@nil{%
189 | \advance\DT@counti \@ne
190 | \@namedef{DT@level@\the\DT@counti}{#1}%
191 | \@namedef{DT@body@\the\DT@counti}{\strut{\DTstyle{#2}\strut}}%
192 | \ifx\relax#3\relax
193 | \let\next\@gobble
194 | \fi
195 | \next#3\@nil
196 | }
197 | \catcode`\@=\DTAtCode\relax
198 | \endinput
199 | %%
200 | %% End of file `dirtree.tex'.
201 |
--------------------------------------------------------------------------------
/tutorial2/jni/tutorial2.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2009 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | // OpenGL ES 2.0 code
18 |
19 | #include
20 | #include
21 |
22 | #include
23 | #include
24 | #include
25 | #include
26 |
27 | #define LOG_TAG "tutorial2"
28 | #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
29 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
30 |
31 | static JavaVM *gJavaVM;
32 | static jobject gObject;
33 | static jclass gClass;
34 |
35 |
36 | /*
37 | * The enum below is used to switch between the various callback functions.
38 | * Basically the callback will depend on the return type rTYPE and on the presence
39 | * or absence of parameters. In case of parameters presence, a proper jvalue array
40 | * will be used.
41 | */
42 | typedef enum {
43 | JNI_WRAPPER_rVOID = 0,
44 | JNI_WRAPPER_rVOID_p = 1,
45 | JNI_WRAPPER_rINT = 2,
46 | JNI_WRAPPER_rINT_p = 3,
47 | JNI_WRAPPER_rFLOAT = 4,
48 | JNI_WRAPPER_rFLOAT_p = 5
49 | } jniWrapper_t;
50 |
51 | typedef enum {
52 | INT = 0,
53 | FLOAT = 1,
54 | STRING = 2,
55 | } nType;
56 |
57 | typedef struct {
58 | int i;
59 | float f;
60 | char* s;
61 | nType type;
62 | } nvalue;
63 |
64 | typedef struct {
65 | const char* cbName;
66 | const char* cbSignature;
67 | jniWrapper_t jniWrapper;
68 | jmethodID cbMethod;
69 | } callback_t;
70 |
71 | /*
72 | * Declaration of callbacks methods, with regard to the callback_t structure:
73 | */
74 | callback_t cb[] = {
75 | // cb[0]
76 | {
77 | "callback1", "()V", JNI_WRAPPER_rVOID,
78 | },
79 | // cb[1]
80 | {
81 | "callback2", "(IFLjava/lang/String;)I", JNI_WRAPPER_rINT_p,
82 | },
83 | // cb[2]
84 | {
85 | "callback3", "(Ljava/lang/String;)V", JNI_WRAPPER_rVOID_p,
86 | },
87 | // cb[2]
88 | {
89 | "callback4", "(F)F", JNI_WRAPPER_rFLOAT_p,
90 | },
91 | };
92 |
93 | int flag = 1;
94 |
95 | jint JNI_OnLoad(JavaVM* vm, void* reserved)
96 | {
97 | JNIEnv *env;
98 | gJavaVM = vm;
99 | LOGI("JNI_OnLoad called");
100 | if ( (*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) {
101 | LOGE("Failed to get the environment using GetEnv()");
102 | return -1;
103 | }
104 | return JNI_VERSION_1_4;
105 | }
106 |
107 | void
108 | Java_com_android_tutorial2_Tutorial2Activity_init( JNIEnv* env, jobject thiz )
109 | {
110 | LOGI("init native function called");
111 | int status;
112 | int isAttached = 0;
113 | gObject = (jobject)(*env)->NewGlobalRef(env, thiz);
114 | jclass clazz = (*env)->GetObjectClass(env, thiz);
115 | gClass = (jclass)(*env)->NewGlobalRef(env, clazz);
116 | if (!clazz) {
117 | LOGE("callback_handler: failed to get object Class");
118 | goto failure;
119 | }
120 | int i = sizeof cb / sizeof cb[0];
121 | LOGI("getting methodIDs of %d configured callback methods", i);
122 | while(i--) {
123 | LOGI("Method %d is %s with signature %s", i, cb[i].cbName, cb[i].cbSignature);
124 | cb[i].cbMethod = (*env)->GetMethodID(env, clazz, cb[i].cbName, cb[i].cbSignature);
125 | if(!cb[i].cbMethod) {
126 | LOGE("callback_handler: failed to get method ID");
127 | goto failure;
128 | }
129 | }
130 | failure:
131 | return;
132 | }
133 |
134 | /*
135 | * The callStaticMethodWrapper takes as input the int mid number which identifies the callback method
136 | * to be called, the nvalue npar[] array, which contains the input parameters, if any, and the parSize
137 | * which indicates the number of parameters
138 | */
139 |
140 | int callMethodWrapper(JNIEnv* env, int mid, nvalue npar[], int parSize) {
141 | LOGI("callStaticMethodWrapper called for cb[%d] method %s,signature %s,"
142 | "switch case %d", mid, cb[mid].cbName, cb[mid].cbSignature,
143 | cb[mid].jniWrapper);
144 | //Case with parameters:
145 | //Create a jvalue array with the same size of the nvalue array:
146 | jvalue jpar[parSize];
147 | if (parSize > 0) {
148 | //Handle mapping nvalue -> jvalue
149 | int i;
150 | for (i=0; iNewStringUTF(env, npar[i].s);
160 | break;
161 | }
162 | }
163 | }
164 | switch (cb[mid].jniWrapper) {
165 | case JNI_WRAPPER_rVOID:
166 | (*env)->CallVoidMethod(env, gObject, cb[mid].cbMethod);
167 | break;
168 | case JNI_WRAPPER_rINT:
169 | (*env)->CallIntMethod(env, gObject, cb[mid].cbMethod);
170 | break;
171 | case JNI_WRAPPER_rFLOAT:
172 | (*env)->CallFloatMethod(env, gObject, cb[mid].cbMethod);
173 | break;
174 | case JNI_WRAPPER_rVOID_p:
175 | (*env)->CallVoidMethodA(env, gObject, cb[mid].cbMethod, jpar);
176 | break;
177 | case JNI_WRAPPER_rINT_p:
178 | (*env)->CallIntMethodA(env, gObject, cb[mid].cbMethod, jpar);
179 | break;
180 | case JNI_WRAPPER_rFLOAT_p:
181 | (*env)->CallFloatMethodA(env, gObject, cb[mid].cbMethod, jpar);
182 | break;
183 | }
184 | return 0;
185 | }
186 |
187 | /*
188 | * The *randomCaller switches between four callbacks declared above, preparing the input
189 | * parameters needed by each call.
190 | */
191 |
192 | void *randomCaller() {
193 | flag = 1;
194 | JNIEnv *env;
195 | int isAttached = 0;
196 | int status = (*gJavaVM)->GetEnv(gJavaVM, (void **) &env, JNI_VERSION_1_4);
197 | if(status < 0) {
198 | LOGE("callback_handler: failed to get JNI environment, assuming native thread");
199 | status = (*gJavaVM)->AttachCurrentThread(gJavaVM, &env, NULL);
200 | if(status < 0) {
201 | LOGE("callback_handler: failed to attach current thread");
202 | }
203 | isAttached = 1;
204 | }
205 | int i=0;
206 | nvalue v1, v2, v3, npar[3];
207 | while (flag == 1) {
208 | switch(i){
209 | case 0:
210 | i=1;
211 | callMethodWrapper(env, 0, NULL, 0);
212 | break;
213 | case 1:
214 | i=2;
215 | v1.type = INT;
216 | v1.i = 12;
217 | v2.type = FLOAT;
218 | v2.f = 2.3;
219 | v3.type = STRING;
220 | v3.s = "string";
221 | npar[0] = v1;
222 | npar[1] = v2;
223 | npar[2] = v3;
224 | callMethodWrapper(env, 1, npar, 3);
225 | break;
226 | case 2:
227 | i=3;
228 | v1.type = STRING;
229 | v1.s = "test string :)";
230 | npar[0] = v1;
231 | callMethodWrapper(env, 2, npar, 1);
232 | break;
233 | case 3:
234 | i=0;
235 | v1.type = FLOAT;
236 | v1.f = 2.3;
237 | npar[0] = v1;
238 | callMethodWrapper(env, 3, npar, 1);
239 | break;
240 | }
241 | sleep(2);
242 | }
243 | if(isAttached)
244 | (*gJavaVM)->DetachCurrentThread(gJavaVM);
245 | }
246 |
247 | void daemonStart() {
248 | LOGI("daemonStart called!");
249 | pthread_t thread;
250 | char *message = "Thread 1 started!";
251 | int iret;
252 | iret = pthread_create( &thread, NULL, randomCaller, NULL);
253 | }
254 |
255 | /*
256 | * We could have used the jobject below, to access to the view and to public non-static methods,
257 | * but the aim of this tutorial is to sumulate a native thread which can asynchronously interact
258 | * with the Java View, without necessarily being linked to the calling object.
259 | */
260 |
261 | void
262 | Java_com_android_tutorial2_Tutorial2Activity_foo1( JNIEnv* env, jobject thiz)
263 | {
264 | daemonStart();
265 | }
266 |
267 | void daemonStop() {
268 | LOGI("daemonStop called!");
269 | flag = 0;
270 | }
271 |
272 | void
273 | Java_com_android_tutorial2_Tutorial2Activity_foo2( JNIEnv* env, jclass thiz )
274 | {
275 | daemonStop();
276 | }
277 |
--------------------------------------------------------------------------------
/tutorial3/jni/tutorial3.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2009 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | // OpenGL ES 2.0 code
18 |
19 | #include
20 | #include
21 |
22 | #include
23 | #include
24 | #include
25 | #include
26 |
27 | #define LOG_TAG "tutorial3"
28 | #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
29 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
30 |
31 | //Global reference to the caller Java VM
32 | static JavaVM *gJavaVM;
33 |
34 | //Global reference to the caller Class, so that the
35 | //garbage collector won't delete it.
36 | static jclass gClass;
37 |
38 | //Global reference to the caller Object, so that the
39 | //garbage collector won't delete it.
40 | static jobject gObject;
41 |
42 | /*
43 | * The enum below is used to switch between the various callback functions.
44 | * Basically the callback will depend on the return type rTYPE and on the presence
45 | * or absence of parameters. In case of parameters presence, a proper jvalue array
46 | * will be used.
47 | */
48 | typedef enum {
49 | JNI_WRAPPER_rVOID = 0,
50 | JNI_WRAPPER_rVOID_p,
51 | JNI_WRAPPER_rINT,
52 | JNI_WRAPPER_rINT_p,
53 | JNI_WRAPPER_rFLOAT,
54 | JNI_WRAPPER_rFLOAT_p
55 | } jniWrapper_t;
56 |
57 | typedef enum {
58 | INT = 0,
59 | FLOAT,
60 | STRING,
61 | } nType;
62 |
63 | typedef struct {
64 | int i;
65 | float f;
66 | char* s;
67 | nType type;
68 | } nvalue;
69 |
70 | typedef struct {
71 | const char* cbName;
72 | const char* cbSignature;
73 | jniWrapper_t jniWrapper;
74 | jmethodID cbMethod;
75 | } callback_t;
76 |
77 | /*
78 | * Declaration of callbacks methods, with regard to the callback_t structure:
79 | * here we declare the method name, the method signature, and the type of method
80 | * to be called, tipically it will depend on the return type, and the presence
81 | * or absence of input parameters.
82 | */
83 | callback_t cb[] = {
84 | // cb[0]
85 | {
86 | "callback1", "()V", JNI_WRAPPER_rVOID,
87 | },
88 | // cb[1]
89 | {
90 | "callback2", "(IFLjava/lang/String;)I", JNI_WRAPPER_rINT_p,
91 | },
92 | // cb[2]
93 | {
94 | "callback3", "(Ljava/lang/String;)V", JNI_WRAPPER_rVOID_p,
95 | },
96 | // cb[3]
97 | {
98 | "callback4", "(F)F", JNI_WRAPPER_rFLOAT_p,
99 | },
100 | };
101 |
102 | int flag = 1;
103 |
104 | jint JNI_OnLoad(JavaVM* vm, void* reserved)
105 | {
106 | JNIEnv *env;
107 | gJavaVM = vm;
108 | LOGI("JNI_OnLoad called");
109 | if ( (*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) {
110 | LOGE("Failed to get the environment using GetEnv()");
111 | return -1;
112 | }
113 | return JNI_VERSION_1_4;
114 | }
115 |
116 | /********************************
117 | * SERVICE VERSION JNI FUNCTION *
118 | ********************************/
119 |
120 | void
121 | Java_com_android_tutorial3_Tutorial3Service_init( JNIEnv* env, jobject thiz )
122 | {
123 | LOGI("init native function called");
124 | int status;
125 | int isAttached = 0;
126 | gObject = (jobject)(*env)->NewGlobalRef(env, thiz);
127 | jclass clazz = (*env)->GetObjectClass(env, thiz);
128 | gClass = (jclass)(*env)->NewGlobalRef(env, clazz);
129 | if (!clazz) {
130 | LOGE("callback_handler: failed to get object Class");
131 | }
132 | int i = sizeof cb / sizeof cb[0];
133 | LOGI("getting methodIDs of %d configured callback methods", i);
134 | while(i--) {
135 | LOGI("Method %d is %s with signature %s", i, cb[i].cbName, cb[i].cbSignature);
136 | cb[i].cbMethod = (*env)->GetMethodID(env, clazz, cb[i].cbName, cb[i].cbSignature);
137 | if(!cb[i].cbMethod) {
138 | LOGE("callback_handler: failed to get method ID");
139 | }
140 | }
141 | }
142 |
143 | /*
144 | * The callStaticMethodWrapper takes as input the int mid number which identifies
145 | * the callback method to be called, the nvalue npar[] array, which contains the
146 | * input parameters, if any, and the parSize which indicates the number of parameters
147 | */
148 |
149 | int callMethodWrapper(JNIEnv* env, int mid, nvalue npar[], int parSize) {
150 | LOGI("callStaticMethodWrapper called for cb[%d] method %s,signature %s,"
151 | "switch case %d", mid, cb[mid].cbName, cb[mid].cbSignature,
152 | cb[mid].jniWrapper);
153 | //Case with parameters:
154 | //Create a jvalue array with the same size of the nvalue array:
155 | jvalue jpar[parSize];
156 | if (parSize > 0) {
157 | //Handle mapping nvalue -> jvalue
158 | int i;
159 | for (i=0; iNewStringUTF(env, npar[i].s);
169 | break;
170 | }
171 | }
172 | }
173 | switch (cb[mid].jniWrapper) {
174 | case JNI_WRAPPER_rVOID:
175 | (*env)->CallVoidMethod(env, gObject, cb[mid].cbMethod);
176 | break;
177 | case JNI_WRAPPER_rINT:
178 | (*env)->CallIntMethod(env, gObject, cb[mid].cbMethod);
179 | break;
180 | case JNI_WRAPPER_rFLOAT:
181 | (*env)->CallFloatMethod(env, gObject, cb[mid].cbMethod);
182 | break;
183 | case JNI_WRAPPER_rVOID_p:
184 | (*env)->CallVoidMethodA(env, gObject, cb[mid].cbMethod, jpar);
185 | break;
186 | case JNI_WRAPPER_rINT_p:
187 | (*env)->CallIntMethodA(env, gObject, cb[mid].cbMethod, jpar);
188 | break;
189 | case JNI_WRAPPER_rFLOAT_p:
190 | (*env)->CallFloatMethodA(env, gObject, cb[mid].cbMethod, jpar);
191 | break;
192 | }
193 | return 0;
194 | }
195 |
196 | /*
197 | * The *randomCaller switches between four callbacks declared above, preparing the input
198 | * parameters needed by each call.
199 | */
200 |
201 | void *randomCaller() {
202 | flag = 1;
203 | JNIEnv *env;
204 | int isAttached = 0;
205 | int status = (*gJavaVM)->GetEnv(gJavaVM, (void **) &env, JNI_VERSION_1_4);
206 | if(status < 0) {
207 | LOGE("callback_handler: failed to get JNI environment, assuming native thread");
208 | status = (*gJavaVM)->AttachCurrentThread(gJavaVM, &env, NULL);
209 | if(status < 0) {
210 | LOGE("callback_handler: failed to attach current thread");
211 | }
212 | isAttached = 1;
213 | }
214 | int i=0;
215 | nvalue v1, v2, v3, npar[3];
216 | while (flag == 1) {
217 | switch(i){
218 | case 0:
219 | i=1;
220 | callMethodWrapper(env, 0, NULL, 0);
221 | break;
222 | case 1:
223 | i=2;
224 | v1.type = INT;
225 | v1.i = 12;
226 | v2.type = FLOAT;
227 | v2.f = 2.3;
228 | v3.type = STRING;
229 | v3.s = "string";
230 | npar[0] = v1;
231 | npar[1] = v2;
232 | npar[2] = v3;
233 | callMethodWrapper(env, 1, npar, 3);
234 | break;
235 | case 2:
236 | i=3;
237 | v1.type = STRING;
238 | v1.s = "test string :)";
239 | npar[0] = v1;
240 | callMethodWrapper(env, 2, npar, 1);
241 | break;
242 | case 3:
243 | i=0;
244 | v1.type = FLOAT;
245 | v1.f = 2.3;
246 | npar[0] = v1;
247 | callMethodWrapper(env, 3, npar, 1);
248 | break;
249 | }
250 | sleep(2);
251 | }
252 | if(isAttached)
253 | (*gJavaVM)->DetachCurrentThread(gJavaVM);
254 | }
255 |
256 | void daemonStart() {
257 | LOGI("daemonStart called!");
258 | pthread_t thread;
259 | char *message = "Thread 1 started!";
260 | int iret;
261 | iret = pthread_create( &thread, NULL, randomCaller, NULL);
262 | }
263 |
264 | /*
265 | * We could have used the jobject below, to access to the view and to public non-static methods,
266 | * but the aim of this tutorial is to sumulate a native thread which can asynchronously interact
267 | * with the Java View, without necessarily being linked to the calling object.
268 | */
269 |
270 | void
271 | Java_com_android_tutorial3_Tutorial3Activity_foo1( JNIEnv* env, jobject thiz)
272 | {
273 | daemonStart();
274 | }
275 |
276 | void daemonStop() {
277 | LOGI("daemonStop called!");
278 | flag = 0;
279 | }
280 |
281 | void
282 | Java_com_android_tutorial3_Tutorial3Activity_foo2( JNIEnv* env, jclass thiz )
283 | {
284 | daemonStop();
285 | }
286 |
--------------------------------------------------------------------------------
/documentation/dirtree.dtx:
--------------------------------------------------------------------------------
1 | % \iffalse
2 | %%
3 | %% Package `dirtree.dtx'
4 | %% -----------------------------------------------
5 | %% Copyright (C) 2004-2006 Jean-C\^ome Charpentier
6 | %% -----------------------------------------------
7 | %%
8 | %% This work may be distributed and/or modified under the
9 | %% conditions of the LaTeX Project Public License, either version 1.3
10 | %% of this license or (at your option) any later version.
11 | %% The latest version of this license is in
12 | %% http://www.latex-project.org/lppl.txt
13 | %% and version 1.3 or later is part of all distributions of LaTeX
14 | %% version 2003/12/01 or later.
15 | %%
16 | %% See CTAN archives in directory macros/latex/base/lppl.txt.
17 | %%
18 | %% CONTENTS:
19 | %% This work consists of the files dirtree.ins and dirtree.dtx.
20 | %% Derived files are dirtree.tex and dirtree.sty.
21 | %%
22 | %% DESCRIPTION:
23 | %% dirtree is a package displaying directory trees.
24 | %%
25 | % \fi
26 | % \iffalse
27 | % \def\fileversion{0.2}
28 | % \def\filedate{2006/01/25}
29 | %<*driver>
30 | \documentclass{ltxdoc}
31 | \GetFileInfo{dirtree.dtx}
32 | \usepackage[T1]{fontenc}
33 | \usepackage[latin1]{inputenc}
34 | \usepackage{lmodern}
35 | \usepackage[english]{babel}
36 | \usepackage{xcolor}
37 | \usepackage{pstricks}
38 | \usepackage{dirtree}
39 | \newcommand*\package[1]{\textsf{#1}}
40 | \newcommand*\file[1]{\texttt{#1}}
41 | \AtBeginDocument{%
42 | \OnlyDescription % comment out for implementation details
43 | \EnableCrossrefs
44 | \RecordChanges
45 | \CodelineIndex}
46 | \AtEndDocument{
47 | \PrintChanges
48 | \PrintIndex}
49 | \hbadness=7000 % Over and under full box warnings
50 | \hfuzz=3pt
51 | \begin{document}
52 | \DocInput{dirtree.dtx}
53 | \end{document}
54 | %
55 | % \fi
56 | %
57 | % \changes{v0.2}{\filedate}{dtx for CTAN, code for both Plain \TeX{}
58 | % and \LaTeX.}
59 | % \changes{v0.12}{2005/12/20}{\cs{DTbaselineskip}. local \cs{parskip},
60 | % \cs{baselineskip}, and \cs{strut} in order to fix a displaying bug.}
61 | % \changes{v0.11}{2005/12/19}{fix bug}
62 | % \changes{v0.01}{2004/08/10}{First realease to answer a question on
63 | % fctt.}
64 | %
65 | % \DoNotIndex{\@,\@gobble,\@latex@error,\@namedef,\@nameuse}
66 | % \DoNotIndex{\@ne,\@nil}
67 | % \DoNotIndex{\advance}
68 | % \DoNotIndex{\baselineskip,\box}
69 | % \DoNotIndex{\catcode,\count@,\csname}
70 | % \DoNotIndex{\def,\dimen,\dotfill,\dp}
71 | % \DoNotIndex{\edef,\else,\endcsname,\endgraf,\expandafter}
72 | % \DoNotIndex{\fi,\filedate,\fileversion}
73 | % \DoNotIndex{\hbox,\hrule,\hsize,\ht}
74 | % \DoNotIndex{\ifnum,\ifx,\input,\iterate}
75 | % \DoNotIndex{\kern}
76 | % \DoNotIndex{\leavevmode,\let,\long,\loop}
77 | % \DoNotIndex{\m@ne}
78 | % \DoNotIndex{\NeedsTeXFormat,\newcount,\newdimen,\next,\noindent}
79 | % \DoNotIndex{\par,\parindent,\parskip,\ProvidesFile,\ProvidesPackage}
80 | % \DoNotIndex{\relax,\repeat,\rm,\rmfamily}
81 | % \DoNotIndex{\setbox,\space,\strut}
82 | % \DoNotIndex{\the,\tt,\ttfamily}
83 | % \DoNotIndex{\vbox,\vrule,\vss}
84 | % \DoNotIndex{\z@}
85 | % \setcounter{IndexColumns}{2}
86 | %
87 | % \CheckSum{0}
88 | % \CharacterTable
89 | % {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
90 | % Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
91 | % Digits \0\1\2\3\4\5\6\7\8\9
92 | % Exclamation \! Double quote \" Hash (number) \#
93 | % Dollar \$ Percent \% Ampersand \&
94 | % Acute accent \' Left paren \( Right paren \)
95 | % Asterisk \* Plus \+ Comma \,
96 | % Minus \- Point \. Solidus \/
97 | % Colon \: Semicolon \; Less than \<
98 | % Equals \= Greater than \> Question mark \?
99 | % Commercial at \@ Left bracket \[ Backslash \\
100 | % Right bracket \] Circumflex \^ Underscore \_
101 | % Grave accent \` Left brace \{ Vertical bar \|
102 | % Right brace \} Tilde \~}
103 | %
104 | % ................. Beginning of the documentation part .................
105 | %
106 | % \title{The \package{dirtree} package\\Directory Tree}
107 | % \author{Jean-C\^ome
108 | % Charpentier\thanks{\texttt{Jean-Come.Charpentier@wanadoo.fr}}}
109 | % \date{Version \fileversion\ \filedate\ \\
110 | % {\small Documentation revised \today}}
111 | %
112 | % \maketitle
113 | %
114 | % \begin{abstract}
115 | % Package \package{dirtree} allows to display directory tree, like
116 | % in the windows explorator.
117 | % \end{abstract}
118 | %
119 | % \tableofcontents
120 | % \section{Introduction}
121 | % During a discussion on fctt (\texttt{fr.comp.text.tex}) about
122 | % directory tree and how display such a structure, it appeared that
123 | % there wasn't many packages which do the job.
124 | %
125 | % One obvious solution is to use \package{PsTricks} but some people
126 | % don't like or don't know this package, so I made the first release
127 | % of \package{dirtree}.
128 | %
129 | % In fact, I didn't plan to send it in CTAN but Robin Fairbairns and
130 | % Danie was very convincing!
131 | %
132 | % \section{Usage}
133 | % Package \package{dirtree} works both on Plain \TeX{} and \LaTeX{}.
134 | % No surprise to call it:
135 | % \begin{verbatim}
136 | % \usepackage{dirtree}
137 | % \end{verbatim}
138 | % for \LaTeX{} (no option available) and
139 | % \begin{verbatim}
140 | % \input dirtree
141 | % \end{verbatim}
142 | % for Plain \TeX{}.
143 | %
144 | % \begin{DescribeMacro}{\dirtree}
145 | % The main macro is |\dirtree| which take one argument (the tree
146 | % structure). This tree structure is a sequence of
147 | % \begin{verbatim}
148 | % ..
149 | % \end{verbatim}
150 | % Note that there is a dot in the beginning and another one at the end
151 | % of each node specification. The spaces are very important: if you
152 | % forgot the space before the |level| there will be an error and if
153 | % you forgot the space after the last dot, you don't indicate the end
154 | % of the node. Since an end of line is like a space for \TeX{}, I
155 | % recommand to write a node per line in the source file: it's handy
156 | % and more readeable.
157 | %
158 | % The |level| indicates the node depth in the tree. There is two
159 | % rules you must respect:
160 | % \begin{enumerate}
161 | % \item The root must have the level one.
162 | % \item When you create a node, if the last node have the level $n$,
163 | % the created node must have a level between 2 and $n+1$.
164 | % \end{enumerate}
165 | % In fact, you can indicates a level greater than $n+1$ if one node
166 | % have a level $n$ somewhere in the tree but the result will be
167 | % strange!
168 | %
169 | % A node of level $n$ will be connected to the last node defined which
170 | % has a level lesser or equal to $n$.
171 | %
172 | % For example, the code
173 | % \begin{verbatim}
174 | % \dirtree{%
175 | % .1 /.
176 | % .2 bin.
177 | % .2 home.
178 | % .3 jeancome.
179 | % .4 texmf.
180 | % .5 tex.
181 | % .6 latex.
182 | % .7 dirtree.
183 | % .3 jeancomeson.
184 | % .3 jeancomedaughter.
185 | % .2 usr.
186 | % .3 bin.
187 | % .3 games.
188 | % .4 fortunes.
189 | % .3 include.
190 | % .3 local.
191 | % .4 bin.
192 | % .4 share.
193 | % .5 texmf.
194 | % .6 fonts.
195 | % .6 metapost.
196 | % .6 tex.
197 | % .3 share.
198 | % }
199 | % \end{verbatim}
200 | % give the result
201 | % \dirtree{%^^A
202 | % .1 /.
203 | % .2 bin.
204 | % .2 home.
205 | % .3 jeancome.
206 | % .4 texmf.
207 | % .5 tex.
208 | % .6 latex.
209 | % .7 dirtree.
210 | % .3 jeancomeson.
211 | % .3 jeancomedaughter.
212 | % .2 usr.
213 | % .3 bin.
214 | % .3 games.
215 | % .4 fortunes.
216 | % .3 include.
217 | % .3 local.
218 | % .4 bin.
219 | % .4 share.
220 | % .5 texmf.
221 | % .6 fonts.
222 | % .6 metapost.
223 | % .6 tex.
224 | % .3 share.
225 | % }
226 | %
227 | % Note the |%| after the left brace in the beginning: it's important
228 | % because the first character encountered must be a dot.
229 | %
230 | % \begin{DescribeMacro}{\DTstyle}
231 | % A text node is typeset with the command |\DTstyle|. Its default
232 | % value is |\ttfamily| when you are under \LaTeX{} and |\tt| when you
233 | % are under Plain \TeX{}. You can redefine this macro as you want,
234 | % it is used with the syntax |{\DTstyle{text node}}|, so you can use
235 | % both |\ttfamily| and |\texttt| for example.
236 | % \end{DescribeMacro}
237 | %
238 | % \begin{DescribeMacro}{\DTcomment}
239 | % The |\DTcomment| command allows to put text at the right side, with
240 | % leaders. The syntax is
241 | % \begin{verbatim}
242 | % \DTcomment{comment text}
243 | % \end{verbatim}
244 | % \begin{DescribeMacro}{\DTstylecomment}
245 | % The style of comment is defined by |\DTstylecomment|. Its default
246 | % value is |\rmfamilly| under \LaTeX{} and |\rm| under Plain \TeX{},
247 | % and it acts like |\DTstyle|.
248 | % Here is an example: the code
249 | % \begin{verbatim}
250 | % \renewcommand*\DTstylecomment{\rmfamily\color{green}\textsc}
251 | % \renewcommand*\DTstyle{\ttfamily\textcolor{red}}
252 | % \dirtree{%
253 | % .1 /.
254 | % .2 bin.
255 | % .2 home.
256 | % .3 jeancome.
257 | % .4 texmf.
258 | % .5 tex.
259 | % .3 jeancomeson\DTcomment{Guillaume}.
260 | % .3 jeancomedaughter\DTcomment{Mathilde}.
261 | % .2 usr.
262 | % .3 bin.
263 | % }
264 | % \end{verbatim}
265 | % give the result
266 | % \begingroup
267 | % \renewcommand*\DTstylecomment{\rmfamily\color{green}\textsc}
268 | % \renewcommand*\DTstyle{\ttfamily\textcolor{red}}
269 | % \dirtree{%^^A
270 | % .1 /.
271 | % .2 bin.
272 | % .2 home.
273 | % .3 jeancome.
274 | % .4 texmf.
275 | % .5 tex.
276 | % .3 jeancomeson\DTcomment{Guillaume}.
277 | % .3 jeancomedaughter\DTcomment{Mathilde}.
278 | % .2 usr.
279 | % .3 bin.
280 | % }
281 | % \endgroup
282 | % In this example we have used the \package{xcolor} package.
283 | % \end{DescribeMacro}
284 | % \end{DescribeMacro}
285 | %
286 | % You can build complex text node. For example, the code
287 | % \begin{verbatim}
288 | % \dirtree{%
289 | % .1 /.
290 | % .2 bin \ldots{} \begin{minipage}[t]{5cm}
291 | % This directory holds executable files (binary
292 | % files or link on binary files){.}
293 | % \end{minipage}.
294 | % .2 home \ldots{} \begin{minipage}[t]{5cm}
295 | % jeancome\\
296 | % guillaume\\
297 | % mathilde\\
298 | % \end{minipage}.
299 | % .4 texmf.
300 | % }
301 | % \end{verbatim}
302 | % give the result
303 | % \dirtree{%^^A
304 | % .1 /.
305 | % .2 bin \ldots{} \begin{minipage}[t]{5cm}
306 | % This directory holds executable files (binary
307 | % files or link on binary files){.}
308 | % \end{minipage}.
309 | % .2 home \ldots{} \begin{minipage}[t]{5cm}
310 | % jeancome\\
311 | % guillaume\\
312 | % mathilde\\
313 | % \end{minipage}.
314 | % .4 texmf.
315 | % }
316 | % We don't encourage to try too complicated code. Package
317 | % \package{dirtree} is still fragile! Note that we pay attention to
318 | % use optional parameter |[t]| in order to have a right vertical
319 | % alignment with horizontal rules.
320 | %
321 | % \begin{DescribeMacro}{\DTsetlength}
322 | % Some dimensions can be changed using the |\DTsetlength| command. The
323 | % syntax is:
324 | % \begin{verbatim}
325 | % \DTsetlength{offset}{width}{sep}{rule-width}{dot-size}
326 | % \end{verbatim}
327 | % \begin{center}
328 | % \begin{pspicture}(0,0)(8,4)
329 | % \psset{linewidth=3pt}
330 | % \psline(1,0)(1,4)
331 | % \psline(1,2)(2.5,2)
332 | % \psline(3.5,0)(3.5,1.75)
333 | % \psset{linewidth=0.4pt}
334 | % \rput[bl](3,2){\framebox{\LARGE Text node}}
335 | % \psframe*(0.75,1.75)(1.25,2.25)
336 | % \psset{linewidth=0.2pt}
337 | % \psline{<->}(0.5,1.75)(0.5,2.25)
338 | % \uput[l](0.5,2){\scriptsize \ttfamily dot-size}
339 | % \psline{<->}(1,2.5)(2.5,2.5)
340 | % \uput[u](1.75,2.5){\scriptsize \ttfamily width}
341 | % \psline{<->}(2.5,2)(3,2)
342 | % \uput[u](2.75,2){\scriptsize \ttfamily sep}
343 | % \psline{<->}(3,1.5)(3.5,1.5)
344 | % \uput[d](3,1.5){\scriptsize \ttfamily offset}
345 | % \end{pspicture}
346 | % \end{center}
347 | % The default value are:
348 | % \begin{itemize}
349 | % \item \texttt{offset = 0.2em}
350 | % \item \texttt{width = 1em}
351 | % \item \texttt{sep = 0.2em}
352 | % \item \texttt{rule-width = 0.4pt}
353 | % \item \texttt{dot-size = 1.6pt}
354 | % \end{itemize}
355 | %
356 | % \begin{DescribeMacro}{\DTbaselineskip}
357 | % The last length parameter is |\DTbaselineskip| which indicates the
358 | % skip between lines of the tree.
359 | % \end{DescribeMacro}
360 | %
361 | % If we typeset the first example with
362 | % \begin{verbatim}
363 | % \setlength{\DTbaselineskip}{20pt}
364 | % \DTsetlength{1em}{3em}{0.1em}{1pt}{4pt}
365 | % \end{verbatim}
366 | % we obtain the (strange) result:
367 | % \begingroup
368 | % \setlength{\DTbaselineskip}{20pt}
369 | % \DTsetlength{1em}{3em}{0.1em}{1pt}{4pt}
370 | % \dirtree{%^^A
371 | % .1 /.
372 | % .2 bin.
373 | % .2 home.
374 | % .3 jeancome.
375 | % .4 texmf.
376 | % .5 tex.
377 | % .6 latex.
378 | % .7 dirtree.
379 | % .3 jeancomeson.
380 | % .3 jeancomedaughter.
381 | % .2 usr.
382 | % .3 bin.
383 | % .3 games.
384 | % .4 fortunes.
385 | % .3 include.
386 | % .3 local.
387 | % .4 bin.
388 | % .4 share.
389 | % .5 texmf.
390 | % .6 fonts.
391 | % .6 metapost.
392 | % .6 tex.
393 | % .3 share.
394 | % }
395 | % \endgroup
396 | % \end{DescribeMacro} %^^A of \DTsetlength
397 | % \end{DescribeMacro} %^^A of \dirtree
398 | %
399 | % Note that \package{dirtree} package is not able to split tree on
400 | % several pages. If this case occurs, the result will be very strange
401 | % with overfull rules. I suppose that the best is to place such trees
402 | % inside floats.
403 | %
404 | % \section{ToDo}
405 | %
406 | % \begin{itemize}
407 | % \item Parameters with \package{xkeyval} syntax;
408 | % \item Command |\DTsplittree| to allows a tree to be typeseted on
409 | % several pages;
410 | % \item Style parameters to rules (color for example) and gap between
411 | % text and comment (by now it's |\dotfill|).
412 | % \item Dimension parameter |abovetreeskip| and |belowtreeskip|.
413 | % \end{itemize}
414 | % .................... End of the documentation part ....................
415 | %
416 | %<*latex-wrapper>
417 | % \newpage
418 | % \section{\package{dirtree} \LaTeX{} Wrapper}
419 | % Nothing special here but the |\DT@fromsty| definition. This latter
420 | % is intended to check if \package{dirtree} is called under \LaTeX{}
421 | % (with |\usepackage|) or under Plain \TeX{}.
422 | % \begin{macrocode}
423 | \NeedsTeXFormat{LaTeX2e}[1995/06/01]
424 | \ProvidesPackage{dirtree}[\filedate\space v\fileversion\space
425 | package wrapper for dirtree]
426 | \newcommand*\DT@fromsty{}
427 | \input{dirtree.tex}
428 | \ProvidesFile{dirtree.tex}
429 | [\filedate\space v\fileversion\space `dirtree' (jcc)]
430 | % \end{macrocode}
431 | %
432 | %<*tex>
433 | % \newpage
434 | % \section{\package{dirtree} Code}
435 | % An ``hello'' message.
436 | % \begin{macrocode}
437 | \message{`dirtree' v\fileversion, \filedate\space (jcc)}
438 | % \end{macrocode}
439 | % Save at current catcode and make @ a letter
440 | % \begin{macrocode}
441 | \edef\DTAtCode{\the\catcode`\@}
442 | \catcode`\@=11
443 | % \end{macrocode}
444 | % Define |\LOOP|, |\REPEAT|, and |\ITERATE| like |\loop|, |\repeat|,
445 | % and |\iterate|. The uppercase form allows to place loop inside
446 | % loop.
447 | % \begin{macrocode}
448 | \long\def\LOOP#1\REPEAT{%
449 | \def\ITERATE{#1\relax\expandafter\ITERATE\fi}%
450 | \ITERATE
451 | \let\ITERATE\relax
452 | }
453 | \let\REPEAT=\fi
454 | % \end{macrocode}
455 | % Define some \LaTeX{} macros if we work under Plain \TeX{}.
456 | % |\@namedef|-like for |\edef|.
457 | % \begin{macrocode}
458 | \expandafter\ifx\csname DT@fromsty\endcsname\relax
459 | \def\@namedef#1{\expandafter\def\csname #1\endcsname}
460 | \def\@nameuse#1{\csname #1\endcsname}
461 | \long\def\@gobble#1{}
462 | \fi
463 | \def\@nameedef#1{\expandafter\edef\csname #1\endcsname}
464 | % \end{macrocode}
465 | % Offset between vertical rule below text and text left boundary.
466 | % \begin{macrocode}
467 | \newdimen\DT@offset \DT@offset=0.2em
468 | % \end{macrocode}
469 | % Length of horizontal rule.
470 | % \begin{macrocode}
471 | \newdimen\DT@width \DT@width=1em
472 | % \end{macrocode}
473 | % Gap between horizontal rule and text.
474 | % \begin{macrocode}
475 | \newdimen\DT@sep \DT@sep=0.2em
476 | % \end{macrocode}
477 | % |\DT@offset|$\null+\null$|\DT@width|$\null+\null$|\DT@sep|
478 | % \begin{macrocode}
479 | \newdimen\DT@all
480 | \DT@all=\DT@offset
481 | \advance\DT@all \DT@width
482 | \advance\DT@all \DT@sep
483 | % \end{macrocode}
484 | % Rule thickness
485 | % \begin{macrocode}
486 | \newdimen\DT@rulewidth \DT@rulewidth=0.4pt
487 | % \end{macrocode}
488 | % Size of square junction.
489 | % \begin{macrocode}
490 | \newdimen\DT@dotwidth \DT@dotwidth=1.6pt
491 | % \end{macrocode}
492 | % baselineskip inside tree.
493 | % \begin{macrocode}
494 | \newdimen\DTbaselineskip \DTbaselineskip=\baselineskip
495 | % \end{macrocode}
496 | % Max index node.
497 | % \begin{macrocode}
498 | \newcount\DT@counti
499 | % \end{macrocode}
500 | % Current index node
501 | % \begin{macrocode}
502 | \newcount\DT@countii
503 | % \end{macrocode}
504 | % |\DT@countiii|$\null=\null$|\DT@countii|$\null-1$. That is, Previous
505 | % index node.
506 | % \begin{macrocode}
507 | \newcount\DT@countiii
508 | % \end{macrocode}
509 | % Last node of a level lesser or equal to current one.
510 | % \begin{macrocode}
511 | \newcount\DT@countiv
512 | % \end{macrocode}
513 | % \begin{macro}{\DTsetlength}
514 | % |\DTsetlength| allows to define dimensions in use for the directory
515 | % tree (see above).
516 | % \begin{macrocode}
517 | \def\DTsetlength#1#2#3#4#5{%
518 | \DT@offset=#1\relax
519 | \DT@width=#2\relax
520 | \DT@sep=#3\relax
521 | % \end{macrocode}
522 | % |\DT@all| is the width of a whole column.
523 | % \begin{macrocode}
524 | \DT@all=\DT@offset
525 | \advance\DT@all by\DT@width
526 | \advance\DT@all by\DT@sep
527 | \DT@rulewidth=#4\relax
528 | \DT@dotwidth=#5\relax
529 | }
530 | % \end{macrocode}
531 | % \end{macro}
532 | % |\DTstyle| is the style used to typeset nodes. |\DTstylecomment| is
533 | % the style used to typeset comments. Since \TeX{} and \LaTeX{} are
534 | % very different, we test the format used before initializations.
535 | % \begin{macro}{\DTstyle}
536 | % \begin{macro}{\DTstylecomment}
537 | % \begin{macrocode}
538 | \expandafter\ifx\csname DT@fromsty\endcsname\relax
539 | \def\DTstyle{\tt}
540 | \def\DTstylecomment{\rm}
541 | \else
542 | \def\DTstyle{\ttfamily}
543 | \def\DTstylecomment{\rmfamily}
544 | \fi
545 | % \end{macrocode}
546 | % \end{macro}
547 | % \end{macro}
548 | % \begin{macro}{\DTcomment}
549 | % |\DTcomment| places comment in a line of the tree.
550 | % \begin{macrocode}
551 | \def\DTcomment#1{%
552 | \kern\parindent\dotfill
553 | {\DTstylecomment{#1}}%
554 | }
555 | % \end{macrocode}
556 | % \end{macro}
557 | % \begin{macro}{\dirtree}
558 | % |\dirtree| is the main package macro.
559 | % \begin{macrocode}
560 | \def\dirtree#1{%
561 | % \end{macrocode}
562 | % Change some parameters (save them before).
563 | % \begin{macrocode}
564 | \let\DT@indent=\parindent
565 | \parindent=\z@
566 | \let\DT@parskip=\parskip
567 | \parskip=\z@
568 | \let\DT@baselineskip=\baselineskip
569 | \baselineskip=\DTbaselineskip
570 | \let\DT@strut=\strut
571 | \def\strut{\vrule width\z@ height0.7\baselineskip depth0.3\baselineskip}%
572 | % \end{macrocode}
573 | % Read the argument and before that, initialize counters. |\DTcounti|
574 | % is the current index node.
575 | % \begin{macrocode}
576 | \DT@counti=\z@
577 | \let\next\DT@readarg
578 | \next#1\@nil
579 | % \end{macrocode}
580 | % When |\DT@readarg| has done its job, the node levels and the node
581 | % texts are saved in |\DT@level@| and |\DT@body@|
582 | % respectively. |\DT@counti| holds the greater index. We can now
583 | % display the tree.
584 | %
585 | % Firstly, display the root. For that, the text is boxed.
586 | % \begin{macrocode}
587 | \dimen\z@=\hsize
588 | \advance\dimen\z@ -\DT@offset
589 | \advance\dimen\z@ -\DT@width
590 | \setbox\z@=\hbox to\dimen\z@{%
591 | \hsize=\dimen\z@
592 | \vbox{\@nameuse{DT@body@1}}%
593 | }%
594 | % \end{macrocode}
595 | % We change the height and the depth of this box in order to have the
596 | % same total height and a height of |0.7\baselineskip|, that is, the
597 | % height of |\strut|.
598 | % \begin{macrocode}
599 | \dimen\z@=\ht\z@
600 | \advance\dimen0 by\dp\z@
601 | \advance\dimen0 by-0.7\baselineskip
602 | \ht\z@=0.7\baselineskip
603 | \dp\z@=\dimen\z@
604 | % \end{macrocode}
605 | % Then we display this box with an indentation as if there had a level 0.
606 | % \begin{macrocode}
607 | \par\leavevmode
608 | \kern\DT@offset
609 | \kern\DT@width
610 | \box\z@
611 | \endgraf
612 | % \end{macrocode}
613 | % Initialize index for the loop.
614 | % \begin{macrocode}
615 | \DT@countii=\@ne
616 | \DT@countiii=\z@
617 | % \end{macrocode}
618 | % |\dimen3| holds the height of the node in the tree. In fact, the
619 | % bottom of the node since this dimension is used to connect vertical
620 | % rules.
621 | % \begin{macrocode}
622 | \dimen3=\dimen\z@
623 | % \end{macrocode}
624 | % |\DT@lastlevel@| holds the baseline of the last node in level
625 | % ||.
626 | % \begin{macrocode}
627 | \@namedef{DT@lastlevel@1}{-0.7\baselineskip}%
628 | % \end{macrocode}
629 | % Loop for displaying the remainder of the tree.
630 | % \begin{macrocode}
631 | \loop
632 | % \end{macrocode}
633 | % Exit loop when the last current index is lesser or equal to max
634 | % index.
635 | % \begin{macrocode}
636 | \ifnum\DT@countii<\DT@counti
637 | % \end{macrocode}
638 | % |\DT@counti| holds current index and |\DT@countii| holds previous
639 | % index (just current index minus one).
640 | % \begin{macrocode}
641 | \advance\DT@countii \@ne
642 | \advance\DT@countiii \@ne
643 | % \end{macrocode}
644 | % Horizontal offset for the text:
645 | %
646 | % $(\mathtt{current\ level} - 1) \times \mathtt{DT@all} +
647 | % \mathtt{DT@offset}$.
648 | % \begin{macrocode}
649 | \dimen\z@=\@nameuse{DT@level@\the\DT@countii}\DT@all
650 | \advance\dimen\z@ by\DT@offset
651 | \advance\dimen\z@ by-\DT@all
652 | \leavevmode
653 | \kern\dimen\z@
654 | % \end{macrocode}
655 | % Look for last node in previous level in order to know how connect
656 | % the current node.
657 | % \begin{macrocode}
658 | \DT@countiv=\DT@countii
659 | \count@=\z@
660 | \LOOP
661 | % \end{macrocode}
662 | % Look for previous node
663 | % \begin{macrocode}
664 | \advance\DT@countiv \m@ne
665 | % \end{macrocode}
666 | % Repeat until this previous node has a level lesser or equal to
667 | % current level.
668 | % \begin{macrocode}
669 | \ifnum\@nameuse{DT@level@\the\DT@countiv} >
670 | \@nameuse{DT@level@\the\DT@countii}\relax
671 | \else
672 | \count@=\@ne
673 | \fi
674 | \ifnum\count@=\z@
675 | \REPEAT
676 | % \end{macrocode}
677 | % Now |\DT@countiv| holds the index node connected to current node.
678 | %
679 | % We box the text node.
680 | % \begin{macrocode}
681 | \edef\DT@hsize{\the\hsize}%
682 | % \end{macrocode}
683 | % \begin{macrocode}
684 | \count@=\@nameuse{DT@level@\the\DT@countii}\relax
685 | % \end{macrocode}
686 | % Since text node is vboxed, we use a |\hsize| minus horizontal
687 | % current offset.
688 | % \begin{macrocode}
689 | \dimen\z@=\count@\DT@all
690 | \advance\hsize by-\dimen\z@
691 | \setbox\z@=\vbox{\@nameuse{DT@body@\the\DT@countii}}%
692 | % \end{macrocode}
693 | % Restore |\hsize|.
694 | % \begin{macrocode}
695 | \hsize=\DT@hsize
696 | % \end{macrocode}
697 | % Change height and depth in such a way that height is
698 | % |0.7\DT@baselineskip| (that is, the |\strut| height), and total
699 | % height is unchanged.
700 | % \begin{macrocode}
701 | \dimen\z@=\ht\z@
702 | \advance\dimen\z@ by\dp\z@
703 | \advance\dimen\z@ by-0.7\baselineskip
704 | \ht\z@=0.7\baselineskip
705 | \dp\z@=\dimen\z@
706 | % \end{macrocode}
707 | % Save the height of the box in tree. The last node is the last node
708 | % in its level!
709 | % \begin{macrocode}
710 | \@nameedef{DT@lastlevel@\the\DT@countii}{\the\dimen3}%
711 | % \end{macrocode}
712 | % |\dimen3| holds the vertical position of the bottom.
713 | % \begin{macrocode}
714 | \advance\dimen3 by\dimen\z@
715 | \advance\dimen3 by0.7\baselineskip
716 | % \end{macrocode}
717 | % Display vertical rule
718 | % \begin{macrocode}
719 | \dimen\z@=\@nameuse{DT@lastlevel@\the\DT@countii}\relax
720 | \advance\dimen\z@ by-\@nameuse{DT@lastlevel@\the\DT@countiv}\relax
721 | \advance\dimen\z@ by0.3\baselineskip
722 | % \end{macrocode}
723 | % If this vertical rule connect two nodes which have different level,
724 | % the rule must be reduced by |0.5\baselineskip| (the rule don't rise
725 | % up to the baselineskip of the connected node).
726 | % \begin{macrocode}
727 | \ifnum\@nameuse{DT@level@\the\DT@countiv} <
728 | \@nameuse{DT@level@\the\DT@countii}\relax
729 | \advance\dimen\z@ by-0.5\baselineskip
730 | \fi
731 | % \end{macrocode}
732 | % Display vertical rule
733 | % \begin{macrocode}
734 | \kern-0.5\DT@rulewidth
735 | \hbox{\vbox to\z@{\vss\hrule width\DT@rulewidth height\dimen\z@}}%
736 | \kern-0.5\DT@rulewidth
737 | % \end{macrocode}
738 | % Display square junction.
739 | % \begin{macrocode}
740 | \kern-0.5\DT@dotwidth
741 | \vrule width\DT@dotwidth height0.5\DT@dotwidth depth0.5\DT@dotwidth
742 | \kern-0.5\DT@dotwidth
743 | % \end{macrocode}
744 | % Display horizontal rule and gap between horizontal rule and text node.
745 | % \begin{macrocode}
746 | \vrule width\DT@width height0.5\DT@rulewidth depth0.5\DT@rulewidth
747 | \kern\DT@sep
748 | % \end{macrocode}
749 | % Display text node.
750 | % \begin{macrocode}
751 | \box\z@
752 | % \end{macrocode}
753 | % New paragraph for next node.
754 | % \begin{macrocode}
755 | \endgraf
756 | \repeat
757 | % \end{macrocode}
758 | % Restore indentation, paragraph skip, and |\strut|.
759 | % \begin{macrocode}
760 | \parindent=\DT@indent
761 | \parskip=\DT@parskip
762 | \DT@baselineskip=\baselineskip
763 | \let\strut\DT@strut
764 | }
765 | % \end{macrocode}
766 | % \end{macro}
767 | % \begin{macro}{\DT@readarg}
768 | % The first processing step is to read the whole tree. It's a
769 | % recursive macro: each call process one node, that is, a
770 | % \begin{verbatim}
771 | % . .
772 | % \end{verbatim}
773 | % in the source file.
774 | % \begin{macrocode}
775 | \def\DT@readarg.#1 #2. #3\@nil{%
776 | % \end{macrocode}
777 | % |\DT@counti| is the current index.
778 | % \begin{macrocode}
779 | \advance\DT@counti \@ne
780 | % \end{macrocode}
781 | % save level node in |\DT@level@| and text node in
782 | % |\DT@body@|. Two \package{dirtree} |\strut| are added to text
783 | % node in order to ensure a right vertical alignment, according to
784 | % \package{dirtree} |\baselineskip|
785 | % \begin{macrocode}
786 | \@namedef{DT@level@\the\DT@counti}{#1}%
787 | \@namedef{DT@body@\the\DT@counti}{\strut{\DTstyle{#2}\strut}}%
788 | % \end{macrocode}
789 | % If |#3| is not empty, it contains the remainder nodes and macro
790 | % calls itself. Otherwise, recursive call is stopped.
791 | % \begin{macrocode}
792 | \ifx\relax#3\relax
793 | \let\next\@gobble
794 | \fi
795 | \next#3\@nil
796 | }
797 | % \end{macrocode}
798 | % \end{macro}
799 | % Restore at catcode.
800 | % \begin{macrocode}
801 | \catcode`\@=\DTAtCode\relax
802 | % \end{macrocode}
803 | %
804 | % \endinput
805 |
--------------------------------------------------------------------------------
/documentation/splncs.bst:
--------------------------------------------------------------------------------
1 | % BibTeX bibliography style `splncs'
2 |
3 | % An attempt to match the bibliography style required for use with
4 | % numbered references in Springer Verlag's "Lecture Notes in Computer
5 | % Science" series. (See Springer's documentation for llncs.sty for
6 | % more details of the suggested reference format.) Note that this
7 | % file will not work for author-year style citations.
8 |
9 | % Use \documentclass{llncs} and \bibliographystyle{splncs}, and cite
10 | % a reference with (e.g.) \cite{smith77} to get a "[1]" in the text.
11 |
12 | % Copyright (C) 1999 Jason Noble.
13 | % Last updated: Friday 07 March 2006, 08:04:42 Frank Holzwarth, Springer
14 | %
15 | % Based on the BibTeX standard bibliography style `unsrt'
16 |
17 | ENTRY
18 | { address
19 | author
20 | booktitle
21 | chapter
22 | edition
23 | editor
24 | howpublished
25 | institution
26 | journal
27 | key
28 | month
29 | note
30 | number
31 | organization
32 | pages
33 | publisher
34 | school
35 | series
36 | title
37 | type
38 | volume
39 | year
40 | }
41 | {}
42 | { label }
43 |
44 | INTEGERS { output.state before.all mid.sentence after.sentence
45 | after.block after.authors between.elements}
46 |
47 | FUNCTION {init.state.consts}
48 | { #0 'before.all :=
49 | #1 'mid.sentence :=
50 | #2 'after.sentence :=
51 | #3 'after.block :=
52 | #4 'after.authors :=
53 | #5 'between.elements :=
54 | }
55 |
56 | STRINGS { s t }
57 |
58 | FUNCTION {output.nonnull}
59 | { 's :=
60 | output.state mid.sentence =
61 | { " " * write$ }
62 | { output.state after.block =
63 | { add.period$ write$
64 | newline$
65 | "\newblock " write$
66 | }
67 | {
68 | output.state after.authors =
69 | { ": " * write$
70 | newline$
71 | "\newblock " write$
72 | }
73 | { output.state between.elements =
74 | { ", " * write$ }
75 | { output.state before.all =
76 | 'write$
77 | { add.period$ " " * write$ }
78 | if$
79 | }
80 | if$
81 | }
82 | if$
83 | }
84 | if$
85 | mid.sentence 'output.state :=
86 | }
87 | if$
88 | s
89 | }
90 |
91 | FUNCTION {output}
92 | { duplicate$ empty$
93 | 'pop$
94 | 'output.nonnull
95 | if$
96 | }
97 |
98 | FUNCTION {output.check}
99 | { 't :=
100 | duplicate$ empty$
101 | { pop$ "empty " t * " in " * cite$ * warning$ }
102 | 'output.nonnull
103 | if$
104 | }
105 |
106 | FUNCTION {output.bibitem}
107 | { newline$
108 | "\bibitem{" write$
109 | cite$ write$
110 | "}" write$
111 | newline$
112 | ""
113 | before.all 'output.state :=
114 | }
115 |
116 | FUNCTION {fin.entry}
117 | { write$
118 | newline$
119 | }
120 |
121 | FUNCTION {new.block}
122 | { output.state before.all =
123 | 'skip$
124 | { after.block 'output.state := }
125 | if$
126 | }
127 |
128 | FUNCTION {stupid.colon}
129 | { after.authors 'output.state := }
130 |
131 | FUNCTION {insert.comma}
132 | { output.state before.all =
133 | 'skip$
134 | { between.elements 'output.state := }
135 | if$
136 | }
137 |
138 | FUNCTION {new.sentence}
139 | { output.state after.block =
140 | 'skip$
141 | { output.state before.all =
142 | 'skip$
143 | { after.sentence 'output.state := }
144 | if$
145 | }
146 | if$
147 | }
148 |
149 | FUNCTION {not}
150 | { { #0 }
151 | { #1 }
152 | if$
153 | }
154 |
155 | FUNCTION {and}
156 | { 'skip$
157 | { pop$ #0 }
158 | if$
159 | }
160 |
161 | FUNCTION {or}
162 | { { pop$ #1 }
163 | 'skip$
164 | if$
165 | }
166 |
167 | FUNCTION {new.block.checka}
168 | { empty$
169 | 'skip$
170 | 'new.block
171 | if$
172 | }
173 |
174 | FUNCTION {new.block.checkb}
175 | { empty$
176 | swap$ empty$
177 | and
178 | 'skip$
179 | 'new.block
180 | if$
181 | }
182 |
183 | FUNCTION {new.sentence.checka}
184 | { empty$
185 | 'skip$
186 | 'new.sentence
187 | if$
188 | }
189 |
190 | FUNCTION {new.sentence.checkb}
191 | { empty$
192 | swap$ empty$
193 | and
194 | 'skip$
195 | 'new.sentence
196 | if$
197 | }
198 |
199 | FUNCTION {field.or.null}
200 | { duplicate$ empty$
201 | { pop$ "" }
202 | 'skip$
203 | if$
204 | }
205 |
206 | FUNCTION {emphasize}
207 | { duplicate$ empty$
208 | { pop$ "" }
209 | { "" swap$ * "" * }
210 | if$
211 | }
212 |
213 | FUNCTION {bold}
214 | { duplicate$ empty$
215 | { pop$ "" }
216 | { "\textbf{" swap$ * "}" * }
217 | if$
218 | }
219 |
220 | FUNCTION {parens}
221 | { duplicate$ empty$
222 | { pop$ "" }
223 | { "(" swap$ * ")" * }
224 | if$
225 | }
226 |
227 | INTEGERS { nameptr namesleft numnames }
228 |
229 | FUNCTION {format.springer.names}
230 | { 's :=
231 | #1 'nameptr :=
232 | s num.names$ 'numnames :=
233 | numnames 'namesleft :=
234 | { namesleft #0 > }
235 | { s nameptr "{vv~}{ll}{, jj}{, f{.}.}" format.name$ 't :=
236 | nameptr #1 >
237 | { namesleft #1 >
238 | { ", " * t * }
239 | { numnames #1 >
240 | { ", " * }
241 | 'skip$
242 | if$
243 | t "others" =
244 | { " et~al." * }
245 | { "" * t * }
246 | if$
247 | }
248 | if$
249 | }
250 | 't
251 | if$
252 | nameptr #1 + 'nameptr :=
253 | namesleft #1 - 'namesleft :=
254 | }
255 | while$
256 | }
257 |
258 | FUNCTION {format.names}
259 | { 's :=
260 | #1 'nameptr :=
261 | s num.names$ 'numnames :=
262 | numnames 'namesleft :=
263 | { namesleft #0 > }
264 | { s nameptr "{vv~}{ll}{, jj}{, f.}" format.name$ 't :=
265 | nameptr #1 >
266 | { namesleft #1 >
267 | { ", " * t * }
268 | { numnames #2 >
269 | { "," * }
270 | 'skip$
271 | if$
272 | t "others" =
273 | { " et~al." * }
274 | { " \& " * t * }
275 | if$
276 | }
277 | if$
278 | }
279 | 't
280 | if$
281 | nameptr #1 + 'nameptr :=
282 | namesleft #1 - 'namesleft :=
283 | }
284 | while$
285 | }
286 |
287 | FUNCTION {format.authors}
288 | { author empty$
289 | { "" }
290 | { author format.springer.names }
291 | if$
292 | }
293 |
294 | FUNCTION {format.editors}
295 | { editor empty$
296 | { "" }
297 | { editor format.springer.names
298 | editor num.names$ #1 >
299 | { ", eds." * }
300 | { ", ed." * }
301 | if$
302 | }
303 | if$
304 | }
305 |
306 | FUNCTION {format.title}
307 | { title empty$
308 | { "" }
309 | { title "t" change.case$ }
310 | if$
311 | }
312 |
313 | FUNCTION {n.dashify}
314 | { 't :=
315 | ""
316 | { t empty$ not }
317 | { t #1 #1 substring$ "-" =
318 | { t #1 #2 substring$ "--" = not
319 | { "--" *
320 | t #2 global.max$ substring$ 't :=
321 | }
322 | { { t #1 #1 substring$ "-" = }
323 | { "-" *
324 | t #2 global.max$ substring$ 't :=
325 | }
326 | while$
327 | }
328 | if$
329 | }
330 | { t #1 #1 substring$ *
331 | t #2 global.max$ substring$ 't :=
332 | }
333 | if$
334 | }
335 | while$
336 | }
337 |
338 | FUNCTION {format.date}
339 | { year empty$
340 | { month empty$
341 | { "" }
342 | { "there's a month but no year in " cite$ * warning$
343 | month
344 | }
345 | if$
346 | }
347 | { month empty$
348 | 'year
349 | { month " " * year * }
350 | if$
351 | }
352 | if$
353 | }
354 |
355 | FUNCTION {format.btitle}
356 | { title emphasize
357 | }
358 |
359 | FUNCTION {tie.or.space.connect}
360 | { duplicate$ text.length$ #3 <
361 | { "~" }
362 | { " " }
363 | if$
364 | swap$ * *
365 | }
366 |
367 | FUNCTION {either.or.check}
368 | { empty$
369 | 'pop$
370 | { "can't use both " swap$ * " fields in " * cite$ * warning$ }
371 | if$
372 | }
373 |
374 | FUNCTION {format.bvolume}
375 | { volume empty$
376 | { "" }
377 | { "Volume" volume tie.or.space.connect
378 | series empty$
379 | 'skip$
380 | { " of " * series emphasize * }
381 | if$
382 | add.period$
383 | "volume and number" number either.or.check
384 | }
385 | if$
386 | }
387 |
388 | FUNCTION {format.number.series}
389 | { volume empty$
390 | { number empty$
391 | { series field.or.null }
392 | { output.state mid.sentence =
393 | { "number" }
394 | { "Number" }
395 | if$
396 | number tie.or.space.connect
397 | series empty$
398 | { "there's a number but no series in " cite$ * warning$ }
399 | { " in " * series * }
400 | if$
401 | }
402 | if$
403 | }
404 | { "" }
405 | if$
406 | }
407 |
408 | FUNCTION {format.edition}
409 | { edition empty$
410 | { "" }
411 | { output.state mid.sentence =
412 | { edition "l" change.case$ " edn." * }
413 | { edition "t" change.case$ " edn." * }
414 | if$
415 | }
416 | if$
417 | }
418 |
419 | INTEGERS { multiresult }
420 |
421 | FUNCTION {multi.page.check}
422 | { 't :=
423 | #0 'multiresult :=
424 | { multiresult not
425 | t empty$ not
426 | and
427 | }
428 | { t #1 #1 substring$
429 | duplicate$ "-" =
430 | swap$ duplicate$ "," =
431 | swap$ "+" =
432 | or or
433 | { #1 'multiresult := }
434 | { t #2 global.max$ substring$ 't := }
435 | if$
436 | }
437 | while$
438 | multiresult
439 | }
440 |
441 | FUNCTION {format.pages}
442 | { pages empty$
443 | { "" }
444 | { pages multi.page.check
445 | { "" pages n.dashify tie.or.space.connect }
446 | { "" pages tie.or.space.connect }
447 | if$
448 | }
449 | if$
450 | }
451 |
452 | FUNCTION {format.vol}
453 | { volume bold
454 | }
455 |
456 | FUNCTION {format.vol.num}
457 | { volume bold
458 | number empty$
459 | { }
460 | { number "(" swap$ * * ")" * }
461 | if$
462 | }
463 |
464 | FUNCTION {pre.format.pages}
465 | { pages empty$
466 | 'skip$
467 | { duplicate$ empty$
468 | { pop$ format.pages }
469 | { " " * pages n.dashify * }
470 | if$
471 | }
472 | if$
473 | }
474 |
475 | FUNCTION {format.chapter.pages}
476 | { chapter empty$
477 | 'format.pages
478 | { type empty$
479 | { "chapter" }
480 | { type "l" change.case$ }
481 | if$
482 | chapter tie.or.space.connect
483 | pages empty$
484 | 'skip$
485 | { " " * format.pages * }
486 | if$
487 | }
488 | if$
489 | }
490 |
491 | FUNCTION {format.in.ed.booktitle}
492 | { booktitle empty$
493 | { "" }
494 | { editor empty$
495 | { "In: " booktitle emphasize * }
496 | { "In " format.editors * ": " * booktitle emphasize * }
497 | if$
498 | }
499 | if$
500 | }
501 |
502 | FUNCTION {empty.misc.check}
503 | { author empty$ title empty$ howpublished empty$
504 | month empty$ year empty$ note empty$
505 | and and and and and
506 | { "all relevant fields are empty in " cite$ * warning$ }
507 | 'skip$
508 | if$
509 | }
510 |
511 | FUNCTION {format.thesis.type}
512 | { type empty$
513 | 'skip$
514 | { pop$
515 | type "t" change.case$
516 | }
517 | if$
518 | }
519 |
520 | FUNCTION {format.tr.number}
521 | { type empty$
522 | { "Technical Report" }
523 | 'type
524 | if$
525 | number empty$
526 | { "t" change.case$ }
527 | { number tie.or.space.connect }
528 | if$
529 | }
530 |
531 | FUNCTION {format.article.crossref}
532 | { key empty$
533 | { journal empty$
534 | { "need key or journal for " cite$ * " to crossref " * crossref *
535 | warning$
536 | ""
537 | }
538 | { "In {\em " journal * "\/}" * }
539 | if$
540 | }
541 | { "In " key * }
542 | if$
543 | " \cite{" * crossref * "}" *
544 | }
545 |
546 | FUNCTION {format.crossref.editor}
547 | { editor #1 "{vv~}{ll}" format.name$
548 | editor num.names$ duplicate$
549 | #2 >
550 | { pop$ " et~al." * }
551 | { #2 <
552 | 'skip$
553 | { editor #2 "{ff }{vv }{ll}{ jj}" format.name$ "others" =
554 | { " et~al." * }
555 | { " and " * editor #2 "{vv~}{ll}" format.name$ * }
556 | if$
557 | }
558 | if$
559 | }
560 | if$
561 | }
562 |
563 | FUNCTION {format.book.crossref}
564 | { volume empty$
565 | { "empty volume in " cite$ * "'s crossref of " * crossref * warning$
566 | "In "
567 | }
568 | { "Volume" volume tie.or.space.connect
569 | " of " *
570 | }
571 | if$
572 | " \cite{" * crossref * "}" *
573 | }
574 |
575 | FUNCTION {format.incoll.inproc.crossref}
576 | { editor empty$
577 | editor field.or.null author field.or.null =
578 | or
579 | { key empty$
580 | { booktitle empty$
581 | { "need editor, key, or booktitle for " cite$ * " to crossref " *
582 | crossref * warning$
583 | ""
584 | }
585 | { "" }
586 | if$
587 | }
588 | { "" }
589 | if$
590 | }
591 | { "" }
592 | if$
593 | " \cite{" * crossref * "}" *
594 | }
595 |
596 | FUNCTION {and.the.note}
597 | { note output
598 | note empty$
599 | 'skip$
600 | { add.period$ }
601 | if$
602 | }
603 |
604 | FUNCTION {article}
605 | { output.bibitem
606 | format.authors "author" output.check
607 | stupid.colon
608 | format.title "title" output.check
609 | new.block
610 | crossref missing$
611 | { journal emphasize "journal" output.check
612 | format.vol.num output
613 | format.date parens output
614 | format.pages output
615 | }
616 | { format.article.crossref output.nonnull
617 | format.pages output
618 | }
619 | if$
620 | and.the.note
621 | fin.entry
622 | }
623 |
624 | FUNCTION {book}
625 | { output.bibitem
626 | author empty$
627 | { format.editors "author and editor" output.check }
628 | { format.authors output.nonnull
629 | crossref missing$
630 | { "author and editor" editor either.or.check }
631 | 'skip$
632 | if$
633 | }
634 | if$
635 | stupid.colon
636 | format.btitle "title" output.check
637 | new.sentence
638 | crossref missing$
639 | { format.edition output
640 | format.bvolume output
641 | new.block
642 | format.number.series output
643 | new.sentence
644 | publisher "publisher" output.check
645 | address empty$
646 | 'skip$
647 | { insert.comma }
648 | if$
649 | address output
650 | format.date parens output
651 | }
652 | { format.book.crossref output.nonnull
653 | }
654 | if$
655 | and.the.note
656 | fin.entry
657 | }
658 |
659 | FUNCTION {booklet}
660 | { output.bibitem
661 | format.authors output
662 | stupid.colon
663 | format.title "title" output.check
664 | howpublished address new.block.checkb
665 | howpublished output
666 | address empty$
667 | 'skip$
668 | { insert.comma }
669 | if$
670 | address output
671 | format.date parens output
672 | and.the.note
673 | fin.entry
674 | }
675 |
676 | FUNCTION {inbook}
677 | { output.bibitem
678 | author empty$
679 | { format.editors "author and editor" output.check }
680 | { format.authors output.nonnull
681 | crossref missing$
682 | { "author and editor" editor either.or.check }
683 | 'skip$
684 | if$
685 | }
686 | if$
687 | stupid.colon
688 | crossref missing$
689 | { chapter output
690 | new.block
691 | format.number.series output
692 | new.sentence
693 | "In:" output
694 | format.btitle "title" output.check
695 | new.sentence
696 | format.edition output
697 | format.bvolume output
698 | publisher "publisher" output.check
699 | address empty$
700 | 'skip$
701 | { insert.comma }
702 | if$
703 | address output
704 | format.date parens output
705 | }
706 | { chapter output
707 | new.block
708 | format.incoll.inproc.crossref output.nonnull
709 | }
710 | if$
711 | format.pages output
712 | and.the.note
713 | fin.entry
714 | }
715 |
716 | FUNCTION {incollection}
717 | { output.bibitem
718 | format.authors "author" output.check
719 | stupid.colon
720 | format.title "title" output.check
721 | new.block
722 | crossref missing$
723 | { format.in.ed.booktitle "booktitle" output.check
724 | new.sentence
725 | format.bvolume output
726 | format.number.series output
727 | new.block
728 | format.edition output
729 | publisher "publisher" output.check
730 | address empty$
731 | 'skip$
732 | { insert.comma }
733 | if$
734 | address output
735 | format.date parens output
736 | format.pages output
737 | }
738 | { format.incoll.inproc.crossref output.nonnull
739 | format.chapter.pages output
740 | }
741 | if$
742 | and.the.note
743 | fin.entry
744 | }
745 |
746 | FUNCTION {inproceedings}
747 | { output.bibitem
748 | format.authors "author" output.check
749 | stupid.colon
750 | format.title "title" output.check
751 | new.block
752 | crossref missing$
753 | { format.in.ed.booktitle "booktitle" output.check
754 | new.sentence
755 | format.bvolume output
756 | format.number.series output
757 | address empty$
758 | { organization publisher new.sentence.checkb
759 | organization empty$
760 | 'skip$
761 | { insert.comma }
762 | if$
763 | organization output
764 | publisher empty$
765 | 'skip$
766 | { insert.comma }
767 | if$
768 | publisher output
769 | format.date parens output
770 | }
771 | { insert.comma
772 | address output.nonnull
773 | organization empty$
774 | 'skip$
775 | { insert.comma }
776 | if$
777 | organization output
778 | publisher empty$
779 | 'skip$
780 | { insert.comma }
781 | if$
782 | publisher output
783 | format.date parens output
784 | }
785 | if$
786 | }
787 | { format.incoll.inproc.crossref output.nonnull
788 | }
789 | if$
790 | format.pages output
791 | and.the.note
792 | fin.entry
793 | }
794 |
795 | FUNCTION {conference} { inproceedings }
796 |
797 | FUNCTION {manual}
798 | { output.bibitem
799 | author empty$
800 | { organization empty$
801 | 'skip$
802 | { organization output.nonnull
803 | address output
804 | }
805 | if$
806 | }
807 | { format.authors output.nonnull }
808 | if$
809 | stupid.colon
810 | format.btitle "title" output.check
811 | author empty$
812 | { organization empty$
813 | { address new.block.checka
814 | address output
815 | }
816 | 'skip$
817 | if$
818 | }
819 | { organization address new.block.checkb
820 | organization output
821 | address empty$
822 | 'skip$
823 | { insert.comma }
824 | if$
825 | address output
826 | }
827 | if$
828 | new.sentence
829 | format.edition output
830 | format.date parens output
831 | and.the.note
832 | fin.entry
833 | }
834 |
835 | FUNCTION {mastersthesis}
836 | { output.bibitem
837 | format.authors "author" output.check
838 | stupid.colon
839 | format.title "title" output.check
840 | new.block
841 | "Master's thesis" format.thesis.type output.nonnull
842 | school empty$
843 | 'skip$
844 | { insert.comma }
845 | if$
846 | school "school" output.check
847 | address empty$
848 | 'skip$
849 | { insert.comma }
850 | if$
851 | address output
852 | format.date parens output
853 | and.the.note
854 | fin.entry
855 | }
856 |
857 | FUNCTION {misc}
858 | { output.bibitem
859 | format.authors "author" output.check
860 | stupid.colon
861 | format.title "title" output.check
862 | howpublished new.block.checka
863 | howpublished output
864 | format.date parens output
865 | and.the.note
866 | fin.entry
867 | empty.misc.check
868 | }
869 |
870 | FUNCTION {phdthesis}
871 | { output.bibitem
872 | format.authors "author" output.check
873 | stupid.colon
874 | format.btitle "title" output.check
875 | new.block
876 | "PhD thesis" format.thesis.type output.nonnull
877 | school empty$
878 | 'skip$
879 | { insert.comma }
880 | if$
881 | school "school" output.check
882 | address empty$
883 | 'skip$
884 | { insert.comma }
885 | if$
886 | address output
887 | format.date parens output
888 | and.the.note
889 | fin.entry
890 | }
891 |
892 | FUNCTION {proceedings}
893 | { output.bibitem
894 | editor empty$
895 | { organization empty$
896 | { "" }
897 | { organization output
898 | stupid.colon }
899 | if$
900 | }
901 | { format.editors output.nonnull
902 | stupid.colon
903 | }
904 | if$
905 | format.btitle "title" output.check
906 | new.block
907 | crossref missing$
908 | { format.in.ed.booktitle "booktitle" output.check
909 | new.sentence
910 | format.bvolume output
911 | format.number.series output
912 | address empty$
913 | { organization publisher new.sentence.checkb
914 | organization empty$
915 | 'skip$
916 | { insert.comma }
917 | if$
918 | organization output
919 | publisher empty$
920 | 'skip$
921 | { insert.comma }
922 | if$
923 | publisher output
924 | format.date parens output
925 | }
926 | { insert.comma
927 | address output.nonnull
928 | organization empty$
929 | 'skip$
930 | { insert.comma }
931 | if$
932 | organization output
933 | publisher empty$
934 | 'skip$
935 | { insert.comma }
936 | if$
937 | publisher output
938 | format.date parens output
939 | }
940 | if$
941 | }
942 | { format.incoll.inproc.crossref output.nonnull
943 | }
944 | if$
945 | and.the.note
946 | fin.entry
947 | }
948 |
949 | FUNCTION {techreport}
950 | { output.bibitem
951 | format.authors "author" output.check
952 | stupid.colon
953 | format.title "title" output.check
954 | new.block
955 | format.tr.number output.nonnull
956 | institution empty$
957 | 'skip$
958 | { insert.comma }
959 | if$
960 | institution "institution" output.check
961 | address empty$
962 | 'skip$
963 | { insert.comma }
964 | if$
965 | address output
966 | format.date parens output
967 | and.the.note
968 | fin.entry
969 | }
970 |
971 | FUNCTION {unpublished}
972 | { output.bibitem
973 | format.authors "author" output.check
974 | stupid.colon
975 | format.title "title" output.check
976 | new.block
977 | note "note" output.check
978 | format.date parens output
979 | fin.entry
980 | }
981 |
982 | FUNCTION {default.type} { misc }
983 |
984 | MACRO {jan} {"January"}
985 |
986 | MACRO {feb} {"February"}
987 |
988 | MACRO {mar} {"March"}
989 |
990 | MACRO {apr} {"April"}
991 |
992 | MACRO {may} {"May"}
993 |
994 | MACRO {jun} {"June"}
995 |
996 | MACRO {jul} {"July"}
997 |
998 | MACRO {aug} {"August"}
999 |
1000 | MACRO {sep} {"September"}
1001 |
1002 | MACRO {oct} {"October"}
1003 |
1004 | MACRO {nov} {"November"}
1005 |
1006 | MACRO {dec} {"December"}
1007 |
1008 | MACRO {acmcs} {"ACM Computing Surveys"}
1009 |
1010 | MACRO {acta} {"Acta Informatica"}
1011 |
1012 | MACRO {cacm} {"Communications of the ACM"}
1013 |
1014 | MACRO {ibmjrd} {"IBM Journal of Research and Development"}
1015 |
1016 | MACRO {ibmsj} {"IBM Systems Journal"}
1017 |
1018 | MACRO {ieeese} {"IEEE Transactions on Software Engineering"}
1019 |
1020 | MACRO {ieeetc} {"IEEE Transactions on Computers"}
1021 |
1022 | MACRO {ieeetcad}
1023 | {"IEEE Transactions on Computer-Aided Design of Integrated Circuits"}
1024 |
1025 | MACRO {ipl} {"Information Processing Letters"}
1026 |
1027 | MACRO {jacm} {"Journal of the ACM"}
1028 |
1029 | MACRO {jcss} {"Journal of Computer and System Sciences"}
1030 |
1031 | MACRO {scp} {"Science of Computer Programming"}
1032 |
1033 | MACRO {sicomp} {"SIAM Journal on Computing"}
1034 |
1035 | MACRO {tocs} {"ACM Transactions on Computer Systems"}
1036 |
1037 | MACRO {tods} {"ACM Transactions on Database Systems"}
1038 |
1039 | MACRO {tog} {"ACM Transactions on Graphics"}
1040 |
1041 | MACRO {toms} {"ACM Transactions on Mathematical Software"}
1042 |
1043 | MACRO {toois} {"ACM Transactions on Office Information Systems"}
1044 |
1045 | MACRO {toplas} {"ACM Transactions on Programming Languages and Systems"}
1046 |
1047 | MACRO {tcs} {"Theoretical Computer Science"}
1048 |
1049 | READ
1050 |
1051 | STRINGS { longest.label }
1052 |
1053 | INTEGERS { number.label longest.label.width }
1054 |
1055 | FUNCTION {initialize.longest.label}
1056 | { "" 'longest.label :=
1057 | #1 'number.label :=
1058 | #0 'longest.label.width :=
1059 | }
1060 |
1061 | FUNCTION {longest.label.pass}
1062 | { number.label int.to.str$ 'label :=
1063 | number.label #1 + 'number.label :=
1064 | label width$ longest.label.width >
1065 | { label 'longest.label :=
1066 | label width$ 'longest.label.width :=
1067 | }
1068 | 'skip$
1069 | if$
1070 | }
1071 |
1072 | EXECUTE {initialize.longest.label}
1073 |
1074 | ITERATE {longest.label.pass}
1075 |
1076 | FUNCTION {begin.bib}
1077 | { preamble$ empty$
1078 | 'skip$
1079 | { preamble$ write$ newline$ }
1080 | if$
1081 | "\begin{thebibliography}{" longest.label * "}" * write$ newline$
1082 | }
1083 |
1084 | EXECUTE {begin.bib}
1085 |
1086 | EXECUTE {init.state.consts}
1087 |
1088 | ITERATE {call.type$}
1089 |
1090 | FUNCTION {end.bib}
1091 | { newline$
1092 | "\end{thebibliography}" write$ newline$
1093 | }
1094 |
1095 | EXECUTE {end.bib}
1096 |
1097 |
1098 |
1099 |
--------------------------------------------------------------------------------
/documentation/tcilatex.tex:
--------------------------------------------------------------------------------
1 | % Macros for Scientific Word 3.0 documents saved with the LaTeX filter.
2 | %Copyright (C) 1994-97 TCI Software Research, Inc.
3 | \typeout{TCILATEX Macros for Scientific Word 3.0 <05 August 1998>.}
4 | \typeout{NOTICE: This macro file is NOT proprietary and may be
5 | freely copied and distributed.}
6 | %
7 | \makeatletter
8 | %
9 | %%%%%%%%%%%%%%%%%%%%%%
10 | % macros for time
11 | \newcount\@hour\newcount\@minute\chardef\@x10\chardef\@xv60
12 | \def\tcitime{
13 | \def\@time{%
14 | \@minute\time\@hour\@minute\divide\@hour\@xv
15 | \ifnum\@hour<\@x 0\fi\the\@hour:%
16 | \multiply\@hour\@xv\advance\@minute-\@hour
17 | \ifnum\@minute<\@x 0\fi\the\@minute
18 | }}%
19 |
20 | %%%%%%%%%%%%%%%%%%%%%%
21 | % macro for hyperref
22 | \@ifundefined{hyperref}{\def\hyperref#1#2#3#4{#2\ref{#4}#3}}{}
23 |
24 | % macro for external program call
25 | \@ifundefined{qExtProgCall}{\def\qExtProgCall#1#2#3#4#5#6{\relax}}{}
26 | %%%%%%%%%%%%%%%%%%%%%%
27 | %
28 | % macros for graphics
29 | %
30 | \def\FILENAME#1{#1}%
31 | %
32 | \def\QCTOpt[#1]#2{%
33 | \def\QCTOptB{#1}
34 | \def\QCTOptA{#2}
35 | }
36 | \def\QCTNOpt#1{%
37 | \def\QCTOptA{#1}
38 | \let\QCTOptB\empty
39 | }
40 | \def\Qct{%
41 | \@ifnextchar[{%
42 | \QCTOpt}{\QCTNOpt}
43 | }
44 | \def\QCBOpt[#1]#2{%
45 | \def\QCBOptB{#1}
46 | \def\QCBOptA{#2}
47 | }
48 | \def\QCBNOpt#1{%
49 | \def\QCBOptA{#1}
50 | \let\QCBOptB\empty
51 | }
52 | \def\Qcb{%
53 | \@ifnextchar[{%
54 | \QCBOpt}{\QCBNOpt}
55 | }
56 | \def\PrepCapArgs{%
57 | \ifx\QCBOptA\empty
58 | \ifx\QCTOptA\empty
59 | {}%
60 | \else
61 | \ifx\QCTOptB\empty
62 | {\QCTOptA}%
63 | \else
64 | [\QCTOptB]{\QCTOptA}%
65 | \fi
66 | \fi
67 | \else
68 | \ifx\QCBOptA\empty
69 | {}%
70 | \else
71 | \ifx\QCBOptB\empty
72 | {\QCBOptA}%
73 | \else
74 | [\QCBOptB]{\QCBOptA}%
75 | \fi
76 | \fi
77 | \fi
78 | }
79 | \newcount\GRAPHICSTYPE
80 | %\GRAPHICSTYPE 0 is for TurboTeX
81 | %\GRAPHICSTYPE 1 is for DVIWindo (PostScript)
82 | %%%(removed)%\GRAPHICSTYPE 2 is for psfig (PostScript)
83 | \GRAPHICSTYPE=\z@
84 | \def\GRAPHICSPS#1{%
85 | \ifcase\GRAPHICSTYPE%\GRAPHICSTYPE=0
86 | \special{ps: #1}%
87 | \or%\GRAPHICSTYPE=1
88 | \special{language "PS", include "#1"}%
89 | %%%\or%\GRAPHICSTYPE=2
90 | %%% #1%
91 | \fi
92 | }%
93 | %
94 | \def\GRAPHICSHP#1{\special{include #1}}%
95 | %
96 | % \graffile{ body } %#1
97 | % { contentswidth (scalar) } %#2
98 | % { contentsheight (scalar) } %#3
99 | % { vertical shift when in-line (scalar) } %#4
100 | \def\graffile#1#2#3#4{%
101 | %%% \ifnum\GRAPHICSTYPE=\tw@
102 | %%% %Following if using psfig
103 | %%% \@ifundefined{psfig}{\input psfig.tex}{}%
104 | %%% \psfig{file=#1, height=#3, width=#2}%
105 | %%% \else
106 | %Following for all others
107 | % JCS - added BOXTHEFRAME, see below
108 | \bgroup
109 | \leavevmode
110 | \@ifundefined{bbl@deactivate}{\def~{\string~}}{\activesoff}
111 | \raise -#4 \BOXTHEFRAME{%
112 | \hbox to #2{\raise #3\hbox to #2{\null #1\hfil}}}%
113 | \egroup
114 | }%
115 | %
116 | % A box for drafts
117 | \def\draftbox#1#2#3#4{%
118 | \leavevmode\raise -#4 \hbox{%
119 | \frame{\rlap{\protect\tiny #1}\hbox to #2%
120 | {\vrule height#3 width\z@ depth\z@\hfil}%
121 | }%
122 | }%
123 | }%
124 | %
125 | \newcount\draft
126 | \draft=\z@
127 | \let\nographics=\draft
128 | \newif\ifwasdraft
129 | \wasdraftfalse
130 |
131 | % \GRAPHIC{ body } %#1
132 | % { draft name } %#2
133 | % { contentswidth (scalar) } %#3
134 | % { contentsheight (scalar) } %#4
135 | % { vertical shift when in-line (scalar) } %#5
136 | \def\GRAPHIC#1#2#3#4#5{%
137 | \ifnum\draft=\@ne\draftbox{#2}{#3}{#4}{#5}%
138 | \else\graffile{#1}{#3}{#4}{#5}%
139 | \fi
140 | }%
141 | %
142 | \def\addtoLaTeXparams#1{%
143 | \edef\LaTeXparams{\LaTeXparams #1}}%
144 | %
145 | % JCS - added a switch BoxFrame that can
146 | % be set by including X in the frame params.
147 | % If set a box is drawn around the frame.
148 |
149 | \newif\ifBoxFrame \BoxFramefalse
150 | \newif\ifOverFrame \OverFramefalse
151 | \newif\ifUnderFrame \UnderFramefalse
152 |
153 | \def\BOXTHEFRAME#1{%
154 | \hbox{%
155 | \ifBoxFrame
156 | \frame{#1}%
157 | \else
158 | {#1}%
159 | \fi
160 | }%
161 | }
162 |
163 |
164 | \def\doFRAMEparams#1{\BoxFramefalse\OverFramefalse\UnderFramefalse\readFRAMEparams#1\end}%
165 | \def\readFRAMEparams#1{%
166 | \ifx#1\end%
167 | \let\next=\relax
168 | \else
169 | \ifx#1i\dispkind=\z@\fi
170 | \ifx#1d\dispkind=\@ne\fi
171 | \ifx#1f\dispkind=\tw@\fi
172 | \ifx#1t\addtoLaTeXparams{t}\fi
173 | \ifx#1b\addtoLaTeXparams{b}\fi
174 | \ifx#1p\addtoLaTeXparams{p}\fi
175 | \ifx#1h\addtoLaTeXparams{h}\fi
176 | \ifx#1X\BoxFrametrue\fi
177 | \ifx#1O\OverFrametrue\fi
178 | \ifx#1U\UnderFrametrue\fi
179 | \ifx#1w
180 | \ifnum\draft=1\wasdrafttrue\else\wasdraftfalse\fi
181 | \draft=\@ne
182 | \fi
183 | \let\next=\readFRAMEparams
184 | \fi
185 | \next
186 | }%
187 | %
188 | %Macro for In-line graphics object
189 | % \IFRAME{ contentswidth (scalar) } %#1
190 | % { contentsheight (scalar) } %#2
191 | % { vertical shift when in-line (scalar) } %#3
192 | % { draft name } %#4
193 | % { body } %#5
194 | % { caption} %#6
195 |
196 |
197 | \def\IFRAME#1#2#3#4#5#6{%
198 | \bgroup
199 | \let\QCTOptA\empty
200 | \let\QCTOptB\empty
201 | \let\QCBOptA\empty
202 | \let\QCBOptB\empty
203 | #6%
204 | \parindent=0pt%
205 | \leftskip=0pt
206 | \rightskip=0pt
207 | \setbox0 = \hbox{\QCBOptA}%
208 | \@tempdima = #1\relax
209 | \ifOverFrame
210 | % Do this later
211 | \typeout{This is not implemented yet}%
212 | \show\HELP
213 | \else
214 | \ifdim\wd0>\@tempdima
215 | \advance\@tempdima by \@tempdima
216 | \ifdim\wd0 >\@tempdima
217 | \textwidth=\@tempdima
218 | \setbox1 =\vbox{%
219 | \noindent\hbox to \@tempdima{\hfill\GRAPHIC{#5}{#4}{#1}{#2}{#3}\hfill}\\%
220 | \noindent\hbox to \@tempdima{\parbox[b]{\@tempdima}{\QCBOptA}}%
221 | }%
222 | \wd1=\@tempdima
223 | \else
224 | \textwidth=\wd0
225 | \setbox1 =\vbox{%
226 | \noindent\hbox to \wd0{\hfill\GRAPHIC{#5}{#4}{#1}{#2}{#3}\hfill}\\%
227 | \noindent\hbox{\QCBOptA}%
228 | }%
229 | \wd1=\wd0
230 | \fi
231 | \else
232 | %\show\BBB
233 | \ifdim\wd0>0pt
234 | \hsize=\@tempdima
235 | \setbox1 =\vbox{%
236 | \unskip\GRAPHIC{#5}{#4}{#1}{#2}{0pt}%
237 | \break
238 | \unskip\hbox to \@tempdima{\hfill \QCBOptA\hfill}%
239 | }%
240 | \wd1=\@tempdima
241 | \else
242 | \hsize=\@tempdima
243 | \setbox1 =\vbox{%
244 | \unskip\GRAPHIC{#5}{#4}{#1}{#2}{0pt}%
245 | }%
246 | \wd1=\@tempdima
247 | \fi
248 | \fi
249 | \@tempdimb=\ht1
250 | \advance\@tempdimb by \dp1
251 | \advance\@tempdimb by -#2%
252 | \advance\@tempdimb by #3%
253 | \leavevmode
254 | \raise -\@tempdimb \hbox{\box1}%
255 | \fi
256 | \egroup%
257 | }%
258 | %
259 | %Macro for Display graphics object
260 | % \DFRAME{ contentswidth (scalar) } %#1
261 | % { contentsheight (scalar) } %#2
262 | % { draft label } %#3
263 | % { name } %#4
264 | % { caption} %#5
265 | \def\DFRAME#1#2#3#4#5{%
266 | \begin{center}
267 | \let\QCTOptA\empty
268 | \let\QCTOptB\empty
269 | \let\QCBOptA\empty
270 | \let\QCBOptB\empty
271 | \ifOverFrame
272 | #5\QCTOptA\par
273 | \fi
274 | \GRAPHIC{#4}{#3}{#1}{#2}{\z@}
275 | \ifUnderFrame
276 | \nobreak\par\nobreak#5\QCBOptA
277 | \fi
278 | \end{center}%
279 | }%
280 | %
281 | %Macro for Floating graphic object
282 | % \FFRAME{ framedata f|i tbph x F|T } %#1
283 | % { contentswidth (scalar) } %#2
284 | % { contentsheight (scalar) } %#3
285 | % { caption } %#4
286 | % { label } %#5
287 | % { draft name } %#6
288 | % { body } %#7
289 | \def\FFRAME#1#2#3#4#5#6#7{%
290 | %If float.sty loaded and float option is 'h', change to 'H' (gp) 1998/09/05
291 | \@ifundefined{floatstyle}
292 | {%floatstyle undefined (and float.sty not present), no change
293 | \begin{figure}[#1]%
294 | }
295 | {%floatstyle DEFINED
296 | \ifx#1h%Only the h parameter, change to H
297 | \begin{figure}[H]%
298 | \else
299 | \begin{figure}[#1]%
300 | \fi
301 | }
302 | \let\QCTOptA\empty
303 | \let\QCTOptB\empty
304 | \let\QCBOptA\empty
305 | \let\QCBOptB\empty
306 | \ifOverFrame
307 | #4
308 | \ifx\QCTOptA\empty
309 | \else
310 | \ifx\QCTOptB\empty
311 | \caption{\QCTOptA}%
312 | \else
313 | \caption[\QCTOptB]{\QCTOptA}%
314 | \fi
315 | \fi
316 | \ifUnderFrame\else
317 | \label{#5}%
318 | \fi
319 | \else
320 | \UnderFrametrue%
321 | \fi
322 | \begin{center}\GRAPHIC{#7}{#6}{#2}{#3}{\z@}\end{center}%
323 | \ifUnderFrame
324 | #4
325 | \ifx\QCBOptA\empty
326 | \caption{}%
327 | \else
328 | \ifx\QCBOptB\empty
329 | \caption{\QCBOptA}%
330 | \else
331 | \caption[\QCBOptB]{\QCBOptA}%
332 | \fi
333 | \fi
334 | \label{#5}%
335 | \fi
336 | \end{figure}%
337 | }%
338 | %
339 | %
340 | % \FRAME{ framedata f|i tbph x F|T } %#1
341 | % { contentswidth (scalar) } %#2
342 | % { contentsheight (scalar) } %#3
343 | % { vertical shift when in-line (scalar) } %#4
344 | % { caption } %#5
345 | % { label } %#6
346 | % { name } %#7
347 | % { body } %#8
348 | %
349 | % framedata is a string which can contain the following
350 | % characters: idftbphxFT
351 | % Their meaning is as follows:
352 | % i, d or f : in-line, display, or floating
353 | % t,b,p,h : LaTeX floating placement options
354 | % x : fit contents box to contents
355 | % F or T : Figure or Table.
356 | % Later this can expand
357 | % to a more general float class.
358 | %
359 | %
360 | \newcount\dispkind%
361 |
362 | \def\makeactives{
363 | \catcode`\"=\active
364 | \catcode`\;=\active
365 | \catcode`\:=\active
366 | \catcode`\'=\active
367 | \catcode`\~=\active
368 | }
369 | \bgroup
370 | \makeactives
371 | \gdef\activesoff{%
372 | \def"{\string"}
373 | \def;{\string;}
374 | \def:{\string:}
375 | \def'{\string'}
376 | \def~{\string~}
377 | %\bbl@deactivate{"}%
378 | %\bbl@deactivate{;}%
379 | %\bbl@deactivate{:}%
380 | %\bbl@deactivate{'}%
381 | }
382 | \egroup
383 |
384 | \def\FRAME#1#2#3#4#5#6#7#8{%
385 | \bgroup
386 | \ifnum\draft=\@ne
387 | \wasdrafttrue
388 | \else
389 | \wasdraftfalse%
390 | \fi
391 | \def\LaTeXparams{}%
392 | \dispkind=\z@
393 | \def\LaTeXparams{}%
394 | \doFRAMEparams{#1}%
395 | \ifnum\dispkind=\z@\IFRAME{#2}{#3}{#4}{#7}{#8}{#5}\else
396 | \ifnum\dispkind=\@ne\DFRAME{#2}{#3}{#7}{#8}{#5}\else
397 | \ifnum\dispkind=\tw@
398 | \edef\@tempa{\noexpand\FFRAME{\LaTeXparams}}%
399 | \@tempa{#2}{#3}{#5}{#6}{#7}{#8}%
400 | \fi
401 | \fi
402 | \fi
403 | \ifwasdraft\draft=1\else\draft=0\fi{}%
404 | \egroup
405 | }%
406 | %
407 | % This macro added to let SW gobble a parameter that
408 | % should not be passed on and expanded.
409 |
410 | \def\TEXUX#1{"texux"}
411 |
412 | %
413 | % Macros for text attributes:
414 | %
415 | \def\BF#1{{\bf {#1}}}%
416 | \def\NEG#1{\leavevmode\hbox{\rlap{\thinspace/}{$#1$}}}%
417 | %
418 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
419 | %
420 | %
421 | % macros for user - defined functions
422 | \def\limfunc#1{\mathop{\rm #1}}%
423 | \def\func#1{\mathop{\rm #1}\nolimits}%
424 | % macro for unit names
425 | \def\unit#1{\mathop{\rm #1}\nolimits}%
426 |
427 | %
428 | % miscellaneous
429 | \long\def\QQQ#1#2{%
430 | \long\expandafter\def\csname#1\endcsname{#2}}%
431 | \@ifundefined{QTP}{\def\QTP#1{}}{}
432 | \@ifundefined{QEXCLUDE}{\def\QEXCLUDE#1{}}{}
433 | \@ifundefined{Qlb}{\def\Qlb#1{#1}}{}
434 | \@ifundefined{Qlt}{\def\Qlt#1{#1}}{}
435 | \def\QWE{}%
436 | \long\def\QQA#1#2{}%
437 | \def\QTR#1#2{{\csname#1\endcsname #2}}%(gp) Is this the best?
438 | \long\def\TeXButton#1#2{#2}%
439 | \long\def\QSubDoc#1#2{#2}%
440 | \def\EXPAND#1[#2]#3{}%
441 | \def\NOEXPAND#1[#2]#3{}%
442 | \def\PROTECTED{}%
443 | \def\LaTeXparent#1{}%
444 | \def\ChildStyles#1{}%
445 | \def\ChildDefaults#1{}%
446 | \def\QTagDef#1#2#3{}%
447 |
448 | % Constructs added with Scientific Notebook
449 | \@ifundefined{correctchoice}{\def\correctchoice{\relax}}{}
450 | \@ifundefined{HTML}{\def\HTML#1{\relax}}{}
451 | \@ifundefined{TCIIcon}{\def\TCIIcon#1#2#3#4{\relax}}{}
452 | \if@compatibility
453 | \typeout{Not defining UNICODE or CustomNote commands for LaTeX 2.09.}
454 | \else
455 | \providecommand{\UNICODE}[2][]{}
456 | \providecommand{\CustomNote}[3][]{\marginpar{#3}}
457 | \fi
458 |
459 | %
460 | % Macros for style editor docs
461 | \@ifundefined{StyleEditBeginDoc}{\def\StyleEditBeginDoc{\relax}}{}
462 | %
463 | % Macros for footnotes
464 | \def\QQfnmark#1{\footnotemark}
465 | \def\QQfntext#1#2{\addtocounter{footnote}{#1}\footnotetext{#2}}
466 | %
467 | % Macros for indexing.
468 | %
469 | \@ifundefined{TCIMAKEINDEX}{}{\makeindex}%
470 | %
471 | % Attempts to avoid problems with other styles
472 | \@ifundefined{abstract}{%
473 | \def\abstract{%
474 | \if@twocolumn
475 | \section*{Abstract (Not appropriate in this style!)}%
476 | \else \small
477 | \begin{center}{\bf Abstract\vspace{-.5em}\vspace{\z@}}\end{center}%
478 | \quotation
479 | \fi
480 | }%
481 | }{%
482 | }%
483 | \@ifundefined{endabstract}{\def\endabstract
484 | {\if@twocolumn\else\endquotation\fi}}{}%
485 | \@ifundefined{maketitle}{\def\maketitle#1{}}{}%
486 | \@ifundefined{affiliation}{\def\affiliation#1{}}{}%
487 | \@ifundefined{proof}{\def\proof{\noindent{\bfseries Proof. }}}{}%
488 | \@ifundefined{endproof}{\def\endproof{\mbox{\ \rule{.1in}{.1in}}}}{}%
489 | \@ifundefined{newfield}{\def\newfield#1#2{}}{}%
490 | \@ifundefined{chapter}{\def\chapter#1{\par(Chapter head:)#1\par }%
491 | \newcount\c@chapter}{}%
492 | \@ifundefined{part}{\def\part#1{\par(Part head:)#1\par }}{}%
493 | \@ifundefined{section}{\def\section#1{\par(Section head:)#1\par }}{}%
494 | \@ifundefined{subsection}{\def\subsection#1%
495 | {\par(Subsection head:)#1\par }}{}%
496 | \@ifundefined{subsubsection}{\def\subsubsection#1%
497 | {\par(Subsubsection head:)#1\par }}{}%
498 | \@ifundefined{paragraph}{\def\paragraph#1%
499 | {\par(Subsubsubsection head:)#1\par }}{}%
500 | \@ifundefined{subparagraph}{\def\subparagraph#1%
501 | {\par(Subsubsubsubsection head:)#1\par }}{}%
502 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
503 | % These symbols are not recognized by LaTeX
504 | \@ifundefined{therefore}{\def\therefore{}}{}%
505 | \@ifundefined{backepsilon}{\def\backepsilon{}}{}%
506 | \@ifundefined{yen}{\def\yen{\hbox{\rm\rlap=Y}}}{}%
507 | \@ifundefined{registered}{%
508 | \def\registered{\relax\ifmmode{}\r@gistered
509 | \else$\m@th\r@gistered$\fi}%
510 | \def\r@gistered{^{\ooalign
511 | {\hfil\raise.07ex\hbox{$\scriptstyle\rm\text{R}$}\hfil\crcr
512 | \mathhexbox20D}}}}{}%
513 | \@ifundefined{Eth}{\def\Eth{}}{}%
514 | \@ifundefined{eth}{\def\eth{}}{}%
515 | \@ifundefined{Thorn}{\def\Thorn{}}{}%
516 | \@ifundefined{thorn}{\def\thorn{}}{}%
517 | % A macro to allow any symbol that requires math to appear in text
518 | \def\TEXTsymbol#1{\mbox{$#1$}}%
519 | \@ifundefined{degree}{\def\degree{{}^{\circ}}}{}%
520 | %
521 | % macros for T3TeX files
522 | \newdimen\theight
523 | \def\Column{%
524 | \vadjust{\setbox\z@=\hbox{\scriptsize\quad\quad tcol}%
525 | \theight=\ht\z@\advance\theight by \dp\z@\advance\theight by \lineskip
526 | \kern -\theight \vbox to \theight{%
527 | \rightline{\rlap{\box\z@}}%
528 | \vss
529 | }%
530 | }%
531 | }%
532 | %
533 | \def\qed{%
534 | \ifhmode\unskip\nobreak\fi\ifmmode\ifinner\else\hskip5\p@\fi\fi
535 | \hbox{\hskip5\p@\vrule width4\p@ height6\p@ depth1.5\p@\hskip\p@}%
536 | }%
537 | %
538 | \def\cents{\hbox{\rm\rlap/c}}%
539 | \def\miss{\hbox{\vrule height2\p@ width 2\p@ depth\z@}}%
540 | %
541 | \def\vvert{\Vert}% %always translated to \left| or \right|
542 | %
543 | \def\tcol#1{{\baselineskip=6\p@ \vcenter{#1}} \Column} %
544 | %
545 | \def\dB{\hbox{{}}}% %dummy entry in column
546 | \def\mB#1{\hbox{$#1$}}% %column entry
547 | \def\nB#1{\hbox{#1}}% %column entry (not math)
548 | %
549 | \@ifundefined{note}{\def\note{$^{\dag}}}{}%
550 | %
551 |
552 | \def\newfmtname{LaTeX2e}
553 | % No longer load latexsym. This is now handled by SWP, which uses amsfonts if necessary
554 |
555 | \ifx\fmtname\newfmtname
556 | \DeclareOldFontCommand{\rm}{\normalfont\rmfamily}{\mathrm}
557 | \DeclareOldFontCommand{\sf}{\normalfont\sffamily}{\mathsf}
558 | \DeclareOldFontCommand{\tt}{\normalfont\ttfamily}{\mathtt}
559 | \DeclareOldFontCommand{\bf}{\normalfont\bfseries}{\mathbf}
560 | \DeclareOldFontCommand{\it}{\normalfont\itshape}{\mathit}
561 | \DeclareOldFontCommand{\sl}{\normalfont\slshape}{\@nomath\sl}
562 | \DeclareOldFontCommand{\sc}{\normalfont\scshape}{\@nomath\sc}
563 | \fi
564 |
565 | %
566 | % Greek bold macros
567 | % Redefine all of the math symbols
568 | % which might be bolded - there are
569 | % probably others to add to this list
570 |
571 | \def\alpha{{\Greekmath 010B}}%
572 | \def\beta{{\Greekmath 010C}}%
573 | \def\gamma{{\Greekmath 010D}}%
574 | \def\delta{{\Greekmath 010E}}%
575 | \def\epsilon{{\Greekmath 010F}}%
576 | \def\zeta{{\Greekmath 0110}}%
577 | \def\eta{{\Greekmath 0111}}%
578 | \def\theta{{\Greekmath 0112}}%
579 | \def\iota{{\Greekmath 0113}}%
580 | \def\kappa{{\Greekmath 0114}}%
581 | \def\lambda{{\Greekmath 0115}}%
582 | \def\mu{{\Greekmath 0116}}%
583 | \def\nu{{\Greekmath 0117}}%
584 | \def\xi{{\Greekmath 0118}}%
585 | \def\pi{{\Greekmath 0119}}%
586 | \def\rho{{\Greekmath 011A}}%
587 | \def\sigma{{\Greekmath 011B}}%
588 | \def\tau{{\Greekmath 011C}}%
589 | \def\upsilon{{\Greekmath 011D}}%
590 | \def\phi{{\Greekmath 011E}}%
591 | \def\chi{{\Greekmath 011F}}%
592 | \def\psi{{\Greekmath 0120}}%
593 | \def\omega{{\Greekmath 0121}}%
594 | \def\varepsilon{{\Greekmath 0122}}%
595 | \def\vartheta{{\Greekmath 0123}}%
596 | \def\varpi{{\Greekmath 0124}}%
597 | \def\varrho{{\Greekmath 0125}}%
598 | \def\varsigma{{\Greekmath 0126}}%
599 | \def\varphi{{\Greekmath 0127}}%
600 |
601 | \def\nabla{{\Greekmath 0272}}
602 | \def\FindBoldGroup{%
603 | {\setbox0=\hbox{$\mathbf{x\global\edef\theboldgroup{\the\mathgroup}}$}}%
604 | }
605 |
606 | \def\Greekmath#1#2#3#4{%
607 | \if@compatibility
608 | \ifnum\mathgroup=\symbold
609 | \mathchoice{\mbox{\boldmath$\displaystyle\mathchar"#1#2#3#4$}}%
610 | {\mbox{\boldmath$\textstyle\mathchar"#1#2#3#4$}}%
611 | {\mbox{\boldmath$\scriptstyle\mathchar"#1#2#3#4$}}%
612 | {\mbox{\boldmath$\scriptscriptstyle\mathchar"#1#2#3#4$}}%
613 | \else
614 | \mathchar"#1#2#3#4%
615 | \fi
616 | \else
617 | \FindBoldGroup
618 | \ifnum\mathgroup=\theboldgroup % For 2e
619 | \mathchoice{\mbox{\boldmath$\displaystyle\mathchar"#1#2#3#4$}}%
620 | {\mbox{\boldmath$\textstyle\mathchar"#1#2#3#4$}}%
621 | {\mbox{\boldmath$\scriptstyle\mathchar"#1#2#3#4$}}%
622 | {\mbox{\boldmath$\scriptscriptstyle\mathchar"#1#2#3#4$}}%
623 | \else
624 | \mathchar"#1#2#3#4%
625 | \fi
626 | \fi}
627 |
628 | \newif\ifGreekBold \GreekBoldfalse
629 | \let\SAVEPBF=\pbf
630 | \def\pbf{\GreekBoldtrue\SAVEPBF}%
631 | %
632 |
633 | \@ifundefined{theorem}{\newtheorem{theorem}{Theorem}}{}
634 | \@ifundefined{lemma}{\newtheorem{lemma}[theorem]{Lemma}}{}
635 | \@ifundefined{corollary}{\newtheorem{corollary}[theorem]{Corollary}}{}
636 | \@ifundefined{conjecture}{\newtheorem{conjecture}[theorem]{Conjecture}}{}
637 | \@ifundefined{proposition}{\newtheorem{proposition}[theorem]{Proposition}}{}
638 | \@ifundefined{axiom}{\newtheorem{axiom}{Axiom}}{}
639 | \@ifundefined{remark}{\newtheorem{remark}{Remark}}{}
640 | \@ifundefined{example}{\newtheorem{example}{Example}}{}
641 | \@ifundefined{exercise}{\newtheorem{exercise}{Exercise}}{}
642 | \@ifundefined{definition}{\newtheorem{definition}{Definition}}{}
643 |
644 |
645 | \@ifundefined{mathletters}{%
646 | %\def\theequation{\arabic{equation}}
647 | \newcounter{equationnumber}
648 | \def\mathletters{%
649 | \addtocounter{equation}{1}
650 | \edef\@currentlabel{\theequation}%
651 | \setcounter{equationnumber}{\c@equation}
652 | \setcounter{equation}{0}%
653 | \edef\theequation{\@currentlabel\noexpand\alph{equation}}%
654 | }
655 | \def\endmathletters{%
656 | \setcounter{equation}{\value{equationnumber}}%
657 | }
658 | }{}
659 |
660 | %Logos
661 | \@ifundefined{BibTeX}{%
662 | \def\BibTeX{{\rm B\kern-.05em{\sc i\kern-.025em b}\kern-.08em
663 | T\kern-.1667em\lower.7ex\hbox{E}\kern-.125emX}}}{}%
664 | \@ifundefined{AmS}%
665 | {\def\AmS{{\protect\usefont{OMS}{cmsy}{m}{n}%
666 | A\kern-.1667em\lower.5ex\hbox{M}\kern-.125emS}}}{}%
667 | \@ifundefined{AmSTeX}{\def\AmSTeX{\protect\AmS-\protect\TeX\@}}{}%
668 | %
669 |
670 | % This macro is a fix to eqnarray
671 | \def\@@eqncr{\let\@tempa\relax
672 | \ifcase\@eqcnt \def\@tempa{& & &}\or \def\@tempa{& &}%
673 | \else \def\@tempa{&}\fi
674 | \@tempa
675 | \if@eqnsw
676 | \iftag@
677 | \@taggnum
678 | \else
679 | \@eqnnum\stepcounter{equation}%
680 | \fi
681 | \fi
682 | \global\tag@false
683 | \global\@eqnswtrue
684 | \global\@eqcnt\z@\cr}
685 |
686 |
687 | \def\TCItag{\@ifnextchar*{\@TCItagstar}{\@TCItag}}
688 | \def\@TCItag#1{%
689 | \global\tag@true
690 | \global\def\@taggnum{(#1)}}
691 | \def\@TCItagstar*#1{%
692 | \global\tag@true
693 | \global\def\@taggnum{#1}}
694 | %
695 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
696 | %
697 | \def\tfrac#1#2{{\textstyle {#1 \over #2}}}%
698 | \def\dfrac#1#2{{\displaystyle {#1 \over #2}}}%
699 | \def\binom#1#2{{#1 \choose #2}}%
700 | \def\tbinom#1#2{{\textstyle {#1 \choose #2}}}%
701 | \def\dbinom#1#2{{\displaystyle {#1 \choose #2}}}%
702 | \def\QATOP#1#2{{#1 \atop #2}}%
703 | \def\QTATOP#1#2{{\textstyle {#1 \atop #2}}}%
704 | \def\QDATOP#1#2{{\displaystyle {#1 \atop #2}}}%
705 | \def\QABOVE#1#2#3{{#2 \above#1 #3}}%
706 | \def\QTABOVE#1#2#3{{\textstyle {#2 \above#1 #3}}}%
707 | \def\QDABOVE#1#2#3{{\displaystyle {#2 \above#1 #3}}}%
708 | \def\QOVERD#1#2#3#4{{#3 \overwithdelims#1#2 #4}}%
709 | \def\QTOVERD#1#2#3#4{{\textstyle {#3 \overwithdelims#1#2 #4}}}%
710 | \def\QDOVERD#1#2#3#4{{\displaystyle {#3 \overwithdelims#1#2 #4}}}%
711 | \def\QATOPD#1#2#3#4{{#3 \atopwithdelims#1#2 #4}}%
712 | \def\QTATOPD#1#2#3#4{{\textstyle {#3 \atopwithdelims#1#2 #4}}}%
713 | \def\QDATOPD#1#2#3#4{{\displaystyle {#3 \atopwithdelims#1#2 #4}}}%
714 | \def\QABOVED#1#2#3#4#5{{#4 \abovewithdelims#1#2#3 #5}}%
715 | \def\QTABOVED#1#2#3#4#5{{\textstyle
716 | {#4 \abovewithdelims#1#2#3 #5}}}%
717 | \def\QDABOVED#1#2#3#4#5{{\displaystyle
718 | {#4 \abovewithdelims#1#2#3 #5}}}%
719 | %
720 | % Macros for text size operators:
721 | %
722 | \def\tint{\mathop{\textstyle \int}}%
723 | \def\tiint{\mathop{\textstyle \iint }}%
724 | \def\tiiint{\mathop{\textstyle \iiint }}%
725 | \def\tiiiint{\mathop{\textstyle \iiiint }}%
726 | \def\tidotsint{\mathop{\textstyle \idotsint }}%
727 | \def\toint{\mathop{\textstyle \oint}}%
728 | \def\tsum{\mathop{\textstyle \sum }}%
729 | \def\tprod{\mathop{\textstyle \prod }}%
730 | \def\tbigcap{\mathop{\textstyle \bigcap }}%
731 | \def\tbigwedge{\mathop{\textstyle \bigwedge }}%
732 | \def\tbigoplus{\mathop{\textstyle \bigoplus }}%
733 | \def\tbigodot{\mathop{\textstyle \bigodot }}%
734 | \def\tbigsqcup{\mathop{\textstyle \bigsqcup }}%
735 | \def\tcoprod{\mathop{\textstyle \coprod }}%
736 | \def\tbigcup{\mathop{\textstyle \bigcup }}%
737 | \def\tbigvee{\mathop{\textstyle \bigvee }}%
738 | \def\tbigotimes{\mathop{\textstyle \bigotimes }}%
739 | \def\tbiguplus{\mathop{\textstyle \biguplus }}%
740 | %
741 | %
742 | %Macros for display size operators:
743 | %
744 | \def\dint{\mathop{\displaystyle \int}}%
745 | \def\diint{\mathop{\displaystyle \iint }}%
746 | \def\diiint{\mathop{\displaystyle \iiint }}%
747 | \def\diiiint{\mathop{\displaystyle \iiiint }}%
748 | \def\didotsint{\mathop{\displaystyle \idotsint }}%
749 | \def\doint{\mathop{\displaystyle \oint}}%
750 | \def\dsum{\mathop{\displaystyle \sum }}%
751 | \def\dprod{\mathop{\displaystyle \prod }}%
752 | \def\dbigcap{\mathop{\displaystyle \bigcap }}%
753 | \def\dbigwedge{\mathop{\displaystyle \bigwedge }}%
754 | \def\dbigoplus{\mathop{\displaystyle \bigoplus }}%
755 | \def\dbigodot{\mathop{\displaystyle \bigodot }}%
756 | \def\dbigsqcup{\mathop{\displaystyle \bigsqcup }}%
757 | \def\dcoprod{\mathop{\displaystyle \coprod }}%
758 | \def\dbigcup{\mathop{\displaystyle \bigcup }}%
759 | \def\dbigvee{\mathop{\displaystyle \bigvee }}%
760 | \def\dbigotimes{\mathop{\displaystyle \bigotimes }}%
761 | \def\dbiguplus{\mathop{\displaystyle \biguplus }}%
762 |
763 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
764 | % NOTE: The rest of this file is read only if amstex has not been
765 | % loaded. This section is used to define amstex constructs in the
766 | % event they have not been defined.
767 | %
768 | %
769 | \ifx\ds@amstex\relax
770 | \message{amstex already loaded}\makeatother\endinput% 2.09 compatability
771 | \else
772 | \@ifpackageloaded{amsmath}%
773 | {\message{amsmath already loaded}\makeatother\endinput}
774 | {}
775 | \@ifpackageloaded{amstex}%
776 | {\message{amstex already loaded}\makeatother\endinput}
777 | {}
778 | \@ifpackageloaded{amsgen}%
779 | {\message{amsgen already loaded}\makeatother\endinput}
780 | {}
781 | \fi
782 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
783 | %%
784 | %
785 | %
786 | % Macros to define some AMS LaTeX constructs when
787 | % AMS LaTeX has not been loaded
788 | %
789 | % These macros are copied from the AMS-TeX package for doing
790 | % multiple integrals.
791 | %
792 | \let\DOTSI\relax
793 | \def\RIfM@{\relax\ifmmode}%
794 | \def\FN@{\futurelet\next}%
795 | \newcount\intno@
796 | \def\iint{\DOTSI\intno@\tw@\FN@\ints@}%
797 | \def\iiint{\DOTSI\intno@\thr@@\FN@\ints@}%
798 | \def\iiiint{\DOTSI\intno@4 \FN@\ints@}%
799 | \def\idotsint{\DOTSI\intno@\z@\FN@\ints@}%
800 | \def\ints@{\findlimits@\ints@@}%
801 | \newif\iflimtoken@
802 | \newif\iflimits@
803 | \def\findlimits@{\limtoken@true\ifx\next\limits\limits@true
804 | \else\ifx\next\nolimits\limits@false\else
805 | \limtoken@false\ifx\ilimits@\nolimits\limits@false\else
806 | \ifinner\limits@false\else\limits@true\fi\fi\fi\fi}%
807 | \def\multint@{\int\ifnum\intno@=\z@\intdots@ %1
808 | \else\intkern@\fi %2
809 | \ifnum\intno@>\tw@\int\intkern@\fi %3
810 | \ifnum\intno@>\thr@@\int\intkern@\fi %4
811 | \int}% %5
812 | \def\multintlimits@{\intop\ifnum\intno@=\z@\intdots@\else\intkern@\fi
813 | \ifnum\intno@>\tw@\intop\intkern@\fi
814 | \ifnum\intno@>\thr@@\intop\intkern@\fi\intop}%
815 | \def\intic@{%
816 | \mathchoice{\hskip.5em}{\hskip.4em}{\hskip.4em}{\hskip.4em}}%
817 | \def\negintic@{\mathchoice
818 | {\hskip-.5em}{\hskip-.4em}{\hskip-.4em}{\hskip-.4em}}%
819 | \def\ints@@{\iflimtoken@ %1
820 | \def\ints@@@{\iflimits@\negintic@
821 | \mathop{\intic@\multintlimits@}\limits %2
822 | \else\multint@\nolimits\fi %3
823 | \eat@}% %4
824 | \else %5
825 | \def\ints@@@{\iflimits@\negintic@
826 | \mathop{\intic@\multintlimits@}\limits\else
827 | \multint@\nolimits\fi}\fi\ints@@@}%
828 | \def\intkern@{\mathchoice{\!\!\!}{\!\!}{\!\!}{\!\!}}%
829 | \def\plaincdots@{\mathinner{\cdotp\cdotp\cdotp}}%
830 | \def\intdots@{\mathchoice{\plaincdots@}%
831 | {{\cdotp}\mkern1.5mu{\cdotp}\mkern1.5mu{\cdotp}}%
832 | {{\cdotp}\mkern1mu{\cdotp}\mkern1mu{\cdotp}}%
833 | {{\cdotp}\mkern1mu{\cdotp}\mkern1mu{\cdotp}}}%
834 | %
835 | %
836 | % These macros are for doing the AMS \text{} construct
837 | %
838 | \def\RIfM@{\relax\protect\ifmmode}
839 | \def\text{\RIfM@\expandafter\text@\else\expandafter\mbox\fi}
840 | \let\nfss@text\text
841 | \def\text@#1{\mathchoice
842 | {\textdef@\displaystyle\f@size{#1}}%
843 | {\textdef@\textstyle\tf@size{\firstchoice@false #1}}%
844 | {\textdef@\textstyle\sf@size{\firstchoice@false #1}}%
845 | {\textdef@\textstyle \ssf@size{\firstchoice@false #1}}%
846 | \glb@settings}
847 |
848 | \def\textdef@#1#2#3{\hbox{{%
849 | \everymath{#1}%
850 | \let\f@size#2\selectfont
851 | #3}}}
852 | \newif\iffirstchoice@
853 | \firstchoice@true
854 | %
855 | %These are the AMS constructs for multiline limits.
856 | %
857 | \def\Let@{\relax\iffalse{\fi\let\\=\cr\iffalse}\fi}%
858 | \def\vspace@{\def\vspace##1{\crcr\noalign{\vskip##1\relax}}}%
859 | \def\multilimits@{\bgroup\vspace@\Let@
860 | \baselineskip\fontdimen10 \scriptfont\tw@
861 | \advance\baselineskip\fontdimen12 \scriptfont\tw@
862 | \lineskip\thr@@\fontdimen8 \scriptfont\thr@@
863 | \lineskiplimit\lineskip
864 | \vbox\bgroup\ialign\bgroup\hfil$\m@th\scriptstyle{##}$\hfil\crcr}%
865 | \def\Sb{_\multilimits@}%
866 | \def\endSb{\crcr\egroup\egroup\egroup}%
867 | \def\Sp{^\multilimits@}%
868 | \let\endSp\endSb
869 | %
870 | %
871 | %These are AMS constructs for horizontal arrows
872 | %
873 | \newdimen\ex@
874 | \ex@.2326ex
875 | \def\rightarrowfill@#1{$#1\m@th\mathord-\mkern-6mu\cleaders
876 | \hbox{$#1\mkern-2mu\mathord-\mkern-2mu$}\hfill
877 | \mkern-6mu\mathord\rightarrow$}%
878 | \def\leftarrowfill@#1{$#1\m@th\mathord\leftarrow\mkern-6mu\cleaders
879 | \hbox{$#1\mkern-2mu\mathord-\mkern-2mu$}\hfill\mkern-6mu\mathord-$}%
880 | \def\leftrightarrowfill@#1{$#1\m@th\mathord\leftarrow
881 | \mkern-6mu\cleaders
882 | \hbox{$#1\mkern-2mu\mathord-\mkern-2mu$}\hfill
883 | \mkern-6mu\mathord\rightarrow$}%
884 | \def\overrightarrow{\mathpalette\overrightarrow@}%
885 | \def\overrightarrow@#1#2{\vbox{\ialign{##\crcr\rightarrowfill@#1\crcr
886 | \noalign{\kern-\ex@\nointerlineskip}$\m@th\hfil#1#2\hfil$\crcr}}}%
887 | \let\overarrow\overrightarrow
888 | \def\overleftarrow{\mathpalette\overleftarrow@}%
889 | \def\overleftarrow@#1#2{\vbox{\ialign{##\crcr\leftarrowfill@#1\crcr
890 | \noalign{\kern-\ex@\nointerlineskip}$\m@th\hfil#1#2\hfil$\crcr}}}%
891 | \def\overleftrightarrow{\mathpalette\overleftrightarrow@}%
892 | \def\overleftrightarrow@#1#2{\vbox{\ialign{##\crcr
893 | \leftrightarrowfill@#1\crcr
894 | \noalign{\kern-\ex@\nointerlineskip}$\m@th\hfil#1#2\hfil$\crcr}}}%
895 | \def\underrightarrow{\mathpalette\underrightarrow@}%
896 | \def\underrightarrow@#1#2{\vtop{\ialign{##\crcr$\m@th\hfil#1#2\hfil
897 | $\crcr\noalign{\nointerlineskip}\rightarrowfill@#1\crcr}}}%
898 | \let\underarrow\underrightarrow
899 | \def\underleftarrow{\mathpalette\underleftarrow@}%
900 | \def\underleftarrow@#1#2{\vtop{\ialign{##\crcr$\m@th\hfil#1#2\hfil
901 | $\crcr\noalign{\nointerlineskip}\leftarrowfill@#1\crcr}}}%
902 | \def\underleftrightarrow{\mathpalette\underleftrightarrow@}%
903 | \def\underleftrightarrow@#1#2{\vtop{\ialign{##\crcr$\m@th
904 | \hfil#1#2\hfil$\crcr
905 | \noalign{\nointerlineskip}\leftrightarrowfill@#1\crcr}}}%
906 | %%%%%%%%%%%%%%%%%%%%%
907 |
908 | \def\qopnamewl@#1{\mathop{\operator@font#1}\nlimits@}
909 | \let\nlimits@\displaylimits
910 | \def\setboxz@h{\setbox\z@\hbox}
911 |
912 |
913 | \def\varlim@#1#2{\mathop{\vtop{\ialign{##\crcr
914 | \hfil$#1\m@th\operator@font lim$\hfil\crcr
915 | \noalign{\nointerlineskip}#2#1\crcr
916 | \noalign{\nointerlineskip\kern-\ex@}\crcr}}}}
917 |
918 | \def\rightarrowfill@#1{\m@th\setboxz@h{$#1-$}\ht\z@\z@
919 | $#1\copy\z@\mkern-6mu\cleaders
920 | \hbox{$#1\mkern-2mu\box\z@\mkern-2mu$}\hfill
921 | \mkern-6mu\mathord\rightarrow$}
922 | \def\leftarrowfill@#1{\m@th\setboxz@h{$#1-$}\ht\z@\z@
923 | $#1\mathord\leftarrow\mkern-6mu\cleaders
924 | \hbox{$#1\mkern-2mu\copy\z@\mkern-2mu$}\hfill
925 | \mkern-6mu\box\z@$}
926 |
927 |
928 | \def\projlim{\qopnamewl@{proj\,lim}}
929 | \def\injlim{\qopnamewl@{inj\,lim}}
930 | \def\varinjlim{\mathpalette\varlim@\rightarrowfill@}
931 | \def\varprojlim{\mathpalette\varlim@\leftarrowfill@}
932 | \def\varliminf{\mathpalette\varliminf@{}}
933 | \def\varliminf@#1{\mathop{\underline{\vrule\@depth.2\ex@\@width\z@
934 | \hbox{$#1\m@th\operator@font lim$}}}}
935 | \def\varlimsup{\mathpalette\varlimsup@{}}
936 | \def\varlimsup@#1{\mathop{\overline
937 | {\hbox{$#1\m@th\operator@font lim$}}}}
938 |
939 | %
940 | %Companion to stackrel
941 | \def\stackunder#1#2{\mathrel{\mathop{#2}\limits_{#1}}}%
942 | %
943 | %
944 | % These are AMS environments that will be defined to
945 | % be verbatims if amstex has not actually been
946 | % loaded
947 | %
948 | %
949 | \begingroup \catcode `|=0 \catcode `[= 1
950 | \catcode`]=2 \catcode `\{=12 \catcode `\}=12
951 | \catcode`\\=12
952 | |gdef|@alignverbatim#1\end{align}[#1|end[align]]
953 | |gdef|@salignverbatim#1\end{align*}[#1|end[align*]]
954 |
955 | |gdef|@alignatverbatim#1\end{alignat}[#1|end[alignat]]
956 | |gdef|@salignatverbatim#1\end{alignat*}[#1|end[alignat*]]
957 |
958 | |gdef|@xalignatverbatim#1\end{xalignat}[#1|end[xalignat]]
959 | |gdef|@sxalignatverbatim#1\end{xalignat*}[#1|end[xalignat*]]
960 |
961 | |gdef|@gatherverbatim#1\end{gather}[#1|end[gather]]
962 | |gdef|@sgatherverbatim#1\end{gather*}[#1|end[gather*]]
963 |
964 | |gdef|@gatherverbatim#1\end{gather}[#1|end[gather]]
965 | |gdef|@sgatherverbatim#1\end{gather*}[#1|end[gather*]]
966 |
967 |
968 | |gdef|@multilineverbatim#1\end{multiline}[#1|end[multiline]]
969 | |gdef|@smultilineverbatim#1\end{multiline*}[#1|end[multiline*]]
970 |
971 | |gdef|@arraxverbatim#1\end{arrax}[#1|end[arrax]]
972 | |gdef|@sarraxverbatim#1\end{arrax*}[#1|end[arrax*]]
973 |
974 | |gdef|@tabulaxverbatim#1\end{tabulax}[#1|end[tabulax]]
975 | |gdef|@stabulaxverbatim#1\end{tabulax*}[#1|end[tabulax*]]
976 |
977 |
978 | |endgroup
979 |
980 |
981 |
982 | \def\align{\@verbatim \frenchspacing\@vobeyspaces \@alignverbatim
983 | You are using the "align" environment in a style in which it is not defined.}
984 | \let\endalign=\endtrivlist
985 |
986 | \@namedef{align*}{\@verbatim\@salignverbatim
987 | You are using the "align*" environment in a style in which it is not defined.}
988 | \expandafter\let\csname endalign*\endcsname =\endtrivlist
989 |
990 |
991 |
992 |
993 | \def\alignat{\@verbatim \frenchspacing\@vobeyspaces \@alignatverbatim
994 | You are using the "alignat" environment in a style in which it is not defined.}
995 | \let\endalignat=\endtrivlist
996 |
997 | \@namedef{alignat*}{\@verbatim\@salignatverbatim
998 | You are using the "alignat*" environment in a style in which it is not defined.}
999 | \expandafter\let\csname endalignat*\endcsname =\endtrivlist
1000 |
1001 |
1002 |
1003 |
1004 | \def\xalignat{\@verbatim \frenchspacing\@vobeyspaces \@xalignatverbatim
1005 | You are using the "xalignat" environment in a style in which it is not defined.}
1006 | \let\endxalignat=\endtrivlist
1007 |
1008 | \@namedef{xalignat*}{\@verbatim\@sxalignatverbatim
1009 | You are using the "xalignat*" environment in a style in which it is not defined.}
1010 | \expandafter\let\csname endxalignat*\endcsname =\endtrivlist
1011 |
1012 |
1013 |
1014 |
1015 | \def\gather{\@verbatim \frenchspacing\@vobeyspaces \@gatherverbatim
1016 | You are using the "gather" environment in a style in which it is not defined.}
1017 | \let\endgather=\endtrivlist
1018 |
1019 | \@namedef{gather*}{\@verbatim\@sgatherverbatim
1020 | You are using the "gather*" environment in a style in which it is not defined.}
1021 | \expandafter\let\csname endgather*\endcsname =\endtrivlist
1022 |
1023 |
1024 | \def\multiline{\@verbatim \frenchspacing\@vobeyspaces \@multilineverbatim
1025 | You are using the "multiline" environment in a style in which it is not defined.}
1026 | \let\endmultiline=\endtrivlist
1027 |
1028 | \@namedef{multiline*}{\@verbatim\@smultilineverbatim
1029 | You are using the "multiline*" environment in a style in which it is not defined.}
1030 | \expandafter\let\csname endmultiline*\endcsname =\endtrivlist
1031 |
1032 |
1033 | \def\arrax{\@verbatim \frenchspacing\@vobeyspaces \@arraxverbatim
1034 | You are using a type of "array" construct that is only allowed in AmS-LaTeX.}
1035 | \let\endarrax=\endtrivlist
1036 |
1037 | \def\tabulax{\@verbatim \frenchspacing\@vobeyspaces \@tabulaxverbatim
1038 | You are using a type of "tabular" construct that is only allowed in AmS-LaTeX.}
1039 | \let\endtabulax=\endtrivlist
1040 |
1041 |
1042 | \@namedef{arrax*}{\@verbatim\@sarraxverbatim
1043 | You are using a type of "array*" construct that is only allowed in AmS-LaTeX.}
1044 | \expandafter\let\csname endarrax*\endcsname =\endtrivlist
1045 |
1046 | \@namedef{tabulax*}{\@verbatim\@stabulaxverbatim
1047 | You are using a type of "tabular*" construct that is only allowed in AmS-LaTeX.}
1048 | \expandafter\let\csname endtabulax*\endcsname =\endtrivlist
1049 |
1050 | % macro to simulate ams tag construct
1051 |
1052 |
1053 | % This macro is a fix to the equation environment
1054 | \def\endequation{%
1055 | \ifmmode\ifinner % FLEQN hack
1056 | \iftag@
1057 | \addtocounter{equation}{-1} % undo the increment made in the begin part
1058 | $\hfil
1059 | \displaywidth\linewidth\@taggnum\egroup \endtrivlist
1060 | \global\tag@false
1061 | \global\@ignoretrue
1062 | \else
1063 | $\hfil
1064 | \displaywidth\linewidth\@eqnnum\egroup \endtrivlist
1065 | \global\tag@false
1066 | \global\@ignoretrue
1067 | \fi
1068 | \else
1069 | \iftag@
1070 | \addtocounter{equation}{-1} % undo the increment made in the begin part
1071 | \eqno \hbox{\@taggnum}
1072 | \global\tag@false%
1073 | $$\global\@ignoretrue
1074 | \else
1075 | \eqno \hbox{\@eqnnum}% $$ BRACE MATCHING HACK
1076 | $$\global\@ignoretrue
1077 | \fi
1078 | \fi\fi
1079 | }
1080 |
1081 | \newif\iftag@ \tag@false
1082 |
1083 | \def\TCItag{\@ifnextchar*{\@TCItagstar}{\@TCItag}}
1084 | \def\@TCItag#1{%
1085 | \global\tag@true
1086 | \global\def\@taggnum{(#1)}}
1087 | \def\@TCItagstar*#1{%
1088 | \global\tag@true
1089 | \global\def\@taggnum{#1}}
1090 |
1091 | \@ifundefined{tag}{
1092 | \def\tag{\@ifnextchar*{\@tagstar}{\@tag}}
1093 | \def\@tag#1{%
1094 | \global\tag@true
1095 | \global\def\@taggnum{(#1)}}
1096 | \def\@tagstar*#1{%
1097 | \global\tag@true
1098 | \global\def\@taggnum{#1}}
1099 | }{}
1100 | % Do not add anything to the end of this file.
1101 | % The last section of the file is loaded only if
1102 | % amstex has not been.
1103 |
1104 |
1105 |
1106 | \makeatother
1107 | \endinput
--------------------------------------------------------------------------------
/documentation/Report.tex:
--------------------------------------------------------------------------------
1 | % VDE Template for EUSAR Papers
2 | % Provided by Barbara Lang und Siegmar Lampe
3 | % University of Bremen, January 2002
4 | % English version by Jens Fischer
5 | % German Aerospace Center (DLR), December 2005
6 | % Additional modifications by Matthias Wei{\ss}
7 | % FGAN, January 2009
8 |
9 | %-----------------------------------------------------------------------------
10 | % Type of publication
11 | \documentclass[a4paper,10pt]{article}
12 | %-----------------------------------------------------------------------------
13 | % Other packets: Most packets may be downloaded from www.dante.de and
14 | % "tcilatex.tex" can be found at (December 2005):
15 | % http://www.mackichan.com/techtalk/v30/UsingFloat.htm
16 | % Not all packets are necessarily needed:
17 | \usepackage[T1]{fontenc}
18 | \usepackage[latin1]{inputenc}
19 | %\usepackage{ngerman} % in german language if required
20 | \usepackage[nooneline,bf]{caption} % Figure descriptions from left margin
21 | \usepackage{times}
22 | \usepackage{multicol}
23 | \usepackage{amsmath}
24 | \usepackage{amssymb}
25 | \usepackage{graphicx}
26 | \usepackage{epsfig}
27 | \usepackage{listings}
28 | \usepackage{color}
29 | \usepackage{nameref}
30 | \usepackage{url}
31 | \usepackage{inconsolata}
32 | \usepackage{dirtree}
33 | \usepackage[firstpage]{draftwatermark}
34 | %\usepackage{draftwatermark}
35 | \SetWatermarkLightness{0.84}
36 | %\usepackage{paralist}
37 |
38 | \input{tcilatex}
39 | %-------------------------------------------------------------------------------
40 | % Page Setup
41 | \textheight24cm \textwidth17cm \columnsep6mm
42 | \oddsidemargin-5mm % depending on print drivers!
43 | \evensidemargin-5mm % required margin size: 2cm
44 | \headheight0cm \headsep0cm \topmargin0cm \parindent0cm
45 | \pagestyle{empty} % delete footer and header
46 | %------------------------------------------------------------------------------
47 | % Environment definitions
48 | \newenvironment*{mytitle}{\begin{LARGE}\bf}{\end{LARGE}\\}%
49 | \newenvironment*{mysubtitle}{\bf}{\\[1.5ex]}%
50 | \newenvironment*{myabstract}{\begin{Large}\bf}{\end{Large}\\[2.5ex]}%
51 | %-------------------------------------------------------------------------------
52 | % Using Pictures and tables:
53 | % - Instead "table" write "tablehere" without parameters
54 | % - Instead "figure" write "figurehere " without parameters
55 | % - Please insert a blank line before and after \begin{figuerhere} ... \end{figurehere}
56 | %
57 | % CAUTION: The first reference to a figure/table in the text should be formatted fat.
58 | %
59 |
60 | \makeatletter
61 | \newenvironment{tablehere}{\def\@captype{table}}{}
62 | \newenvironment{figurehere}{\def\@captype{figure}\vspace{2ex}}{\vspace{2ex}}
63 | \makeatother
64 |
65 | \newenvironment{packeditems}{
66 | \begin{itemize}
67 | \setlength{\itemsep}{3pt}
68 | \setlength{\parskip}{0pt}
69 | \setlength{\parsep}{0pt}
70 | }{\end{itemize}}
71 |
72 | \newenvironment{packedenum}{
73 | \begin{enumerate}
74 | \setlength{\itemsep}{3pt}
75 | \setlength{\parskip}{0pt}
76 | \setlength{\parsep}{0pt}
77 | }{\end{enumerate}}
78 |
79 | \newenvironment{packeddesc}{
80 | \begin{description}
81 | \setlength{\itemsep}{3pt}
82 | \setlength{\parskip}{0pt}
83 | \setlength{\parsep}{0pt}
84 | }{\end{description}}
85 |
86 | \definecolor{lightblue}{rgb}{0.0,0.0,0.7}
87 | \definecolor{lightgrey}{rgb}{0.6,0.6,0.6}
88 | \definecolor{gray}{rgb}{0.4,0.4,0.4}
89 | \definecolor{darkblue}{rgb}{0.0,0.0,0.6}
90 | \definecolor{cyan}{rgb}{0.0,0.6,0.6}
91 |
92 | \newcommand{\iic}{I\textsuperscript{2}C }
93 | \newcommand{\keyword}[1]{\texttt{#1}}
94 | \newcommand{\reff}[1]{\textbf{Figure~\ref{#1}}}
95 | \newcommand{\reft}[1]{\textbf{Table~\ref{#1}}}
96 | \newcommand{\refl}[1]{\textbf{Listing~\ref{#1}}}
97 | \newcommand{\refs}[1]{\textbf{Section~\ref{#1}}}
98 |
99 | % lstlisting global parameters
100 | \lstset{
101 | language=C,
102 | basicstyle=\scriptsize\ttfamily,
103 | keywordstyle=\color{lightblue},
104 | commentstyle=\color{lightgrey},
105 | captionpos=b, % caption at the bottom of listing
106 | xleftmargin=6pt,
107 | xrightmargin=6pt,
108 | framexleftmargin=4pt,
109 | framexrightmargin=4pt,
110 | aboveskip=12pt,
111 | belowskip=12pt
112 | }
113 |
114 | \lstdefinelanguage{XML}
115 | {
116 | morestring=[b]",
117 | morestring=[s]{>}{<},
118 | morecomment=[s]{}{?>},
119 | stringstyle=\color{black},
120 | identifierstyle=\color{darkblue},
121 | keywordstyle=\color{cyan},
122 | morekeywords={xmlns,version,type,string,Button,application,activity,
123 | intent-filter,manifest}% list your attributes here
124 | }
125 |
126 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
127 | \begin{document}
128 |
129 | % Please use capital letters in the beginning of important words as for example
130 | \begin{mytitle}A safari walk-through into JNI within Android\texttrademark \ OS\end{mytitle}
131 | \begin{mysubtitle}
132 | Exploiting JNI capabilities taking advantage of Android\texttrademark \ NDK
133 | \end{mysubtitle}
134 | %
135 | % Please do not insert a line here
136 | %
137 | \\
138 | Antonio Troina\\
139 | Matr. 708267, (antonio.troina@mail.polimi.it)\\
140 | \hspace{10ex}
141 | \begin{flushright}
142 | \emph{Introductory report for the M.Sc. thesis in Computer Science Engineering}\\
143 | \emph{Reviser: PhD. Patrick Bellasi (bellasi@elet.polimi.it)}
144 | \end{flushright}
145 |
146 | Last update: \today
147 | \\
148 | \hspace{10ex}
149 |
150 | %-------------------------------------------------------------------------------
151 | \begin{myabstract} Abstract \end{myabstract}
152 | This article aims to briefly describe, in the form of some simple and annotated
153 | tutorials, how a developer can take advantage of some JNI capabilities under
154 | Android operating system to let the Java and Native environments communicate to
155 | each other. This operation has been made quite easy by the Android's native
156 | development kit (NDK). Special attention will be given to the callback mechanism,
157 | which is by far the most complex, nevertheless the most challenging, under the
158 | developer's point of view.
159 |
160 | \vspace{6ex} % Please do not remove or reduce this space here.
161 | \begin{multicols}{2}
162 |
163 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
164 | \section{Introduction}
165 | The coming of Android in the smart-phones market would suggest that Java is
166 | definitely enough to rule this galaxy. Moreover, lately, the little-green-robot's
167 | operative system has approached, silently but firmly, to the embedded world
168 | which, typically, wasn't famous for being dominated by the Java language,
169 | particularly for its performance-oriented needs. That being said, who's
170 | responsible for connecting the high-level Java application layer to the native
171 | world, and the other way around? Yes, this filling is JNI, which was initially
172 | released in early 1997. With JNI, the developer can achieve two main goals:
173 | reusing his native code within a Java environment, and optimising the execution
174 | with regard to performances, so that intensive operations can run natively,
175 | instead of being interpreted, as Java pattern requires - except for the peculiar
176 | case of the \textit{JIT-ed} code, where the bytecode is compiled \textit{Just In
177 | Time} to run natively (this operation commonly runs at launch time, but can
178 | happen at install time, or at method invoke time).\\
179 | So far, some basic examples are available (mainly on-line) which, however, are
180 | often more theoretical than practical, therefore this article is meant to be a
181 | concrete hands-on guide, to discover - some of - the secrets behind this powerful
182 | instrument which is JNI.
183 |
184 | %------------------------------------------------------------------------------
185 | \subsection{JNI, Android and NDK}
186 | \label{sec:jni-android-ndk}
187 | JNI per se basically needs two components to be used: the \textit{javah} JDK
188 | tool, which builds c-style header files from a given Java class (that will be
189 | implemented afterwards in a proper native source file, which includes the
190 | mentioned header), and the \textit{jni.h} header file, which maps the Java types
191 | to their native counterparts. The whole flow (shown in \reff{fig:jni-flow})
192 | mainly lies in four steps:
193 | \begin{itemize}
194 | \itemsep 0em
195 | \item implement a \textit{Java class}, declare the methods you want to call
196 | on the native environment as \keyword{native}, and compile it
197 | \item generate the header file through the \keyword{javah -jni} command
198 | \item implement as native C/C++ code the function whose signatures have been
199 | generated during the step above
200 | \item compile the file above as a shared library, which will be loaded by the
201 | java class
202 | \end{itemize}
203 |
204 | \begin{figurehere}
205 | \centering
206 | \includegraphics[width=8cm]{./figures/jni-flow.pdf}
207 | \caption{JNI flow}
208 | \label{fig:jni-flow}
209 | \end{figurehere}
210 |
211 | The focus of this work though points to explore JNI within the Android context,
212 | therefore our starting point will be the Android NDK, which basically consists
213 | of a ready-to-use tool-set (available on \url{http://developer.android.com/tools/sdk/ndk/index.html#Downloads}). The use
214 | of the NDK condenses the steps above in just one main step, which will do almost
215 | everything at once, through the \keyword{ndk-build} command.
216 |
217 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
218 |
219 | \section{Getting started}
220 | \label{sec:getting-started}
221 | Basically, to develop an "App" using the NDK, we need:
222 | \begin{itemize}
223 | \item Android SDK (\url{http://developer.android.com/sdk/index.html})
224 | \item Android NDK (\url{http://developer.android.com/tools/sdk/ndk/index.html})
225 | \item A source editor. Using Eclipse IDE for Java Developers automatises somehow the building process. (\url{http://www.eclipse.org/downloads/})
226 | \end{itemize}
227 | From within the \textit{"SDK/tools"} directory, you can execute the \keyword{android} command, to launch the Android SDK Manager: from here, you can download Android API and Extras.\\
228 | The Eclipse version you've downloaded will be a plain version, not yet customised to deal with specific Android needs and options: you then need to set up Android Tools for Eclipse by clicking \textit{"Help -> Install new software"} and putting the url \url{https://dl-ssl.google.com/android/eclipse/}.\\
229 | Once the environment is set up, we are ready to start developing our fist, small, application, which will interact with a native c-written library. Instead of editing the java source code, and the native code separately, and then compiling them as shown in \reff{fig:jni-flow}, Eclipse will just (automatically) build the Java part, while we'll manually generate the native shared library (we'll see how to automatise this procedure at the end of this article).\\
230 | The entirety of the files we'll work on (mainly, and at least two) is organised as shown below:
231 |
232 | \dirtree{%
233 | .1 .
234 | .1 Tutorial1/.
235 | .2 AndroidManifest.xml.
236 | .2 jni/.
237 | .3 Android.mk.
238 | .3 tutorial1.c.
239 | .2 res/.
240 | .3 layout/.
241 | .4 main.xml.
242 | .3 values/.
243 | .4 strings.xml.
244 | .2 src/.
245 | .3 com/.
246 | .4 android/.
247 | .5 tutorial1/.
248 | .6 Tutorial1Activity.java.
249 | }
250 | Let's briefly analyse this structure, taking as example the \textbf{Tutorial1} at \refs{sec:tutorial1}.
251 | \paragraph{Manifest}
252 | \keyword{AndroidManifest.xml} is the file where the applications are described: here they declare the presence of content providers, services, required permissions and other elements.\\
253 | In this simple case, it contains the basic nodes, which are:
254 | \begin{itemize}
255 | \item \keyword{manifest}: here, under the \keyword{package}, the Java package is specified. We use \keyword{com.android.tutorial1}
256 | \item \keyword{uses-sdk}: here it's specified the minimum sdk version (we use API 16, which correspond to Android Jelly Bean)
257 | \item \keyword{application}: general information about the application, a human-readable application label, icons.
258 | \item \keyword{activity}: here we have the \keyword{android:name} full name of the activity (the java file), a \keyword{android:label} which is the name that will appear at the top of our running Activity, and the \keyword{} node, which tells Android when this Activity should be run. Since our Tutorial1Activity will also be the one to be run after launch, we can declare this in the \keyword{} node. When an App is called, Android looks for an activity that declares itself ready to resolve the \keyword{MAIN} action. In the second node, under the \keyword{} node, we declare another attribute, which is \keyword{}, where we specify that the category of our activity is \keyword{LAUNCHER}: this will allow the App to be launched from the Android desktop.
259 | \end{itemize}
260 | For the sake of clarity, the whole \keyword{AndroidManifest.xml} content is presented at \refl{lst:manifest-tut1}.
261 |
262 | \begin{lstlisting}[language=XML,
263 | columns=fullflexible,
264 | showstringspaces=false,
265 | commentstyle=\color{gray}\upshape,
266 | caption=AndroidManifest.xml for Tutorial1,
267 | label=lst:manifest-tut1]
268 |
273 |
274 |
276 |
278 |
279 |
281 |
283 |
284 |
285 |
286 |
287 | \end{lstlisting}
288 | \paragraph{Resources}
289 | The \keyword{res} directory, contains, at least, the following subdirectories:
290 | \begin{itemize}
291 | \item \keyword{layout/}: This folder contains Android user interface XML files.\\
292 | Without going into detail too much, here we can find each visible element that composes what we see on the screen: strings, buttons, tables, text fields, menus. An example of a button declaration can be seen below
293 | \begin{lstlisting}[language=XML,
294 | columns=fullflexible,
295 | showstringspaces=false,
296 | commentstyle=\color{gray}\upshape]
297 |
302 | \end{lstlisting}
303 | The \keyword{@+id/button0} and the \keyword{@string/button0} are references to other resources: the former will be used by the Java code to identify this specific button element, the latter identifies the value of the variable \keyword{button0} declared into the \keyword{strings.xml} file (see below)
304 | \item \keyword{values/}: This folder contains values that the application will read during its execution, or static data an application will use for such purposes as internationalization of UI strings. In the \keyword{string.xml} file, we can declare the values corresponding to the \keyword{@string} definition, as shown below, for the \keyword{@string/button0} declared above:
305 | \begin{lstlisting}[language=XML,
306 | columns=fullflexible,
307 | showstringspaces=false,
308 | commentstyle=\color{gray}\upshape]
309 | Call to native
310 | \end{lstlisting}
311 | \end{itemize}
312 | These xml files will then be automatically built into an \keyword{R} object, visible to the activity, which will access to it and get views, and set values on its attributes.
313 |
314 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
315 |
316 | \section{Tutorial1}
317 | \label{sec:tutorial1}
318 | The complete code from this tutorial can be found at \url{https://github.com/thoeni/ndk-tutorials/tree/master/tutorial1}.\\
319 | Eventually, after this brief introduction, we can get to the most interesting part of the tutorial: the Java activity, and the native code, which are respectively placed into the \keyword{src} and the \keyword{jni} directories.\\
320 | The activity isn't any different from a regular Android activity except for two things: methods that correspond to native functions are declared as \keyword{native}, and a shared library is statically loaded by the \keyword{System.loadLibrary()} method.\\
321 | Basically, this tutorial, illustrates how to call a native function from within the Java activity, and how to call the native function which, in turn, calls back the Java activity: the methods that perform these operations are, respectively \keyword{foo1(String)} and \keyword{foo2}, declared within the \keyword{Tutorial1Activity}, as shown in \refl{lst:tut1-java1}, line 1 and line 2.
322 |
323 | \begin{lstlisting}[language=Java,
324 | columns=fullflexible,
325 | showstringspaces=false,
326 | xleftmargin=15pt,
327 | frame = l,
328 | numbers=left,
329 | commentstyle=\color{gray}\upshape,
330 | caption=Part of Tutorial1Activity.java,
331 | label=lst:tut1-java1]
332 | public native String foo1(String message);
333 | public native void foo2();
334 |
335 | public void foo3Callback() {
336 | String message = "foo3Callback called back by foo2";
337 | output.setText(message);
338 | }
339 |
340 | static {
341 | System.loadLibrary("tutorial1");
342 | }
343 | \end{lstlisting}
344 | In the same piece of code, we can see - line 4 - a regular \keyword{public void} method, named \keyword{foo3Callback()} which will be called by the native code, and - line 9 - the static declaration to load the shared library that will be generated by the \keyword{ndk-build} command.\\
345 | For this first tutorial, we analyse entirely the native code. These are the basics of JNI, and later on, we won't need to specify everything this much: the C code can be seen at \refl{lst:tut1-c1}
346 |
347 | \begin{lstlisting}[language=C,
348 | columns=fullflexible,
349 | showstringspaces=false,
350 | xleftmargin=15pt,
351 | frame = l,
352 | numbers=left,
353 | commentstyle=\color{gray}\upshape,
354 | caption=tutorial1.c,
355 | label=lst:tut1-c1]
356 | #include
357 | #include
358 |
359 | #include
360 | #include
361 | #include
362 |
363 | #define LOG_TAG "tutorial1"
364 | #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,
365 | LOG_TAG,__VA_ARGS__)
366 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,
367 | LOG_TAG,__VA_ARGS__)
368 |
369 | jstring Java_com_android_tutorial1_Tutorial1Activity_foo1(
370 | JNIEnv* env, jobject thiz, jstring message) {
371 | //To print out a char* we have to convert
372 | //the jstring to char*
373 | const char *nativeString = (*env)->GetStringUTFChars(env,
374 | message, 0);
375 | LOGI("foo1 called! Input parameter: %s", nativeString);
376 | //Then we have to release the memory allocated for
377 | //the string
378 | (*env)->ReleaseStringUTFChars(env, message, nativeString);
379 | return (*env)->NewStringUTF(env, "JNI call J2C performed!");
380 | }
381 |
382 | void Java_com_android_tutorial1_Tutorial1Activity_foo2(
383 | JNIEnv* env, jobject thiz) {
384 | LOGI("foo2 called!");
385 | //Get class from the calling object
386 | jclass clazz = (*env)->GetObjectClass(env, thiz);
387 | if (!clazz) {
388 | LOGE("callback_handler: failed to get object Class");
389 | goto failure;
390 | }
391 | //Get the methodID from the class which the calling
392 | //object belongs
393 | jmethodID method = (*env)->GetMethodID(env, clazz,
394 | "foo3Callback", "()V");
395 | if (!method) {
396 | LOGE("callback_handler: failed to get method ID");
397 | goto failure;
398 | }
399 | //Call the method on the calling object, defined by the
400 | //methodID
401 | (*env)->CallVoidMethod(env, thiz, method);
402 |
403 | failure: return;
404 | }
405 | \end{lstlisting}
406 | The first thing that we can see is the \keyword{\#include } at line 1: this is the header file - included with the JDK - that maps Java types to their native counterparts.\\
407 | There are two functions (line 14 and line 27): their names have a specific format which maps the full name of the "caller" Java class - where the \textit{underline} character replaces the typical Java \textit{dot notation} - and, at the end, there's the name of the function, which corresponds to the \keyword{native} method declared into our class.\\
408 | Let's take \keyword{foo1} as example: the method declaration in \refl{lst:tut1-java1}\textbf{:1} is natively implemented in \refl{lst:tut1-c1}\textbf{:14}. As it's done for the name, the input parameters and the return type have to match as well, therefore we have that the java \keyword{String} type is mapped to a native \keyword{jstring} type (thanks to the jni.h library that we included some lines above); the same goes for the input (\keyword{String/jstring} again), with a peculiarity: native functions mapped to Java methods through JNI paradigm always have two more parameters, a \keyword{JNIEnv*} which is a pointer to the current Java environment, and a \keyword{jobject} which is a reference to the caller object. Given this, depending on the variety of input(s) and of the output type, we're able to properly create the correct JNI function declaration: from now on, with some attentions, native code can freely run.\\
409 | In this tutorial I decided to pass a \keyword{String} as input to have the opportunity to show how the developer should proceed when she needs to handle variable types that are not primary ones. In this case, we have to explicitly convert the string from \keyword{jstring} to a \textit{"native-friendly"} \keyword{char*}: if you don't, the error is sometimes not as verbose as you would expect it to be, and it's quite hard to debug this situation, therefore pay attention to the Java/native types mismatch. As the reader can easily understand, we declare a native string, which will save the result of the right-hand side function (\refl{lst:tut1-c1}\textbf{:18}) \keyword{GetStringUTFChars} which obtains string characters represented in the Unicode format. The third parameter indicates whether we want a copy, or the pointer to the actual java string: in the latter case, the developer must pay attention not to modify the contents of the returned string. This parameter is typically set to NULL, and the JVM will autonomously determine the choice to pick.\\
410 | We can finally log our parameter as \textit{information}. When the native code finishes using the UTF-8 string obtained through GetStringUTFChars, it calls ReleaseStringUTFChars, thus the memory taken by the UTF-8 string can be freed.\\
411 | To satisfy the return type declared for this \keyword{foo1}, we return a new string. The procedure shown at \refl{lst:tut1-c1}\textbf{:24} is specific for generating a jstring object: we'll see further in this article that from the native code we are able to find java classes, instantiate them as jobjects, and call methods on them.\\
412 | \keyword{foo2} function represents a very simple example of a JNI callback: typically, whenever we need to callback a Java method implemented into the class that made the call, we go through three main steps:
413 | \begin{itemize}
414 | \item get the class (\keyword{jclass}), starting from the object (\keyword{jobject}) which made the call, through the \keyword{GetObjectClass} \refl{lst:tut1-c1}\textbf{:31}
415 | \item get the method identifier, through the \keyword{GetMethodID}, which performs a lookup for the method in the given class. The lookup is based on
416 | the name and type descriptor of the method. If the method does not exist, \keyword{GetMethodID} returns \keyword{NULL} \refl{lst:tut1-c1}\textbf{:38}
417 | \item call the method, on the caller object, passing the \keyword{methodID} \refl{lst:tut1-c1}\textbf{:46}
418 | \end{itemize}
419 | The code in \refl{lst:tut1-c1}\textbf{:27-49} is easy to read, despite for a detail that we are going to analyse: at line 38, the \keyword{GetMethodID} function, takes as input 4 parameters:
420 | \begin{itemize}
421 | \item \keyword{JNIEnv*}, the pointer to the Java environment
422 | \item \keyword{jobject}, the caller object, that we passed to the native function as input parameter
423 | \item \keyword{const char*}, the string which identifies the name of the method to call back
424 | \item \keyword{const char*}, the "signature" of the method, called the method descriptor: despite it could seem bizarre, it's very easy to understand. The first part, between the round brackets, represents the input parameters, and their types; the last identifier, after the closed round bracket, represents the return type. In our case, \keyword{()V} means \keyword{void foo3Callback()}. If our function was, let's say, \keyword{float foo3Callback(int i)} we would write, as its descriptor: \keyword{(I)F}. And, again, with \keyword{float foo3Callback(int i, float f, int j)} we would write \keyword{(IFI)F}. We will see how to declare complex descriptors, with strings, objects and arrays further
425 | \end{itemize}
426 | We still miss the last step, which allows the Java class to load the shared native library: the native code needs to be compiled by the \keyword{ndk-build} command. Before doing this, we have to create the \keyword{Android.mk} into the \keyword{jni} directory. The content of this file, for this tutorial, is shown at \refl{lst:tut1-c2}: after defining the name of the module that will be compiled, its source file, and local libs that we want to use, through the \keyword{include \$(BUILD\_SHARED\_LIBRARY)} instruction, we tell the compiler to create the shared object. Doing so, this library will be available to be loaded by Java classes. The use of \keyword{ndk-build} command is highly suggested, since it will generate all the files and folders that our environment needs.
427 |
428 | \begin{lstlisting}[language=make,
429 | columns=fullflexible,
430 | showstringspaces=false,
431 | xleftmargin=15pt,
432 | frame = l,
433 | numbers=left,
434 | commentstyle=\color{gray}\upshape,
435 | caption=Android.mk for tutorial1.c,
436 | label=lst:tut1-c2]
437 | LOCAL_PATH:= $(call my-dir)
438 |
439 | include $(CLEAR_VARS)
440 |
441 | LOCAL_MODULE := tutorial1
442 | LOCAL_CFLAGS := -Werror
443 | LOCAL_SRC_FILES := tutorial1.c
444 | LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog
445 |
446 | include $(BUILD_SHARED_LIBRARY)
447 | \end{lstlisting}
448 |
449 | An example of the activity performing a callback can be found at \reff{fig:tut1-scr1}: the output visible at the top of the screen comes from the Java method at \refl{lst:tut1-java1}\textbf{:5}\\
450 |
451 | \begin{figurehere}
452 | \centering
453 | \includegraphics[width=6cm]{./figures/tut1-scr1.png}
454 | \caption{Tutorial1 performing a callback}
455 | \label{fig:tut1-scr1}
456 | \end{figurehere}
457 |
458 | So far we introduced the main components needed to develop within the Android NDK, and we saw a simple example where an activity calls - and is called back by - a native function.\\
459 | In the next section, we'll add some features to this first example.
460 |
461 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
462 |
463 | \section{Tutorial2}
464 | \label{sec:tutorial2}
465 | The complete code from this tutorial can be found at \url{https://github.com/thoeni/ndk-tutorials/tree/master/tutorial2}.\\
466 | Often we deal with threads, and we want to implement asynchronous calls from native to Java environment. Asynchronous calls are easy to do when the direction is Java to native, while the other way around - implemented through the callback mechanism - isn't that easy to figure out.\\
467 | This example will consist of basic activity (almost identical to the one we used for \textit{Tutorial1}), that will be able to "run" and "stop" a routine. This routine will consist of a loop of four different callbacks, that will run into a thread: the loop exit condition is based on a flag that will be set and unset by the activity.\\
468 | In addition to the basic blocks we saw for \textit{Tutorial1} at \refl{lst:tut1-java1}, we can find at \refl{lst:tut2-java1} the lines relevant to understand how \textit{Tutorial2} performs.
469 | \begin{lstlisting}[language=Java,
470 | columns=fullflexible,
471 | showstringspaces=false,
472 | xleftmargin=15pt,
473 | frame = l,
474 | numbers=left,
475 | commentstyle=\color{gray}\upshape,
476 | caption=Part of Tutorial2Activity.java source code,
477 | label=lst:tut2-java1]
478 | int int0;
479 | float float0;
480 | String string0;
481 |
482 | public void onCreate(Bundle savedInstanceState) {
483 | // [...]
484 | init();
485 | handler = new Handler();
486 | }
487 |
488 | // [...]
489 |
490 | public void callback1() {
491 | System.out.println("callback1 called");
492 | handler.post(callback1Thread);
493 | }
494 |
495 | Runnable callback1Thread = new Runnable() {
496 | @Override
497 | public void run() {
498 | output.setText("callback 1, no params");
499 | }
500 | };
501 |
502 | public int callback2(int param0, float param1,
503 | String param2) {
504 | System.out.println("callback2 called, params are: "
505 | + param0 + " " + param1 + " " + param2);
506 | int0 = param0;
507 | float0 = param1;
508 | string0 = param2;
509 | handler.post(callback2Thread);
510 | return 0;
511 | }
512 |
513 | Runnable callback2Thread = new Runnable() {
514 | @Override
515 | public void run() {
516 | output.setText("callback 2, params are: "
517 | + int0 + ", " + float0 + ", " + string0);
518 | }
519 | };
520 |
521 | public void callback3(String param0) {
522 | System.out.println("callback 3, param is: "
523 | + param0);
524 | string0 = param0;
525 | handler.post(callback3Thread);
526 | }
527 |
528 | Runnable callback3Thread = new Runnable() {
529 | @Override
530 | public void run() {
531 | output.setText("callback 3, param is: " + string0);
532 | }
533 | };
534 |
535 | public float callback4(float param0) {
536 | System.out.println("callback 4, param is: " + param0);
537 | float0 = param0;
538 | handler.post(callback4Thread);
539 | return param0;
540 | }
541 |
542 | Runnable callback4Thread = new Runnable() {
543 | @Override
544 | public void run() {
545 | output.setText("callback 4, param is: " + float0);
546 | }
547 | };
548 |
549 | // [...]
550 |
551 | public native void init();
552 | public native void foo1();
553 | public native void foo2();
554 |
555 | static {
556 | System.loadLibrary("tutorial2");
557 | }
558 | \end{lstlisting}
559 | At \refl{lst:tut2-java1}\textbf{:1-3} we declare three global variables where some callback values will be stored, and that will be accessed during some of the callbacks methods execution.\\
560 | Within the \keyword{onCreate} method we call the first out of three native methods, named \keyword{init()}: the corresponding native function initialises some parameters and retrieves the various \keyword{methodIDs}.\\
561 | Then callback methods declarations follow, at \refl{lst:tut2-java1}\textbf{:13-70}: for each callback method, there's a corresponding \keyword{Runnable} object which represents a command that can be executed, and is often used to run code in a different thread. This class declares an \keyword{abstract void} method, which therefore is mandatory to implement, and is the \keyword{run()} method: within this method we can put the active part of the code that must be executed and, typically, we use this to change the output view and display some values on the screen.\\
562 | Below (\refl{lst:tut2-java1}\textbf{:74-76}) there are the declarations of three \keyword{native} functions.\\
563 | Compared to the example we considered for the \textit{Tutorial1}, this native code is slightly more complex, and uses a thread and some JNI specific types we haven't had the chance to introduce before. To start, here we use the \keyword{JNI\_OnLoad} function (\refl{lst:tut2-c1}), which performs initialization operations for a given native library and returns the JNI version required by the native library. The virtual machine implementation calls \keyword{JNI\_OnLoad} when the native library is loaded, therefore we can use it to save a reference to the current Virtual Machine which - unlike the case of the \keyword{JNIEnv*} that is local to each call - lives along the whole life of the application.
564 | \begin{lstlisting}[language=C,
565 | columns=fullflexible,
566 | showstringspaces=false,
567 | xleftmargin=15pt,
568 | frame = l,
569 | numbers=left,
570 | commentstyle=\color{gray}\upshape,
571 | caption=Part of tutorial2.c - JNI\_OnLoad,
572 | label=lst:tut2-c1]
573 | static JavaVM *gJavaVM;
574 |
575 | jint JNI_OnLoad(JavaVM* vm, void* reserved)
576 | {
577 | JNIEnv *env;
578 | gJavaVM = vm;
579 | LOGI("JNI_OnLoad called");
580 | if ( (*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4)
581 | != JNI_OK) {
582 | LOGE("Failed to get the environment using GetEnv()");
583 | return -1;
584 | }
585 | return JNI_VERSION_1_4;
586 | }
587 | \end{lstlisting}
588 | The \keyword{init()} function saves global references to the caller object and, hence, to the caller class the objects belongs to. Besides it saves the references to the \keyword{methodIDs} statically declared into the \keyword{callback\_t} structure (specifically defined for this example).\\
589 | In \refl{lst:tut2-c2} an extract of the structure declaration (\textbf{lines:1-15}), the global variables to save the global references to (\textbf{lines:17-18}), the same \keyword{GetMethodID} implementation we already saw (\textbf{line:35}) and the \keyword{NewGlobalRef()} function (\textbf{lines:26-28}), which creates a new global reference to the object referred to by the second argument. Global references must be explicitly disposed of by calling \keyword{DeleteGlobalRef}.\\
590 | Since \keyword{init()} native method is called within the \keyword{onCreate}, this whole procedure will be executed the first time we run the activity, and when we launch it again after having destroyed it.\\
591 | Now we can see what happens when the user calls \keyword{foo1}, and starts the testing routine.
592 | \begin{lstlisting}[language=C,
593 | columns=fullflexible,
594 | showstringspaces=false,
595 | xleftmargin=15pt,
596 | frame = l,
597 | numbers=left,
598 | commentstyle=\color{gray}\upshape,
599 | caption=Part of tutorial2.c - init(),
600 | label=lst:tut2-c2]
601 | callback_t cb[] = {
602 | // cb[0]
603 | {
604 | "callback1",
605 | "()V",
606 | JNI_WRAPPER_rVOID,
607 | },
608 | // cb[1]
609 | {
610 | "callback2",
611 | "(IFLjava/lang/String;)I",
612 | JNI_WRAPPER_rINT_p,
613 | },
614 | //[...]
615 | };
616 |
617 | static jobject gObject;
618 | static jclass gClass;
619 |
620 | void
621 | Java_com_android_tutorial2_Tutorial2Activity_init(
622 | JNIEnv* env, jobject thiz)
623 | {
624 | LOGI("init native function called");
625 | //[...]
626 | gObject = (jobject)(*env)->NewGlobalRef(env, thiz);
627 | jclass clazz = (*env)->GetObjectClass(env, thiz);
628 | gClass = (jclass)(*env)->NewGlobalRef(env, clazz);
629 | //[...]
630 | int i = sizeof cb / sizeof cb[0];
631 | //[...]
632 | while(i--) {
633 | LOGI("Method %d is %s with signature %s", i,
634 | cb[i].cbName, cb[i].cbSignature);
635 | cb[i].cbMethod = (*env)->GetMethodID(env, clazz,
636 | cb[i].cbName, cb[i].cbSignature);
637 | }
638 | }
639 | \end{lstlisting}
640 | \keyword{foo1} has no parameters, and its return value is void: its main code consists of a call to the function \keyword{daemonStart()}, therefore it's useless to show its code, though can be easily found on-line at the repository address. \keyword{daemonStart()}, in turn, creates a pthread and exits, and this is traditional C code, so far.\\
641 | The function that is launched as thread is called \keyword{randomCaller()}, and uses the \keyword{gJavaVM} variable to retrieve the current \keyword{JNIEnv} and send it as input parameter to another function, which is a wrapper that, depending on the input parameters, chooses which method has to be called. A sequence diagram to clarify its working is shown in \reff{fig:tut12-seq}.
642 | \begin{figure*}[t]
643 | \includegraphics[width=17cm]{./figures/sequence.pdf}
644 | \caption{Tutorial2 sequence diagram}
645 | \label{fig:tut12-seq}
646 | \end{figure*}
647 | Unlike \textit{Tutorial1}, this example uses a thread, and there's a proper procedure to \textit{attach} the current thread to the JVM, as shown in \refl{lst:tut2-c3}.
648 | \begin{lstlisting}[language=C,
649 | columns=fullflexible,
650 | showstringspaces=false,
651 | xleftmargin=15pt,
652 | frame = l,
653 | numbers=left,
654 | commentstyle=\color{gray}\upshape,
655 | caption=Part of tutorial2.c - thread attachment in randomCaller(),
656 | label=lst:tut2-c3]
657 | void *randomCaller() {
658 | flag = 1;
659 | JNIEnv *env;
660 | int isAttached = 0;
661 | int status = (*gJavaVM)->GetEnv(gJavaVM, (void **) &env,
662 | JNI_VERSION_1_4);
663 | if(status < 0) {
664 | LOGE("callback_handler: failed to get JNI environment,
665 | assuming native thread");
666 | status = (*gJavaVM)->AttachCurrentThread(gJavaVM, &env,
667 | NULL);
668 | if(status < 0) {
669 | LOGE("callback_handler: failed to attach current
670 | thread");
671 | }
672 | isAttached = 1;
673 |
674 | /*
675 | * callMethodWrapper(i++)
676 | * sleep(2);
677 | */
678 |
679 | if(isAttached)
680 | (*gJavaVM)->DetachCurrentThread(gJavaVM);
681 | }
682 | \end{lstlisting}
683 | At \refl{lst:tut2-c3}\textbf{:5} is called the \keyword{GetEnv} function on the global reference of the JVM: this function sets \keyword{*env} to \keyword{NULL} if the current thread is not attached to the given virtual machine instance, and returns \keyword{JNI\_EDETACHED} which corresponds to \keyword{-2}; if the specified interface is not supported, it sets \keyword{*env} to \keyword{NULL}, and returns \keyword{JNI\_EVERSION} which corresponds to \keyword{-3}. Otherwise, sets \keyword{*env} to the appropriate interface, and returns \keyword{JNI\_OK}, which corresponds to \keyword{0}. Since we know we are running this code within a thread, the status value will be \keyword{-2}, and the thread attachment will be attempted (\refl{lst:tut2-c3}\textbf{:10}): the \keyword{AttachCurrentThread} function sets up the current native thread to run as part of a virtual machine instance. Once a thread is attached to the virtual machine instance, it can then make JNI function calls to perform such tasks as accessing objects and invoking methods. The \keyword{DetachCurrentThread} function (\refl{lst:tut2-c3}\textbf{:24}) informs a virtual machine instance that the current thread no longer needs to issue JNI function calls, allowing the virtual machine implementation to perform clean-ups and free resources.\\
684 | How the \keyword{switch} condition works inside the \keyword{randomCaller} is easy to understand (\refl{lst:tut2-c3}\textbf{:18-21}), hence the full code isn't presented in this paper, nonetheless it's important to stress the peculiarity of a calling method, which is the \keyword{callMethodA()} \refl{lst:tut2-c5}\textbf{:24}: to test this cycle, the \keyword{randomCaller} defines some variables, and calls the wrapper passing four arguments to it. An example about this can be seen in \refl{lst:tut2-c4}: at \textbf{line:11} the developer sets as input parameters the env variable, the ordinal number of the chosen callback method (\refl{lst:tut2-c2}\textbf{:9-13}), the array of native params (which is a \keyword{struct} we defined) and the size of this array.
685 | \begin{lstlisting}[language=C,
686 | columns=fullflexible,
687 | showstringspaces=false,
688 | xleftmargin=15pt,
689 | frame = l,
690 | numbers=left,
691 | commentstyle=\color{gray}\upshape,
692 | caption=Part of tutorial2.c - method calls in randomCaller(),
693 | label=lst:tut2-c4]
694 | nvalue v1, v2, v3, npar[3];
695 | v1.type = INT;
696 | v1.i = 12;
697 | v2.type = FLOAT;
698 | v2.f = 2.3;
699 | v3.type = STRING;
700 | v3.s = "string";
701 | npar[0] = v1;
702 | npar[1] = v2;
703 | npar[2] = v3;
704 | callMethodWrapper(env, 1, npar, 3);
705 | \end{lstlisting}
706 | The \keyword{callMethodWrapper} function is partially shown in \refl{lst:tut2-c5}: the \keyword{for} at \textbf{line:7} maps all the native values to \keyword{jvalue[]}, which is a \keyword{struct} already defined for the JNI environment. It comes quite useful in this case because we can take advantage of the \keyword{callMethodA} function, where the \keyword{A} at the end of its name means that it takes as fourth parameter an \keyword{jvalue} array.
707 |
708 | \begin{figure*}[b]
709 | \includegraphics[width=17cm]{./figures/tut2-scr1.png}
710 | \caption{Tutorial2 running example}
711 | \label{fig:tut2-scr1}
712 | \end{figure*}
713 | \begin{lstlisting}[language=C,
714 | columns=fullflexible,
715 | showstringspaces=false,
716 | xleftmargin=15pt,
717 | frame = l,
718 | numbers=left,
719 | commentstyle=\color{gray}\upshape,
720 | caption=Part of tutorial2.c - callingMethodWrapper,
721 | label=lst:tut2-c5]
722 | int callMethodWrapper(JNIEnv* env, int mid, nvalue npar[],
723 | int parSize) {
724 | jvalue jpar[parSize];
725 | //[ ... ]
726 | if (parSize > 0) {
727 | int i;
728 | for (i=0; iNewStringUTF(env, npar[i].s);
738 | break;
739 | }
740 | }
741 | }
742 | switch (cb[mid].jniWrapper) {
743 | //[ ... ]
744 | case JNI_WRAPPER_rINT_p:
745 | (*env)->CallIntMethodA(env, gObject, cb[mid].cbMethod,
746 | jpar);
747 | break;
748 | //[ ... ]
749 | }
750 | \end{lstlisting}
751 | A screenshot of \textit{Tutorial2} activity and logcat during the execution can be found at \reff{fig:tut2-scr1}
752 |
753 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
754 |
755 | \section{Java object handling within native code}
756 | It's possible that you would need to pass to the Java world a reference to an object that doesn't exist yet.\\
757 | We'll analyse how it's possible to find a class, create an instance of this class, and call some methods on it.\\
758 | Let's suppose we created a class, called Param, within the \keyword{tutorial2} package, which looks like the one in \refl{lst:tut2b-java1}
759 | \begin{lstlisting}[language=Java,
760 | columns=fullflexible,
761 | showstringspaces=false,
762 | xleftmargin=15pt,
763 | frame = l,
764 | numbers=left,
765 | commentstyle=\color{gray}\upshape,
766 | caption=Java class Param,
767 | label=lst:tut2b-java1]
768 | package com.android.tutorial2;
769 |
770 | public class Param {
771 | private int[] iParams;
772 | private float[] fParams;
773 | private String[] sParams;
774 |
775 | public Param(int[] iP, float[] fP, String[] sP) {
776 | setiParams(iP);
777 | setfParams(fP);
778 | setsParams(sP);
779 | }
780 |
781 | public int[] getiParams() {
782 | return iParams;
783 | }
784 | public void setiParams(int[] iParams) {
785 | this.iParams = iParams;
786 | }
787 | public String[] getsParams() {
788 | return sParams;
789 | }
790 | public void setsParams(String[] sParams) {
791 | this.sParams = sParams;
792 | }
793 |
794 | public float[] getfParams() {
795 | return fParams;
796 | }
797 | public void setfParams(float[] fParams) {
798 | this.fParams = fParams;
799 | }
800 | }
801 | \end{lstlisting}
802 | Suppose that we need to create a Param object, assign some values to its fields, and pass its reference to a Java method through the callback mechanism. Let's see the main steps to achieve this aim.\\
803 | To begin, we need to get a reference to the \keyword{Param} class, and we do this as follow:
804 | \begin{lstlisting}[language=C,
805 | columns=fullflexible,
806 | showstringspaces=false,
807 | xleftmargin=15pt,
808 | frame = l,
809 | numbers=left,
810 | commentstyle=\color{gray}\upshape]
811 | //Find the "Param" Class
812 | cls = (*env)->FindClass(env, "com/android/tutorial2/Param");
813 | \end{lstlisting}
814 | We can then create java arrays and, depending on the type of array we are going to create, we have to use a different constructor function, for instance, to create a \keyword{jint} array:
815 | \begin{lstlisting}[language=C,
816 | columns=fullflexible,
817 | showstringspaces=false,
818 | xleftmargin=15pt,
819 | frame = l,
820 | numbers=left,
821 | commentstyle=\color{gray}\upshape]
822 | int isize = 3;
823 | jint iparams[isize] = {0, 1, 2};
824 | //###Create a new Array of integers###
825 | iarr = (*env)->NewIntArray(env, isize);
826 | //Fill the array with the integer input parameter
827 | (*env)->SetIntArrayRegion(env, iarr, 0, isize, iparams);
828 | \end{lstlisting}
829 | Now the object \keyword{iarr} is a Java array of integers.\\
830 | The same thing can be done for floats, as follows:
831 | \begin{lstlisting}[language=C,
832 | columns=fullflexible,
833 | showstringspaces=false,
834 | xleftmargin=15pt,
835 | frame = l,
836 | numbers=left,
837 | commentstyle=\color{gray}\upshape]
838 | int fsize = 2;
839 | jfloat fparams[fsize] = {1.2, 3.2};
840 | //###Create a new Array of floats###
841 | farr = (*env)->NewIntArray(env, fsize);
842 | //Fill the array with the float input parameter
843 | (*env)->SetFloatArrayRegion(env, farr, 0, fsize, fparams);
844 | \end{lstlisting}
845 | Now, for the \keyword{String} we don't have any ready-to-use function to create an array of \keyword{String} objects, therefore we can use the more general \keyword{NewObjectArray} function, as follows:
846 | \begin{lstlisting}[language=C,
847 | columns=fullflexible,
848 | showstringspaces=false,
849 | xleftmargin=15pt,
850 | frame = l,
851 | numbers=left,
852 | commentstyle=\color{gray}\upshape]
853 | int ssize = 2;
854 | char* sparams[ssize] = {"ab","cd"};
855 | sarr = (*env)->NewObjectArray(
856 | env, ssize, (*env)->FindClass(
857 | env, "java/lang/String"), NULL);
858 | for (i=0; iSetObjectArrayElement(
860 | env, sarr, i, (*env)->NewStringUTF(
861 | env, sparams[i]));
862 | \end{lstlisting}
863 | Now, we have three Java arrays correctly initialised: we can create an object of the \keyword{Param} class, and use its constructor (\refl{lst:tut2b-java1}\textbf{:8}) to initialise it with these newly generated arrays:
864 | \begin{lstlisting}[language=C,
865 | columns=fullflexible,
866 | showstringspaces=false,
867 | xleftmargin=15pt,
868 | frame = l,
869 | numbers=left,
870 | commentstyle=\color{gray}\upshape]
871 | jmethodID constructor;
872 | //Find the constructor of the Param object, which takes as
873 | //parameter an int array and a float array
874 | constructor = (*env)->GetMethodID(env, cls, "",
875 | "([I[F[Ljava/lang/String;)V");
876 | //Create the Object with its constructor, and the arrays as
877 | //parameters
878 | obj = (*env)->NewObject(
879 | env, cls, constructor, iarr, farr, sarr);
880 | //Call the callback method passing the object as input
881 | //parameter
882 | (*env)->CallStaticVoidMethod(
883 | env, gClass, cb[id].cbMethod, obj);
884 | \end{lstlisting}
885 | As we saw in \refs{sec:tutorial1}, the following signature \keyword{"([I[F[Ljava/lang/String;)V"} indicates a method - in this case \keyword{} identifies the constructor method - which has a \keyword{void} return, and has input structured like:
886 | \begin{itemize}
887 | \item \keyword{[I} -> array of integers: int[]
888 | \item \keyword{[F} -> array of floats: float[]
889 | \item \keyword{[Ljava/lang/String;} -> array of objects \keyword{L} indicates object, of type \keyword{java/lang/String}: String[]
890 | \end{itemize}
891 | Therefore this signature means \keyword{void (int[], float[], String[])}, which is exactly how the \keyword{Param} constructor is defined at \refl{lst:tut2b-java1}\textbf{:8}.
892 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
893 |
894 | \section{Conclusions}
895 |
896 | This report and all the source code are publicly available through the git
897 | repository at \url{https://github.com/thoeni/ndk-tutorials} or at \url{https://bitbucket.org/atroina/ndk-tutorials}.
898 |
899 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
900 | % No cited references
901 | \nocite{liang1999jni}
902 | \nocite{marakanajni}
903 | \nocite{learningandroid}
904 | \nocite{programmingandroid}
905 |
906 | % We suggest the use of JabRef for editing your bibliography file (Report.bib)
907 | \bibliographystyle{splncs}
908 | \bibliography{Report}
909 |
910 | \end{multicols}
911 | \end{document}
912 |
--------------------------------------------------------------------------------