diff options
Diffstat (limited to 'libslang/doc/tm/cslang.tm')
-rw-r--r-- | libslang/doc/tm/cslang.tm | 2033 |
1 files changed, 2033 insertions, 0 deletions
diff --git a/libslang/doc/tm/cslang.tm b/libslang/doc/tm/cslang.tm new file mode 100644 index 0000000..acc82c6 --- /dev/null +++ b/libslang/doc/tm/cslang.tm @@ -0,0 +1,2033 @@ +#c -*- mode: tm; mode: fold -*- + +#c text-macro definitions #%{{{ +#i linuxdoc.tm + +#d slang \bf{S-Lang} +#d slrn \bf{slrn} +#d jed \bf{jed} +#d key#1 <tt>$1</tt> +#d footnote#1 <footnote>$1</footnote> +#d grp#1 <tt>$1</tt> +#d file#1 <tt>$1</tt> +#d -1 <tt>-1</tt> +#d 0 <tt>0</tt> +#d 1 <tt>1</tt> + +#d kw#1 \tt{$1} +#d exmp#1 \tt{$1} +#d var#1 \tt{$1} + +#d cfun#1 \tt{$1} +#d ivar#1 \tt{$1} +#d ifun#1 \tt{$1} +#d exfile#1 \tt{$1} +#d exns#1 \tt{$1} +#d exstr#1 \tt{"$1"} + +#d ldots ... +#d times * +#d sc#1 \tt{$1} +#d verb#1 \tt{$1} +#d sldxe \bf{sldxe} +#d url#1 <htmlurl url="$1" name="$1"> +#d slang-library-reference \bf{The \slang Library Reference} +#d chapter#1 <chapt>$1<p> +#d tag#1 <tag>$1</tag> +#d appendix <appendix> + +#d kbd#1 <tt>$1</tt> + +#d documentstyle book + +#%}}} + +\linuxdoc + +\begin{\documentstyle} + +\title S-Lang Library C Programmer's Guide, V1.4.9 +\author John E. Davis, \tt{davis@space.mit.edu} +\date \__today__ + +\toc + +#i preface.tm + +\chapter{Introduction} #%{{{ + + \slang is a C programmer's library that includes routines for the rapid + development of sophisticated, user friendly, multi-platform applications. + The \slang library includes the following: + +\begin{itemize} +\item Low level tty input routines for reading single characters at a time. +\item Keymap routines for defining keys and manipulating multiple keymaps. +\item A high-level keyprocessing interface (\verb{SLkp}) for + handling function and arrow keys. +\item High level screen management routines for manipulating both + monochrome and color terminals. These routines are \em{very} + efficient. (\tt{SLsmg}) +\item Low level terminal-independent routines for manipulating the display + of a terminal. (\tt{SLtt}) +\item Routines for reading single line input with line editing and recall + capabilities. (\tt{SLrline}) +\item Searching functions: both ordinary searches and regular expression + searches. (\tt{SLsearch}) +\item An embedded stack-based language interpreter with a C-like syntax. +\end{itemize} + + The library is currently available for OS/2, MSDOS, Unix, and VMS + systems. For the most part, the interface to library routines has + been implemented in such a way that it appears to be platform + independent from the point of view of the application. In addition, + care has been taken to ensure that the routines are ``independent'' + of one another as much as possible. For example, although the + keymap routines require keyboard input, they are not tied to + \slang's keyboard input routines--- one can use a different keyboard + \verb{getkey} routine if one desires. This also means that linking + to only part of the \slang library does not pull the whole library + into the application. Thus, \slang applications tend to be + relatively small in comparison to programs that use libraries with + similar capabilities. + +#%}}} + +\chapter{Interpreter Interface} #%{{{ + + The \slang library provides an interpreter that when embedded into + an application, makes the application extensible. Examples of + programs that embed the interpreter include the \jed editor and the + \slrn newsreader. + + Embedding the interpreter is easy. The hard part is to decide what + application specific built-in or intrinsic functions should be + provided by the application. The \slang library provides some + pre-defined intrinsic functions, such as string processing + functions, and simple file input-output routines. However, the + basic philosophy behind the interpreter is that it is not a + standalone program and it derives much of its power from the + application that embeds it. + +\sect{Embedding the Interpreter} #%{{{ + + Only one function needs to be called to embed the \slang interpreter + into an application: \cfun{SLang_init_slang}. This function + initializes the interpreter's data structures and adds some intrinsic + functions: +#v+ + if (-1 == SLang_init_slang ()) + exit (EXIT_FAILURE); +#v- + This function does not provide file input output intrinsic nor does + it provide mathematical functions. To make these as well as some + posix system calls available use +#v+ + if ((-1 == SLang_init_slang ()) /* basic interpreter functions */ + || (-1 == SLang_init_slmath ()) /* sin, cos, etc... */ + || (-1 == SLang_init_stdio ()) /* stdio file I/O */ + || (-1 == SLang_init_posix_dir ()) /* mkdir, stat, etc. */ + || (-1 == SLang_init_posix_process ()) /* getpid, umask, etc. */ + ) + exit (EXIT_FAILURE); +#v- + If you intend to enable all intrinsic functions, then it is simpler + to initialize the interpreter via +#v+ + if (-1 == SLang_init_all ()) + exit (EXIT_FAILURE); +#v- + See the \slang-run-time-library for more information about the + intrinsic functions. + + +#%}}} + +\sect{Calling the Interpreter} #%{{{ + + There are several ways of calling the interpreter. The two most common + method is to load a file containing \slang code, or to load a + string. + +\sect1{Loading Files} + The \cfun{SLang_load_file} and \cfun{SLns_load_file} functions may + be used to interpret a file. Both these functions return zero if + successful, or \-1 upon failure. If either of these functions fail, + the interpreter will accept no more code unless the error state is + cleared. This is done by calling \cfun{SLang_restart} function to + set the interpreter to its default state, \em{and} setting + \ivar{SLang_Error} to 0, e.g., +#v+ + if (-1 == SLang_load_file ("site.sl")) + { + /* Clear the error and rest the interpreter */ + SLang_restart (1); + SLang_Error = 0; + } +#v- + + When a file is loaded via \cfun{SLang_load_file}, any non-public + variables and functions defined in the file will be placed into a + namespace that is local to the file itself. The + \cfun{SLns_load_file} function may be used to load a file using a + specified namespace, e.g., +#v+ + if (-1 == SLns_load_file ("site.sl", "NS")) + { + SLang_restart (1); + SLang_Error = 0; + } +#v- + will load \exfile{site.sl} into a namespace called \exns{NS}. If such a + namespace does not exist, then it will be created. + + Both the \cfun{SLang_load_file} and \cfun{SLns_load_file} functions + search for files along an application-specified search path. This + path may be set using the \cfun{SLpath_set_load_path} function, as + well as from interpeted code via the \ifun{set_slang_load_path} + function. By default, no search path is defined. + + Files are searched as follows: If the name begins with the + equivalent of \exstr{./} or \exstr{../}, then it is searched for + with respect to the current directory, and not along the load-path. + If no such file exists, then an error will be generated. Otherwise, + the file is searched for in each of the directories of the load-path + by concatenating the path element with the specified file name. The + first such file found to exist by this process will be loaded. If a + matching file still has not been found, and the file name lacks an + extension, then the path is searched with \exstr{.sl} and + \exstr{.slc} appended to the filename. If two such files are found + (one ending with \exstr{.sl} and the other with \exstr{.slc}), then + the more recent of the two will be used. If no matching file has + been found by this process, then the search will cease and an error + generated. + + The search path is a delimiter separated list of directories that + specify where the interpreter looks for files. By default, the + value of the delimiter is OS-dependent following the convention of + the underlying OS. For example, on Unix the delimiter is + represented by a colon, on DOS/Windows it is a semi-colon, and on + VMS it is a space. The \cfun{SLpath_set_delimiter} and + \cfun{SLpath_get_delimiter} may be used to set and query the + delimiter's value, respectively. + +\sect1{Loading Strings} + There are several other mechanisms for interacting with the + interpreter. For example, the \cfun{SLang_load_string} function + loads a string into the interpreter and interprets it: +#v+ + if (-1 == SLang_load_string ("message (\"hello\");")) + { + SLang_restart (1); + SLang_Error = 0; + } +#v- + Similarly, the \cfun{SLns_load_string} function may be used to load + a string into a specified namespace. + + Typically, an interactive application will load a file via + \cfun{SLang_load_file} and then go into a loop that consists of + reading lines of input and sending them to the interpreter, e.g., +#v+ + while (EOF != fgets (buf, sizeof (buf), stdin)) + { + if (-1 == SLang_load_string (buf)) + SLang_restart (1); + SLang_Error = 0; + } +#v- + + Finally, some applications such as \jed and \slrn use another method of + interacting with the interpreter. They read key sequences from the + keyboard and map those key sequences to interpreter functions via + the \slang keymap interface. + +#%}}} + +\sect{Intrinsic Functions} #%{{{ + + An intrinsic function is simply a function that is written in C and + is made available to the interpreter as a built-in function. For + this reason, the words `intrinsic' and `built-in' are often used + interchangeably. + + Applications are expected to add application specific functions to + the interpreter. For example, \jed adds nearly 300 editor-specific + intrinsic functions. The application designer should think + carefully about what intrinsic functions to add to the interpreter. + +\sect1{Restrictions on Intrinsic Functions} #%{{{ + + When implementing intrinsic functions, it is necessary to follow a + few rules to cooperate with the interpreter. + + The C version of an intrinsic function takes only pointer arguments. + This is because when the interpreter calls an intrinsic function, it + passes values to the function by reference and \em{not} by value. For + example, intrinsic with the declarations: +#v+ + int intrinsic_0 (void); + int intrinsic_1 (char *s); + void intrinsic_2 (char *s, int *i); + void intrinsic_3 (int *i, double *d, double *e); +#v- + are all valid. However, +#v+ + int invalid_1 (char *s, int len); +#v- + is not valid since the \var{len} parameter is not a pointer. + + The return value of an intrinsic function must be one of the + following types: \var{void}, \var{char}, \var{short}, \var{int}, + \var{long}, \var{double}, \var{char *}, as well as unsigned versions + of the integer types. A function such as +#v+ + int *invalid (void); +#v- + is not permitted since \var{int*} is not a valid return-type for an + intrinsic function. Any other type of value can be passed back to + the interpreter by explicitly pushing the object onto the + interpreter's stack via the appropriate "push" function. + + The current implementation limits the number of arguments of an + intrinsic function to \exmp{7}. The "pop" functions can be used to + allow the function to take an arbitrary number as seen from an + interpreter script. + + Another restriction is that the intrinsic function should regard all its + parameters as pointers to constant objects and make no attempt to + modify the value to which they point. For example, +#v+ + void truncate (char *s) + { + s[0] = 0; + } +#v- + is illegal since the function modifies the string \var{s}. + + +#%}}} + +\sect1{Adding a New Intrinsic} #%{{{ + + There are two basic mechanisms for adding an intrinsic function to the + interpreter: \cfun{SLadd_intrinsic_function} and + \cfun{SLadd_intrin_fun_table}. Functions may be added to a specified + namespace via \cfun{SLns_add_intrinsic_function} and + \cfun{SLns_add_intrin_fun_table} functions. + + As an specific example, consider a function that will cause the + program to exit via the \var{exit} C library function. It is not + possible to make this function an intrinsic because it does not meet + the specifications for an intrinsic function that were described + earlier. However, one can call \var{exit} from a function that is + suitable, e.g., +#v+ + void intrin_exit (int *code) + { + exit (*code); + } +#v- + This function may be made available to the interpreter as an + intrinsic via the \cfun{SLadd_intrinsic_function} routine: +#v+ + if (-1 == SLadd_intrinsic_function ("exit", (FVOID_STAR) intrin_exit, + SLANG_VOID_TYPE, 1, + SLANG_INT_TYPE)) + exit (EXIT_FAILURE); +#v- + This statement basically tells the interpreter that + \var{intrin_exit} is a function that returns nothing and takes a + single argument: a pointer to an integer (\var{SLANG_INT_TYPE}). + A user can call this function from within the interpreter + via +#v+ + message ("Calling the exit function"); + exit (0); +#v- + After printing a message, this will cause the \var{intrin_exit} + function to execute, which in turn calls \var{exit}. + + The most convenient mechanism for adding new intrinsic functions is + to create a table of \cfun{SLang_Intrin_Fun_Type} objects and add the + table via the \cfun{SLadd_intrin_fun_table} function. The table will + look like: +#v+ + SLang_Intrin_Fun_Type My_Intrinsics [] = + { + /* table entries */ + MAKE_INTRINSIC_N(...), + MAKE_INTRINSIC_N(...), + . + . + MAKE_INTRINSIC_N(...), + SLANG_END_INTRIN_FUN_TABLE + }; +#v- + Construction of the table entries may be facilitated using a set of + \var{MAKE_INTRINSIC} macros defined in \var{slang.h}. The main + macro is called \var{MAKE_INTRINSIC_N} and takes 11 arguments: +#v+ + MAKE_INTRINSIC_N(name, funct-ptr, return-type, num-args, + arg-1-type, arg-2-type, ... arg-7-type) +#v- + Here \var{name} is the name of the intrinsic function that the + interpreter is to give to the function. \var{func-ptr} is a pointer + to the intrinsic function taking \var{num-args} and returning + \var{ret-type}. The final \exmp{7} arguments specifiy the argument + types. For example, the \var{intrin_exit} intrinsic described above + may be added to the table using +#v+ + MAKE_INTRINSIC_N("exit", intrin_exit, SLANG_VOID_TYPE, 1, + SLANG_INT_TYPE, 0,0,0,0,0,0) +#v- + + While \var{MAKE_INTRINSIC_N} is the main macro for constructing + table entries, \var{slang.h} defines other macros that may prove + useful. In particular, an entry for the \var{intrin_exit} function + may also be created using any of the following forms: +#v+ + MAKE_INTRINSIC_1("exit", intrin_exit, SLANG_VOID_TYPE, SLANG_INT_TYPE) + MAKE_INTRINSIC_I("exit", intrin_exit, SLANG_VOID_TYPE) +#v- + See \var{slang.h} for related macros. You are also encouraged to + look at, e.g., \var{slang/src/slstd.c} for a more extensive examples. + + The table may be added via the \cfun{SLadd_intrin_fun_table} + function, e.g., +#v+ + if (-1 == SLadd_intrin_fun_table (My_Intrinsics, NULL)) + { + /* an error occurred */ + } +#v- + Please note that there is no need to load a given table more than + once, and it is considered to be an error on the part of the + application it adds the same table multiple times. For performance + reasons, no checking is performed by the library to see if a table + has already been added. + + Earlier it was mentioned that intrinsics may be added to a specified + namespace. To this end, one must first get a pointer to the + namespace via the \cfun{SLns_create_namespace} function. The + following example illustrates how this function is used to add the + \var{My_Intrinsics} table to a namespace called \exmp{my}: +#v+ + SLang_NameSpace_Type *ns = SLns_create_namespace ("my"); + if (ns == NULL) + return -1; + + return SLns_add_intrin_fun_table (ns, My_Intrinsics, "__MY__")); +#v- + +#%}}} + +\sect1{More Complicated Intrinsics} #%{{{ + The intrinsic functions described in the previous example were + functions that took a fixed number of arguments. In this section we + explore more complex intrinsics such as those that take a variable + number of arguments. + + Consider a function that takes two double precision numbers and + returns the lesser: +#v+ + double intrin_min (double *a, double *b) + { + if (*a < *b) return *a; + return *b; + } +#v- + This function may be added to a table of intrinsics using +#v+ + MAKE_INTRINSIC_2("vmin", intrin_min, SLANG_DOUBLE_TYPE, + SLANG_DOUBLE_TYPE, SLANG_DOUBLE_TYPE) +#v- + It is useful to extend this function to take an arbitray number of + arguments and return the lesser. Consider the following variant: +#v+ + double intrin_min_n (int *num_ptr) + { + double min_value, x; + unsigned int num = (unsigned int) *num_ptr; + + if (-1 == SLang_pop_double (&min_value, NULL, NULL)) + return 0.0; + num--; + + while (num > 0) + { + num--; + if (-1 == SLang_pop_double (&x, NULL, NULL)) + return 0.0; + if (x < min_value) min_value = x; + } + return min_value; + } +#v- + Here the number to compare is passed to the function and the actual + numbers are removed from the stack via the \cfun{SLang_pop_double} + function. A suitable table entry for it is +#v+ + MAKE_INTRINSIC_I("vmin", intrin_min_n, SLANG_DOUBLE_TYPE) +#v- + This function would be used in an interpreter script via a statement + such as +#v+ + variable xmin = vmin (x0, x1, x2, x3, x4, 5); +#v- + which computes the smallest of \exmp{5} values. + + The problem with this intrinsic function is that the user must + explicitly specify how many numbers to compare. It would be more + convenient to simply use +#v+ + variable xmin = vmin (x0, x1, x2, x3, x4); +#v- + An intrinsic function can query the value of the variable + \var{SLang_Num_Function_Args} to obtain the necessary information: +#v+ + double intrin_min (void) + { + double min_value, x; + + unsigned int num = SLang_Num_Function_Args; + + if (-1 == SLang_pop_double (&min_value, NULL, NULL)) + return 0.0; + num--; + + while (num > 0) + { + num--; + if (-1 == SLang_pop_double (&x, NULL, NULL)) + return 0.0; + if (x < min_value) min_value = x; + } + return min_value; + } +#v- + This may be declared as an intrinsic using: +#v+ + MAKE_INTRINSIC_0("vmin", intrin_min, SLANG_DOUBLE_TYPE) +#v- + + +#%}}} + +#%}}} + +\sect{Intrinsic Variables} #%{{{ + + It is possible to access an application's global variables from + within the interpreter. The current implementation supports the + access of variables of type \var{int}, \var{char *}, and + \var{double}. + + There are two basic methods of making an intrinsic variable + available to the interpreter. The most straight forward method is + to use the function \cfun{SLadd_intrinsic_variable}: +#v+ + int SLadd_intrinsic_variable (char *name, VOID_STAR addr, + unsigned char data_type, + int read_only); +#v- + For example, suppose that \var{I} is an integer variable, e.g., +#v+ + int I; +#v- + One can make it known to the interpreter as \var{I_Variable} via a + statement such as +#v+ + if (-1 == SLadd_intrinsic_variable ("I_Variable", &I, + SLANG_INT_TYPE, 0)) + exit (EXIT_FAILURE); +#v- + Similarly, if \var{S} is declared as +#v+ + char *S; +#v- + then +#v+ + if (-1 == SLadd_intrinsic_variable ("S_Variable", &S, + SLANG_STRING_TYPE, 1)) + exit (EXIT_FAILURE); +#v- + makes \var{S} available as a \em{read-only} variable with the name + \var{S_Variable}. Note that if a pointer variable is made available + to the interpreter, its value is managed by the interpreter and + not the application. For this reason, it is recommended that such + variables be declared as \em{read-only}. + + It is important to note that if \var{S} were declared as an array of + characters, e.g., +#v+ + char S[256]; +#v- + then it would not be possible to make it directly available to the + interpreter. However, one could create a pointer to it, i.e., +#v+ + char *S_Ptr = S; +#v- + and make \var{S_Ptr} available as a read-only variable. + + One should not make the mistake of trying to use the same address + for different variables as the following example illustrates: +#v+ + int do_not_try_this (void) + { + static char *names[3] = {"larry", "curly", "moe"}; + unsigned int i; + + for (i = 0; i < 3; i++) + { + int value; + if (-1 == SLadd_intrinsic_variable (names[i], (VOID_STAR) &value, + SLANG_INT_TYPE, 1)) + return -1; + } + return 0; + } +#v- + Not only does this piece of code create intrinsic variables that use + the same address, it also uses the address of a local variable that + will go out of scope. + + The most convenient method for adding many intrinsic variables to + the interpreter is to create an array of \var{SLang_Intrin_Var_Type} + objects and then add the array via \cfun{SLadd_intrin_var_table}. + For example, the array +#v+ + static SLang_Intrin_Var_Type Intrin_Vars [] = + { + MAKE_VARIABLE("I_Variable", &I, SLANG_INT_TYPE, 0), + MAKE_VARIABLE("S_Variable", &S_Ptr, SLANG_STRING_TYPE, 1), + SLANG_END_TABLE + }; +#v- + may be added via +#v+ + if (-1 == SLadd_intrin_var_table (Intrin_Vars, NULL)) + exit (EXIT_FAILURE); +#v- + It should be rather obvious that the arguments to the + \var{MAKE_VARIABLE} macro correspond to the parameters of the + \cfun{SLadd_intrinsic_variable} function. + + Finally, variables may be added to a specific namespace via the + SLns_add_intrin_var_table and SLns_add_intrinsic_variable functions. + +#%}}} + +\sect{Aggregate Data Objects} #%{{{ + An aggregate data object is an object that can contain more than one + data value. The \slang interpreter supports several such objects: + arrays, structure, and associative arrays. In the following + sections, information about interacting with these objects is given. + +\sect1{Arrays} #%{{{ + An intrinsic function may interact with an array in several different + ways. For example, an intrinsic may create an array and return it. + The basic functions for manipulating arrays include: +#v+ + SLang_create_array + SLang_pop_array_of_type + SLang_push_array + SLang_free_array + SLang_get_array_element + SLang_set_array_element +#v- + The use of these functions will be illustrated via a few simple + examples. + + The first example shows how to create an return an array of strings + to the interpreter. In particular, the names of the four seasons of + the year will be returned: +#v+ + void months_of_the_year (void) + { + static char *seasons[4] = + { + "Spring", "Summer", "Autumn", "Winter" + }; + SLang_Array_Type *at; + int i, four; + + four = 4; + at = SLang_create_array (SLANG_STRING_TYPE, 0, NULL, &four, 1); + if (at == NULL) + return; + + /* Now set the elements of the array */ + for (i = 0; i < 4; i++) + { + if (-1 == SLang_set_array_element (at, &i, &seasons[i])) + { + SLang_free_array (at); + return; + } + } + + (void) SLang_push_array (at, 0); + SLang_free_array (at); + } +#v- + This example illustrates several points. First of all, the + \cfun{SLang_create_array} function was used to create a 1 dimensional + array of 4 strings. Since this function could fail, its return value + was checked. Then the \cfun{SLang_set_array_element} function was + used to set the elements of the newly created array. Note that the + address containing the value of the array element was passed and not + the value of the array element itself. That is, +#v+ + SLang_set_array_element (at, &i, seasons[i]) +#v- + was not used. The return value from this function was also checked + because it too could also fail. Finally, the array was pushed onto + the interpreter's stack and then it was freed. It is important to + understand why it was freed. This is because arrays are + reference-counted. When the array was created, it was returned with + a reference count of \var{1}. When it was pushed, the reference + count was bumped up to \var{2}. Then since it was nolonger needed by + the function, \cfun{SLang_free_array} was called to decrement the + reference count back to \var{1}. For convenience, the second + argument to \cfun{SLang_push_array} determines whether or not it is to + also free the array. So, instead of the two function calls: +#v+ + (void) SLang_push_array (at, 0); + SLang_free_array (at); +#v- + it is preferable to combine them as +#v+ + (void) SLang_push_array (at, 1); +#v- + + The second example returns a diagonal array of a specified size to + the stack. A diagonal array is a 2-d array with all elements zero + except for those along the diagonal, which have a value of one: +#v+ + void make_diagonal_array (int n) + { + SLang_Array_Type *at; + int dims[2]; + int i, one; + + dims[0] = dims[1] = n; + at = SLang_create_array (SLANG_INT_TYPE, 0, NULL, dims, 2); + if (at == NULL) + return; + + one = 1; + for (i = 0; i < n; i++) + { + dims[0] = dims[1] = i; + if (-1 == SLang_set_array_element (at, dims, &one)) + { + SLang_free_array (at); + return; + } + } + + (void) SLang_push_array (at, 1); + } +#v- + In this example, only the diagonal elements of the array were set. + This is bacause when the array was created, all its elements were + set to zero. + + Now consider an example that acts upon an existing array. In + particular, consider one that computes the trace of a 2-d matrix, + i.e., the sum of the diagonal elements: +#v+ + double compute_trace (void) + { + SLang_Array_Type *at; + double trace; + int dims[2]; + + if (-1 == SLang_pop_array_of_type (&at, SLANG_DOUBLE_TYPE)) + return 0.0; + + /* We want a 2-d square matrix. If the matrix is 1-d and has only one + element, then return that element. */ + trace = 0.0; + if (((at->num_dims == 1) && (at->dims[0] == 1)) + || ((at->num_dims == 2) && (at->dims[0] == at->dims[1]))) + { + double dtrace; + int n = at->dims[0]; + + for (i = 0; i < n; i++) + { + dims[0] = dims[1] = i; + (void) SLang_get_array_element (at, &dims, &dtrace); + trace += dtrace; + } + } + else SLang_verror (SL_TYPE_MISMATCH, "Expecting a square matrix"); + + SLang_free_array (at); + return trace; + } +#v- + In this example, \cfun{SLang_pop_array_of_type} was used to pop an + array of doubles from the stack. This function will make implicit + typecasts in order to return an array of the requested type. + +#%}}} + +\sect1{Structures} #%{{{ + + For the purposes of this section, we shall differentiate structures + according to whether or not they correspond to an application defined + C structure. Those that do are called intrinsic structures, and + those do not are called \slang interpreter structures. + +\sect2{Interpreter Structures} + + The following simple example shows one method that may be used to + create and return a structure with a string and integer field to the + interpreter's stack: +#v+ + int push_struct_example (char *string_value, int int_value) + { + char *field_names[2]; + unsigned char field_types[2]; + VOID_STAR field_values[2]; + + field_names[0] = "string_field"; + field_types[0] = SLANG_STRING_TYPE; + field_values[0] = &string_value; + + field_names[1] = "int_field"; + field_types[1] = SLANG_INT_TYPE; + field_values[1] = &int_value; + + if (-1 == SLstruct_create_struct (2, field_names, + field_types, field_values)) + return -1; + return 0; + } +#v- + Here, \cfun{SLstruct_create_struct} is used to push a + structure with the specified field names and values onto the + interpreter's stack. + + A simpler mechanism exists provided that one has already defined a C + structure with a description of how the structure is laid out. For + example, consider a C structure defined by +#v+ + typedef struct + { + char *s; + int i; + } + SI_Type; +#v- + Its layout may be specified via a table of + \var{SLang_CStruct_Field_Type} entries: +#v+ + SLang_CStruct_Field_Type SI_Type_Layout [] = + { + MAKE_CSTRUCT_FIELD(SI_Type, s, "string_field", SLANG_STRING_TYPE, 0), + MAKE_CSTRUCT_FIELD(SI_Type, i, "int_field", SLANG_INT_TYPE, 0), + SLANG_END_CSTRUCT_TABLE + }; +#v- + Here, MAKE_CSTRUCT_FIELD is a macro taking 5 arguments: +#v+ + MAKE_CSTRUCT_FIELD(C-structure-type, + C-field-name, + slang-field-name, + slang-data-type, + is-read-only) +#v- + The first argument is the structure type, the second is the name of + a field of the structure, the third is a string that specifies the + name of the corresponding field of the \slang structure, the fourth + argument specifies the field's type, and the last argument + specifies whether or not the field should be regarded as read-only. + + Once the layout of the structure has been specified, pushing a + \slang version of the structure is trival: +#v+ + int push_struct_example (char *string_value, int int_value) + { + SI_Type si; + + si.s = string_value; + si.i = int_value; + return SLang_push_cstruct ((VOID_STAR)&si, SI_Type_Layout); + } +#v- + + This mechanism of structure creation also permits a \slang + structure to be passed to an intrinsic function through the use of + the SLang_pop_cstruct routine, e.g., +#v+ + void print_si_struct (void) + { + SI_Type si; + if (-1 == SLang_pop_cstruct ((VOID_STAR)&si, SI_Type_Layout)) + return; + printf ("si.i=%d", si.i); + printf ("si.s=%s", si.s); + SLang_free_cstruct ((VOID_STAR)&si, SI_Type_Layout); + } +#v- + Assuming \exmp{print_si_struct} exists as an intrinsic function, + the \slang code +#v+ + variable s = struct {string_field, int_field}; + s.string_field = "hello"; + s.int_field = 20; + print_si_struct (s); +#v- + would result in the display of +#v+ + si.i=20; + si.s=hello +#v- + Note that the \cfun{SLang_free_cstruct} function was called after + the contents of \exmp{si} were nolonger needed. This was necessary + because \cfun{SLang_pop_cstruct} allocated memory to set the + \exmp{char *s} field of \exmp{si}. Calling + \cfun{SLang_free_cstruct} frees up such memory. + + Now consider the following: +#v+ + typedef struct + { + pid_t pid; + gid_t group; + } + X_t; +#v- + How should the layout of this structure be defined? One might be + tempted to use: +#v+ + SLang_CStruct_Field_Type X_t_Layout [] = + { + MAKE_CSTRUCT_FIELD(X_t, pid, "pid", SLANG_INT_TYPE, 0), + MAKE_CSTRUCT_FIELD(X_t, group, "group", SLANG_INT_TYPE, 0), + SLANG_END_CSTRUCT_TABLE + }; +#v- + However, this assumes \exmp{pid_t} and \exmp{gid_t} have been + typedefed as ints. But what if \exmp{gid_t} is a \exmp{short}? In + such a case, using +#v+ + MAKE_CSTRUCT_FIELD(X_t, group, "group", SLANG_SHORT_TYPE, 0), +#v- + would be the appropriate entry for the \exmp{group} field. Of + course, one has no way of knowing how \exmp{gid_t} is declared on + other systems. For this reason, it is preferable to use the + \var{MAKE_CSTRUCT_INT_FIELD} macro in cases involving integer valued + fields, e.g., +#v+ + SLang_CStruct_Field_Type X_t_Layout [] = + { + MAKE_CSTRUCT_INT_FIELD(X_t, pid, "pid", 0), + MAKE_CSTRUCT_INT_FIELD(X_t, group, "group", 0), + SLANG_END_CSTRUCT_TABLE + }; +#v- + + Before leaving this section, it is important to mention that + access to character array fields is not permitted via this + interface. That is, a structure such as +#v+ + typedef struct + { + char name[32]; + } + Name_Type; +#v- + is not supported since \exmp{char name[32]} is not a + \var{SLANG_STRING_TYPE} object. Always keep in mind that a + \var{SLANG_STRING_TYPE} object is a \exmp{char *}. + +\sect2{Intrinsic Structures} + + Here we show how to make intrinsic structures available to + the interpreter. + + The simplest interface is to structure pointers and not + to the actual structures themselves. The latter would require the + interpreter to be involved with the creation and destruction of the + structures. Dealing with the pointers themselves is far simpler. + + As an example, consider an object such as +#v+ + typedef struct _Window_Type + { + char *title; + int row; + int col; + int width; + int height; + } Window_Type; +#v- + which defines a window object with a title, size (\var{width}, + \var{height}), and location (\var{row}, \var{col}). + + We can make variables of type \var{Window_Type} available to the + interpreter via a table as follows: +#v+ + static SLang_IStruct_Field_Type Window_Type_Field_Table [] = + { + MAKE_ISTRUCT_FIELD(Window_Type, title, "title", SLANG_STRING_TYPE, 1), + MAKE_ISTRUCT_FIELD(Window_Type, row, "row", SLANG_INT_TYPE, 0), + MAKE_ISTRUCT_FIELD(Window_Type, col, "col", SLANG_INT_TYPE, 0), + MAKE_ISTRUCT_FIELD(Window_Type, width, "width", SLANG_INT_TYPE, 0), + MAKE_ISTRUCT_FIELD(Window_Type, height, "height", SLANG_INT_TYPE, 0), + SLANG_END_ISTRUCT_TABLE + }; +#v- + More precisely, this defines the layout of the \var{Window_Type} structure. + Here, the \var{title} has been declared as a read-only field. Using +#v+ + MAKE_ISTRUCT_FIELD(Window_Type, title, "title", SLANG_STRING_TYPE, 0), +#v- + would allow read-write access. + + Now suppose that \var{My_Window} is a pointer to a \var{Window_Type} + object, i.e., +#v+ + Window_Type *My_Window; +#v- + We can make this variable available to the interpreter via the + \cfun{SLadd_istruct_table} function: +#v+ + if (-1 == SLadd_istruct_table (Window_Type_Field_Table, + (VOID_STAR) &My_Window, + "My_Win")) + exit (1); +#v- + This creates a S-Lang interpreter variable called \var{My_Win} whose value + corresponds to the \var{My_Win} structure. This would permit one to + access the fields of \var{My_Window} via \slang statements such as +#v+ + define set_width_and_height (w,h) + { + My_Win.width = w; + My_Win.height = h; + } +#v- + + It is extremely important to understand that the interface described in + this section does not allow the interpreter to create new instances of + \var{Window_Type} objects. The interface merely defines an association or + correspondence between an intrinsic structure pointer and a \slang + variable. For example, if the value of \var{My_Window} is \var{NULL}, then + \var{My_Win} would also be \var{NULL}. + + One should be careful in allowing read/write access to character string + fields. If read/write access is allowed, then the application should + always use the \cfun{SLang_create_slstring} and \cfun{SLang_free_slstring} + functions to set the character string field of the structure. + +#%}}} + + +#%}}} + +#%}}} + +\chapter{Keyboard Interface} #%{{{ + +#%{{{ Overview + + \slang's keyboard interface has been designed to allow an + application to read keyboard input from the user in a + system-independent manner. The interface consists of a set of low + routines for reading single character data as well as a higher + level interface (\grp{SLkp}) which utilize \slang's keymap facility + for reading multi-character sequences. + + To initialize the interface, one must first call the function + \verb{SLang_init_tty}. Before exiting the program, the function + \verb{SLang_reset_tty} must be called to restore the keyboard + interface to its original state. Once initialized, the low-level + \verb{SLang_getkey} function may be used to read \em{simgle} + keyboard characters from the terminal. An application using the + higher-level \grp{SLkp} interface will read charcters using the + \verb{SLkp_getkey} function. + + In addition to these basic functions, there are also functions to + ``unget'' keyboard characters, flush the input, detect pending-input + with a timeout, etc. These functions are defined below. + +#%}}} + +\sect{Initializing the Keyboard Interface} #%{{{ + + The function \verb{SLang_init_tty} must be called to initialize the + terminal for single character input. This puts the terminal in a mode + usually referred to as ``raw'' mode. + + The prototype for the function is: +#v+ + int SLang_init_tty (int abort_char, int flow_ctrl, int opost); +#v- + It takes three parameters that are used to specify how the terminal is to + be initialized. +#%+ + Although the \slang keyboard interface has been + %designed to be as system independent as possible, there are semantic + % differences. +#%- + + The first parameter, \verb{abort_char}, is used to specify the interrupt + character (\tt{SIGINT}). Under MSDOS, this value corresponds to the scan + code of the character that will be used to generate the interrupt. For + example, under MSDOS, \verb{34} should be used to make \key{Ctrl-G} generate an + interrupt signal since 34 is the scan code for \key{G}. On other + systems, the value of \verb{abort_char} will simply be the ascii value of + the control character that will be used to generate the interrupt signal, + e.g., \tt{7} for \key{Ctrl-G}. If \verb{-1} is passed, the interrupt + character will not be changed. + + Pressing the interrupt character specified by the first argument will + generate a signal (\tt{SIGINT}) that may or not be caught by the + application. It is up to the application to catch this signal. \slang + provides the function \verb{Slang_set_abort_signal} to make it easy to + facilitate this task. + + The second parameter is used to specify whether or not flow control should + be used. If this parameter is zero, flow control is enabled otherwise + it is disabled. Disabling flow control is necessary to pass certain + characters to the application (e.g., \key{Ctrl-S} and \key{Ctrl-Q}). + For some systems such as MSDOS, this parameter is meaningless. + + The third parameter, \verb{opost}, is used to turn output processing on or + off. If \verb{opost} is zero, output processing is \em{not} turned on + otherwise, output processing is turned on. + + The \verb{SLang_init_tty} function returns -1 upon failure. In addition, + after it returns, the \slang global variable \verb{SLang_TT_Baud_Rate} + will be set to the baud rate of the terminal if this value can be + determined. + + Example: +#v+ + if (-1 == SLang_init_tty (7, 0, 0)) /* For MSDOS, use 34 as scan code */ + { + fprintf (stderr, "Unable to initialize the terminal.\n"); + exit (1); + } + SLang_set_abort_signal (NULL); +#v- + Here the terminal is initialized such that flow control and output + processing are turned off. In addition, the character + \key{Ctrl-G}\footnote{For MSDOS systems, use the \em{scan code} 34 + instead of 7 for \key{Ctrl-G}} has been specified to be the interrupt + character. The function \verb{SLang_set_abort_signal} is used to + install the default \slang interrupt signal handler. + +#%}}} + +\sect{Resetting the Keyboard Interface} #%{{{ + + The function \verb{SLang_reset_tty} must be called to reset the terminal + to the state it was in before the call to \verb{SLang_init_tty}. The + prototype for this function is: +#v+ + void SLang_reset_tty (void); +#v- + Usually this function is only called before the program exits. However, + if the program is suspended it should also be called just before suspension. + +#%}}} + +\sect{Initializing the \grp{SLkp} Routines} #%{{{ + + Extra initialization of the higher-level \grp{SLkp} functions are + required because they are layered on top of the lower level + routines. Since the \verb{SLkp_getkey} function is able to process + function and arrow keys in a terminal independent manner, it is + necessary to call the \verb{SLtt_get_terminfo} function to get + information about the escape character sequences that the terminal's + function keys send. Once that information is available, the + \verb{SLkp_init} function can construct the proper keymaps to + process the escape sequences. + + This part of the initialization process for an application using + this interface will look something like: + +#v+ + SLtt_get_terminfo (); + if (-1 == SLkp_init ()) + { + SLang_doerror ("SLkp_init failed."); + exit (1); + } + if (-1 == SLang_init_tty (-1, 0, 1)) + { + SLang_doerror ("SLang_init_tty failed."); + exit (1); + } +#v- + + It is important to check the return status of the \verb{SLkp_init} + function which can failed if it cannot allocate enough memory for + the keymap. + +#%}}} + +\sect{Setting the Interrupt Handler} #%{{{ + + The function \verb{SLang_set_abort_signal} may be used to associate an + interrupt handler with the interrupt character that was previously + specified by the \verb{SLang_init_tty} function call. The prototype for + this function is: +#v+ + void SLang_set_abort_signal (void (*)(int)); +#v- + This function returns nothing and takes a single parameter which is a + pointer to a function taking an integer value and returning + \verb{void}. If a \verb{NULL} pointer is passed, the default \slang + interrupt handler will be used. The \slang default interrupt handler + under Unix looks like: +#v+ + static void default_sigint (int sig) + { + SLsignal_intr (SIGINT, default_sigint); + SLKeyBoard_Quit = 1; + if (SLang_Ignore_User_Abort == 0) SLang_Error = USER_BREAK; + } +#v- + It simply sets the global variable \verb{SLKeyBoard_Quit} to one and + if the variable \verb{SLang_Ignore_User_Abort} is non-zero, + \verb{SLang_Error} is set to indicate a user break condition. (The + function \verb{SLsignal_intr} is similar to the standard C + \verb{signal} function \em{except that it will interrupt system + calls}. Some may not like this behavior and may wish to call + this \verb{SLang_set_abort_signal} with a different handler.) + + Although the function expressed above is specific to Unix, the + analogous routines for other operating systems are equivalent in + functionality even though the details of the implementation may vary + drastically (e.g., under MSDOS, the hardware keyboard interrupt + \verb{int 9h} is hooked). + +#%}}} + +\sect{Reading Keyboard Input with SLang_getkey} #%{{{ + + After initializing the keyboard via \verb{SLang_init_tty}, + the \slang function \verb{SLang_getkey} may be used to read + characters from the terminal interface. In addition, the function + \verb{SLang_input_pending} may be used to determine whether or not + keyboard input is available to be read. + + These functions have prototypes: +#v+ + unsigned int SLang_getkey (void); + int SLang_input_pending (int tsecs); +#v- + The \verb{SLang_getkey} function returns a single character from the + terminal. Upon failure, it returns \verb{0xFFFF}. If the interrupt + character specified by the \verb{SLang_init_tty} function is pressed + while this function is called, the function will return the value of the + interrupt character and set the \slang global variable + \verb{SLKeyBoard_Quit} to a non-zero value. In addition, if the default + \slang interrupt handler has been specified by a \verb{NULL} argument to + the \verb{SLang_set_abort_signal} function, the global variable + \verb{SLang_Error} will be set to \verb{USER_BREAK} \em{unless} the + variable \verb{SLang_Ignore_User_Abort} is non-zero. + + The \verb{SLang_getkey} function waits until input is available to be + read. The \verb{SLang_input_pending} function may be used to determine + whether or not input is ready. It takes a single parameter that indicates + the amount of time to wait for input before returning with information + regarding the availability of input. This parameter has units of one + tenth (1/10) of a second, i.e., to wait one second, the value of the + parameter should be \tt{10}. Passing a value of zero causes the function + to return right away. \verb{SLang_input_pending} returns a positive + integer if input is available or zero if input is not available. It will + return -1 if an error occurs. + + Here is a simple example that reads keys from the terminal until one + presses \key{Ctrl-G} or until 5 seconds have gone by with no input: +#v+ + #include <stdio.h> + #include "slang.h" + int main () + { + int abort_char = 7; /* For MSDOS, use 34 as scan code */ + unsigned int ch; + + if (-1 == SLang_init_tty (abort_char, 0, 1)) + { + fprintf (stderr, "Unable to initialize the terminal.\n"); + exit (-1); + } + SLang_set_abort_signal (NULL); + while (1) + { + fputs ("\nPress any key. To quit, press Ctrl-G: ", stdout); + fflush (stdout); + if (SLang_input_pending (50) == 0) /* 50/10 seconds */ + { + fputs ("Waited too long! Bye\n", stdout); + break; + } + + ch = SLang_getkey (); + if (SLang_Error == USER_BREAK) + { + fputs ("Ctrl-G pressed! Bye\n", stdout); + break; + } + putc ((int) ch, stdout); + } + SLang_reset_tty (); + return 0; + } +#v- + + +#%}}} + +\sect{Reading Keyboard Input with SLkp_getkey} #%{{{ + + Unlike the low-level function \verb{SLang_getkey}, the + \verb{SLkp_getkey} function can read a multi-character sequence + associated with function keys. The \verb{SLkp_getkey} function uses + \verb{SLang_getkey} and \slang's keymap facility to process escape + sequences. It returns a single integer which describes the key that + was pressed: +#v+ + int SLkp_getkey (void); +#v- + That is, the \verb{SLkp_getkey} function simple provides a mapping + between keys and integers. In this context the integers are called + \em{keysyms}. + + For single character input such as generated by the \key{a} key on + the keyboard, the function returns the character that was generated, + e.g., \verb{'a'}. For single characters, \verb{SLkp_getkey} will + always return an keysym whose value ranges from 0 to 256. For + keys that generate multiple character sequences, e.g., a function or + arrow key, the function returns an keysym whose value is greater + that 256. The actual values of these keysyms are represented as + macros defined in the \file{slang.h} include file. For example, the + up arrow key corresponds to the keysym whose value is + \verb{SL_KEY_UP}. + + Since it is possible for the user to enter a character sequence that + does not correspond to any key. If this happens, the special keysym + \verb{SL_KEY_ERR} will be returned. + + Here is an example of how \verb{SLkp_getkey} may be used by a file + viewer: +#v+ + switch (SLkp_getkey ()) + { + case ' ': + case SL_KEY_NPAGE: + next_page (); + break; + case 'b': + case SL_KEY_PPAGE: + previous_page (); + break; + case '\r': + case SL_KEY_DOWN: + next_line (); + break; + . + . + case SL_KEY_ERR: + default: + SLtt_beep (); + } +#v- + + Unlike its lower-level counterpart, \verb{SLang_getkey}, there do + not yet exist any functions in the library that are capable of + ``ungetting'' keysyms. In particular, the \verb{SLang_ungetkey} + function will not work. + +#%}}} + +\sect{Buffering Input} #%{{{ + + \slang has several functions pushing characters back onto the + input stream to be read again later by \verb{SLang_getkey}. It + should be noted that none of the above functions are designed to + push back keysyms read by the \verb{SLkp_getkey} function. These + functions are declared as follows: +#v+ + void SLang_ungetkey (unsigned char ch); + void SLang_ungetkey_string (unsigned char *buf, int buflen); + void SLang_buffer_keystring (unsigned char *buf, int buflen); +#v- + + \verb{SLang_ungetkey} is the most simple of the three functions. It takes + a single character a pushes it back on to the input stream. The next call to + \verb{SLang_getkey} will return this character. This function may be used + to \em{peek} at the character to be read by first reading it and then + putting it back. + + \verb{SLang_ungetkey_string} has the same function as + \verb{SLang_ungetkey} except that it is able to push more than one + character back onto the input stream. Since this function can push back + null (ascii 0) characters, the number of characters to push is required as + one of the parameters. + + The last of these three functions, \verb{SLang_buffer_keystring} can + handle more than one charater but unlike the other two, it places the + characters at the \em{end} of the keyboard buffer instead of at the + beginning. + + Note that the use of each of these three functions will cause + \verb{SLang_input_pending} to return right away with a non-zero value. + + Finally, the \slang keyboard interface includes the function + \verb{SLang_flush_input} with prototype +#v+ + void SLang_flush_input (void); +#v- + It may be used to discard \em{all} input. + + Here is a simple example that looks to see what the next key to be read is + if one is available: +#v+ + int peek_key () + { + int ch; + if (SLang_input_pending (0) == 0) return -1; + ch = SLang_getkey (); + SLang_ungetkey (ch); + return ch; + } +#v- + + +#%}}} + +\sect{Global Variables} #%{{{ + Although the following \slang global variables have already been + mentioned earlier, they are gathered together here for completeness. + + \verb{int SLang_Ignore_User_Abort;} + If non-zero, pressing the interrupt character will not result in + \verb{SLang_Error} being set to \verb{USER_BREAK}. + + \verb{volatile int SLKeyBoard_Quit;} + This variable is set to a non-zero value when the interrupt + character is pressed. If the interrupt character is pressed when + \verb{SLang_getkey} is called, the interrupt character will be + returned from \verb{SLang_getkey}. + + \verb{int SLang_TT_Baud_Rate;} + On systems which support it, this variable is set to the value of the + terminal's baud rate after the call to \verb{SLang_init_tty}. + +#%}}} + +#%}}} + +\chapter{Screen Management} #%{{{ + + The \slang library provides two interfaces to terminal independent + routines for manipulating the display on a terminal. The highest level + interface, known as the \verb{SLsmg} interface is discussed in this + section. It provides high level screen management functions more + manipulating the display in an optimal manner and is similar in spirit to + the \verb{curses} library. The lowest level interface, or the + \verb{SLtt} + interface, is used by the \verb{SLsmg} routines to actually perform the + task of writing to the display. This interface is discussed in another + section. Like the keyboard routines, the \verb{SLsmg} routines are + \em{platform independent} and work the same on MSDOS, OS/2, Unix, and VMS. + + The screen management, or \verb{SLsmg}, routines are initialized by + function \verb{SLsmg_init_smg}. Once initialized, the application uses + various \verb{SLsmg} functions to write to a \em{virtual} display. This does + not cause the \em{physical} terminal display to be updated immediately. + The physical display is updated to look like the virtual display only + after a call to the function \verb{SLsmg_refresh}. Before exiting, the + application using these routines is required to call + \verb{SLsmg_reset_smg} to reset the display system. + + The following subsections explore \slang's screen management system in + greater detail. + +\sect{Initialization} + + The function \verb{SLsmg_init_smg} must be called before any other + \verb{SLsmg} function can be used. It has the simple prototype: +#v+ + int SLsmg_init_smg (void); +#v- + It returns zero if successful or -1 if it cannot allocate space for + the virtual display. + + For this routine to properly initialize the virtual display, the + capabilities of the terminal must be known as well as the size of + the \em{physical} display. For these reasons, the lower level \verb{SLtt} routines + come into play. In particular, before the first call to + \verb{SLsmg_init_smg}, the application is required to call the function + \verb{SLtt_get_terminfo} before calling \verb{SLsmg_init_smg}. + + The \verb{SLtt_get_terminfo} function sets the global variables + \verb{SLtt_Screen_Rows} and \verb{SLtt_Screen_Cols} to the values + appropriate for the terminal. It does this by calling the + \verb{SLtt_get_screen_size} function to query the terminal driver + for the appropriate values for these variables. From this point on, + it is up to the application to maintain the correct values for these + variables by calling the \verb{SLtt_get_screen_size} function + whenever the display size changes, e.g., in response to a + \verb{SIGWINCH} signal. Finally, if the application is going to read + characters from the keyboard, it is also a good idea to initialize + the keyboard routines at this point as well. + +\sect{Resetting SLsmg} + + Before the program exits or suspends, the function + \verb{SLsmg_reset_tty} + should be called to shutdown the display system. This function has the + prototype +#v+ + void SLsmg_reset_smg (void); +#v- + This will deallocate any memory allocated for the virtual screen and + reset the terminal's display. + + Basically, a program that uses the \verb{SLsmg} screen management functions + and \slang's keyboard interface will look something like: +#v+ + #include "slang.h" + int main () + { + SLtt_get_terminfo (); + SLang_init_tty (-1, 0, 0); + SLsmg_init_smg (); + + /* do stuff .... */ + + SLsmg_reset_smg (); + SLang_reset_tty (); + return 0; + } +#v- + If this program is compiled and run, all it will do is clear the screen + and position the cursor at the bottom of the display. In the following + sections, other \verb{SLsmg} functions will be introduced which may be used + to make this simple program do much more. + +\sect{Handling Screen Resize Events} + The function \verb{SLsmg_reinit_smg} is designed to be used in + conjunction with resize events. + + Under Unix-like operating systems, when the size of the display + changes, the application will be sent a \verb{SIGWINCH} signal. To + properly handle this signal, the \verb{SLsmg} routines must be + reinitialized to use the new display size. This may be accomplished + by calling \verb{SLtt_get_screen_size} to get the new size, followed by + \verb{SLsmg_reinit_smg} to reinitialize the \verb{SLsmg} interface + to use the new size. Keep in mind that these routines should + not be called from within the signal handler. The following code + illustrates the main ideas involved in handling such events: +#v+ + static volatile int Screen_Size_Changed; + static sigwinch_handler (int sig) + { + Screen_Size_Changed = 1; + SLsignal (SIGWINCH, sigwinch_handler); + } + + int main (int argc, char **argv) + { + SLsignal (SIGWINCH, sigwinch_handler); + SLsmg_init_smg (); + . + . + /* Now enter main loop */ + while (not_done) + { + if (Screen_Size_Changed) + { + SLtt_get_screen_size (); + SLsmg_reinit_smg (); + redraw_display (); + } + . + . + } + return 0; + } +#v- + + +\sect{SLsmg Functions} #%{{{ + + In the previous sections, functions for initializing and shutting down the + \verb{SLsmg} routines were discussed. In this section, the rest of the + \verb{SLsmg} functions are presented. These functions act only on the + \em{virtual} display. The \em{physical} display is updated when the + \verb{SLsmg_refresh} function is called and \em{not until that time}. + This function has the simple prototype: +#v+ + void SLsmg_refresh (void); +#v- + +\sect1{Positioning the cursor} + + The \verb{SLsmg_gotorc} function is used to position the cursor at a given + row and column. The prototype for this function is: +#v+ + void SLsmg_gotorc (int row, int col); +#v- + The origin of the screen is at the top left corner and is given the + coordinate (0, 0), i.e., the top row of the screen corresponds to + \verb{row = 0} and the first column corresponds to \verb{col = 0}. The last + row of the screen is given by \verb{row = SLtt_Screen_Rows - 1}. + + It is possible to change the origin of the coordinate system by using the + function \verb{SLsmg_set_screen_start} with prototype: +#v+ + void SLsmg_set_screen_start (int *r, int *c); +#v- + This function takes pointers to the new values of the first row and first + column. It returns the previous values by modifying the values of the + integers at the addresses specified by the parameter list. A + \verb{NULL} + pointer may be passed to indicate that the origin is to be set to its + initial value of 0. For example, +#v+ + int r = 10; + SLsmg_set_screen_start (&r, NULL); +#v- + sets the origin to (10, 0) and after the function returns, the variable + \verb{r} will have the value of the previous row origin. + +\sect1{Writing to the Display} + + \verb{SLsmg} has several routines for outputting text to the virtual + display. The following points should be understood: +\begin{itemize} +\item The text is output at the position of the cursor of the virtual + display and the cursor is advanced to the position that corresponds to + the end of the text. + +\item Text does \em{not} wrap at the boundary of the + display--- it is trucated. This behavior seems to be more useful in + practice since most programs that would use screen management tend to + be line oriented. + +\item Control characters are displayed in a two character sequence + representation with \verb{^} as the first character. That is, + \key{Ctrl-X} is output as \verb{^X}. + +\item The newline character does \em{not} cause the cursor to advance to + the next row. Instead, when a newline character is encountered when + outputting text, the output routine will return. That is, outputting + a string containing a newline character will only display the contents + of the string up to the newline character. +\end{itemize} + + Although the some of the above items might appear to be too restrictive, in + practice this is not seem to be the case. In fact, the design of the + output routines was influenced by their actual use and modified to + simplify the code of the application utilizing them. + + \verb{void SLsmg_write_char (char ch);} + Write a single character to the virtual display. + + \verb{void SLsmg_write_nchars (char *str, int len);} + Write \verb{len} characters pointed to by \verb{str} to the virtual display. + + \verb{void SLsmg_write_string (char *str);} + Write the null terminated string given by pointer \verb{str} to the virtual + display. This function is a wrapper around \verb{SLsmg_write_nchars}. + + \verb{void SLsmg_write_nstring (char *str, int n);} + Write the null terminated string given by pointer \verb{str} to the virtual + display. At most, only \verb{n} characters are written. If the length of + the string is less than \verb{n}, then the string will be padded with blanks. + This function is a wrapper around \verb{SLsmg_write_nchars}. + + \verb{void SLsmg_printf (char *fmt, ...);} + This function is similar to \verb{printf} except that it writes to the + \verb{SLsmg} virtual display. + + \verb{void SLsmg_vprintf (char *, va_list);} + Like \verb{SLsmg_printf} but uses a variable argument list. + +\sect1{Erasing the Display} + + The following functions may be used to fill portions of the display with + blank characters. The attributes of blank character are the current + attributes. (See below for a discussion of character attributes) + + \verb{void SLsmg_erase_eol (void);} + Erase line from current position to the end of the line. + + \verb{void SLsmg_erase_eos (void);} + Erase from the current position to the end of the screen. + + \verb{void SLsmg_cls (void);} + Clear the entire virtual display. + +\sect1{Setting Character Attributes} + + Character attributes define the visual characteristics the character + possesses when it is displayed. Visual characteristics include the + foreground and background colors as well as other attributes such as + blinking, bold, and so on. Since \verb{SLsmg} takes a different approach + to this problem than other screen management libraries an explanation of + this approach is given here. This approach has been motivated by + experience with programs that require some sort of screen management. + + Most programs that use \verb{SLsmg} are composed of specific textual + objects or objects made up of line drawing characters. For example, + consider an application with a menu bar with drop down menus. The menus + might be enclosed by some sort of frame or perhaps a shadow. The basic + idea is to associate an integer to each of the objects (e.g., menu bar, + shadow, current menu item, etc.) and create a mapping from the integer to + the set of attributes. In the terminology of \verb{SLsmg}, the integer is + simply called an \em{object}. + + For example, the menu bar might be associated with the object \verb{1}, the + drop down menu could be object \verb{2}, the shadow could be object + \verb{3}, + and so on. + + The range of values for the object integer is restricted from 0 up to + and including 255 on all systems except MSDOS where the maximum allowed + integer is 15\footnote{This difference is due to memory constraints + imposed by MSDOS. This restriction might be removed in a future version of + the library.}. The object numbered zero should not be regarding as an + object at all. Rather it should be regarded as all \em{other} objects + that have not explicitly been given an object number. \verb{SLsmg}, or + more precisely \verb{SLtt}, refers to the attributes of this special object + as the \em{default} or \em{normal} attributes. + + The \verb{SLsmg} routines know nothing about the mapping of the color to the + attributes associated with the color. The actual mapping takes place at a + lower level in the \verb{SLtt} routines. Hence, to map an object to the + actual set of attributes requires a call to any of the following + \verb{SLtt} + routines: +#v+ + void SLtt_set_color (int obj, char *name, char *fg, char *bg); + void SLtt_set_color_object (int obj, SLtt_Char_Type attr); + void SLtt_set_mono (int obj, char *, SLtt_Char_Type attr); +#v- + Only the first of these routines will be discussed briefly here. The + latter two functions allow more fine control over the object to attribute + mapping (such as assigning a ``blink'' attribute to the object). For a + more full explanation on all of these routines see the section about the + \verb{SLtt} interface. + + The \verb{SLtt_set_color} function takes four parameters. The first + parameter, \verb{obj}, is simply the integer of the object for which + attributes are to be assigned. The second parameter is currently + unused by these routines. The third and forth parameters, \verb{fg} + and \verb{bg}, are the names of the foreground and background color + to be used associated with the object. The strings that one can use + for the third and fourth parameters can be any one of the 16 colors: +#v+ + "black" "gray" + "red" "brightred" + "green" "brightgreen" + "brown" "yellow" + "blue" "brightblue" + "magenta" "brightmagenta" + "cyan" "brightcyan" + "lightgray" "white" +#v- + The value of the foreground parameter \verb{fg} can be anyone of these + sixteen colors. However, on most terminals, the background color will + can only be one of the colors listed in the first column\footnote{This is + also true on the Linux console. However, it need not be the case and + hopefully the designers of Linux will someday remove this restriction.}. + + Of course not all terminals are color terminals. If the \slang global + variable \verb{SLtt_Use_Ansi_Colors} is non-zero, the terminal is + assumed to be a color terminal. The \verb{SLtt_get_terminfo} will + try to determine whether or not the terminal supports colors and set + this variable accordingly. It does this by looking for the + capability in the terminfo/termcap database. Unfortunately many Unix + databases lack this information and so the \verb{SLtt_get_terminfo} + routine will check whether or not the environment variable + \verb{COLORTERM} exists. If it exists, the terminal will be assumed + to support ANSI colors and \verb{SLtt_Use_Ansi_Colors} will be set to one. + Nevertheless, the application should provide some other mechanism to set + this variable, e.g., via a command line parameter. + + When the \verb{SLtt_Use_Ansi_Colors} variable is zero, all objects + with numbers greater than one will be displayed in inverse + video\footnote{This behavior can be modified by using the + \tt{SLtt_set_mono} function call.}. + + With this background, the \verb{SLsmg} functions for setting the character + attributes can now be defined. These functions simply set the object + attributes that are to be assigned to \em{subsequent} characters written + to the virtual display. For this reason, the new attribute is called the + \em{current} attribute. + + \verb{void SLsmg_set_color (int obj);} + Set the current attribute to those of object \verb{obj}. + + \verb{void SLsmg_normal_video (void);} + This function is equivalent to \verb{SLsmg_set_color (0)}. + + \verb{void SLsmg_reverse_video (void);} + This function is equivalent to \verb{SLsmg_set_color (1)}. On monochrome + terminals, it is equivalent to setting the subsequent character attributes + to inverse video. + + Unfortunately there does not seem to be a standard way for the + application or, in particular, the library to determine which color + will be used by the terminal for the default background. Such + information would be useful in initializing the foreground and + background colors associated with the default color object (0). FOr + this reason, it is up to the application to provide some means for + the user to indicate what these colors are for the particular + terminal setup. To facilitate this, the \verb{SLtt_get_terminfo} + function checks for the existence of the \verb{COLORFGBG} + environment variable. If this variable exists, its value will be + used to initialize the colors associated with the default color + object. Specifically, the value is assumed to consist of a + foreground color name and a background color name separated by a + semicolon. For example, if the value of \verb{COLORTERM} is + \verb{lightgray;blue}, the default color object will be initialized + to represent a \verb{lightgray} foreground upon a \verb{blue} + background. + +\sect1{Lines and Alternate Character Sets} + The \slang screen management library also includes routines for turning + on and turning off alternate character sets. This is especially useful + for drawing horizontal and vertical lines. + + \verb{void SLsmg_set_char_set (int flag);} + If \verb{flag} is non-zero, subsequent write functions will use characters + from the alternate character set. If \verb{flag} is zero, the default, or, + ordinary character set will be used. + + \verb{void SLsmg_draw_hline (int len);} + Draw a horizontal line from the current position to the column that is + \verb{len} characters to the right. + + \verb{void SLsmg_draw_vline (int len);} + Draw a horizontal line from the current position to the row that is + \verb{len} rows below. + + \verb{void SLsmg_draw_box (int r, int c, int dr, int dc);} + Draw a box whose upper right corner is at row \verb{r} and column + \verb{c}. + The box spans \verb{dr} rows and \verb{dc} columns. The current position + will be left at row \verb{r} and column \verb{c}. + +\sect1{Miscellaneous Functions} + + \verb{void SLsmg_touch_lines (int r, int n);} + Mark screen rows numbered \verb{r}, \verb{r + 1}, \ldots \verb{r + + (n - 1)} as + modified. When \verb{SLsmg_refresh} is called, these rows will be + completely redrawn. + + \verb{unsigned short SLsmg_char_at(void);} + Returns the character and its attributes object number at the current + cursor position. The character itself occupies the lower byte and the + object attributes number forms the upper byte. The object returned + by this function call should not be written back out via any of the + functions that write characters or character strings. + + +#%}}} + +\sect{Variables} #%{{{ + + The following \slang global variables are used by the \verb{SLsmg} + interface. Some of these have been previously discussed. + + \verb{int SLtt_Screen_Rows;} + \verb{int SLtt_Screen_Cols;} + The number of rows and columns of the \em{physical} display. If either of + these numbers changes, the functions \verb{SLsmg_reset_smg} and + \verb{SLsmg_init_smg} should be called again so that the \verb{SLsmg} + routines can re-adjust to the new size. + + \verb{int SLsmg_Tab_Width;} + Set this variable to the tab width that will be used when expanding tab + characters. The default is 8. + + \verb{int SLsmg_Display_Eight_Bit} + This variable determines how characters with the high bit set are to be + output. Specifically, a character with the high bit set with a value + greater than or equal to this value is output as is; otherwise, it will be + output in a 7-bit representation. The default value for this variable is + \verb{128} for MSDOS and \verb{160} for other systems (ISO-Latin). + + \verb{int SLtt_Use_Ansi_Colors;} + If this value is non-zero, the terminal is assumed to support ANSI colors + otherwise it is assumed to be monochrome. The default is 0. + + \verb{int SLtt_Term_Cannot_Scroll;} + If this value is zero, the \verb{SLsmg} will attempt to scroll the physical + display to optimize the update. If it is non-zero, the screen management + routines will not perform this optimization. For some applications, this + variable should be set to zero. The default value is set by the + \verb{SLtt_get_terminfo} function. + +#%}}} + +\sect{Hints for using SLsmg} + + This section discusses some general design issues that one must face when + writing an application that requires some sort of screen management. + +#%}}} + +\chapter{Signal Functions} #%{{{ + + Almost all non-trivial programs must worry about signals. This is + especially true for programs that use the \slang terminal + input/output and screen management routines. Unfortunately, there is + no fixed way to handle signals; otherwise, the Unix kernel would take + care of all issues regarding signals and the application programmer + would never have to worry about them. For this reason, none of the + routines in the \slang library catch signals; however, some of the + routines block the delivery of signals during crucial moments. It is + up to the application programmer to install handlers for the various + signals of interest. + + For the interpreter, the most important signal to worry about is + \var{SIGINT}. This signal is usually generated when the user presses + \key{Ctrl-C} at the keyboard. The interpreter checks the value of the + \var{SLang_Error} variable to determine whether or not it should abort the + interpreting process and return control back to the application. + This means that if \var{SIGINT} is to be used to abort the interpreter, a + signal handler for \var{SIGINT} should be installed. The handler should + set the value of \var{SLang_Error} to \var{SL_USER_BREAK}. + + Applications that use the \grp{tty} \var{getkey} routines or the screen + management routines must worry about signals such as: +#v+ + SIGINT interrupt + SIGTSTP stop + SIGQUIT quit + SIGTTOU background write + SIGTTIN background read + SIGWINCH window resize +#v- + It is important that handlers be established for these signals while + the either the \var{SLsmg} routines or the \var{getkey} routines are + initialized. The \cfun{SLang_init_tty}, \cfun{SLang_reset_tty}, + \cfun{SLsmg_init_smg}, and \cfun{SLsmg_reset_smg} functions block these + signals from occuring while they are being called. + + Since a signal can be delivered at any time, it is important for the + signal handler to call only functions that can be called from a + signal handler. This usually means that such function must be + re-entrant. In particular, the \var{SLsmg} routines are \em{not} + re-entrant; hence, they should not be called when a signal is being + processed unless the application can ensure that the signal was not + delivered while an \var{SLsmg} function was called. This statement + applies to many other functions such as \var{malloc}, or, more + generally, any function that calls \var{malloc}. The upshot is that + the signal handler should not attempt to do too much except set a + global variable for the application to look at while not in a signal + handler. + + The \slang library provides two functions for blocking and unblocking the + above signals: +#v+ + int SLsig_block_signals (void); + int SLsig_unblock_signals (void); +#v- + It should be noted that for every call to \cfun{SLsig_block_signals}, a + corresponding call should be made to \cfun{SLsig_unblock_signals}, e.g., +#v+ + void update_screen () + { + SLsig_block_signals (); + + /* Call SLsmg functions */ + . + . + SLsig_unblock_signals (); + } +#v- + See \file{demo/pager.c} for examples. + + +#%}}} + +\chapter{Searching Functions} #%{{{ + + The S-Lang library incorporates two types of searches: Regular expression + pattern matching and ordinary searching. + +\sect{Regular Expressions} #%{{{ + + !!! No documentation available yet !!! + +#%}}} + +\sect{Simple Searches} #%{{{ + The routines for ordinary searching are defined in the + \verb{slsearch.c} file. + To use these routines, simply include "slang.h" in your program and simply + call the appropriate routines. + + The searches can go in either a forward or backward direction and can + either be case or case insensitive. The region that is searched may + contain null characters (ASCII 0) however, the search string cannot in the + current implementation. In addition the length of the string to be found + is currently limited to 256 characters. + + Before searching, the function \verb{SLsearch_init} must first be called to + \verb{`preprocess}' the search string. + +#%}}} + +\sect{Initialization} #%{{{ + The function \verb{SLsearch_init} must be called before a search can take place. + Its prototype is: +#v+ + int SLsearch_init (char *key, int dir, int case_sens, SLsearch_Type *st); +#v- + Here \verb{key} is the string to be searched for. \verb{dir} specifies the direction + of the search: a value greater than zero is used for searching forward and + a value less than zero is used for searching backward. The parameter + \verb{case_sens} specifies whether the search is case sensitive or not. A + non-zero value indicates that case is important. \verb{st} is a pointer to a + structure of type \verb{SLsearch_Type} defined in "slang.h". This structure is + initialized by this routine and must be passed to \verb{SLsearch} when the + search is actually performed. + + This routine returns the length of the string to be searched for. + +#%}}} + +\sect{SLsearch} #%{{{ + +#v+ + Prototype: unsigned char *SLsearch (unsigned char *pmin, + unsigned char *pmax, + SLsearch_Type *st); +#v- + + This function performs the search defined by a previous call to + \verb{SLsearch_init} over a region specified by the pointers + \verb{pmin} and \verb{pmax}. + + It returns a pointer to the start of the match if successful or it will + return \verb{NULL} if a match was not found. + + +#%}}} + +#%}}} + +\appendix + +#i copyright.tm + +\end{\documentstyle} |