mcgrew@dartagnan.rutgers.edu (Charles Mcgrew) (06/07/89)
Submitted-by: Chuck Musciano <chuck@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@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@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@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@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}