Section 24.2. Output Handling


24.2. Output Handling

Internally, S-Lang's terminal output functions are divided into two sets: terminal-handling functions (the SLtt family) and higher-level screen management functions (the SLsmg family).

The SLtt function family works directly with the terminal; it includes functions that map closely with capabilities defined in the terminal database. It also includes routines for defining foreground and background color pairs and turning the cursor on and off. Only a few of these functions are normally used by application programmers; the rest are called internally by S-Lang.

The SLsmg family provides a higher-level abstraction of the display terminal. Although these functions use the SLtt functions for terminal handling, they provide a much more powerful interface for application developers.

These functions include string output, line drawing, and screen-querying functions. For performance reasons, these routines write to an internal buffer rather than directly to the terminal. When the application instructs S-Lang to update the physical terminal, S-Lang compares the new display to the original one and optimizes the output sequence appropriately.

24.2.1. Initializing Screen Management

Before using S-Lang's terminal output functions, a program must tell SLang to look up the current terminal (as determined by the TERM environment variable) in the terminal database. This is done by calling

 void SLtt_get_terminfo(void); 

One of the primary functions of SLtt_get_terminfo() is to set the physical size of the screen to the size listed in the terminal database. The number of rows and columns on the terminal are stored in SLtt_Screen_Rows and SLtt_Screen_Cols, respectively. Although the terminal database is often correct, resizeable terminals (such as xterms) are popular these days, and once they are resized from the defaults, the terminal database no longer contains the correct size for the terminal. To compensate for this, S-Lang allows programs to reset the values of SLtt_Screen_Rows and SLtt_Screen_Cols after the call to SLtt_get_terminfo(). Under Linux, the current terminal size is always available through the TIOCGWINSZ ioctl, which is discussed in detail on page 376.

Initializing the S-Lang's screen management layer is straightforward:

 void SLsmg_init_smg(void); SLsmg_init_smg() 

24.2.2. Updating the Display

Before the results of a sequence of SLsmg routines gets reflected on the physical terminal, you must call the SLsmg_refresh() function. This function does not take any arguments or return a value, but it does update the physical terminal with the results of any screen drawing that has been done since the previous time it was called.

24.2.3. Moving the Cursor

As in most programs, the terminal cursor is used by S-Lang as both the default location for text output and a cue for the user. S-Lang programs can move the cursor with the following code:

 extern void SLsmg_gotorc (int row, int column); 

Note that the upper-left corner of the screen is (0, 0) and the bottom-right corner is (SLtt_Screen_Rows - 1, SLtt_Screen_Cols - 1).

24.2.4. Finishing Screen Management

When a program that uses SLsmg has finished, it needs to tell S-Lang it is done, allowing S-Lang to free buffers and restore the terminal state. Before doing this, it is a good idea to move the cursor to the bottom of the screen and refresh the display to make sure all output has been shown to the user.

24.2.5. Skeleton Screen Management

Here is a program that initializes S-Lang's screen management abilities and then closes them. Although it certainly does not do much, it does illustrate the basics of using S-Lang's SLsmg functionality.

  1: /* slinit.c */  2:  3: #include <slang/slang.h>  4: #include <stdio.h>  5: #include <sys/ioctl.h>  6: #include <termios.h>  7:  8: int main(void) {  9:     struct winsize ws; 10: 11:     /* get the size of the terminal connected to stdout */ 12:     if (ioctl(1, TIOCGWINSZ, &ws)) { 13:         perror("failed to get window size"); 14:         return 1; 15:     } 16: 17:     SLtt_get_terminfo(); 18: 19:     SLtt_Screen_Rows = ws.ws_row; 20:     SLtt_Screen_Cols = ws.ws_col; 21: 22:     SLsmg_init_smg(); 23: 24:     /* heart of the program goes here */ 25: 26:     SLsmg_gotorc(SLtt_Screen_Rows - 1, 0); 27:     SLsmg_refresh(); 28:     SLsmg_reset_smg(); 29:     SLang_reset_tty(); 30: 31:     return 0; 32: } 

24.2.6. Switching Character Sets

