home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
games
/
volume16
/
nethack31
/
patch2w
< prev
next >
Wrap
Internet Message Format
|
1993-06-16
|
58KB
Path: uunet!gatech!news-feed-1.peachnet.edu!emory!ogicse!news.tek.com!saab!billr
From: billr@saab.CNA.TEK.COM (Bill Randle)
Newsgroups: comp.sources.games
Subject: v17i098: nethack31 - display oriented dungeons & dragons (Ver. 3.1), Patch2w/33
Message-ID: <1v8is9$j65@ying.cna.tek.com>
Date: 11 Jun 93 00:16:09 GMT
Article-I.D.: ying.1v8is9$j65
Organization: Tektronix, Inc, Redmond, OR, USA
Lines: 2196
Approved: billr@saab.CNA.TEK.COM
NNTP-Posting-Host: saab.cna.tek.com
Xref: uunet comp.sources.games:1761
Submitted-by: izchak@linc.cis.upenn.edu (Izchak Miller)
Posting-number: Volume 17, Issue 98
Archive-name: nethack31/Patch2w
Patch-To: nethack31: Volume 16, Issue 1-116
Environment: Amiga, Atari, Mac, MS-DOS, Windows-NT, OS2, Unix, VMS, X11
#! /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 23 (of 33)."
# Contents: src/ball.c sys/mac/mactty.c
# Wrapped by billr@saab on Thu Jun 10 16:55:06 1993
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'src/ball.c' -a "${1}" != "-c" ; then
echo shar: Renaming existing file \"'src/ball.c'\" to \"'src/ball.c.orig'\"
mv -f 'src/ball.c' 'src/ball.c.orig'
fi
echo shar: Extracting \"'src/ball.c'\" \(16324 characters\)
sed "s/^X//" >'src/ball.c' <<'END_OF_FILE'
X/* SCCS Id: @(#)ball.c 3.1 93/05/15 */
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed. See license for details. */
X
X/* Ball & Chain =============================================================*/
X
X#include "hack.h"
X
Xstatic int NDECL(bc_order);
Xstatic void NDECL(litter);
X
Xvoid
Xballfall()
X{
X boolean gets_hit;
X
X gets_hit = (((uball->ox != u.ux) || (uball->oy != u.uy)) &&
X ((uwep == uball)? FALSE : (boolean)rn2(5)));
X if (carried(uball)) {
X pline("Startled, you drop the iron ball.");
X if (uwep == uball)
X setuwep((struct obj *)0);
X if (uwep != uball)
X freeinv(uball);
X }
X if(gets_hit){
X int dmg = rn1(7,25);
X pline("The iron ball falls on your %s.",
X body_part(HEAD));
X if (uarmh)
X if(is_metallic(uarmh)) {
X pline("Fortunately, you are wearing a hard helmet.");
X dmg = 3;
X } else if (flags.verbose)
X Your("%s does not protect you.", xname(uarmh));
X losehp(dmg, "Crunched in the head by an iron ball",
X NO_KILLER_PREFIX);
X }
X}
X
X/*
X * To make this work, we have to mess with the hero's mind. The rules for
X * ball&chain are:
X *
X * 1. If the hero can see them, fine.
X * 2. If the hero can't see either, it isn't seen.
X * 3. If either is felt it is seen.
X * 4. If either is felt and moved, it disappears.
X *
X * If the hero can see, then when a move is done, the ball and chain are
X * first picked up, the positions under them are corrected, then they
X * are moved after the hero moves. Not too bad.
X *
X * If the hero is blind, then she can "feel" the ball and/or chain at any
X * time. However, when the hero moves, the felt ball and/or chain become
X * unfelt and whatever was felt "under" the ball&chain appears. Pretty
X * nifty, but it requires that the ball&chain "remember" what was under
X * them --- i.e. they pick-up glyphs when they are felt and drop them when
X * moved (and felt). When swallowed, the ball&chain are pulled completely
X * off of the dungeon, but are still on the object chain. They are placed
X * under the hero when she is expelled.
X */
X
X/*
X * from you.h
X * int u.bglyph glyph under the ball
X * int u.cglyph glyph under the chain
X * int u.bc_felt mask for ball/chain being felt
X * #define BC_BALL 0x01 bit mask in u.bc_felt for ball
X * #define BC_CHAIN 0x02 bit mask in u.bc_felt for chain
X * int u.bc_order ball & chain order
X *
X * u.bc_felt is also manipulated in display.c and read.c, the others only
X * in this file. None of these variables are valid unless the player is
X * Blind.
X */
X
X/* values for u.bc_order */
X#define BCPOS_DIFFER 0 /* ball & chain at different positions */
X#define BCPOS_CHAIN 1 /* chain on top of ball */
X#define BCPOS_BALL 2 /* ball on top of chain */
X
X
X
X/*
X * Place the ball & chain under the hero. Make sure that the ball & chain
X * variables are set (actually only needed when blind, but what the heck).
X * It is assumed that when this is called, the ball and chain are NOT
X * attached to the object list.
X *
X * Should not be called while swallowed.
X */
Xvoid
Xplacebc()
X{
X if (!uchain || !uball) {
X impossible("Where are your ball and chain?");
X return;
X }
X
X (void) flooreffects(uchain, u.ux, u.uy, ""); /* chain might rust */
X uchain->nobj = fobj; /* put chain on object list */
X fobj = uchain;
X
X if (carried(uball)) /* the ball is carried */
X u.bc_order = BCPOS_DIFFER;
X else {
X /* ball might rust -- already checked when carried */
X (void) flooreffects(uball, u.ux, u.uy, "");
X uball->nobj = fobj; /* put ball on object list */
X fobj = uball;
X
X place_object(uball, u.ux, u.uy);
X u.bc_order = BCPOS_CHAIN;
X }
X
X place_object(uchain, u.ux, u.uy);
X
X u.bglyph = u.cglyph = levl[u.ux][u.uy].glyph; /* pick up glyph */
X
X newsym(u.ux,u.uy);
X}
X
Xvoid
Xunplacebc()
X{
X if (u.uswallow) return; /* ball&chain not placed while swallowed */
X
X if (!carried(uball)) {
X freeobj(uball);
X if (Blind && (u.bc_felt & BC_BALL)) /* drop glyph */
X levl[uball->ox][uball->oy].glyph = u.bglyph;
X
X newsym(uball->ox,uball->oy);
X }
X freeobj(uchain);
X if (Blind && (u.bc_felt & BC_CHAIN)) /* drop glyph */
X levl[uchain->ox][uchain->oy].glyph = u.cglyph;
X
X newsym(uchain->ox,uchain->oy);
X u.bc_felt = 0; /* feel nothing */
X}
X
X
X/*
X * Return the stacking of the hero's ball & chain. This assumes that the
X * hero is being punished.
X */
Xstatic int
Xbc_order()
X{
X struct obj *obj;
X
X if (uchain->ox != uball->ox || uchain->oy != uball->oy || carried(uball)
X || u.uswallow)
X return BCPOS_DIFFER;
X
X for (obj = level.objects[uball->ox][uball->oy]; obj; obj = obj->nexthere) {
X if (obj == uchain) return BCPOS_CHAIN;
X if (obj == uball) return BCPOS_BALL;
X }
X impossible("bc_order: ball&chain not in same location!");
X return BCPOS_DIFFER;
X}
X
X/*
X * set_bc()
X *
X * The hero is either about to go blind or already blind and just punished.
X * Set up the ball and chain variables so that the ball and chain are "felt".
X */
Xvoid
Xset_bc(already_blind)
Xint already_blind;
X{
X int ball_on_floor = !carried(uball);
X
X u.bc_order = bc_order(); /* get the order */
X u.bc_felt = ball_on_floor ? BC_BALL|BC_CHAIN : BC_CHAIN; /* felt */
X
X if (already_blind || u.uswallow) {
X u.cglyph = u.bglyph = levl[u.ux][u.uy].glyph;
X return;
X }
X
X /*
X * Since we can still see, remove the ball&chain and get the glyph that
X * would be beneath them. Then put the ball&chain back. This is pretty
X * disgusting, but it will work.
X */
X remove_object(uchain);
X if (ball_on_floor) remove_object(uball);
X
X newsym(uchain->ox, uchain->oy);
X u.cglyph = levl[uchain->ox][uchain->oy].glyph;
X
X if (u.bc_order == BCPOS_DIFFER) { /* different locations */
X place_object(uchain, uchain->ox, uchain->oy);
X newsym(uchain->ox, uchain->oy);
X if (ball_on_floor) {
X newsym(uball->ox, uball->oy); /* see under ball */
X u.bglyph = levl[uball->ox][uball->oy].glyph;
X place_object(uball, uball->ox, uball->oy);
X newsym(uball->ox, uball->oy); /* restore ball */
X }
X } else {
X u.bglyph = u.cglyph;
X if (u.bc_order == BCPOS_CHAIN) {
X place_object(uball, uball->ox, uball->oy);
X place_object(uchain, uchain->ox, uchain->oy);
X } else {
X place_object(uchain, uchain->ox, uchain->oy);
X place_object(uball, uball->ox, uball->oy);
X }
X newsym(uball->ox, uball->oy);
X }
X}
X
X
X/*
X * move_bc()
X *
X * Move the ball and chain. This is called twice for every move. The first
X * time to pick up the ball and chain before the move, the second time to
X * place the ball and chain after the move. If the ball is carried, this
X * function should never have BC_BALL as part of its control.
X *
X * Should not be called while swallowed.
X */
Xvoid
Xmove_bc(before, control, ballx, bally, chainx, chainy)
Xint before, control;
Xxchar ballx, bally, chainx, chainy; /* only matter !before */
X{
X if (Blind) {
X /*
X * The hero is blind. Time to work hard. The ball and chain that
X * are attached to the hero are very special. The hero knows that
X * they are attached, so when they move, the hero knows that they
X * aren't at the last position remembered. This is complicated
X * by the fact that the hero can "feel" the surrounding locations
X * at any time, hence, making one or both of them show up again.
X * So, we have to keep track of which is felt at any one time and
X * act accordingly.
X */
X if (!before) {
X if ((control & BC_CHAIN) && (control & BC_BALL)) {
X /*
X * Both ball and chain moved. If felt, drop glyph.
X */
X if (u.bc_felt & BC_BALL)
X levl[uball->ox][uball->oy].glyph = u.bglyph;
X if (u.bc_felt & BC_CHAIN)
X levl[uchain->ox][uchain->oy].glyph = u.cglyph;
X u.bc_felt = 0;
X
X /* Pick up glyph at new location. */
X u.bglyph = levl[ballx][bally].glyph;
X u.cglyph = levl[chainx][chainy].glyph;
X
X movobj(uball,ballx,bally);
X movobj(uchain,chainx,chainy);
X } else if (control & BC_BALL) {
X if (u.bc_felt & BC_BALL) {
X if (u.bc_order == BCPOS_DIFFER) { /* ball by itself */
X levl[uball->ox][uball->oy].glyph = u.bglyph;
X } else if (u.bc_order == BCPOS_BALL) {
X if (u.bc_felt & BC_CHAIN) { /* know chain is there */
X map_object(uchain, 0);
X } else {
X levl[uball->ox][uball->oy].glyph = u.bglyph;
X }
X }
X u.bc_felt &= ~BC_BALL; /* no longer feel the ball */
X }
X
X /* Pick up glyph at new position. */
X u.bglyph = (ballx != chainx || bally != chainy) ?
X levl[ballx][bally].glyph : u.cglyph;
X
X movobj(uball,ballx,bally);
X } else if (control & BC_CHAIN) {
X if (u.bc_felt & BC_CHAIN) {
X if (u.bc_order == BCPOS_DIFFER) {
X levl[uchain->ox][uchain->oy].glyph = u.cglyph;
X } else if (u.bc_order == BCPOS_CHAIN) {
X if (u.bc_felt & BC_BALL) {
X map_object(uball, 0);
X } else {
X levl[uchain->ox][uchain->oy].glyph = u.cglyph;
X }
X }
X u.bc_felt &= ~BC_CHAIN;
X }
X /* Pick up glyph at new position. */
X u.cglyph = (ballx != chainx || bally != chainy) ?
X levl[chainx][chainy].glyph : u.bglyph;
X
X movobj(uchain,chainx,chainy);
X }
X
X u.bc_order = bc_order(); /* reset the order */
X }
X
X } else {
X /*
X * The hero is not blind. To make this work correctly, we need to
X * pick up the ball and chain before the hero moves, then put them
X * in their new positions after the hero moves.
X */
X if (before) {
X if (!control) {
X /*
X * Neither ball nor chain is moving, so remember which was
X * on top until !before. Use the variable u.bc_order
X * since it is only valid when blind.
X */
X u.bc_order = bc_order();
X }
X
X remove_object(uchain);
X newsym(uchain->ox, uchain->oy);
X if (!carried(uball)) {
X remove_object(uball);
X newsym(uball->ox, uball->oy);
X }
X } else {
X int on_floor = !carried(uball);
X
X if ((control & BC_CHAIN) ||
X (!control && u.bc_order == BCPOS_CHAIN)) {
X /* If the chain moved or nothing moved & chain on top. */
X if (on_floor) place_object(uball, ballx, bally);
X place_object(uchain, chainx, chainy); /* chain on top */
X } else {
X place_object(uchain, chainx, chainy);
X if (on_floor) place_object(uball, ballx, bally);
X /* ball on top */
X }
X newsym(chainx, chainy);
X if (on_floor) newsym(ballx, bally);
X }
X }
X}
X
X/* return TRUE if ball could be dragged
X *
X * Should not be called while swallowed.
X */
Xboolean
Xdrag_ball(x, y, bc_control, ballx, bally, chainx, chainy)
Xxchar x, y;
Xint *bc_control;
Xxchar *ballx, *bally, *chainx, *chainy;
X{
X struct trap *t = (struct trap *)0;
X
X *ballx = uball->ox;
X *bally = uball->oy;
X *chainx = uchain->ox;
X *chainy = uchain->oy;
X *bc_control = 0;
X
X if (dist2(x, y, uchain->ox, uchain->oy) <= 2) { /* nothing moved */
X move_bc(1, *bc_control, *ballx, *bally, *chainx, *chainy);
X return TRUE;
X }
X
X if (carried(uball) || dist2(x, y, uball->ox, uball->oy) < 3 ||
X (uball->ox == uchain->ox && uball->oy == uchain->oy)) {
X *bc_control = BC_CHAIN;
X move_bc(1, *bc_control, *ballx, *bally, *chainx, *chainy);
X *chainx = u.ux;
X *chainy = u.uy;
X return TRUE;
X }
X
X if (near_capacity() > SLT_ENCUMBER) {
X You("cannot %sdrag the heavy iron ball.",
X invent ? "carry all that and also " : "");
X nomul(0);
X return FALSE;
X }
X
X if ((is_pool(uchain->ox, uchain->oy) &&
X /* water not mere continuation of previous water */
X (levl[uchain->ox][uchain->oy].typ == POOL ||
X !is_pool(uball->ox, uball->oy) ||
X levl[uball->ox][uball->oy].typ == POOL))
X || ((t = t_at(uchain->ox, uchain->oy)) &&
X (t->ttyp == PIT ||
X t->ttyp == SPIKED_PIT ||
X t->ttyp == TRAPDOOR)) ) {
X
X if (Levitation) {
X You("feel a tug from the iron ball.");
X if (t) t->tseen = 1;
X } else {
X struct monst *victim;
X
X You("are jerked back by the iron ball!");
X if ((victim = m_at(uchain->ox, uchain->oy)) != 0) {
X int tmp;
X
X tmp = -2 + Luck + find_mac(victim);
X
X if (victim->msleep) {
X victim->msleep = 0;
X tmp += 2;
X }
X if (!victim->mcanmove) {
X tmp += 4;
X if (!rn2(10)) {
X victim->mcanmove = 1;
X victim->mfrozen = 0;
X }
X }
X if (tmp >= rnd(20))
X (void) hmon(victim,uball,1);
X else
X miss(xname(uball), victim);
X
X } /* now check again in case mon died */
X if (!m_at(uchain->ox, uchain->oy)) {
X u.ux = uchain->ox;
X u.uy = uchain->oy;
X newsym(u.ux0, u.uy0);
X }
X nomul(0);
X
X *bc_control = BC_BALL;
X move_bc(1, *bc_control, *ballx, *bally, *chainx, *chainy);
X *ballx = uchain->ox;
X *bally = uchain->oy;
X move_bc(0, *bc_control, *ballx, *bally, *chainx, *chainy);
X spoteffects();
X return FALSE;
X }
X }
X
X *bc_control = BC_BALL|BC_CHAIN;;
X nomul(-2);
X nomovemsg = "";
X
X move_bc(1, *bc_control, *ballx, *bally, *chainx, *chainy);
X *ballx = uchain->ox;
X *bally = uchain->oy;
X *chainx = u.ux;
X *chainy = u.uy;
X return TRUE;
X}
X
X/*
X * drop_ball()
X *
X * The punished hero drops or throws her iron ball. If the hero is
X * blind, we must reset the order and glyph. Check for side effects.
X * This routine expects the ball to be already placed.
X *
X * Should not be called while swallowed.
X */
Xvoid
Xdrop_ball(x, y)
Xxchar x, y;
X{
X if (Blind) {
X u.bc_order = bc_order(); /* get the order */
X /* pick up glyph */
X u.bglyph = (u.bc_order) ? u.cglyph : levl[x][y].glyph;
X }
X
X if (x != u.ux || y != u.uy) {
X struct trap *t;
X const char *pullmsg = "The ball pulls you out of the %s!";
X
X if (u.utrap && u.utraptype != TT_INFLOOR) {
X switch(u.utraptype) {
X case TT_PIT:
X pline(pullmsg, "pit");
X break;
X case TT_WEB:
X pline(pullmsg, "web");
X pline("The web is destroyed!");
X deltrap(t_at(u.ux,u.uy));
X break;
X case TT_LAVA:
X pline(pullmsg, "lava");
X break;
X case TT_BEARTRAP: {
X register long side = rn2(3) ? LEFT_SIDE : RIGHT_SIDE;
X pline(pullmsg, "bear trap");
X Your("%s %s is severely damaged.",
X (side == LEFT_SIDE) ? "left" : "right",
X body_part(LEG));
X set_wounded_legs(side, rn1(1000, 500));
X losehp(2, "leg damage from being pulled out of a bear trap",
X KILLED_BY);
X break;
X }
X }
X u.utrap = 0;
X fill_pit(u.ux, u.uy);
X }
X
X u.ux0 = u.ux;
X u.uy0 = u.uy;
X if (!Levitation && !MON_AT(x, y) && !u.utrap &&
X (is_pool(x, y) ||
X ((t = t_at(x, y)) &&
X (t->ttyp == PIT || t->ttyp == SPIKED_PIT ||
X t->ttyp == TRAPDOOR)))) {
X u.ux = x;
X u.uy = y;
X } else {
X u.ux = x - u.dx;
X u.uy = y - u.dy;
X }
X vision_full_recalc = 1; /* hero has moved, recalculate vision later */
X
X if (Blind) {
X /* drop glyph under the chain */
X if (u.bc_felt & BC_CHAIN)
X levl[uchain->ox][uchain->oy].glyph = u.cglyph;
X u.bc_felt = 0; /* feel nothing */
X /* pick up new glyph */
X u.cglyph = (u.bc_order) ? u.bglyph : levl[u.ux][u.uy].glyph;
X }
X movobj(uchain,u.ux,u.uy); /* has a newsym */
X if (Blind) {
X u.bc_order = bc_order();
X }
X newsym(u.ux0,u.uy0); /* clean up old position */
X spoteffects();
X }
X}
X
X
Xstatic void
Xlitter()
X{
X struct obj *otmp = invent, *nextobj;
X int capacity = weight_cap();
X
X while (otmp) {
X nextobj = otmp->nobj;
X if ((otmp != uball) && (rnd(capacity) <= otmp->owt)) {
X if (otmp == uwep)
X setuwep((struct obj *)0);
X if ((otmp != uwep) && (canletgo(otmp, ""))) {
X Your("%s you down the stairs.",
X aobjnam(otmp, "follow"));
X dropx(otmp);
X }
X }
X otmp = nextobj;
X }
X}
X
Xvoid
Xdrag_down()
X{
X boolean forward;
X uchar dragchance = 3;
X
X /*
X * Assume that the ball falls forward if:
X *
X * a) the character is wielding it, or
X * b) the character has both hands available to hold it (i.e. is
X * not wielding any weapon), or
X * c) (perhaps) it falls forward out of his non-weapon hand
X */
X
X forward = carried(uball) && (uwep == uball || !uwep || !rn2(3));
X
X if (carried(uball))
X You("lose your grip on the iron ball.");
X
X if (forward) {
X if(rn2(6)) {
X pline("The iron ball drags you downstairs!");
X losehp(rnd(6), "dragged downstairs by an iron ball",
X NO_KILLER_PREFIX);
X litter();
X }
X } else {
X if(rn2(2)) {
X pline("The iron ball smacks into you!");
X losehp(rnd(20), "iron ball collision", KILLED_BY_AN);
X exercise(A_STR, FALSE);
X dragchance -= 2;
X }
X if( (int) dragchance >= rnd(6)) {
X pline("The iron ball drags you downstairs!");
X losehp(rnd(3), "dragged downstairs by an iron ball",
X NO_KILLER_PREFIX);
X exercise(A_STR, FALSE);
X litter();
X }
X }
X}
X
X/*ball.c*/
END_OF_FILE
if test 16324 -ne `wc -c <'src/ball.c'`; then
echo shar: \"'src/ball.c'\" unpacked with wrong size!
fi
# end of 'src/ball.c'
if test -f 'sys/mac/mactty.c' -a "${1}" != "-c" ; then
echo shar: Renaming existing file \"'sys/mac/mactty.c'\" to \"'sys/mac/mactty.c.orig'\"
mv -f 'sys/mac/mactty.c' 'sys/mac/mactty.c.orig'
fi
echo shar: Extracting \"'sys/mac/mactty.c'\" \(36517 characters\)
sed "s/^X//" >'sys/mac/mactty.c' <<'END_OF_FILE'
X/* SCCS Id: @(#)mactty.c 3.1 93/03/01 */
X/* Copyright (c) Jon W{tte 1993. */
X/* NetHack may be freely redistributed. See license for details. */
X
X/*
X * mactty.c
X *
X * This file contains the actual code for the tty library. For a
X * description, see the file mactty.h, which contains all you
X * need to know to use the library.
X */
X
X#include "mttypriv.h"
X
X#if PRINTF_TTY
X# include <stdio.h>
X# include <stdarg.h>
X#endif
X
Xextern void dprintf ( char * , ... ) ;
Xstatic void select_onscreen_window ( tty_record * record ) ;
Xstatic void select_offscreen_port ( tty_record * record ) ;
X
X#define MEMORY_MARGIN 30000
X
X
X/*
X * Error code returned when it's probably our fault, or
X * bad parameters.
X */
X#define general_failure 1
X
X/*
X * How long lines do we support for input?
X */
X#define IB_LIMIT 80
X
X/*
X * Convenience macro for most functions - put last in declaration
X */
X#define RECORD(record) \
Xtty_record * record ; \
X if ( ! window ) { \
X dprintf ( "*** NULL Window ***" ) ; \
X return general_failure ; \
X } \
X record = ( tty_record * ) GetWRefCon ( window ) ; \
X if ( ! record ) { \
X return general_failure ; \
X }
X
X/*
X * Simple macro for deciding wether we draw at once or delay
X */
X#define DRAW_DIRECT ( 0L != ( TA_ALWAYS_REFRESH & record -> \
X attribute [ TTY_ATTRIB_FLAGS ] ) )
X
X
X/*
X * Module variable used as return value for various calls.
X */
Xstatic short s_err = 0 ;
X
X/*
X * Table of special characters. Zero is ALWAYS special; it means
X * end of string and would be MISSED if it was not included here.
X */
Xstatic const unsigned char s_cooked_controls [ ] = {
X 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X} ;
X
Xstatic const unsigned char s_raw_controls [ ] = {
X 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X} ;
X
Xstatic const unsigned char * s_control = s_cooked_controls ;
X
X
X/*
X * Memory-related error
X */
Xstatic short
Xmem_err ( void ) {
X if ( MemError ( ) ) {
X return MemError ( ) ;
X }
X return general_failure ;
X}
X
X
X/*
X * Make a rectangle empty
X */
Xstatic void
Xempty_rect ( Rect * r ) {
X
X r -> right = -20000 ;
X r -> left = 20000 ;
X r -> top = 20000 ;
X r -> bottom = -20000 ;
X}
X
X
X/*
X * Union twp rect together
X */
Xstatic void
Xunion_rect ( Rect * r1 , Rect * r2 , Rect * dest ) {
X
X if ( r1 -> left < r2 -> left ) {
X dest -> left = r1 -> left ;
X } else {
X dest -> left = r2 -> left ;
X }
X
X if ( r1 -> top < r2 -> top ) {
X dest -> top = r1 -> top ;
X } else {
X dest -> top = r2 -> top ;
X }
X
X if ( r1 -> bottom > r2 -> bottom ) {
X dest -> bottom = r1 -> bottom ;
X } else {
X dest -> bottom = r2 -> bottom ;
X }
X
X if ( r1 -> right > r2 -> right ) {
X dest -> right = r1 -> right ;
X } else {
X dest -> right = r2 -> right ;
X }
X}
X
X
X/*
X * Dispose a pointer using the set memory-allocator
X */
Xstatic short
Xdispose_ptr ( tty_record * record , void * ptr ) {
Xpascal short ( * func ) ( WindowPtr window , void * ptr ) =
X ( pascal short ( * ) ( WindowPtr , void * ) )
X record -> attribute [ TTY_FREE_MEMORY_FUNCTION ] ;
X
X if ( ! ptr ) {
X return noErr ; /* Silently accept disposing NULLs */
X }
X if ( func ) {
X s_err = ( * func ) ( record -> its_window , ptr ) ;
X } else {
X DisposePtr ( ptr ) ;
X s_err = MemError ( ) ;
X }
X return s_err ;
X}
X
X
X/*
X * Allocate a pointer using the set memory-allocator
X */
Xstatic short
Xalloc_ptr ( tty_record * record , void * * ptr , long size ) {
Xpascal short ( * func ) ( WindowPtr window , void * * ptr , long ) =
X ( pascal short ( * ) ( WindowPtr , void * * , long ) )
X record -> attribute [ TTY_ALLOCATE_MEMORY_FUNCTION ] ;
X
X if ( func ) {
X s_err = ( * func ) ( record -> its_window , ptr , size ) ;
X } else {
X * ptr = NewPtr ( size ) ;
X s_err = * ptr ? noErr : mem_err ( ) ;
X }
X return s_err ;
X}
X
X
X/*
X * Set up a GWorld in the record
X */
Xstatic short
Xallocate_offscreen_world ( tty_record * record ) {
XGWorldPtr gw = NULL ;
XGWorldFlags world_flags = clipPix ;
Xlong mem_here , mem_there , other , required_mem ;
XPoint p = { 0 , 0 } ;
XRect r_screen ;
XGDHandle gdh ;
X
X select_onscreen_window ( record ) ;
X LocalToGlobal ( & p ) ;
X r_screen = record -> its_bits . bounds ;
X OffsetRect ( & r_screen , p . h , p . v ) ;
X
X gdh = GetMaxDevice ( & r_screen ) ;
X required_mem = ( long ) ( * ( ( * gdh ) -> gdPMap ) ) -> pixelSize *
X ( ( long ) record -> its_bits . bounds . right *
X record -> its_bits . bounds . bottom ) >> 3 ;
X
X PurgeSpace ( & other , & mem_here ) ;
X if ( other < mem_here + MEMORY_MARGIN ) {
X mem_here = other - MEMORY_MARGIN ;
X }
X dprintf ( "Heap %ld Required %ld" , mem_here , required_mem ) ;
X if ( required_mem > mem_here ) {
X mem_there = required_mem ;
X if ( required_mem > MFMaxMem ( & mem_there ) ) {
X dprintf ( "No memory" ) ;
X return memFullErr ;
X }
X world_flags |= useTempMem ;
X }
X s_err = NewGWorld ( & gw , 16 , & r_screen , NULL , NULL , world_flags ) ;
X if ( ! s_err ) {
X record -> offscreen_world = gw ;
X select_offscreen_port ( record ) ;
X SetOrigin ( 0 , 0 ) ;
X dprintf ( "New GWorld @ %lx;dm %lx CGrafPtr" , gw , gw ) ;
X }
X return s_err ;
X}
X
X
X/*
X * Done with GWorld, release data
X */
Xstatic short
Xdeallocate_gworld ( tty_record * record ) {
X if ( record -> offscreen_world ) {
X DisposeGWorld ( record -> offscreen_world ) ;
X record -> offscreen_world = NULL ;
X }
X return noErr ;
X}
X
X
X/*
X * Save the current port/world in a safe place for later retrieval
X */
Xstatic void
Xsave_port ( tty_record * record , void * save ) {
XGWorldPtr gw ;
XGDHandle gh ;
XGrafPtr gp ;
X
X if ( record -> uses_gworld ) {
X GetGWorld ( & gw , & gh ) ;
X * ( GWorldPtr * ) save = gw ;
X } else {
X GetPort ( & gp ) ;
X * ( GrafPtr * ) save = gp ;
X }
X}
X
X
X/*
X * Restore current port/world after a save
X */
Xstatic void
Xuse_port ( tty_record * record , void * port ) {
X if ( record -> uses_gworld ) {
X PixMapHandle pix_map ;
X
X SetGWorld ( ( GWorldPtr ) port , NULL ) ;
X if ( port == record -> offscreen_world ) {
X pix_map = GetGWorldPixMap ( record -> offscreen_world ) ;
X if ( pix_map ) {
X LockPixels ( pix_map ) ;
X }
X } else {
X pix_map = GetGWorldPixMap ( record -> offscreen_world ) ;
X if ( pix_map ) {
X UnlockPixels ( pix_map ) ;
X }
X }
X } else {
X SetPort ( ( GrafPtr ) port ) ;
X }
X}
X
X
X/*
X * Use offscreen drawing - lock the pixels through use_port
X */
Xstatic void
Xselect_offscreen_port ( tty_record * record ) {
X if ( record -> uses_gworld ) {
X use_port ( record , record -> offscreen_world ) ;
X } else {
X use_port ( record , record -> offscreen_port ) ;
X }
X}
X
X
X/*
X * Use the window - unlock pixels
X */
Xstatic void
Xselect_onscreen_window ( tty_record * record ) {
X if ( record -> uses_gworld ) {
X use_port ( record , record -> its_window_world ) ;
X SetPort ( record -> its_window ) ;
X } else {
X use_port ( record , record -> its_window ) ;
X }
X}
X
X
X/*
X * Do bits copy depending on if we're using color or not
X */
Xstatic void
Xcopy_bits ( tty_record * record , Rect * bounds , short xfer_mode , RgnHandle mask_rgn ) {
XRGBColor old_fore , old_back ;
XRGBColor rgb_black = { 0 , 0 , 0 } ;
XRGBColor rgb_white = { 0xffff , 0xffff , 0xffff } ;
X
X if ( record -> uses_gworld ) {
X GWorldFlags pix_state = GetPixelsState ( GetGWorldPixMap ( record -> offscreen_world ) ) ;
X
X LockPixels ( GetGWorldPixMap ( record -> offscreen_world ) ) ;
X GetForeColor ( & old_fore ) ;
X GetBackColor ( & old_back ) ;
X RGBForeColor ( & rgb_black ) ;
X RGBBackColor ( & rgb_white ) ;
X CopyBits ( ( BitMap * ) & ( record -> offscreen_world -> portPixMap ) ,
X & ( record -> its_window -> portBits ) , bounds , bounds , xfer_mode ,
X mask_rgn ) ;
X RGBForeColor ( & old_fore ) ;
X RGBBackColor ( & old_back ) ;
X SetPixelsState ( GetGWorldPixMap ( record -> offscreen_world ) , pix_state ) ;
X } else {
X CopyBits ( & ( record -> its_bits ) , & ( record -> its_window -> portBits ) ,
X bounds , bounds , xfer_mode , mask_rgn ) ;
X }
X}
X
X
X/*
X * Fill an area with the background color
X */
Xstatic void
Xerase_rect ( tty_record * record , Rect * area ) {
X#if defined(applec)
X# pragma unused(record)
X#endif
X
X EraseRect ( area ) ;
X}
X
X
X/*
X * Get rid of offscreen bitmap
X */
Xstatic short
Xfree_bits ( tty_record * record ) {
X if ( record -> uses_gworld ) {
X s_err = deallocate_gworld ( record ) ;
X } else {
X if ( record -> offscreen_port ) {
X ClosePort ( record -> offscreen_port ) ;
X s_err = dispose_ptr ( record , record -> offscreen_port ) ;
X if ( ! s_err ) {
X record -> offscreen_port = NULL ;
X } else {
X return s_err ;
X }
X }
X s_err = dispose_ptr ( record , record -> its_bits . baseAddr ) ;
X if ( ! s_err ) {
X record -> its_bits . baseAddr = NULL ;
X }
X }
X return s_err ;
X}
X
X
X/*
X * Snatch a window from the resource fork. Create the record.
X * Otherwise, do nothing.
X */
Xpascal short
Xcreate_tty ( WindowPtr * window , short resource_id , Boolean in_color ) {
Xtty_record * record ;
XBoolean was_allocated = !! * window ;
X
X if ( in_color ) {
X * window = GetNewCWindow ( resource_id , ( Ptr ) * window , ( WindowPtr ) -1L ) ;
X } else {
X * window = GetNewWindow ( resource_id , ( Ptr ) * window , ( WindowPtr ) -1L ) ;
X }
X if ( ! * window ) {
X return mem_err ( ) ;
X }
X
X record = ( tty_record * ) NewPtrClear ( sizeof ( tty_record ) ) ;
X if ( ! record ) {
X if ( was_allocated ) {
X CloseWindow ( * window ) ;
X } else {
X DisposeWindow ( * window ) ;
X }
X return mem_err ( ) ;
X }
X record -> its_window = * window ;
X SetWRefCon ( * window , ( long ) record ) ;
X record -> was_allocated = was_allocated ;
X record -> its_bits . baseAddr = NULL ;
X#if TTY_INPUT
X record -> input_buffer = NULL ;
X#endif
X
X/*
X * Wee need to keep the window world around if we switch worlds
X */
X record -> offscreen_world = NULL ;
X record -> uses_gworld = in_color ;
X if ( in_color ) {
X GDHandle gh ;
X
X SetPort ( * window ) ;
X GetGWorld ( & ( record -> its_window_world ) , & gh ) ;
X } else {
X record -> its_window_world = NULL ;
X }
X
X#if CLIP_RECT_ONLY
X empty_rect ( & ( record -> invalid_rect ) ) ;
X#else
X record -> invalid_part = NewRgn ( ) ;
X if ( ! record -> invalid_part ) {
X short err = mem_err ( ) ;
X
X err = destroy_tty ( * window ) ;
X return err ;
X }
X#endif
X
X return noErr ;
X}
X
X
X/*
X * Initialize the struct so it actually works as a tty.
X */
Xpascal short
Xinit_tty_name ( WindowPtr window , unsigned char * font_name , short font_size ,
X short x_size , short y_size ) {
Xshort font_num = 0 ;
X
X GetFNum ( font_name , & font_num ) ;
X if ( ! font_num ) {
X return general_failure ;
X }
X return init_tty_number ( window , font_num , font_size , x_size , y_size ) ;
X}
X
X
Xpascal short
Xinit_tty_number ( WindowPtr window , short font_number , short font_size ,
X short x_size , short y_size ) {
XRECORD ( record ) ;
X
X record -> font_number = font_number ;
X record -> font_size = font_size ;
X record -> x_size = x_size ;
X record -> y_size = y_size ;
X
X record -> offscreen_port = NULL ;
X record -> attribute [ TTY_ATTRIB_BACKGROUND ] = 0xffffff ; /* White */
X
X#if TTY_INPUT
X record -> input_buffer_len = 0 ;
X record -> input_buffer_limit = IB_LIMIT ;
X s_err = alloc_ptr ( record , & ( record -> input_buffer ) , IB_LIMIT ) ;
X if ( s_err ) {
X return s_err ;
X }
X#endif
X
X return force_tty_coordinate_system_recalc ( window ) ;
X}
X
X
X/*
X * Done with a window - destroy it. Release the memory only if
X * it wasn't allocated when we got it!
X */
Xpascal short
Xdestroy_tty ( WindowPtr window ) {
XBoolean close_flag ;
XRECORD ( record ) ;
X
X s_err = free_bits ( record ) ;
X#if TTY_INPUT
X if ( ! s_err ) {
X s_err = dispose_ptr ( record -> input_buffer ) ;
X if ( ! s_err ) {
X record -> input_buffer = NULL ;
X }
X }
X#endif
X if ( ! s_err ) {
X close_flag = record -> was_allocated ;
X DisposePtr ( ( Ptr ) record ) ;
X s_err = MemError ( ) ;
X if ( close_flag ) {
X CloseWindow ( window ) ;
X } else {
X DisposeWindow ( window ) ;
X }
X }
X
X return s_err ;
X}
X
X
X/*
X * Use a new font for drawing.
X */
Xpascal short
Xset_tty_font_name ( WindowPtr window , unsigned char * font_name ) {
XRECORD ( record ) ;
X
X record -> font_number = 0 ;
X GetFNum ( font_name , & ( record -> font_number ) ) ;
X
X return ! record -> font_number ;
X}
X
X
Xpascal short
Xset_tty_font_number ( WindowPtr window , short font_number ) {
XRECORD ( record ) ;
X
X record -> font_number = font_number ;
X
X return noErr ;
X}
X
X
Xpascal short
Xset_tty_font_size ( WindowPtr window , short font_size ) {
XRECORD ( record ) ;
X
X record -> font_size = font_size ;
X
X return noErr ;
X}
X
X
Xstatic void
Xdo_set_port_font ( tty_record * record ) {
X
X PenNormal ( ) ;
X TextFont ( record -> font_number ) ;
X TextFace ( 0 ) ;
X TextSize ( record -> font_size ) ;
X if ( 0L != ( record -> attribute [ TTY_ATTRIB_FLAGS ] & TA_OVERSTRIKE ) ) {
X TextMode ( srcOr ) ;
X } else {
X TextMode ( srcCopy ) ;
X }
X}
X
X
X/*
X * Fill in some fields from some other fields that may have changed
X */
Xstatic void
Xcalc_font_sizes ( tty_record * record ) {
XFontInfo font_info ;
X
X do_set_port_font ( record ) ;
X
X GetFontInfo ( & font_info ) ;
X record -> char_width = font_info . widMax ;
X record -> ascent_height = font_info . ascent + font_info . leading ;
X record -> row_height = record -> ascent_height + font_info . descent ;
X}
X
X
X/*
X * Allocate memory for the bitmap holding the tty window
X */
Xstatic short
Xalloc_bits ( tty_record * record ) {
Xvoid * old_port ;
X
X save_port ( record , & old_port ) ;
X SetRect ( & record -> its_bits . bounds , 0 , 0 ,
X record -> char_width * record -> x_size ,
X record -> row_height * record -> y_size ) ;
X
X/*
X * Clear two highest and lowest bit - not a color pixMap, and even in size
X */
X record -> its_bits . rowBytes = ( ( record -> its_bits . bounds . right + 15 )
X >> 3 ) & 0x1ffe ;
X
X if ( record -> uses_gworld ) {
X s_err = allocate_offscreen_world ( record ) ;
X } else {
X s_err = alloc_ptr ( record , ( void * * ) & ( record -> its_bits . baseAddr ) ,
X record -> its_bits . rowBytes * record -> its_bits . bounds . bottom ) ;
X if ( ! s_err ) {
X s_err = alloc_ptr ( record , ( void * * ) & ( record -> offscreen_port ) ,
X sizeof ( GrafPort ) ) ;
X }
X if ( ! s_err ) {
X OpenPort ( record -> offscreen_port ) ;
X SetPort ( record -> offscreen_port ) ;
X ClipRect ( & ( record -> its_bits . bounds ) ) ;
X SetPortBits ( & ( record -> its_bits ) ) ;
X }
X }
X use_port ( record , old_port ) ;
X
X return s_err ;
X}
X
X
Xstatic void
Xupdate_offscreen_info ( tty_record * record ) {
X
X select_offscreen_port ( record ) ;
X do_set_port_font ( record ) ;
X}
X
X
X/*
X * Recalculate the window based on new size, font, extent values,
X * and re-allocate the bitmap.
X */
Xpascal short
Xforce_tty_coordinate_system_recalc ( WindowPtr window ) {
XRECORD ( record ) ;
X
X if ( s_err = free_bits ( record ) ) {
X return s_err ;
X }
X select_onscreen_window ( record ) ;
X calc_font_sizes ( record ) ;
X
X if ( s_err = alloc_bits ( record ) ) {
X/*
X * Catastrophe! We could not allocate memory for the bitmap! Things may go very
X * much downhill from here!
X */
X dprintf ( "alloc_bits returned NULL in force_tty_coordinate_system_recalc!" ) ;
X return s_err ;
X }
X
X update_offscreen_info ( record ) ;
X return clear_tty ( window ) ;
X}
X
X
X/*
X * Update TTY according to new color environment for the window
X */
Xpascal short
Xtty_environment_changed ( WindowPtr window ) {
XPoint p = { 0 , 0 } ;
XRect r_screen ;
XRECORD ( record ) ;
X
X if ( record -> uses_gworld ) {
X select_onscreen_window ( record ) ;
X r_screen = record -> its_bits . bounds ;
X LocalToGlobal ( & p ) ;
X OffsetRect ( & r_screen , p . h , p . v ) ;
X UpdateGWorld ( & ( record -> offscreen_world ) , 0 , & r_screen ,
X NULL , NULL , stretchPix ) ;
X select_offscreen_port ( record ) ;
X SetOrigin ( 0 , 0 ) ;
X }
X return s_err ;
X}
X
X
X/*
X * Read a lot of interesting and useful information from the current tty
X */
Xpascal short
Xget_tty_metrics ( WindowPtr window , short * x_size , short * y_size ,
X short * x_size_pixels , short * y_size_pixels , short * font_number ,
X short * font_size , short * char_width , short * row_height ) {
XRECORD ( record ) ;
X
X/*
X * First, test that we actually have something to draw to...
X */
X if ( ( ( NULL == record -> its_bits . baseAddr ) && ! record -> uses_gworld ) ||
X ( ( NULL == record -> offscreen_world ) && record -> uses_gworld ) ) {
X return general_failure ;
X }
X
X * x_size = record -> x_size ;
X * y_size = record -> y_size ;
X * x_size_pixels = record -> its_bits . bounds . right ;
X * y_size_pixels = record -> its_bits . bounds . bottom ;
X * font_number = record -> font_number ;
X * font_size = record -> font_size ;
X * char_width = record -> char_width ;
X * row_height = record -> row_height ;
X
X return noErr ;
X}
X
X
X/*
X * Map a position on the map to screen coordinates
X */
Xstatic void
Xpos_rect ( tty_record * record , Rect * r , short x_pos , short y_pos ,
X short x_end , short y_end ) {
X
X SetRect ( r , x_pos * ( record -> char_width ) , y_pos * ( record -> row_height ) ,
X ( 1 + x_end ) * ( record -> char_width ) , ( 1 + y_end ) *
X ( record -> row_height ) ) ;
X}
X
X
Xstatic void
Xaccumulate_rect ( tty_record * record , Rect * rect ) {
X#if CLIP_RECT_ONLY
X union_rect ( rect , & ( record -> invalid_rect ) , & ( record -> invalid_rect ) ) ;
X#else
XRgnHandle rh = NewRgn ( ) ;
X
X RectRgn ( rh , rect ) ;
X UnionRgn ( record -> invalid_part , rh , record -> invalid_part ) ;
X DisposeRgn ( rh ) ;
X#endif
X}
X
X
X/*
X * Invert the specified position
X */
Xstatic void
Xcurs_pos ( tty_record * record , short x_pos , short y_pos , short to_state ) {
XRect r ;
X
X if ( record -> curs_state == to_state ) {
X return ;
X }
X record -> curs_state = to_state ;
X pos_rect ( record , & r , x_pos , y_pos , x_pos , y_pos ) ;
X
X if ( DRAW_DIRECT ) {
X void * old_port ;
X
X save_port ( record , & old_port ) ;
X select_onscreen_window ( record ) ;
X InvertRect ( & r ) ;
X use_port ( record , old_port ) ;
X } else {
X accumulate_rect ( record , & r ) ;
X }
X}
X
X
X/*
X * Move the cursor (both as displayed and where drawing goes)
X * HOWEVER: The cursor is NOT stored in the bitmap!
X */
Xpascal short
Xmove_tty_cursor ( WindowPtr window , short x_pos , short y_pos ) {
XRECORD ( record ) ;
X
X select_onscreen_window ( record ) ;
X if ( record -> x_curs == x_pos && record -> y_curs == y_pos ) {
X return noErr ;
X }
X if ( record -> x_size <= x_pos || x_pos < 0 ||
X record -> y_size <= y_pos || y_pos < 0 ) {
X return general_failure ;
X }
X curs_pos ( record , record -> x_curs , record -> y_curs , 0 ) ;
X record -> x_curs = x_pos ;
X record -> y_curs = y_pos ;
X curs_pos ( record , x_pos , y_pos , 1 ) ;
X
X return noErr ;
X}
X
X
X/*
X * Get the current cursor position. Note that the cursor may not be
X * displayed there yet; it depends on wether you've called update_tty()
X * or have the window in TA_ALWAYS_REFRESH mode.
X */
Xpascal short
Xget_tty_cursor ( WindowPtr window , short * x_pos , short * y_pos ) {
XRECORD ( record ) ;
X
X * x_pos = record -> x_curs ;
X * y_pos = record -> y_curs ;
X
X return noErr ;
X}
X
X
X/*
X * Update the screen to match the current bitmap, after adding stuff
X * with add_tty_char etc.
X */
Xpascal short
Xupdate_tty ( WindowPtr window ) {
XRect r ;
XRECORD ( record ) ;
X
X#if CLIP_RECT_ONLY
X if ( record -> invalid_rect . right <= record -> invalid_rect . left ||
X record -> invalid_rect . bottom <= record -> invalid_rect . top ) {
X return noErr ;
X }
X r = record -> invalid_rect ;
X#else
X if ( EmptyRgn ( record -> invalid_part ) ) {
X return noErr ;
X }
X r = ( * ( record -> invalid_part ) ) -> rgnBBox ;
X#endif
X select_onscreen_window ( record ) ;
X#if CLIP_RECT_ONLY
X copy_bits ( record , & r , srcCopy , NULL ) ;
X empty_rect ( & ( record -> invalid_rect ) ) ;
X#else
X copy_bits ( record , & r , srcCopy , NULL ) ;
X SetEmptyRgn ( record -> invalid_part ) ;
X#endif
X if ( record -> curs_state ) {
X
X pos_rect ( record , & r , record -> x_curs , record -> y_curs ,
X record -> x_curs , record -> y_curs ) ;
X InvertRect ( & r ) ;
X }
X
X return noErr ;
X}
X
X
X/*
X * Add a single character. It is drawn directly if the correct flag is set,
X * else deferred to the next update event or call of update_tty()
X */
Xpascal short
Xadd_tty_char ( WindowPtr window , short character ) {
Xchar s [ 2 ] ;
X
X s [ 0 ] = character ;
X s [ 1 ] = 0 ;
X return add_tty_string ( window , s ) ;
X}
X
X
X/*
X * Low level add to screen
X */
Xstatic void
Xdo_add_string ( tty_record * record , char * str , short len ) {
XRect r ;
Xregister int x_pos , count = len ;
X
X if ( len < 1 ) {
X return ;
X }
X select_offscreen_port ( record ) ;
X
X if ( 0L != ( record -> attribute [ TTY_ATTRIB_FLAGS ] & TA_MOVE_EACH_CHAR ) ) {
X x_pos = record -> x_curs ;
X while ( count -- ) {
X MoveTo ( x_pos * record -> char_width , record -> y_curs *
X record -> row_height + record -> ascent_height ) ;
X DrawChar ( * ( str ++ ) ) ;
X }
X } else {
X MoveTo ( record -> x_curs * record -> char_width , record -> y_curs *
X record -> row_height + record -> ascent_height ) ;
X DrawText ( str , 0 , len ) ;
X }
X
X pos_rect ( record , & r , record -> x_curs , record -> y_curs ,
X record -> x_curs + len - 1 , record -> y_curs ) ;
X if ( DRAW_DIRECT ) {
X select_onscreen_window ( record ) ;
X copy_bits ( record , & r , srcCopy , NULL ) ;
X } else {
X accumulate_rect ( record , & r ) ;
X }
X}
X
X
X/*
X * Low-level cursor handling routine
X */
Xstatic void
Xdo_add_cursor ( tty_record * record , short x_pos ) {
X
X record -> x_curs = x_pos ;
X if ( record -> x_curs >= record -> x_size ) {
X if ( 0L != ( record -> attribute [ TTY_ATTRIB_FLAGS ] & TA_WRAP_AROUND ) ) {
X record -> y_curs ++ ;
X record -> x_curs = 0 ;
X if ( record -> y_curs >= record -> y_size ) {
X if ( 0L != ( record -> attribute [ TTY_ATTRIB_FLAGS ] &
X TA_INHIBIT_VERT_SCROLL ) ) {
X record -> y_curs = record -> y_size ;
X } else {
X scroll_tty ( record -> its_window , 0 , 1 + record -> y_curs -
X record -> y_size ) ;
X }
X }
X } else {
X record -> x_curs = record -> x_size ;
X }
X }
X}
X
X
X/*
X * Beep
X */
Xstatic void
Xdo_tty_beep ( tty_record * record ) {
X if ( record -> attribute [ TTY_BEEP_FUNCTION ] ) {
X pascal void ( * tty_beep ) ( WindowPtr ) = ( pascal void ( * ) ( WindowPtr ) )
X record -> attribute [ TTY_BEEP_FUNCTION ] ;
X ( * tty_beep ) ( record -> its_window ) ;
X } else {
X SysBeep ( 20 ) ;
X }
X}
X
X
X/*
X * Do control character
X */
Xstatic void
Xdo_control ( tty_record * record , short character ) {
Xstatic int recurse = 0 ;
X
X/*
X * Check recursion because nl_add_cr and cr_add_nl may both be set and call each other
X */
X recurse ++ ;
X if ( recurse > 2 ) {
X return ;
X }
X switch ( character ) {
X case 10 :
X record -> y_curs ++ ;
X if ( record -> y_curs >= record -> y_size ) {
X scroll_tty ( record -> its_window , 0 , 1 + record -> y_curs -
X record -> y_size ) ;
X }
X if ( 0L != ( record -> attribute [ TTY_ATTRIB_CURSOR ] & TA_NL_ADD_CR ) ) {
X do_control ( record , 13 ) ;
X }
X break ;
X case 13 :
X record -> x_curs = 0 ;
X if ( 0L != ( record -> attribute [ TTY_ATTRIB_CURSOR ] & TA_CR_ADD_NL ) ) {
X do_control ( record , 10 ) ;
X }
X break ;
X case 7 :
X do_tty_beep ( record ) ;
X break ;
X case 8 :
X if ( record -> x_curs > 0 ) {
X record -> x_curs -- ;
X }
X break ;
X default :
X break ;
X }
X recurse -- ;
X}
X
X
X/*
X * Add a null-terminated string of characters
X */
Xpascal short
Xadd_tty_string ( WindowPtr window , const char * string ) {
Xregister const unsigned char * start_c ;
Xregister const unsigned char * the_c ;
Xregister short max_x , pos_x ;
XRECORD ( record ) ;
X
X select_onscreen_window ( record ) ;
X curs_pos ( record , record -> x_curs , record -> y_curs , 0 ) ;
X
X the_c = ( const unsigned char * ) string ;
X max_x = record -> x_size ;
X while ( 1 ) {
X start_c = the_c ;
X pos_x = record -> x_curs ;
X if ( ( 0L == ( record -> attribute [ TTY_ATTRIB_FLAGS ] & TA_WRAP_AROUND ) ) &&
X pos_x >= max_x ) { /* Optimize away drawing across border without wrap */
X break ;
X }
X while ( pos_x < max_x && ! s_control [ * the_c ] ) {
X the_c ++ ;
X pos_x ++ ;
X }
X do_add_string ( record , ( char * ) start_c , the_c - start_c ) ;
X do_add_cursor ( record , pos_x ) ;
X if ( ! * the_c ) {
X break ;
X }
X if ( s_control [ * the_c ] ) {
X do_control ( record , * the_c ) ;
X the_c ++ ;
X }
X }
X select_onscreen_window ( record ) ;
X curs_pos ( record , record -> x_curs , record -> y_curs , 1 ) ;
X
X ShowWindow ( window ) ;
X
X return noErr ;
X}
X
X
X/*
X * Do a c-style printf - the result shouldn't be too long...
X */
Xshort
Xprintf_tty ( WindowPtr window , const char * fmt , ... ) {
Xstatic char buf [ 256 ] ;
Xva_list list ;
X
X va_start ( list , fmt ) ;
X vsprintf ( buf , fmt , list ) ;
X va_end ( list ) ;
X
X return add_tty_string ( window , buf ) ;
X}
X
X
X/*
X * Read or change attributes for the tty. Note that some attribs may
X * very well clear and reallocate the bitmap when changed, whereas
X * others (color, highlight, ...) are guaranteed not to.
X */
Xpascal short
Xget_tty_attrib ( WindowPtr window , tty_attrib attrib , long * value ) {
XRECORD ( record ) ;
X
X if ( attrib < 0 || attrib >= TTY_NUMBER_ATTRIBUTES ) {
X return general_failure ;
X }
X * value = record -> attribute [ attrib ] ;
X
X return noErr ;
X}
X
X
Xpascal short
Xset_tty_attrib ( WindowPtr window , tty_attrib attrib , long value ) {
Xlong old_value ;
XRGBColor rgb_color ;
XRECORD ( record ) ;
X
X if ( attrib < 0 || attrib >= TTY_NUMBER_ATTRIBUTES ) {
X return general_failure ;
X }
X old_value = record -> attribute [ attrib ] ;
X if ( old_value == value ) {
X return noErr ;
X }
X record -> attribute [ attrib ] = value ;
X /*
X * Presently, no attributes generate a new bitmap.
X */
X switch ( attrib ) {
X case TTY_ATTRIB_CURSOR :
X/*
X * Check if we should change tables
X */
X if ( 0L != ( value & TA_RAW_OUTPUT ) ) {
X s_control = s_raw_controls ;
X } else {
X s_control = s_cooked_controls ;
X }
X break ;
X case TTY_ATTRIB_FLAGS :
X/*
X * Check if we should flush the output going from cached to draw-direct
X */
X if ( 0L != ( value & TA_ALWAYS_REFRESH ) ) {
X update_tty ( window ) ;
X }
X break ;
X case TTY_ATTRIB_FOREGROUND :
X/*
X * Set foreground color
X */
X TA_TO_RGB ( value , rgb_color ) ;
X select_offscreen_port ( record ) ;
X RGBForeColor ( & rgb_color ) ;
X select_onscreen_window ( record ) ;
X RGBForeColor ( & rgb_color ) ;
X break ;
X case TTY_ATTRIB_BACKGROUND :
X/*
X * Set background color
X */
X TA_TO_RGB ( value , rgb_color ) ;
X select_offscreen_port ( record ) ;
X RGBBackColor ( & rgb_color ) ;
X select_onscreen_window ( record ) ;
X RGBBackColor ( & rgb_color ) ;
X break ;
X default :
X break ;
X }
X return noErr ;
X}
X
X
X/*
X * Scroll the window. Positive is up/left. scroll_tty ( window , 0 , 1 ) is a line feed.
X * Scroll flushes the accumulated update area by calling update_tty().
X */
Xpascal short
Xscroll_tty ( WindowPtr window , short delta_x , short delta_y ) {
XRgnHandle rgn ;
XRECORD ( record ) ;
X
X select_onscreen_window ( record ) ;
X s_err = update_tty ( window ) ;
X
X rgn = NewRgn ( ) ;
X
X select_offscreen_port ( record ) ;
X ScrollRect ( & ( record -> its_bits . bounds ) , - delta_x * record -> char_width ,
X - delta_y * record -> row_height , rgn ) ;
X EraseRgn ( rgn ) ;
X SetEmptyRgn ( rgn ) ;
X
X select_onscreen_window ( record ) ;
X ScrollRect ( & ( record -> its_bits . bounds ) , - delta_x * record -> char_width ,
X - delta_y * record -> row_height , rgn ) ;
X EraseRgn ( rgn ) ;
X DisposeRgn ( rgn ) ;
X
X record -> y_curs -= delta_y ;
X record -> x_curs -= delta_x ;
X
X return noErr ;
X}
X
X
X/*
X * Clear the screen. Immediate.
X */
Xpascal short
Xclear_tty ( WindowPtr window ) {
XRECORD ( record ) ;
X
X select_offscreen_port ( record ) ;
X erase_rect ( record , & ( record -> its_bits . bounds ) ) ;
X select_onscreen_window ( record ) ;
X curs_pos ( record , record -> x_curs , record -> y_curs , 0 ) ;
X erase_rect ( record , & ( record -> its_bits . bounds ) ) ;
X#if CLIP_RECT_ONLY
X empty_rect ( & ( record -> invalid_rect ) ) ;
X#else
X SetEmptyRgn ( record -> invalid_part ) ;
X#endif
X curs_pos ( record , record -> x_curs , record -> y_curs , 1 ) ;
X
X return noErr ;
X}
X
X
X/*
X * Resize the area - clears and reallocates the bitmap.
X */
Xpascal short
Xresize_tty_area ( WindowPtr window , short x_size , short y_size ) {
XRECORD ( record ) ;
X
X record -> x_size = x_size ;
X record -> y_size = y_size ;
X
X return force_tty_coordinate_system_recalc ( window ) ;
X}
X
X
X/*
X * Echo to the user if echo mode on
X */
Xstatic void
Xdo_add_input_character ( tty_record * record , unsigned char character ) {
X if ( 0L != ( record -> attribute [ TTY_ATTRIB_CURSOR ] & TA_ECHO_INPUT ) ) {
X add_tty_char ( record -> its_window , character ) ;
X }
X}
X
X
X#if TTY_INPUT
X/*
X * Add a key in the queue.
X */
Xstatic short
Xdo_add_key ( tty_record * record , long message ) {
X if ( record -> input_buffer_len >= record -> input_buffer_limit ) {
X do_tty_beep ( record ) ;
X return general_failure ;
X } else {
X/*
X * If input is cooked, we should fix up this here line to allow line editting...
X */
X record -> input_buffer [ record -> input_buffer_len ++ ] = message & 0xff ;
X do_add_input_character ( record , message & 0xff ) ;
X return noErr ;
X }
X}
X#endif
X
X
X/*
X * Add a key in the queue.
X */
Xstatic short
Xdo_cmd_key ( tty_record * record , EventRecord * event ) {
X pascal void ( * callback ) ( EventRecord * event , WindowPtr window ) =
X ( pascal void ( * ) ( EventRecord * , WindowPtr ) )
X record -> attribute [ TTY_COMMAND_KEY_CALLBACK ] ;
X
X if ( callback ) {
X ( * callback ) ( event , record -> its_window ) ;
X return noErr ;
X }
X return general_failure ;
X}
X
X
X/*
X * Handle a tty event:
X * Updates, pertaining to our window.
X * Key downs, entered into the queue (if we are frontmost)
X */
Xpascal short
Xhandle_tty_event ( WindowPtr window , EventRecord * event ) {
XRECORD ( record ) ;
X
X update_tty ( window ) ;
X
X if ( 0L != ( record -> attribute [ TTY_ATTRIB_CURSOR ] & TA_BLINKING_CURSOR ) ) {
X if ( event -> when > record -> last_cursor + GetCaretTime ( ) ) {
X curs_pos ( record , record -> x_curs , record -> y_curs ,
X ! record -> curs_state ) ;
X record -> last_cursor = event -> when ;
X }
X }
X
X switch ( event -> what ) {
X case updateEvt :
X if ( event -> message == ( long ) window ) {
X BeginUpdate ( window ) ;
X erase_rect ( record , & ( record -> its_bits . bounds ) ) ;
X tty_environment_changed ( window ) ;
X s_err = image_tty ( window ) ;
X EndUpdate ( window ) ;
X return s_err ;
X }
X break ;
X#if TTY_INPUT
X case keyDown :
X case autoKey :
X if ( FrontWindow ( ) == window ) {
X if ( event -> modifiers & cmdKey ) {
X return do_cmd_key ( record , event ) ;
X } else {
X return do_add_key ( record , event -> message ) ;
X }
X }
X break ;
X#endif
X deafult :
X break ;
X }
X
X return general_failure ;
X}
X
X
X/*
X * Draw an image of the tty - used for update events and can be called
X * for screen dumps.
X */
Xpascal short
Ximage_tty ( WindowPtr window ) {
XRect r ;
XRECORD ( record ) ;
X
X select_onscreen_window ( record ) ;
X copy_bits ( record , & ( record -> its_bits . bounds ) , srcCopy , NULL ) ;
X if ( record -> curs_state ) {
X
X pos_rect ( record , & r , record -> x_curs , record -> y_curs ,
X record -> x_curs , record -> y_curs ) ;
X InvertRect ( & r ) ;
X }
X
X return noErr ;
X}
X
X
X#if TTY_INPUT
X
X/*
X * Read a character depending on the input mode
X */
Xpascal short
Xgetchar_tty ( WindowPtr window , short * character ) {
XRECORD ( record ) ;
X
X if ( 0L != ( record -> attribute [ TTY_ATTRIB_CURSOR ] & TA_RAW_INPUT ) ) {
X while ( ! record -> input_buffer_len ) {
X EventRecord er ;
X
X WaitNextEvent ( -1 , & er , GetCaretTime ( ) , NULL ) ;
X if ( handle_tty_event ( window , & er ) ) {
X switch ( er . what ) {
X default :
X break ;
X }
X }
X }
X * character =
X } else {
X
X }
X}
X
X#endif /* TTY_INPUT */
X
X#if EXTENDED_SUPPORT
X/*
X * Delete or insert operations used by many terminals can bottleneck through
X * here. Note that the order of executin for row/colum insertions is NOT
X * specified. Negative values for num_ mean delete, zero means no effect.
X */
Xpascal short
Xmangle_tty_rows_columns ( WindowPtr window , short from_row , short num_rows ,
X short from_column , short num_columns ) {
XRect r ;
XRgnHandle rh = NewRgn ( ) ;
XRECORD ( record ) ;
X
X update_tty ( window ) ; /* Always make sure screen is OK */
X curs_pos ( record , record -> x_curs , record -> y_curs , 0 ) ;
X
X if ( num_rows ) {
X pos_rect ( record , & r , 0 , from_row , record -> x_size - 1 ,
X record -> y_size - 1 ) ;
X select_offscreen_port ( record ) ;
X ScrollRect ( & r , 0 , num_rows * record -> row_height , rh ) ;
X EraseRgn ( rh ) ;
X SetEmptyRgn ( rh ) ;
X select_onscreen_window ( record ) ;
X ScrollRect ( & r , 0 , num_rows * record -> row_height , rh ) ;
X EraseRgn ( rh ) ;
X SetEmptyRgn ( rh ) ;
X }
X if ( num_columns ) {
X pos_rect ( record , & r , from_column , 0 , record -> x_size - 1 ,
X record -> y_size - 1 ) ;
X select_offscreen_port ( record ) ;
X ScrollRect ( & r , num_columns * record -> char_width , 0 , rh ) ;
X EraseRgn ( rh ) ;
X SetEmptyRgn ( rh ) ;
X select_onscreen_window ( record ) ;
X ScrollRect ( & r , num_columns * record -> char_width , 0 , rh ) ;
X EraseRgn ( rh ) ;
X SetEmptyRgn ( rh ) ;
X }
X DisposeRgn ( rh ) ;
X if ( record -> x_curs >= from_column ) {
X record -> x_curs += num_columns ;
X }
X if ( record -> y_curs >= from_row ) {
X record -> y_curs += num_rows ;
X }
X curs_pos ( record , record -> x_curs , record -> y_curs , 1 ) ;
X
X return noErr ;
X}
X
X
X/*
X * Clear an area
X */
Xpascal short
Xclear_tty_window ( WindowPtr window , short from_x , short from_y ,
X short to_x , short to_y ) {
XRect r ;
XRECORD ( record ) ;
X
X if ( from_x > to_x || from_y > to_y ) {
X return general_failure ;
X }
X pos_rect ( record , & r , from_x , from_y , to_x , to_y ) ;
X select_offscreen_port ( record ) ;
X erase_rect ( record , & r ) ;
X accumulate_rect ( record , & r ) ;
X if ( DRAW_DIRECT ) {
X update_tty ( window ) ;
X }
X}
X
X
X/*
X * Frame an area in an aesthetically pleasing way.
X */
Xpascal short
Xframe_tty_window ( WindowPtr window , short from_x , short from_y ,
X short to_x , short to_y , short frame_fatness ) {
XRect r ;
XRECORD ( record ) ;
X
X if ( from_x > to_x || from_y > to_y ) {
X return general_failure ;
X }
X pos_rect ( record , & r , from_x , from_y , to_x , to_y ) ;
X select_offscreen_port ( record ) ;
X PenSize ( frame_fatness , frame_fatness ) ;
X FrameRect ( & r ) ;
X PenNormal ( ) ;
X accumulate_rect ( record , & r ) ;
X if ( DRAW_DIRECT ) {
X update_tty ( window ) ;
X }
X}
X
X
X/*
X * Highlighting a specific part of the tty window
X */
Xpascal short
Xinvert_tty_window ( WindowPtr window , short from_x , short from_y ,
X short to_x , short to_y ) {
XRect r ;
XRECORD ( record ) ;
X
X if ( from_x > to_x || from_y > to_y ) {
X return general_failure ;
X }
X pos_rect ( record , & r , from_x , from_y , to_x , to_y ) ;
X select_offscreen_port ( record ) ;
X InvertRect ( & r ) ;
X accumulate_rect ( record , & r ) ;
X if ( DRAW_DIRECT ) {
X update_tty ( window ) ;
X }
X}
X
X
Xstatic void
Xcanonical_rect ( Rect * r , short x1 , short y1 , short x2 , short y2 ) {
X if ( x1 < x2 ) {
X if ( y1 < y2 ) {
X SetRect ( r , x1 , x2 , y1 , y2 ) ;
X } else {
X SetRect ( r , x1 , x2 , y2 , y1 ) ;
X }
X } else {
X if ( y1 < y2 ) {
X SetRect ( r , x2 , x1 , y1 , y2 ) ;
X } else {
X SetRect ( r , x2 , x1 , y2 , y1 ) ;
X }
X }
X}
X
X
X/*
X * Line drawing - very device dependent
X */
Xpascal short
Xdraw_tty_line ( WindowPtr window , short from_x , short from_y ,
X short to_x , short to_y ) {
XRect r ;
XRECORD ( record ) ;
X
X select_offscreen_port ( record ) ;
X MoveTo ( from_x , from_y ) ;
X LineTo ( to_x , to_y ) ;
X canonical_rect ( & r , from_x , from_y , to_x , to_y ) ;
X accumulate_rect ( record , & r ) ;
X if ( DRAW_DIRECT ) {
X update_tty ( window ) ;
X }
X}
X
X
X#endif /* EXTENDED_SUPPORT */
END_OF_FILE
if test 36517 -ne `wc -c <'sys/mac/mactty.c'`; then
echo shar: \"'sys/mac/mactty.c'\" unpacked with wrong size!
fi
# end of 'sys/mac/mactty.c'
echo shar: End of archive 23 \(of 33\).
cp /dev/null ark23isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 33 archives.
echo "Now execute ./patchit.sh"
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