CXXCURSORWINDOWS

 [See also:  CXXTOOLS.txt, CXXLIBRARY.txt, CXXDIRVIEWER, CXXEDITOR.txt, and README]
 
 
 ==================
 CXX CURSOR WINDOWS
 ==================
 
 
     INTRODUCTION
     ------------
 
     The library, tools.a (or .lib on Windows), contains a variety of general purpose
     routines that can be used to write applications portable to linux, unix, and
     windows.  One set of routines provides a cursor based windowing system.  That is,
     windowing applications can be written that draw in "windows" within an Xterm
     window, a putty terminal, or on MS Windows using a console window.
 
     There are several layers of routines that make up this subsystem.  However, it is
     generally advisable to only think in terms of the highest layer.  The lower layers
     are driven carefully by the upper layers -- if you try to mingle calls to the
     wrong layers you will create an application that doesn't always respond correctly
     to user events.
 
     The cursor windows that you can create are tiled.  That is, due to the small size
     of terminal windows, a design decision was made not to waste space with window
     borders.  To avoid this, tiled windows are used -- and instead of explicitly
     drawn window boxes, highlighting and underlining are used to separate tiled
     window regions.  Thus you have a some slight responsibility with respect to the
     content of your windows.  Your responsibities include setting the text attributes
     of the top and bottom lines of your windows to help mark the borders.  Note
     that the screen can be split both horizontally and vertically.  
 
     To write an application that uses the CXX cursor windows, you derive from class
     Viewer and superseed to virtual two functions:  a repaint handler and a keyboard 
     event handler.  Note that I thought that I would try to support mice one day but 
     I never could get it to work reliably.  Don't let the data structures confuse you, 
     there is no mouse support at this time.
 
     In addition to the tiled windows, it is possible to create popup dialog windows
     that are centered in the middle of the terminal and are drawn in reversed video
     attributes to eliminate the need for space wasting boxes -- although by the time
     you read this, I may have added a box border anyway.
 
     To see an example of how create a cursor windowing application, look to file
     editor/editor.cxx.  This file combines all the existing cursor windowing
     applications into a single executable.  You can add new ones to the editor or
     make separate executables if you don't want to burden the editor.exe program
     with your new creations.
 
 
     MAIN PROGRAMS FOR TEXT WINDOWING APPLICATIONS
     ---------------------------------------------
 
     The basic logic of a cursor windowing executable works like this:
 
 
 
 
 	ViewerManager vm;  // the cursor windowing system main interface
 	
 	// set up some information used by the help subsystem
 
 	vm.executable_version_ = editversion;
 	vm.executable_name_    = options.argv[0]; // guaranteed to exist
 
 	// open the main cursor window
 	
 	vm.open();  // need to open the window so that sizes of viewports
 		    // can be calculated.  This must be done AFTER the program
 		    // options are parsed because of the potential of the 
 		    // ProgramOptions constructor to call exit().  If the window 
 		    // is open when that happens the terminal characteristics will 
 		    // get messed up.
 	
 
 
 
 
 	// now add application TYPES to the viewer manager so that it can know how to
 	// handle various types of files
 
 	// directories
 
 	vm.add_app(DirectoryViewer::app, DirectoryViewer::app_name);
 	vm.set_directory_app(DirectoryViewer::app);
 	
 	// generalized text editing (edit or 'e' command from dir viewer)
 
 	vm.add_app(TextEditor::app, TextEditor::app_name);
 	vm.add_editor_app(TextEditor::app, "");  // handles all files extensions
 
 	// generalized text viewing (show or 's' 
 	// command from dir viewer (enter key too))
 
 	vm.add_app(TextViewer::app, TextViewer::app_name);
 	vm.add_viewer_app(read_only_edit, "");  // handles all files extensions
 
 	// comma separated values file editing.
 
 	vm.add_app(CsvViewer::app, "CsvViewer");
 	vm.add_editor_app(CsvViewer::app, ".csv");  
 
 	// other windowing applications that have to be manually invoked.
 
 	vm.add_app(KeyViewer::app, KeyViewer::app_name);
 
 	// ... other types of your own construction
 
 
 
 
 	// now, add an actual Viewer that the user can interact with:
 
 	Viewer * editor = vm.open("Some Filename");
 
 	vm.add(editor, "Some Filename");  // viewer's are associated with a file
 
 
 	// finally, animate the windows until the user quits.
 
 	vm.run();
 
 
     WINDOWING APPLICATIONS
     ----------------------
 
     As mentioned above, a windowing application consists of two fundamental functions:
 
       * screen repaint handler
 
       * keyboard event handler
 
     There are a few other things you have to do as well:
 
       *  declare a variable holding the application name and brief description
 
       *  create a function that will "new-up" your application and when invoked by
 	 the viewer manager.
 
       *  properly handle some system specific events that switch windows, kill 
 	 the application, etc.  
 
       *  implement help for your application
 
     The editor of course does all these things and can serve as a programming example
     when needed -- if you can find how things work.  It's pretty complicated.  The
     Key Viewer application is much simpler -- it ignores some of the interfaces 
     because it is designed to always work with the screen space given to it.  See
     lib/keyviewer.cxx.
 
 
     REPAINT HANDLER
     ---------------
 
     An application must have a repaint handler function.  This function repaints the
     window from scratch.  It must obey the text attribute guidelines or your app
     will look messed up when the screen is resized.  Here are the basic rules:
 
       *  each window can either be active or not
 
       *  the top line of a window should be the title line and should be in the
 	 active title attribute or the inactive title attribute at all times
 
       *  the bottom line of the window should be displayed in the bottom line
 	 attribute -- which will make it underlined on xterms and putty and
 	 a unique color in windows.
 
       *  when the screen is split horizontallay and your window is not the
 	 leftmost window, you should draw verticle bars in column 0 of every
 	 line.
 
       *  you draw most of your window's text in the normal text attribute
 
       *  use the highted attribute for cursor lines
 
       *  use the active_mark attribute or the inactive_mark attribute for
 	 lines the user has marked.
 
      The ViewerManager provides variables that hold most of these text attributes.
      The member names and default values are:
 
 	 int ViewerManager::normal_att        = CursorWindow::normal;
 	 int ViewerManager::active_title_att  = CursorWindow::reverse_bold;
 	 int ViewerManager::inactive_title_att= CursorWindow::underlined;
 	 int ViewerManager::active_mark_att   = CursorWindow::reverse_ul;
 	 int ViewerManager::inactive_mark_att = CursorWindow::bold;
 	 int ViewerManager::bottom_att        = CursorWindow::underlined; 
 	 int ViewerManager::highlighted_att   = CursorWindow::reversed;
 
      Theoretically, you might implement functionality that changes these
      attributes on the fly but it is proably not a good idea -- there are just
      barely enough separate attributes in the curses implementation to do the
      above. 
 
      A trivial repaint handler works something like this:
 
 	Get the width and height of the viewport passed in
 
 	fill the whole viewport with normal attribute
 
 	Paint the top line of the viewport with a title using the
 	active_title attribute -- and fill to end of line to make
 	it a title bar.
 
 	Paint any other text of interest in either the normal attribute
 	or the bottom_att if you are painting the bottom line.
 
 	Position the text cursor on the first line of interest.
 
      Note that the repaint handler is passed a command to tell you what is going
      on.  For example, you might receive a normal paint request.  Or, your window
      might be losing focus and in that case you would only want to repaint the
      very top line of your window in inactive_title_att so that the user sees
      that your window is not longer active.  There should only be 1 active viewport
      at a time.
 
 
      WINDOWS AND VIEWPORTS AND MANAGERS -- OH MY!
      ----------------------------------------------
 
      There is actually only 1 cursor window object for the whole application. You
      should not make any direct drawing calls to the cursor pointer that you
      might have occaision to receive.  You can use it to call the beep() function
      and to get the total screen width and height.  That's about the only safe
      things you can do with it.
 
      There is also only 1 viewer manager object.
 
      There are an infinite number of viewports.  A viewport is a constantly 
      changing handle to sub-set of the screen space.  Basically, your application
      gets a new (and different) viewport everytime the repaint handler or keyboard
      handler is invoked.  Do not attempt to save the pointers passed to these
      functions.  You should architecture your function calls to take a viewport
      pointer as a parameter.
 
      You can store the viewer manager pointer, however, and you should because
      you will need it to make various inquiries.
 	 
 
      POPUP DIALOGS
      -------------
 
      Popup dialogs fall into various categories and popups know how to respond
      to screen resizes, so they are a good way to ask the user for input data.
      They do not make sense as an entire application implementation strategy.
      They pop up in the middle of the screen and you can only have one at a time.
 
      There are several kinds of dialogs:
 
        simple message -- Just pops up text and waits for the user to press
 			 enter.  
 
        string         -- asks the user for a string and also interprets the
 			 tab key as a way of expand the existing string
 			 with any files in the current directory that match
 			 that string as a prefix.  Similar to the way
 			 bash and the Windows command line interpret tab.
 			 Esc aborts input.
 
        Multifield     -- a collection of fields of various types that you
 			 can construct.  The user can enter them all or
 			 none by pressing Esc to abort input.
 
        FileSelector   -- prompts the user for a filename by providing a list
 			 alternatives to choose from.  The user can scroll
 			 in the list or add a new name or change the text of
 			 an existing name.
 
      All dialogs have a title and are painted in reversed video to delimit
      them from the background text.
 
      Dialog's are typically class object that have an operator += that lets you add
      fields or strings.  To construct most dialogs you do something roughly like
      this:
 
 	 CursorWindow::Dialog::DialogType   d(some parameters);
 
 	 d += "some strings";
 
 	 d += new FieldType(name, parms);
 
 	 if(d.popup(viewerManager_->window()))
 	 {
 	    return false;  // the user aborted
 	 }
 
      Dialog fields typically have names.  To get the data out of the dialog
      you inquire the field value given a field name.  If it is not there,
      you assume the user didn't set the value.
 
      
      ListViewers
      -----------
 
      The directory viewer shows you the files in a directory and lets you
      issue commands on them.  It is implemented as a derived class of the
      ListViewer base class.  Any simple list of items can be handled with
      a ListViewer extension class.  On the other hand, it only lets you
      perform fairly simple commands on the list.  See lib/directoryviewer.cxx.
 
      The ListViewer base class handles most screen painting and keyboard
      interactions.  The derived class focuses on handling keyboard events
      but is limited in how it can draw the lines.  It does support
      marking lines and special lines that are displayed in bold.
 
 
      Table Viewers and Editors
      -------------------------
 
      The TableViewer and TableEditor classes present the user with rectangular
      grids of strings.  They are meant to be base classes from which real
      editors and viewers are derived.  There two examples in the editor.exe
      program:
 
        *  The comma separated values editor (also handles tab separated values)
 
        *  The ScriptTableEditor that lets you supply a bash script that
 	  that drives the scriptTableEditor viewer to display information
 	  and let the user issue commands on it.  The ScriptTableEditor is
 	  meant primarily for displaying of data from the file system or
 	  CM system (such as svn or git).  It is not meant as a primary
 	  editing too -- mainly it should be used to display script outputs
 	  and let the user make simple choices.  See the STV subdirectory
 	  for scripts.  From the DirectoryViewer, you can press the 'V' key
 	  and it will prompt you for one of the table editor scripts to
 	  execute.  At this time the following table editor scripts exist:
 
 	    *  example.sh (heavily commented trivial example)
 	    *  svn.sh     (pretty complete)
 	    *  git.sh     (pretty useful)
 	    *  grep.sh    (poor quality)
 	    *  ps.sh      (toy wrapper around the system ps command)
 	    *  zip.sh     (toy wrapper around unzip)
 
 
      Tree Viewer
      -----------
 
 	An indented list viewer that is currently used only to display the
 	program symbol database (TAGPP.tagpp) created by cpptagdb.exe.
 
 	You can derive from the base class and create your own viewers. 
Generated on Wed Feb 29 22:51:48 2012 for CXXUtilities by  doxygen 1.6.3