A Java Windowing Toolkit for Text Terminals

Menu
Quick Info
Operating System: Linux
Language: Java, C
Licence: GNU
Author: Rob Pitman
Frequently Asked Questions
Please mail me your questions to be added to the FAQ.
General
Why is the library called "Charva"?
It's a contraction of CHARacter-mode jaVA.
Why not name the "Charva Swing" package javax.swing instead of charvax.swing? That way, you could run an existing Swing application as a Charva application just by changing the classpath.
According to the Sun license:

You may not create, or authorize your licensees to create, additional classes, interfaces, or subpackages that are in any way identified as "java", "javax" or "sun".

In any case, it is not practical to run Swing applications as Charva applications without modifying some lines of source code. In Swing, for example, dimensions are measured in pixels, whereas in Charva they are in rows and columns.

How scalable is Charva? Can Charva handle multiple users in one JVM?
Because Charva uses ncurses, each user requires his/her own instance of Charva, in its own JVM.

Having said that, I've found that I can easily run 40 instances of the Charva "Tutorial" program (included with the download zipfile), each simulating a busy user, on a single-CPU Pentium with a 1.5GHz CPU and 768 MByte of memory. With this number of simultaneous instances there is no swapping of memory to disk.

Bearing in mind that (in 2006) RAM costs have dropped to, say, 25 US cents per megabyte, Charva is well suited for "intranet"-type data-capture applications with up to several thousand simultaneous users, provided you scale horizontally across multiple servers, with several hundred users on each server.

Getting CHARVA to run
When I run my CHARVA program, it just displays the message "Exception in main", and returns to the shell command prompt. How do I find out the cause?
Any time an uncaught exception occurs in CHARVA, a stack-trace is produced in the file $HOME/charva.log. This gives detailed information about the cause of the error.
When I run the example programs, I get the error message "java.lang.NoClassDefFoundError java/lang/Object". Why?
In versions of the Charva package before 0.8.5, the example script executed the java interpreter by just calling an executable called "java". There may be another executable called "java" in your PATH, occurring before the JDK1.3/JDK1.4 version of "java". Check which executable is being executed by using the command "which -a java". (In Charva version 0.8.5 the example scripts were changed to execute $JAVA_HOME/bin/java).
When I run a Charva program, I get the error message "Exception in thread main", and the $HOME/charva.log file reports Java.lang.UnsatisfiedLinkError: no Terminal in java.library.path. What is wrong?
Java cannot find the shared library file libTerminal.so in its library search path. Different flavors of Unix have different methods of specifying the library search path. On Linux, use the command:

            export LD_LIBRARY_PATH=directory_containing_libTerminal.so:$LD_LIBRARY_PATH
        
AIX uses LIBPATH and HP-UX uses SHLIB_PATH instead of LD_LIBRARY_PATH. Note that on HP-UX, the library file name must be libTerminal.sl, not libTerminal.so.
My CHARVA program throws the following exception: "charva.awt.IllegalComponentStateException: no focus-traversable components inside this Container". What is wrong?
When displaying a Window (i.e. a JFrame or a JDialog), CHARVA needs to move the keyboard input focus to a component (such as a JButton or JTextField) inside that Window. If there are no focus-traversable components in the window, CHARVA will throw the exception.

A focus-traversable component is one which is capable of accepting the keyboard input focus, and of passing it on to the next component, when the user presses TAB or BACK-TAB. Note that JLabel is not focus-traversable. Also, components that are normally focus-traversable become non-focus-traversable when their setEnabled(false) method is called.

To my knowledge, there is never any need in a real-world application to display a Window that contains only non-focus-traversable components such as labels.

When I try to debug a Charva program inside my IDE (Eclipse, IDEA or other), it throws the following exception: "LINES value must be >= 2 and <=8021: got 1; initscr(): LINES=1 COLS=1: too small". What is wrong?
You can't run ncurses programs inside a graphical IDE. You have to run them in a "terminal session" (i.e. in an "xterm" session, or an "rlogin" or "ssh" session, or on a real physical terminal, or in a DOS shell if you're running Windows). Having said that, you can use the IDE's debugger to debug Charva programs (see the question "How can I debug Charva applications?" below).
Why does CHARVA do this, that or the other?
When I run a Charva program, garbage is displayed on my terminal. Why?
It is essential that the $TERM environment variable is correctly set to match the type of terminal you are using, and that the terminfo description file correctly describes the capabilities of your terminal. For more information on ncurses and terminfo, look at http://en.tldp.org/HOWTO/Text-Terminal-HOWTO.html and http://www.gnu.org/software/ncurses/ncurses.html. There is also an O'Reilly book on terminfo.

