home *** CD-ROM | disk | FTP | other *** search
- From: guido@cwi.nl (Guido van Rossum)
- Newsgroups: alt.sources
- Subject: STDWIN 0.9.5, Part 05/19
- Message-ID: <3069@charon.cwi.nl>
- Date: 4 Mar 91 11:57:45 GMT
-
- Archive-name: stdwin/part05
-
- #! /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 5 (of 19)."
- # Contents: Appls/klok/klok.c Conf/proto.os.bsd Ports/alfa/menu.c
- # Ports/msdos/ptrm.c
- # Wrapped by guido@voorn.cwi.nl on Mon Mar 4 12:37:24 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'Appls/klok/klok.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Appls/klok/klok.c'\"
- else
- echo shar: Extracting \"'Appls/klok/klok.c'\" \(17064 characters\)
- sed "s/^X//" >'Appls/klok/klok.c' <<'END_OF_FILE'
- X/* Analog clock with alarm.
- X
- X Displays the date at the top, a circular clock in the middle,
- X and the alarm time at the bottom of the window.
- X The clock has two hands.
- X
- X Resizing the window recomputes the items' positions and sizes.
- X
- X When the alarm goes off, the clock window is made current,
- X the clock face is inverted for 5 minutes, and a beep is emitted
- X each minute. The alarm can be acknowledged explicitly, which
- X silences it until the next time the alarm goes off.
- X
- X Dragging the hands of the clock can be used to set the time
- X (and the date, if you care to drag around several times).
- X The alarm is currently set through a dialog only.
- X
- X TO DO:
- X - make the display prettier (how??? everything I design gets ugly :-( )
- X - display alarm time as tick mark?
- X - improve the alarm setting procedure
- X - add more general 'nag' and 'calendar'-like facilities
- X - add a button to allow/disallow setting the time
- X - add a way to change the date directly
- X - turn it into a subroutine package like VT or editwin
- X - organize the code top-down instead of bottom-up
- X*/
- X
- X#include "tools.h"
- X#include "stdwin.h"
- X
- X#include <ctype.h>
- X#include <math.h>
- X#include <time.h>
- X#include <sys/types.h> /* For time_t, on some systems */
- X
- X#ifndef PI
- X#define PI 3.14159265359
- X#endif
- X
- X/* Alarm parametrizations */
- X
- X#ifndef DEF_ALARM
- X#define DEF_ALARM -1 /* Initial setting of alarm */
- X#endif
- X#ifndef ALARMTIME
- X#define ALARMTIME 5 /* Alarm goes for this many minutes */
- X#endif
- X
- X/* Relative hand sizes */
- X
- X#define LITPERC 60 /* Little hand size (percent of radius) */
- X#define BIGPERC 80 /* Big hand size */
- X#define SECPERC 100 /* Seconds hand size */
- X
- X/* Menu items */
- X
- X#define SETALARM 0
- X#define CLEARALARM 1
- X#define OKALARM 2
- X#define SECONDSHAND 4
- X#define QUIT 6
- X
- X/* Global variables */
- X
- Xchar *progname = "klok"; /* Program name (for error messages) */
- Xchar *title; /* Menu title (default capitalized progname) */
- XWINDOW *win; /* Clock window */
- XMENU *mp; /* Menu pointer */
- Xint centh, centv; /* Clock center */
- Xint radius; /* Clock radius */
- Xstruct tm curtime; /* Current time/date */
- Xint alarm = DEF_ALARM; /* Alarm time (hh*60 + mm); -1 if off */
- Xbool alarmed; /* Is it alarm time? */
- Xbool okayed; /* Has the current alarm been OK'ed? */
- Xbool excited; /* == (alarmed && !okayed) */
- Xbool do_seconds; /* Set if drawing 'seconds' hand */
- X
- X/* Force a redraw of the entire window */
- X
- Xchangeall()
- X{
- X wchange(win, 0, 0, 10000, 10000);
- X}
- X
- X/* Compute the sine of an angle given in clock units
- X (zero at 12 o'clock, full circle is 60).
- X We cache the sine values in a table,
- X since calling sin is too slow on some systems. */
- X
- Xdouble
- Xsine(i)
- X int i;
- X{
- X static double sines[15+1];
- X static bool inited;
- X
- X if (!inited) {
- X int k;
- X inited = TRUE;
- X for (k = 0; k <= 15; ++k)
- X sines[k] = sin(k * PI/30);
- X }
- X i = i % 60;
- X if (i < 0)
- X i += 60;
- X if (i <= 15)
- X return sines[i];
- X if (i <= 30)
- X return sines[30-i];
- X if (i <= 45)
- X return -sines[i-30];
- X return -sines[60-i];
- X}
- X
- X/* Compute the cosine (from the sine) */
- X
- Xdouble
- Xcosine(i)
- X int i;
- X{
- X return sine(i+15);
- X}
- X
- X/* Compute the absolute position of the endpoint of a line drawn at
- X i minutes, whose length is a certain percentage of the radius */
- X
- Xvoid
- Xendpoint(i, perc, ph, pv)
- X int i; /* Minutes */
- X int perc; /* Percentage of length */
- X int *ph, *pv; /* Return values */
- X{
- X double s = sine(i), c = cosine(i);
- X
- X *ph = centh + s*perc*radius/100 + 0.5;
- X *pv = centv - c*perc*radius/100 + 0.5;
- X}
- X
- X/* Draw a mark at i minutes.
- X Marks at hour positions are longer, every 3 hours even longer. */
- X
- Xvoid
- Xdrawmark(i)
- X int i;
- X{
- X int begh, begv;
- X int endh, endv;
- X int len;
- X
- X endpoint(i, 100, &endh, &endv);
- X if (i % 5 != 0)
- X len = 3;
- X else if (i % 15 != 0)
- X len = 8;
- X else
- X len = 19;
- X endpoint(i, 100-len, &begh, &begv);
- X wdrawline(begh, begv, endh, endv);
- X}
- X
- X/* Draw a hand at i minutes, whose length is a given percentage
- X of the radius */
- X
- Xvoid
- Xdrawhand(i, perc)
- X int i;
- X int perc;
- X{
- X int endh, endv;
- X endpoint(i, perc, &endh, &endv);
- X wdrawline(centh, centv, endh, endv);
- X}
- X
- X/* Draw a hand in XOR mode */
- X
- Xvoid
- Xxorhand(i, perc)
- X int i;
- X int perc;
- X{
- X int endh, endv;
- X endpoint(i, perc, &endh, &endv);
- X wxorline(centh, centv, endh, endv);
- X}
- X
- X/* Draw the date in the top left corner */
- X
- Xvoid
- Xdrawdate(tp)
- X struct tm *tp;
- X{
- X char buf[100];
- X
- X sprintf(buf, "%02d/%02d/%02d", tp->tm_year % 100,
- X tp->tm_mon+1, tp->tm_mday);
- X werase(0, 0, 10000, centv - radius);
- X wdrawtext(0, centv - radius - wlineheight(), buf, -1);
- X}
- X
- X/* Draw the alarm time in the bottom left corner */
- X
- Xvoid
- Xdrawalarm()
- X{
- X char buf[100];
- X
- X sprintf(buf, "*%02d:%02d", alarm/60, alarm%60);
- X wdrawtext(0, centv + radius, buf, -1);
- X}
- X
- X/* Compute the AM/MP/Noon/Midnight indicator character */
- X
- Xint
- Xampm(tp)
- X struct tm *tp;
- X{
- X if (tp->tm_min == 0 && tp->tm_hour%12 == 0) {
- X if (tp->tm_hour == 12)
- X return 'N';
- X else
- X return 'M';
- X }
- X else if (tp->tm_hour < 12)
- X return 'A';
- X else
- X return 'P';
- X}
- X
- X/* Draw the AM/PM/Noon/Midnight indicator in the top right corner */
- X
- Xvoid
- Xdrawampm(c)
- X int c;
- X{
- X int dh = wcharwidth('M');
- X int dv = wlineheight();
- X int h = centh + radius - dh;
- X int v = centv - radius - dv;
- X
- X werase(h, v, h+dh, v+dv);
- X wdrawchar(h, v, c);
- X}
- X
- X#ifdef UGLY
- X
- X/* Draw a shaded square around the clock */
- X
- X#define SHOFF 4
- X
- Xvoid
- Xdrawborder()
- X{
- X int d = radius * 10/9;
- X int left = centh-d, top = centv-d, right = centh+d, bottom = centv+d;
- X wdrawbox(left, top, right, bottom);
- X wshade(right, top+4, right+4, bottom+4, 50);
- X wshade(left+4, bottom, right, bottom+4, 50);
- X}
- X
- X/* Draw a shaded circle around the clock's face;
- X the shadow is on the top left side, so the face appeares to
- X be slightly *lower* than the surrounding material.
- X Also a thin vertical line to indicate 6 and 12 o'clock. */
- X
- Xvoid
- Xdrawoutline()
- X{
- X wdrawcircle(centh-1, centv-1, radius+2);
- X wdrawelarc(centh-1, centv-1, radius+1, radius+1, 45-10, 45+180+10);
- X wdrawelarc(centh-1, centv-1, radius , radius , 45+10, 45+180-10);
- X wdrawline(centh, centv-radius, centh, centv+radius);
- X}
- X
- X#endif /*UGLY*/
- X
- X/* Compute the little hand position from hour, min */
- X
- Xint
- Xlittlehand(hour, min)
- X int hour, min;
- X{
- X return (hour*5 + (min+6)/12) % 60;
- X}
- X
- X/* Draw procedure */
- X
- Xvoid
- Xdrawproc(win, left, top, right, bottom)
- X WINDOW *win;
- X{
- X int i;
- X
- X /* Draw the fixed elements of the clock */
- X#ifdef UGLY
- X drawborder();
- X drawoutline();
- X#else
- X#ifdef macintosh
- X wdrawcircle(centh+1, centv+1, radius+1);
- X#else
- X wdrawcircle(centh, centv, radius);
- X#endif
- X for (i = 0; i < 12; ++i)
- X drawmark(i*5); /* Hour marks */
- X#endif
- X
- X /* Draw the hands */
- X drawhand(curtime.tm_min, BIGPERC);
- X i = littlehand(curtime.tm_hour, curtime.tm_min);
- X if (i != curtime.tm_min)
- X xorhand(i, LITPERC);
- X if (do_seconds)
- X xorhand(curtime.tm_sec, SECPERC);
- X
- X /* Draw the other elements */
- X drawdate(&curtime);
- X drawampm(ampm(&curtime));
- X if (alarm >= 0)
- X drawalarm();
- X
- X /* Invert if the alarm is going */
- X if (excited)
- X winvert(0, 0, 10000, 10000);
- X}
- X
- X/* Compute the nearest clock angle corresponding to
- X absolute position (h, v) */
- X
- Xint
- Xwhereis(h, v)
- X int h, v;
- X{
- X double dnew;
- X
- X h -= centh;
- X v -= centv;
- X if (h == 0 && v == 0)
- X return 0;
- X dnew = atan2((double)h, (double)(-v)) * 30.0 / PI;
- X if (dnew < 0)
- X dnew += 60.0;
- X return ((int)(dnew + 0.5)) % 60;
- X}
- X
- X/* Show a change in time with minimal redrawing */
- X
- Xshowchange(old, new)
- X struct tm *old, *new;
- X{
- X int litold = littlehand(old->tm_hour, old->tm_min);
- X int litnew = littlehand(new->tm_hour, new->tm_min);
- X int newampm = ampm(new);
- X
- X wbegindrawing(win);
- X
- X if (do_seconds && old->tm_sec != new->tm_sec) {
- X xorhand(old->tm_sec, SECPERC);
- X xorhand(new->tm_sec, SECPERC);
- X }
- X
- X if (old->tm_min != new->tm_min) {
- X xorhand(old->tm_min, BIGPERC);
- X xorhand(new->tm_min, BIGPERC);
- X }
- X
- X if (litold != litnew ||
- X litold == old->tm_min || litnew == new->tm_min) {
- X if (litold != old->tm_min)
- X xorhand(litold, LITPERC);
- X if (litnew != new->tm_min)
- X xorhand(litnew, LITPERC);
- X }
- X
- X if (old->tm_mday != new->tm_mday)
- X drawdate(new);
- X
- X if (newampm != ampm(old))
- X drawampm(newampm);
- X
- X wenddrawing(win);
- X
- X}
- X
- X/* Leap year calculation. Input is year - 1900 (but may be >= 100). */
- X
- Xint
- Xisleap(year)
- X int year;
- X{
- X year += 1900;
- X
- X return year%4 == 0 && (year%100 != 0 || year%400 == 0);
- X}
- X
- X/* Increment a time variable in minutes, and show the change */
- X
- Xvoid
- Xincrshowtime(tp, incr)
- X struct tm *tp;
- X int incr;
- X{
- X struct tm old;
- X static int mdays[12]=
- X {31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
- X
- X mdays[1] = 28 + isleap(tp->tm_year);
- X
- X old = *tp;
- X
- X tp->tm_min += incr;
- X
- X while (tp->tm_min >= 60) {
- X tp->tm_min -= 60;
- X tp->tm_hour++;
- X if (tp->tm_hour >= 24) {
- X tp->tm_hour -= 24;
- X tp->tm_mday++;
- X tp->tm_wday = (tp->tm_wday + 1) % 7;
- X if (tp->tm_mday > mdays[tp->tm_mon]) {
- X tp->tm_mday = 1;
- X tp->tm_mon++;
- X if (tp->tm_mon >= 12) {
- X tp->tm_mon = 0;
- X tp->tm_year++;
- X mdays[1] = 28 + isleap(tp->tm_year);
- X }
- X }
- X }
- X }
- X
- X while (tp->tm_min < 0) {
- X tp->tm_min += 60;
- X tp->tm_hour--;
- X if (tp->tm_hour < 0) {
- X tp->tm_hour += 24;
- X tp->tm_mday--;
- X tp->tm_wday = (tp->tm_wday + 6) % 7;
- X if (tp->tm_mday < 1) {
- X tp->tm_mon--;
- X if (tp->tm_mon < 0) {
- X tp->tm_mon = 11;
- X tp->tm_year--;
- X mdays[1] = 28 + isleap(tp->tm_year);
- X }
- X tp->tm_mday = mdays[tp->tm_mon];
- X }
- X }
- X }
- X
- X showchange(&old, tp);
- X}
- X
- X/* Drag the little hand */
- X
- Xvoid
- Xdraglittlehand(h, v)
- X int h, v;
- X{
- X EVENT e;
- X struct tm newtime;
- X int i;
- X
- X newtime = curtime;
- X wsettimer(win, 0);
- X
- X do {
- X wgetevent(&e);
- X if (e.type != WE_MOUSE_MOVE && e.type != WE_MOUSE_UP) {
- X showchange(&newtime, &curtime);
- X wungetevent(&e);
- X return;
- X }
- X i = whereis(e.u.where.h, e.u.where.v) / 5;
- X if ((i - newtime.tm_hour) % 12 != 0) {
- X int diff = i - newtime.tm_hour;
- X while (diff > 6)
- X diff -= 12;
- X while (diff < -6)
- X diff += 12;
- X incrshowtime(&newtime, diff*60);
- X }
- X } while (e.type != WE_MOUSE_UP);
- X setdatetime(&newtime, FALSE);
- X curtime = newtime;
- X}
- X
- X/* Drag the big hand */
- X
- Xvoid
- Xdragbighand(h, v)
- X int h, v;
- X{
- X EVENT e;
- X struct tm newtime;
- X int i;
- X
- X newtime = curtime;
- X wsettimer(win, 0);
- X
- X do {
- X wgetevent(&e);
- X if (e.type != WE_MOUSE_MOVE && e.type != WE_MOUSE_UP) {
- X showchange(&newtime, &curtime);
- X wungetevent(&e);
- X return;
- X }
- X i = whereis(e.u.where.h, e.u.where.v);
- X if (i != newtime.tm_min) {
- X int diff = i - newtime.tm_min;
- X if (diff > 30)
- X diff -= 60;
- X else if (diff < -30)
- X diff += 60;
- X incrshowtime(&newtime, diff);
- X }
- X } while (e.type != WE_MOUSE_UP);
- X setdatetime(&newtime, TRUE);
- X curtime = newtime;
- X}
- X
- X/* Test whether the given position lies on the hand at the
- X given clock angle with the given length percentage */
- X
- Xbool
- Xtesthand(h, v, pos, perc)
- X int h, v;
- X int pos;
- X int perc;
- X{
- X long dist2 = (h-centh)*(h-centh)+ (v-centv)*(v-centv);
- X long length2 = ((long)radius*perc/100) * ((long)radius*perc/100);
- X
- X if (dist2 > length2)
- X return FALSE;
- X if ((whereis(h, v) - pos) % 60 != 0)
- X return FALSE;
- X return TRUE;
- X}
- X
- X/* Recompute the time and the alarm parameters.
- X Called every minute, and when other parameters may have changed. */
- X
- Xvoid
- Xnewtime(flash)
- X bool flash;
- X{
- X struct tm oldtime;
- X time_t now;
- X bool wasalarmed;
- X
- X /* Save the old time displayed */
- X oldtime = curtime;
- X
- X /* Get the current time */
- X time(&now);
- X curtime = *localtime(&now);
- X
- X /* Set the window timer to go off at the next tick */
- X if (do_seconds) {
- X wsettimer(win, 10);
- X }
- X else {
- X if (curtime.tm_sec >= 59) {
- X /* When we wake up just at the end of the minute,
- X (which may happen if STDWIN isn't very precise),
- X pretend it's a bit later, to avoid waking up
- X again in a second */
- X curtime.tm_sec -= 60;
- X curtime.tm_min += 1;
- X }
- X wsettimer(win, 10 * (60 - curtime.tm_sec));
- X }
- X
- X /* Check whether the alarm should go off */
- X wasalarmed = alarmed;
- X if (!wasalarmed)
- X okayed = FALSE;
- X if (alarm >= 0) {
- X int a = alarm;
- X int hhmm = curtime.tm_hour*60 + curtime.tm_min;
- X if (hhmm < 60 && a >= 23*60)
- X hhmm += 24*60; /* Correct for wrap-around */
- X alarmed = hhmm >= a && hhmm < a+ALARMTIME;
- X }
- X else {
- X alarmed = okayed = FALSE;
- X }
- X excited = alarmed && !okayed;
- X if (excited) {
- X if (!wasalarmed)
- X wsetactive(win);
- X wfleep();
- X }
- X if (excited || wasalarmed && !okayed)
- X flash = TRUE;
- X wmenuenable(mp, OKALARM, excited);
- X
- X /* Redraw the clock face or schedule a redraw */
- X if (flash) {
- X changeall();
- X }
- X else {
- X showchange(&oldtime, &curtime);
- X }
- X}
- X
- X/* Time-setting procedure by dragging the hands around */
- X
- Xvoid
- Xchangehand(h, v)
- X int h, v;
- X{
- X /* Test the little hand first, so that if the hands
- X overlap, a click near the center implies the little
- X hand and a click further away implies the big hand */
- X if (testhand(h, v,
- X littlehand(curtime.tm_hour, curtime.tm_min), LITPERC)) {
- X /* Drag the little hand -- minutes stay unchanged */
- X draglittlehand(h, v);
- X }
- X else if (testhand(h, v, curtime.tm_min, BIGPERC)) {
- X /* Drag the big hand -- hours may change, too */
- X dragbighand(h, v);
- X }
- X else {
- X /* No hit -- make some noise */
- X wfleep();
- X }
- X newtime(FALSE);
- X}
- X
- X/* Recompute the clock size and position
- X and the time/alarm information.
- X Called initially and when the window is resized. */
- X
- Xvoid
- Xgetallinfo()
- X{
- X int width, height;
- X
- X wgetwinsize(win, &width, &height);
- X centh = width/2;
- X centv = height/2;
- X radius = centv - wlineheight();
- X CLIPMAX(radius, centh);
- X newtime(TRUE);
- X}
- X
- X/* Set the alarm time from a string formatted as hhmm */
- X
- Xbool
- Xsetalarm(str)
- X char *str;
- X{
- X int al;
- X
- X if (str[0] == EOS || str[0] == '-' && str[1] == EOS) {
- X alarm = -1;
- X wmenuenable(mp, CLEARALARM, FALSE);
- X return TRUE;
- X }
- X al = atoi(str);
- X if (al < 0 || al > 2400 || al%60 >= 60)
- X return FALSE;
- X if (al == 2400)
- X al = 0;
- X alarm = (al/100)*60 + al%100;
- X wmenuenable(mp, CLEARALARM, TRUE);
- X return TRUE;
- X}
- X
- X/* Set up the menu */
- X
- Xvoid
- Xbuildmenu()
- X{
- X wmenusetdeflocal(TRUE);
- X mp = wmenucreate(1, "Klok");
- X
- X wmenuadditem(mp, "Set alarm...", 'S');
- X wmenuadditem(mp, "Clear alarm", 'C');
- X wmenuadditem(mp, "OK alarm", 'O');
- X wmenuadditem(mp, "", -1);
- X wmenuadditem(mp, "Seconds Hand", 'H');
- X wmenuadditem(mp, "", -1);
- X wmenuadditem(mp, "Quit", 'Q');
- X
- X wmenuenable(mp, CLEARALARM, alarm >= 0);
- X wmenucheck(mp, SECONDSHAND, do_seconds);
- X}
- X
- X/* Handle a menu selection */
- X
- Xvoid
- Xdomenu(item)
- X int item;
- X{
- X bool flash = FALSE;
- X
- X switch (item) {
- X case SETALARM: {
- X char buf[6];
- X if (alarm < 0)
- X buf[0] = EOS;
- X else
- X sprintf(buf, "%02d%02d", alarm/60, alarm%60);
- X if (!waskstr("Set alarm:", buf, sizeof buf))
- X return;
- X if (!setalarm(buf))
- X wmessage("Invalid alarm (must be hhmm)");
- X okayed = FALSE;
- X flash = TRUE;
- X break;
- X }
- X case CLEARALARM:
- X if (alarm >= 0) {
- X setalarm("");
- X flash = TRUE;
- X }
- X break;
- X case OKALARM:
- X if (excited) {
- X flash = okayed = TRUE;
- X }
- X break;
- X case SECONDSHAND:
- X do_seconds = !do_seconds;
- X wmenucheck(mp, SECONDSHAND, do_seconds);
- X wbegindrawing(win);
- X xorhand(curtime.tm_sec, SECPERC);
- X wenddrawing(win);
- X break;
- X case QUIT:
- X wclose(win);
- X wdone();
- X exit(0);
- X break;
- X }
- X newtime(flash);
- X}
- X
- X#ifndef macintosh
- X/* Print usage message and exit; called for command line errors */
- X
- Xvoid
- Xusage()
- X{
- X wdone();
- X fprintf(stderr,
- X "usage: %s [-s] [-m] [-a hhmm] [-t title]\n", progname);
- X exit(2);
- X}
- X#endif
- X
- X/* Main program */
- X
- Xmain(argc, argv)
- X int argc;
- X char **argv;
- X{
- X /* Initialize */
- X winitargs(&argc, &argv);
- X buildmenu(); /* Must be done before setalarm is called */
- X
- X /* Find out program name */
- X if (argc > 0) {
- X progname = strrchr(argv[0], '/');
- X if (progname == NULL)
- X progname = argv[0];
- X else
- X ++progname;
- X }
- X
- X#ifndef macintosh
- X /* Parse command line */
- X for (;;) {
- X int c = getopt(argc, argv, "msa:t:");
- X if (c == EOF)
- X break;
- X switch (c) {
- X case 's':
- X do_seconds = TRUE;
- X break;
- X case 'm':
- X do_seconds = FALSE;
- X break;
- X case 'a':
- X if (!setalarm(optarg))
- X usage();
- X break;
- X case 't':
- X title = optarg;
- X break;
- X default:
- X usage();
- X /*NOTREACHED*/
- X }
- X }
- X wmenucheck(mp, SECONDSHAND, do_seconds);
- X#endif
- X
- X /* Create the window */
- X wsetdefwinsize(120, 120);
- X win = wopen(title == NULL ? progname : title, drawproc);
- X wmenuattach(win, mp);
- X
- X /* Main loop */
- X getallinfo();
- X for (;;) {
- X EVENT e;
- X wgetevent(&e);
- X
- X switch (e.type) {
- X
- X case WE_MOUSE_DOWN:
- X if (excited)
- X domenu(OKALARM);
- X else
- X changehand(e.u.where.h, e.u.where.v);
- X break;
- X
- X case WE_MENU:
- X if (e.u.m.id == 1)
- X domenu(e.u.m.item);
- X break;
- X
- X case WE_CHAR:
- X if (excited)
- X break;
- X switch (e.u.character) {
- X case 's':
- X case 'S':
- X domenu(SETALARM);
- X break;
- X case 'c':
- X case 'C':
- X domenu(CLEARALARM);
- X break;
- X case 'h':
- X case 'H':
- X domenu(SECONDSHAND);
- X break;
- X case 'q':
- X case 'Q':
- X domenu(QUIT);
- X break;
- X }
- X break;
- X
- X case WE_COMMAND:
- X switch (e.u.command) {
- X case WC_RETURN:
- X newtime(FALSE);
- X break;
- X case WC_CLOSE:
- X case WC_CANCEL:
- X domenu(QUIT);
- X break;
- X }
- X break;
- X
- X case WE_CLOSE:
- X domenu(QUIT);
- X break;
- X
- X case WE_SIZE:
- X getallinfo();
- X break;
- X
- X case WE_TIMER:
- X newtime(FALSE);
- X break;
- X
- X }
- X }
- X}
- END_OF_FILE
- if test 17064 -ne `wc -c <'Appls/klok/klok.c'`; then
- echo shar: \"'Appls/klok/klok.c'\" unpacked with wrong size!
- fi
- # end of 'Appls/klok/klok.c'
- fi
- if test -f 'Conf/proto.os.bsd' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Conf/proto.os.bsd'\"
- else
- echo shar: Extracting \"'Conf/proto.os.bsd'\" \(143 characters\)
- sed "s/^X//" >'Conf/proto.os.bsd' <<'END_OF_FILE'
- X
- X#
- X# Definitions pertaining to BSD (4.3)
- X#
- X
- XOS= bsd
- XRANLIB= ranlib
- X
- X# MKDEP is defined in proto.arch.*
- X
- XLIBTERMCAP= -ltermcap
- XLIBX11= -lX11
- END_OF_FILE
- if test 143 -ne `wc -c <'Conf/proto.os.bsd'`; then
- echo shar: \"'Conf/proto.os.bsd'\" unpacked with wrong size!
- fi
- # end of 'Conf/proto.os.bsd'
- fi
- if test -f 'Ports/alfa/menu.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Ports/alfa/menu.c'\"
- else
- echo shar: Extracting \"'Ports/alfa/menu.c'\" \(10366 characters\)
- sed "s/^X//" >'Ports/alfa/menu.c' <<'END_OF_FILE'
- X/* TERMCAP STDWIN -- MENUS. */
- X
- X#include "alfa.h"
- X
- Xstatic bool deflocal= FALSE; /* Default menu state */
- X
- Xstatic struct menubar gmenus; /* All global menus */
- Xstatic struct menubar lmenus; /* All local menus */
- X
- Xstatic MENU *sysmenu; /* Window selection commands */
- Xstatic MENU *curmenu;
- X
- Xstatic void
- Xaddtobar(mbp, mp)
- X struct menubar *mbp;
- X MENU *mp;
- X{
- X int i;
- X
- X for (i= 0; i < mbp->nmenus; ++i) {
- X if (mp == mbp->menulist[i])
- X return; /* Already attached */
- X }
- X L_APPEND(mbp->nmenus, mbp->menulist, MENU *, mp);
- X}
- X
- Xstatic void
- Xdelfrombar(mbp, mp)
- X struct menubar *mbp;
- X MENU *mp;
- X{
- X int i;
- X
- X for (i= 0; i < mbp->nmenus; ++i) {
- X if (mp == mbp->menulist[i]) {
- X L_REMOVE(mbp->nmenus, mbp->menulist,
- X MENU *, i);
- X break;
- X }
- X }
- X}
- X
- X_winitmenus()
- X{
- X sysmenu= wmenucreate(0, "Windows");
- X wmenuadditem(sysmenu, "Previous Window", -1);
- X wmenuadditem(sysmenu, "Next Window", -1);
- X#ifndef EM
- X /* Somehow, Euromath doesn't like this?!? */
- X wmenuadditem(sysmenu, "Close Window", -1);
- X wmenuadditem(sysmenu, "(left)", -1);
- X wmenuadditem(sysmenu, "(right)", -1);
- X wmenuadditem(sysmenu, "(up)", -1);
- X wmenuadditem(sysmenu, "(down)", -1);
- X wmenuadditem(sysmenu, "(cancel)", -1);
- X wmenuadditem(sysmenu, "(backspace)", -1);
- X wmenuadditem(sysmenu, "(tab)", -1);
- X wmenuadditem(sysmenu, "(return)", -1);
- X#endif
- X /* Shortcuts are compiled in the key map! */
- X}
- X
- XMENU *
- Xwmenucreate(id, title)
- X int id;
- X char *title;
- X{
- X MENU *mp= ALLOC(MENU);
- X
- X if (mp == NULL)
- X return NULL;
- X mp->id= id;
- X mp->title= strdup(title);
- X mp->local= deflocal;
- X mp->dirty= TRUE;
- X mp->left= mp->right= 0;
- X L_INIT(mp->nitems, mp->itemlist);
- X addtobar(mp->local ? &lmenus : &gmenus, mp);
- X if (!mp->local)
- X menubarchanged();
- X return mp;
- X}
- X
- Xvoid
- Xwmenudelete(mp)
- X MENU *mp;
- X{
- X int i;
- X
- X if (mp->local) {
- X for (i= 0; i < MAXWINDOWS; ++i) {
- X if (winlist[i].open)
- X delfrombar(&winlist[i].mbar, mp);
- X }
- X }
- X delfrombar(mp->local ? &lmenus : &gmenus, mp);
- X for (i= 0; i < mp->nitems; ++i) {
- X FREE(mp->itemlist[i].text);
- X FREE(mp->itemlist[i].shortcut);
- X }
- X L_DEALLOC(mp->nitems, mp->itemlist);
- X FREE(mp);
- X menubarchanged();
- X}
- X
- Xint
- Xwmenuadditem(mp, text, shortcut)
- X MENU *mp;
- X char *text;
- X int shortcut;
- X{
- X struct item it;
- X
- X mp->dirty= TRUE;
- X it.text= strdup(text);
- X#ifdef EM
- X/* need to add the shortcut now, otherwise it will be taken from
- X the keymap whenever the menu is displayed, which might be after
- X opening another window and overwriting the keymap entry.
- X In the AddMenuEntry code I overwrite the shortcut anyway. */
- X/* I don't understand this --Guido */
- X if(shortcut >= 32) {
- X it.shortcut=(char *)malloc(8);
- X sprintf(it.shortcut,"ESC %c", shortcut);
- X } else
- X#endif
- X it.shortcut= NULL;
- X it.enabled= (text != NULL && *text != EOS);
- X it.checked= FALSE;
- X L_APPEND(mp->nitems, mp->itemlist, struct item, it);
- X if (shortcut >= 0)
- X wsetmetakey(mp->id, mp->nitems-1, shortcut);
- X return mp->nitems-1;
- X}
- X
- Xvoid
- Xwmenusetitem(mp, item, text)
- X MENU *mp;
- X int item;
- X char *text;
- X{
- X if (item < 0 || item >= mp->nitems)
- X return;
- X mp->dirty= TRUE;
- X FREE(mp->itemlist[item].text);
- X mp->itemlist[item].text= strdup(text);
- X mp->itemlist[item].enabled= (text != NULL && *text != EOS);
- X}
- X
- Xvoid
- Xwmenuenable(mp, item, flag)
- X MENU *mp;
- X int item;
- X int flag;
- X{
- X if (item < 0 || item >= mp->nitems)
- X return;
- X mp->itemlist[item].enabled= flag;
- X}
- X
- Xvoid
- Xwmenucheck(mp, item, flag)
- X MENU *mp;
- X int item;
- X int flag;
- X{
- X if (item < 0 || item >= mp->nitems)
- X return;
- X mp->itemlist[item].checked= flag;
- X}
- X
- Xvoid
- Xwmenuattach(win, mp)
- X WINDOW *win;
- X MENU *mp;
- X{
- X if (!mp->local)
- X return;
- X addtobar(&win->mbar, mp);
- X if (win == front)
- X menubarchanged();
- X}
- X
- Xvoid
- Xwmenudetach(win, mp)
- X WINDOW *win;
- X MENU *mp;
- X{
- X if (!mp->local)
- X return;
- X delfrombar(&win->mbar, mp);
- X if (win == front)
- X menubarchanged();
- X}
- X
- Xvoid
- Xwmenusetdeflocal(local)
- X bool local;
- X{
- X deflocal= local;
- X}
- X
- X/* Interface routines for the rest of the library. */
- X
- Xvoid
- Xinitmenubar(mb)
- X struct menubar *mb;
- X{
- X L_INIT(mb->nmenus, mb->menulist);
- X}
- X
- Xvoid
- Xkillmenubar(mb)
- X struct menubar *mb;
- X{
- X L_DEALLOC(mb->nmenus, mb->menulist);
- X}
- X
- Xvoid
- Xdrawmenubar() /* This is part of the syswin draw procedure! */
- X{
- X WINDOW *win= front;
- X char buf[256];
- X int k= 0;
- X int i;
- X
- X buf[0]= EOS;
- X for (i= 0; i < gmenus.nmenus; ++i)
- X k= bufappend(buf, k, gmenus.menulist[i]);
- X if (win != NULL) {
- X for (i= 0; i < win->mbar.nmenus; ++i)
- X k= bufappend(buf, k, win->mbar.menulist[i]);
- X }
- X wdrawtext(0, 0, buf, -1);
- X}
- X
- Xstatic int
- Xbufappend(buf, pos, mp)
- X char *buf;
- X int pos;
- X MENU *mp;
- X{
- X if (pos > 0) {
- X buf[pos++]= ' ';
- X buf[pos++]= ' ';
- X }
- X mp->left= pos;
- X strcpy(buf+pos, mp->title);
- X pos += strlen(buf+pos);
- X mp->right= pos;
- X return pos;
- X}
- X
- X/* TO DO:
- X - highlight current menu title, current menu item
- X - remember last menu and item
- X - Allow GOTO to select menus or menu items
- X (m-down on mbar opens the menu; m-up on item selects the item)
- X*/
- X
- Xstatic void menudraw(), menuitemdraw(), menucalcwidth();
- Xstatic bool handleevt(), handlecmd(), handlemenu();
- Xstatic int calcleft();
- X
- Xstatic leftblank;
- X
- Xstatic bool curlocal;
- Xstatic struct menubar * curmbar;
- Xstatic int curimenu;
- Xstatic int curitem;
- Xstatic int lowest;
- X
- Xstatic bool
- Xfirstmenu()
- X{
- X curlocal= FALSE;
- X curmbar= &gmenus;
- X curimenu= 0;
- X
- X if (curmbar->nmenus == 0) {
- X curmbar= &lmenus;
- X curlocal= TRUE;
- X if (curmbar->nmenus == 0) {
- X wmessage("No menus defined");
- X return FALSE;
- X }
- X }
- X curmenu= curmbar->menulist[curimenu];
- X curitem= 0;
- X menudraw();
- X return TRUE;
- X}
- X
- Xstatic void
- Xnextmenu()
- X{
- X WINDOW *win=front; /* added mcv */
- X/* the menus are now taken from the window's menubar, instead
- X of the menubar for *all* local menus */
- X
- X ++curimenu;
- X while (curimenu >= curmbar->nmenus) {
- X curlocal= !curlocal;
- X curmbar= curlocal ?
- X &win->mbar /* changed mcv, was: &lmenus*/ :
- X &gmenus;
- X curimenu= 0;
- X }
- X curmenu= curmbar->menulist[curimenu];
- X curitem= 0;
- X menudraw();
- X}
- X
- Xstatic void
- Xprevmenu()
- X{
- X WINDOW *win=front; /* added mcv */
- X/* the menus are now taken from the window's menubar, instead
- X of the menubar for *all* local menus */
- X
- X --curimenu;
- X while (curimenu < 0) {
- X curlocal= !curlocal;
- X curmbar= curlocal ?
- X &win->mbar /* changed mcv, was: &lmenus*/ :
- X &gmenus;
- X curimenu= curmbar->nmenus - 1;
- X }
- X curmenu= curmbar->menulist[curimenu];
- X curitem= 0;
- X menudraw();
- X}
- X
- Xstatic void
- Xnextitem()
- X{
- X ++curitem;
- X if (curitem >= curmenu->nitems)
- X curitem= 0;
- X trmsync(curitem+1, curmenu->left);
- X}
- X
- Xstatic void
- Xprevitem()
- X{
- X --curitem;
- X if (curitem < 0)
- X curitem= curmenu->nitems - 1;
- X trmsync(curitem+1, curmenu->left);
- X}
- X
- Xstatic void
- Xselectitem(ep)
- X EVENT *ep;
- X{
- X ep->type= WE_NULL;
- X if (curitem >= curmenu->nitems || !curmenu->itemlist[curitem].enabled)
- X return;
- X ep->type= WE_MENU;
- X ep->u.m.id= curmenu->id;
- X ep->u.m.item= curitem;
- X}
- X
- Xvoid
- Xmenuselect(ep)
- X EVENT *ep;
- X{
- X leftblank= columns;
- X lowest= 0;
- X wmessage((char *)NULL);
- X if (!firstmenu())
- X return;
- X for (;;) {
- X wsysevent(ep, 1);
- X if (handleevt(ep))
- X break;
- X }
- X}
- X
- Xstatic bool
- Xhandleevt(ep)
- X EVENT *ep;
- X{
- X switch (ep->type) {
- X
- X case WE_MENU:
- X return handlemenu(ep);
- X
- X case WE_COMMAND:
- X return handlecmd(ep);
- X
- X default:
- X trmbell();
- X return FALSE;
- X
- X }
- X}
- X
- Xstatic bool
- Xhandlecmd(ep)
- X EVENT *ep;
- X{
- X switch (ep->u.command) {
- X
- X default:
- X trmbell();
- X return FALSE;
- X
- X case WC_RETURN:
- X selectitem(ep);
- X if (curmenu == sysmenu)
- X wsyscommand(ep);
- X return TRUE;
- X
- X case WC_LEFT:
- X prevmenu();
- X break;
- X
- X case WC_RIGHT:
- X nextmenu();
- X break;
- X
- X case WC_UP:
- X previtem();
- X break;
- X
- X case WC_DOWN:
- X nextitem();
- X break;
- X
- X case WC_CANCEL:
- X ep->type= WE_NULL;
- X return TRUE;
- X
- X }
- X return FALSE;
- X}
- X
- Xstatic bool
- Xhandlemenu(ep)
- X EVENT *ep;
- X{
- X if (ep->u.m.id != 0)
- X return TRUE;
- X switch (ep->u.m.item) {
- X
- X case SUSPEND_PROC:
- X _wsuspend();
- X menudraw();
- X break;
- X
- X case REDRAW_SCREEN:
- X _wredraw();
- X menudraw();
- X break;
- X
- X case MENU_CALL:
- X ep->type= WE_NULL;
- X return TRUE;
- X
- X default:
- X if (ep->u.m.item <= LAST_CMD) {
- X wsyscommand(ep);
- X if (ep->type == WE_COMMAND)
- X return handlecmd(ep);
- X else
- X return TRUE;
- X }
- X else {
- X trmbell();
- X return FALSE;
- X }
- X
- X }
- X return FALSE;
- X}
- X
- Xstatic void
- Xmenudraw()
- X{
- X MENU *mp= curmenu;
- X int left;
- X int width;
- X int i;
- X
- X wupdate(syswin);
- X if (mp->dirty)
- X menucalcwidth(mp);
- X left= calcleft(mp);
- X width= mp->maxwidth;
- X if (left + width > columns)
- X width= columns - left;
- X for (i= 0; i < mp->nitems; ++i)
- X menuitemdraw(i+1, left, &mp->itemlist[i], width);
- X if (i+1 > lowest) {
- X lowest= i+1;
- X if (lowest < lines)
- X uptodate[lowest]= FALSE;
- X }
- X trmputdata(i+1, lowest, 0, "");
- X leftblank= left;
- X trmsync(curitem+1, mp->left);
- X}
- X
- Xstatic int
- Xcalcleft(mp)
- X MENU *mp;
- X{
- X int left= columns - mp->maxwidth;
- X
- X if (left > mp->left)
- X left= mp->left;
- X if (left < 0)
- X left= 0;
- X if (left-3 < leftblank) {
- X leftblank= left-3;
- X if (leftblank < 4)
- X leftblank= 0;
- X }
- X return left;
- X}
- X
- Xstatic void
- Xmenuitemdraw(line, left, ip, width)
- X int line, left;
- X struct item *ip;
- X int width;
- X{
- X char buf[256];
- X int margin= left-leftblank;
- X
- X buf[0]= EOS;
- X if (ip->text != NULL && *ip->text != EOS) {
- X int space;
- X char *p= buf;
- X for (space= margin; space-- > 0; )
- X *p++ = ' ';
- X if (ip->checked && margin >= 2)
- X p[-2]= '*';
- X strcpy(p, ip->text);
- X p += strlen(p);
- X if (!ip->enabled && margin >= 1 &&
- X ip->text != NULL && ip->text[0] != EOS) {
- X buf[margin-1]= '(';
- X *p++= ')';
- X *p= '\0';
- X }
- X if (ip->shortcut != NULL && *ip->shortcut != EOS) {
- X space= width - (p - buf - margin)
- X - strlen(ip->shortcut);
- X if (space <= 0)
- X space= 2;
- X while (--space >= 0)
- X *p++ = ' ';
- X strcpy(p, ip->shortcut);
- X }
- X }
- X /* This was added because brackets and stars from disabled/marked
- X items on the first menu (after the sysmenu) weren't removed
- X from the screen. I haven't tried to fix this in a more
- X efficient manner. */
- X trmputdata(line, line, 0, "");
- X trmputdata(line, line, leftblank, buf);
- X uptodate[line]= FALSE;
- X}
- X
- Xstatic void
- Xmenucalcwidth(mp)
- X MENU *mp;
- X{
- X int i;
- X int width= 0;
- X
- X for (i= 0; i < mp->nitems; ++i) {
- X struct item *ip= &mp->itemlist[i];
- X char *text= ip->text;
- X if (text != NULL && *text != EOS) {
- X int w= strlen(text);
- X if (ip->shortcut == NULL) {
- X char buf[256];
- X getbindings(buf, mp->id, i);
- X ip->shortcut= strdup(buf);
- X }
- X if (ip->shortcut != NULL && *ip->shortcut != EOS)
- X w += 2 + strlen(ip->shortcut);
- X if (w > width)
- X width= w;
- X }
- X }
- X mp->maxwidth= width;
- X mp->dirty= FALSE;
- X}
- END_OF_FILE
- if test 10366 -ne `wc -c <'Ports/alfa/menu.c'`; then
- echo shar: \"'Ports/alfa/menu.c'\" unpacked with wrong size!
- fi
- # end of 'Ports/alfa/menu.c'
- fi
- if test -f 'Ports/msdos/ptrm.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Ports/msdos/ptrm.c'\"
- else
- echo shar: Extracting \"'Ports/msdos/ptrm.c'\" \(23047 characters\)
- sed "s/^X//" >'Ports/msdos/ptrm.c' <<'END_OF_FILE'
- X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1986. */
- X
- X/*
- X * ibm Pc virtual TeRMinal package.
- X *
- X * (Under reconstruction by Guido!)
- X *
- X * An implementation of the VTRM interface for MS-DOS machines.
- X *
- X * This code supports two modes of accessing the screen.
- X * The first one (BIOS) will be used, unless the user overwrites this
- X * by setting the SCREEN environment variable.
- X * This variable can also be used to convey a screen size that differs
- X * from the default 25 lines and 80 columns. See below.
- X *
- X * The two modes are:
- X *
- X * 1) IBM BIOS interrupt 10 hex, video io.
- X * (See IBM PC XT Technical Reference 6936833, May 1983,
- X * Appendix A, pages A46-A47).
- X * This is what you really want to use, since it's the only one that
- X * can decently scroll. It cannot insert or delete characters, so
- X * most optimisations from vtrm.c are useless and taken out.
- X * Unfortunately, not every PC-compatible machine supports this BIOS
- X * interrupt, so for these unlucky souls there is the following escape:
- X *
- X * 2) The ANSI.SYS driver.
- X * (See IBM MS-DOS 6936839, Jan 1983, Version 2.00, Chapter 13.)
- X * (Some compatibles don't have a separate ANSI.SYS driver but do the
- X * same escape interpretation by default.)
- X * This works reasonably, apart from scrolling downward, or part of
- X * the screen, which is clumsy.
- X * (The ANSI standard provides an escape sequence for scrolling
- X * but ANSI.SYS does not support it, nor any other way of scrolling.)
- X *
- X * The rest of the interface is the same as described in vtrm.c,
- X * with the following exceptions:
- X * - to ease coding for ansi scrolls, the terminal is supposed to
- X * contain blanks at positions that were not written yet;
- X * the unknown rubbish that is initially on the screen can
- X * only be cleared by the caller by scrolling the whole screen up
- X * by one or more lines;
- X * - the number of lines on the terminal is assumed to be 25;
- X * the number of columns is (1) determined by a BIOS function, or
- X * (2) assumed to be 80 for ANSI;
- X * the user can overwrite this by setting the environment variable:
- X *
- X * SET SCREEN=BIOS y x
- X * or
- X * SET SCREEN=ANSI y x
- X *
- X * where x and y are the number of lines and columns respectively.
- X *
- X * The lines and columns of our virtual terminal are numbered
- X * y = {0...lines-1} from top to bottom, and
- X * x = {0...cols-1} from left to right,
- X * respectively.
- X *
- X * The Visible Procedures in this package are as described in vtrm.c.
- X *
- X */
- X
- X/*
- X * Includes and data definitions.
- X */
- X
- X#include <stdio.h>
- X#include <signal.h>
- X#include <ctype.h>
- X#include <dos.h>
- X#include <fcntl.h>
- X#include <io.h>
- X
- Xchar *malloc();
- X
- X#define STDIN_HANDLE 0
- X
- X#include "vtrm.h"
- X
- X#ifdef lint
- X#define VOID (void)
- X#else
- X#define VOID
- X#endif
- X
- X#define Forward
- X#define Visible
- X#define Hidden static
- X#define Procedure
- X
- Xtypedef short intlet;
- Xtypedef char *string;
- Xtypedef char bool;
- X#define Yes '\1'
- X#define No '\0'
- X#define Undefined (-1)
- X
- X#define Min(a,b) ((a) <= (b) ? (a) : (b))
- X
- X#define MESS(number, text) text
- X
- X#ifdef GFX
- X#include "gfx.h"
- X#endif
- X
- X/* terminal status */
- X
- XHidden int started = No;
- X
- XHidden int scr_mode = 0;
- X#define ANSI 'A'
- X#define BIOS 'B'
- X
- X#define Nlines 25
- X#define Ncols 80
- XHidden int lines = Nlines;
- XHidden int cols = Ncols;
- XHidden int flags = 0;
- X
- X/* current standout mode */
- X#define Off 0
- X#define On 0200
- XHidden int so_mode = Off;
- X
- X/* masks for char's and intlet's */
- X#define NULCHAR '\000'
- X#define CHAR 0177
- X#define SOBIT On
- X#define SOCHAR 0377
- X
- X/* current cursor position */
- XHidden intlet cur_y = Undefined, cur_x = Undefined;
- X
- X/* "line[y][x]" holds the char on the terminal, with the SOBIT.
- X * the SOBIT tells whether the character is standing out.
- X * "lenline[y]" holds the length of the line.
- X * (Partially) empty lines are distinghuished by "lenline[y] < cols".
- X * Unknown chars will be ' ', so the scrolling routines for ANSI
- X * can use "unwritten" chars (with indent > 0 in trmputdata).
- X * To make the optimising compare in putline fail, lenline[y] is initially 0.
- X * The latter implies that if a line is first addressed with trmputdata,
- X * any rubbish that is on the screen beyond the data that gets put, will
- X * remain there.
- X */
- X
- XHidden char **line = 0;
- XHidden intlet *lenline = 0;
- X
- X/* Make the cursor invisible when trmsync() tries to move outside the screen */
- XHidden bool no_cursor = No;
- X
- X/*
- X * Starting, Ending and (fatal) Error.
- X */
- X
- Xbool wasbreak;
- X
- X/*
- X * Initialization call.
- X * Determine terminal mode.
- X * Start up terminal and internal administration.
- X * Return Yes if succeeded, No if trouble (which doesn't apply here).
- X */
- X
- XVisible int
- Xtrmstart(plines, pcols, pflags)
- Xint *plines;
- Xint *pcols;
- Xint *pflags;
- X{
- X static char setup = No;
- X int err;
- X
- X#ifdef TRACE
- Xif (!setup) freopen("TRACE.DAT", "a", stderr);
- Xfprintf(stderr, "\ttrmstart(&li, &co, &fl);\n");
- X#endif
- X
- X if (started)
- X return TE_TWICE;
- X
- X#ifdef GFX
- X if (gfx_mode != TEXT_MODE)
- X gfx_mode= SPLIT_MODE;
- X#endif
- X
- X if (!setup) {
- X err= set_screen_up();
- X if (err != TE_OK)
- X return err;
- X setup = Yes;
- X }
- X
- X err= start_trm(); /* internal administration */
- X if (err != TE_OK)
- X return err;
- X
- X *plines = lines;
- X *pcols = cols;
- X *pflags = flags;
- X
- X setmode(STDIN_HANDLE, O_BINARY); /* Don't translate CRLF to LF */
- X setraw(STDIN_HANDLE, Yes);
- X wasbreak= getbreak(); /* Save BREAK status; restore when done */
- X setbreak(No);
- X
- X set_handler();
- X started = Yes;
- X return TE_OK;
- X}
- X
- XHidden int
- Xset_screen_up()
- X{
- X int height;
- X int width;
- X int get_screen_env();
- X int get_cols();
- X
- X height = width = 0;
- X scr_mode = get_screen_env(&height, &width);
- X
- X switch (scr_mode) {
- X case BIOS:
- X case TE_OK:
- X cols = get_cols();
- X flags = HAS_STANDOUT|CAN_SCROLL;
- X break;
- X case ANSI:
- X flags = HAS_STANDOUT;
- X break;
- X default:
- X return scr_mode; /* Error flag */
- X }
- X
- X /* allow x and y in environment variable SCREEN to override */
- X if (height > 0)
- X lines = height;
- X if (width > 0)
- X cols = width;
- X return TE_OK;
- X}
- X
- XHidden int
- Xget_screen_env(pheight, pwidth)
- X int *pheight, *pwidth;
- X{
- X string s;
- X int mode;
- X char screrr;
- X string getenv();
- X string strip();
- X string skip();
- X
- X screrr = No;
- X s = getenv("SCREEN");
- X if (s == NULL)
- X return BIOS;
- X
- X s = strip(s);
- X switch (*s) {
- X case '\0':
- X return BIOS;
- X case 'a':
- X mode = ANSI;
- X s = skip(s, "ansi");
- X break;
- X case 'A':
- X mode = ANSI;
- X s = skip(s, "ANSI");
- X break;
- X case 'b':
- X mode = BIOS;
- X s = skip(s, "bios");
- X break;
- X case 'B':
- X mode = BIOS;
- X s = skip(s, "BIOS");
- X break;
- X default:
- X mode = BIOS;
- X screrr = Yes;
- X }
- X
- X /* *pheight and *pwidth were set to 0 above */
- X s = strip(s);
- X while (isdigit(*s)) {
- X *pheight = *pheight * 10 + (*s++ - '0');
- X }
- X s = strip(s);
- X while (isdigit(*s)) {
- X *pwidth = *pwidth * 10 + (*s++ -'0');
- X }
- X s = strip(s);
- X if (screrr || *s != '\0')
- X return TE_BADTERM;
- X
- X return mode;
- X}
- X
- XHidden string strip(s)
- Xstring s;
- X{
- X while (*s == ' ' || *s == '\t')
- X ++s;
- X return s;
- X}
- X
- XHidden string skip(s, pat)
- Xstring s, pat;
- X{
- X while (*s == *pat)
- X ++s, ++pat;
- X return s;
- X}
- X
- XHidden int /* initialise internal administration */
- Xstart_trm()
- X{
- X register int y;
- X
- X if (line == 0) {
- X if ((line = (char**) malloc(lines * sizeof(char*))) == NULL)
- X return TE_NOMEM;
- X for (y = 0; y < lines; y++) {
- X if ((line[y] = malloc(cols * sizeof(char))) == NULL)
- X return TE_NOMEM;
- X }
- X }
- X if (lenline == 0) {
- X if ((lenline = (intlet *)
- X malloc(lines * sizeof(intlet))) == NULL)
- X return TE_NOMEM;
- X }
- X
- X trmundefined();
- X return TE_OK;
- X}
- X
- X/*
- X * Termination call.
- X * Beware that it might be called by a catched interrupt even in the middle
- X * of trmstart()!
- X */
- X
- XVisible Procedure
- Xtrmend()
- X{
- X#ifdef TRACE
- Xfprintf(stderr, "\ttrmend();\n");
- X#endif
- X if (started && so_mode != Off)
- X standend();
- X if (scr_mode == ANSI) {
- X VOID fflush(stdout);
- X }
- X /* Always turn off RAW mode -- it is unlikely that anybody
- X would want to interface to COMMAND.COM in raw mode.
- X This way, if you were accidentally left in RAW mode
- X because of a crash, it will go away if you re-enter. */
- X setraw(STDIN_HANDLE, No);
- X setbreak(wasbreak);
- X
- X started = No;
- X}
- X
- X/*
- X * Set all internal statuses to undefined, especially the contents of
- X * the screen, so a hard redraw will not be optimised to heaven.
- X */
- X
- XVisible Procedure
- Xtrmundefined()
- X{
- X register int y, x;
- X#ifdef TRACE
- Xfprintf(stderr, "\ttrmundefined();\n");
- X#endif
- X
- X cur_y = cur_x = Undefined;
- X so_mode = Undefined;
- X
- X for (y = 0; y < lines; y++) {
- X for (x = 0; x < cols; x++)
- X line[y][x] = ' ';
- X /* they may get printed in scrolling */
- X lenline[y] = 0;
- X }
- X}
- X
- X#ifdef DEBUG
- XHidden Procedure
- Xcheck_started(m)
- X char *m;
- X{
- X if (!started) {
- X printf("Not started: %s\n", m);
- X exit(TE_TWICE);
- X }
- X}
- X#else
- X#define check_started(m) /*empty*/
- X#endif
- X
- X/*
- X * Sensing the cursor.
- X * (NOT IMPLEMENTED, since there is no way to locally move the cursor.)
- X */
- X
- X/*
- X * Sense the current (y, x) cursor position, after a possible manual
- X * change by the user with local cursor motions.
- X * If the terminal cannot be asked for the current cursor position,
- X * or if the string returned by the terminal is garbled,
- X * the position is made Undefined.
- X */
- XVisible Procedure
- Xtrmsense(py, px)
- X int *py;
- X int *px;
- X{
- X/* bool getpos(); */
- X#ifdef TRACE
- Xfprintf(stderr, "\ttrmsense(&yy, &xx);\n");
- X#endif
- X check_started(MESS(7904, "trmsense called outside trmstart/trmend"));
- X
- X *py = *px = Undefined;
- X
- X/*
- X * if (flags&CAN_SENSE && getpos(py, px)) {
- X * if (*py < 0 || lines <= *py || *px < 0 || cols <= *px)
- X * *py = *px = Undefined;
- X * }
- X */
- X cur_y = *py;
- X cur_x = *px;
- X}
- X
- X/*
- X * Putting data on the screen.
- X */
- X
- X/*
- X * Fill screen area with given data.
- X * Characters with the SO-bit (0200) set are put in standout mode.
- X * (Unfortunately this makes it impossible to display accented characters.
- X * The interface should change.)
- X */
- XVisible Procedure
- Xtrmputdata(yfirst, ylast, indent, data)
- Xint yfirst;
- Xint ylast;
- Xregister int indent;
- Xregister string data;
- X{
- X register int y;
- X int x, len, lendata, space;
- X
- X#ifdef TRACE
- Xfprintf(stderr, "\ttrmputdata(%d, %d, %d, \"%s\");\n", yfirst, ylast, indent, data);
- X#endif
- X check_started(MESS(7905, "trmputdata called outside trmstart/trmend"));
- X
- X if (yfirst < 0)
- X yfirst = 0;
- X if (ylast >= lines)
- X ylast = lines-1;
- X space = cols*(ylast-yfirst+1) - indent;
- X if (space <= 0)
- X return;
- X yfirst += indent/cols;
- X indent %= cols;
- X y = yfirst;
- X if (data) {
- X x = indent;
- X lendata = strlen(data);
- X if (ylast == lines-1 && lendata >= space)
- X lendata = space - 1;
- X len = Min(lendata, cols-x);
- X while (len > 0 && y <= ylast) {
- X put_line(y, x, data, len);
- X y++;
- X lendata -= len;
- X if (lendata > 0) {
- X x = 0;
- X data += len;
- X len = Min(lendata, cols);
- X }
- X else
- X break;
- X }
- X }
- X if (y <= ylast)
- X clear_lines(y, ylast);
- X}
- X
- X/*
- X * We will try to get the picture:
- X *
- X * op>>>>>>>>>>>op oq
- X * ^ ^ ^
- X * <xskip><-----m1----><---------------od-------------------->
- X * OLD: "You're in a maze of twisty little pieces of code, all alike"
- X * NEW: "in a maze of little twisting pieces of code, all alike"
- X * <-----m1----><----------------nd--------------------->
- X * ^ ^ ^
- X * np>>>>>>>>>>>np nq
- X * where
- X * op, oq, np, nq are pointers to start and end of Old and New data,
- X * and
- X * xskip = length of indent to be skipped,
- X * m1 = length of Matching part at start,
- X * od = length of Differing end on screen,
- X * nd = length of Differing end in data to be put.
- X */
- XHidden int
- Xput_line(y, xskip, data, len)
- Xint y, xskip;
- Xstring data;
- Xint len;
- X{
- X register char *op, *oq, *np, *nq;
- X int m1, od, nd, delta;
- X
- X /* calculate the magic parameters */
- X op = &line[y][xskip];
- X oq = &line[y][lenline[y]-1];
- X np = data;
- X nq = data + len - 1;
- X m1 = 0;
- X while ((*op&SOCHAR) == (*np&SOCHAR) && op <= oq && np <= nq)
- X op++, np++, m1++;
- X od = oq - op + 1;
- X nd = nq - np + 1;
- X /* now we have the picture above */
- X
- X if (od==0 && nd==0)
- X return;
- X
- X delta = nd - od;
- X move(y, xskip + m1);
- X if (nd > 0) {
- X put_str(np, nd);
- X }
- X if (delta < 0) {
- X clr_to_eol();
- X return;
- X }
- X lenline[y] = xskip + len;
- X if (cur_x == cols) {
- X cur_y++;
- X cur_x = 0;
- X }
- X}
- X
- X/*
- X * Scrolling (part of) the screen up (or down, dy<0).
- X */
- X
- XVisible Procedure
- Xtrmscrollup(yfirst, ylast, by)
- Xregister int yfirst;
- Xregister int ylast;
- Xregister int by;
- X{
- X#ifdef TRACE
- Xfprintf(stderr, "\ttrmscrollup(%d, %d, %d);\n", yfirst, ylast, by);
- X#endif
- X check_started(MESS(7906, "trmscrollup called outside trmstart/trmend"));
- X
- X if (by == 0)
- X return;
- X
- X if (yfirst < 0)
- X yfirst = 0;
- X if (ylast >= lines)
- X ylast = lines-1;
- X
- X if (yfirst > ylast)
- X return;
- X
- X if (so_mode != Off)
- X standend();
- X
- X if (by > 0 && yfirst + by > ylast
- X ||
- X by < 0 && yfirst - by > ylast)
- X {
- X clear_lines(yfirst, ylast);
- X return;
- X }
- X
- X switch (scr_mode) {
- X case BIOS:
- X biosscrollup(yfirst, ylast, by);
- X break;
- X case ANSI:
- X if (by > 0 && yfirst == 0) {
- X lf_scroll(ylast, by);
- X }
- X else if (by > 0) {
- X move_lines(yfirst+by, yfirst, ylast-yfirst+1-by, 1);
- X clear_lines(ylast-by+1, ylast);
- X }
- X else {
- X move_lines(ylast+by, ylast, ylast-yfirst+1+by, -1);
- X clear_lines(yfirst, yfirst-by-1);
- X }
- X break;
- X }
- X}
- X
- X/*
- X * Synchronization, move cursor to given position (or previous if < 0).
- X */
- X
- XVisible Procedure
- Xtrmsync(y, x)
- X int y;
- X int x;
- X{
- X#ifdef TRACE
- Xfprintf(stderr, "\ttrmsync(%d, %d);\n", y, x);
- X#endif
- X check_started(MESS(7907, "trmsync called outside trmstart/trmend"));
- X
- X if (0 <= y && y < lines && 0 <= x && x < cols) {
- X move(y, x);
- X }
- X VOID fflush(stdout);
- X}
- X
- X/*
- X * Send a bell, visible if possible.
- X */
- X
- XVisible Procedure
- Xtrmbell()
- X{
- X#ifdef TRACE
- Xfprintf(stderr, "\ttrmbell();\n");
- X#endif
- X check_started(MESS(7908, "trmbell called outside trmstart/trmend"));
- X ring_bell();
- X}
- X
- X/*
- X * Now for the real work: here are all low level routines that really
- X * differ for BIOS or ANSI mode.
- X */
- X
- X/*
- X * BIOS video io is called by generating an 8086 software interrupt,
- X * using lattice's int86() function.
- X * To ease coding, all routines fill in the apropriate parameters in regs,
- X * and then call bios10(code), where code is to be placed in ah.
- X */
- X
- XHidden union REGS regs, outregs;
- X
- X/* A macro for speed */
- X#define bios10(code) (regs.h.ah = (code), int86(0x10, ®s, ®s))
- X#define nbios10(code) (regs.h.ah = (code), int86(0x10, ®s, &outregs))
- X
- X/* Video attributes: (see the BASIC manual) (used for standout mode) */
- X
- XHidden int video_attr;
- X#ifndef GFX
- X#define V_NORMAL 7
- X#else
- X#define V_NORMAL (gfx_mode == TEXT_MODE ? 7 : 0)
- X#endif
- X#define V_STANDOUT (7<<4)
- X
- X/* Some BIOS only routines */
- X
- XHidden get_cols()
- X{
- X bios10(15);
- X return regs.h.ah;
- X}
- X
- X/*
- X * ANSI escape sequences
- X */
- X#define A_CUP "\033[%d;%dH" /* cursor position */
- X#define A_SGR0 "\033[0m" /* set graphics rendition to normal */
- X#define A_SGR7 "\033[7m" /* set graphics rendition to standout */
- X#define A_ED "\033[2J" /* erase display (and cursor home) */
- X#define A_EL "\033[K" /* erase (to end of) line */
- X
- X/*
- X * The following routine is the time bottleneck, I believe!
- X */
- X
- XHidden Procedure
- Xput_str(data, n)
- Xchar *data;
- Xint n;
- X{
- X register char c, so;
- X
- X so = so_mode;
- X if (scr_mode == BIOS) {
- X regs.x.cx = 1; /* repition count */
- X regs.h.bh = 0; /* page number */
- X regs.h.bl = video_attr;
- X while (--n >= 0) {
- X c = (*data++)&SOCHAR;
- X if ((c&SOBIT) != so) {
- X so = c&SOBIT;
- X so ? standout() : standend();
- X regs.h.bl = video_attr;
- X }
- X regs.h.al = c&CHAR;
- X nbios10(9);
- X if (cur_x >= cols-1) {
- X line[cur_y][cols-1] = c;
- X continue;
- X }
- X regs.h.dh = cur_y;
- X regs.h.dl = cur_x + 1;
- X nbios10(2);
- X line[cur_y][cur_x] = c;
- X cur_x++;
- X }
- X }
- X else {
- X while (--n >= 0) {
- X c = (*data++)&SOCHAR;
- X if ((c&SOBIT) != so) {
- X so = c&SOBIT;
- X so ? standout() : standend();
- X }
- X putch(c&CHAR);
- X line[cur_y][cur_x] = c;
- X cur_x++;
- X }
- X }
- X}
- X
- X/*
- X * Move to position y,x on the screen
- X */
- X
- XHidden Procedure
- Xmove(y, x)
- Xint y, x;
- X{
- X if (scr_mode != BIOS && cur_y == y && cur_x == x)
- X return;
- X switch (scr_mode) {
- X case BIOS:
- X regs.h.dh = y;
- X regs.h.dl = x;
- X regs.h.bh = 0; /* Page; must be 0 for graphics */
- X bios10(2);
- X break;
- X case ANSI:
- X cprintf(A_CUP, y+1, x+1);
- X break;
- X }
- X cur_y = y;
- X cur_x = x;
- X}
- X
- XHidden Procedure
- Xstandout()
- X{
- X so_mode = On;
- X switch (scr_mode) {
- X case BIOS:
- X video_attr = V_STANDOUT;
- X break;
- X case ANSI:
- X cputs(A_SGR7);
- X break;
- X }
- X}
- X
- XHidden Procedure
- Xstandend()
- X{
- X so_mode = Off;
- X switch (scr_mode) {
- X case BIOS:
- X video_attr = V_NORMAL;
- X break;
- X case ANSI:
- X cputs(A_SGR0);
- X break;
- X }
- X}
- X
- X#ifdef UNUSED
- XHidden Procedure
- Xput_c(c)
- Xint c;
- X{
- X int ch;
- X
- X ch = c&CHAR;
- X#ifndef NDEBUG
- X if (!isprint(ch)) {
- X ch = '?';
- X c = (c&SOBIT)|'?';
- X }
- X#endif
- X switch (scr_mode) {
- X case BIOS:
- X regs.h.al = ch;
- X regs.h.bl = video_attr;
- X regs.x.cx = 1; /* repition count */
- X regs.h.bh = 0; /* page number */
- X bios10(9);
- X if (cur_x >= cols-1) {
- X line[cur_y][cols-1] = c;
- X return;
- X }
- X regs.h.dh = cur_y;
- X regs.h.dl = cur_x + 1;
- X bios10(2);
- X break;
- X case ANSI:
- X putch(ch);
- X break;
- X }
- X line[cur_y][cur_x] = c;
- X cur_x++;
- X}
- X#endif /* UNUSED */
- X
- XHidden Procedure
- Xclear_lines(yfirst, ylast)
- Xint yfirst, ylast ;
- X{
- X register int y;
- X
- X if (scr_mode == BIOS) {
- X regs.h.al = 0; /* scroll with al = 0 means blank window */
- X regs.h.ch = yfirst;
- X regs.h.cl = 0;
- X regs.h.dh = ylast;
- X regs.h.dl = cols-1;
- X regs.h.bh = V_NORMAL;
- X bios10(6);
- X for (y = yfirst; y <= ylast; y++)
- X lenline[y] = 0;
- X return;
- X }
- X /* scr_mode == ANSI */
- X if (yfirst == 0 && ylast == lines-1) {
- X if (so_mode == On)
- X standend();
- X move(0, 0); /* since some ANSI'd don't move */
- X cputs(A_ED);
- X cur_y = cur_x = 0;
- X for (y = yfirst; y < ylast; y++)
- X lenline[y] = 0;
- X return;
- X }
- X for (y = yfirst; y <= ylast; y++) {
- X if (lenline[y] > 0) {
- X move(y, 0);
- X clr_to_eol();
- X }
- X }
- X}
- X
- XHidden Procedure
- Xclr_to_eol()
- X{
- X if (so_mode == On)
- X standend();
- X switch (scr_mode) {
- X case BIOS:
- X regs.h.bh = 0; /* page */
- X regs.x.cx = lenline[cur_y] - cur_x;
- X regs.h.al = ' ';
- X regs.h.bl = V_NORMAL;
- X bios10(9);
- X break;
- X case ANSI:
- X cputs(A_EL);
- X break;
- X }
- X lenline[cur_y] = cur_x;
- X}
- X
- XHidden Procedure /* scrolling for BIOS */
- Xbiosscrollup(yfirst, ylast, by)
- Xint yfirst;
- Xint ylast;
- Xint by;
- X{
- X regs.h.al = (by < 0 ? -by : by);
- X regs.h.ch = yfirst;
- X regs.h.cl = 0;
- X regs.h.dh = ylast;
- X regs.h.dl = cols-1;
- X regs.h.bh= V_NORMAL;
- X bios10(by < 0 ? 7 : 6);
- X cur_y = cur_x = Undefined;
- X if (by > 0)
- X scr_lines(yfirst, ylast, by, 1);
- X else
- X scr_lines(ylast, yfirst, -by, -1);
- X}
- X
- XHidden Procedure /* Reset internal administration accordingly */
- Xscr_lines(yfrom, yto, n, dy)
- Xint yfrom, yto, n, dy;
- X{
- X register int y, x;
- X char *saveln;
- X
- X while (n-- > 0) {
- X saveln = line[yfrom];
- X for (y = yfrom; y != yto; y += dy) {
- X line[y] = line[y+dy];
- X lenline[y] = lenline[y+dy];
- X }
- X line[yto] = saveln;
- X for (x = 0; x < cols; x++ )
- X line[yto][x] = ' ';
- X lenline[yto] = 0;
- X }
- X}
- X
- XHidden Procedure
- Xlf_scroll(yto, by)
- Xint yto;
- Xint by;
- X{
- X register int n = by;
- X
- X move(lines-1, 0);
- X while (n-- > 0) {
- X putch('\n');
- X }
- X scr_lines(0, lines-1, by, 1);
- X move_lines(lines-1-by, lines-1, lines-1-yto, -1);
- X clear_lines(yto-by+1, yto);
- X}
- X
- XHidden Procedure /* for dumb scrolling, uses and updates */
- Xmove_lines(yfrom, yto, n, dy) /* internal administration */
- Xint yfrom;
- Xint yto;
- Xint n;
- Xint dy;
- X{
- X while (n-- > 0) {
- X put_line(yto, 0, line[yfrom], lenline[yfrom]);
- X yfrom += dy;
- X yto += dy;
- X }
- X}
- X
- XHidden Procedure ring_bell()
- X{
- X switch (scr_mode) {
- X case BIOS:
- X regs.h.al = '\007';
- X regs.h.bl = V_NORMAL;
- X bios10(14);
- X break;
- X case ANSI:
- X putch('\007');
- X break;
- X }
- X}
- X
- X/*
- X * Show the current internal statuses of the screen on stderr.
- X * For debugging only.
- X */
- X
- X#ifdef SHOW
- XVisible Procedure
- Xtrmshow(s)
- Xchar *s;
- X{
- X int y, x;
- X
- X fprintf(stderr, "<<< %s >>>\n", s);
- X for (y = 0; y < lines; y++) {
- X for (x = 0; x <= lenline[y] /*** && x < cols ***/ ; x++) {
- X fputc(line[y][x]&CHAR, stderr);
- X }
- X fputc('\n', stderr);
- X for (x = 0; x <= lenline[y] && x < cols-1; x++) {
- X if (line[y][x]&SOBIT)
- X fputc('-', stderr);
- X else
- X fputc(' ', stderr);
- X }
- X fputc('\n', stderr);
- X }
- X fprintf(stderr, "CUR_Y = %d, CUR_X = %d.\n", cur_y, cur_x);
- X VOID fflush(stderr);
- X}
- X#endif
- X
- X/*
- X * Interrupt handling.
- X *
- X * (This has not properly been tested, nor is it clear that
- X * this interface is what we want. Anyway, it's here for you
- X * to experiment with. What does it do, you may ask?
- X * Assume an interactive program which reads its characters
- X * through trminput. Assume ^C is the interrupt character.
- X * Normally, ^C is treated just like any other character: when
- X * typed, it turns up in the input. The program may understand
- X * input ^C as "quit from the current mode".
- X * Occasionally, the program goes into a long period of computation.
- X * Now it would be uninterruptible, except if it calls trminterrupt
- X * at times in its computational loop. Trminterrupt magically looks
- X * ahead in the input queue, and if it sees a ^C, discards all input
- X * before that point and returns Yes. It also sets a flag, so that
- X * the interupt "sticks around" until either trminput or trmavail
- X * is called. It is undefined whether typing ^C several times in
- X * a row is seen as one interrupt, or an interrupt followed by input
- X * of ^C's. A program should be prepared for either.)
- X */
- X
- Xstatic bool intrflag= No;
- X
- Xstatic
- Xhandler(sig)
- X int sig;
- X{
- X signal(sig, handler);
- X intrflag= Yes;
- X}
- X
- Xstatic
- Xset_handler()
- X{
- X signal(SIGINT, handler);
- X}
- X
- Xbool
- Xtrminterrupt()
- X{
- X /* Force a check for ^C which will call handler. */
- X /* (This does a ^C check even if stdin is in RAW mode. */
- X (void) kbhit();
- X return intrflag;
- X}
- X
- X
- X/* Definitions for DOS function calls. */
- X
- X#define IOCTL 0x44
- X#define IOCTL_GETDATA 0x4400
- X#define IOCTL_SETDATA 0x4401
- X#define DEVICEBIT 0x80
- X#define RAWBIT 0x20
- X
- X#define BREAKCK 0x33
- X#define GET 0x00
- X#define SET 0x01
- X
- X#define IOCTL_GETSTS 0x4406
- X
- X#define STDIN_HANDLE 0
- X
- X/*
- X * Terminal input without echo.
- X */
- X
- Xint
- Xtrminput()
- X{
- X char c;
- X
- X intrflag= No;
- X /* Assume stdin is in RAW mode; this turns echo and ^C checks off. */
- X if (read(STDIN_HANDLE, &c, 1) < 1)
- X return -1;
- X else
- X return c;
- X}
- X
- X/*
- X * Check for character available.
- X *
- X */
- X
- Xtrmavail()
- X{
- X intrflag= No;
- X regs.x.ax= IOCTL_GETSTS;
- X regs.x.bx= STDIN_HANDLE;
- X intdos(®s, ®s);
- X if (regs.x.cflag)
- X return -1; /* Error */
- X return regs.h.al != 0;
- X}
- X
- Xtrmsuspend()
- X{
- X /* Not implementable on MS-DOS */
- X}
- X
- X/* Issue an IOCTL to turn RAW for a device on or off. */
- X
- Xsetraw(handle, raw)
- X int handle;
- X bool raw;
- X{
- X regs.x.ax= IOCTL_GETDATA;
- X regs.x.bx= handle;
- X intdos(®s, ®s);
- X if (regs.x.cflag || !(regs.h.dl & DEVICEBIT))
- X return; /* Error or not a device -- ignore it */
- X regs.h.dh= 0;
- X if (raw)
- X regs.h.dl |= RAWBIT;
- X else
- X regs.h.dl &= ~RAWBIT;
- X regs.x.ax= IOCTL_SETDATA;
- X intdos(®s, ®s);
- X /* Ignore errors */
- X}
- X
- X/* Get the raw bit of a device. */
- X
- Xint
- Xgetraw(handle)
- X int handle;
- X{
- X regs.x.ax= IOCTL_GETDATA;
- X regs.x.bx= handle;
- X intdos(®s, ®s);
- X return !regs.x.cflag &&
- X (regs.h.dh & (DEVICEBIT|RAWBIT)) == (DEVICEBIT|RAWBIT);
- X}
- X
- X/* Set the break status. */
- X
- Xsetbreak(on)
- X bool on;
- X{
- X bdos(BREAKCK, on, SET);
- X}
- X
- X/* Get the break status. */
- X
- Xint
- Xgetbreak()
- X{
- X regs.x.ax= (BREAKCK << 8) | GET;
- X intdos(®s, ®s);
- X return regs.h.dl;
- X}
- END_OF_FILE
- if test 23047 -ne `wc -c <'Ports/msdos/ptrm.c'`; then
- echo shar: \"'Ports/msdos/ptrm.c'\" unpacked with wrong size!
- fi
- # end of 'Ports/msdos/ptrm.c'
- fi
- echo shar: End of archive 5 \(of 19\).
- cp /dev/null ark5isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 19 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
-