/* zterm.c - Zed's Virtual Terminal
* Copyright (C) 1998 Michael Zucchi
*
* A simple terminal program, based on ZTerm.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <pwd.h>
#include <stdlib.h>
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#include <gdk/gdkprivate.h>
#include <gdk/gdkkeysyms.h>
#include <zvt/zvtterm.h>
Yes, you should always remember the license! Of course,
i'm rather fond of GNU's version ...
#define FONT "-misc-fixed-medium-r-normal--12-200-75-75-c-100-iso8859-1"
Here we have the font we're using. This is the full name
of "fixed". A nice readable fixed-width, and small font.
Another signal that may be generated by the widget is the
title_changed signal. This signal is generated when the xterm
escape sequence to set a title is processed. Here we setup a
simple handler that will change the window title when this
sequence is caught. By default no action is taken.
gint
main (gint argc, gchar *argv[])
{
int i, c, cmdindex, scrollbacklines, login_shell;
char buffer[60], **p;
struct passwd *pw;
GtkWidget *term, *hbox, *scrollbar;
enum { RIGHT, LEFT } scrollpos = LEFT;
login_shell = 0;
cmdindex = 0;
scrollbacklines = 50;
The next section sets up the environment as explained
elsewhere. We setup the TERM environment and drop the terminal
size environment, and add the COLORTERM value, to enable colour
output for specific applications.
We also setup a placeholder for the WINDOWID environment
when it is known later on. This is used by some X-aware
terminal applications to manipulate the terminal window.
/* set up terminal environment */
env = environ;
for (p = env; *p; p++);
i = p - env;
env_copy = (char **) g_malloc (sizeof (char *) * (i + 3));
for (i = 0, p = env; *p; p++) {
if (strncmp (*p, "TERM=", 5) == 0) {
env_copy [i++] = "TERM=xterm";
} else if ((strncmp (*p, "COLUMNS=", 8) == 0) ||
(strncmp (*p, "LINES=", 6) == 0)) {
continue;
} else {
env_copy [i++] = *p;
}
}
env_copy [i++] = "COLORTERM=zterm";
winid_pos = i++;
env_copy [winid_pos] = "TEST";
env_copy [i] = NULL;
gtk_init(&argc, &argv);
Process the command line options. Note the saving of the
position of the '-e' option and the termination of processing
once it has been found. This is a compatability with the
'xterm' '-e' command line option.
/* process arguments */
while ( (cmdindex==0) && (c=getopt(argc, argv, "le:s:rh")) != EOF ) {
switch(c) {
case 'e':
cmdindex = optind-1; /* index of argv array to pass to exec */
break;
case 's':
scrollbacklines = atoi(optarg);
break;
case 'l':
login_shell = 1;
break;
case 'r':
scrollpos = RIGHT;
break;
case '?':
case 'h':
default:
fprintf(stderr, "Usage: zterm [-sNN] [-l] [-r] [-e command args]\n");
exit(1);
break;
}
}
Now we are ready to create our application widgets
...
Attatch the signal handlers we defined above. We also
attach the destroy signal to the exit handling event - if the
window is closed by the window manager then this catches that
event. Otherwise the close button doesn't work!
And here we show how the scrollbar is attached to the term
adjustment designed for this purpose, and how the scrollbar has
its focus disabled. We also give the user the option for a left
or right scrollbar.
Although many perfer the windows/motif
convention of a right-mounted scrollbar, but a left-mounted
scrollbar should be an option if possible, as it is often a much
more practical position to have it in. Particularly if there
are overlapping windows, or windows partly off-screen.
Here we show how the sub-shell is created using
zvt_term_forkpty(). We also give the user the option of logging
the session in utmp/wtmp. This probably isn't that necessary
for a non-shell application, but might be useful.
It also shows how either a shell is executed, or the
command given on the command line is executed. And how the
login shell arguments are processed. Again this is not normally
required for a non-shell application.
/* fork the shell/program */
switch (zvt_term_forkpty(ZVT_TERM (term), ZVT_TERM_DO_UTMP_LOG | ZVT_TERM_DO_WTMP_LOG)) {
case -1:
perror("ERROR: unable to fork:");
exit(1);
break;
case 0:
if (cmdindex) {
environ = env_copy;
execvp(argv[cmdindex], &argv[cmdindex]);
} else {
GString *shell, *name;
/* get shell from passwd */
pw = getpwuid(getuid());
if (pw) {
shell = g_string_new(pw->pw_shell);
if (login_shell)
name = g_string_new("-");
else
name = g_string_new("");
g_string_append(name, strrchr(pw->pw_shell, '/'));
} else {
shell = g_string_new("/bin/sh");
if (login_shell)
name = g_string_new("-sh");
else
name = g_string_new("sh");
}
execle (shell->str, name->str, NULL, env_copy);
perror ("Could not exec\n");
_exit (127);
}
perror("ERROR: Cannot exec command:");
exit(1);
default:
break;
}
And thats it! We're ready to go into the main processing
loop!
/* main loop */
gtk_main ();
gtk_exit(0);
return 0;
}
This example is basically the 'zterm' test-application
which is in the source code tree under gnome-libs/zvt/zterm.c.
The gnome-terminal application (in gnome-core/gnome-terminal)
provides a much richer set of features. It exercises all
configurable options of the terminal emulator as well.
Crescendo and xchat are two other examples that use the
widget in different ways. Crescendo runs a subordinate TinyFuge
mud client, and xchat uses it as a color output device.