Incidentally, don't use the "gnome-terminal" application, which is the standard xterm emulator in the GNOME desktop environment; it is buggy and won't work properly with Charva. Rather use the "konsole" emulator which is the standard emulator in the KDE environment (see next question).

In running the tutorial program, instead of having the frame border, I got some fuzzy characters like this:

─────────────

The problem is in your terminfo setting. Run "infocmp" and look at the setting of "acsc". On my PuTTY screen, for example, the setting of "acsc" looks like this:
            acsc=``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~
        
The "acsc" setting defines an array of ASCII characters that map to the line-drawing characters of your terminal. If these are set incorrectly, you will get weird characters instead of the line drawing characters. I suggest you try several other settings of your $TERM variable and see if one of them causes the correct characters to be displayed. Then edit your "terminfo" file appropriately and run "tic" as explained elsewhere in this FAQ.

On Red Hat Linux, using the KDE "konsole" terminal emulator (which sets the $TERM environment variable to "xterm"), the cursor behaves erratically. Why?
I have found that the standard "xterm" terminfo description file (distributed with Red Hat Linux) is not totally compatible with the Konsole terminal emulator. In the root directory of the Charva download zipfile you will find a file named "xterm.ti", which is a terminfo description in source form; it works fine with Charva and the Konsole emulator. You can compile it using the command "tic xterm.ti" (you have to be root to do this). You may want to save the original xterm description file (/usr/share/terminfo/x/xterm) before doing this.

Note that this terminfo description defines CTRL-B as the back-tab key.

The "gnome-terminal" emulator, on the other hand, doesn't seem to work properly with any terminfo file.

