v01i026: Tooltool - a suntools user interface builder, Part 07/13
Charles Mcgrew
mcgrew at dartagnan.rutgers.edu
Wed Jun 7 14:19:43 AEST 1989
Submitted-by: Chuck Musciano <chuck at trantor.harris-atd.com>
Posting-number: Volume 1, Issue 26
Archive-name: tooltool2.1c/part07
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 7 (of 13)."
# Contents: objects.c samples/vt100/out.c
# Wrapped by chuck at melmac on Thu Jun 1 10:39:33 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'objects.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'objects.c'\"
else
echo shar: Extracting \"'objects.c'\" \(19133 characters\)
sed "s/^X//" >'objects.c' <<'END_OF_FILE'
X/************************************************************************/
X/* Copyright 1988 by Chuck Musciano and Harris Corporation */
X/* */
X/* Permission to use, copy, modify, and distribute this software */
X/* and its documentation for any purpose and without fee is */
X/* hereby granted, provided that the above copyright notice */
X/* appear in all copies and that both that copyright notice and */
X/* this permission notice appear in supporting documentation, and */
X/* that the name of Chuck Musciano and Harris Corporation not be */
X/* used in advertising or publicity pertaining to distribution */
X/* of the software without specific, written prior permission. */
X/* Chuck Musciano and Harris Corporation make no representations */
X/* about the suitability of this software for any purpose. It is */
X/* provided "as is" without express or implied warranty. */
X/* */
X/* The sale of any product based wholely or in part upon the */
X/* technology provided by tooltool is strictly forbidden without */
X/* specific, prior written permission from Harris Corporation. */
X/* Tooltool technology includes, but is not limited to, the source */
X/* code, executable binary files, specification language, and */
X/* sample specification files. */
X/************************************************************************/
X
X
X#include <ctype.h>
X
X#include "tooltool.h"
X
XPRIVATE short cross_bits[] = {0x4000, 0xe000, 0x4000};
Xmpr_static(tt_better_button_cross, 3, 3, 1, cross_bits);
X
XPRIVATE short arrow_bits[] = {0x0400, 0x0600, 0xFD00, 0x0180, 0xFD00, 0x0600, 0x0400};
Xmpr_static(tt_menu_arrow, 9, 7, 1, arrow_bits);
X
XPUBLIC event_proc(),
X notify_proc();
X
X/************************************************************************/
X/* This group of routines contructs individual panel gadgets. */
X/************************************************************************/
X
X/************************************************************************/
XPRIVATE struct pixrect *better_menu_image(text, chars, pixels, font)
X
Xchar *text;
Xint chars;
Xint pixels;
Xstruct pixfont *font;
X
X{ struct pixrect *pr;
X struct pr_prpos pos;
X int width, true_width, height;
X
X width = chars * charwidth_of(font) + pixels;
X true_width = text_width(text, font) + 13;
X if (width < true_width)
X width = true_width;
X pr = mem_create(width + 8, height = charheight_of(font) + 6, 1);
X pr_rop(pr, 0, 0, width + 8, height, PIX_SRC | PIX_COLOR(1), NULL, 0, 0);
X pr_rop(pr, 2, 2, width + 4, height - 4, PIX_SRC | PIX_COLOR(0), NULL, 0, 0);
X pr_rop(pr, width - 5, (height - 7) / 2, 9, 7, PIX_SRC, &tt_menu_arrow, 0, 0);
X pos.pr = pr;
X pos.pos.x = 4 + (width - true_width) / 2;
X pos.pos.y = 4 + baseline_of(font);
X pf_ttext(pos, PIX_SRC | PIX_COLOR(1), font, text);
X return(pr);
X}
X
X/************************************************************************/
XPRIVATE struct pixrect *better_button_image(text, chars, pixels, font)
X
Xchar *text;
Xint chars;
Xint pixels;
Xstruct pixfont *font;
X
X{ struct pixrect *pr;
X struct pr_prpos pos;
X int width, true_width, height;
X
X width = chars * charwidth_of(font) + pixels;
X true_width = text_width(text, font);
X if (width < true_width)
X width = true_width;
X pr = mem_create(width + 8, height = charheight_of(font) + 6, 1);
X pr_rop(pr, 3, 0, width + 2, 2, PIX_SRC | PIX_COLOR(1), NULL, 0, 0);
X pr_rop(pr, 3, height - 2, width + 2, 2, PIX_SRC | PIX_COLOR(1), NULL, 0, 0);
X pr_rop(pr, 0, 3, 2, height - 6, PIX_SRC | PIX_COLOR(1), NULL, 0, 0);
X pr_rop(pr, width + 6, 3, 2, height - 6, PIX_SRC | PIX_COLOR(1), NULL, 0, 0);
X pr_rop(pr, 1, 1, 3, 3, PIX_SRC | PIX_DST, &tt_better_button_cross, 0, 0);
X pr_rop(pr, width + 4, 1, 3, 3, PIX_SRC | PIX_DST, &tt_better_button_cross, 0, 0);
X pr_rop(pr, width + 4, height - 4, 3, 3, PIX_SRC | PIX_DST, &tt_better_button_cross, 0, 0);
X pr_rop(pr, 1, height - 4, 3, 3, PIX_SRC | PIX_DST, &tt_better_button_cross, 0, 0);
X pos.pr = pr;
X pos.pos.x = 4 + (width - true_width) / 2;
X pos.pos.y = 4 + baseline_of(font);
X pf_ttext(pos, PIX_SRC | PIX_COLOR(1), font, text);
X return(pr);
X}
X
X/************************************************************************/
XPRIVATE image_box(gadget)
X
Xg_ptr gadget;
X
X{ int w, h, mw, mh;
X cv_ptr cv;
X double log10();
X
X if (gadget->kind == GADGET_BUTTON) {
X if (gadget->u.but.label[0]->is_icon) {
X gadget->image = gadget->u.but.label[0]->image;
X gadget->width = gadget->image->pr_width;
X gadget->height = gadget->image->pr_height;
X }
X else {
X gadget->width = text_width(gadget->u.but.label[0]->label, gadget->u.but.label[0]->font) + 8;
X gadget->height = charheight_of(gadget->u.but.label[0]->font) + 6;
X }
X }
X else if (gadget->kind == GADGET_MENU) {
X if (gadget->u.men.label->is_icon) {
X gadget->image = gadget->u.men.label->image;
X gadget->width = gadget->image->pr_width;
X gadget->height = gadget->image->pr_height;
X }
X else {
X gadget->width = text_width(gadget->u.men.label->label, gadget->u.men.label->font) + 21;
X gadget->height = charheight_of(gadget->u.men.label->font) + 6;
X }
X }
X else if (gadget->kind == GADGET_LABEL) {
X tt_construct_label(gadget->u.lab.label);
X gadget->image = gadget->u.lab.label->image;
X gadget->width = gadget->image->pr_width;
X gadget->height = gadget->image->pr_height;
X }
X else if (gadget->kind == GADGET_CHOICE) {
X if (gadget->u.cho.label == NULL) {
X gadget->width = -4; /* hack: correct for 4 pixel offset below */
X gadget->height = 0;
X }
X else {
X tt_construct_label(gadget->u.cho.label);
X gadget->image = gadget->u.cho.label->image;
X gadget->width = gadget->u.cho.label->image->pr_width;
X gadget->height = gadget->u.cho.label->image->pr_height;
X }
X tt_construct_label(gadget->u.cho.mark);
X tt_construct_label(gadget->u.cho.nomark);
X mw = max(gadget->u.cho.mark->image->pr_width, gadget->u.cho.nomark->image->pr_width);
X mh = max(gadget->u.cho.mark->image->pr_height, gadget->u.cho.nomark->image->pr_height);
X for (w = h = 0, cv = gadget->u.cho.value; cv; cv = cv->next) {
X tt_construct_label(cv->label);
X switch (gadget->u.cho.mode) {
X case CHOICE_CURRENT :
X case CHOICE_CYCLE : h = max(cv->label->image->pr_height, h);
X w = max(cv->label->image->pr_width, w);
X break;
X case CHOICE_VERTICAL : h += max(cv->label->image->pr_height, mh) + 4;
X w = max(cv->label->image->pr_width, w);
X break;
X case CHOICE_HORIZONTAL : h = max(cv->label->image->pr_height, h);
X w += cv->label->image->pr_width + mw + 8;
X break;
X }
X }
X switch (gadget->u.cho.mode) {
X case CHOICE_CURRENT : gadget->width += w + 4;
X gadget->height = max(gadget->height, h);
X break;
X case CHOICE_CYCLE : gadget->width += w + mw + 8;
X gadget->height = max(gadget->height, h);
X gadget->height = max(gadget->height, mh);
X break;
X case CHOICE_VERTICAL : gadget->width += w + mw + 8;
X gadget->height = max(gadget->height, h - 4);
X break;
X case CHOICE_HORIZONTAL : gadget->width += w;
X gadget->height = max(gadget->height, h);
X break;
X }
X gadget->u.cho.ch_width = w;
X gadget->u.cho.ch_height = h;
X }
X else if (gadget->kind == GADGET_SLIDER) {
X if (gadget->u.sli.label == NULL) {
X gadget->width = -4; /* hack: correct for 4 pixel offset below */
X gadget->height = 0;
X }
X else {
X tt_construct_label(gadget->u.sli.label);
X gadget->image = gadget->u.sli.label->image;
X gadget->width = gadget->u.sli.label->image->pr_width;
X gadget->height = gadget->u.sli.label->image->pr_height;
X }
X gadget->height = max(gadget->height, charheight_of(gadget->u.sli.font));
X gadget->width += 10 + gadget->u.sli.width;
X w = max(((int) log10(abs(gadget->u.sli.minimum) + 0.1)), ((int) log10(abs(gadget->u.sli.maximum) + 0.1))) + 1;
X if (gadget->u.sli.minimum < 0 || gadget->u.sli.maximum < 0)
X w++;
X if (gadget->u.sli.range)
X gadget->width += (2 * w + 2) * charwidth_of(gadget->u.sli.font);
X if (gadget->u.sli.value)
X gadget->width += (w + 3) * charwidth_of(gadget->u.sli.font);
X }
X else if (gadget->kind == GADGET_TEXT) {
X if (gadget->u.tex.label == NULL) {
X gadget->width = -4; /* hack: correct for 4 pixel offset below */
X gadget->height = 0;
X }
X else {
X tt_construct_label(gadget->u.tex.label);
X gadget->image = gadget->u.tex.label->image;
X gadget->width = gadget->u.tex.label->image->pr_width;
X gadget->height = gadget->u.tex.label->image->pr_height;
X }
X gadget->width += 4 + gadget->u.tex.display_len * charwidth_of(gadget->u.tex.font);
X gadget->height = max(charheight_of(gadget->u.tex.font), gadget->height);
X }
X}
X
X/************************************************************************/
XEXPORT tt_build_images(d)
X
Xd_ptr d;
X
X{ int i, len = 0;
X g_ptr b;
X char *p;
X
X for (b = d->gadgets; b; b = b->next) {
X image_box(b);
X if (b->kind == GADGET_BUTTON || b->kind == GADGET_MENU)
X len = (b->width > len)? b->width : len;
X }
X if (d->proportional)
X len = 0;
X for (b = d->gadgets; b; b = b->next) {
X if (b->kind == GADGET_BUTTON) {
X if (b->image == NULL) {
X b->image = better_button_image(b->u.but.label[0]->label, 0, len - 8, b->u.but.label[0]->font);
X b->width = b->image->pr_width;
X b->height = b->image->pr_height;
X }
X b->u.but.menu = menu_create(0);
X for (i = 0; i < MAX_SHIFT_SETS; i++)
X if (b->u.but.label[i])
X if (b->u.but.label[i]->is_icon) {
X menu_set(b->u.but.menu,
X MENU_APPEND_ITEM, menu_create_item(MENU_IMAGE_ITEM, b->u.but.label[i]->image, b->u.but.action[i],
X 0),
X 0);
X }
X else {
X p = (char *) safe_malloc(strlen(b->u.but.label[i]->label) + 5);
X strcpy(p, " ");
X strcat(p, b->u.but.label[i]->label);
X if (i & S_SHIFT)
X p[0] = 'S';
X if (i & S_CONTROL)
X p[1] = 'C';
X if (i & S_META)
X p[2] = 'M';
X menu_set(b->u.but.menu,
X MENU_APPEND_ITEM, menu_create_item(MENU_STRING_ITEM, p, b->u.but.action[i],
X MENU_FONT, b->u.but.label[i]->font,
X 0),
X 0);
X }
X }
X else if (b->kind == GADGET_MENU) {
X if (b->image == NULL) {
X b->image = better_menu_image(b->u.men.label->label, 0, len - 8, d->g_font);
X b->width = b->image->pr_width;
X b->height = b->image->pr_height;
X }
X }
X else if (b->kind == GADGET_LABEL) {
X /* do nothing, image_box took care of it */
X }
X else if (b->kind == GADGET_TEXT) {
X /* do nothing, image_box took care of it */
X }
X else if (b->kind == GADGET_CHOICE) {
X /* do nothing, image_box took care of it */
X }
X else if (b->kind == GADGET_SLIDER) {
X /* do nothing, image_box took care of it */
X }
X }
X}
X
X/************************************************************************/
XEXPORT tt_make_gadget(d, gadget, x, y)
X
Xd_ptr d;
Xg_ptr gadget;
Xint x;
Xint y;
X
X{ char *s;
X int i, lx, ly, mx, my, vx, vy, max_h, max_mh, max_mw;
X Panel_item p;
X cv_ptr cv;
X
X if (gadget->x != -1) {
X x = gadget->x;
X y = gadget->y;
X }
X if (gadget->kind == GADGET_BUTTON || gadget->kind == GADGET_MENU)
X p = panel_create_item(d->panel, (gadget->kind == GADGET_BUTTON)? PANEL_BUTTON : PANEL_MESSAGE,
X PANEL_LABEL_IMAGE, gadget->image,
X PANEL_ITEM_X, x,
X PANEL_ITEM_Y, y,
X PANEL_CLIENT_DATA, gadget,
X PANEL_EVENT_PROC, event_proc,
X PANEL_NOTIFY_PROC, notify_proc,
X PANEL_ACCEPT_KEYSTROKE, !d->text_items_exist,
X 0);
X else if (gadget->kind == GADGET_LABEL)
X p = panel_create_item(d->panel, PANEL_MESSAGE,
X PANEL_LABEL_IMAGE, gadget->image,
X PANEL_ITEM_X, x,
X PANEL_ITEM_Y, y,
X PANEL_CLIENT_DATA, gadget,
X PANEL_EVENT_PROC, event_proc,
X PANEL_NOTIFY_PROC, notify_proc,
X PANEL_ACCEPT_KEYSTROKE, !d->text_items_exist,
X 0);
X else if (gadget->kind == GADGET_SLIDER) {
X if (gadget->u.sli.label == NULL)
X /* do nothing */ ;
X else if (gadget->u.sli.label->image->pr_height > charheight_of(gadget->u.sli.font)) {
X ly = y;
X vy = y + (gadget->u.sli.label->image->pr_height - charheight_of(gadget->u.sli.font)) / 2;
X }
X else {
X ly = y + (charheight_of(gadget->u.sli.font) - gadget->u.sli.label->image->pr_height) / 2;
X vy = y;
X }
X if (gadget->u.sli.label)
X p = panel_create_item(d->panel, PANEL_SLIDER,
X PANEL_LABEL_IMAGE, gadget->image,
X PANEL_LABEL_X, x,
X PANEL_LABEL_Y, ly,
X PANEL_VALUE_X, x + gadget->image->pr_width + 4,
X PANEL_VALUE_Y, vy,
X 0);
X else
X p = panel_create_item(d->panel, PANEL_SLIDER,
X PANEL_VALUE_X, x,
X PANEL_VALUE_Y, y,
X 0);
X panel_set(p, PANEL_MIN_VALUE, gadget->u.sli.minimum,
X PANEL_MAX_VALUE, gadget->u.sli.maximum,
X PANEL_VALUE, gadget->u.sli.initial,
X PANEL_VALUE_FONT, gadget->u.sli.font,
X PANEL_SHOW_RANGE, gadget->u.sli.range,
X PANEL_SHOW_VALUE, gadget->u.sli.value,
X PANEL_SLIDER_WIDTH, gadget->u.sli.width,
X PANEL_CLIENT_DATA, gadget,
X PANEL_EVENT_PROC, event_proc,
X PANEL_NOTIFY_PROC, notify_proc,
X PANEL_ACCEPT_KEYSTROKE, !d->text_items_exist,
X 0);
X }
X else if (gadget->kind == GADGET_CHOICE) {
X p = panel_create_item(d->panel, PANEL_CHOICE,
X PANEL_MARK_IMAGES, gadget->u.cho.mark->image, 0,
X PANEL_NOMARK_IMAGES, gadget->u.cho.nomark->image, 0,
X PANEL_CLIENT_DATA, gadget,
X PANEL_EVENT_PROC, event_proc,
X PANEL_NOTIFY_PROC, notify_proc,
X PANEL_FEEDBACK, (gadget->u.cho.mode != CHOICE_CURRENT)? PANEL_MARKED : PANEL_NONE,
X 0);
X if (gadget->u.cho.mode == CHOICE_CURRENT || gadget->u.cho.mode == CHOICE_CYCLE)
X panel_set(p, PANEL_DISPLAY_LEVEL, PANEL_CURRENT, 0);
X else
X panel_set(p, PANEL_DISPLAY_LEVEL, PANEL_ALL, 0);
X max_mw = (gadget->u.cho.mode != CHOICE_CURRENT)? max(gadget->u.cho.mark->image->pr_width, gadget->u.cho.nomark->image->pr_width) : -4;
X max_mh = (gadget->u.cho.mode != CHOICE_CURRENT)? max(gadget->u.cho.mark->image->pr_height, gadget->u.cho.nomark->image->pr_height) : 0;
X if (gadget->u.cho.label) {
X lx = x;
X mx = x + gadget->u.cho.label->image->pr_width + 4;
X vx = mx + max_mw + 4;
X if (gadget->u.cho.label->image->pr_height > max_mh)
X if (gadget->u.cho.label->image->pr_height > gadget->u.cho.ch_height)
X max_h = gadget->u.cho.label->image->pr_height;
X else
X max_h = gadget->u.cho.ch_height;
X else if (max_mh > gadget->u.cho.ch_height)
X max_h = max_mh;
X else
X max_h = gadget->u.cho.ch_height;
X ly = y + (max_h - gadget->u.cho.label->image->pr_height) / 2;
X my = y + (max_h - max_mh) / 2;
X vy = y + (max_h - gadget->u.cho.ch_height) / 2;
X }
X else {
X mx = x;
X vx = x + max_mw + 4;
X max_h = max(max_mh, gadget->u.cho.ch_height);
X my = y + (max_h - max_mh) / 2;
X vy = y + (max_h - gadget->u.cho.ch_height) / 2;
X }
X if (gadget->u.cho.mode == CHOICE_VERTICAL) {
X ly = y;
X for (i = 0, vy = y, cv = gadget->u.cho.value; cv; i++, cv = cv->next) {
X if (max_mh > cv->label->image->pr_height)
X panel_set(p, PANEL_CHOICE_IMAGE, i, cv->label->image,
X PANEL_CHOICE_X, i, vx,
X PANEL_CHOICE_Y, i, vy + (max_mh - cv->label->image->pr_height) / 2,
X PANEL_MARK_X, i, mx,
X PANEL_MARK_Y, i, vy,
X 0);
X else
X panel_set(p, PANEL_CHOICE_IMAGE, i, cv->label->image,
X PANEL_CHOICE_X, i, vx,
X PANEL_CHOICE_Y, i, vy,
X PANEL_MARK_X, i, mx,
X PANEL_MARK_Y, i, vy + (cv->label->image->pr_height - max_mh) / 2,
X 0);
X vy += max(max_mh, cv->label->image->pr_height) + 4;
X }
X }
X else {
X for (i = 0, cv = gadget->u.cho.value; cv; cv = cv->next, i++) {
X panel_set(p, PANEL_CHOICE_IMAGE, i, cv->label->image,
X PANEL_CHOICE_X, i, vx,
X PANEL_CHOICE_Y, i, vy + (gadget->u.cho.ch_height - cv->label->image->pr_height) / 2,
X 0);
X if (gadget->u.cho.mode != CHOICE_CURRENT)
X panel_set(p, PANEL_MARK_X, i, mx,
X PANEL_MARK_Y, i, my,
X 0);
X if (gadget->u.cho.mode == CHOICE_HORIZONTAL) {
X mx += max_mw + cv->label->image->pr_width + 8;
X vx += max_mw + cv->label->image->pr_width + 8;
X }
X }
X }
X if (gadget->u.cho.label)
X panel_set(p, PANEL_LABEL_IMAGE, gadget->u.cho.label->image,
X PANEL_LABEL_X, lx,
X PANEL_LABEL_Y, ly,
X 0);
X }
X else if (gadget->kind == GADGET_TEXT) {
X if (gadget->u.tex.label == NULL)
X vy = y;
X else if (gadget->u.tex.label->is_icon)
X if (gadget->u.tex.label->image->pr_height > gadget->u.tex.font->pf_defaultsize.y) {
X ly = y;
X vy = y + (gadget->height - gadget->u.tex.font->pf_defaultsize.y) / 2;
X }
X else {
X ly = y + (gadget->height - gadget->u.tex.label->image->pr_height) / 2;
X vy = y;
X }
X else
X if (gadget->u.tex.label->font->pf_defaultsize.y > gadget->u.tex.font->pf_defaultsize.y) {
X ly = y;
X vy = y + (baseline_of(gadget->u.tex.label->font) - baseline_of(gadget->u.tex.font));
X }
X else {
X ly = y + (baseline_of(gadget->u.tex.font) - baseline_of(gadget->u.tex.label->font));
X vy = y;
X }
X if (gadget->u.tex.label)
X p = panel_create_item(d->panel, PANEL_TEXT,
X PANEL_LABEL_IMAGE, gadget->image,
X PANEL_LABEL_X, x,
X PANEL_LABEL_Y, ly,
X 0);
X else
X p = panel_create_item(d->panel, PANEL_TEXT, 0);
X panel_set(p, PANEL_VALUE_X, gadget->u.tex.label? x + 4 + gadget->image->pr_width : x,
X PANEL_VALUE_Y, vy,
X PANEL_VALUE_DISPLAY_LENGTH, gadget->u.tex.display_len,
X PANEL_VALUE_STORED_LENGTH, gadget->u.tex.retain_len,
X PANEL_VALUE_FONT, gadget->u.tex.font,
X PANEL_NOTIFY_LEVEL, PANEL_ALL,
X PANEL_CLIENT_DATA, gadget,
X PANEL_EVENT_PROC, event_proc,
X PANEL_NOTIFY_PROC, notify_proc,
X 0);
X }
X gadget->panel_item = p;
X}
END_OF_FILE
if test 19133 -ne `wc -c <'objects.c'`; then
echo shar: \"'objects.c'\" unpacked with wrong size!
fi
# end of 'objects.c'
fi
if test -f 'samples/vt100/out.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'samples/vt100/out.c'\"
else
echo shar: Extracting \"'samples/vt100/out.c'\" \(19613 characters\)
sed "s/^X//" >'samples/vt100/out.c' <<'END_OF_FILE'
X/*
X * vtem - A termcap driven VT100 emulator for BSD Unix
X *
X * $Header: /home/src/local/vttool/RCS/out.c,v 1.2 89/02/08 16:08:10 jqj Exp $
X *
X * $Log: out.c,v $
X * Revision 1.2 89/02/08 16:08:10 jqj
X * Many changes for better emulation. Emulator now passes most vttest tests
X * with the exception of double height/width lines and special characters.
X * Major changes include:
X * 1/ respond to terminal inquiries
X * 2/ reasonable handling of 132-column mode (truncate lines if no room). Full
X * support if CO >= 132 in termcap.
X * 3/ correct handling of autowrap (e.g. "x" in col 80 then cursor up => no wrap)
X * 4/ support for VT102 features (I/D line, D char, IRM, terminal inquiry)
X * 5/ newline mode
X * 6/ \E[5r should set scrolling region to [5,24]
X * 7/ correct handling of character sets in VT52 mode
X * 8/ correct handling of most control characters
X * 9/ various miscellaneous bugs in the emulation
X *
X * Version 1.1+gnu1+bgb
X * Fixed handling of ^[[0;0r - clear scroll region barnett at ge-crd.arpa
X * added mechanism to approximate the VT52 Special Graphics Set
X * ^[Fn where \0157 <= n <= \0176
X *
X * Version 1.1+gnu1
X * Bug fixes by hoptoad!gnu for version 1.1+gnu1:
X * Don't walk past the end of the 'tabs' array if we are in column 81.
X * There may still be a few column 81 bugs in here.
X *
X * Public domain software.
X * Written by Leif Samuelsson (leif at erisun) in December, 1985
X */
X
X#include "vtem.h"
X
Xtypedef Bool int;
Xtypedef enum { NORMAL, GRAPHICS } char_set;
X
Xstatic int row, col, save_row, save_col, top_margin, bottom_margin;
Xstatic char_set g0_set, g1_set;
Xstatic Bool blink, bold, reverse, underline,
X save_blink, save_bold, save_reverse, save_underline,
X origin_mode, vt52_mode, wrap_mode,
X newline_mode, insert_mode, echo_mode,
X cursor_key_mode, keypad_app_mode,
X shift_out, need_wrap;
Xstatic int wrap_column; /* 80 or 132 */
Xstatic short tabs[132];
Xstatic FILE *f;
Xstatic int arg[10], argno;
Xstatic char *answerback = "\r";
X
X/* arow is absolute row, taking top_margin into account */
X#define arow (row + (origin_mode ? (top_margin - 1) : 0))
X
X
X/* nextch - read output and interpret control characters.
X * Return first non-control character, or EOF or CAN on error
X */
Xstatic
Xint nextch()
X{
Xregister int ch;
X
X while ((ch = getc(f)) != EOF) {
X switch (ch) {
X case '\0': /* Ignore nulls and DELs */
X case '\177':
X break;
X case '\005': /* Dumb answerback */
X write(master,answerback,strlen(answerback));
X break;
X case '\007': /* Bell */
X ring_bell(); break;
X case '\b': /* BackSpace */
X need_wrap = 0;
X if (col > 1) {
X if (--col < CO)
X backspace();
X } break;
X case '\t': /* Tab */
X while (col < wrap_column && !tabs[col++])
X need_wrap = 0;
X set_cursor(col-1, arow-1); break;
X case '\n': /* Line Feed */
X case '\013': /* VT */
X case '\014': /* FF */
X if (newline_mode)
X do_newline();
X else do_linefeed();
X break;
X
X case '\r': /* Carriage Return */
X need_wrap = 0;
X if (col > 1) {
X col = 1;
X cr();
X } break;
X case '\016':
X shift_out = 1; break;
X case '\017':
X shift_out = 0; break;
X case '\032': /* SUB -- treat as CAN */
X ch = '\030'; /* and print error indicator */
X do_printing('a', GRAPHICS);
X default:
X return(ch);
X }
X if (f->_cnt == 0)
X fflush(stdout);
X }
X return(ch);
X}
X
X/* handle_output - Main loop of output process.
X * Reads and dispatches characters from output stream.
X * Called from main() in a lower fork.
X */
Xhandle_output()
X{
Xregister int ch;
X
X (void) close(0);
X if ((f = fdopen(master, "r")) == (FILE *) 0) {
X fprintf(stderr, "handle_output: Can't read from shell\r\n");
X exit(1);
X }
X do_reset();
X if (vttype == VT52)
X vt52_mode = 1;
X while ((ch = nextch()) != EOF) {
X if (ch == '\033') { /* Escape character */
X if (vt52_mode)
X do_vt52_escape();
X else
X do_ansi_escape();
X }
X else if (ch >= ' ') /* Printing character */
X do_printing(ch,(shift_out ? g1_set : g0_set));
X if (f->_cnt == 0)
X fflush(stdout);
X }
X fclose(f);
X exit(0);
X}
X
X
X/* do_printing - process a printing character.
X * ch -- the ascii character to be printed.
X * charset -- NORMAL or GRAPHICS
X */
Xstatic do_printing(ch, charset)
Xchar ch;
Xchar_set charset;
X{
X /* on some terminals, we could be smarter about graphics characters */
X if (charset == GRAPHICS) {
X if (ch >= '_')
X ch = " *#HFCLo+NV+++++---__++++!<>P##. "[ch - '_'];
X }
X if (need_wrap) { /* last action wrote to wrap column */
X col = 1;
X need_wrap = 0;
X set_cursor(col-1, arow-1);
X do_linefeed();
X }
X if (col == wrap_column) { /* last column of current display */
X if (arow < LI && col <= CO)
X putchar(ch); /* Must ignore last pos to avoid scroll */
X set_cursor(col-1, arow-1);
X if (wrap_mode)
X need_wrap = 1;
X }
X else {
X if (col <= CO && (col < CO || arow < LI)) {
X if (insert_mode)
X insert_char(ch); /* maybe make room, then print */
X else putchar(ch); /* just print it */
X if (col == CO) /* might have caused a wrap if AM */
X set_cursor(col-1, arow-1); /* put it back where it was */
X }
X col++;
X }
X}
X
X/* do_ansi_escape - reads and interprets an ANSI escape sequence
X */
X
Xstatic do_ansi_escape()
X{
Xregister int ch;
X
X if ((ch = nextch()) == EOF)
X return;
X switch (ch) {
X case '\030': /* CANCEL */
X break;
X case '#':
X do_hash();
X break;
X case '=': /* we ignore keypad_app_mode */
X keypad_app_mode = 0; break;
X case '>':
X keypad_app_mode = 1; break;
X case '(':
X case ')':
X do_character_sets(ch); break;
X case '7': /* save cursor */
X save_row = row;
X save_col = col;
X save_blink = blink;
X save_bold = bold;
X save_reverse = reverse;
X save_underline = underline;
X break;
X case '8': /* resort cursor */
X row = save_row; /* if no previous SAVE, use default */
X col = save_col;
X set_cursor(col-1, arow-1);
X if (blink = save_blink)
X start_blink();
X if (bold = save_bold)
X start_bold();
X if (reverse = save_reverse)
X start_reverse();
X if (underline = save_underline)
X start_underline();
X break;
X case 'D': /* cursor down, with scroll */
X do_linefeed(); break;
X case 'E': /* CRLF, with scroll */
X do_newline(); break;
X case 'H': /* set tab in current column */
X if (col <= sizeof (tabs)/sizeof (*tabs))
X tabs[col-1] = 1; break;
X case 'M': /* cursor up, with scroll */
X do_reverse_lf(); break;
X case 'Z':
X do_device_attributes(); break;
X case '[':
X do_csi(); break;
X case 'c':
X do_reset();
X ring_bell(); break;
X }
X}
X
X/* do_csi - the real ANSI interpreter
X */
Xstatic do_csi()
X{
Xregister int i, ch;
Xint private;
X
X if ((ch = nextch()) == EOF || ch == '\030')
X return;
X
X /* Check if private VT100 esc sequence */
X private = 0;
X if (ch == '?') {
X private = 1;
X if ((ch = nextch()) == EOF || ch == '\030')
X return;
X }
X
X /* Parse arguments */
X argno = 0;
X while ((ch >= '0' && ch <= '9') || ch == ';') {
X arg[argno] = 0;
X while (ch >= '0' && ch <= '9') {
X arg[argno] = arg[argno] * 10 + (ch - '0');
X if ((ch = nextch()) == EOF || ch == '\030')
X return;
X }
X if (ch == ';') {
X if ((ch = nextch()) == EOF || ch == '\030')
X return;
X }
X argno++;
X }
X
X if (private) {
X switch (ch) {
X case 'h':
X do_set_mode(private,1);
X break;
X case 'l':
X do_set_mode(private,0);
X break;
X }
X }
X else {
X switch (ch) {
X case 'A':
X need_wrap = 0;
X i = (argno == 1 && arg[0] > 0) ? arg[0] : 1;
X while (i-- && arow > 1 && arow != top_margin) {
X cursor_up();
X row--;
X } break;
X
X case 'B':
X need_wrap = 0;
X i = (argno == 1 && arg[0] > 0) ? arg[0] : 1;
X while (i-- && arow < 24 && arow != bottom_margin) {
X cursor_down();
X row++;
X } break;
X
X case 'C':
X i = (argno == 1 && arg[0] > 0) ? arg[0] : 1;
X while (i-- && col < wrap_column) {
X need_wrap = 0;
X if (col++ < CO)
X cursor_right();
X } break;
X
X case 'D':
X need_wrap = 0;
X i = (argno == 1 && arg[0] > 0) ? arg[0] : 1;
X while (i-- && col > 1) {
X if (--col < CO)
X backspace();
X } break;
X
X case 'H':
X case 'f':
X do_set_cursor(); break;
X case 'J':
X do_erase_in_display(); break;
X case 'K':
X do_erase_in_line(); break;
X case 'L':
X do_insert_line(); break;
X case 'M':
X do_delete_line(); break;
X case 'P':
X do_delete_char(); break;
X case 'c':
X do_device_attributes(); break;
X case 'g':
X do_clear_tabs(); break;
X case 'h':
X do_set_mode(private,1); break;
X case 'l':
X do_set_mode(private,0); break;
X case 'm':
X do_attributes(); break;
X case 'n':
X do_device_status_report(private); break;
X case 'r':
X do_set_scroll_region(); break;
X case 'x':
X /* Request Terminal Parameters--make some up for now */
X if (argno == 0 || arg[0] == 0)
X write(master,"\033[2;1;2;120;120;1;0x",20);
X else if (arg[0] == 1)
X write(master,"\033[3;1;2;120;120;1;0x",20);
X break;
X }
X }
X}
X
X/* do_set_mode - process \E[<#;...>h \E[<#;...>l
X * private == 1 -- call was \E[?...
X * setit == 1 -- call was \E[...h (set_mode) rather than \E[...l (reset_mode)
X */
Xstatic do_set_mode(private,setit)
XBool private, setit;
X{
X int i;
X for (i = 0; i < argno; i++) {
X if (private) switch (arg[i]) {
X case 1: /* DECCKM */
X cursor_key_mode = setit; break;
X case 2: /* DECANM */
X vt52_mode = !setit; break;
X case 3: /* DECCOLM */
X clear_screen();
X row = 1; col = 1;
X top_margin = 1; bottom_margin = 24;
X set_cursor(col-1, arow-1);
X wrap_column = setit ? 132 : 80;
X break;
X case 6: /* DECOM */
X origin_mode = setit; break;
X case 7: /* DECAWN */
X wrap_mode = setit; break;
X case 12: /* echo -- not implemented */
X echo_mode = setit; break;
X default: /* DECSNM, DECARM, DECPFF, DECPEX */
X break;
X }
X else switch (arg[i]) { /* ANSI sequences */
X case 4: /* IRM -- insert/replace mode */
X if (vttype == VT102) {
X insert_mode = setit;
X set_insert_mode(setit);
X }
X break;
X case 20: /* LNM - linefeed/newline mode */
X newline_mode = setit; break;
X }
X }
X}
X
X
X/* do_vt52_escape - interprets VT52 escape sequences
X * note that if vttype==VT52 we provide a partial emulation of a VT52,
X * just as a VT100 does, not a real VT52.
X */
Xstatic do_vt52_escape()
X{
Xregister int ch;
X
X if ((ch = nextch()) == EOF)
X return;
X switch (ch) {
X case '=': /* we ignore keypad_app_mode */
X keypad_app_mode = 0; break;
X case '>':
X keypad_app_mode = 1; break;
X case '<':
X if (vttype != VT52) /* can we handle VT100 sequences? */
X vt52_mode = 0;
X break;
X case 'A':
X if (row > 1) {
X need_wrap = 0;
X cursor_up();
X row--;
X } break;
X case 'B':
X if (row < bottom_margin-top_margin+1) {
X need_wrap = 0;
X cursor_down();
X row++;
X } break;
X case 'C':
X if (col < wrap_column) {
X need_wrap = 0;
X cursor_right();
X col++;
X } break;
X case 'D':
X if (col > 1) {
X need_wrap = 0;
X if (--col < CO)
X backspace();
X } break;
X case 'H':
X row = col = 1;
X need_wrap = 0;
X set_cursor(col-1, arow-1); break;
X case 'I':
X do_reverse_lf(); break;
X case 'J':
X clear_eos(); break;
X case 'K':
X clear_eol(col-1, arow-1); break;
X case 'Y':
X do_vt52_set_cursor(); break;
X case 'F':
X g0_set = g1_set = GRAPHICS; break;
X case 'G':
X g0_set = g1_set = NORMAL; break;
X case 'Z': /* identify as VT52 */
X write(master,"\033/Z",3); break;
X }
X}
X
Xstatic do_set_cursor()
X{
X if (arg[0] == 0)
X arg[0]++;
X if (arg[1] == 0)
X arg[1]++;
X switch (argno) {
X case 0:
X arg[0] = 1;
X /* Fall through */
X
X case 1:
X arg[1] = 1;
X /* Fall through... */
X
X case 2:
X if (arg[0] > 24)
X arg[0] = 24;
X if (arg[1] > wrap_column)
X arg[1] = wrap_column;
X if (row != arg[0] || col != arg[1])
X need_wrap = 0; /* bizarre */
X row = arg[0];
X col = arg[1];
X set_cursor(col-1, arow-1);
X break;
X }
X}
X
Xstatic do_vt52_set_cursor()
X{
Xregister int ch1, ch2;
X
X if ((ch1 = nextch()) == EOF)
X return;
X if ((ch2 = nextch()) == EOF)
X return;
X ch1 -= 0x1f;
X ch2 -= 0x1f;
X if (ch1 >= 1 && ch1 <= 24 && ch2 >= 1 && ch2 <= 80) {
X if (row != ch1 || col != ch2)
X need_wrap = 0;
X row = ch1;
X col = ch2;
X set_cursor(col-1, arow-1);
X }
X}
X
X/* do_erase_in_display - process \E[<#>J
X */
Xstatic do_erase_in_display()
X{
X switch (argno) {
X case 0:
X arg[0] = 0;
X argno++;
X /* Fall through */
X case 1:
X switch (arg[0]) {
X case 0:
X clear_eos();
X break;
X case 1:
X clear_bos(col-1, arow-1);
X break;
X case 2:
X clear_screen();
X set_cursor(col-1, arow-1);
X break;
X }
X break;
X }
X}
X
X/* do_erase_in_line - process \E[<#>K
X */
Xstatic do_erase_in_line()
X{
X switch(argno) {
X case 0:
X arg[0] = 0;
X argno++;
X /* fall through */
X case 1:
X switch (arg[0]) {
X case 0:
X clear_eol(col-1, arow-1);
X break;
X case 1:
X clear_bol(col-1, arow-1);
X break;
X case 2:
X cr();
X clear_eol(0, arow-1);
X set_cursor(col-1, arow-1);
X break;
X } break;
X }
X}
X
Xstatic do_clear_tabs()
X{
Xregister int i;
X
X if (argno == 0)
X arg[argno++] = 0;
X switch (arg[0]) {
X case 0:
X if (col <= sizeof (tabs)/sizeof (*tabs))
X tabs[col-1] = 0; break;
X case 3:
X for (i = 0; i < sizeof (tabs)/sizeof (*tabs); i++)
X tabs[i] = 0; /* should we stop at wrap_column? */
X break;
X }
X}
X
X/* do_attributes - process \E[<#...>m
X */
Xstatic do_attributes()
X{
Xregister int i;
X
X if (argno == 0) {
X arg[0] = 0;
X argno++;
X }
X for (i=0; i<argno; i++) {
X switch (arg[i]) {
X case 0:
X end_attributes();
X bold = underline = blink = reverse = 0;
X break;
X case 1:
X start_bold();
X bold = 1; break;
X
X case 4:
X start_underline();
X underline = 1; break;
X
X case 5:
X start_blink();
X blink = 1; break;
X
X case 7:
X start_reverse();
X reverse = 1; break;
X }
X }
X}
X
Xstatic do_set_scroll_region()
X{
X switch (argno) {
X case 0:
X arg[0] = 1;
X /* Fall through */
X case 1:
X arg[1] = 24;
X argno = 2;
X /* Fall through */
X case 2:
X if (arg[0] == 0 && arg[1] == 0) { /* per bgb */
X arg[0] = 1; arg[1] = 24;
X } else {
X if (arg[0] == 0)
X arg[0] = 1;
X if (arg[1] == 0)
X arg[1] = 1;
X }
X if (arg[0] < arg[1]) { /* region must be at least 2 lines */
X top_margin = arg[0];
X bottom_margin = arg[1];
X col = row = 1;
X need_wrap = 0;
X set_cursor(col-1, arow-1);
X }
X break;
X }
X}
X
X/* do_newline - next line, column 0, with possible scroll
X */
Xstatic do_newline()
X{
X if (col > 1) {
X col = 1;
X cr();
X need_wrap = 0;
X }
X do_linefeed();
X}
X
X/* do_linefeed - next line, same column, with possible scroll
X * (note -- no cursor down if at bottom of screen below scrolling region)
X */
Xstatic do_linefeed()
X{
X if (arow == bottom_margin) {
X need_wrap = 0;
X if (bottom_margin < LI || top_margin > 1) {
X scroll_region(top_margin-1, bottom_margin-1, TRUE);
X set_cursor(col-1, arow-1);
X }
X else
X linefeed(); /* assumed to cause fullscreen scroll */
X }
X else if (arow < 24) { /* don't scroll if below scrolling region */
X need_wrap = 0;
X row++;
X linefeed();
X }
X}
X
X/* do_reverse_lf - previous line, same column, with possible scroll
X */
Xstatic do_reverse_lf()
X{
X if (arow == top_margin) {
X need_wrap = 0;
X scroll_region(top_margin-1, bottom_margin-1, FALSE);
X set_cursor(col-1, arow-1);
X }
X else if (arow > 1) { /* don't scroll if above scrolling region */
X need_wrap = 0;
X row--;
X reverse_lf(); /* assumed to cause fullscreen scroll */
X }
X}
X
X/* do_hash - process \E#<#>. Only DECALN -- screen alignment display
X * functions not implemented include double hight and double width lines!
X */
Xstatic do_hash()
X{
Xregister int ch, i, j;
Xint maxch;
X
X if ((ch = nextch()) == EOF)
X return;
X switch(ch) {
X case '8': /* screen alignment display */
X set_cursor(0, 0);
X if ((maxch = wrap_column) > CO) maxch = CO;
X for (i=1; i<24; i++) {
X for (j=maxch; j>0; j--)
X putchar('E');
X set_cursor(0, i);
X }
X if (LI <= 24 && CO <= maxch)
X maxch--; /* avoid last space on display */
X for (j=maxch; j>0; j--)
X putchar('E');
X top_margin = 1;
X bottom_margin = 24; /* at least on my VT102... */
X row = col = 1;
X set_cursor(col-1, arow-1);
X break;
X }
X}
X
X/* do_characters_sets - Not fully implemented
X */
Xstatic do_character_sets(ch)
Xregister int ch;
X{
Xregister int ch2;
X
X if ((ch2 = nextch()) == EOF)
X return;
X switch (ch2) {
X case 'A':
X case 'B':
X if (ch == '(')
X g0_set = NORMAL;
X else
X g1_set = NORMAL;
X break;
X case '0':
X if (ch == '(')
X g0_set = GRAPHICS;
X else
X g1_set = GRAPHICS;
X break;
X }
X}
X
X/* do_reset - Reset emulator and screen
X */
Xstatic do_reset()
X{
Xregister int i;
X
X clear_screen();
X row = 1;
X col = 1;
X top_margin = 1;
X bottom_margin = 24;
X origin_mode = 0;
X vt52_mode = (vttype == VT52); /* stuck in VT52 mode? */
X wrap_mode = 1;
X newline_mode = 0;
X insert_mode = 0;
X echo_mode = 0;
X cursor_key_mode = 0;
X keypad_app_mode = 0;
X wrap_column = 80;
X g0_set = NORMAL;
X g1_set = NORMAL;
X shift_out = 0;
X need_wrap = 0;
X end_attributes();
X set_insert_mode(0);
X bold = underline = blink = reverse = 0;
X save_bold = save_underline = save_blink = save_reverse = 0;
X save_row = save_col = 1; /* VT102 goes home if none saved */
X for (i=0; i<132; i++)
X tabs[i] = ((i/8)*8 == i);
X}
X
X/* do_insert_line - VT102 only
X * insert lines at the cursor, moving the current line down. Note that
X * on a VT102 this is a no-op if the cursor is outside the scrolling region.
X */
Xstatic do_insert_line()
X{
X int i;
X if (vttype != VT102 || arow < top_margin || arow > bottom_margin)
X return;
X if (argno==0 || arg[0] == 0) arg[0] = 1;
X for (i = 0; i < arg[0]; i++)
X scroll_region(arow-1,bottom_margin-1, FALSE);
X set_cursor(col-1,arow-1);
X}
X
X/* do_delete_line - VT102 only
X * delete the line containing the cursor. Note that on a VT102 this
X * is a no-op if the cursor is outside the scrolling region.
X */
Xstatic do_delete_line()
X{
X int i;
X if (vttype != VT102 || arow < top_margin || arow > bottom_margin)
X return;
X if (argno==0 || arg[0] == 0) arg[0] = 1;
X for (i = 0; i < arg[0]; i++)
X scroll_region(arow-1,bottom_margin-1, TRUE);
X set_cursor(col-1,arow-1);
X}
X
X/* do_delete_char - VT102 only
X * delete the character at the cursor. End of line must fill with
X * blanks.
X */
Xstatic do_delete_char()
X{
X int i;
X if (vttype != VT102) return;
X if (argno==0 || arg[0] == 0) arg[0] = 1;
X if (CO > wrap_column) {
X set_cursor(wrap_column,arow-1);
X clear_eol(wrap_column-1,arow-1);
X set_cursor(col-1,arow-1);
X }
X for (i = 0; i < arg[0]; i++)
X delete_char();
X}
X
X/*
X * Status reports
X */
X
X/* do_device_status_report - process \E[<#>n and \E[?<#>n
X */
Xstatic do_device_status_report(private)
Xint private;
X{
X char buf[12];
X if (argno==0) arg[argno++]=1;
X switch (arg[0]) {
X case 5: /* device status */
X write(master,"\033[0n",4); /* terminal is ok */
X break;
X case 6: /* cursor position report */
X sprintf(buf,"\033[%d;%dR",arow,col);
X write(master,buf,strlen(buf));
X break;
X case 15: /* printer status */
X if (private) /* say "no printer" */
X write(master,"\033[?13n",6);
X break;
X }
X}
X
X/* do_device_attributes - Device Attributes
X * say we're a VT100 without AVO or a VT102
X */
Xstatic do_device_attributes() {
X switch (vttype) {
X default:
X case VT100:
X write(master,"\033[?1;0c",7); break;
X case VT102:
X write(master,"\033[?6c",5); break;
X }
X}
X
X
END_OF_FILE
if test 19613 -ne `wc -c <'samples/vt100/out.c'`; then
echo shar: \"'samples/vt100/out.c'\" unpacked with wrong size!
fi
# end of 'samples/vt100/out.c'
fi
echo shar: End of archive 7 \(of 13\).
cp /dev/null ark7isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 13 archives.
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0
Chuck Musciano ARPA : chuck at trantor.harris-atd.com
Harris Corporation Usenet: ...!uunet!x102a!trantor!chuck
PO Box 37, MS 3A/1912 AT&T : (407) 727-6131
Melbourne, FL 32902 FAX : (407) 727-{5118,5227,4004}
More information about the Comp.sources.sun
mailing list