home *** CD-ROM | disk | FTP | other *** search
- /* wimpc.c */
- /* Wimp interface for command line C programs. */
-
- /* Copyright (C) David Elworthy 1991. No warranty is given on this code. */
-
- /*
- 1.0 -- April 1991 -- First working version
- 2.0 -- Nov 1991 -- Don't automatically show windows
-
- If you include this in your build, then printf, and fprintf output can be
- redirected. By default, both stdout and stderr are directed to a wprintf
- window. Using printf_select allows fine tuning of this. You must first
- initialise with wimpc_init.
-
- fread is also redirected. If the file given is stdin, it reads from a wimp
- read window, as many times as the parameter specifies. This only really makes
- sense when reading a string, but we don't actually check to closely.
-
- Similarly, for fwrite, we test for stdout and stderr.
-
- This file must NOT include wimpc.h, otherwise the calls to the
- fread, etc. will NOT work!
-
- */
-
-
- #include "wimpt.h"
- #include "res.h"
- #include "resspr.h"
- #include "template.h"
- #include "dbox.h"
- #include "werr.h"
- #include "event.h"
- #include "flex.h"
- #include "heap.h"
-
- #include <stdio.h>
- #include <stdarg.h>
- #include <string.h>
- #include "wimpio.h"
-
- #define MAX_LOCAL_BUFFER 4096
-
-
- /* Checkpoint - allow tasks and event handlers to have a go. */
- void wimpc_checkpoint(void)
- {
- if (event_anywindows()) event_process();
- }
-
-
- /*------------------------------------------------------------------------*/
- /* Print and write functions */
-
- static int wprintf_window_up = 0; /* 0 = not tried, 1 = ok, -1 = failed */
-
- static int catch_stdout = 1;
- static int catch_stderr = 1;
-
-
- /*------------------------------------------------------------------------*/
-
- static BOOL printf_check_window(BOOL show)
- {
- if (wprintf_window_up == 1) return TRUE;
- else if (wprintf_window_up == -1) return FALSE;
- else
- {
- if (wprintf_create(wimpt_programname(), NULL, 0))
- {
- if (show)
- wprintf_show();
- wprintf_window_up = 1;
- return TRUE;
- }
- else
- {
- wprintf_window_up = -1;
- return FALSE;
- }
- }
- }
-
- int w_fprintf(FILE *stream, const char *format, ...)
- {
- int chars_out;
- va_list ap;
-
- va_start(ap,format);
- if ((catch_stdout == 1 && stream == stdout) ||
- (catch_stderr == 1 && stream == stderr))
- {
- if (printf_check_window(FALSE))
- {
- chars_out = wprintf(format, ap);
- #if (0)
- wimpc_checkpoint(); /* Allow one event */
- #endif
- va_end(ap);
- return chars_out;
- }
- }
- else if (catch_stderr == -1 && stream == stderr)
- {
- char local_buffer[MAX_LOCAL_BUFFER];
- chars_out = vsprintf(local_buffer, format, ap);
- werr(0, local_buffer);
- wimpc_checkpoint(); /* Allow one event */
- va_end(ap);
- return chars_out;
- }
-
- chars_out = vfprintf(stream, format, ap);
- va_end(ap);
- return chars_out;
- }
-
- int w_printf(const char *format, ...)
- {
- int chars_out;
- va_list ap;
-
- va_start(ap,format);
- if (catch_stdout == 1)
- {
- if (printf_check_window(FALSE))
- {
- chars_out = wprintf(format, ap);
- wimpc_checkpoint(); /* Allow one event */
- va_end(ap);
- return chars_out;
- }
- }
-
- chars_out = vfprintf(stdout, format, ap);
- va_end(ap);
- return chars_out;
- }
-
- /* The code here duplicates some of that in wprintf - we should tidy it up */
- size_t w_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
- {
- int write_mode = 0; /* 0 = standard, 1 = wprintf, -1 = werr */
- char *rptr;
- int total_size;
- rptr = (char *)ptr;
-
- /* See how we want to write */
- if ((catch_stdout == 1 && stream == stdout) || (catch_stderr == 1 && stream == stderr))
- write_mode = 1;
- else if (catch_stderr == -1 && stream == stderr)
- write_mode = -1;
- else
- return fwrite(ptr, size, nmemb, stream);
-
- if (write_mode == 1 && !printf_check_window(FALSE))
- return 0;
-
- /* Write in chunks as large as we can */
- for (total_size = size * nmemb ; total_size > 0 ; )
- {
- int to_write = (total_size > MAX_LOCAL_BUFFER-1) ? MAX_LOCAL_BUFFER-1 : total_size;
-
- if (write_mode == 1)
- w_write(rptr, to_write);
- else
- werr(0, rptr);
-
- rptr += to_write;
- total_size -= to_write;
- }
- wimpc_checkpoint(); /* Allow one event */
- return nmemb;
- }
-
-
- void printf_select(int w_stdout, /* 1 for window, 0 for real stdout */
- int w_stderr /* 1 for window, 0 for real, -1 for werr */)
- {
- catch_stdout = w_stdout;
- catch_stderr = w_stderr;
- }
-
- /*------------------------------------------------------------------------*/
- /* Read functions */
-
- static int wread_window_up = 0; /* 0 = not tried, 1 = ok, -1 = failed */
-
- /* Local buffer and indexes */
- static char w_stdio_buffer[MAX_LOCAL_BUFFER];
- static int w_next = 0; /* index of next char to take */
- static int w_len = 0; /* length of buffer */
-
- /* Fake input to the stdio buffer */
- void w_fake_input(char *buffer, int len)
- {
- int to_copy = (len+w_len > MAX_LOCAL_BUFFER) ? MAX_LOCAL_BUFFER-w_len-1 : len;
- strncpy(w_stdio_buffer+len+1, buffer, to_copy);
- w_len += len;
- }
-
- /* Check existence of/create read window */
- static BOOL read_check_window(BOOL show)
- {
- if (wread_window_up == 1) return TRUE;
- else if (wread_window_up == -1) return FALSE;
- else
- {
- if (wread_create(wimpt_programname(), TRUE))
- {
- if (show) wread_show();
- wread_window_up = 1;
- return TRUE;
- }
- else
- {
- wread_window_up = -1;
- return FALSE;
- }
- }
- }
-
- /* Simulate fread. When we read from the window, it is possible that the
- previous call did not read the whole buffer, especially on input that
- comes a character at a time. So we must keep a local buffer for this
- case, and read more as needed. A bit wasteful!
- */
- size_t w_fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
- {
- if (stream == stdin)
- {
- int total_size, chunk;
- char *rptr;
- rptr = (char *)ptr;
-
- /* Get as much as you can from the local buffer */
- total_size = size * nmemb;
- if (w_len - w_next > 0)
- {
- chunk = (total_size < w_len - w_next) ? total_size : w_len - w_next;
- memcpy(rptr, w_stdio_buffer + w_next, chunk);
- w_next += chunk;
- total_size -= chunk;
- rptr += chunk;
- }
-
- /* Buffer exhausted - see if we need more */
- if (total_size > 0)
- {
- w_len = w_next = 0;
-
- if (!read_check_window(FALSE))
- return 0;
-
- do
- {
- w_len = wread(w_stdio_buffer, MAX_LOCAL_BUFFER-1);
- if (w_len == -1) return 0; /* Error - should really say how much we managed */
-
- /* Transfer some or all of the result buffer */
- chunk = (total_size < w_len) ? total_size : w_len;
- memcpy(rptr, w_stdio_buffer, chunk);
- total_size -= chunk;
- rptr += chunk;
- } while (total_size > 0);
- w_next = chunk;
- }
- return nmemb;
- }
- else
- return fread(ptr, size, nmemb, stream);
- }
-
-
- /*------------------------------------------------------------------------*/
- /* General functions */
-
- /* Initialise the wimp. You must call this. */
- void wimpc_init(char *taskname, char *resources, int init_heap, int init_flex, int create)
- {
- wimpt_init(taskname); /* Main Wimp initialisation */
- res_init(resources); /* Resources */
- resspr_init(); /* Application sprites */
- template_init(); /* Templates */
- dbox_init(); /* Dialogue boxes */
-
- if (init_flex || init_heap) flex_init();
- if (init_heap) heap_init(TRUE);
-
- /* Clear drop handler */
- w_register_drop(NULL, NULL, NULL);
-
- /* Force creation (if asked) */
- if (create != WIMPIO_NOCREATE)
- {
- printf_check_window(create == WIMPIO_SHOW);
- read_check_window(create == WIMPIO_SHOW);
- }
- }
-