home *** CD-ROM | disk | FTP | other *** search
/ PC Shareware 1999 March / PCShareware-3-99.iso / IMPLE / DJGPP.RAR / DJGPP2 / XLIB-SR0.ZIP / SRC / XLIBEMU / CONSOLE.C < prev    next >
C/C++ Source or Header  |  1994-02-20  |  9KB  |  475 lines

  1. /* $Id$ */
  2. /* 
  3.  * console.c 
  4.  *
  5.  * Redirect stdout and stderr into a window.
  6.  * At exit dump the redirected file to "con".
  7.  */
  8. #include <stdio.h>
  9. #include <malloc.h>
  10. #include <stdarg.h>
  11.  
  12. #include <X11/Xlib.h>
  13. #include <X11/Xutil.h>
  14. #include <X11/keysym.h>
  15.  
  16. static char *program = "console";
  17. static Display *dpy = NULL;
  18. static int screen = 0;
  19. static Window win;
  20. static XSizeHints hints;
  21. static GC gc_normal;
  22. static GC gc_cursor;
  23. static int nrows, ncols;
  24. static int row = -1, col = -1;
  25. static XFontStruct *font;
  26. static unsigned int font_width, font_height, font_ascent;
  27. static unsigned int width, height;
  28.  
  29. #define MAX_NCOLS 100
  30. #define MAX_NROWS 40
  31. static char *text;
  32.  
  33. static char *my_stdout_name = NULL;
  34. static FILE *my_stderr = NULL;
  35. static FILE *my_stdout = NULL;
  36. static long my_stderr_pos = 0l;
  37. static long my_stdout_pos = 0l;
  38.  
  39. static char *my_stdin_name = NULL;
  40. static FILE *my_stdin = NULL;
  41. static long my_stdin_pos = 0L;
  42. static char my_stdin_buf[512] = "";
  43.  
  44. static void
  45. Init (int argc, char **argv)
  46. {
  47.   int background, foreground;
  48.   long event_mask;
  49.  
  50.   dpy = XOpenDisplay ("");
  51.   if (dpy == NULL)
  52.     {
  53.       fprintf (stderr, "Cannot open display\n");
  54.       exit (1);
  55.     }
  56.   screen = DefaultScreen (dpy);
  57.  
  58.   font = XLoadQueryFont (dpy, "8x14");
  59.   ncols = 80;
  60.   nrows = 10;
  61.  
  62.   text = (char *) calloc (MAX_NROWS * MAX_NCOLS, 1);
  63.  
  64.   font_width = font->max_bounds.width;
  65.   font_ascent = font->max_bounds.ascent;
  66.   font_height = font->max_bounds.ascent + font->max_bounds.descent;
  67.   width = ncols * font_width;
  68.   height = nrows * font_height;
  69.  
  70.   background = WhitePixel (dpy, screen);
  71.   foreground = BlackPixel (dpy, screen);
  72.  
  73.   hints.flags = 0;
  74.   hints.x = DisplayWidth (dpy, screen) - width - 10;
  75.   hints.y = DisplayHeight (dpy, screen) - height - 10;
  76.   hints.flags |= PPosition;
  77.   hints.width = width;
  78.   hints.height = height;
  79.   hints.flags |= PSize;
  80.   hints.min_width = font_width * 20;
  81.   hints.min_height = font_height * 5;
  82.   hints.flags |= PMinSize;
  83.   hints.max_width = font_width * MAX_NCOLS;
  84.   hints.max_height = font_height * MAX_NROWS;
  85.   hints.flags |= PMaxSize;
  86.   hints.width_inc = font_width;
  87.   hints.height_inc = font_height;
  88.   hints.flags |= PResizeInc;
  89.  
  90.   win = XCreateSimpleWindow (dpy,
  91.                  DefaultRootWindow (dpy),
  92.                  hints.x, hints.y,
  93.                  hints.width, hints.height, 4,
  94.                  foreground, background);
  95.   event_mask = EnterWindowMask 
  96.     |LeaveWindowMask 
  97.     |ButtonPressMask
  98.     |KeyPressMask
  99.     |ExposureMask;
  100.  
  101.   XSelectInput (dpy, win, event_mask);
  102.  
  103.   gc_normal = XCreateGC (dpy, (Drawable) win, 0, 0);
  104.   XSetFont (dpy, gc_normal, font->fid);
  105.   XSetBackground (dpy, gc_normal, background);
  106.   XSetForeground (dpy, gc_normal, foreground);
  107.  
  108.   gc_cursor = XCreateGC (dpy, (Drawable) win, 0, 0);
  109.   XSetFont (dpy, gc_cursor, font->fid);
  110.   XSetBackground (dpy, gc_cursor, foreground);
  111.   XSetForeground (dpy, gc_cursor, background);
  112.  
  113.   XSetStandardProperties (dpy, win,
  114.               program, program,
  115.               None,
  116.               argv, argc, &hints);
  117.   XMapWindow (dpy, win);
  118. }
  119.  
  120. static void
  121. Resize(int new_cols, int new_rows)
  122. {
  123.   int i, nc, nr;
  124.   char *new_text;
  125.  
  126.   if (new_cols == ncols && new_rows == nrows)
  127.     return;
  128.  
  129.   new_text = (char *) calloc (new_cols * new_rows, 1);
  130.   if (new_text == NULL)
  131.     return;
  132.  
  133.   nc = (ncols > new_cols) ? new_cols : ncols;
  134.   nr = (nrows > new_rows) ? new_rows : nrows;
  135.  
  136.   for (i = 0; i < nr; i++)
  137.     {
  138.       memcpy (new_text + (i * new_cols), text + (i * ncols), nc);
  139.     }
  140.   free (text);
  141.   text = new_text;
  142. }
  143.  
  144.  
  145. static void
  146. Redraw()
  147. {
  148.   int i, length, y, x;
  149.   char *p;
  150.   
  151.   y = 0;
  152.   p = text;
  153.   for (i = 0; i < nrows; i++)
  154.     {
  155.       for (length = 0;
  156.        length < ncols && p[length] != 0;
  157.        length++);
  158.       if (length > 0)
  159.     {
  160.       XDrawImageString (dpy, win, gc_normal,
  161.                 0,  y + font_ascent - 1,
  162.                 p, length);
  163.     }
  164.       if (length < ncols) 
  165.     {
  166.       x = length * font_width;
  167.       XClearArea (dpy, win,
  168.               x, y,
  169.               width - x, font_height,
  170.               0);
  171.     }
  172.       y += font_height;
  173.       p += ncols;
  174.     }
  175. }
  176.  
  177. static void 
  178. ScrollUp (int lines)
  179. {
  180.   if (lines < 0)
  181.     return;
  182.  
  183.   if (lines >= nrows) {
  184.     memset (text, 0, ncols * nrows);
  185.     row = 0;
  186.     col = 0;
  187.   }
  188.   else {
  189.     char *src, *dst;
  190.     
  191.     dst = text;
  192.     src = text + ncols * lines;
  193.     memcpy (dst, src, ncols * (nrows - lines));
  194.     dst += ncols * (nrows - lines);
  195.     memset (dst, 0, ncols * lines);
  196.     row -= lines;
  197.   }
  198. }
  199.  
  200. static void
  201. PutChar (char c)
  202. {
  203.   char *p = text + ncols * row + col;
  204.  
  205.   switch (c) {
  206.   case '\n':
  207.     if (col < (ncols - 1)) *p = 0;
  208.     row++;
  209.     if (row >= nrows)
  210.       {
  211.     ScrollUp (nrows / 2);
  212.       }
  213.   case '\r':
  214.     col = 0;
  215.     break;
  216.   case '\t':
  217.     do PutChar (' '); while ((col % 8) != 0);
  218.     break;
  219.   case '\b':
  220.     col--;
  221.     if (col < 0) col = 0;
  222.     break;
  223.   default:
  224.     *p = c;
  225.     col++;
  226.     if (col >= ncols)
  227.       {
  228.     col = 0;
  229.     row ++;
  230.     if (row >= nrows)
  231.       {
  232.         ScrollUp (nrows / 2);
  233.       }
  234.       }
  235.     break;
  236.   }
  237. }
  238.  
  239. static void
  240. PutString (char *string)
  241. {
  242.   char c;
  243.  
  244.   while ((c = *string++) != 0)
  245.     PutChar (c);
  246. }
  247.  
  248. static void
  249. ProcessInput()
  250. {
  251.   int got_something = 0;
  252.   long pos;
  253.   char buf[512];
  254.  
  255.   if (my_stdout) {
  256.     fgetpos (stdout, &pos);
  257.     if (pos > my_stdout_pos) {
  258.       fsetpos (my_stdout, &my_stdout_pos);
  259.       while (fgets (buf, sizeof(buf)-1, my_stdout))
  260.     {
  261.       buf[sizeof(buf)-1] = 0;
  262.       PutString (buf);
  263.       got_something = 1;
  264.     }
  265.       fgetpos (my_stdout, &my_stdout_pos);
  266.       fsetpos (stdout, &pos);
  267.     }
  268.   }
  269.   if (my_stderr) {
  270.     fgetpos (stderr, &pos);
  271.     if (pos > my_stderr_pos) {
  272.       fsetpos (my_stderr, &my_stderr_pos);
  273.       while (fgets (buf, sizeof(buf)-1, my_stderr))
  274.     {
  275.       buf[sizeof(buf)-1] = 0;
  276.       PutString (buf);
  277.       got_something = 1;
  278.     }
  279.       fgetpos (my_stderr, &my_stderr_pos);
  280.       fsetpos (stderr, &pos);
  281.     }
  282.   }
  283.   if (got_something)
  284.     Redraw ();
  285. }
  286.  
  287. static void
  288. ProcessOutput(char *string)
  289. {
  290.   long pos;
  291.  
  292.   if (my_stdin) {
  293.     fgetpos (stdin, &pos);
  294.     fsetpos (my_stdin, &my_stdin_pos);
  295.     fputs (string, my_stdin);
  296.  
  297.     if (strchr (string, '\n'))
  298.       fflush (my_stdin);
  299.  
  300.     fgetpos (my_stdin, &my_stdin_pos);
  301.     fsetpos (stdin, &pos);
  302.   }
  303. }
  304.  
  305.  
  306. static void
  307. ProcessEvent()
  308. {
  309.   char text[10];
  310.   KeySym keysym;
  311.   XComposeStatus cs;
  312.   int i, n, count;
  313.   XEvent ev;
  314.  
  315.   XNextEvent (dpy, &ev);
  316.     
  317.   switch (ev.type) {
  318.   case KeyPress:
  319.     count = XLookupString (&ev.xkey, text, 10, &keysym, &cs);
  320.     text[count] = 0;
  321.     if (count == 1) {
  322.       if (text[0] == '\r')
  323.     text[0] = '\n';
  324.     }
  325.     else switch (keysym) {
  326.     case XK_Return:
  327.     case XK_Linefeed:
  328.       text[0] = '\n';
  329.       text[1] = 0;
  330.       break;
  331.     case XK_Tab:
  332.       text[0] = '\t';
  333.       text[1] = 0;
  334.       break;
  335.     case XK_BackSpace:
  336.       text[0] = '\b';
  337.       text[1] = 0;
  338.       break;
  339.     case XK_Delete:
  340.       break;
  341.     case XK_Left:
  342.       break;
  343.     case XK_Right:
  344.       break;
  345.     case XK_Down:
  346.       break;
  347.     case XK_Up:
  348.       break;
  349.     }
  350.     if (text[0]) {
  351.       PutString (text);
  352.       Redraw ();
  353.       strcat (my_stdin_buf, text);
  354.       if (strchr (text, '\n')) {
  355.     ProcessOutput (my_stdin_buf);
  356.     my_stdin_buf[0] = 0;
  357.       }
  358.     }
  359.     break;
  360.   case Expose:
  361.     if (ev.xexpose.count == 0)
  362.       Redraw ();
  363.     break;
  364.   case ConfigureNotify:
  365.     width = ev.xconfigure.width;
  366.     height = ev.xconfigure.height;
  367.     Resize (width / font_width, height / font_height);
  368.     break;
  369.   }
  370. }
  371.  
  372. static void
  373. Cleanup ()
  374. {
  375.   if (my_stderr) fclose (my_stderr);
  376.   if (my_stdout) fclose (my_stdout);
  377.   if (my_stdout_name)
  378.     unlink (my_stdout_name);
  379.  
  380.   if (my_stdin) fclose (my_stdin);
  381.   if (my_stdin_name)
  382.     unlink (my_stdin_name);
  383. }
  384.  
  385. static void
  386. Redirect ()
  387. {
  388.   if (isatty (fileno(stdout)))
  389.     {
  390.       my_stdout_name = tempnam ("c:/", "cout");
  391.  
  392.       (void) freopen (my_stdout_name, "wb", stdout);
  393.       (void) freopen (my_stdout_name, "wb", stderr);
  394.     }
  395.   my_stdout = fdopen (fileno(stdout), "r");
  396.   my_stderr = fdopen (fileno(stderr), "r");
  397.  
  398.   if (isatty (fileno(stdin)))
  399.     {
  400.       my_stdin_name = tempnam ("c:/", "cinp");
  401.       (void) freopen (my_stdin_name, "rb", stdin);
  402.  
  403.       my_stdin = fdopen (fileno(stdin), "wb");
  404.     }
  405.  
  406.   atexit (Cleanup);
  407. }
  408.  
  409.  
  410. static int
  411. main_console (int argc, char *argv[])
  412. {
  413.   if (dpy == NULL)
  414.     {
  415.       Init (argc, argv);
  416.       Redirect ();
  417.     }
  418.   ProcessInput ();
  419.   while (XPending (dpy)) ProcessEvent();
  420.   return 1;
  421. }
  422.  
  423. console()
  424. {
  425.   int argc;
  426.   char *argv[2];
  427.   argc = 1;
  428.   argv[0] = "console";
  429.   argv[1] = NULL;
  430.  
  431.   return main_console(argc, argv);
  432. }
  433.  
  434. #ifdef TEST
  435. int
  436. main(int argc, char **argv)
  437. {
  438.   FILE *fp;
  439.   char buf[512];
  440.  
  441.   fvwm();
  442.   console();
  443.  
  444.   while (argc > 1)
  445.     {
  446.       argc --;
  447.       argv ++;
  448.       fp = fopen (*argv, "r");
  449.       if (fp == NULL) continue;
  450.  
  451.       while (fgets (buf, sizeof(buf)-1, fp))
  452.     {
  453.       buf[sizeof(buf)-1] = 0;
  454.       fputs (buf, stdout);
  455.     }
  456.       fclose (fp);
  457.  
  458.       fvwm();
  459.       console();
  460.     }
  461.  
  462.   while (1)
  463.     {
  464.       fvwm();
  465.       console();
  466.       while (fgets (buf, sizeof(buf)-1, stdin))
  467.     {
  468.       buf[sizeof(buf)-1] = 0;
  469.       fputs (buf, stdout);
  470.     }
  471.     }
  472.   return 0;
  473. }
  474. #endif
  475.