If you thought finding a good screen library was difficult, you're right. But author Michaels supplies some useful hints to aid your search.
This article is for those of you starting a new project and finding yourself in the unenviable position of trying to locate a nice, simple, cross-platform user interface library. I've spent many hours over the past few months in just such a search, checking books, magazines and the Internet. I'm hoping this will save you a great deal of time if you find yourself in a similar position.
Two Extremes
The most basic screen I/O available in C++ is the iostreams library. Personally I'd be happy to just use cout and cin in all my programs, if only I had not run into some drawbacks. One problem is that not all compilers support cin and cout correctly, especially if they create programs for Microsoft Windows. Later versions of these compilers may correct this problem, but I must work with what I have. Another major concern is that many users want a more standard user interface, one that looks like the rest of the programs that run under their operating system. Trying to create a user interface that includes menus, edit boxes, push buttons, and the like using just cout- and cin-style commands would take an enormous amount of work. That's the point of trying to locate the screen library in the first place -- to avoid that work.
Going to the other extreme, there are plenty of commercial cross-platform libraries available. But, for a variety of reasons -- among them cost and complexity -- I quickly ruled them out. Lots of software magazines run some good comparison articles if you think this is the route you want to take.
Having ruled out those two possibilities, I began to explore the options between the two extremes. The biggest difficulty I face in my applications is that I want my user interface library to work on character-based systems (like MS-DOS) as well as graphical systems (like Windows). It's easy to find systems for one or the other category, but finding one that supports both is almost impossible.
Character-Based Libraries
Curses
Let's start with character-based user interfaces. One of the most well-known character-based screen libraries is curses (a.k.a. ncurses). If you have programs written in curses or are willing to work with the curses API, you can find several ports of curses available for different systems. The ncurses library works on any POSIX-conformant UNIX platform, and can be obtained by ftp from most GNU collections. (For example, see Item #1 in the box "Starting Places. ") A note about downloadable software: whenever retrieving libraries, especially from the Internet, be sure to check that you have the latest stable version. Also, since information on the Internet can change daily, if you can't access a reference, try locating the library or program with a search engine. If you need a DOS port of curses, there's a nice version available from the SIMTEL archive called PDCURSES. (For more information, see Item #2.) It also works on OS/2 and an X11 version is available. There are also ports of curses available for Windows NT and other platforms.
If you find, as I did, that curses doesn't give you enough high-level functionality, you can check for libraries that work on top of curses. A couple of good ones are versions of WXWIN or TK. However, I found out the hard way that just because screen libraries work with curses and you have a DOS version (or a version for whatever system you're on), it does not mean the screen library will work on your system. A lot of libraries that work with curses have other UNIX dependencies in their code as well.
More functionality
I did finally manage in my search to turn up a good number of character-based libraries with higher functionality than curses. They are available for a nominal fee. Several are located at the Simtel archives under the msdos/cpluspls directory. There is a library called Sword written for djgpp compiler users. It works with other compilers too. You can check the djgcc collections, such as those under the SIMTEL archive for more information. (See Item #3.)
I also found a very comprehensive library, C/Windows Toolchest, available from Tom Mix software (Item #4). All of these character-based options are reasonably priced. With most of them, you can try before you buy. Another option is Turbo Vision, which Borland freely includes with its C++ compilers. These make a good alternative if you feel very comfortable with the API and you don't need support for other platforms. However, I do need support for other platforms and compilers, so I decided to continue my search.
D-Flat
One last character-based choice I found was the library D-Flat. It is written in C and chronicled in a series of articles in Al Stevens' "C Programming" column of Dr. Dobb's Journal [1] . D-Flat is freely available. There are several versions floating around, including a C++ version, an OS-2 version and a djgpp version. However, the latest and most stable version I could turn up was version 20 (Item #5). You can also get a C++ wrapper class (Item #6) to use with version 20. D-Flat 20 works on a DOS platform and can be compiled as a 16-bit or 32-bit library for Borland, Microsoft, or Watcom. (Although I could not find specific mention of Symantec support in the latest version, it shouldn't be too hard to get a Symantec version running with support for so many other compilers built in.)
Graphical Libraries
Moving on to the graphical end of the spectrum, I located several comprehensive libraries freely available over the Internet. The first one I found was wxWindows. (See Item #7.) wxWindows supports or has ports in progress for Windows, UNIX, Macintosh, OS/2, Nextstep, VMS, and Amiga. I also found some references to YACL. (See Item #8.) YACL supports Windows and OS/2 platforms and UNIX systems with Motif. One nice thing about YACL: there is a YACL book [2] , and it's available in local bookstores. Be aware that YACL has some strings attached if you use it for commercial purposes.
Continuing with freely available libraries, I'd be remiss if I failed to mentionTCL/TK. (See Item #9.) TCL often runs as an interpreted language, but the libraries for it are all written in C. In fact, TCL was orginally designed as a library to be used in C programs. Some libraries also exist to ease the embedding of TCL functions in C or C++ code. TK is the actual screen interface library, but it requires the TCL library to run.
TCL and TK are available on a variety of platforms including Windows (3.1, 95, and NT), UNIX, Macintosh, and OS/2. TK includes both standard GUI versions and a curses version to support character-based applications. The UNIX version is very well supported. Rewrites for Windows and Macintosh are currently in the works and may not be as stable. You can also find a number of recent books about this library in bookstores [3] [4] .
Have Some Java
Some would say that Java, with its Abstract Window Toolkit (AWT) is the ultimate cross-platform language. I found some references to the AWT libraries. (See Item #10) The AWT is Java's official screen library. It's similar toC++'s iostreams in that it allows screen I/O across all platforms, but has more functionality in creating GUIs. I personally would love to see something like this for C++, as it would automatically solve my portability problems. The Java syntax is very similar to C/C++, so if you want to be absolutely sure that you're using a portable screen interface, switching to Java to write your code may be a very attractive alternative.
Of course, as with most solutions, this one has drawbacks. Java is available only on specific platforms, such as Windows 95, Windows NT, Solaris 2.x, SPARC, and Macintosh systems. No other platforms are supported by Sun as of this writing. Also, while Java is great for applications that are run over networks, if you're selling an executable, it's not a good choice. At this stage in the language's development, Java is an interpreted compiled language. You compile your code into device independent p-code (using a compiler such as javac) and run it through an interpreter, such as the java program. If you need a single executable program, you'll have to look at other alternatives.
Going Native
A list of screen library options would not be complete without considering native user-interface libraries. If you're on Windows, you can use the Win32, MFC, or OWL APIs. On UNIX, there's Motif and Open Look, etc. Native APIs or frameworks are convenient because they're freely available with the compiler. Problems arise when you have to port to other systems. The good news is that several native APIs have already been ported to various other machines. For example, ports now exist from X-Window calls to Microsoft Windows. If you've already coded your program on one system and don't want to rewrite it, this is one option for porting your code.
Based on what I've read, and from my experience with libraries, if I were going the native route I would probably choose a cross-platform API based on MFC. I would choose MFC mainly because it supports the most platforms. Versions of the MFC API are available for UNIX, Macintosh, and even MS-DOS. MFCis also easier to work with (at least for C++ programmers) than Win32. Beyond these two things, however, I know of no compelling reason for you to abandon a framework or library you're comfortable with.
Now for the drawbacks of native APIs. Many of the ports for other systems run much, much slower than the native version. Also, while the native version is usually freely available along with the compiler, many of the other system ports require you to buy commercial products from various vendors.
If All Else Fails . . .
One last place to look for information and comparisons on portable user interface libraries is in the Platform Independent Graphical User Interface FAQ. (See Item #11). It's also helpful to keep an eye on current developments through magazines and on the Internet to see if anything new eventually surfaces.
What Works for Me
So far, I've run through several options, but none of them have worked perfectly for my situation, and perhaps would not for yours either. As I've mentioned, my biggest problem in locating a screen library is trying to find a user interface that can support both character-based and graphical systems. Many implementors of libraries (both commercial and non-commercial) feel that character-based libraries are on their way out and a waste of their time to implement or support. In answer to that thinking, I would like to quickly point out the cases when a programmer may need a character-based user interface library, and to remind implementors of a few reasons for using one in the first place.
One reason to prefer a character-based library is that the user may be working with a low-end machine. Believe it or not, some people out there are still running old-style 8086 or 80286 PCs with nothing more than DOS installed. Not every user is a programmer who needs to keep up-to-date with the latest systems. If you're working with limited hardware, you may not have the luxury of using a full-blown graphical operating system either. Some people actually do prefer the look of character-based programs and prefer to purchase them over other programs. It is often easier to read the print on character-based screens than on graphical screens. The moral of this story is: it's important to know who your end user is and be familiar with your market or customer base. Also, it's easier to choose a library that supports more than what you currently need, than to have to search for and port to another new library later on if you find the one you have doesn't support all your goals.
If you're in a position similiar to mine, you're probably wondering if I ever found my ideal screen library. The answer is yes and no. What I finally decided to do was pick some libraries that worked well on the systems I needed to implement them on and create some wrapper classes to make those implementations all appear alike on the different systems. This solution keeps me from writing everything from scratch. For Windows I chose MFC, since code written for it can easily be ported between Windows 3.1, 95, and NT. A port of MFC is also available for the Mac platform. When I have more time, I can change the underlying code to use a native Macintosh API and increase the execution speed of my programs for that platform. For DOS platforms, I decided to use D-Flat and the D-Flat wrapper classes. The controls in this library and the D-Flat wrapper class interface are very similar to the MFC library. This helps decrease coding time for the DOS platform port.
I haven't found any one solution that's perfect for my situation; I still have had to do some coding. I created three main wrapper classes similar to the classes used in MFC. One encapsulates the application, another the frame window, and the third encapsulates the individual MDI (multiple document interface) windows. Any functionality specific to the libraries I'm working with is hidden within these three classes. I then designed a uniform interface for the wrapper classes that lets me write to, get information from, or add controls to a window in the same way regardless of the underlying library I'm using. For example, my MDI Window class wrapper has a text function that lets me add text to the screen the same way on any platform. The member function for sending text to a window appears as follows:
void text (char *words, position *pos, attributes *att);I also took pains to encapsulate data in classes as much as possible. This data includes information such as position of controls or text on screen, color of controls or text, and the actual text being written to or read from the screen. Not only does encapsulating this data help when porting, it also allows for room to grow. The requirements of my screen library and the way information is displayed or the type of information I display may change. By encapsulating the information, it becomes much easier to make these changes later. This also helps minimize the amount of code that will be affected by these changes.
My final screen library design is composed of two parts. I choose a platform-specific screen library for the platform I'm working on. I then encapsulate the screen library in my own classes so that I have a universal subset of commands that will get the job done. I hide the platform-specific code within these classes and use it to create my own screen library. I had to do a lot of searching to find which libraries to use, and to finally come to the conclusion that no one library is right for my specific needs. Hopefully, I've managed to give you enough concrete examples of actual user interface libraries available to make your own search for an ideal screen library easier.
References
[1] Al Stevens. "C Programming" column, Dr. Dobb's Journal, May 1991 - May 1995.
[2] M.A. Sridhar. Building Portable C++ Applications with YACL (Addison-Wesley, 1996). ISBN:0-201-83276-3.
[3] John K. Ousterhout. Tcl and the TK Toolkit (Addison-Wesley, 1994). ISBN: 0-201-63337-X.
[4] Brent B. Welch. Practical Programming in TCL and TK (Prentice-Hall PTR, 1995). ISBN: 0-13-182007-9.
Laura Michaels is a senior software engineer at INTERCOMP, creator of entertainment, hobby, and custom software. She can be reached through INTERCOMP, section INT-IP, Box 6514, Delray, FL 33482 or
http://members.aol.com/lauram3017/index.html.