Separated library source code from testing code, fixing #6
[rodin/chimara.git] / src / multiwin.c
diff --git a/src/multiwin.c b/src/multiwin.c
deleted file mode 100644 (file)
index 261d7fb..0000000
+++ /dev/null
@@ -1,843 +0,0 @@
-#include "glk.h"
-
-/* multiwin.c: Sample program for Glk API, version 0.5.
-    Designed by Andrew Plotkin <erkyrath@eblong.com>
-    http://www.eblong.com/zarf/glk/index.html
-    This program is in the public domain.
-*/
-
-/* This example demonstrates multiple windows and timed input in the
-    Glk API. */
-
-/* This is the cleanest possible form of a Glk program. It includes only
-    "glk.h", and doesn't call any functions outside Glk at all. We even
-    define our own string functions, rather than relying on the
-    standard libraries. */
-
-/* We also define our own TRUE and FALSE and NULL. */
-#ifndef TRUE
-#define TRUE 1
-#endif
-#ifndef FALSE
-#define FALSE 0
-#endif
-#ifndef NULL
-#define NULL 0
-#endif
-
-/* The story and status windows. */
-static winid_t mainwin1 = NULL;
-static winid_t mainwin2 = NULL;
-static winid_t statuswin = NULL;
-
-/* Key windows don't get stored in a global variable; we'll find them
-    by iterating over the list and looking for this rock value. */
-#define KEYWINROCK (97)
-
-/* For the two main windows, we keep a flag saying whether that window
-    has a line input request pending. (Because if it does, we need to
-    cancel the line input before printing to that window.) */
-static int inputpending1, inputpending2;
-/* When we cancel line input, we should remember how many characters
-    had been typed. This lets us restart the input with those characters
-    already in place. */
-static int already1, already2;
-
-/* There's a three-second timer which can be on or off. */
-static int timer_on = FALSE;
-
-/* Forward declarations */
-void glk_main(void);
-
-static void draw_statuswin(void);
-static void draw_keywins(void);
-static void perform_key(winid_t win, glui32 key);
-static void perform_timer(void);
-
-static int str_eq(char *s1, char *s2);
-static int str_len(char *s1);
-static char *str_cpy(char *s1, char *s2);
-static char *str_cat(char *s1, char *s2);
-static void num_to_str(char *buf, int num);
-
-static void verb_help(winid_t win);
-static void verb_jump(winid_t win);
-static void verb_yada(winid_t win);
-static void verb_both(winid_t win);
-static void verb_clear(winid_t win);
-static void verb_page(winid_t win);
-static void verb_pageboth(winid_t win);
-static void verb_timer(winid_t win);
-static void verb_untimer(winid_t win);
-static void verb_chars(winid_t win);
-static void verb_quit(winid_t win);
-
-/* The glk_main() function is called by the Glk system; it's the main entry
-    point for your program. */
-void glk_main(void)
-{
-    char commandbuf1[256]; /* For mainwin1 */
-    char commandbuf2[256]; /* For mainwin2 */
-
-    /* Open the main windows. */
-    mainwin1 = glk_window_open(0, 0, 0, wintype_TextBuffer, 1);
-    if (!mainwin1) {
-        /* It's possible that the main window failed to open. There's
-            nothing we can do without it, so exit. */
-        return; 
-    }
-    
-    /* Open a second window: a text grid, above the main window, five 
-        lines high. It is possible that this will fail also, but we accept 
-        that. */
-    statuswin = glk_window_open(mainwin1, 
-        winmethod_Above | winmethod_Fixed, 
-        5, wintype_TextGrid, 0);
-        
-    /* And a third window, a second story window below the main one. */
-    mainwin2 = glk_window_open(mainwin1, 
-        winmethod_Below | winmethod_Proportional, 
-        50, wintype_TextBuffer, 0);
-        
-    /* We're going to be switching from one window to another all the
-        time. So we'll be setting the output stream on a case-by-case
-        basis. Every function that prints must set the output stream
-        first. (Contrast model.c, where the output stream is always the
-        main window, and every function that changes that must set it
-        back afterwards.) */
-    
-    glk_set_window(mainwin1);
-    glk_put_string("Multiwin\nAn Interactive Sample Glk Program\n");
-    glk_put_string("By Andrew Plotkin.\nRelease 3.\n");
-    glk_put_string("Type \"help\" for a list of commands.\n");
-    
-    glk_set_window(mainwin2);
-    glk_put_string("Note that the upper left-hand window accepts character");
-    glk_put_string(" input. Hit 'h' to split the window horizontally, 'v' to");
-    glk_put_string(" split the window vertically, 'c' to close a window,");
-    glk_put_string(" and any other key (including special keys) to display");
-    glk_put_string(" key codes. All new windows accept these same keys as");
-    glk_put_string(" well.\n\n");
-    glk_put_string("This bottom window accepts normal line input.\n");
-    
-    if (statuswin) {
-        /* For fun, let's open a fourth window now, splitting the status
-            window. */
-        winid_t keywin;
-        keywin = glk_window_open(statuswin, 
-            winmethod_Left | winmethod_Proportional, 
-            66, wintype_TextGrid, KEYWINROCK);
-        if (keywin) {
-            glk_request_char_event(keywin);
-        }
-    }
-    
-    /* Draw the key window now, since we don't draw it every input (as
-        we do the status window. */
-    draw_keywins();
-
-    inputpending1 = FALSE;
-    inputpending2 = FALSE;
-    already1 = 0;
-    already2 = 0;
-    
-    while (1) {
-        char *cx, *cmd;
-        int doneloop, len;
-        winid_t whichwin;
-        event_t ev;
-        
-        draw_statuswin();
-        /* We're not redrawing the key windows every command. */
-        
-        /* Either main window, or both, could already have line input
-            pending. If so, leave that window alone. If there is no
-            input pending on a window, set a line input request, but
-            keep around any characters that were in the buffer already. */
-        
-        if (mainwin1 && !inputpending1) {
-            glk_set_window(mainwin1);
-            glk_put_string("\n>");
-            /* We request up to 255 characters. The buffer can hold 256, 
-                but we are going to stick a null character at the end, so 
-                we have to leave room for that. Note that the Glk library 
-                does *not* put on that null character. */
-            glk_request_line_event(mainwin1, commandbuf1, 255, already1);
-            inputpending1 = TRUE;
-        }
-        
-        if (mainwin2 && !inputpending2) {
-            glk_set_window(mainwin2);
-            glk_put_string("\n>");
-            /* See above. */
-            glk_request_line_event(mainwin2, commandbuf2, 255, already2);
-            inputpending2 = TRUE;
-        }
-        
-        doneloop = FALSE;
-        while (!doneloop) {
-        
-            /* Grab an event. */
-            glk_select(&ev);
-            
-            switch (ev.type) {
-            
-                case evtype_LineInput:
-                    /* If the event comes from one main window or the other,
-                        we mark that window as no longer having line input
-                        pending. We also set commandbuf to point to the
-                        appropriate buffer. Then we leave the event loop. */
-                    if (mainwin1 && ev.win == mainwin1) {
-                        whichwin = mainwin1;
-                        inputpending1 = FALSE;
-                        cmd = commandbuf1;
-                        doneloop = TRUE;
-                    }
-                    else if (mainwin2 && ev.win == mainwin2) {
-                        whichwin = mainwin2;
-                        inputpending2 = FALSE;
-                        cmd = commandbuf2;
-                        doneloop = TRUE;
-                    }
-                    break;
-                    
-                case evtype_CharInput:
-                    /* It's a key event, from one of the keywins. We
-                        call a subroutine rather than exiting the
-                        event loop (although I could have done it
-                        that way too.) */
-                    perform_key(ev.win, ev.val1);
-                    break;
-                
-                case evtype_Timer:
-                    /* It's a timer event. This does exit from the event
-                        loop, since we're going to interrupt input in
-                        mainwin1 and then re-print the prompt. */
-                    whichwin = NULL;
-                    cmd = NULL; 
-                    doneloop = TRUE;
-                    break;
-                    
-                case evtype_Arrange:
-                    /* Windows have changed size, so we have to redraw the
-                        status window and key window. But we stay in the
-                        event loop. */
-                    draw_statuswin();
-                    draw_keywins();
-                    break;
-            }
-        }
-        
-        if (cmd == NULL) {
-            /* It was a timer event. */
-            perform_timer();
-            continue;
-        }
-        
-        /* It was a line input event. cmd now points at a line of input
-            from one of the main windows. */
-        
-        /* The line we have received in commandbuf is not null-terminated.
-            We handle that first. */
-        len = ev.val1; /* Will be between 0 and 255, inclusive. */
-        cmd[len] = '\0';
-        
-        /* Then squash to lower-case. */
-        for (cx = cmd; *cx; cx++) { 
-            *cx = glk_char_to_lower(*cx);
-        }
-        
-        /* Then trim whitespace before and after. */
-        
-        for (cx = cmd; *cx == ' '; cx++, len--) { };
-        
-        cmd = cx;
-        
-        for (cx = cmd+len-1; cx >= cmd && *cx == ' '; cx--) { };
-        *(cx+1) = '\0';
-        
-        /* cmd now points to a nice null-terminated string. We'll do the
-            simplest possible parsing. */
-        if (str_eq(cmd, "")) {
-            glk_set_window(whichwin);
-            glk_put_string("Excuse me?\n");
-        }
-        else if (str_eq(cmd, "help")) {
-            verb_help(whichwin);
-        }
-        else if (str_eq(cmd, "yada")) {
-            verb_yada(whichwin);
-        }
-        else if (str_eq(cmd, "both")) {
-            verb_both(whichwin);
-        }
-        else if (str_eq(cmd, "clear")) {
-            verb_clear(whichwin);
-        }
-        else if (str_eq(cmd, "page")) {
-            verb_page(whichwin);
-        }
-        else if (str_eq(cmd, "pageboth")) {
-            verb_pageboth(whichwin);
-        }
-        else if (str_eq(cmd, "timer")) {
-            verb_timer(whichwin);
-        }
-        else if (str_eq(cmd, "untimer")) {
-            verb_untimer(whichwin);
-        }
-        else if (str_eq(cmd, "chars")) {
-            verb_chars(whichwin);
-        }
-        else if (str_eq(cmd, "jump")) {
-            verb_jump(whichwin);
-        }
-        else if (str_eq(cmd, "quit")) {
-            verb_quit(whichwin);
-        }
-        else {
-            glk_set_window(whichwin);
-            glk_put_string("I don't understand the command \"");
-            glk_put_string(cmd);
-            glk_put_string("\".\n");
-        }
-        
-        if (whichwin == mainwin1)
-            already1 = 0;
-        else if (whichwin == mainwin2)
-            already2 = 0;
-    }
-}
-
-static void draw_statuswin(void)
-{
-    glui32 width, height;
-    
-    if (!statuswin) {
-        /* It is possible that the window was not successfully 
-            created. If that's the case, don't try to draw it. */
-        return;
-    }
-    
-    glk_set_window(statuswin);
-    glk_window_clear(statuswin);
-    
-    glk_window_get_size(statuswin, &width, &height);
-    
-    /* Draw a decorative compass rose in the center. */
-    width = (width/2);
-    if (width > 0)
-        width--;
-    height = (height/2);
-    if (height > 0)
-        height--;
-        
-    glk_window_move_cursor(statuswin, width, height+0);
-    glk_put_string("\\|/");
-    glk_window_move_cursor(statuswin, width, height+1);
-    glk_put_string("-*-");
-    glk_window_move_cursor(statuswin, width, height+2);
-    glk_put_string("/|\\");
-    
-}
-
-/* This draws some corner decorations in *every* key window -- the
-    one created at startup, and any later ones. It finds them all
-    with glk_window_iterate. */
-static void draw_keywins(void)
-{
-    winid_t win;
-    glui32 rock;
-    glui32 width, height;
-    
-    for (win = glk_window_iterate(NULL, &rock);
-            win;
-            win = glk_window_iterate(win, &rock)) {
-        if (rock == KEYWINROCK) {
-            glk_set_window(win);
-            glk_window_clear(win);
-            glk_window_get_size(win, &width, &height);
-            glk_window_move_cursor(win, 0, 0);
-            glk_put_char('O');
-            glk_window_move_cursor(win, width-1, 0);
-            glk_put_char('O');
-            glk_window_move_cursor(win, 0, height-1);
-            glk_put_char('O');
-            glk_window_move_cursor(win, width-1, height-1);
-            glk_put_char('O');
-        }
-    }
-}
-
-/* React to character input in a key window. */
-static void perform_key(winid_t win, glui32 key)
-{
-    glui32 width, height, len;
-    int ix;
-    char buf[128], keyname[64];
-    
-    if (key == 'h' || key == 'v') {
-        winid_t newwin;
-        glui32 loc;
-        /* Open a new keywindow. */
-        if (key == 'h')
-            loc = winmethod_Right | winmethod_Proportional;
-        else
-            loc = winmethod_Below | winmethod_Proportional;
-        newwin = glk_window_open(win, 
-            loc, 50, wintype_TextGrid, KEYWINROCK);
-        /* Since the new window has rock value KEYWINROCK, the
-            draw_keywins() routine will redraw it. */
-        if (newwin) {
-            /* Request character input. In this program, only keywins
-                get char input, so the CharInput events always call
-                perform_key() -- and so the new window will respond
-                to keys just as this one does. */
-            glk_request_char_event(newwin);
-            /* We now have to redraw the keywins, because any or all of
-                them could have changed size when we opened newwin.
-                glk_window_open() does not generate Arrange events; we
-                have to do the redrawing manually. */
-            draw_keywins();
-        }
-        /* Re-request character input for this window, so that future
-            keys are accepted. */
-        glk_request_char_event(win);
-        return;
-    }
-    else if (key == 'c') {
-        /* Close this keywindow. */
-        glk_window_close(win, NULL);
-        /* Again, any key windows could have changed size. Also the
-            status window could have (if this was the last key window). */
-        draw_keywins();
-        draw_statuswin();
-        return;
-    }
-    
-    /* Print a string naming the key that was just hit. */
-    
-    switch (key) {
-        case ' ':
-            str_cpy(keyname, "space");
-            break;
-        case keycode_Left:
-            str_cpy(keyname, "left");
-            break;
-        case keycode_Right:
-            str_cpy(keyname, "right");
-            break;
-        case keycode_Up:
-            str_cpy(keyname, "up");
-            break;
-        case keycode_Down:
-            str_cpy(keyname, "down");
-            break;
-        case keycode_Return:
-            str_cpy(keyname, "return");
-            break;
-        case keycode_Delete:
-            str_cpy(keyname, "delete");
-            break;
-        case keycode_Escape:
-            str_cpy(keyname, "escape");
-            break;
-        case keycode_Tab:
-            str_cpy(keyname, "tab");
-            break;
-        case keycode_PageUp:
-            str_cpy(keyname, "page up");
-            break;
-        case keycode_PageDown:
-            str_cpy(keyname, "page down");
-            break;
-        case keycode_Home:
-            str_cpy(keyname, "home");
-            break;
-        case keycode_End:
-            str_cpy(keyname, "end");
-            break;
-        default:
-            if (key >= keycode_Func1 && key < keycode_Func12) {
-                str_cpy(keyname, "function key");
-            }
-            else if (key < 32) {
-                str_cpy(keyname, "ctrl-");
-                keyname[5] = '@' + key;
-                keyname[6] = '\0';
-            }
-            else if (key <= 255) {
-                keyname[0] = key;
-                keyname[1] = '\0';
-            }
-            else {
-                str_cpy(keyname, "unknown key");
-            }
-            break;
-    }
-    
-    str_cpy(buf, "Key: ");
-    str_cat(buf, keyname);
-    
-    len = str_len(buf);
-    
-    /* Print the string centered in this window. */
-    glk_set_window(win);
-    glk_window_get_size(win, &width, &height);
-    glk_window_move_cursor(win, 0, height/2);
-    for (ix=0; ix<width; ix++)
-        glk_put_char(' ');
-        
-    width = width/2;
-    len = len/2;
-    
-    if (width > len)
-        width = width-len;
-    else
-        width = 0;
-    
-    glk_window_move_cursor(win, width, height/2);
-    glk_put_string(buf);
-    
-    /* Re-request character input for this window, so that future
-        keys are accepted. */
-    glk_request_char_event(win);
-}
-
-/* React to a timer event. This just prints "Tick" in mainwin1, but it
-    first has to cancel line input if any is pending. */
-static void perform_timer()
-{
-    event_t ev;
-    
-    if (!mainwin1)
-        return;
-    
-    if (inputpending1) {
-        glk_cancel_line_event(mainwin1, &ev);
-        if (ev.type == evtype_LineInput)
-            already1 = ev.val1;
-        inputpending1 = FALSE;
-    }
-
-    glk_set_window(mainwin1);
-    glk_put_string("Tick.\n");
-}
-
-/* This is a utility function. Given a main window, it finds the
-    "other" main window (if both actually exist) and cancels line
-    input in that other window (if input is pending.) It does not
-    set the output stream to point there, however. If there is only
-    one main window, this returns 0. */
-static winid_t print_to_otherwin(winid_t win)
-{
-    winid_t otherwin = NULL;
-    event_t ev;
-
-    if (win == mainwin1) {
-        if (mainwin2) {
-            otherwin = mainwin2;
-            glk_cancel_line_event(mainwin2, &ev);
-            if (ev.type == evtype_LineInput)
-                already2 = ev.val1;
-            inputpending2 = FALSE;
-        }
-    }
-    else if (win == mainwin2) {
-        if (mainwin1) {
-            otherwin = mainwin1;
-            glk_cancel_line_event(mainwin1, &ev);
-            if (ev.type == evtype_LineInput)
-                already1 = ev.val1;
-            inputpending1 = FALSE;
-        }
-    }
-    
-    return otherwin;
-}
-
-static void verb_help(winid_t win)
-{
-    glk_set_window(win);
-    
-    glk_put_string("This model only understands the following commands:\n");
-    glk_put_string("HELP: Display this list.\n");
-    glk_put_string("JUMP: Print a short message.\n");
-    glk_put_string("YADA: Print a long paragraph.\n");
-    glk_put_string("BOTH: Print a short message in both main windows.\n");
-    glk_put_string("CLEAR: Clear one window.\n");
-    glk_put_string("PAGE: Print thirty lines, demonstrating paging.\n");
-    glk_put_string("PAGEBOTH: Print thirty lines in each window.\n");
-    glk_put_string("TIMER: Turn on a timer, which ticks in the upper ");
-    glk_put_string("main window every three seconds.\n");
-    glk_put_string("UNTIMER: Turns off the timer.\n");
-    glk_put_string("CHARS: Prints the entire Latin-1 character set.\n");
-    glk_put_string("QUIT: Quit and exit.\n");
-}
-
-static void verb_jump(winid_t win)
-{
-    glk_set_window(win);
-    
-    glk_put_string("You jump on the fruit, spotlessly.\n");
-}
-
-/* Print some text in both windows. This uses print_to_otherwin() to
-    find the other window and prepare it for printing. */
-static void verb_both(winid_t win)
-{
-    winid_t otherwin;
-    
-    glk_set_window(win);
-    glk_put_string("Something happens in this window.\n");
-    
-    otherwin = print_to_otherwin(win);
-    
-    if (otherwin) {
-        glk_set_window(otherwin);
-        glk_put_string("Something happens in the other window.\n");
-    }
-}
-
-/* Clear a window. */
-static void verb_clear(winid_t win)
-{
-    glk_window_clear(win);
-}
-
-/* Print thirty lines. */
-static void verb_page(winid_t win)
-{
-    int ix;
-    char buf[32];
-    
-    glk_set_window(win);
-    for (ix=0; ix<30; ix++) {
-        num_to_str(buf, ix);
-        glk_put_string(buf);
-        glk_put_char('\n');
-    }
-}
-
-/* Print thirty lines in both windows. This gets fancy by printing
-    to each window alternately, without setting the output stream,
-    by using glk_put_string_stream() instead of glk_put_string(). 
-    There's no particular difference; this is just a demonstration. */
-static void verb_pageboth(winid_t win)
-{
-    int ix;
-    winid_t otherwin;
-    strid_t str, otherstr;
-    char buf[32];
-    
-    str = glk_window_get_stream(win);
-    otherwin = print_to_otherwin(win);
-    if (otherwin) 
-        otherstr = glk_window_get_stream(otherwin);
-    else
-        otherstr = NULL;
-
-    for (ix=0; ix<30; ix++) {
-        num_to_str(buf, ix);
-        str_cat(buf, "\n");
-        glk_put_string_stream(str, buf);
-        if (otherstr)
-            glk_put_string_stream(otherstr, buf);
-    }
-}
-
-/* Turn on the timer. The timer prints a tick in mainwin1 every three
-    seconds. */
-static void verb_timer(winid_t win)
-{
-    glk_set_window(win);
-    
-    if (timer_on) {
-        glk_put_string("The timer is already running.\n");
-        return;
-    }
-    
-    if (glk_gestalt(gestalt_Timer, 0) == 0) {
-        glk_put_string("Your Glk library does not support timer events.\n");
-        return;
-    }
-    
-    glk_put_string("A timer starts running in the upper window.\n");
-    glk_request_timer_events(3000); /* Every three seconds. */
-    timer_on = TRUE;
-}
-
-/* Turn off the timer. */
-static void verb_untimer(winid_t win)
-{
-    glk_set_window(win);
-    
-    if (!timer_on) {
-        glk_put_string("The timer is not currently running.\n");
-        return;
-    }
-    
-    glk_put_string("The timer stops running.\n");
-    glk_request_timer_events(0);
-    timer_on = FALSE;
-}
-
-/* Print every character, or rather try to. */
-static void verb_chars(winid_t win)
-{
-    int ix;
-    char buf[16];
-    
-    glk_set_window(win);
-    
-    for (ix=0; ix<256; ix++) {
-        num_to_str(buf, ix);
-        glk_put_string(buf);
-        glk_put_string(": ");
-        glk_put_char(ix);
-        glk_put_char('\n');
-    }
-}
-
-static void verb_yada(winid_t win)
-{
-    /* This is a goofy (and overly ornate) way to print a long paragraph. 
-        It just shows off line wrapping in the Glk implementation. */
-    #define NUMWORDS (13)
-    static char *wordcaplist[NUMWORDS] = {
-        "Ga", "Bo", "Wa", "Mu", "Bi", "Fo", "Za", "Mo", "Ra", "Po",
-            "Ha", "Ni", "Na"
-    };
-    static char *wordlist[NUMWORDS] = {
-        "figgle", "wob", "shim", "fleb", "moobosh", "fonk", "wabble",
-            "gazoon", "ting", "floo", "zonk", "loof", "lob",
-    };
-    static int wcount1 = 0;
-    static int wcount2 = 0;
-    static int wstep = 1;
-    static int jx = 0;
-    int ix;
-    int first = TRUE;
-    
-    glk_set_window(win);
-    
-    for (ix=0; ix<85; ix++) {
-        if (ix > 0) {
-            glk_put_string(" ");
-        }
-                
-        if (first) {
-            glk_put_string(wordcaplist[(ix / 17) % NUMWORDS]);
-            first = FALSE;
-        }
-        
-        glk_put_string(wordlist[jx]);
-        jx = (jx + wstep) % NUMWORDS;
-        wcount1++;
-        if (wcount1 >= NUMWORDS) {
-            wcount1 = 0;
-            wstep++;
-            wcount2++;
-            if (wcount2 >= NUMWORDS-2) {
-                wcount2 = 0;
-                wstep = 1;
-            }
-        }
-        
-        if ((ix % 17) == 16) {
-            glk_put_string(".");
-            first = TRUE;
-        }
-    }
-    
-    glk_put_char('\n');
-}
-
-static void verb_quit(winid_t win)
-{
-    glk_set_window(win);
-    
-    glk_put_string("Thanks for playing.\n");
-    glk_exit();
-    /* glk_exit() actually stops the process; it does not return. */
-}
-
-/* simple string length test */
-static int str_len(char *s1)
-{
-    int len;
-    for (len = 0; *s1; s1++)
-        len++;
-    return len;
-}
-
-/* simple string comparison test */
-static int str_eq(char *s1, char *s2)
-{
-    for (; *s1 && *s2; s1++, s2++) {
-        if (*s1 != *s2)
-            return FALSE;
-    }
-    
-    if (*s1 || *s2)
-        return FALSE;
-    else
-        return TRUE;
-}
-
-/* simple string copy */
-static char *str_cpy(char *s1, char *s2)
-{
-    char *orig = s1;
-    
-    for (; *s2; s1++, s2++)
-        *s1 = *s2;
-    *s1 = '\0';
-    
-    return orig;
-}
-
-/* simple string concatenate */
-static char *str_cat(char *s1, char *s2)
-{
-    char *orig = s1;
-    
-    while (*s1)
-        s1++;
-    for (; *s2; s1++, s2++)
-        *s1 = *s2;
-    *s1 = '\0';
-    
-    return orig;
-}
-
-/* simple number printer */
-static void num_to_str(char *buf, int num)
-{
-    int ix;
-    int size = 0;
-    char tmpc;
-    
-    if (num == 0) {
-        str_cpy(buf, "0");
-        return;
-    }
-    
-    if (num < 0) {
-        buf[0] = '-';
-        buf++;
-        num = -num;
-    }
-    
-    while (num) {
-        buf[size] = '0' + (num % 10);
-        size++;
-        num /= 10;
-    }
-    for (ix=0; ix<size/2; ix++) {
-        tmpc = buf[ix];
-        buf[ix] = buf[size-ix-1];
-        buf[size-ix-1] = tmpc;
-    }
-    buf[size] = '\0';
-}