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 >
Wrap
C/C++ Source or Header
|
1994-02-20
|
9KB
|
475 lines
/* $Id$ */
/*
* console.c
*
* Redirect stdout and stderr into a window.
* At exit dump the redirected file to "con".
*/
#include <stdio.h>
#include <malloc.h>
#include <stdarg.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
static char *program = "console";
static Display *dpy = NULL;
static int screen = 0;
static Window win;
static XSizeHints hints;
static GC gc_normal;
static GC gc_cursor;
static int nrows, ncols;
static int row = -1, col = -1;
static XFontStruct *font;
static unsigned int font_width, font_height, font_ascent;
static unsigned int width, height;
#define MAX_NCOLS 100
#define MAX_NROWS 40
static char *text;
static char *my_stdout_name = NULL;
static FILE *my_stderr = NULL;
static FILE *my_stdout = NULL;
static long my_stderr_pos = 0l;
static long my_stdout_pos = 0l;
static char *my_stdin_name = NULL;
static FILE *my_stdin = NULL;
static long my_stdin_pos = 0L;
static char my_stdin_buf[512] = "";
static void
Init (int argc, char **argv)
{
int background, foreground;
long event_mask;
dpy = XOpenDisplay ("");
if (dpy == NULL)
{
fprintf (stderr, "Cannot open display\n");
exit (1);
}
screen = DefaultScreen (dpy);
font = XLoadQueryFont (dpy, "8x14");
ncols = 80;
nrows = 10;
text = (char *) calloc (MAX_NROWS * MAX_NCOLS, 1);
font_width = font->max_bounds.width;
font_ascent = font->max_bounds.ascent;
font_height = font->max_bounds.ascent + font->max_bounds.descent;
width = ncols * font_width;
height = nrows * font_height;
background = WhitePixel (dpy, screen);
foreground = BlackPixel (dpy, screen);
hints.flags = 0;
hints.x = DisplayWidth (dpy, screen) - width - 10;
hints.y = DisplayHeight (dpy, screen) - height - 10;
hints.flags |= PPosition;
hints.width = width;
hints.height = height;
hints.flags |= PSize;
hints.min_width = font_width * 20;
hints.min_height = font_height * 5;
hints.flags |= PMinSize;
hints.max_width = font_width * MAX_NCOLS;
hints.max_height = font_height * MAX_NROWS;
hints.flags |= PMaxSize;
hints.width_inc = font_width;
hints.height_inc = font_height;
hints.flags |= PResizeInc;
win = XCreateSimpleWindow (dpy,
DefaultRootWindow (dpy),
hints.x, hints.y,
hints.width, hints.height, 4,
foreground, background);
event_mask = EnterWindowMask
|LeaveWindowMask
|ButtonPressMask
|KeyPressMask
|ExposureMask;
XSelectInput (dpy, win, event_mask);
gc_normal = XCreateGC (dpy, (Drawable) win, 0, 0);
XSetFont (dpy, gc_normal, font->fid);
XSetBackground (dpy, gc_normal, background);
XSetForeground (dpy, gc_normal, foreground);
gc_cursor = XCreateGC (dpy, (Drawable) win, 0, 0);
XSetFont (dpy, gc_cursor, font->fid);
XSetBackground (dpy, gc_cursor, foreground);
XSetForeground (dpy, gc_cursor, background);
XSetStandardProperties (dpy, win,
program, program,
None,
argv, argc, &hints);
XMapWindow (dpy, win);
}
static void
Resize(int new_cols, int new_rows)
{
int i, nc, nr;
char *new_text;
if (new_cols == ncols && new_rows == nrows)
return;
new_text = (char *) calloc (new_cols * new_rows, 1);
if (new_text == NULL)
return;
nc = (ncols > new_cols) ? new_cols : ncols;
nr = (nrows > new_rows) ? new_rows : nrows;
for (i = 0; i < nr; i++)
{
memcpy (new_text + (i * new_cols), text + (i * ncols), nc);
}
free (text);
text = new_text;
}
static void
Redraw()
{
int i, length, y, x;
char *p;
y = 0;
p = text;
for (i = 0; i < nrows; i++)
{
for (length = 0;
length < ncols && p[length] != 0;
length++);
if (length > 0)
{
XDrawImageString (dpy, win, gc_normal,
0, y + font_ascent - 1,
p, length);
}
if (length < ncols)
{
x = length * font_width;
XClearArea (dpy, win,
x, y,
width - x, font_height,
0);
}
y += font_height;
p += ncols;
}
}
static void
ScrollUp (int lines)
{
if (lines < 0)
return;
if (lines >= nrows) {
memset (text, 0, ncols * nrows);
row = 0;
col = 0;
}
else {
char *src, *dst;
dst = text;
src = text + ncols * lines;
memcpy (dst, src, ncols * (nrows - lines));
dst += ncols * (nrows - lines);
memset (dst, 0, ncols * lines);
row -= lines;
}
}
static void
PutChar (char c)
{
char *p = text + ncols * row + col;
switch (c) {
case '\n':
if (col < (ncols - 1)) *p = 0;
row++;
if (row >= nrows)
{
ScrollUp (nrows / 2);
}
case '\r':
col = 0;
break;
case '\t':
do PutChar (' '); while ((col % 8) != 0);
break;
case '\b':
col--;
if (col < 0) col = 0;
break;
default:
*p = c;
col++;
if (col >= ncols)
{
col = 0;
row ++;
if (row >= nrows)
{
ScrollUp (nrows / 2);
}
}
break;
}
}
static void
PutString (char *string)
{
char c;
while ((c = *string++) != 0)
PutChar (c);
}
static void
ProcessInput()
{
int got_something = 0;
long pos;
char buf[512];
if (my_stdout) {
fgetpos (stdout, &pos);
if (pos > my_stdout_pos) {
fsetpos (my_stdout, &my_stdout_pos);
while (fgets (buf, sizeof(buf)-1, my_stdout))
{
buf[sizeof(buf)-1] = 0;
PutString (buf);
got_something = 1;
}
fgetpos (my_stdout, &my_stdout_pos);
fsetpos (stdout, &pos);
}
}
if (my_stderr) {
fgetpos (stderr, &pos);
if (pos > my_stderr_pos) {
fsetpos (my_stderr, &my_stderr_pos);
while (fgets (buf, sizeof(buf)-1, my_stderr))
{
buf[sizeof(buf)-1] = 0;
PutString (buf);
got_something = 1;
}
fgetpos (my_stderr, &my_stderr_pos);
fsetpos (stderr, &pos);
}
}
if (got_something)
Redraw ();
}
static void
ProcessOutput(char *string)
{
long pos;
if (my_stdin) {
fgetpos (stdin, &pos);
fsetpos (my_stdin, &my_stdin_pos);
fputs (string, my_stdin);
if (strchr (string, '\n'))
fflush (my_stdin);
fgetpos (my_stdin, &my_stdin_pos);
fsetpos (stdin, &pos);
}
}
static void
ProcessEvent()
{
char text[10];
KeySym keysym;
XComposeStatus cs;
int i, n, count;
XEvent ev;
XNextEvent (dpy, &ev);
switch (ev.type) {
case KeyPress:
count = XLookupString (&ev.xkey, text, 10, &keysym, &cs);
text[count] = 0;
if (count == 1) {
if (text[0] == '\r')
text[0] = '\n';
}
else switch (keysym) {
case XK_Return:
case XK_Linefeed:
text[0] = '\n';
text[1] = 0;
break;
case XK_Tab:
text[0] = '\t';
text[1] = 0;
break;
case XK_BackSpace:
text[0] = '\b';
text[1] = 0;
break;
case XK_Delete:
break;
case XK_Left:
break;
case XK_Right:
break;
case XK_Down:
break;
case XK_Up:
break;
}
if (text[0]) {
PutString (text);
Redraw ();
strcat (my_stdin_buf, text);
if (strchr (text, '\n')) {
ProcessOutput (my_stdin_buf);
my_stdin_buf[0] = 0;
}
}
break;
case Expose:
if (ev.xexpose.count == 0)
Redraw ();
break;
case ConfigureNotify:
width = ev.xconfigure.width;
height = ev.xconfigure.height;
Resize (width / font_width, height / font_height);
break;
}
}
static void
Cleanup ()
{
if (my_stderr) fclose (my_stderr);
if (my_stdout) fclose (my_stdout);
if (my_stdout_name)
unlink (my_stdout_name);
if (my_stdin) fclose (my_stdin);
if (my_stdin_name)
unlink (my_stdin_name);
}
static void
Redirect ()
{
if (isatty (fileno(stdout)))
{
my_stdout_name = tempnam ("c:/", "cout");
(void) freopen (my_stdout_name, "wb", stdout);
(void) freopen (my_stdout_name, "wb", stderr);
}
my_stdout = fdopen (fileno(stdout), "r");
my_stderr = fdopen (fileno(stderr), "r");
if (isatty (fileno(stdin)))
{
my_stdin_name = tempnam ("c:/", "cinp");
(void) freopen (my_stdin_name, "rb", stdin);
my_stdin = fdopen (fileno(stdin), "wb");
}
atexit (Cleanup);
}
static int
main_console (int argc, char *argv[])
{
if (dpy == NULL)
{
Init (argc, argv);
Redirect ();
}
ProcessInput ();
while (XPending (dpy)) ProcessEvent();
return 1;
}
console()
{
int argc;
char *argv[2];
argc = 1;
argv[0] = "console";
argv[1] = NULL;
return main_console(argc, argv);
}
#ifdef TEST
int
main(int argc, char **argv)
{
FILE *fp;
char buf[512];
fvwm();
console();
while (argc > 1)
{
argc --;
argv ++;
fp = fopen (*argv, "r");
if (fp == NULL) continue;
while (fgets (buf, sizeof(buf)-1, fp))
{
buf[sizeof(buf)-1] = 0;
fputs (buf, stdout);
}
fclose (fp);
fvwm();
console();
}
while (1)
{
fvwm();
console();
while (fgets (buf, sizeof(buf)-1, stdin))
{
buf[sizeof(buf)-1] = 0;
fputs (buf, stdout);
}
}
return 0;
}
#endif