Inspired by Simon Ford's "Terminal" library, this is a clean-room reimplementation that supports a larger set of the ANSI escape sequences and includes a few handy drawing routines. Useful for making console UIs for your projects. The box-drawing stuff requires your terminal to be set to codepage 850.

Fork of ANSITerm by Dan Summers

Revision:
0:863811463610
Child:
1:e3403c93f864
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ANSITerm.h	Tue Sep 18 18:58:19 2012 +0000
@@ -0,0 +1,334 @@
+/**
+ * @file ANSITerm.h
+ * @author Dan Summers [ https://mbed.org/users/dansummers ]
+ * @date 20120918
+ */
+/*
+Copyright (c) 2012 dansummers
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in 
+the Software without restriction, including without limitation the rights to 
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 
+of the Software, and to permit persons to whom the Software is furnished to do 
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all 
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
+SOFTWARE.
+ */
+ 
+#ifndef _ANSITERM_
+#define _ANSITERM_
+
+#define _ANSITERM_CP850_ /* Use CodePage 850 for box-drawing. */
+
+#include "mbed.h"
+
+/** ANSI Terminal control library, inheriting from Serial.
+ *
+ * ANSITerm encapsulates a large portion of the ANSI escape sequence set,
+ * so that a user unfamiliar with the escape sequences can manipulate the
+ * terminal.  It also provides a tidy point of abstraction, should it be
+ * necessary to support multiple different escape sets in the future.
+ *
+ * ANSITerm assumes that the terminal being manipulated implements the 
+ * ANSI-standard escapes.  The terminal is divided into cells, each one
+ * the size of a character (a typical "default" terminal will have 25 rows of 
+ * cells, each with 80 character cells in it, but this will change if the
+ * terminal is resized.)
+ *
+ * The box-drawing functions currently assume that the terminal is using 
+ * CodePage 850 to interpret received characters.  It is untested under
+ * UNIX and MacOS (fixing this is on the TODO list).
+ *
+ * Example:
+ * @code
+ *  terminal.clear_screen();
+ *  terminal.hide_cursor();
+ *  terminal.set_display_style(ANSITerm::SGR_NONE);
+ *  terminal.set_text_colour(ANSITerm::SGR_RED);
+ *  terminal.draw_box(3,3,19,5,ANSITerm::simple,false);
+ *  terminal.set_text_colour(ANSITerm::SGR_WHITE);
+ *  terminal.set_display_style(ANSITerm::SGR_BOLD);
+ *  terminal.set_cursor_position(5,4);
+ *  terminal.printf("ANSI Terminal");
+ * @endcode
+ */
+class ANSITerm : public Serial
+{
+  public:
+    /* Internal buffer for the SGR style flagset currently in use. */
+    char current_style;
+    
+    /** SGR "flag" indicating the default text style. */
+    const static char SGR_NONE = 0;
+    
+    /** SGR flag to request bold text. */
+    const static char SGR_BOLD = 1;
+    
+    /** SGR flag to request faint text. */
+    const static char SGR_FAINT = 2;
+    
+    /** SGR flag to request italic text. */
+    const static char SGR_ITALIC = 4;
+    
+    /** SGR flag to request underlined text. */
+    const static char SGR_UNDERLINE = 8;
+    
+    /** SGR flag to request slow-blinking text (not always supported). */
+    const static char SGR_BLINK_SLOW = 16;
+    
+    /** SGR flag to request fast-flashing text (not always supported). */
+    const static char SGR_BLINK_RAPID = 32;
+    
+    /** SGR flag to request inverse-video. */
+    const static char SGR_IMAGE_NEGATIVE = 64; /* Switch on inverse video */
+    
+    /** SGR flag to request struck-through text (not commonly supported).*/
+    const static char SGR_CROSSED_OUT = 128;
+
+    /* SGR colours */
+    /** SGR colour indicator for ANSI Black.*/
+    const static char SGR_BLACK = 1; //30
+    
+    /** SGR colour indicator for ANSI Red.*/
+    const static char SGR_RED = 2; //31
+    
+    /** SGR colour indicator for ANSI Green.*/
+    const static char SGR_GREEN = 4; //32
+    
+    /** SGR colour indicator for ANSI Yellow.*/
+    const static char SGR_YELLOW = 8; //33
+    
+    /** SGR colour indicator for ANSI Blue.*/
+    const static char SGR_BLUE = 16; //34
+    
+    /** SGR colour indicator for ANSI Magenta.*/
+    const static char SGR_MAGENTA = 32; //35
+    
+    /** SGR colour indicator for ANSI Cyan.*/
+    const static char SGR_CYAN = 64; //36
+    
+    /** SGR colour indicator for ANSI White.*/
+    const static char SGR_WHITE = 128; //37
+    
+    /* Box styles */
+#ifdef _ANSITERM_CP850_
+    /** Box-drawing style using ASCII two-line box-drawing characters. */
+    static const char two_lines[11];
+    
+    /** Box-drawing style using ASCII one-line box-drawing characters. */
+    static const char one_line[11];
+    
+    /** Box-drawing style using pluses, minuses and pipes (low-ASCII, should work anywhere).*/
+    static const char simple[11];
+#endif
+    
+    ANSITerm(PinName tx, PinName rx);
+    
+    /* Emit a Control Sequence Initiator (which is the header for an ANSI escape sequence). */
+    inline void ansi_csi() { this->putc(0x1B); this->putc('['); }
+    /* Cursor Up by n rows. */
+    inline void ansi_cuu(int n) { this->printf("%dA", n); }
+    /* Cursor Down by n rows. */
+    inline void ansi_cud(int n) { this->printf("%dB", n); }
+    /* Cursor Forward by n columns. */
+    inline void ansi_cuf(int n) { this->printf("%dC", n); }
+    /* Cursor Back by n columns.  */
+    inline void ansi_cub(int n) { this->printf("%dD", n); }
+    /* Cursor Next Line (moves the cursor to the start of the line n lines down). */
+    inline void ansi_cnl(int n) { this->printf("%dE", n); }
+    /* Cursor Previous Line (moves the cursor to the start of the line n lines up). */
+    inline void ansi_cpl(int n) { this->printf("%dF", n); }
+    /* Cursor Horizontal Absolute (moves the cursor to column n). */
+    inline void ansi_cha(int n) { this->printf("%dG", n); }
+    /* Cursor Position (positions the cursor at column x, row y, on a 1-based grid starting top-left). */
+    inline void ansi_cup(int x, int y) { this->printf("%d;%dH", y, x); }
+    /* Erase Data (0 = from cursor to end of screen, 1 = from cursor to beginning of screen, 2 = entire screen) */
+    inline void ansi_ed(int n) { this->printf("%dJ", n); }
+    /* Erase in Line (0 = from cursor to end of screen, 1 = from cursor to beginning of screen, 2 = entire screen) */
+    inline void ansi_el(int n) { this->printf("%dK", n); }
+    /* Scroll Up by n lines. */
+    inline void ansi_su(int n) { this->printf("%dS", n); }
+    /* Scroll Down by n lines. */
+    inline void ansi_sd(int n) { this->printf("%dT", n); }
+    /* Horizontal and Vertical Position (positions the cursor at column x, row y, on a 1-based grid starting top-left). */
+    inline void ansi_hvp(int y, int x) { this->printf("%d;%dH", y, x); }
+    /* Save Cursor Position */
+    inline void ansi_scp() { this->putc('s'); }
+    /* Restore Cursor Position */
+    inline void ansi_rcp() { this->putc('u'); }
+    /*DEC Terminal Cursor Enable Mode - hide cursor */
+    inline void ansi_dectcem_hide() { this->printf("?25l"); }
+    /*DEC Terminal Cursor Enable Mode - show cursor */
+    inline void ansi_dectcem_show() { this->printf("?25h"); }
+    
+    /* Select Graphic Rendition - Make the output bold, underlined, coloured... all manner of things.*/
+    /*
+      reset = 1 to reset to defaults.  0 to read and apply the rest of the inputs.
+      text_style is an OR of SGR_{BOLD,FAINT,ITALIC,UNDERLINE,BLINK_SLOW,BLINK_RAPID,IMAGE_NEGATIVE,CROSSED_OUT}
+      text_colour is one of SGR_{BLACK,RED,GREEN,YELLOW,BLUE,MAGENTA,CYAN,WHITE}
+      background_colour is one of SGR_{BLACK,RED,GREEN,YELLOW,BLUE,MAGENTA,CYAN,WHITE}
+     */
+    void ansi_sgr(bool reset, char text_style, char text_colour, char background_colour); 
+    
+    /* Device Status Report (Returns CSIn;mR, where n,m is the coordinates of the cursor). */
+    void ansi_dsr(int* x_coord, int* y_coord); 
+    
+    /** Position the cursor at the requested coordinates, relative to the terminal frame.
+     * Coordinates are calculated from the top left of the frame, using character
+     * cells as the unit, and start at an origin of (1,1).
+     * @param x_coord the x-coordinate (column number) in which to place the cursor, starting at 1.
+     * @param y_coord the y coordinate (row number) in which to place the cursor, starting at 1.
+     */
+    inline void set_cursor_position(int x_coord, int y_coord)
+    {
+      this->ansi_csi();
+      this->ansi_cup(x_coord, y_coord);
+    }
+    
+    /** Get the current position of the cursor, relative to the terminal frame.
+     * Coordinates are calculated from the top left of the frame, using character
+     * cells as the unit, and start at an origin of (1,1).
+     * @param x_coord A pointer into which the current x-coordinate of the cursor should be written.
+     * @param y_coord A pointer into which the current y-coordinate of the cursor should be written.
+     */
+    inline void get_cursor_position(int* x_coord, int* y_coord)
+    {
+      this->ansi_csi();
+      this->ansi_dsr(x_coord, y_coord);
+    }
+    
+    /** Blank all cells on the screen.
+     */
+    inline void clear_screen()
+    {
+      this->ansi_csi();
+      this->ansi_ed(2);
+    }
+    
+    /** Draw a box with these top-left and bottom-right points.  Various styling options exist.
+     * @param x1 The x-coordinate of the top-left point.
+     * @param y1 The y-coordinate of the top-left point.
+     * @param x2 The x-coordinate of the bottom-right point.
+     * @param style The style of box-drawing to use (an 11-cell array of glyphs to use: three sets are defined above).
+     *              The styles are stored as arrays of eleven glyphs, with the following descriptive names: 
+     *              [0]top-left corner, [1]top-right corner, [2]bottom-left corner, [3]bottom-right corner, 
+     *              [4]horizontal bar, [5]vertical bar, 
+     *              [6]upward-pointing tee, [7]downward-pointing tee, [8]left-pointing tee, [9]right-pointing tee, 
+     *              [10]cross
+     * @param clear_inner If true, the space contained within the box will be overwritten with space characters.  If not, it will be unmodified.
+     */
+    void draw_box(int x1, int y1, int x2, int y2, const char* style, bool clear_inner);
+    
+    /** Draw a box containing these top-left and bottom-right points.  Various styling options exist.
+     * @param x1 The x-coordinate of the top-left point.
+     * @param y1 The y-coordinate of the top-left point.
+     * @param x2 The x-coordinate of the bottom-right point.
+     * @param style The style of box-drawing to use (an 11-cell array of glyphs to use: three sets are defined above).
+     *              The styles are stored as arrays of eleven glyphs, with the following descriptive names: 
+     *              [0]top-left corner, [1]top-right corner, [2]bottom-left corner, [3]bottom-right corner, 
+     *              [4]horizontal bar, [5]vertical bar, 
+     *              [6]upward-pointing tee, [7]downward-pointing tee, [8]left-pointing tee, [9]right-pointing tee, 
+     *              [10]cross
+     * @param clear_inner If true, the space contained within the box will be overwritten with space characters.  If not, it will be unmodified.
+     *
+     * draw_enclosing_box differs from draw_box because it draws around a space 
+     * rather than inscribing it.  If draw_box and draw_enclosing_box are given
+     * the same parameters, they will draw concentric boxes and the box from
+     * draw_box will be two cells smaller in both dimensions.
+     */
+    inline void draw_enclosing_box(int x1, int y1, int x2, int y2, const char* style, bool clear_inner)
+    {
+      draw_box((x1-1), (y1-1), (x2+1), (y2+1), style, clear_inner);
+    }
+    
+    /** Set the SGR display style for subsequent characters.
+     * @param style A flagset ORred together from the SGR parameters above.  
+     *              Flags that are set in the flagset will be turned on, 
+     *              flags that are clear will be turned off.
+     *
+     * Example:
+     * @code
+     * terminal.printf("Some text.");
+     * terminal.set_display_style(SGR_BOLD|SGR_UNDERLINE);
+     * terminal.printf("Some very important text!");
+     * terminal.set_display_style(SGR_NONE);
+     * terminal.printf("Some more normal text.");
+     * @endcode
+     */
+    inline void set_display_style(char style)
+    {
+      this->current_style = style;
+      this->ansi_csi();
+      this->ansi_sgr(false, style, 0, 0);
+    }
+    
+    /** Set the colour of subsequent characters.
+     * @param sgr_colour One of the SGR Colours defined above (Black, Red, Green, Yellow, Blue, Magenta, Cyan, White).
+     *
+     * Example:
+     * @code
+     * terminal.printf("Some text in the default terminal colour.");
+     * terminal.set_display_text_colour(SGR_RED);
+     * terminal.printf("Some text in red.);
+     * @endcode
+     */
+    inline void set_text_colour(char sgr_colour)
+    {
+      this->ansi_csi();
+      this->ansi_sgr(false, this->current_style, sgr_colour, 0);
+    }
+    
+    /** Set the background colour for subsequent characters.
+     * @param sgr_colour One of the SGR Colours defined above (Black, Red, Green, Yellow, Blue, Magenta, Cyan, White).
+     * 
+     * Example:
+     * @code
+     * terminal.printf("Some text in the default terminal colour.");
+     * terminal.set_display_background_colour(SGR_RED);
+     * terminal.printf("Some text on a red background.);
+     * @endcode
+     */
+    inline void set_background_colour(char sgr_colour)
+    {
+      this->ansi_csi();
+      this->ansi_sgr(false, this->current_style, 0, sgr_colour);
+    }
+    
+    /** Tell the terminal not to display the cursor.
+     */
+    inline void hide_cursor()
+    {
+      this->ansi_csi();
+      this->ansi_dectcem_hide();
+    }
+    
+    /** Tell the terminal to display the cursor.
+     */
+    inline void show_cursor()
+    {
+      this->ansi_csi();
+      this->ansi_dectcem_show();
+    }
+    
+    /** Reset the display to its default parameters (clearing all text styling and colour settings).
+     */
+    inline void set_display_to_defaults()
+    {
+      this->ansi_csi();
+      this->ansi_sgr(true, 0, 0, 0);
+    }
+    
+};
+
+
+#endif
\ No newline at end of file