If I run "ps aux" while a Charva program is running, I see about a dozen instances of the same java process running. Why?
In Linux kernels before version 2.6, native threads are implemented as separate kernel processes, so that each thread shows up separately in the output of "ps". To avoid this you can use "green threads" instead of "native threads"; just use the "-classic" command-line switch with the java interpreter (this option works with Sun's JDK1.3, but is no longer supported in JDK1.4). In Linux kernel 2.6, and in Red Hat Enterprise Linux, threads are implemented within a single process.
The JDialog component in Charva is always modal, in other words its setVisible(true) method (and the equivalent show() method) always blocks until the dialog is hidden again. Why?
I felt it didn't make sense to have non-modal dialogs on a text terminal.

Note that the JFrame.show() method also blocks, except for the first time that the application program calls it.

When I press TAB the cursor moves to the next enabled component, but I can't get the cursor to move back to the previous component. Why?
The back-tab key must be defined in the terminfo file, and must be mapped to the correct key (usually SHIFT-TAB) so that you can back-tab to the previous field or component. Enter the infocmp command to check whether the kcbt key is defined (use the man terminfo command and search for kcbt to get more info on this). By default, the kcbt capability is not defined for an xterm terminal on Red Hat Linux. If the back-tab is not defined, edit the terminfo description for your terminal, and add in a suitable key-code for the kcbt capability (for example, kcbt=^B will set it to CTRL-B); then use the tic command to compile the terminfo description. To find out the suitable key-code, see the next item in this FAQ.

To get more information about the infocmp and tic commands, use man infocmp and man tic

How do I .....?
How can I debug Charva applications?

Since version 1.1.3, Charva uses Jakarta commons-logging. You should use the same mechanism for adding debug statements to your code. See the commons-logging website for details.

Another way is to use a commercial IDE such as IntelliJ IDEA which has a good debugger built into it. You have to start the debuggee application with certain command-line options which cause it to listen on a specified TCP port; the debugger then opens a connection to this port. The test scripts (test.sh and test.bat) in the distribution tarball show examples of the required command-line options.

I am told that other IDEs such as NetBeans, Eclipse and JBuilder have the same capabilities.

How can I find out the key-code seen by curses when I press key x?
To find out what key-code is produced by any arbitrary key, run your CHARVA program with the "charva.script.record" system property set to a filename, as in the following example:
 java -Dcharva.script.record=scriptfile \
            -classpath ../classes:../lib/charva.jar classname

This will cause CHARVA to log the hexadecimal key-code of each key (and its equivalent symbolic name, if it is a control character or function-key) in the file "scriptfile".

I'm having trouble capturing function-keys in CHARVA; when I define the charva.script.record=scriptfile property as described above, the output in the scriptfile indicates that a sequence of bytes such as "ESC [ [ A" is produced when I press the F1 key, instead of the KeyEvent.VK_F1 code.
Check that the $TERM environment variable is set correctly for your terminal type. Then run the Linux/Unix command "infocmp" to display what the terminfo file for your terminal-type thinks the byte-sequence for the F1 key should be. The output of the infocmp command will contain a string such as "kf1=\EOP", for example; this indicates that terminfo expects the F1 key to produce the byte-sequence "ESC O P".

There are two ways of fixing the problem. If you are using a terminal-emulator, there is usually some way of configuring the key-mapping so that any particular key will generate a specified byte-sequence. You should configure the terminal emulator so that each function-key generates the same byte-sequence as specified by the terminfo file. The same applies to the cursor keys.

If you are using a non-programmable terminal or a terminal emulator with a hardcoded key-mapping, you will have to edit the terminfo file itself. To do this:

  • run infocmp > /tmp/termfile to decompile the terminfo file into a human-readable format.
  • Edit the file /tmp/termfile with an ASCII editor. It may be advisable to rename the terminal-type in this file, thus creating a new customized terminal-type.
  • Recompile the edited terminfo file with the command tic /tmp/termfile.
To get more information about the infocmp and tic commands, use man infocmp and man tic
Can I use function keys like ALT F1 in my CHARVA program? What about SHIFT F1 or CTRL F1?
It depends on your terminal or terminal-emulator. If your terminal-emulator can be configured to produce a unique escape-sequence for each function key (with the SHIFT, CTRL or ALT modifier), then that escape-sequence can be mapped to a function-key in the terminfo file. Note that terminfo and the ncurses library do not know or care about the SHIFT, CTRL or ALT modifiers; they only know about function keys kf1 to kfn, where n is some arbitrarily large integer. The unmodified function-keys are mapped to kf1 to kf12 (on a keyboard with 12 function-keys). Typically you would map the SHIFTed function-keys to kf13 - kf24, and so on. To do this you would have to edit and recompile the terminfo file as described above.

As far as your Java application code is concerned, you would have to write it to handle key-codes such as KeyEvent.VK_F13 and above; your application would not receive an indication that the SHIFT, CTRL or ALT modifier-key was pressed together with the function key.

Currently CHARVA defines only F1 to F20, but the definitions can easily be extended.

I'm having trouble getting the cursor control keys mapped correctly. Which fields must I edit in the terminfo file?
Note that all the symbols for key strings in the terminfo file start with "k". Symbols that don't start with "k" refer to strings that are received by the terminal, not to strings that are sent by the terminal. For example, cuf1 is the byte-sequence which, if sent to the terminal, will move the cursor forward one column; whereas kcuf1 is the byte-sequence sent by the terminal when the RIGHT CURSOR key is pressed.

Here is a list of useful key symbols in the terminfo file (i.e. in the output of infocmp or the input to tic):

  • kcub1 is the left-arrow key.
  • kcuf1 is the right-arrow key.
  • kcuu1 is the up-arrow key.
  • kcud1 is the down-arrow key.
  • kend is the END key.
  • khome is the HOME key.
  • knp is the PAGE DOWN key.
  • kpp is the PAGE UP key.
  • kich1 is the INSERT key.
  • kdch1 is the DELETE key.
After running my Charva application for a while, the screen becomes corrupted with control characters. Is there a way to programmatically force a refresh of the screen?
Yes, call the Toolkit.redrawWin() method (to indicate to the ncurses library that all the lines of the screen have changed and need to be redrawn), followed by the Toolkit.sync() method to actually redraw the screen.

The underlying cause of the screen corruption may be that your terminal or terminal-emulator is not 100% compatible with the terminfo file corresponding to your $TERM environment variable (see questions above). Try running your application on a different type of terminal, with $TERM set appropriately.

Can I record and play back scripts?
Yes, you can record a script file as shown above by defining the system property "charva.script.record" as a filename. To play the script back, define the system property "charva.script.playback" as in the following example:

 java -Dcharva.script.playback=scriptfile \
            -classpath ../classes:../lib/charva.jar classname

Charva will then play back the keystrokes that were recorded in the script file, with the original time delays between keystrokes. Since the script file is an ASCII file, you can edit it and modify the time delays and the keystrokes. Each line of the script file has three fields; the first field is the hexadecimal code for the keystroke, the second field is the time delay in milliseconds, and the third field is the symbolic name of the keystroke (which is ignored on playback).

While the script file is being played back, any keys that you enter via the keyboard will also be injected into the playback stream.

You can record a script on one type of terminal and play it back on another (incompatible) terminal, because the function-keys and cursor-keys are interpreted by ncurses before they are recorded in the script-file.

How do I display colors?
To display colors, you need four things:

  • Ensure that your terminfo description supports color capability. Run infocmp and check that the string colors#8 appears in the output (or colors#n where n is the number of colors supported).

  • Ensure that the terminal or emulator itself supports colors and is compatible with its terminfo description.

  • Define the system property "charva.color". You can either do this on the command-line with the option -Dcharva.color, or you can define it inside your program (before calling any Charva methods):

                    System.setProperty("charva.color","");
                

  • The source code of the Charva program must set foreground and/or background colors of components (using the setForeground() and setBackground() methods inherited from the charva.awt.Component class).
Using the LayoutManagers provided with Charva is too complicated. Can't I lay out my components "manually"?
You don't have to use the layout managers; they are there for "compatibility" with AWT and Swing, and for people who want to generate a user interface on a WYSIWIG GUI-building tool.

For those who prefer to lay out the components manually, just use the "null" layout manager:

            Container.setLayout(null);
        
The container will then not attempt to lay out its children, and it is up to the application to set their locations (using the setLocation() method inherited from charva.awt.Component). In the case of child components that are instances of charva.awt.Container subclasses, the application must also set their size using setSize().

Note that the setLocation() method sets the top left corner of the component, relative to the top left corner of its parent container; except in the case of a Window (i.e a Frame or Dialog), in which case setLocation() sets the absolute location on screen.

Note also that if you set the size of a Window (i.e. a Frame or Dialog) explicitly in your application, you must remember not to call the pack() method afterwards, otherwise the window will be resized to the smallest size that can contain all its child components.

When writing a Charva program, should I use the components in the charva.awt package or the charvax.swing package?
Use the charvax.swing package. The components in the charvax.swing package have a far richer API.
I don't like the appearance of the components (buttons, labels, frames etc) that the Charva library provides. How can I change the appearance of the components without losing compatibility with Charva?
Thanks to the power of class inheritance, you can easily create your own set of components with a customized appearance. For each customized component, simply subclass the appropriate Charva component and override the following methods:
  • getSize()
  • minimumSize()
  • getHeight()
  • getWidth()
  • draw()
You should of course create your customized widgets in a separate package.
How do I get mouse support working?
Mouse events are only generated by terminal-emulators which provide the kmous capability. To see if your terminal-emulator generates mouse-events, run "terminfo | grep kmous" to see whether kmous is defined. I know that "xterm" and "putty" support mouse-events; there may be others.
Is Charva capable of handling non-ASCII character sets?
Leos Urban has kindly added support for unicode (UTF-8) characters. The changes mainly involved linking with libncursesw instead of libncurses. To quote Leos' email: "I send to you my changes to Charva, tested with Linux (Fedora Core 5). With my changes I can display unicode (UTF-8) characters without problem (see attached screenshot animal_cz.gif - grabbed from linux with cs_CZ.UTF-8 locale)".

The English version of the same screen is animal_en.gif

According to Leos, there are some limitations to the UTF-8 support: "With JTextArea I cannot type any national characters, after some changes I can type most of characters in JTextEdit (but 0x11b and 0x10d do simply nothing and 0x161 works as backtab)."

In the JFileChooser and JOptionPane, having to TAB from one button to the next is too slow; I would like to set up "hot-keys" or "accelerator keys" that are equivalent to individual buttons. Also, I want to be able to customize the button-labels to indicate these hot-keys.
JFileChooser and JOptionPane allow you to customize the button-labels and set up accelerator keys, by modifying static (class) variables. Look at the javadoc-generated documentation of these classes, or at the tutorial application (tutorial/charva/Tutorial.java) for more information on this feature.
After I change the terminal to 132-column mode, Charva still clips the display to 80 columns. How can I make it show all 132 columns?
Call the following code after changing to 132-column mode:
            Toolkit.getDefaultToolkit().resetClipRect();
        
How can I display a JFrame without the line-borders? I need to be able to use all of the available space on the screen.
Just create a subclass of JFrame that has zero-width insets, as follows:
    public class MyFrame extends JFrame {
        public MyFrame() {
            super();
            super._insets = new Insets(0, 0, 0, 0);
        }
    }
        
Then just use your customized subclass instead of JFrame - it will draw itself without borders.
In my CHARVA application, I have a collection of screens that I want to display in any order, selectable at runtime. How can I do this?
In the CHARVA application programming model, the very first window to be displayed must be a JFrame (in other words, this must be the "main window" of your application). This may be a full-screen frame (as described above) or a frame with a border. This "main" frame then creates other JFrames and/or JDialogs (collectively known as Windows) and displays them, using their show() method. Each window can create and show further windows, thus building up a "stack" of windows.

Each window can hide itself by calling its own hide() method. This effectively "pops" the window off the stack, and causes the previous show() method to return. Note that calling hide() does not destroy the window; it remains in existence and can be redisplayed, in exactly the same state as it was before, by calling its show() method again.

If your application is always going to display screens (windows) in the same order, you can just get each window to create and show the next one in the sequence, thus building up the "stack". On the other hand, if the display order must be determined at runtime, you can use the following approach. Assume you have three screen classes A, B and C, and you want to show them in the order A -> B -> C -> A:

            A a = new A();
            B b = new B();
            C c = new C();
            a.show(); // show() blocks until a hides itself
            b.show(); // show() blocks until b hides itself
            c.show(); // show() blocks until c hides itself
            a.show(); // show() blocks until a hides itself
        
How do I do pass-through printing (i.e. to a printer attached to the terminal)?
The terminfo file for the terminal must have the "mc4" and "mc5" capabilities defined, for turning the attached printer off and on. For more information about these capabilities, do a "man terminfo" and look for "mc4" and "mc5". The vt220 terminfo file, for example, does have these capabilities defined.

Use the following code to do the printing:

    Toolkit toolkit = Toolkit.getDefaultToolkit();
            .
            .
            .
    try {
        toolkit.print(String_to_be_printed);
    } catch (TerminfoCapabilityException e) {
            ...
    }
        
Thanks to Craig O'Shannessy for information about this issue.
How do I print the screen contents (to a printer attached to the terminal)?
The terminfo file for the terminal must have the "mc0" capability defined. Do a "man terminfo" and look for "mc0". The vt220 terminfo file, for example, does have this capability defined.

Use the following code to do the printing:

            Toolkit toolkit = Toolkit.getDefaultToolkit();
            String print_screen = toolkit.getStringCapability("mc0");
            .
            .
            toolkit.putp(print_screen);
        
My terminal has an output port (activated by an escape sequence) for opening a cash drawer. How do I activate this port using Charva?
You have to define a "user-defined capability string" (containing the escape-code sequence for activating the output) in your terminfo file. Do a "man terminfo" and look for "u0". You will notice that you can define up to ten user-defined capabilities, named u0 to u9. After adding the user-defined capability, compile the terminfo file using "tic". Then use the Toolkit.putp() method to output the user-defined string to the terminal, as follows:

            Toolkit toolkit = Toolkit.getDefaultToolkit();
            String open_drawer = toolkit.getStringCapability("u0");
            .
            .
            .
            toolkit.putp(open_drawer);
        
Can I use a bar-code scanner with Charva?
Yes, the bar-code scanner is typically attached to the keyboard port of the terminal; Charva cannot tell whether characters are entered via the barcode scanner or manually via the keyboard.
Can I call the methods of the various CHARVA components from arbitrary threads in a multi-threaded program?
No; as in Swing, most of the methods are not synchronized (for performance reasons, as well as to avoid deadlocks). Exceptions are:
  • JTextComponent.setText
  • JTextArea.insert
  • JTextArea.append
  • JTextArea.replaceRange
The subject is very well explained in Chapter 1 of "Core Java 2, Volume 2 - Advanced Features" by Horstmann and Cornell. (page 61, in the subsection titled "Threads and Swing").

Like Swing, CHARVA does all of its drawing (i.e. all of the ncurses function calls, besides reading the keyboard) in a single "event dispatcher" thread. If you want to modify the display from other threads, you should use the static SwingUtilities.invokeLater(Runnable) method, as described in the Core Java book.

My Charva application performs a time-consuming operation (for example, a network operation) and the user-interface "freezes" until the operation has completed. How can I make the user interface responsive while the time-consuming operation is progressing?
Spawn a separate "worker" thread to do the time-consuming task, and use the technique described above (the SwingUtilities.invokeLater() method) for the worker thread to communicate with the Charva event-handling thread. The worker thread can call SwingUtilities.invokeLater() at various stages of its progress, causing Charva to (for example) update a JProgressBar.

The Tutorial program (tutorial/charva/Tutorial.java) included in the distribution zipfile includes an example of how to perform a time-consuming task in a separate worker thread.


Last updated: 31 October, 2006