Most modern terminals (including the VT100, which the Linux console closely emulates) support at least two character sets. The primary one is usually ISO-8859-1 or something similar; the second is used primarily for line-drawing characters. S-Lang allows you to choose which character set is used for drawing characters.

 void SLsmg_set_char_set(int useAlternate) 

When SLsmg_set_char_set() is called with a nonzero argument, new characters written to the display are mapped through the alternate character set. Calling SLsmg_set_char_set() with zero as its parameter disables this mapping, allowing characters to appear normally.

S-Lang defines a set of symbolic names for the commonly used line-drawing characters contained in the alternate character set. Table 24.1 shows the available line-drawing characters and S-Lang's name for each.

Table 24.1. Line Characters


Symbolic Constant












24.2.7. Writing to the Screen

Although there are a number of ways to write strings to the screen under S-Lang, they all look about the same. Here is the entire set of functions:

 void SLsmg_write_char(char ch); void SLsmg_write_string(char * str); void SLsmg_write_nchars(char * chars, int length); void SLsmg_write_nstring(char * str, int length); void SLsmg_printf(char * format, ...); void SLsmg_vprintf(char * format, va_list args); void SLsmg_write_wrapped_string(char * str, int row, int column,                                 int height, int width, int fill); 

All of these functions, except SLsmg_write_wrapped_string(), write the requested string into the screen buffer[4] at the current cursor location using the current color and character set. They all have different ways of deciding what string to write, however. After the information has been written, the cursor is advanced to the end of the area affected, just as on a normal terminal. Any strings that extend past the right side of the screen are truncated rather than wrapped. Although this is different from normal terminal output, it is reasonable for most full-screen applications, in which wrapped text has an adverse effect on the screen's layout.

[4] Remember, the physical terminal is updated only by SLsmg_refresh().


Of all the screen output functions, this one is the simplest. It writes the character passed to the current cursor position and advances the cursor.


The string that is passed to the function is written to the screen.


The length characters pointed to by chars are written to the screen. NULL termination is ignored a '\0' is written if one is found, and the routine continues past the end of the string.


At most length characters from str are written to the screen. If str is shorter than length characters, the remainder of the space is filled with blank characters.


As the name implies, this routine acts like the standard printf() function, formatting the first argument, with the remainder of the arguments used as parameters for the formatting. The formatted string is then written to the screen.


Like the C library's vfprintf() function, this routine expects a va_arg argument, which it uses to format the first parameter. The formatted string is then displayed.


Although S-Lang truncates strings rather than wrap them, it does provide a simple function for writing strings wrapped to an arbitrary rectangle on the screen. SLsmg_write_wrapped_string() writes str to the rectangle that begins at row and column of size height and width.

Although this routine does wrap on word boundaries, a \n in the string forces it to go to the next line. If final parameter fill is nonzero, every line is filled to the full width of the rectangle, with spaces used for padding where necessary.

24.2.8. Drawing Lines and Boxes

Although SLsmg_set_char_set() provides all the functionality needed to draw simple line graphics on a terminal, S-Lang provides some shortcut functions that are easier to use.

 void SLsmg_draw_hline(int row); void SLsmg_draw_vline(int column); void SLsmg_draw_box(int row, int column, int height, int width); 

The SLsmg_draw_hline() function draws a single horizontal line at row row; SLsmg_draw_vline() draws a single vertical line at column col.

SLsmg_draw_box() draws a box starting at row and col that extends for height rows and width columns. SLsmg_draw_box() is similar to a combination of SLsmg_draw_hline() and SLsmg_draw_vline(), but it gets the corners right, as well.

