Weeks of Linux terminal experimentation and reading countless web posts about terminal emulation and ANSI escape sequences and I have somewhat gained control of terminal output. But some simple coding to try to implement my original project has shown that another approach is going to be necessary.
My situation is that I am a Windows programmer moving to a new programming environment in Linux. It appears that the standard for terminal programming where any kind of character output control has been done with the ncurses library. Even using that forces the programmer into a sequential style of programming, not an event-driven programming paradigm such as Microsoft Windows and its API.
My new project direction is to develop a Windows-like API for Linux terminal (text-based) programming. This will be very similar to the structure of a Windows program using Visual Studio C++. This has been under development now for about 3 weeks. This and following posts will be updates on the progress of this major undertaking.
First, I want to describe by Linux setup. I am developing between several computer, one is a Windows 10 computer with VirtualBox running a Linux Mint virtual machine. The other computer is an 8 year-old gaming computer running Linux Mint as its core OS. Both machines are running Microsoft Visual Studio Code for the IDE. This provides a familiar environment for someone coming from a Windows Visual Studio background. I have found programming in the Linux environment very similar to Windows. It’s not much of a leap moving between Windows and Linux. To be honest, the biggest difference is the compiling process where in Windows it’s pretty much all taken care of for you behind the scenes. In Linux, it requires learning a bit about ‘makefiles’. But once the makefile is created, just a few keystrokes to get to a separate workspace and to compile and run are now just as automatic and almost as fast as it was in Windows.
I’ve developed a core library of cursor positioning, text formatting, keyboard and mouse input for the terminal. This provides the foundation for user input and ouput where each key stroke is mapped to a virtual key integer value. This is required for non-ASCII keystrokes such as [Page Up], [Alt]+[Page Up], [Ctrl]+[Page Up], etc. This reduces ANSI escape sequences received from stdin from up to 7 bytes to only a single integer, which allows for simple packing into a SendMessage function. Mouse input is similar but is a minimum of 9 bytes. These mouse escape sequences give the mouse action such as move, scroll wheel up or down, button click, which button down or up, and the character position the mouse pointer was over when the event happened. So these events are happening many times per second, interspersed with keyboard keystrokes. An application message queue was developed to hold these mouse/keyboard event messages until they are processed. An event loop was created to process the application message queue and I’m getting a loop processing time of 1/100 of a second, or 10ms. The event loop has a variable delay built-in to save CPU processor time by sleeping about 8ms per loop when there’s no messages in the application queue waiting to be processed, to 1us when there are unprocessed events in the queue.
I’ve still got some work to do with screen mapping and window client area and non-client areas to have a consistent coordinate system. The Linux terminal maps the character positions as 1-based (first row is row 1), and I’m pretty sure I need a 0-based coordinate system to make it the same as Windows.
Another issue I’ve discovered is the wide range of terminal emulators and the varying degrees to which they support text attributes (text color, text background color, bold, italics, underlined, etc.), and even mouse input. Some terminals will not report mouse movements, but will report click and scroll actions. This is probably the biggest benefit to using the ncurses library, but what exactly would I learn about Linux programming by using a pre-built library? In this project, I am excited about the destination, but really more excited about the journey.
So, for now, I’ve got the application message queue, the message loop, RegisterClass(), CreateWindow(), SendMessage() and a few other basic Windows functions working, or mostly working in my text-based Linux Windows project. I don’t even know what I’m going to end up calling it. I hope to be able to share some screenshots on my next and following posts to keep you informed on the progress.