Merge branch 'tty-status' into win-tty-status
This commit is contained in:
@@ -26,7 +26,7 @@ E void NDECL(display_gamewindows);
|
||||
E void NDECL(newgame);
|
||||
E void FDECL(welcome, (BOOLEAN_P));
|
||||
E time_t NDECL(get_realtime);
|
||||
E boolean FDECL(argcheck, (int, char **, enum earlyarg));
|
||||
E int FDECL(argcheck, (int, char **, enum earlyarg));
|
||||
|
||||
/* ### apply.c ### */
|
||||
|
||||
@@ -786,6 +786,7 @@ E void NDECL(read_wizkit);
|
||||
E int FDECL(read_sym_file, (int));
|
||||
E int FDECL(parse_sym_line, (char *, int));
|
||||
E void FDECL(paniclog, (const char *, const char *));
|
||||
E void FDECL(testinglog, (const char *, const char *, const char *));
|
||||
E int FDECL(validate_prefix_locations, (char *));
|
||||
#ifdef SELECTSAVED
|
||||
E char *FDECL(plname_from_file, (const char *));
|
||||
@@ -1157,6 +1158,7 @@ E boolean FDECL(usmellmon, (struct permonst *));
|
||||
|
||||
E int FDECL(mapglyph, (int, int *, int *, unsigned *, int, int));
|
||||
E char *FDECL(encglyph, (int));
|
||||
E const char *FDECL(decode_mixed, (char *,const char *));
|
||||
E void FDECL(genl_putmixed, (winid, int, const char *));
|
||||
|
||||
/* ### mcastu.c ### */
|
||||
|
||||
@@ -221,6 +221,16 @@ enum getloc_filters {
|
||||
NUM_GFILTER
|
||||
};
|
||||
|
||||
struct debug_flags {
|
||||
boolean test;
|
||||
#ifdef TTY_GRAPHICS
|
||||
boolean ttystatus;
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
boolean immediateflips;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct instance_flags {
|
||||
/* stuff that really isn't option or platform related. They are
|
||||
* set and cleared during the game to control the internal
|
||||
@@ -423,6 +433,7 @@ struct instance_flags {
|
||||
short mines_prize_type; /* luckstone */
|
||||
short soko_prize_type1; /* bag of holding or */
|
||||
short soko_prize_type2; /* amulet of reflection */
|
||||
struct debug_flags debug;
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* #define BETA */ /* development or beta testing [MRS] */
|
||||
#define BETA /* development or beta testing [MRS] */
|
||||
|
||||
#define DEBUG
|
||||
|
||||
|
||||
@@ -69,6 +69,19 @@ struct DisplayDesc {
|
||||
|
||||
#endif /* WINDOW_STRUCTS */
|
||||
|
||||
#ifdef STATUS_HILITES
|
||||
struct tty_status_fields {
|
||||
int idx;
|
||||
int color;
|
||||
int attr;
|
||||
int x, y;
|
||||
size_t lth;
|
||||
boolean valid;
|
||||
boolean dirty;
|
||||
boolean redraw;
|
||||
};
|
||||
#endif
|
||||
|
||||
#define MAXWIN 20 /* maximum number of windows, cop-out */
|
||||
|
||||
/* tty dependent window types */
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
/* various code that was replicated in *main.c */
|
||||
|
||||
#include "hack.h"
|
||||
#include <ctype.h>
|
||||
|
||||
#ifndef NO_SIGNAL
|
||||
#include <signal.h>
|
||||
@@ -16,6 +17,7 @@ STATIC_DCL void NDECL(do_positionbar);
|
||||
#endif
|
||||
STATIC_DCL void FDECL(regen_hp, (int));
|
||||
STATIC_DCL void FDECL(interrupt_multi, (const char *));
|
||||
STATIC_DCL void FDECL(debug_fields, (const char *));
|
||||
|
||||
void
|
||||
moveloop(resuming)
|
||||
@@ -752,11 +754,18 @@ const char *msg;
|
||||
*/
|
||||
|
||||
static struct early_opt earlyopts[] = {
|
||||
{ARG_DEBUG, "debug", 5, FALSE},
|
||||
{ARG_DEBUG, "debug", 5, TRUE},
|
||||
{ARG_VERSION, "version", 4, TRUE},
|
||||
};
|
||||
|
||||
boolean
|
||||
/*
|
||||
* Returns:
|
||||
* 0 = no match
|
||||
* 1 = found and skip past this argument
|
||||
* 2 = found and trigger immediate exit
|
||||
*/
|
||||
|
||||
int
|
||||
argcheck(argc, argv, e_arg)
|
||||
int argc;
|
||||
char *argv[];
|
||||
@@ -774,7 +783,7 @@ enum earlyarg e_arg;
|
||||
if ((idx >= SIZE(earlyopts)) || (argc <= 1))
|
||||
return FALSE;
|
||||
|
||||
for (i = 1; i < argc; ++i) {
|
||||
for (i = 0; i < argc; ++i) {
|
||||
if (argv[i][0] != '-')
|
||||
continue;
|
||||
if (argv[i][1] == '-') {
|
||||
@@ -789,15 +798,20 @@ enum earlyarg e_arg;
|
||||
}
|
||||
|
||||
if (match) {
|
||||
const char *extended_opt = index(userea,':');
|
||||
|
||||
if (!extended_opt)
|
||||
extended_opt = index(userea, '=');
|
||||
switch(e_arg) {
|
||||
case ARG_DEBUG:
|
||||
if (extended_opt) {
|
||||
extended_opt++;
|
||||
debug_fields(extended_opt);
|
||||
}
|
||||
return 1;
|
||||
break;
|
||||
case ARG_VERSION: {
|
||||
boolean insert_into_pastebuf = FALSE;
|
||||
const char *extended_opt = index(userea,':');
|
||||
|
||||
if (!extended_opt)
|
||||
extended_opt = index(userea, '=');
|
||||
|
||||
if (extended_opt) {
|
||||
extended_opt++;
|
||||
@@ -812,7 +826,7 @@ enum earlyarg e_arg;
|
||||
}
|
||||
}
|
||||
early_version_info(insert_into_pastebuf);
|
||||
return TRUE;
|
||||
return 2;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -822,4 +836,62 @@ enum earlyarg e_arg;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* These are internal controls to aid developers with
|
||||
* testing and debugging particular aspects of the code.
|
||||
* They are not player options and the only place they
|
||||
* are documented is right here. No gameplay is altered.
|
||||
*
|
||||
* test - test whether this parser is working
|
||||
* ttystatus - TTY:
|
||||
* immediateflips - WIN32: turn off display performance
|
||||
* optimization so that display output
|
||||
* can be debugged without buffering.
|
||||
*/
|
||||
void
|
||||
debug_fields(opts)
|
||||
const char *opts;
|
||||
{
|
||||
char *op;
|
||||
boolean negated = FALSE;
|
||||
|
||||
while ((op = index(opts, ',')) != 0) {
|
||||
*op++ = 0;
|
||||
/* recurse */
|
||||
debug_fields(op);
|
||||
}
|
||||
if (strlen(opts) > BUFSZ / 2)
|
||||
return;
|
||||
|
||||
|
||||
/* strip leading and trailing white space */
|
||||
while (isspace((uchar) *opts))
|
||||
opts++;
|
||||
op = eos((char *) opts);
|
||||
while (--op >= opts && isspace((uchar) *op))
|
||||
*op = '\0';
|
||||
|
||||
if (!*opts) {
|
||||
/* empty */
|
||||
return;
|
||||
}
|
||||
while ((*opts == '!') || !strncmpi(opts, "no", 2)) {
|
||||
if (*opts == '!')
|
||||
opts++;
|
||||
else
|
||||
opts += 2;
|
||||
negated = !negated;
|
||||
}
|
||||
if (match_optname(opts, "test", 4, FALSE))
|
||||
iflags.debug.test = negated ? FALSE : TRUE;
|
||||
#ifdef TTY_GRAPHICS
|
||||
if (match_optname(opts, "ttystatus", 9, FALSE))
|
||||
iflags.debug.ttystatus = negated ? FALSE : TRUE;
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
if (match_optname(opts, "immediateflips", 14, FALSE))
|
||||
iflags.debug.immediateflips = negated ? FALSE : TRUE;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
/*allmain.c*/
|
||||
|
||||
15
src/botl.c
15
src/botl.c
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 botl.c $NHDT-Date: 1506903619 2017/10/02 00:20:19 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.81 $ */
|
||||
/* NetHack 3.6 botl.c $NHDT-Date: 1525696908 2018/05/07 12:41:48 $ $NHDT-Branch: tty-status $:$NHDT-Revision: 1.91 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/*-Copyright (c) Michael Allison, 2006. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
@@ -483,14 +483,14 @@ STATIC_DCL struct istat_s initblstats[MAXBLSTATS] = {
|
||||
INIT_BLSTAT("charisma", " Ch:%s", ANY_INT, 10, BL_CH),
|
||||
INIT_BLSTAT("alignment", " %s", ANY_STR, 40, BL_ALIGN),
|
||||
INIT_BLSTAT("score", " S:%s", ANY_LONG, 20, BL_SCORE),
|
||||
INIT_BLSTAT("carrying-capacity", " %s", ANY_LONG, 20, BL_CAP),
|
||||
INIT_BLSTAT("carrying-capacity", " %s", ANY_INT, 20, BL_CAP),
|
||||
INIT_BLSTAT("gold", " %s", ANY_LONG, 30, BL_GOLD),
|
||||
INIT_BLSTATP("power", " Pw:%s", ANY_INT, 10, BL_ENEMAX, BL_ENE),
|
||||
INIT_BLSTAT("power-max", "(%s)", ANY_INT, 10, BL_ENEMAX),
|
||||
INIT_BLSTAT("experience-level", " Xp:%s", ANY_LONG, 10, BL_XP),
|
||||
INIT_BLSTAT("experience-level", " Xp:%s", ANY_INT, 10, BL_XP),
|
||||
INIT_BLSTAT("armor-class", " AC:%s", ANY_INT, 10, BL_AC),
|
||||
INIT_BLSTAT("HD", " HD:%s", ANY_INT, 10, BL_HD),
|
||||
INIT_BLSTAT("time", " T:%s", ANY_INT, 20, BL_TIME),
|
||||
INIT_BLSTAT("time", " T:%s", ANY_LONG, 20, BL_TIME),
|
||||
INIT_BLSTAT("hunger", " %s", ANY_UINT, 40, BL_HUNGER),
|
||||
INIT_BLSTATP("hitpoints", " HP:%s", ANY_INT, 10, BL_HPMAX, BL_HP),
|
||||
INIT_BLSTAT("hitpoints-max", "(%s)", ANY_INT, 10, BL_HPMAX),
|
||||
@@ -630,7 +630,7 @@ bot_via_windowport()
|
||||
|
||||
/* Experience */
|
||||
blstats[idx][BL_XP].a.a_int = u.ulevel;
|
||||
blstats[idx][BL_EXP].a.a_int = u.uexp;
|
||||
blstats[idx][BL_EXP].a.a_long = u.uexp;
|
||||
|
||||
/* Time (moves) */
|
||||
blstats[idx][BL_TIME].a.a_long = moves;
|
||||
@@ -858,7 +858,10 @@ boolean
|
||||
: TRUE;
|
||||
|
||||
fieldname = initblstats[i].fldname;
|
||||
fieldfmt = initblstats[i].fldfmt;
|
||||
if (fld == BL_TITLE && iflags.wc2_hitpointbar)
|
||||
fieldfmt = "%-30s";
|
||||
else
|
||||
fieldfmt = initblstats[i].fldfmt;
|
||||
status_enablefield(fld, fieldname, fieldfmt, fldenabled);
|
||||
}
|
||||
update_all = TRUE;
|
||||
|
||||
28
src/files.c
28
src/files.c
@@ -3542,7 +3542,7 @@ const char *dir UNUSED_if_not_OS2_CODEVIEW;
|
||||
|
||||
/* ---------- END SCOREBOARD CREATION ----------- */
|
||||
|
||||
/* ---------- BEGIN PANIC/IMPOSSIBLE LOG ----------- */
|
||||
/* ---------- BEGIN PANIC/IMPOSSIBLE/TESTING LOG ----------- */
|
||||
|
||||
/*ARGSUSED*/
|
||||
void
|
||||
@@ -3579,7 +3579,31 @@ const char *reason; /* explanation */
|
||||
return;
|
||||
}
|
||||
|
||||
/* ---------- END PANIC/IMPOSSIBLE LOG ----------- */
|
||||
/*ARGSUSED*/
|
||||
void
|
||||
testinglog(filenm, type, reason)
|
||||
const char *filenm; /* ad hoc file name */
|
||||
const char *type;
|
||||
const char *reason; /* explanation */
|
||||
{
|
||||
FILE *lfile;
|
||||
char fnbuf[BUFSZ];
|
||||
|
||||
if (!filenm) return;
|
||||
Strcpy(fnbuf, filenm);
|
||||
if (index(fnbuf, '.') == 0)
|
||||
Strcat(fnbuf, ".log");
|
||||
lfile = fopen_datafile(fnbuf, "a", TROUBLEPREFIX);
|
||||
if (lfile) {
|
||||
time_t now = getnow();
|
||||
int uid = getuid();
|
||||
(void) fprintf(lfile, "%s\n%s\n", type, reason);
|
||||
(void) fclose(lfile);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* ---------- END PANIC/IMPOSSIBLE/TESTING LOG ----------- */
|
||||
|
||||
#ifdef SELF_RECOVER
|
||||
|
||||
|
||||
136
src/mapglyph.c
136
src/mapglyph.c
@@ -247,6 +247,78 @@ int glyph;
|
||||
return encbuf;
|
||||
}
|
||||
|
||||
const char *
|
||||
decode_mixed(buf, str)
|
||||
char *buf;
|
||||
const char *str;
|
||||
{
|
||||
static const char hex[] = "00112233445566778899aAbBcCdDeEfF";
|
||||
char *put = buf;
|
||||
|
||||
if (!put || !str)
|
||||
return "";
|
||||
|
||||
while (*str) {
|
||||
if (*str == '\\') {
|
||||
int rndchk, dcount, so, gv, ch = 0, oc = 0;
|
||||
unsigned os = 0;
|
||||
const char *dp, *save_str;
|
||||
|
||||
save_str = str++;
|
||||
switch (*str) {
|
||||
case 'G': /* glyph value \GXXXXNNNN*/
|
||||
rndchk = dcount = 0;
|
||||
for (++str; *str && ++dcount <= 4; ++str)
|
||||
if ((dp = index(hex, *str)) != 0)
|
||||
rndchk = (rndchk * 16) + ((int) (dp - hex) / 2);
|
||||
else
|
||||
break;
|
||||
if (rndchk == context.rndencode) {
|
||||
gv = dcount = 0;
|
||||
for (; *str && ++dcount <= 4; ++str)
|
||||
if ((dp = index(hex, *str)) != 0)
|
||||
gv = (gv * 16) + ((int) (dp - hex) / 2);
|
||||
else
|
||||
break;
|
||||
so = mapglyph(gv, &ch, &oc, &os, 0, 0);
|
||||
*put++ = showsyms[so];
|
||||
/* 'str' is ready for the next loop iteration and '*str'
|
||||
should not be copied at the end of this iteration */
|
||||
continue;
|
||||
} else {
|
||||
/* possible forgery - leave it the way it is */
|
||||
str = save_str;
|
||||
}
|
||||
break;
|
||||
#if 0
|
||||
case 'S': /* symbol offset */
|
||||
so = rndchk = dcount = 0;
|
||||
for (++str; *str && ++dcount <= 4; ++str)
|
||||
if ((dp = index(hex, *str)) != 0)
|
||||
rndchk = (rndchk * 16) + ((int) (dp - hex) / 2);
|
||||
else
|
||||
break;
|
||||
if (rndchk == context.rndencode) {
|
||||
dcount = 0;
|
||||
for (; *str && ++dcount <= 2; ++str)
|
||||
if ((dp = index(hex, *str)) != 0)
|
||||
so = (so * 16) + ((int) (dp - hex) / 2);
|
||||
else
|
||||
break;
|
||||
}
|
||||
*put++ = showsyms[so];
|
||||
break;
|
||||
#endif
|
||||
case '\\':
|
||||
break;
|
||||
}
|
||||
}
|
||||
*put++ = *str++;
|
||||
}
|
||||
*put = '\0';
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* This differs from putstr() because the str parameter can
|
||||
* contain a sequence of characters representing:
|
||||
@@ -265,71 +337,9 @@ winid window;
|
||||
int attr;
|
||||
const char *str;
|
||||
{
|
||||
static const char hex[] = "00112233445566778899aAbBcCdDeEfF";
|
||||
char buf[BUFSZ];
|
||||
const char *cp = str;
|
||||
char *put = buf;
|
||||
|
||||
while (*cp) {
|
||||
if (*cp == '\\') {
|
||||
int rndchk, dcount, so, gv, ch = 0, oc = 0;
|
||||
unsigned os = 0;
|
||||
const char *dp, *save_cp;
|
||||
|
||||
save_cp = cp++;
|
||||
switch (*cp) {
|
||||
case 'G': /* glyph value \GXXXXNNNN*/
|
||||
rndchk = dcount = 0;
|
||||
for (++cp; *cp && ++dcount <= 4; ++cp)
|
||||
if ((dp = index(hex, *cp)) != 0)
|
||||
rndchk = (rndchk * 16) + ((int) (dp - hex) / 2);
|
||||
else
|
||||
break;
|
||||
if (rndchk == context.rndencode) {
|
||||
gv = dcount = 0;
|
||||
for (; *cp && ++dcount <= 4; ++cp)
|
||||
if ((dp = index(hex, *cp)) != 0)
|
||||
gv = (gv * 16) + ((int) (dp - hex) / 2);
|
||||
else
|
||||
break;
|
||||
so = mapglyph(gv, &ch, &oc, &os, 0, 0);
|
||||
*put++ = showsyms[so];
|
||||
/* 'cp' is ready for the next loop iteration and '*cp'
|
||||
should not be copied at the end of this iteration */
|
||||
continue;
|
||||
} else {
|
||||
/* possible forgery - leave it the way it is */
|
||||
cp = save_cp;
|
||||
}
|
||||
break;
|
||||
#if 0
|
||||
case 'S': /* symbol offset */
|
||||
so = rndchk = dcount = 0;
|
||||
for (++cp; *cp && ++dcount <= 4; ++cp)
|
||||
if ((dp = index(hex, *cp)) != 0)
|
||||
rndchk = (rndchk * 16) + ((int) (dp - hex) / 2);
|
||||
else
|
||||
break;
|
||||
if (rndchk == context.rndencode) {
|
||||
dcount = 0;
|
||||
for (; *cp && ++dcount <= 2; ++cp)
|
||||
if ((dp = index(hex, *cp)) != 0)
|
||||
so = (so * 16) + ((int) (dp - hex) / 2);
|
||||
else
|
||||
break;
|
||||
}
|
||||
*put++ = showsyms[so];
|
||||
break;
|
||||
#endif
|
||||
case '\\':
|
||||
break;
|
||||
}
|
||||
}
|
||||
*put++ = *cp++;
|
||||
}
|
||||
*put = '\0';
|
||||
/* now send it to the normal putstr */
|
||||
putstr(window, attr, buf);
|
||||
putstr(window, attr, decode_mixed(buf, str));
|
||||
}
|
||||
|
||||
/*mapglyph.c*/
|
||||
|
||||
@@ -331,9 +331,14 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/
|
||||
Strcpy(hackdir, HACKDIR);
|
||||
#endif
|
||||
if (argc > 1) {
|
||||
if (argcheck(argc, argv, ARG_VERSION))
|
||||
if (argcheck(argc, argv, ARG_VERSION) == 2)
|
||||
nethack_exit(EXIT_SUCCESS);
|
||||
|
||||
if (argcheck(argc, argv, ARG_DEBUG) == 1) {
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
|
||||
if (!strncmp(argv[1], "-d", 2) && argv[1][2] != 'e') {
|
||||
/* avoid matching "-dec" for DECgraphics; since the man page
|
||||
* says -d directory, hope nobody's using -desomething_else
|
||||
|
||||
@@ -111,9 +111,14 @@ char *argv[];
|
||||
dir = nh_getenv("HACKDIR");
|
||||
|
||||
if (argc > 1) {
|
||||
if (argcheck(argc, argv, ARG_VERSION))
|
||||
if (argcheck(argc, argv, ARG_VERSION) == 2)
|
||||
exit(EXIT_SUCCESS);
|
||||
|
||||
if (argcheck(argc, argv, ARG_DEBUG) == 1) {
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
|
||||
if (!strncmp(argv[1], "-d", 2) && argv[1][2] != 'e') {
|
||||
/* avoid matching "-dec" for DECgraphics; since the man page
|
||||
* says -d directory, hope nobody's using -desomething_else
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 nttty.c $NHDT-Date: 1524931557 2018/04/28 16:05:57 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.71 $ */
|
||||
/* NetHack 3.6 nttty.c $NHDT-Date: 1525643540 2018/05/06 21:52:20 $ $NHDT-Branch: tty-status $:$NHDT-Revision: 1.77 $ */
|
||||
/* Copyright (c) NetHack PC Development Team 1993 */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
* Switch to low level console output routines M. Allison 2003/10/01
|
||||
* Restrict cursor movement until input pending M. Lehotay 2003/10/02
|
||||
* Call Unicode version of output API on NT R. Chason 2005/10/28
|
||||
* Use of back buffer to improve performance B. House 2018/05/06
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -151,6 +152,249 @@ SOURCEWHERE pSourceWhere;
|
||||
SOURCEAUTHOR pSourceAuthor;
|
||||
KEYHANDLERNAME pKeyHandlerName;
|
||||
|
||||
/* CP437 to Unicode mapping according to the Unicode Consortium */
|
||||
static const WCHAR cp437[] = {
|
||||
0x0020, 0x263A, 0x263B, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022,
|
||||
0x25D8, 0x25CB, 0x25D9, 0x2642, 0x2640, 0x266A, 0x266B, 0x263C,
|
||||
0x25BA, 0x25C4, 0x2195, 0x203C, 0x00B6, 0x00A7, 0x25AC, 0x21A8,
|
||||
0x2191, 0x2193, 0x2192, 0x2190, 0x221F, 0x2194, 0x25B2, 0x25BC,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
|
||||
0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
|
||||
0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
|
||||
0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
|
||||
0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
|
||||
0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
|
||||
0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x2302,
|
||||
0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7,
|
||||
0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
|
||||
0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
|
||||
0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
|
||||
0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba,
|
||||
0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
|
||||
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
|
||||
0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
|
||||
0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
|
||||
0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
|
||||
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b,
|
||||
0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580,
|
||||
0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4,
|
||||
0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229,
|
||||
0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248,
|
||||
0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0
|
||||
};
|
||||
|
||||
/*
|
||||
* cpConsole provides the mapping of characters in the console code page to
|
||||
* UNICODE. It maps a character to at most two WCHARs storing the number of
|
||||
* WCHARs in count.
|
||||
*
|
||||
* NOTE: cpConsole is only valid if has_unicode is TRUE.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
WCHAR characters[2];
|
||||
int count;
|
||||
} CodePageMapping;
|
||||
|
||||
static CodePageMapping cpConsole[256];
|
||||
|
||||
static void initialize_cp_console()
|
||||
{
|
||||
if (has_unicode) {
|
||||
UINT codePage = GetConsoleOutputCP();
|
||||
|
||||
for (int i = 0; i < 256; i++) {
|
||||
char c = (char)i;
|
||||
cpConsole[i].count = MultiByteToWideChar(codePage, 0, &c, 1,
|
||||
&cpConsole[i].characters[0], 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Console Buffer Flipping Support
|
||||
*
|
||||
* To minimize the number of calls into the WriteConsoleOutputXXX methods,
|
||||
* we implement a notion of a console back buffer which keeps the next frame
|
||||
* of console output as it is being composed. When ready to show the new
|
||||
* frame, we compare this next frame to what is currently being output and
|
||||
* only call WriteConsoleOutputXXX for those console values that need to
|
||||
* change.
|
||||
*
|
||||
*/
|
||||
|
||||
#define CONSOLE_CLEAR_ATTRIBUTE (FOREGROUND_RED | FOREGROUND_GREEN \
|
||||
| FOREGROUND_BLUE)
|
||||
#define CONSOLE_CLEAR_CHARACTER (' ')
|
||||
|
||||
typedef struct {
|
||||
WCHAR characters[2];
|
||||
int count;
|
||||
WORD attribute;
|
||||
} cell_t;
|
||||
|
||||
typedef struct {
|
||||
cell_t * cells;
|
||||
} console_buffer_t;
|
||||
|
||||
static int buffer_width;
|
||||
static int buffer_height;
|
||||
|
||||
console_buffer_t back_buffer;
|
||||
console_buffer_t front_buffer;
|
||||
cell_t clear_cell;
|
||||
cell_t undefined_cell;
|
||||
|
||||
static boolean buffer_flipping_initialized = FALSE;
|
||||
|
||||
static void check_buffer_size(int width, int height);
|
||||
static cell_t * buffer_get_cell(console_buffer_t * buffer, int x, int y);
|
||||
|
||||
static void back_buffer_flip();
|
||||
|
||||
static void buffer_fill_to_end(console_buffer_t * buffer, cell_t * cell,
|
||||
int x, int y);
|
||||
static void back_buffer_clear_to_end_of_line(int x, int y);
|
||||
static void back_buffer_write(cell_t * cell, int x, int y);
|
||||
|
||||
static void initialize_buffer_flipping(int width, int height)
|
||||
{
|
||||
if (buffer_flipping_initialized) {
|
||||
check_buffer_size(width, height);
|
||||
return;
|
||||
}
|
||||
|
||||
buffer_width = 0;
|
||||
buffer_height = 0;
|
||||
|
||||
back_buffer.cells = NULL;
|
||||
front_buffer.cells = NULL;
|
||||
|
||||
clear_cell.attribute = CONSOLE_CLEAR_ATTRIBUTE;
|
||||
clear_cell.characters[0] = CONSOLE_CLEAR_CHARACTER;
|
||||
clear_cell.characters[1] = 0;
|
||||
clear_cell.count = 1;
|
||||
|
||||
undefined_cell = clear_cell;
|
||||
undefined_cell.count = 0;
|
||||
|
||||
check_buffer_size(width, height);
|
||||
|
||||
buffer_flipping_initialized = TRUE;
|
||||
}
|
||||
|
||||
static void resize_buffer(console_buffer_t * buffer, cell_t * fill,
|
||||
int width, int height)
|
||||
{
|
||||
cell_t * cells = (cell_t *)malloc(sizeof(cell_t) * width * height);
|
||||
cell_t * dst = cells;
|
||||
cell_t * sentinel = dst + (width * height);
|
||||
|
||||
while (dst != sentinel)
|
||||
*dst++ = *fill;
|
||||
|
||||
int height_to_copy = (buffer_height > height ? height : buffer_height);
|
||||
int bytes_to_copy = (buffer_width > width ? width : buffer_width)
|
||||
* sizeof(cell_t);
|
||||
|
||||
for (int y = 0; y < height_to_copy; y++)
|
||||
memcpy(cells + (width * y), buffer->cells + (buffer_width * y),
|
||||
bytes_to_copy);
|
||||
|
||||
free(buffer->cells);
|
||||
buffer->cells = cells;
|
||||
}
|
||||
|
||||
static void check_buffer_size(int width, int height)
|
||||
{
|
||||
if (width != buffer_width || height != buffer_height) {
|
||||
resize_buffer(&back_buffer, &clear_cell, width, height);
|
||||
resize_buffer(&front_buffer, &undefined_cell, width, height);
|
||||
buffer_width = width;
|
||||
buffer_height = height;
|
||||
}
|
||||
}
|
||||
|
||||
static cell_t * buffer_get_cell(console_buffer_t * buffer, int x, int y)
|
||||
{
|
||||
return buffer->cells + (buffer_width * y) + x;
|
||||
}
|
||||
|
||||
static void back_buffer_flip()
|
||||
{
|
||||
if (!buffer_flipping_initialized)
|
||||
return;
|
||||
|
||||
cell_t * back = back_buffer.cells;
|
||||
cell_t * front = front_buffer.cells;
|
||||
COORD pos;
|
||||
|
||||
for (pos.Y = 0; pos.Y < buffer_height; pos.Y++) {
|
||||
for (pos.X = 0; pos.X < buffer_width; pos.X++) {
|
||||
if (back->attribute != front->attribute) {
|
||||
WriteConsoleOutputAttribute(hConOut, &back->attribute,
|
||||
1, pos, &acount);
|
||||
front->attribute = back->attribute;
|
||||
}
|
||||
if (back->count != front->count ||
|
||||
back->characters[0] != front->characters[0] ||
|
||||
back->characters[1] != front->characters[1]) {
|
||||
if (has_unicode) {
|
||||
WriteConsoleOutputCharacterW(hConOut, back->characters,
|
||||
back->count, pos, &ccount);
|
||||
} else {
|
||||
char ch = (char)back->characters[0];
|
||||
WriteConsoleOutputCharacterA(hConOut, &ch, 1, pos,
|
||||
&ccount);
|
||||
}
|
||||
*front = *back;
|
||||
}
|
||||
back++;
|
||||
front++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void buffer_fill_to_end(console_buffer_t * buffer, cell_t * src,
|
||||
int x, int y)
|
||||
{
|
||||
cell_t * dst = buffer_get_cell(buffer, x, y);
|
||||
cell_t * sentinel = buffer_get_cell(buffer, 0, buffer_height);
|
||||
while (dst != sentinel)
|
||||
*dst++ = clear_cell;
|
||||
|
||||
if (iflags.debug.immediateflips && buffer == &back_buffer)
|
||||
back_buffer_flip();
|
||||
}
|
||||
|
||||
static void back_buffer_write(cell_t * cell, int x, int y)
|
||||
{
|
||||
cell_t * dst = buffer_get_cell(&back_buffer, x, y);
|
||||
*dst = *cell;
|
||||
|
||||
if (iflags.debug.immediateflips)
|
||||
back_buffer_flip();
|
||||
}
|
||||
|
||||
static void back_buffer_clear_to_end_of_line(int x, int y)
|
||||
{
|
||||
cell_t * cell;
|
||||
cell_t *sentinel;
|
||||
|
||||
cell = buffer_get_cell(&back_buffer, x, y);
|
||||
sentinel = buffer_get_cell(&back_buffer, 0, y+1);
|
||||
while (cell != sentinel)
|
||||
*cell++ = clear_cell;
|
||||
|
||||
if (iflags.debug.immediateflips)
|
||||
back_buffer_flip();
|
||||
}
|
||||
|
||||
/*
|
||||
* Called after returning from ! or ^Z
|
||||
*/
|
||||
@@ -197,7 +441,6 @@ setftty()
|
||||
adjust_palette();
|
||||
#endif
|
||||
start_screen();
|
||||
has_unicode = ((GetVersion() & 0x80000000) == 0);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -232,6 +475,10 @@ tty_end_screen()
|
||||
clear_screen();
|
||||
really_move_cursor();
|
||||
if (GetConsoleScreenBufferInfo(hConOut, &csbi)) {
|
||||
|
||||
buffer_fill_to_end(&back_buffer, &clear_cell, 0, 0);
|
||||
buffer_fill_to_end(&front_buffer, &clear_cell, 0, 0);
|
||||
|
||||
DWORD ccnt;
|
||||
COORD newcoord;
|
||||
|
||||
@@ -270,7 +517,16 @@ DWORD ctrltype;
|
||||
}
|
||||
}
|
||||
|
||||
/* called by init_tty in wintty.c for WIN32 port only */
|
||||
/*
|
||||
* ntty_open() is called in several places. It is called by win_tty_init
|
||||
* passing in a mode of zero. It is then later called again by pcmain passing
|
||||
* in a mode of one. Finally, it can also be called by process_options also
|
||||
* with a mode of one.
|
||||
*
|
||||
* barthouse - The fact this is getting called multiple times needs to be
|
||||
* reviewed and perhaps cleaned up.
|
||||
*
|
||||
*/
|
||||
void
|
||||
nttty_open(mode)
|
||||
int mode;
|
||||
@@ -279,6 +535,10 @@ int mode;
|
||||
DWORD cmode;
|
||||
long mask;
|
||||
|
||||
has_unicode = ((GetVersion() & 0x80000000) == 0);
|
||||
|
||||
initialize_cp_console();
|
||||
|
||||
GUILaunched = 0;
|
||||
|
||||
try :
|
||||
@@ -307,6 +567,9 @@ int mode;
|
||||
mode = 0;
|
||||
goto try;
|
||||
} else {
|
||||
/* barthouse - Need to understand how this can happen and
|
||||
* whether we should bail instead of returning.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -314,6 +577,30 @@ int mode;
|
||||
hConIn = GetStdHandle(STD_INPUT_HANDLE);
|
||||
hConOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
|
||||
GetConsoleScreenBufferInfo(hConOut, &csbi);
|
||||
|
||||
int height = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
|
||||
|
||||
/* NOTE: We currently force to a width of 80 due to unresolved issues
|
||||
* within the TTY code. These issues will need to resolved before
|
||||
* we could allow widths > 80. We will always need a width of
|
||||
* atleast 80.
|
||||
*/
|
||||
|
||||
int width = 80;
|
||||
|
||||
/* If the window is not big enough to meet our minimum height needs,
|
||||
* grow the console's buffer to be large enough. The user will have
|
||||
* to manually extend the size of the window.
|
||||
*/
|
||||
|
||||
height = max(25, height);
|
||||
|
||||
COORD size = { width, height };
|
||||
SetConsoleScreenBufferSize(hConOut, size);
|
||||
|
||||
initialize_buffer_flipping(width, height);
|
||||
|
||||
load_keyboard_handler();
|
||||
/* Initialize the function pointer that points to
|
||||
* the kbhit() equivalent, in this TTY case nttty_kbhit()
|
||||
@@ -338,7 +625,10 @@ int mode;
|
||||
/* Unable to set control handler */
|
||||
cmode = 0; /* just to have a statement to break on for debugger */
|
||||
}
|
||||
get_scr_size();
|
||||
|
||||
LI = height;
|
||||
CO = width;
|
||||
|
||||
console.cursor.X = console.cursor.Y = 0;
|
||||
really_move_cursor();
|
||||
}
|
||||
@@ -363,32 +653,6 @@ nttty_kbhit()
|
||||
return pNHkbhit(hConIn, &ir);
|
||||
}
|
||||
|
||||
void
|
||||
get_scr_size()
|
||||
{
|
||||
int lines, cols;
|
||||
|
||||
GetConsoleScreenBufferInfo(hConOut, &csbi);
|
||||
|
||||
lines = csbi.srWindow.Bottom - (csbi.srWindow.Top + 1);
|
||||
cols = csbi.srWindow.Right - (csbi.srWindow.Left + 1);
|
||||
|
||||
LI = lines;
|
||||
CO = min(cols, 80);
|
||||
|
||||
if ((LI < 25) || (CO < 80)) {
|
||||
COORD newcoord;
|
||||
|
||||
LI = 25;
|
||||
CO = 80;
|
||||
|
||||
newcoord.Y = LI;
|
||||
newcoord.X = CO;
|
||||
|
||||
SetConsoleScreenBufferSize(hConOut, newcoord);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
tgetch()
|
||||
{
|
||||
@@ -440,6 +704,8 @@ really_move_cursor()
|
||||
console.cursor.Y = ttyDisplay->cury;
|
||||
}
|
||||
SetConsoleCursorPosition(hConOut, console.cursor);
|
||||
|
||||
back_buffer_flip();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -498,6 +764,7 @@ xputc_core(ch)
|
||||
char ch;
|
||||
{
|
||||
boolean inverse = FALSE;
|
||||
cell_t cell;
|
||||
switch (ch) {
|
||||
case '\n':
|
||||
console.cursor.Y++;
|
||||
@@ -515,17 +782,19 @@ char ch;
|
||||
ttycolors[console.current_nhcolor];
|
||||
if (console.current_nhattr[ATR_BOLD])
|
||||
console.attr |= (inverse) ?
|
||||
BACKGROUND_INTENSITY : FOREGROUND_INTENSITY;
|
||||
WriteConsoleOutputAttribute(hConOut, &console.attr, 1, console.cursor, &acount);
|
||||
BACKGROUND_INTENSITY : FOREGROUND_INTENSITY;
|
||||
|
||||
cell.attribute = console.attr;
|
||||
if (has_unicode) {
|
||||
/* Avoid bug in ANSI API on WinNT */
|
||||
WCHAR c2[2];
|
||||
int rc;
|
||||
rc = MultiByteToWideChar(GetConsoleOutputCP(), 0, &ch, 1, c2, 2);
|
||||
WriteConsoleOutputCharacterW(hConOut, c2, rc, console.cursor, &ccount);
|
||||
cell.characters[0] = cpConsole[ch].characters[0];
|
||||
cell.characters[1] = cpConsole[ch].characters[1];
|
||||
cell.count = cpConsole[ch].count;
|
||||
} else {
|
||||
WriteConsoleOutputCharacterA(hConOut, &ch, 1, console.cursor, &ccount);
|
||||
cell.characters[0] = ch;
|
||||
cell.characters[1] = 0;
|
||||
cell.count = 1;
|
||||
}
|
||||
back_buffer_write(&cell, console.cursor.X, console.cursor.Y);
|
||||
console.cursor.X++;
|
||||
}
|
||||
}
|
||||
@@ -535,46 +804,11 @@ char ch;
|
||||
* for win32. It is used for glyphs only, not text.
|
||||
*/
|
||||
|
||||
/* CP437 to Unicode mapping according to the Unicode Consortium */
|
||||
static const WCHAR cp437[] = {
|
||||
0x0020, 0x263A, 0x263B, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022,
|
||||
0x25D8, 0x25CB, 0x25D9, 0x2642, 0x2640, 0x266A, 0x266B, 0x263C,
|
||||
0x25BA, 0x25C4, 0x2195, 0x203C, 0x00B6, 0x00A7, 0x25AC, 0x21A8,
|
||||
0x2191, 0x2193, 0x2192, 0x2190, 0x221F, 0x2194, 0x25B2, 0x25BC,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
|
||||
0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
|
||||
0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
|
||||
0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
|
||||
0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
|
||||
0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
|
||||
0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x2302,
|
||||
0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7,
|
||||
0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
|
||||
0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
|
||||
0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
|
||||
0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba,
|
||||
0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
|
||||
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
|
||||
0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
|
||||
0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
|
||||
0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
|
||||
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b,
|
||||
0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580,
|
||||
0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4,
|
||||
0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229,
|
||||
0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248,
|
||||
0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0
|
||||
};
|
||||
|
||||
void
|
||||
g_putch(in_ch)
|
||||
int in_ch;
|
||||
{
|
||||
cell_t cell;
|
||||
boolean inverse = FALSE;
|
||||
unsigned char ch = (unsigned char) in_ch;
|
||||
|
||||
@@ -587,23 +821,24 @@ int in_ch;
|
||||
ttycolors[console.current_nhcolor];
|
||||
if (console.current_nhattr[ATR_BOLD])
|
||||
console.attr |= (inverse) ? BACKGROUND_INTENSITY : FOREGROUND_INTENSITY;
|
||||
WriteConsoleOutputAttribute(hConOut, &console.attr, 1, console.cursor, &acount);
|
||||
|
||||
cell.attribute = console.attr;
|
||||
cell.characters[1] = 0;
|
||||
cell.count = 1;
|
||||
if (has_unicode)
|
||||
WriteConsoleOutputCharacterW(hConOut, &cp437[ch], 1, console.cursor, &ccount);
|
||||
cell.characters[0] = cp437[ch];
|
||||
else
|
||||
WriteConsoleOutputCharacterA(hConOut, &ch, 1, console.cursor, &ccount);
|
||||
cell.characters[0] = ch;
|
||||
back_buffer_write(&cell, console.cursor.X, console.cursor.Y);
|
||||
}
|
||||
|
||||
void
|
||||
cl_end()
|
||||
{
|
||||
int cx;
|
||||
console.cursor.X = ttyDisplay->curx;
|
||||
console.cursor.Y = ttyDisplay->cury;
|
||||
cx = CO - console.cursor.X;
|
||||
FillConsoleOutputAttribute(hConOut, DEFTEXTCOLOR, cx, console.cursor, &acount);
|
||||
FillConsoleOutputCharacter(hConOut, ' ', cx, console.cursor, &ccount);
|
||||
|
||||
back_buffer_clear_to_end_of_line(console.cursor.X, console.cursor.Y);
|
||||
|
||||
tty_curs(BASE_WINDOW, (int) ttyDisplay->curx + 1, (int) ttyDisplay->cury);
|
||||
}
|
||||
|
||||
@@ -611,6 +846,10 @@ void
|
||||
raw_clear_screen()
|
||||
{
|
||||
if (GetConsoleScreenBufferInfo(hConOut, &csbi)) {
|
||||
|
||||
buffer_fill_to_end(&front_buffer, &clear_cell, 0, 0);
|
||||
buffer_fill_to_end(&back_buffer, &clear_cell, 0, 0);
|
||||
|
||||
DWORD ccnt;
|
||||
COORD newcoord;
|
||||
|
||||
@@ -621,6 +860,7 @@ raw_clear_screen()
|
||||
csbi.dwSize.X * csbi.dwSize.Y, newcoord, &ccnt);
|
||||
FillConsoleOutputCharacter(
|
||||
hConOut, ' ', csbi.dwSize.X * csbi.dwSize.Y, newcoord, &ccnt);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -651,11 +891,18 @@ cl_eos()
|
||||
{
|
||||
int cy = ttyDisplay->cury + 1;
|
||||
if (GetConsoleScreenBufferInfo(hConOut, &csbi)) {
|
||||
|
||||
buffer_fill_to_end(&front_buffer, &clear_cell, ttyDisplay->curx,
|
||||
ttyDisplay->cury);
|
||||
buffer_fill_to_end(&back_buffer, &clear_cell, ttyDisplay->curx,
|
||||
ttyDisplay->cury);
|
||||
|
||||
DWORD ccnt;
|
||||
COORD newcoord;
|
||||
|
||||
newcoord.X = ttyDisplay->curx;
|
||||
newcoord.Y = ttyDisplay->cury;
|
||||
|
||||
FillConsoleOutputAttribute(
|
||||
hConOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,
|
||||
csbi.dwSize.X * csbi.dwSize.Y - cy, newcoord, &ccnt);
|
||||
@@ -684,6 +931,7 @@ tty_delay_output()
|
||||
int k;
|
||||
|
||||
goal = 50 + clock();
|
||||
back_buffer_flip();
|
||||
while (goal > clock()) {
|
||||
k = junk; /* Do nothing */
|
||||
}
|
||||
@@ -1063,10 +1311,10 @@ VA_DECL(const char *, fmt)
|
||||
else {
|
||||
if(!init_ttycolor_completed)
|
||||
init_ttycolor();
|
||||
|
||||
xputs(buf);
|
||||
if (ttyDisplay)
|
||||
curs(BASE_WINDOW, console.cursor.X + 1, console.cursor.Y);
|
||||
really_move_cursor();
|
||||
}
|
||||
VA_END();
|
||||
return;
|
||||
|
||||
752
win/tty/wintty.c
752
win/tty/wintty.c
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 wintty.c $NHDT-Date: 1520825319 2018/03/12 03:28:39 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.142 $ */
|
||||
/* NetHack 3.6 wintty.c $NHDT-Date: 1525885919 2018/05/09 17:11:59 $ $NHDT-Branch: tty-status $:$NHDT-Revision: 1.146 $ */
|
||||
/* Copyright (c) David Cohrs, 1991 */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -66,7 +66,7 @@ struct window_procs tty_procs = {
|
||||
| WC2_SELECTSAVED
|
||||
#endif
|
||||
#if defined(STATUS_HILITES)
|
||||
| WC2_HILITE_STATUS | WC2_HITPOINTBAR | WC2_FLUSH_STATUS
|
||||
| WC2_HILITE_STATUS | WC2_HITPOINTBAR
|
||||
#endif
|
||||
| WC2_DARKGRAY),
|
||||
tty_init_nhwindows, tty_player_selection, tty_askname, tty_get_nh_event,
|
||||
@@ -176,6 +176,14 @@ STATIC_DCL void FDECL(setup_racemenu, (winid, BOOLEAN_P, int, int, int));
|
||||
STATIC_DCL void FDECL(setup_gendmenu, (winid, BOOLEAN_P, int, int, int));
|
||||
STATIC_DCL void FDECL(setup_algnmenu, (winid, BOOLEAN_P, int, int, int));
|
||||
STATIC_DCL boolean NDECL(reset_role_filtering);
|
||||
#ifdef STATUS_HILITES
|
||||
STATIC_DCL boolean FDECL(check_fields, (BOOLEAN_P));
|
||||
STATIC_DCL void NDECL(render_status);
|
||||
STATIC_DCL void FDECL(tty_putstatusfield, (struct tty_status_fields *,
|
||||
const char *, int, int));
|
||||
STATIC_DCL int FDECL(set_cond_shrinklvl, (int, int));
|
||||
STATIC_DCL boolean NDECL(check_windowdata);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* A string containing all the default commands -- to add to a list
|
||||
@@ -2489,8 +2497,7 @@ const char *str;
|
||||
{
|
||||
register struct WinDesc *cw = 0;
|
||||
register char *ob;
|
||||
register const char *nb;
|
||||
register long i, j, n0;
|
||||
register long i, n0;
|
||||
|
||||
/* Assume there's a real problem if the window is missing --
|
||||
* probably a panic message
|
||||
@@ -2518,7 +2525,7 @@ const char *str;
|
||||
#endif
|
||||
update_topl(str);
|
||||
break;
|
||||
|
||||
#ifndef STATUS_HILITES
|
||||
case NHW_STATUS:
|
||||
ob = &cw->data[cw->cury][j = cw->curx];
|
||||
if (context.botlx)
|
||||
@@ -2532,32 +2539,14 @@ const char *str;
|
||||
nb = str;
|
||||
for (i = cw->curx + 1, n0 = cw->cols; i < n0; i++, nb++) {
|
||||
if (!*nb) {
|
||||
#ifndef STATUS_HILITES
|
||||
if (*ob || context.botlx) {
|
||||
#else
|
||||
/* STATUS_HILITES will call cl_end() when finished
|
||||
* its sequence of putstr's. We don't want to call
|
||||
* cl_end() with each putstr() which may cause flashing
|
||||
* in the Windows port
|
||||
*/
|
||||
if (context.botlx) {
|
||||
#endif
|
||||
/* last char printed may be in middle of line */
|
||||
tty_curs(WIN_STATUS, i, cw->cury);
|
||||
cl_end();
|
||||
}
|
||||
break;
|
||||
}
|
||||
#ifdef STATUS_HILITES
|
||||
/* Don't optimize the putsym away, in case it happens
|
||||
to be the same character but different color/attr.
|
||||
We don't optimize on iflags.use_status_hilites either,
|
||||
in case old chars were written with highlighting and
|
||||
that option has just now been toggled off. [We could
|
||||
do better by tracking color/attr more closely.] */
|
||||
#else
|
||||
if (*ob != *nb)
|
||||
#endif
|
||||
tty_putsym(WIN_STATUS, i, cw->cury, *nb);
|
||||
if (*ob)
|
||||
ob++;
|
||||
@@ -2565,11 +2554,10 @@ const char *str;
|
||||
|
||||
(void) strncpy(&cw->data[cw->cury][j], str, cw->cols - j - 1);
|
||||
cw->data[cw->cury][cw->cols - 1] = '\0'; /* null terminate */
|
||||
#ifndef STATUS_HILITES
|
||||
cw->cury = (cw->cury + 1) % 2;
|
||||
cw->curx = 0;
|
||||
#endif
|
||||
break;
|
||||
#endif /* STATUS_HILITES */
|
||||
case NHW_MAP:
|
||||
tty_curs(window, cw->curx + 1, cw->cury);
|
||||
term_start_attr(attr);
|
||||
@@ -3426,36 +3414,108 @@ char *posbar;
|
||||
video_update_positionbar(posbar);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#endif /* POSITIONBAR */
|
||||
|
||||
|
||||
/*
|
||||
* +------------------+
|
||||
* | STATUS CODE |
|
||||
* +------------------+
|
||||
*/
|
||||
|
||||
/*
|
||||
* The following data structures come from the genl_ routines in
|
||||
* src/windows.c and as such are considered to be on the window-port
|
||||
* "side" of things, rather than the NetHack-core "side" of things.
|
||||
*/
|
||||
|
||||
extern const char *status_fieldfmt[MAXBLSTATS];
|
||||
extern char *status_vals[MAXBLSTATS];
|
||||
extern boolean status_activefields[MAXBLSTATS];
|
||||
extern winid WIN_STATUS;
|
||||
|
||||
#ifdef STATUS_HILITES
|
||||
static long tty_condition_bits;
|
||||
static int tty_status_colors[MAXBLSTATS];
|
||||
int hpbar_percent, hpbar_color;
|
||||
const char *fieldnames[] = {
|
||||
"title", "strength", "dexterity", "constitution", "intelligence",
|
||||
"wisdom", "charisma", "alignment", "score", "carrying-capacity",
|
||||
"gold", "power", "power-max", "experience-level", "armor-class",
|
||||
"HD", "time", "hunger", "hitpoints", "hitpoints-max",
|
||||
"dungeon-level", "experience", "condition",
|
||||
};
|
||||
|
||||
#ifdef STATUS_HILITES
|
||||
static int FDECL(condcolor, (long, unsigned long *));
|
||||
static int FDECL(condattr, (long, unsigned long *));
|
||||
#endif /* STATUS_HILITES */
|
||||
static long tty_condition_bits;
|
||||
static unsigned long *tty_colormasks;
|
||||
static struct tty_status_fields
|
||||
tty_status[2][MAXBLSTATS]; /* 2: first index is for current
|
||||
and previous */
|
||||
static int hpbar_percent, hpbar_color;
|
||||
static struct condition_t {
|
||||
long mask;
|
||||
const char *text[3]; /* 3: potential display values, progressively
|
||||
* smaller */
|
||||
} conditions[] = {
|
||||
/* The sequence order of these matters */
|
||||
{ BL_MASK_STONE, {"Stone", "Ston", "Sto"}},
|
||||
{ BL_MASK_SLIME, {"Slime", "Slim", "Slm"}},
|
||||
{ BL_MASK_STRNGL, {"Strngl", "Stngl", "Str"}},
|
||||
{ BL_MASK_FOODPOIS, {"FoodPois", "Fpois", "Poi"}},
|
||||
{ BL_MASK_TERMILL, {"TermIll" , "Ill", "Ill"}},
|
||||
{ BL_MASK_BLIND, {"Blind", "Blnd", "Bl"}},
|
||||
{ BL_MASK_DEAF, {"Deaf", "Def", "Df"}},
|
||||
{ BL_MASK_STUN, {"Stun", "Stun", "St"}},
|
||||
{ BL_MASK_CONF, {"Conf", "Cnf", "Cn"}},
|
||||
{ BL_MASK_HALLU, {"Hallu", "Hal", "Ha"}},
|
||||
{ BL_MASK_LEV, {"Lev", "Lev", "Lv"}},
|
||||
{ BL_MASK_FLY, {"Fly", "Fly", "Fl"}},
|
||||
{ BL_MASK_RIDE, {"Ride", "Rid", "Ri"}},
|
||||
};
|
||||
static enum statusfields fieldorder[2][15] = { /* 2: two status lines */
|
||||
{ BL_TITLE, BL_STR, BL_DX, BL_CO, BL_IN, BL_WI, BL_CH, BL_ALIGN,
|
||||
BL_SCORE, BL_FLUSH, BL_FLUSH, BL_FLUSH, BL_FLUSH, BL_FLUSH,
|
||||
BL_FLUSH },
|
||||
{ BL_LEVELDESC, BL_GOLD, BL_HP, BL_HPMAX, BL_ENE, BL_ENEMAX,
|
||||
BL_AC, BL_XP, BL_EXP, BL_HD, BL_TIME, BL_HUNGER,
|
||||
BL_CAP, BL_CONDITION, BL_FLUSH }
|
||||
};
|
||||
static boolean windowdata_init = FALSE;
|
||||
/* This controls whether to skip fields that aren't
|
||||
* flagged as requiring updating during the current
|
||||
* render_status().
|
||||
*
|
||||
* Hopefully that can be confirmed as working correctly
|
||||
* for all platforms eventually and the conditional
|
||||
* setting below can be removed.
|
||||
*/
|
||||
#if defined(UNIX)
|
||||
static int do_field_opt = 0;
|
||||
#else
|
||||
static int do_field_opt = 1;
|
||||
#endif
|
||||
#endif /* STATUS_HILITES */
|
||||
|
||||
/*
|
||||
* tty_status_init()
|
||||
* -- initialize the tty-specific data structures.
|
||||
* -- call genl_status_init() to initialize the general data.
|
||||
*/
|
||||
void
|
||||
tty_status_init()
|
||||
{
|
||||
#ifdef STATUS_HILITES
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAXBLSTATS; ++i)
|
||||
tty_status_colors[i] = NO_COLOR; /* no color */
|
||||
for (i = 0; i < MAXBLSTATS; ++i) {
|
||||
tty_status[NOW][i].idx = -1;
|
||||
tty_status[NOW][i].color = NO_COLOR; /* no color */
|
||||
tty_status[NOW][i].attr = ATR_NONE;
|
||||
tty_status[NOW][i].x = 0;
|
||||
tty_status[NOW][i].y = 0;
|
||||
tty_status[NOW][i].valid = FALSE;
|
||||
tty_status[NOW][i].dirty = FALSE;
|
||||
tty_status[NOW][i].redraw = FALSE;
|
||||
tty_status[BEFORE][i] = tty_status[NOW][i];
|
||||
}
|
||||
tty_condition_bits = 0L;
|
||||
hpbar_percent = 0, hpbar_color = NO_COLOR;
|
||||
#endif /* STATUS_HILITES */
|
||||
@@ -3464,6 +3524,8 @@ tty_status_init()
|
||||
genl_status_init();
|
||||
}
|
||||
|
||||
#ifdef STATUS_HILITES
|
||||
|
||||
/*
|
||||
* *_status_update()
|
||||
* -- update the value of a status field.
|
||||
@@ -3517,8 +3579,165 @@ tty_status_init()
|
||||
* See doc/window.doc for more details.
|
||||
*/
|
||||
|
||||
void
|
||||
tty_status_update(fldidx, ptr, chg, percent, color, colormasks)
|
||||
int fldidx, chg UNUSED, percent, color;
|
||||
genericptr_t ptr;
|
||||
unsigned long *colormasks;
|
||||
{
|
||||
long *condptr = (long *) ptr;
|
||||
char *text = (char *) ptr;
|
||||
boolean do_color = FALSE;
|
||||
boolean force_update = FALSE;
|
||||
|
||||
#ifdef TEXTCOLOR
|
||||
do_color = TRUE;
|
||||
#endif
|
||||
|
||||
if (fldidx != BL_FLUSH && !status_activefields[fldidx])
|
||||
return;
|
||||
|
||||
switch (fldidx) {
|
||||
case BL_FLUSH:
|
||||
force_update = TRUE;
|
||||
break;
|
||||
case BL_CONDITION:
|
||||
tty_status[NOW][fldidx].idx = fldidx;
|
||||
tty_condition_bits = *condptr;
|
||||
tty_colormasks = colormasks;
|
||||
tty_status[NOW][fldidx].valid = TRUE;
|
||||
tty_status[NOW][fldidx].dirty = TRUE;
|
||||
break;
|
||||
default:
|
||||
tty_status[NOW][fldidx].idx = fldidx;
|
||||
Sprintf(status_vals[fldidx],
|
||||
status_fieldfmt[fldidx] ?
|
||||
status_fieldfmt[fldidx] : "%s", text);
|
||||
tty_status[NOW][fldidx].color = do_color ? (color & 0x00FF)
|
||||
: NO_COLOR;
|
||||
tty_status[NOW][fldidx].attr = (color & 0xFF00) >> 8;
|
||||
tty_status[NOW][fldidx].lth = strlen(status_vals[fldidx]);
|
||||
tty_status[NOW][fldidx].valid = TRUE;
|
||||
tty_status[NOW][fldidx].dirty = TRUE;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Special additional processing for hitpointbar */
|
||||
if (iflags.wc2_hitpointbar && fldidx == BL_HP) {
|
||||
hpbar_percent = percent;
|
||||
hpbar_color = do_color ? (color & 0x00FF) : NO_COLOR;
|
||||
}
|
||||
|
||||
/* The core botl engine sends a single blank to the window port
|
||||
for carrying-capacity when its unused. Let's suppress that */
|
||||
if (tty_status[NOW][fldidx].lth == 1
|
||||
&& status_vals[fldidx][0] == ' ') {
|
||||
status_vals[fldidx][0] = '\0';
|
||||
tty_status[NOW][fldidx].lth = 0;
|
||||
}
|
||||
|
||||
/* The core botl engine sends BL_LEVELDESC with trailing blanks
|
||||
included. Let's suppress one of the trailing blanks */
|
||||
if (fldidx == BL_LEVELDESC) {
|
||||
char *lastchar = eos(status_vals[fldidx]);
|
||||
lastchar--;
|
||||
while (lastchar && *lastchar == ' '
|
||||
&& lastchar >= status_vals[fldidx]) {
|
||||
*lastchar-- = '\0';
|
||||
tty_status[NOW][fldidx].lth--;
|
||||
}
|
||||
}
|
||||
|
||||
/* Some other special case fixups */
|
||||
if (iflags.wc2_hitpointbar && fldidx == BL_TITLE)
|
||||
tty_status[NOW][fldidx].lth += 2; /* [ and ] */
|
||||
if (fldidx == BL_GOLD)
|
||||
tty_status[NOW][fldidx].lth -= 9; /* \GXXXXNNNN counts as 1 */
|
||||
|
||||
|
||||
if (check_fields(force_update))
|
||||
render_status();
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the routine where we figure out where each field
|
||||
* should be placed, and flag whether the on-screen details
|
||||
* must be updated because they need to change.
|
||||
* This is now done at an individual field case-by-case level.
|
||||
*/
|
||||
boolean
|
||||
check_fields(forcefields)
|
||||
boolean forcefields;
|
||||
{
|
||||
int c, i, row, col;
|
||||
boolean valid = TRUE, matchprev = FALSE, update_right;
|
||||
|
||||
if (!windowdata_init && !check_windowdata())
|
||||
return FALSE;
|
||||
|
||||
for (row = 0; row < 2; ++row) {
|
||||
col = 1;
|
||||
update_right = FALSE;
|
||||
for (i = 0; fieldorder[row][i] != BL_FLUSH; ++i) {
|
||||
int idx = fieldorder[row][i];
|
||||
|
||||
if (!status_activefields[idx])
|
||||
continue;
|
||||
|
||||
if (!tty_status[NOW][idx].valid)
|
||||
valid = FALSE;
|
||||
|
||||
tty_status[NOW][idx].y = row;
|
||||
tty_status[NOW][idx].x = col;
|
||||
|
||||
/* evaluate */
|
||||
if (tty_status[NOW][idx].lth != tty_status[BEFORE][idx].lth)
|
||||
update_right = TRUE;
|
||||
|
||||
/*
|
||||
* Check values against those already on the dislay.
|
||||
* - Is the additional processing time for this worth it?
|
||||
*/
|
||||
matchprev = FALSE;
|
||||
if (do_field_opt && tty_status[NOW][idx].dirty) {
|
||||
/* compare values */
|
||||
const char *ob, *nb; /* old byte, new byte */
|
||||
|
||||
c = col - 1;
|
||||
ob = &wins[WIN_STATUS]->data[row][c];
|
||||
nb = status_vals[idx];
|
||||
while (*nb && c < wins[WIN_STATUS]->cols) {
|
||||
if (*nb != *ob)
|
||||
break;
|
||||
nb++;
|
||||
ob++;
|
||||
c++;
|
||||
}
|
||||
if (!*nb && c > col - 1)
|
||||
matchprev = TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* With STATUS_HILITES, it is possible that the color
|
||||
* needs to change even if the text is the same, so
|
||||
* we flag that here by setting .redraw.
|
||||
* Then, render_status() will see that flag setting
|
||||
* and ensure that the tty cell content is updated.
|
||||
* After the field has been updated, render_status()
|
||||
* will also clear .redraw.
|
||||
*/
|
||||
if (forcefields || update_right || !matchprev
|
||||
|| tty_status[NOW][idx].color != tty_status[BEFORE][idx].color
|
||||
|| tty_status[NOW][idx].attr != tty_status[BEFORE][idx].attr)
|
||||
tty_status[NOW][idx].redraw = TRUE;
|
||||
col += tty_status[NOW][idx].lth;
|
||||
}
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
/* new approach through status_update() only */
|
||||
#define Begin_Attr(m) \
|
||||
if (m) { \
|
||||
if ((m) & HL_BOLD) \
|
||||
@@ -3547,235 +3766,272 @@ tty_status_init()
|
||||
term_end_attr(ATR_BOLD); \
|
||||
}
|
||||
|
||||
#ifdef STATUS_HILITES
|
||||
|
||||
#ifdef TEXTCOLOR
|
||||
#define MaybeDisplayCond(bm,txt) \
|
||||
if (tty_condition_bits & (bm)) { \
|
||||
putstr(WIN_STATUS, 0, " "); \
|
||||
if (iflags.hilite_delta) { \
|
||||
attrmask = condattr(bm, colormasks); \
|
||||
Begin_Attr(attrmask); \
|
||||
if ((coloridx = condcolor(bm, colormasks)) != NO_COLOR) \
|
||||
term_start_color(coloridx); \
|
||||
} \
|
||||
putstr(WIN_STATUS, 0, txt); \
|
||||
if (iflags.hilite_delta) { \
|
||||
if (coloridx != NO_COLOR) \
|
||||
term_end_color(); \
|
||||
End_Attr(attrmask); \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define MaybeDisplayCond(bm,txt) \
|
||||
if (tty_condition_bits & (bm)) { \
|
||||
putstr(WIN_STATUS, 0, " "); \
|
||||
if (iflags.hilite_delta) { \
|
||||
attrmask = condattr(bm, colormasks); \
|
||||
Begin_Attr(attrmask); \
|
||||
} \
|
||||
putstr(WIN_STATUS, 0, txt); \
|
||||
if (iflags.hilite_delta) { \
|
||||
End_Attr(attrmask); \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
tty_status_update(fldidx, ptr, chg, percent, color, colormasks)
|
||||
int fldidx, chg UNUSED, percent UNUSED, color;
|
||||
genericptr_t ptr;
|
||||
unsigned long *colormasks;
|
||||
render_status(VOID_ARGS)
|
||||
{
|
||||
long *condptr = (long *) ptr;
|
||||
int i, attrmask = 0;
|
||||
#ifdef TEXTCOLOR
|
||||
int coloridx = NO_COLOR;
|
||||
#endif
|
||||
char *text = (char *) ptr;
|
||||
static boolean oncearound = FALSE; /* prevent premature partial display */
|
||||
enum statusfields fieldorder[2][15] = {
|
||||
{ BL_TITLE, BL_STR, BL_DX, BL_CO, BL_IN, BL_WI, BL_CH, BL_ALIGN,
|
||||
BL_SCORE, BL_FLUSH, BL_FLUSH, BL_FLUSH, BL_FLUSH, BL_FLUSH,
|
||||
BL_FLUSH },
|
||||
{ BL_LEVELDESC, BL_GOLD, BL_HP, BL_HPMAX, BL_ENE, BL_ENEMAX,
|
||||
BL_AC, BL_XP, BL_EXP, BL_HD, BL_TIME, BL_HUNGER,
|
||||
BL_CAP, BL_CONDITION, BL_FLUSH }
|
||||
};
|
||||
int attridx = 0;
|
||||
long mask = 0L;
|
||||
int i, c, row, shrinklvl = 0, attrmask = 0;
|
||||
struct WinDesc *cw = 0;
|
||||
boolean do_color = FALSE, fit = FALSE;
|
||||
struct tty_status_fields *nullfield = (struct tty_status_fields *)0;
|
||||
|
||||
if (fldidx != BL_FLUSH) {
|
||||
if (!status_activefields[fldidx])
|
||||
#ifdef TEXTCOLOR
|
||||
do_color = TRUE;
|
||||
#endif
|
||||
|
||||
if (WIN_STATUS == WIN_ERR
|
||||
|| (cw = wins[WIN_STATUS]) == (struct WinDesc *) 0) {
|
||||
paniclog("render_status", "WIN_ERR on status window.");
|
||||
return;
|
||||
switch (fldidx) {
|
||||
case BL_CONDITION:
|
||||
tty_condition_bits = *condptr;
|
||||
oncearound = TRUE;
|
||||
break;
|
||||
default:
|
||||
Sprintf(status_vals[fldidx],
|
||||
(fldidx == BL_TITLE && iflags.wc2_hitpointbar) ? "%-30s" :
|
||||
status_fieldfmt[fldidx] ? status_fieldfmt[fldidx] : "%s",
|
||||
text);
|
||||
#ifdef TEXTCOLOR
|
||||
tty_status_colors[fldidx] = color;
|
||||
#else
|
||||
tty_status_colors[fldidx] = NO_COLOR;
|
||||
#endif
|
||||
if (iflags.wc2_hitpointbar && fldidx == BL_HP) {
|
||||
hpbar_percent = percent;
|
||||
#ifdef TEXTCOLOR
|
||||
hpbar_color = color;
|
||||
#else
|
||||
hpbar_color = NO_COLOR;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!oncearound) return;
|
||||
for (row = 0; row < 2; ++row) {
|
||||
curs(WIN_STATUS, 1, row);
|
||||
for (i = 0; fieldorder[row][i] != BL_FLUSH; ++i) {
|
||||
int fldidx = fieldorder[row][i];
|
||||
|
||||
curs(WIN_STATUS, 1, 0);
|
||||
for (i = 0; fieldorder[0][i] != BL_FLUSH; ++i) {
|
||||
int fldidx1 = fieldorder[0][i];
|
||||
if (status_activefields[fldidx1]) {
|
||||
if (fldidx1 != BL_TITLE || !iflags.wc2_hitpointbar) {
|
||||
#ifdef TEXTCOLOR
|
||||
coloridx = tty_status_colors[fldidx1] & 0x00FF;
|
||||
#endif
|
||||
attridx = (tty_status_colors[fldidx1] & 0xFF00) >> 8;
|
||||
text = status_vals[fldidx1];
|
||||
if (iflags.hilite_delta) {
|
||||
if (*text == ' ') {
|
||||
putstr(WIN_STATUS, 0, " ");
|
||||
text++;
|
||||
if (status_activefields[fldidx]) {
|
||||
int coloridx = tty_status[NOW][fldidx].color;
|
||||
int attridx = tty_status[NOW][fldidx].attr;
|
||||
int x = tty_status[NOW][fldidx].x;
|
||||
int y = row;
|
||||
char *text = status_vals[fldidx];
|
||||
boolean hitpointbar = (fldidx == BL_TITLE && iflags.wc2_hitpointbar);
|
||||
|
||||
if (do_field_opt && !tty_status[NOW][fldidx].redraw)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Ignore zero length fields. check_fields() didn't count
|
||||
* them in either.
|
||||
*/
|
||||
if (!tty_status[NOW][fldidx].lth && fldidx != BL_CONDITION)
|
||||
continue;
|
||||
|
||||
if (fldidx == BL_CONDITION) {
|
||||
/*
|
||||
* +-----------------+
|
||||
* | Condition Codes |
|
||||
* +-----------------+
|
||||
*/
|
||||
shrinklvl = set_cond_shrinklvl(x, cw->cols);
|
||||
for (c = 0; c < SIZE(conditions); ++c) {
|
||||
mask = conditions[c].mask;
|
||||
if ((tty_condition_bits & mask) == mask) {
|
||||
tty_putstatusfield(nullfield, " ", x++, y);
|
||||
if (iflags.hilite_delta) {
|
||||
attrmask = condattr(mask, tty_colormasks);
|
||||
Begin_Attr(attrmask);
|
||||
if (do_color) {
|
||||
coloridx = condcolor(mask, tty_colormasks);
|
||||
if (coloridx != NO_COLOR)
|
||||
term_start_color(coloridx);
|
||||
}
|
||||
}
|
||||
tty_putstatusfield(nullfield,
|
||||
conditions[c].text[shrinklvl], x, y);
|
||||
x += (int) strlen(conditions[c].text[shrinklvl]);
|
||||
if (iflags.hilite_delta) {
|
||||
if (do_color && coloridx != NO_COLOR)
|
||||
term_end_color();
|
||||
End_Attr(attrmask);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* multiple attributes can be in effect concurrently */
|
||||
Begin_Attr(attridx);
|
||||
#ifdef TEXTCOLOR
|
||||
if (coloridx != NO_COLOR && coloridx != CLR_MAX)
|
||||
term_start_color(coloridx);
|
||||
#endif
|
||||
}
|
||||
tty_curs(WIN_STATUS, x, y);
|
||||
cl_end();
|
||||
} else if (fldidx == BL_GOLD) {
|
||||
char buf[BUFSZ];
|
||||
/*
|
||||
* +-----------+
|
||||
* | Gold |
|
||||
* +-----------+
|
||||
*/
|
||||
/* decode_mixed() due to GOLD glyph */
|
||||
tty_putstatusfield(nullfield,
|
||||
decode_mixed(buf, text), x, y);
|
||||
} else if (hitpointbar) {
|
||||
/*
|
||||
* +-------------------------+
|
||||
* | Title with Hitpoint Bar |
|
||||
* +-------------------------+
|
||||
*/
|
||||
/* hitpointbar using hp percent calculation */
|
||||
int bar_pos, bar_len;
|
||||
char *bar2 = (char *)0;
|
||||
char bar[MAXCO], savedch;
|
||||
boolean twoparts = FALSE;
|
||||
|
||||
putstr(WIN_STATUS, 0, text);
|
||||
|
||||
if (iflags.hilite_delta) {
|
||||
#ifdef TEXTCOLOR
|
||||
if (coloridx != NO_COLOR)
|
||||
term_end_color();
|
||||
#endif
|
||||
End_Attr(attridx);
|
||||
}
|
||||
} else {
|
||||
/* hitpointbar using hp percent calculation */
|
||||
int bar_pos, bar_len;
|
||||
char *bar2 = (char *)0;
|
||||
char bar[MAXCO], savedch;
|
||||
boolean twoparts = FALSE;
|
||||
|
||||
text = status_vals[fldidx1];
|
||||
bar_len = strlen(text);
|
||||
if (bar_len < MAXCO-1) {
|
||||
Strcpy(bar, text);
|
||||
bar_pos = (bar_len * hpbar_percent) / 100;
|
||||
if (bar_pos < 1 && hpbar_percent > 0)
|
||||
bar_pos = 1;
|
||||
if (bar_pos >= bar_len && hpbar_percent < 100)
|
||||
bar_pos = bar_len - 1;
|
||||
if (bar_pos > 0 && bar_pos < bar_len) {
|
||||
twoparts = TRUE;
|
||||
bar2 = &bar[bar_pos];
|
||||
savedch = *bar2;
|
||||
*bar2 = '\0';
|
||||
bar_len = strlen(text);
|
||||
if (bar_len < MAXCO-1) {
|
||||
Strcpy(bar, text);
|
||||
bar_pos = (bar_len * hpbar_percent) / 100;
|
||||
if (bar_pos < 1 && hpbar_percent > 0)
|
||||
bar_pos = 1;
|
||||
if (bar_pos >= bar_len && hpbar_percent < 100)
|
||||
bar_pos = bar_len - 1;
|
||||
if (bar_pos > 0 && bar_pos < bar_len) {
|
||||
twoparts = TRUE;
|
||||
bar2 = &bar[bar_pos];
|
||||
savedch = *bar2;
|
||||
*bar2 = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
if (iflags.hilite_delta && iflags.wc2_hitpointbar) {
|
||||
putstr(WIN_STATUS, 0, "[");
|
||||
#ifdef TEXTCOLOR
|
||||
coloridx = hpbar_color & 0x00FF;
|
||||
/* attridx = (hpbar_color & 0xFF00) >> 8; */
|
||||
if (coloridx != NO_COLOR)
|
||||
term_start_color(coloridx);
|
||||
#endif
|
||||
term_start_attr(ATR_INVERSE);
|
||||
putstr(WIN_STATUS, 0, bar);
|
||||
term_end_attr(ATR_INVERSE);
|
||||
#ifdef TEXTCOLOR
|
||||
if (coloridx != NO_COLOR)
|
||||
term_end_color();
|
||||
#endif
|
||||
if (twoparts) {
|
||||
*bar2 = savedch;
|
||||
putstr(WIN_STATUS, 0, bar2);
|
||||
}
|
||||
putstr(WIN_STATUS, 0, "]");
|
||||
} else
|
||||
putstr(WIN_STATUS, 0, text);
|
||||
}
|
||||
}
|
||||
}
|
||||
cl_end();
|
||||
curs(WIN_STATUS, 1, 1);
|
||||
for (i = 0; fieldorder[1][i] != BL_FLUSH; ++i) {
|
||||
int fldidx2 = fieldorder[1][i];
|
||||
|
||||
if (status_activefields[fldidx2]) {
|
||||
if (fldidx2 != BL_CONDITION) {
|
||||
#ifdef TEXTCOLOR
|
||||
coloridx = tty_status_colors[fldidx2] & 0x00FF;
|
||||
#endif
|
||||
attridx = (tty_status_colors[fldidx2] & 0xFF00) >> 8;
|
||||
text = status_vals[fldidx2];
|
||||
if (iflags.hilite_delta) {
|
||||
if (*text == ' ') {
|
||||
putstr(WIN_STATUS, 0, " ");
|
||||
text++;
|
||||
}
|
||||
/* multiple attributes can be in effect concurrently */
|
||||
Begin_Attr(attridx);
|
||||
#ifdef TEXTCOLOR
|
||||
if (coloridx != NO_COLOR && coloridx != CLR_MAX)
|
||||
term_start_color(coloridx);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (fldidx2 == BL_GOLD) {
|
||||
/* putmixed() due to GOLD glyph */
|
||||
putmixed(WIN_STATUS, 0, text);
|
||||
if (iflags.hilite_delta) {
|
||||
tty_putstatusfield(nullfield, "[", x++, y);
|
||||
if (do_color && hpbar_color != NO_COLOR)
|
||||
term_start_color(hpbar_color);
|
||||
term_start_attr(ATR_INVERSE);
|
||||
tty_putstatusfield(nullfield, bar, x, y);
|
||||
x += (int) strlen(bar);
|
||||
term_end_attr(ATR_INVERSE);
|
||||
if (do_color && hpbar_color != NO_COLOR)
|
||||
term_end_color();
|
||||
if (twoparts) {
|
||||
*bar2 = savedch;
|
||||
tty_putstatusfield(nullfield, bar2, x, y);
|
||||
x += (int) strlen(bar2);
|
||||
tty_curs(WIN_STATUS, x, y);
|
||||
}
|
||||
tty_putstatusfield(nullfield, "]", x++, y);
|
||||
} else {
|
||||
tty_putstatusfield(&tty_status[NOW][fldidx],
|
||||
(char *)0, x, y);
|
||||
}
|
||||
} else {
|
||||
putstr(WIN_STATUS, 0, text);
|
||||
/*
|
||||
* +-----------------------------+
|
||||
* | Everything else that is not |
|
||||
* | in a special case above |
|
||||
* +-----------------------------+
|
||||
*/
|
||||
if (iflags.hilite_delta) {
|
||||
if (*text == ' ') {
|
||||
tty_putstatusfield(nullfield, " ", x++, y);
|
||||
text++;
|
||||
}
|
||||
/* multiple attributes can be in effect concurrently */
|
||||
Begin_Attr(attridx);
|
||||
if (do_color && coloridx != NO_COLOR
|
||||
&& coloridx != CLR_MAX)
|
||||
term_start_color(coloridx);
|
||||
}
|
||||
tty_putstatusfield(&tty_status[NOW][fldidx],
|
||||
text, x, y);
|
||||
if (iflags.hilite_delta) {
|
||||
if (do_color && coloridx != NO_COLOR)
|
||||
term_end_color();
|
||||
End_Attr(attridx);
|
||||
}
|
||||
}
|
||||
|
||||
if (iflags.hilite_delta) {
|
||||
#ifdef TEXTCOLOR
|
||||
if (coloridx != NO_COLOR)
|
||||
term_end_color();
|
||||
#endif
|
||||
End_Attr(attridx);
|
||||
}
|
||||
} else {
|
||||
MaybeDisplayCond(BL_MASK_STONE, "Stone");
|
||||
MaybeDisplayCond(BL_MASK_SLIME, "Slime");
|
||||
MaybeDisplayCond(BL_MASK_STRNGL, "Strngl");
|
||||
MaybeDisplayCond(BL_MASK_FOODPOIS, "FoodPois");
|
||||
MaybeDisplayCond(BL_MASK_TERMILL, "TermIll");
|
||||
MaybeDisplayCond(BL_MASK_BLIND, "Blind");
|
||||
MaybeDisplayCond(BL_MASK_DEAF, "Deaf");
|
||||
MaybeDisplayCond(BL_MASK_STUN, "Stun");
|
||||
MaybeDisplayCond(BL_MASK_CONF, "Conf");
|
||||
MaybeDisplayCond(BL_MASK_HALLU, "Hallu");
|
||||
MaybeDisplayCond(BL_MASK_LEV, "Lev");
|
||||
MaybeDisplayCond(BL_MASK_FLY, "Fly");
|
||||
MaybeDisplayCond(BL_MASK_RIDE, "Ride");
|
||||
/* reset .redraw and .dirty now that they've been rendered */
|
||||
tty_status[NOW][fldidx].dirty = FALSE;
|
||||
tty_status[NOW][fldidx].redraw = FALSE;
|
||||
/*
|
||||
* Make a copy of the entire tty_status struct for comparison
|
||||
* of current and previous.
|
||||
*/
|
||||
tty_status[BEFORE][fldidx] = tty_status[NOW][fldidx]; /* copy struct */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
cl_end();
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is what places a field on the tty display.
|
||||
* If val isn't null, it will be used rather than
|
||||
* fld (it takes precedence).
|
||||
*/
|
||||
void
|
||||
tty_putstatusfield(fld, val, x, y)
|
||||
struct tty_status_fields *fld;
|
||||
const char *val;
|
||||
int x,y;
|
||||
{
|
||||
int i, n, ncols, lth;
|
||||
struct WinDesc *cw = 0;
|
||||
const char *text = (char *)0;
|
||||
|
||||
if ((cw = wins[NHW_STATUS]) == (struct WinDesc *) 0)
|
||||
panic("Invalid WinDesc\n");
|
||||
|
||||
ncols = cw->cols;
|
||||
if (val) {
|
||||
text = val;
|
||||
lth = strlen(text);
|
||||
} else if (fld) {
|
||||
text = status_vals[fld->idx];
|
||||
lth = fld->lth;
|
||||
}
|
||||
if (!text) return;
|
||||
|
||||
print_vt_code2(AVTC_SELECT_WINDOW, NHW_STATUS);
|
||||
|
||||
tty_curs(NHW_STATUS, x, y);
|
||||
for (i = 0; i < lth; ++i) {
|
||||
n = i + x;
|
||||
if (n < ncols && *text) {
|
||||
(void) putchar(*text);
|
||||
ttyDisplay->curx++;
|
||||
cw->curx++;
|
||||
cw->data[y][n-1] = *text;
|
||||
text++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
set_cond_shrinklvl(col, ncols)
|
||||
int col, ncols;
|
||||
{
|
||||
long mask = 0L;
|
||||
int j, c, x, avail, shrinklvl = 0;
|
||||
boolean fitting = FALSE;
|
||||
|
||||
avail = ncols - col;
|
||||
/* determine appropriate shrinklvl required */
|
||||
for (j = 0; j < 3 && !fitting; ++j) {
|
||||
x = 0;
|
||||
for (c = 0; c < SIZE(conditions); ++c) {
|
||||
mask = conditions[c].mask;
|
||||
if ((tty_condition_bits & mask) == mask) {
|
||||
x++; /* for spacer */
|
||||
x += (int) strlen(conditions[c].text[shrinklvl]);
|
||||
}
|
||||
}
|
||||
if (x < avail)
|
||||
fitting = TRUE;
|
||||
else if (shrinklvl < 2)
|
||||
shrinklvl++;
|
||||
}
|
||||
return shrinklvl;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure the underlying status window data start out
|
||||
* blank and null-terminated.
|
||||
*/
|
||||
boolean
|
||||
check_windowdata(VOID_ARGS)
|
||||
{
|
||||
if (WIN_STATUS == WIN_ERR || wins[WIN_STATUS] == (struct WinDesc *) 0) {
|
||||
paniclog("check_windowdata", " null status window.");
|
||||
return FALSE;
|
||||
} else if (!windowdata_init) {
|
||||
int i, n = wins[WIN_STATUS]->cols;
|
||||
|
||||
for (i = 0; i < wins[WIN_STATUS]->cols; ++i)
|
||||
wins[WIN_STATUS]->data[0][i] = ' ';
|
||||
wins[WIN_STATUS]->data[0][n - 1] = '\0'; /* null terminate */
|
||||
for (i = 0; i < wins[WIN_STATUS]->cols; ++i)
|
||||
wins[WIN_STATUS]->data[1][i] = ' ';
|
||||
wins[WIN_STATUS]->data[0][n - 1] = '\0'; /* null terminate */
|
||||
windowdata_init = TRUE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#ifdef TEXTCOLOR
|
||||
/*
|
||||
* Return what color this condition should
|
||||
@@ -3828,8 +4084,10 @@ unsigned long *bmarray;
|
||||
}
|
||||
return attr;
|
||||
}
|
||||
|
||||
#endif /* STATUS_HILITES */
|
||||
|
||||
#endif /* TTY_GRAPHICS */
|
||||
|
||||
/*wintty.c*/
|
||||
|
||||
|
||||
Reference in New Issue
Block a user