On Fri, Oct 26, 2012 at 10:06:38AM +0200, Jens Mueller wrote: > H. S. Teoh wrote: > > On Fri, Oct 26, 2012 at 12:27:38AM +0200, Jens Mueller wrote: > > > Walter Bright wrote: > > [...] [...] > > > > 1. getting mouse input > > > > > > Anybody an idea how to this on Linux? > > > > You can only do this in terminals that support it. XTerm, I believe, > > has escape sequences that you can send to turn on mouse tracking. > > Those will show up as special escape sequences on stdin, which will > > have to be intercepted and removed from the program's normal input > > stream. Other modern terminals probably have their own way of doing > > mouse tracking. AFAIK, there isn't any standard for this, so you'll > > have to stick with terminal-specific code. > > > > (Which is why I recommended earlier that this module must be modular > > so that support for specific terminals can be plugged in easily -- > > for the initial stab, something very simple such as vt100 support > > may be good enough, as long as it's easy to add support for new > > terminals.) > > So there exists no portable library abstracting mouse input? If > that's the case then being modular is the only option. How would you > design it? I don't plan to implement this. But leaving the door open > for others should be possible.
Hmm. I googled around a bit, and found that the only portable libraries for abstracting terminal capabilities appear to be curses and its derivatives like ncurses. So if we're going to reengineer a D console library that doesn't depend on ncurses, we'll have to get our hands dirty with interpreting $TERM and parsing terminal capabilities. :-( As for design, I think a very simple and easily extensible design would be something along these lines: Have a generic Terminal base class that contains all the API functions for various terminal capabilities, like interacting with the mouse, setting color, moving the cursor, etc. These functions are stubbed to throw an UnsupportedTerminalCapability (or something like that) exception when they are called. Then each supported terminal type will derive from Terminal, and override those functions that are supported for that terminal type. The module initialization code will determine at runtime which of these subclasses to instantiate. Then build an additional layer on top, with higher-level API functions that eventually call the object's methods to perform various terminal functions (e.g., writeln can be extended to support color by interpreting color escape sequences that ultimately result in calling some underlying method in Terminal). When the module is extended to handle new capabilities, we just add new methods to Terminal, stubbed to throw UnsupportedTerminalCapability. When we add support for new terminal types, we just create a new subclass of Terminal that implements the new methods. I think for maintainability, Terminal should not be directly accessed by the user, so that its methods can be kept concise and at the correct abstraction level for interacting with low-level terminal functions. The module should provide a higher-level API with underlying calls to these functions, say by extending writeln, implementing screen buffering, etc.. [...] > > > > 7. getting no-echo raw input > > > > > > Tried this but couldn't make it work yet. This is useful for > > > passwords prompts, right? > > > > Not just that, but also for fully-interactive programs that want to > > capture every keystroke immediately (instead of waiting for the user > > to hit Enter). Like games and stuff. Or menu-driven systems where > > the user can navigate between menus and items without needing to hit > > Enter each time. > > > > For Unix terminals, you need to send certain escape sequences > > (specific to the terminal) to enable what is called 'raw' mode or > > 'cbreak' mode. (Googling for 'cbreak' should give you useful > > references.) This will cause the terminal to immediately transmit > > keystrokes, instead of buffering them until the user hits Enter. > > > > Also, make sure that there is a way to turn off this mode after the > > program is finished, otherwise the terminal may become unusable when > > it returns to the shell prompt. :) > > Thanks for the pointers. > So these are then two things. First noecho and the other one is raw > input. Yeah, noecho is useful for password input; raw input is needed for interactive apps like games or menu-driven programs. Both should be supported. [...] > > The important stuff are cursor positioning, box drawing, incremental > > updates, cbreak mode, etc.. > > Can you say something about incremental updates? Any pointers? [...] The idea behind incremental updates is this: if I write a string "ABCDEF" at position (10,10), then I write "ABDCEF" at the same position, the console library should know to only replace "CD" with "DC" the second time round, instead of redrawing the entire string. Or, on larger scale, if my app draws an almost-identical copy of the current screen, the library should know to only redraw the "diff" between the previous state of the screen and the new one. This is commonly implemented by buffering the current state of the screen in the library, and marking parts of the buffer "dirty" when they are changed. Then when there is a pause (say the app is waiting for input) or the screen needs to scroll, etc., the library updates only the parts of the screen that correspond with the "dirty" buffers, and clears the dirty flag. The basic motivation is that the terminal may be connected to a remote machine via a slow or congested network, so it's faster to keep track of things locally and only send "diffs" to the remote end. Waiting for a pause also allows you to group several updates into a single network packet, instead of sending one packet per character, which is very slow. (Even if the terminal is local, it can be faster to do things this way, because it minimizes writes to video RAM, which is slower than writing to main memory. Or in the case of X11 terminal emulators, it saves the cost of redrawing the same pixels over and over.) T -- People demand freedom of speech to make up for the freedom of thought which they avoid. -- Soren Aabye Kierkegaard (1813-1855)
