home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 5 / DATAFILE_PDCD5.iso / utilities / g / gs / !GS / ps / Source / WimpPlus / c / wimpc next >
Encoding:
Text File  |  1991-11-24  |  8.0 KB  |  300 lines

  1. /* wimpc.c */
  2. /* Wimp interface for command line C programs. */
  3.  
  4. /* Copyright (C) David Elworthy 1991. No warranty is given on this code. */
  5.  
  6. /*
  7.    1.0  --  April 1991  --  First working version
  8.    2.0  --  Nov   1991  --  Don't automatically show windows
  9.  
  10.    If you include this in your build, then printf, and fprintf output can be
  11.    redirected. By default, both stdout and stderr are directed to a wprintf
  12.    window. Using printf_select allows fine tuning of this. You must first
  13.    initialise with wimpc_init.
  14.  
  15.    fread is also redirected. If the file given is stdin, it reads from a wimp
  16.    read window, as many times as the parameter specifies. This only really makes
  17.    sense when reading a string, but we don't actually check to closely.
  18.  
  19.    Similarly, for fwrite, we test for stdout and stderr.
  20.  
  21.    This file must NOT include wimpc.h, otherwise the calls to the
  22.    fread, etc. will NOT work!
  23.  
  24.  */
  25.  
  26.  
  27. #include "wimpt.h"
  28. #include "res.h"
  29. #include "resspr.h"
  30. #include "template.h"
  31. #include "dbox.h"
  32. #include "werr.h"
  33. #include "event.h"
  34. #include "flex.h"
  35. #include "heap.h"
  36.  
  37. #include <stdio.h>
  38. #include <stdarg.h>
  39. #include <string.h>
  40. #include "wimpio.h"
  41.  
  42. #define MAX_LOCAL_BUFFER 4096
  43.  
  44.  
  45. /* Checkpoint - allow tasks and event handlers to have a go. */
  46. void wimpc_checkpoint(void)
  47. {
  48.     if (event_anywindows()) event_process();
  49. }
  50.  
  51.  
  52. /*------------------------------------------------------------------------*/
  53. /* Print and write functions */
  54.  
  55. static int wprintf_window_up = 0; /* 0 = not tried, 1 = ok, -1 = failed */
  56.  
  57. static int catch_stdout      = 1;
  58. static int catch_stderr      = 1;
  59.  
  60.  
  61. /*------------------------------------------------------------------------*/
  62.  
  63. static BOOL printf_check_window(BOOL show)
  64. {
  65.     if (wprintf_window_up == 1) return TRUE;
  66.     else if (wprintf_window_up == -1) return FALSE;
  67.     else
  68.     {
  69.         if (wprintf_create(wimpt_programname(), NULL, 0))
  70.         {
  71.             if (show)
  72.                 wprintf_show();
  73.             wprintf_window_up = 1;
  74.             return TRUE;
  75.         }
  76.         else
  77.         {
  78.             wprintf_window_up = -1;
  79.             return FALSE;
  80.         }
  81.     }
  82. }
  83.  
  84. int w_fprintf(FILE *stream, const char *format, ...)
  85. {
  86.     int  chars_out;
  87.     va_list ap;
  88.  
  89.     va_start(ap,format);
  90.     if ((catch_stdout == 1 && stream == stdout) ||
  91.         (catch_stderr == 1 && stream == stderr))
  92.     {
  93.         if (printf_check_window(FALSE))
  94.         {
  95.             chars_out = wprintf(format, ap);
  96. #if (0)
  97.             wimpc_checkpoint(); /* Allow one event */
  98. #endif
  99.             va_end(ap);
  100.             return chars_out;
  101.         }
  102.     }
  103.     else if (catch_stderr == -1 && stream == stderr)
  104.     {
  105.         char local_buffer[MAX_LOCAL_BUFFER];
  106.         chars_out = vsprintf(local_buffer, format, ap);
  107.         werr(0, local_buffer);
  108.         wimpc_checkpoint(); /* Allow one event */
  109.         va_end(ap);
  110.         return chars_out;
  111.     }
  112.  
  113.     chars_out = vfprintf(stream, format, ap);
  114.     va_end(ap);
  115.     return chars_out;
  116. }
  117.  
  118. int w_printf(const char *format, ...)
  119. {
  120.     int chars_out;
  121.     va_list ap;
  122.  
  123.     va_start(ap,format);
  124.     if (catch_stdout == 1)
  125.     {
  126.         if (printf_check_window(FALSE))
  127.         {
  128.             chars_out = wprintf(format, ap);
  129.             wimpc_checkpoint(); /* Allow one event */
  130.             va_end(ap);
  131.             return chars_out;
  132.         }
  133.     }
  134.  
  135.     chars_out = vfprintf(stdout, format, ap);
  136.     va_end(ap);
  137.     return chars_out;
  138. }
  139.  
  140. /* The code here duplicates some of that in wprintf - we should tidy it up */
  141. size_t w_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
  142. {
  143.     int write_mode = 0; /* 0 = standard, 1 = wprintf, -1 = werr */
  144.     char *rptr;
  145.     int  total_size;
  146.     rptr = (char *)ptr;
  147.  
  148.     /* See how we want to write */
  149.     if ((catch_stdout == 1 && stream == stdout) || (catch_stderr == 1 && stream == stderr))
  150.         write_mode = 1;
  151.     else if (catch_stderr == -1 && stream == stderr)
  152.         write_mode = -1;
  153.     else
  154.         return fwrite(ptr, size, nmemb, stream);
  155.         
  156.     if (write_mode == 1 && !printf_check_window(FALSE))
  157.         return 0;
  158.  
  159.     /* Write in chunks as large as we can */
  160.     for (total_size = size * nmemb ; total_size > 0 ; )
  161.     {
  162.         int to_write = (total_size > MAX_LOCAL_BUFFER-1) ? MAX_LOCAL_BUFFER-1 : total_size;
  163.  
  164.         if (write_mode == 1)
  165.             w_write(rptr, to_write);
  166.         else
  167.             werr(0, rptr);
  168.  
  169.         rptr       += to_write;
  170.         total_size -= to_write;
  171.     }
  172.     wimpc_checkpoint(); /* Allow one event */
  173.     return nmemb;
  174. }
  175.  
  176.  
  177. void printf_select(int w_stdout, /* 1 for window, 0 for real stdout */
  178.                    int w_stderr  /* 1 for window, 0 for real, -1 for werr */)
  179. {
  180.     catch_stdout = w_stdout;
  181.     catch_stderr = w_stderr;
  182. }
  183.  
  184. /*------------------------------------------------------------------------*/
  185. /* Read functions */
  186.  
  187. static int wread_window_up = 0;   /* 0 = not tried, 1 = ok, -1 = failed */
  188.  
  189. /* Local buffer and indexes */
  190. static char w_stdio_buffer[MAX_LOCAL_BUFFER];
  191. static int  w_next = 0; /* index of next char to take */
  192. static int  w_len  = 0; /* length of buffer */
  193.  
  194. /* Fake input to the stdio buffer */
  195. void w_fake_input(char *buffer, int len)
  196. {
  197.     int to_copy = (len+w_len > MAX_LOCAL_BUFFER) ? MAX_LOCAL_BUFFER-w_len-1 : len;
  198.     strncpy(w_stdio_buffer+len+1, buffer, to_copy);
  199.     w_len += len;
  200. }
  201.  
  202. /* Check existence of/create read window */
  203. static BOOL read_check_window(BOOL show)
  204. {
  205.     if (wread_window_up == 1) return TRUE;
  206.     else if (wread_window_up == -1) return FALSE;
  207.     else
  208.     {
  209.         if (wread_create(wimpt_programname(), TRUE))
  210.         {
  211.             if (show) wread_show();
  212.             wread_window_up = 1;
  213.             return TRUE;
  214.         }
  215.         else
  216.         {
  217.             wread_window_up = -1;
  218.             return FALSE;
  219.         }
  220.     }
  221. }
  222.  
  223. /* Simulate fread. When we read from the window, it is possible that the
  224.    previous call did not read the whole buffer, especially on input that
  225.    comes a character at a time. So we must keep a local buffer for this
  226.    case, and read more as needed. A bit wasteful!
  227. */
  228. size_t w_fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
  229. {
  230.     if (stream == stdin)
  231.     {
  232.         int total_size, chunk;
  233.         char *rptr;
  234.         rptr = (char *)ptr;
  235.  
  236.         /* Get as much as you can from the local buffer */
  237.         total_size = size * nmemb;
  238.         if (w_len - w_next > 0)
  239.         {
  240.             chunk = (total_size < w_len - w_next) ? total_size : w_len - w_next;
  241.             memcpy(rptr, w_stdio_buffer + w_next, chunk);
  242.             w_next      += chunk;
  243.             total_size -= chunk;
  244.             rptr       += chunk;
  245.         }
  246.  
  247.         /* Buffer exhausted - see if we need more */
  248.         if (total_size > 0)
  249.         {
  250.             w_len = w_next = 0;
  251.  
  252.             if (!read_check_window(FALSE))
  253.                 return 0;
  254.  
  255.             do
  256.             {
  257.                 w_len = wread(w_stdio_buffer, MAX_LOCAL_BUFFER-1);
  258.                 if (w_len == -1) return 0; /* Error - should really say how much we managed */
  259.  
  260.                 /* Transfer some or all of the result buffer */
  261.                 chunk = (total_size < w_len) ? total_size : w_len;
  262.                 memcpy(rptr, w_stdio_buffer, chunk);
  263.                 total_size -= chunk;
  264.                 rptr       += chunk;
  265.             } while (total_size > 0);
  266.             w_next = chunk;
  267.         }
  268.         return nmemb;
  269.     }
  270.     else
  271.         return fread(ptr, size, nmemb, stream);
  272. }
  273.  
  274.  
  275. /*------------------------------------------------------------------------*/
  276. /* General functions */
  277.  
  278. /* Initialise the wimp. You must call this. */
  279. void wimpc_init(char *taskname, char *resources, int init_heap, int init_flex, int create)
  280. {
  281.   wimpt_init(taskname);     /* Main Wimp initialisation */
  282.   res_init(resources);      /* Resources */
  283.   resspr_init();            /* Application sprites */
  284.   template_init();          /* Templates */
  285.   dbox_init();              /* Dialogue boxes */
  286.  
  287.   if (init_flex || init_heap) flex_init();
  288.   if (init_heap) heap_init(TRUE);
  289.  
  290.   /* Clear drop handler */
  291.   w_register_drop(NULL, NULL, NULL);
  292.  
  293.   /* Force creation (if asked) */
  294.   if (create != WIMPIO_NOCREATE)
  295.   {
  296.       printf_check_window(create == WIMPIO_SHOW);
  297.       read_check_window(create == WIMPIO_SHOW);
  298.   }
  299. }
  300.