Here is an example program that draws a screen containing the normal character set and the alternate character set. It also demonstrates a simple use of SLsmg_draw_box().

  1: /* slcharset.c */  2:  3: #include <slang/slang.h>  4: #include <stdio.h>  5: #include <sys/ioctl.h>  6: #include <termios.h>  7:  8: /* displays a table containing 256 characters in a single character  9:    set, starting a column col. The 'label' is displayed over the 10:    table, and the alternate character set is displayed iff 11:    isAlternate is nonzero */ 12: static void drawCharSet(int col, int isAlternate, char * label) { 13:     int i, j; 14:     int n = 0; 15: 16:     /* draw the box */ 17:     SLsmg_draw_box(0, col, 20, 38); 18: 19:     /* center the label */ 20:     SLsmg_gotorc(0, col + 2); 21:     SLsmg_write_string(label); 22: 23: 24:     /* draw the horizontal legend */ 25:     SLsmg_gotorc(2, col + 4); 26:     SLsmg_write_string("0 1 2 3 4 5 6 7 8 9 A B C D E F"); 27: 28:     /* set the character set to use */ 29:     SLsmg_set_char_set(isAlternate); 30: 31:     /* this iterates over the 4 most significant bits */ 32:     for (i = 0; i < 16; i++) { 33:         SLsmg_gotorc(3 + i, 2 + col); 34:         SLsmg_write_char(i < 10 ? i + '0': (i - 10) + 'A'); 35: 36:         /* this iterates over the 4 least significant bits */ 37:         for (j = 0; j < 16; j++) { 38:             SLsmg_gotorc(3 + i, col + 4 + (j * 2)); 39:             SLsmg_write_char(n++); 40:         } 41:     } 42: 43:     SLsmg_set_char_set(0); 44: } 45: 46: int main(void) { 47:     struct winsize ws; 48: 49:     /* get the size of the terminal connected to stdout */ 50:     if (ioctl(1, TIOCGWINSZ, &ws)) { 51:         perror("failed to get window size"); 52:         return 1; 53:     } 54: 55:     SLtt_get_terminfo(); 56: 57:     SLtt_Screen_Rows = ws.ws_row; 58:     SLtt_Screen_Cols = ws.ws_col; 59: 60:     SLsmg_init_smg(); 61:     SLang_init_tty(-1, 0, 1); 62: 63:     drawCharSet(0, 0, "Normal Character Set"); 64:     drawCharSet(40, 1, "Alternate Character Set"); 65: 66:     SLsmg_refresh(); 67:     SLang_getkey(); 68: 69:     SLsmg_gotorc(SLtt_Screen_Rows - 1, 0); 70:     SLsmg_refresh(); 71:     SLsmg_reset_smg(); 72:     SLang_reset_tty(); 73: 74:     return 0; 75: } 

24.2.9. Using Color

S-Lang makes it easy to add color to an application. It allows the user to use a palette of 256 entries[5], each defining a foreground and a background color. Most applications use a palette entry for one type of rendered object, such as window frame or listbox entry. A palette's colors are set through SLtt_set_color().

[5] This number could be increased in the future, but it is doubtful such a change will ever be necessary.

 void SLtt_set_color(int entry, char * name, char * fg, char * bg); 

The first parameter specifies the palette entry being modified. The name parameter is currently ignored and should be passed as NULL. The final two entries name the new foreground and background colors for that palette entry. Table 24.2 lists the colors S-Lang supports; the fg and bg should both be strings containing the name of the color to use. All the colors on the left side of the table may be used for the foreground or background color. However, the colors on the right side must be used only for foreground colors. Using them for background colors would give unpredictable results.[6]

[6] Results might include blinking text on some systems.

Table 24.2. S-Lang Colors

Foreground or Background


















Writes to the screen are done using the current palette entry, which is set by the SLsmg_set_color() function.

 void SLsmg_set_color(int entry); 

This sets the current palette entry to the specified entry. The colors specified by this entry are used for future screen writes.

Although an application may use the color-related functions on any terminal type, a number of factors control whether colors are displayed. The SLtt_Use_Ansi_Colors global variable controls whether colors are displayed. If it is set to zero, no colors are used. Any other value allows colors to be displayed.

SLtt_get_terminfo() tries to guess whether color should be enabled on the current terminal. Unfortunately, many termcap and terminfo databases are incomplete in this regard. If the COLORTERM environment variable is set, S-Lang sets SLtt_Use_Ansi_Colors no matter what the terminal database indicates.

Most applications that provide color support also provide a command-line option to allow users to selectively enable color support. When the option is used, the application explicitly sets SLtt_Use_Ansi_Colors.


    Linux Application Development
    Linux Application Development (paperback) (2nd Edition)
    ISBN: 0321563220
    EAN: 2147483647
    Year: 2003
    Pages: 168 © 2008-2017.
    If you may any questions please contact us: