src: move console files into a subdir; NFC
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
/* c_file.cpp --
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
and/or modify them under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING.
|
||||
If not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
#include "../conf.h"
|
||||
|
||||
#if (USE_CONSOLE)
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
static int init(FILE *f, int o, int now) {
|
||||
UNUSED(f);
|
||||
UNUSED(o);
|
||||
UNUSED(now);
|
||||
return CON_FILE;
|
||||
}
|
||||
|
||||
static int set_fg(FILE *f, int fg) {
|
||||
UNUSED(f);
|
||||
UNUSED(fg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void print0(FILE *f, const char *s) {
|
||||
#if 1
|
||||
fputs(s, f);
|
||||
#else
|
||||
/* filter out all ANSI sequences */
|
||||
int c;
|
||||
while ((c = *s++) != 0) {
|
||||
if (c == '\033' && *s == ']') {
|
||||
while (*s && *s != 'm')
|
||||
s++;
|
||||
} else
|
||||
fputc(c, f);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool intro(FILE *f) {
|
||||
UNUSED(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
console_t console_file = {init, set_fg, print0, intro};
|
||||
|
||||
#endif /* USE_CONSOLE */
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
@@ -0,0 +1,141 @@
|
||||
/* c_init.cpp --
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
and/or modify them under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING.
|
||||
If not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
#include "../conf.h"
|
||||
|
||||
FILE *con_term = nullptr;
|
||||
|
||||
#if (USE_CONSOLE)
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
static console_t *const me = &console_init;
|
||||
console_t *con = &console_init;
|
||||
|
||||
int con_mode = CON_INIT;
|
||||
|
||||
static void try_init(console_t *c, FILE *f) {
|
||||
int k;
|
||||
|
||||
assert(c);
|
||||
assert(c->init);
|
||||
k = c->init(f, opt->console, con_mode);
|
||||
if (k == CON_INIT)
|
||||
return;
|
||||
#if 0
|
||||
if (con_mode != CON_INIT && opt->console != CON_INIT)
|
||||
if (k != opt->console)
|
||||
return;
|
||||
#endif
|
||||
if (k > con_mode) {
|
||||
con_mode = k;
|
||||
con = c;
|
||||
con->init = nullptr;
|
||||
if (!con->set_fg)
|
||||
con->set_fg = console_none.set_fg;
|
||||
if (!con->print0)
|
||||
con->print0 = console_none.print0;
|
||||
if (!con->intro)
|
||||
con->intro = console_none.intro;
|
||||
}
|
||||
}
|
||||
|
||||
static int do_init(FILE *f) {
|
||||
assert(con_mode == CON_INIT);
|
||||
|
||||
try_init(&console_none, f);
|
||||
assert(con != me);
|
||||
assert(con == &console_none);
|
||||
if (opt->console == CON_NONE || opt->to_stdout)
|
||||
return con_mode;
|
||||
try_init(&console_file, f);
|
||||
if (!acc_isatty(STDIN_FILENO) || !acc_isatty(STDOUT_FILENO) || !acc_isatty(STDERR_FILENO))
|
||||
return con_mode;
|
||||
|
||||
#if (USE_ANSI)
|
||||
try_init(&console_ansi_mono, f);
|
||||
try_init(&console_ansi_color, f);
|
||||
#endif
|
||||
#if (USE_SCREEN)
|
||||
try_init(&console_screen, f);
|
||||
#endif
|
||||
#if (USE_AALIB)
|
||||
try_init(&console_aalib, f);
|
||||
#endif
|
||||
|
||||
return con_mode;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
static int init(FILE *f, int o, int now) {
|
||||
if (con != me)
|
||||
return con_mode;
|
||||
assert(o == -1);
|
||||
assert(now == -1);
|
||||
UNUSED(o);
|
||||
UNUSED(now);
|
||||
return do_init(f);
|
||||
}
|
||||
|
||||
static int set_fg(FILE *f, int fg) {
|
||||
if (con == me)
|
||||
init(f, -1, -1);
|
||||
assert(con != me);
|
||||
return con->set_fg(f, fg);
|
||||
}
|
||||
|
||||
static bool intro(FILE *f) {
|
||||
if (con == me)
|
||||
init(f, -1, -1);
|
||||
assert(con != me);
|
||||
return con->intro(f);
|
||||
}
|
||||
|
||||
console_t console_init = {init, set_fg, nullptr, intro};
|
||||
|
||||
void con_fprintf(FILE *f, const char *format, ...) {
|
||||
va_list args;
|
||||
char buf[80 * 25];
|
||||
|
||||
va_start(args, format);
|
||||
upx_safe_vsnprintf(buf, sizeof(buf), format, args);
|
||||
va_end(args);
|
||||
|
||||
if (con == me)
|
||||
init(f, -1, -1);
|
||||
assert(con != me);
|
||||
con->print0(f, buf);
|
||||
}
|
||||
|
||||
#endif /* USE_CONSOLE */
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
@@ -0,0 +1,63 @@
|
||||
/* c_none.cpp --
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
and/or modify them under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING.
|
||||
If not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
#include "../conf.h"
|
||||
|
||||
#if (USE_CONSOLE)
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
static int init(FILE *f, int o, int now) {
|
||||
UNUSED(f);
|
||||
UNUSED(o);
|
||||
UNUSED(now);
|
||||
return CON_NONE;
|
||||
}
|
||||
|
||||
static int set_fg(FILE *f, int fg) {
|
||||
UNUSED(f);
|
||||
UNUSED(fg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void print0(FILE *f, const char *s) {
|
||||
UNUSED(f);
|
||||
UNUSED(s);
|
||||
}
|
||||
|
||||
static bool intro(FILE *f) {
|
||||
UNUSED(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
console_t console_none = {init, set_fg, print0, intro};
|
||||
|
||||
#endif /* USE_CONSOLE */
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
@@ -0,0 +1,275 @@
|
||||
/* c_screen.cpp -- console screen driver
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
and/or modify them under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING.
|
||||
If not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
#include "../conf.h"
|
||||
|
||||
#if (USE_SCREEN)
|
||||
|
||||
#include "screen.h"
|
||||
|
||||
#define mask_fg 0x0f
|
||||
#define mask_bg 0xf0
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
static int do_init(screen_t *s, int fd) {
|
||||
int fg, bg;
|
||||
|
||||
if (s->init(s, fd) != 0)
|
||||
return -1;
|
||||
|
||||
if (s->getCols(s) < 80 || s->getCols(s) > 256)
|
||||
return -1;
|
||||
if (s->getRows(s) < 24)
|
||||
return -1;
|
||||
|
||||
fg = s->getFg(s);
|
||||
bg = s->getBg(s);
|
||||
if (s->isMono(s))
|
||||
fg = -1;
|
||||
if (fg == (bg >> 4))
|
||||
return -1;
|
||||
if (bg != BG_BLACK)
|
||||
if (!s->isMono(s)) {
|
||||
/* return 0; */ /* we could emulate ANSI mono */
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static screen_t *do_construct(screen_t *s, int fd) {
|
||||
if (!s)
|
||||
return nullptr;
|
||||
if (do_init(s, fd) != 0) {
|
||||
s->destroy(s);
|
||||
return nullptr;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
static screen_t *screen = nullptr;
|
||||
|
||||
static void __acc_cdecl_atexit do_destroy(void) {
|
||||
if (screen) {
|
||||
if (screen->atExit)
|
||||
screen->atExit();
|
||||
screen->destroy(screen);
|
||||
screen = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static int mode = -1;
|
||||
static int init_fg = -1;
|
||||
static int init_bg = -1;
|
||||
static int cur_fg = -1;
|
||||
static int cur_bg = -1;
|
||||
|
||||
static int init(FILE *f, int o, int now) {
|
||||
int fd = fileno(f);
|
||||
int n;
|
||||
|
||||
UNUSED(now);
|
||||
assert(screen == nullptr);
|
||||
|
||||
if (o == CON_SCREEN)
|
||||
n = CON_SCREEN;
|
||||
else if (o == CON_INIT) /* use by default */
|
||||
n = CON_SCREEN;
|
||||
else if (o == CON_ANSI_COLOR) /* can emulate ANSI color */
|
||||
n = CON_ANSI_COLOR;
|
||||
else if (o == CON_ANSI_MONO) /* can emulate ANSI mono */
|
||||
n = CON_ANSI_MONO;
|
||||
else
|
||||
return CON_INIT;
|
||||
|
||||
#if (ACC_OS_DOS32) && defined(__DJGPP__)
|
||||
if (!screen)
|
||||
screen = do_construct(screen_djgpp2_construct(), fd);
|
||||
#endif
|
||||
#if (USE_SCREEN_WIN32)
|
||||
if (!screen)
|
||||
screen = do_construct(screen_win32_construct(), fd);
|
||||
#endif
|
||||
#if (USE_SCREEN_VCSA)
|
||||
if (!screen)
|
||||
screen = do_construct(screen_vcsa_construct(), fd);
|
||||
#endif
|
||||
#if (USE_SCREEN_CURSES)
|
||||
if (!screen && o == CON_SCREEN)
|
||||
screen = do_construct(screen_curses_construct(), fd);
|
||||
#endif
|
||||
if (!screen)
|
||||
return CON_INIT;
|
||||
|
||||
mode = screen->getMode(screen);
|
||||
init_fg = cur_fg = screen->getFg(screen);
|
||||
init_bg = cur_bg = screen->getBg(screen);
|
||||
if (screen->isMono(screen))
|
||||
cur_fg = -1;
|
||||
|
||||
atexit(do_destroy);
|
||||
return n;
|
||||
}
|
||||
|
||||
static int set_fg(FILE *f, int fg) {
|
||||
const int last_fg = cur_fg;
|
||||
int f1 = fg & mask_fg;
|
||||
int f2 = init_fg & mask_fg;
|
||||
|
||||
UNUSED(f);
|
||||
cur_fg = fg;
|
||||
if (screen->isMono(screen)) {
|
||||
const int b = (init_bg & mask_bg) >> 4;
|
||||
if (fg == -1) /* restore startup fg */
|
||||
f1 = f2;
|
||||
else if (b == 0)
|
||||
f1 = (f2 <= 8) ? 15 : 8;
|
||||
else if (b <= 8)
|
||||
f1 = (f2 == 0) ? 15 : 0;
|
||||
else
|
||||
f1 = (f2 == 0) ? 8 : 0;
|
||||
} else if (con_mode == CON_ANSI_MONO && f1 != f2) {
|
||||
f1 = f2 ^ 0x08;
|
||||
}
|
||||
|
||||
screen->setFg(screen, f1 & mask_fg);
|
||||
return last_fg;
|
||||
}
|
||||
|
||||
static void print0(FILE *f, const char *ss) {
|
||||
int cx, cy;
|
||||
int old_cx = 0, old_cy = 0;
|
||||
const int sx = screen->getCols(screen);
|
||||
const int sy = screen->getRows(screen);
|
||||
int pass;
|
||||
|
||||
// Note:
|
||||
// We use 2 passes to avoid unnecessary system calls because
|
||||
// scrollUp() under Win32 is *extremely* slow.
|
||||
UNUSED(f);
|
||||
|
||||
screen->getCursor(screen, &old_cx, &old_cy);
|
||||
cx = old_cx;
|
||||
cy = old_cy;
|
||||
|
||||
for (pass = 0; pass < 2; pass++) {
|
||||
const char *s = ss;
|
||||
// char buffer for pass 2
|
||||
char p[256 + 1];
|
||||
int pi = 0, px = 0, py = 0;
|
||||
|
||||
for (;;) {
|
||||
// walk over whitespace
|
||||
for (;;) {
|
||||
if (*s == '\n') {
|
||||
cx = 0;
|
||||
cy++;
|
||||
} else if (*s == '\r') {
|
||||
cx = 0;
|
||||
if (pass > 0 && cy < sy)
|
||||
screen->clearLine(screen, cy);
|
||||
} else
|
||||
break;
|
||||
s++;
|
||||
}
|
||||
// adjust cursor
|
||||
if (cx >= sx) {
|
||||
cx = 0;
|
||||
cy++;
|
||||
}
|
||||
if (pass > 0) {
|
||||
// check if we should print something
|
||||
if (pi > 0 && (*s == 0 || py != cy)) {
|
||||
p[pi] = 0;
|
||||
screen->putString(screen, p, px, py);
|
||||
pi = 0;
|
||||
}
|
||||
// check if we should scroll even more (this can happen
|
||||
// if the string is longer than sy lines)
|
||||
if (cy >= sy) {
|
||||
int scroll_y = cy - sy + 1;
|
||||
screen->scrollUp(screen, scroll_y);
|
||||
cy -= scroll_y;
|
||||
if (cy < 0)
|
||||
cy = 0;
|
||||
}
|
||||
}
|
||||
// done ?
|
||||
if (*s == 0)
|
||||
break;
|
||||
if (pass > 0) {
|
||||
// store current char
|
||||
if (pi == 0) {
|
||||
px = cx;
|
||||
py = cy;
|
||||
}
|
||||
p[pi++] = *s;
|
||||
}
|
||||
// advance
|
||||
cx++;
|
||||
s++;
|
||||
}
|
||||
|
||||
if (pass == 0) {
|
||||
// end of pass 1 - scroll up, restore cursor
|
||||
if (cy >= sy) {
|
||||
int scroll_y = cy - sy + 1;
|
||||
screen->scrollUp(screen, scroll_y);
|
||||
cy = old_cy - scroll_y;
|
||||
if (cy < 0)
|
||||
cy = 0;
|
||||
} else
|
||||
cy = old_cy;
|
||||
cx = old_cx;
|
||||
}
|
||||
}
|
||||
|
||||
screen->setCursor(screen, cx, cy);
|
||||
screen->refresh(screen);
|
||||
}
|
||||
|
||||
static bool intro(FILE *f) {
|
||||
UNUSED(f);
|
||||
#if (USE_FRAMES)
|
||||
if (screen->intro)
|
||||
return screen->intro(screen, screen_show_frames);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
console_t console_screen = {init, set_fg, print0, intro};
|
||||
|
||||
#endif /* USE_SCREEN */
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
@@ -0,0 +1,169 @@
|
||||
/* console.h --
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
and/or modify them under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING.
|
||||
If not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
#undef USE_CONSOLE
|
||||
#undef USE_ANSI
|
||||
#undef USE_SCREEN
|
||||
#undef USE_SCREEN_CURSES
|
||||
#undef USE_SCREEN_VCSA
|
||||
#undef USE_SCREEN_WIN32
|
||||
#undef USE_FRAMES
|
||||
|
||||
#if 1 && (WITH_GUI) && !defined(NO_CONSOLE)
|
||||
#define NO_CONSOLE 1
|
||||
#endif
|
||||
|
||||
#if 1 && defined(__linux__)
|
||||
#define USE_SCREEN 1
|
||||
#define USE_SCREEN_VCSA 1
|
||||
#if !(HAVE_LINUX_KD_H)
|
||||
#undef USE_SCREEN
|
||||
#undef USE_SCREEN_VCSA
|
||||
#endif
|
||||
#if !(HAVE_LINUX_KDEV_T_H) || !(HAVE_LINUX_MAJOR_H)
|
||||
#undef USE_SCREEN
|
||||
#undef USE_SCREEN_VCSA
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if 1 && (ACC_OS_DOS32) && defined(__DJGPP__)
|
||||
#define USE_SCREEN 1
|
||||
#elif 1 && (ACC_OS_CYGWIN || ACC_OS_WIN32 || ACC_OS_WIN64)
|
||||
#define USE_SCREEN 1
|
||||
#define USE_SCREEN_WIN32 1
|
||||
#elif 1 && (ACC_OS_EMX && defined(__RSXNT__))
|
||||
#define USE_SCREEN 1
|
||||
#define USE_SCREEN_WIN32 1
|
||||
#elif 1 && (ACC_ARCH_M68K && ACC_OS_TOS)
|
||||
#define NO_CONSOLE 1
|
||||
#endif
|
||||
|
||||
#if 0 || (NO_ANSI)
|
||||
#undef USE_ANSI
|
||||
#endif
|
||||
#if 0 || (NO_SCREEN)
|
||||
#undef USE_SCREEN
|
||||
#endif
|
||||
#if 0 || (NO_FRAMES) || !(USE_SCREEN)
|
||||
#undef USE_FRAMES
|
||||
#endif
|
||||
#if 1
|
||||
#undef USE_FRAMES
|
||||
#endif
|
||||
|
||||
#if 0 || (USE_ANSI) || (USE_SCREEN)
|
||||
#define USE_CONSOLE 1
|
||||
#endif
|
||||
|
||||
#if 0 || (NO_CONSOLE) || !(USE_CONSOLE)
|
||||
#undef USE_CONSOLE
|
||||
#undef USE_ANSI
|
||||
#undef USE_SCREEN
|
||||
#undef USE_SCREEN_VCSA
|
||||
#undef USE_SCREEN_CURSES
|
||||
#undef USE_FRAMES
|
||||
#endif
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
enum { CON_INIT, CON_NONE, CON_FILE, CON_ANSI_MONO, CON_ANSI_COLOR, CON_SCREEN, CON_UNUSED };
|
||||
|
||||
#if (USE_CONSOLE)
|
||||
|
||||
typedef struct {
|
||||
int (*init)(FILE *f, int, int);
|
||||
int (*set_fg)(FILE *f, int fg);
|
||||
void (*print0)(FILE *f, const char *s);
|
||||
bool (*intro)(FILE *f);
|
||||
} console_t;
|
||||
|
||||
void con_fprintf(FILE *f, const char *format, ...) attribute_format(2, 3);
|
||||
|
||||
#define FG_BLACK 0x00
|
||||
#define FG_BLUE 0x01
|
||||
#define FG_GREEN 0x02
|
||||
#define FG_CYAN 0x03
|
||||
#define FG_RED 0x04
|
||||
#define FG_VIOLET 0x05
|
||||
#define FG_ORANGE 0x06
|
||||
#define FG_LTGRAY 0x07
|
||||
#define FG_DKGRAY 0x08
|
||||
#define FG_BRTBLUE 0x09
|
||||
#define FG_BRTGREEN 0x0a
|
||||
#define FG_BRTCYAN 0x0b
|
||||
#define FG_BRTRED 0x0c
|
||||
#define FG_BRTVIOLET 0x0d
|
||||
#define FG_YELLOW 0x0e
|
||||
#define FG_WHITE 0x0f
|
||||
|
||||
#define BG_BLACK 0x00
|
||||
#define BG_BLUE 0x10
|
||||
#define BG_GREEN 0x20
|
||||
#define BG_CYAN 0x30
|
||||
#define BG_RED 0x40
|
||||
#define BG_VIOLET 0x50
|
||||
#define BG_ORANGE 0x60
|
||||
#define BG_WHITE 0x70
|
||||
|
||||
#endif /* USE_CONSOLE */
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
extern FILE *con_term;
|
||||
|
||||
#if (USE_CONSOLE)
|
||||
|
||||
extern int con_mode;
|
||||
extern console_t *con;
|
||||
|
||||
extern console_t console_init;
|
||||
extern console_t console_none;
|
||||
extern console_t console_file;
|
||||
extern console_t console_ansi_mono;
|
||||
extern console_t console_ansi_color;
|
||||
extern console_t console_screen;
|
||||
|
||||
#define con_fg(f, x) con->set_fg(f, x)
|
||||
|
||||
#else
|
||||
|
||||
#define con_fg(f, x) 0
|
||||
#define con_fprintf fprintf
|
||||
|
||||
#endif /* USE_CONSOLE */
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
@@ -0,0 +1,442 @@
|
||||
/* s_djgpp2.cpp -- djggp2 DOS screen driver
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
and/or modify them under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING.
|
||||
If not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
#include "../conf.h"
|
||||
|
||||
#if (USE_SCREEN) && (ACC_OS_DOS32) && defined(__DJGPP__)
|
||||
#if (ACC_CC_GNUC >= 0x040300ul)
|
||||
#pragma GCC diagnostic ignored "-Wvla"
|
||||
#endif
|
||||
|
||||
#include "screen.h"
|
||||
|
||||
#define this self
|
||||
|
||||
#define mask_fg 0x0f
|
||||
#define mask_bg 0xf0
|
||||
|
||||
/* #define USE_SCROLLBACK 1 */
|
||||
|
||||
/*************************************************************************
|
||||
// direct screen access
|
||||
**************************************************************************/
|
||||
|
||||
#include <dos.h>
|
||||
#if 0
|
||||
#include <conio.h>
|
||||
#endif
|
||||
#include <dpmi.h>
|
||||
#include <go32.h>
|
||||
#include <sys/exceptn.h>
|
||||
#include <sys/farptr.h>
|
||||
#include <sys/movedata.h>
|
||||
#define dossel _go32_info_block.selector_for_linear_memory
|
||||
#define co80 _go32_info_block.linear_address_of_primary_screen
|
||||
#undef kbhit
|
||||
|
||||
#define Cell upx_uint16_t
|
||||
|
||||
struct screen_data_t {
|
||||
int mode;
|
||||
int cols;
|
||||
int rows;
|
||||
int cursor_x;
|
||||
int cursor_y;
|
||||
int scroll_counter;
|
||||
unsigned char attr;
|
||||
unsigned char init_attr;
|
||||
unsigned char empty_attr;
|
||||
Cell empty_cell;
|
||||
#if USE_SCROLLBACK
|
||||
/* scrollback buffer */
|
||||
Cell sb_buf[32][256];
|
||||
int sb_size;
|
||||
int sb_base;
|
||||
int sb_sp;
|
||||
#endif /* USE_SCROLLBACK */
|
||||
};
|
||||
|
||||
/* atExit information */
|
||||
static struct {
|
||||
int cursor_shape;
|
||||
} ae = {-1};
|
||||
|
||||
#if USE_SCROLLBACK
|
||||
static __inline__ void sb_add(screen_t *this, int *val, int inc) {
|
||||
*val = (*val + inc) & (this->data->sb_size - 1);
|
||||
}
|
||||
|
||||
static void sb_push(screen_t *this, const Cell *line, int len) {
|
||||
memcpy(this->data->sb_buf[this->data->sb_sp], line, len);
|
||||
sb_add(this, &this->data->sb_sp, 1);
|
||||
if (this->data->sb_sp == this->data->sb_base)
|
||||
sb_add(this, &this->data->sb_base, 1);
|
||||
}
|
||||
|
||||
static const Cell *sb_pop(screen_t *this) {
|
||||
if (this->data->sb_sp == this->data->sb_base)
|
||||
return nullptr;
|
||||
sb_add(this, &this->data->sb_sp, -1);
|
||||
return this->data->sb_buf[this->data->sb_sp];
|
||||
}
|
||||
#endif /* USE_SCROLLBACK */
|
||||
|
||||
static void refresh(screen_t *this) { UNUSED(this); }
|
||||
|
||||
static __inline__ Cell make_cell(screen_t *this, int ch, int attr) {
|
||||
UNUSED(this);
|
||||
return (Cell) (((attr & 0xff) << 8) | (ch & 0xff));
|
||||
}
|
||||
|
||||
static int getMode(const screen_t *this) {
|
||||
UNUSED(this);
|
||||
return ScreenMode();
|
||||
}
|
||||
|
||||
static int getPage(const screen_t *this) {
|
||||
UNUSED(this);
|
||||
return _farpeekb(dossel, 0x462);
|
||||
}
|
||||
|
||||
static int getRows(const screen_t *this) { return this->data->rows; }
|
||||
|
||||
static int getCols(const screen_t *this) { return this->data->cols; }
|
||||
|
||||
static int isMono(const screen_t *this) {
|
||||
if (this->data->mode == 7)
|
||||
return 1;
|
||||
if ((_farpeekb(dossel, 0x465) & (4 | 16)) != 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int getFg(const screen_t *this) { return this->data->attr & mask_fg; }
|
||||
|
||||
static int getBg(const screen_t *this) { return this->data->attr & mask_bg; }
|
||||
|
||||
static void setFg(screen_t *this, int fg) {
|
||||
this->data->attr = (this->data->attr & mask_bg) | (fg & mask_fg);
|
||||
}
|
||||
|
||||
static void setBg(screen_t *this, int bg) {
|
||||
this->data->attr = (this->data->attr & mask_fg) | (bg & mask_bg);
|
||||
}
|
||||
|
||||
static void setCursor(screen_t *this, int x, int y) {
|
||||
if (x >= 0 && y >= 0 && x < this->data->cols && y < this->data->rows) {
|
||||
ScreenSetCursor(y, x);
|
||||
this->data->cursor_x = x;
|
||||
this->data->cursor_y = y;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// I added ScreenGetCursor, because when upx prints something longer than
|
||||
// 1 line (an error message for example), the this->data->cursor_y can
|
||||
// have a bad value - ml1050
|
||||
|
||||
// FIXME:
|
||||
// Laszlo: when does this happen ? This probably indicates a
|
||||
// bug in c_screen.cpp(print0) I've introduced with
|
||||
// the 2 passes implementation.
|
||||
*/
|
||||
|
||||
static void getCursor(const screen_t *this, int *x, int *y) {
|
||||
int cx = this->data->cursor_x;
|
||||
int cy = this->data->cursor_y;
|
||||
#if 1
|
||||
ScreenGetCursor(&cy, &cx);
|
||||
#endif
|
||||
if (x)
|
||||
*x = cx;
|
||||
if (y)
|
||||
*y = cy;
|
||||
}
|
||||
|
||||
static void putCharAttr(screen_t *this, int ch, int attr, int x, int y) {
|
||||
UNUSED(this);
|
||||
ScreenPutChar(ch, attr, x, y);
|
||||
}
|
||||
|
||||
static void putChar(screen_t *this, int ch, int x, int y) {
|
||||
ScreenPutChar(ch, this->data->attr, x, y);
|
||||
}
|
||||
|
||||
static void putStringAttr(screen_t *this, const char *s, int attr, int x, int y) {
|
||||
UNUSED(this);
|
||||
assert((int) strlen(s) <= 256);
|
||||
assert(x + (int) strlen(s) <= this->data->cols);
|
||||
ScreenPutString(s, attr, x, y);
|
||||
}
|
||||
|
||||
static void putString(screen_t *this, const char *s, int x, int y) {
|
||||
assert((int) strlen(s) <= 256);
|
||||
assert(x + (int) strlen(s) <= this->data->cols);
|
||||
ScreenPutString(s, this->data->attr, x, y);
|
||||
}
|
||||
|
||||
/* private */
|
||||
static void getChar(screen_t *this, int *ch, int *attr, int x, int y) {
|
||||
UNUSED(this);
|
||||
ScreenGetChar(ch, attr, x, y);
|
||||
}
|
||||
|
||||
static int getCursorShape(const screen_t *this) {
|
||||
UNUSED(this);
|
||||
return _farpeekw(dossel, 0x460);
|
||||
}
|
||||
|
||||
static void setCursorShape(screen_t *this, int shape) {
|
||||
__dpmi_regs r;
|
||||
|
||||
memset(&r, 0, sizeof(r)); /* just in case... */
|
||||
r.x.ax = 0x0103;
|
||||
#if 1
|
||||
if (this)
|
||||
r.h.al = getMode(this); /* required for buggy BIOSes */
|
||||
#endif
|
||||
r.x.cx = shape & 0x7f1f;
|
||||
__dpmi_int(0x10, &r);
|
||||
}
|
||||
|
||||
static int hideCursor(screen_t *this) {
|
||||
int shape = getCursorShape(this);
|
||||
setCursorShape(this, 0x2000);
|
||||
return shape;
|
||||
}
|
||||
|
||||
static int init(screen_t *this, int fd) {
|
||||
int mode;
|
||||
int cols, rows;
|
||||
int attr;
|
||||
|
||||
#if 0
|
||||
/* force linkage of conio.o */
|
||||
(void) _conio_kbhit();
|
||||
#endif
|
||||
|
||||
if (!this || !this->data)
|
||||
return -1;
|
||||
|
||||
this->data->mode = -1;
|
||||
#if USE_SCROLLBACK
|
||||
this->data->sb_size = 32;
|
||||
this->data->sb_base = 0;
|
||||
this->data->sb_sp = 0;
|
||||
#endif
|
||||
if (fd < 0 || !acc_isatty(fd))
|
||||
return -1;
|
||||
if (getPage(this) != 0)
|
||||
return -1;
|
||||
|
||||
#if 1 && (ACC_OS_DOS32) && defined(__DJGPP__)
|
||||
/* check for Windows NT/2000/XP */
|
||||
if (_get_dos_version(1) == 0x0532)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
cols = ScreenCols();
|
||||
rows = ScreenRows();
|
||||
mode = getMode(this);
|
||||
if (mode > 0x13) {
|
||||
/* assume this is some SVGA/VESA text mode */
|
||||
__dpmi_regs r;
|
||||
|
||||
memset(&r, 0, sizeof(r)); /* just in case... */
|
||||
r.x.ax = 0x4f03; /* VESA - get current video mode */
|
||||
__dpmi_int(0x10, &r);
|
||||
if (r.h.ah == 0)
|
||||
mode = r.x.bx;
|
||||
} else {
|
||||
if (mode != 2 && mode != 3 && mode != 7)
|
||||
return -1;
|
||||
}
|
||||
ScreenGetCursor(&this->data->cursor_y, &this->data->cursor_x);
|
||||
getChar(this, nullptr, &attr, this->data->cursor_x, this->data->cursor_y);
|
||||
this->data->init_attr = attr;
|
||||
if (mode != 7) {
|
||||
/* Does it normally blink when bg has its 3rd bit set? */
|
||||
int b_mask = (_farpeekb(dossel, 0x465) & 0x20) ? 0x70 : 0xf0;
|
||||
attr = attr & (mask_fg | b_mask);
|
||||
}
|
||||
this->data->mode = mode;
|
||||
this->data->cols = cols;
|
||||
this->data->rows = rows;
|
||||
this->data->attr = attr;
|
||||
this->data->empty_attr = attr;
|
||||
this->data->empty_cell = make_cell(this, ' ', attr);
|
||||
|
||||
ae.cursor_shape = getCursorShape(this);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void updateLineN(screen_t *this, const void *line, int y, int len) {
|
||||
if (y >= 0 && y < this->data->rows && len > 0 && len <= 2 * this->data->cols)
|
||||
movedata(_my_ds(), (unsigned) line, dossel, co80 + y * this->data->cols * 2, len);
|
||||
}
|
||||
|
||||
static void clearLine(screen_t *this, int y) {
|
||||
if (y >= 0 && y < this->data->rows) {
|
||||
unsigned sp = co80 + y * this->data->cols * 2;
|
||||
Cell a = this->data->empty_cell;
|
||||
int i = this->data->cols;
|
||||
|
||||
_farsetsel(dossel);
|
||||
do {
|
||||
_farnspokew(sp, a);
|
||||
sp += 2;
|
||||
} while (--i);
|
||||
}
|
||||
}
|
||||
|
||||
static void clear(screen_t *this) {
|
||||
unsigned char attr = ScreenAttrib;
|
||||
ScreenAttrib = this->data->empty_attr;
|
||||
ScreenClear();
|
||||
ScreenAttrib = attr;
|
||||
}
|
||||
|
||||
static int scrollUp(screen_t *this, int lines) {
|
||||
int sr = this->data->rows;
|
||||
int sc = this->data->cols;
|
||||
int y;
|
||||
|
||||
if (lines <= 0 || lines > sr)
|
||||
return 0;
|
||||
|
||||
#if USE_SCROLLBACK
|
||||
/* copy to scrollback buffer */
|
||||
for (y = 0; y < lines; y++) {
|
||||
Cell buf[sc];
|
||||
movedata(dossel, co80 + y * this->data->cols * 2, _my_ds(), (unsigned) buf, sizeof(buf));
|
||||
sb_push(this, buf, sizeof(buf));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* move screen up */
|
||||
if (lines < sr)
|
||||
movedata(dossel, co80 + lines * sc * 2, dossel, co80, (sr - lines) * sc * 2);
|
||||
|
||||
/* fill in blank lines at bottom */
|
||||
for (y = sr - lines; y < sr; y++)
|
||||
clearLine(this, y);
|
||||
|
||||
this->data->scroll_counter += lines;
|
||||
return lines;
|
||||
}
|
||||
|
||||
static int scrollDown(screen_t *this, int lines) {
|
||||
int sr = this->data->rows;
|
||||
int sc = this->data->cols;
|
||||
int y;
|
||||
|
||||
if (lines <= 0 || lines > sr)
|
||||
return 0;
|
||||
|
||||
/* move screen down */
|
||||
if (lines < sr) {
|
||||
/* !@#% movedata can't handle overlapping regions... */
|
||||
/* movedata(dossel,co80,dossel,co80+lines*sc*2,(sr-lines)*sc*2); */
|
||||
Cell buf[(sr - lines) * sc];
|
||||
movedata(dossel, co80, _my_ds(), (unsigned) buf, sizeof(buf));
|
||||
movedata(_my_ds(), (unsigned) buf, dossel, co80 + lines * sc * 2, sizeof(buf));
|
||||
}
|
||||
|
||||
/* copy top lines from scrollback buffer */
|
||||
for (y = lines; --y >= 0;) {
|
||||
#if USE_SCROLLBACK
|
||||
const Cell *buf = sb_pop(this);
|
||||
if (buf == nullptr)
|
||||
clearLine(this, y);
|
||||
else
|
||||
updateLineN(this, buf, y, sc * 2);
|
||||
#else
|
||||
clearLine(this, y);
|
||||
#endif
|
||||
}
|
||||
|
||||
this->data->scroll_counter -= lines;
|
||||
return lines;
|
||||
}
|
||||
|
||||
static int getScrollCounter(const screen_t *this) { return this->data->scroll_counter; }
|
||||
|
||||
static int s_kbhit(screen_t *this) {
|
||||
UNUSED(this);
|
||||
return kbhit();
|
||||
}
|
||||
|
||||
static int intro(screen_t *this, void (*show_frames)(screen_t *)) {
|
||||
int shape;
|
||||
upx_uint16_t old_flags = __djgpp_hwint_flags;
|
||||
|
||||
if ((this->data->init_attr & mask_bg) != BG_BLACK)
|
||||
return 0;
|
||||
|
||||
__djgpp_hwint_flags |= 3;
|
||||
while (kbhit())
|
||||
(void) getkey();
|
||||
|
||||
shape = hideCursor(this);
|
||||
show_frames(this);
|
||||
setCursorShape(this, shape);
|
||||
|
||||
while (kbhit())
|
||||
(void) getkey();
|
||||
__djgpp_hwint_flags = old_flags;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void atExit(void) {
|
||||
static int done = 0;
|
||||
if (done)
|
||||
return;
|
||||
done = 1;
|
||||
if (ae.cursor_shape >= 0)
|
||||
setCursorShape(nullptr, ae.cursor_shape);
|
||||
}
|
||||
|
||||
static const screen_t driver = {sobject_destroy, nullptr, /* finalize */
|
||||
atExit, init, refresh,
|
||||
getMode, getPage, getRows,
|
||||
getCols, isMono, getFg,
|
||||
getBg, getCursor, getCursorShape,
|
||||
setFg, setBg, setCursor,
|
||||
setCursorShape, hideCursor, putChar,
|
||||
putCharAttr, putString, putStringAttr,
|
||||
clear, clearLine, updateLineN,
|
||||
scrollUp, scrollDown, getScrollCounter,
|
||||
s_kbhit, intro, (struct screen_data_t *) nullptr};
|
||||
|
||||
/* public constructor */
|
||||
screen_t *screen_djgpp2_construct(void) { return sobject_construct(&driver, sizeof(*driver.data)); }
|
||||
|
||||
#endif /* (USE_SCREEN) && (ACC_OS_DOS32) && defined(__DJGPP__) */
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
@@ -0,0 +1,85 @@
|
||||
/* s_object.cpp -- base of all screen drivers
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
and/or modify them under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING.
|
||||
If not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
#include "../conf.h"
|
||||
|
||||
#if (USE_SCREEN)
|
||||
|
||||
#define this self
|
||||
|
||||
#include "screen.h"
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
// ugly hacks
|
||||
static screen_t *last_screen = nullptr;
|
||||
|
||||
screen_t *sobject_get_screen(void) { return last_screen; }
|
||||
|
||||
void sobject_destroy(screen_t *this) {
|
||||
last_screen = nullptr;
|
||||
if (!this)
|
||||
return;
|
||||
if (this->data) {
|
||||
if (this->finalize)
|
||||
this->finalize(this);
|
||||
free(this->data);
|
||||
this->data = nullptr;
|
||||
}
|
||||
free(this);
|
||||
}
|
||||
|
||||
screen_t *sobject_construct(const screen_t *c, size_t data_size) {
|
||||
screen_t *this;
|
||||
|
||||
last_screen = nullptr;
|
||||
|
||||
/* allocate object */
|
||||
this = (screen_t *) malloc(sizeof(*this));
|
||||
if (!this)
|
||||
return nullptr;
|
||||
|
||||
/* copy function table */
|
||||
*this = *c;
|
||||
|
||||
/* initialize instance variables */
|
||||
this->data = (struct screen_data_t *) malloc(data_size);
|
||||
if (!this->data) {
|
||||
free(this);
|
||||
return nullptr;
|
||||
}
|
||||
memset(this->data, 0, data_size);
|
||||
|
||||
last_screen = this;
|
||||
return this;
|
||||
}
|
||||
|
||||
#endif /* (USE_SCREEN) */
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
@@ -0,0 +1,494 @@
|
||||
/* s_vcsa.cpp -- Linux /dev/vcsa screen driver
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
and/or modify them under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING.
|
||||
If not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
#include "../conf.h"
|
||||
|
||||
#if (USE_SCREEN) && (USE_SCREEN_VCSA)
|
||||
|
||||
#include "screen.h"
|
||||
|
||||
#define this self
|
||||
|
||||
#define mask_fg 0x0f
|
||||
#define mask_bg 0xf0
|
||||
|
||||
/* #define USE_SCROLLBACK 1 */
|
||||
|
||||
/*************************************************************************
|
||||
// direct screen access ( /dev/vcsaNN )
|
||||
**************************************************************************/
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/select.h>
|
||||
#include <termios.h>
|
||||
#if defined(__linux__)
|
||||
#include <linux/kd.h>
|
||||
#include <linux/kdev_t.h>
|
||||
#include <linux/major.h>
|
||||
#endif
|
||||
|
||||
#define Cell upx_uint16_t
|
||||
|
||||
struct screen_data_t {
|
||||
int fd;
|
||||
int mode;
|
||||
int page;
|
||||
int cols;
|
||||
int rows;
|
||||
int cursor_x;
|
||||
int cursor_y;
|
||||
int scroll_counter;
|
||||
unsigned char attr;
|
||||
unsigned char init_attr;
|
||||
unsigned char map[256];
|
||||
Cell empty_line[256];
|
||||
#if USE_SCROLLBACK
|
||||
/* scrollback buffer */
|
||||
Cell sb_buf[32][256];
|
||||
int sb_size;
|
||||
int sb_base;
|
||||
int sb_sp;
|
||||
#endif /* USE_SCROLLBACK */
|
||||
};
|
||||
|
||||
#if USE_SCROLLBACK
|
||||
static __inline__ void sb_add(screen_t *this, int *val, int inc) {
|
||||
*val = (*val + inc) & (this->data->sb_size - 1);
|
||||
}
|
||||
|
||||
static void sb_push(screen_t *this, const Cell *line, int len) {
|
||||
memcpy(this->data->sb_buf[this->data->sb_sp], line, len);
|
||||
sb_add(this, &this->data->sb_sp, 1);
|
||||
if (this->data->sb_sp == this->data->sb_base)
|
||||
sb_add(this, &this->data->sb_base, 1);
|
||||
}
|
||||
|
||||
static const Cell *sb_pop(screen_t *this) {
|
||||
if (this->data->sb_sp == this->data->sb_base)
|
||||
return nullptr;
|
||||
sb_add(this, &this->data->sb_sp, -1);
|
||||
return this->data->sb_buf[this->data->sb_sp];
|
||||
}
|
||||
#endif /* USE_SCROLLBACK */
|
||||
|
||||
static void refresh(screen_t *this) { UNUSED(this); }
|
||||
|
||||
static __inline__ Cell make_cell(screen_t *this, int ch, int attr) {
|
||||
return ((attr & 0xff) << 8) | (this->data->map[ch & 0xff] & 0xff);
|
||||
}
|
||||
|
||||
static int getMode(const screen_t *this) { return this->data->mode; }
|
||||
|
||||
static int getPage(const screen_t *this) { return this->data->page; }
|
||||
|
||||
static int getRows(const screen_t *this) { return this->data->rows; }
|
||||
|
||||
static int getCols(const screen_t *this) { return this->data->cols; }
|
||||
|
||||
static int isMono(const screen_t *this) {
|
||||
/* FIXME */
|
||||
UNUSED(this);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int getFg(const screen_t *this) { return this->data->attr & mask_fg; }
|
||||
|
||||
static int getBg(const screen_t *this) { return this->data->attr & mask_bg; }
|
||||
|
||||
static void setFg(screen_t *this, int fg) {
|
||||
this->data->attr = (this->data->attr & mask_bg) | (fg & mask_fg);
|
||||
}
|
||||
|
||||
static void setBg(screen_t *this, int bg) {
|
||||
this->data->attr = (this->data->attr & mask_fg) | (bg & mask_bg);
|
||||
}
|
||||
|
||||
/* private */
|
||||
static int gotoxy(screen_t *this, int x, int y) {
|
||||
if (x >= 0 && y >= 0 && x < this->data->cols && y < this->data->rows) {
|
||||
if (lseek(this->data->fd, 4 + (x + y * this->data->cols) * 2, SEEK_SET) != -1) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void setCursor(screen_t *this, int x, int y) {
|
||||
if (gotoxy(this, x, y) == 0) {
|
||||
unsigned char b[2] = {x, y};
|
||||
if (lseek(this->data->fd, 2, SEEK_SET) != -1)
|
||||
write(this->data->fd, b, 2);
|
||||
this->data->cursor_x = x;
|
||||
this->data->cursor_y = y;
|
||||
}
|
||||
}
|
||||
|
||||
static void getCursor(const screen_t *this, int *x, int *y) {
|
||||
int cx = this->data->cursor_x;
|
||||
int cy = this->data->cursor_y;
|
||||
#if 1
|
||||
if (lseek(this->data->fd, 2, SEEK_SET) != -1) {
|
||||
unsigned char b[2];
|
||||
if (read(this->data->fd, b, 2) == 2) {
|
||||
if (b[0] < this->data->cols && b[1] < this->data->rows) {
|
||||
cx = b[0];
|
||||
cy = b[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (x)
|
||||
*x = cx;
|
||||
if (y)
|
||||
*y = cy;
|
||||
}
|
||||
|
||||
static void putCharAttr(screen_t *this, int ch, int attr, int x, int y) {
|
||||
Cell a = make_cell(this, ch, attr);
|
||||
|
||||
if (gotoxy(this, x, y) == 0)
|
||||
write(this->data->fd, &a, 2);
|
||||
}
|
||||
|
||||
static void putChar(screen_t *this, int ch, int x, int y) {
|
||||
putCharAttr(this, ch, this->data->attr, x, y);
|
||||
}
|
||||
|
||||
static void putStringAttr(screen_t *this, const char *s, int attr, int x, int y) {
|
||||
assert((int) strlen(s) <= 256);
|
||||
assert(x + (int) strlen(s) <= this->data->cols);
|
||||
while (*s)
|
||||
putCharAttr(this, *s++, attr, x++, y);
|
||||
}
|
||||
|
||||
static void putString(screen_t *this, const char *s, int x, int y) {
|
||||
putStringAttr(this, s, this->data->attr, x, y);
|
||||
}
|
||||
|
||||
/* private */
|
||||
static void getChar(screen_t *this, int *ch, int *attr, int x, int y) {
|
||||
upx_uint16_t a;
|
||||
|
||||
if (gotoxy(this, x, y) == 0 && read(this->data->fd, &a, 2) == 2) {
|
||||
if (ch)
|
||||
*ch = a & 0xff;
|
||||
if (attr)
|
||||
*attr = (a >> 8) & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
/* private */
|
||||
static int init_scrnmap(screen_t *this, int fd) {
|
||||
int scrnmap_done = 0;
|
||||
int i;
|
||||
|
||||
#if 1 && defined(GIO_UNISCRNMAP) && defined(E_TABSZ)
|
||||
if (!scrnmap_done) {
|
||||
upx_uint16_t scrnmap[E_TABSZ];
|
||||
if (ioctl(fd, GIO_UNISCRNMAP, scrnmap) == 0) {
|
||||
for (i = 0; i < E_TABSZ; i++)
|
||||
this->data->map[scrnmap[i] & 0xff] = i;
|
||||
scrnmap_done = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if 1 && defined(GIO_SCRNMAP) && defined(E_TABSZ)
|
||||
if (!scrnmap_done) {
|
||||
unsigned char scrnmap[E_TABSZ];
|
||||
if (ioctl(fd, GIO_SCRNMAP, scrnmap) == 0) {
|
||||
for (i = 0; i < E_TABSZ; i++)
|
||||
this->data->map[scrnmap[i] & 0xff] = i;
|
||||
scrnmap_done = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return scrnmap_done;
|
||||
}
|
||||
|
||||
static int init(screen_t *this, int fd) {
|
||||
struct stat st;
|
||||
|
||||
if (!this || !this->data)
|
||||
return -1;
|
||||
|
||||
this->data->fd = -1;
|
||||
this->data->mode = -1;
|
||||
this->data->page = 0;
|
||||
#if USE_SCROLLBACK
|
||||
this->data->sb_size = 32;
|
||||
this->data->sb_base = 0;
|
||||
this->data->sb_sp = 0;
|
||||
#endif
|
||||
if (fd < 0 || !acc_isatty(fd))
|
||||
return -1;
|
||||
if (fstat(fd, &st) != 0)
|
||||
return -1;
|
||||
|
||||
/* check if we are running in a virtual console */
|
||||
#if defined(MINOR) && defined(MAJOR) && defined(TTY_MAJOR)
|
||||
if (MAJOR(st.st_rdev) == TTY_MAJOR) {
|
||||
char vc_name[64];
|
||||
unsigned char vc_data[4];
|
||||
int i;
|
||||
int attr;
|
||||
Cell a;
|
||||
|
||||
upx_safe_snprintf(vc_name, sizeof(vc_name), "/dev/vcsa%d", (int) MINOR(st.st_rdev));
|
||||
this->data->fd = open(vc_name, O_RDWR);
|
||||
if (this->data->fd == -1) {
|
||||
upx_safe_snprintf(vc_name, sizeof(vc_name), "/dev/vcc/a%d", (int) MINOR(st.st_rdev));
|
||||
this->data->fd = open(vc_name, O_RDWR);
|
||||
}
|
||||
if (this->data->fd != -1) {
|
||||
if (read(this->data->fd, vc_data, 4) == 4) {
|
||||
this->data->mode = 3;
|
||||
this->data->rows = vc_data[0];
|
||||
this->data->cols = vc_data[1];
|
||||
this->data->cursor_x = vc_data[2];
|
||||
this->data->cursor_y = vc_data[3];
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
this->data->map[i] = i;
|
||||
i = init_scrnmap(this, this->data->fd) || init_scrnmap(this, STDIN_FILENO);
|
||||
|
||||
getChar(this, nullptr, &attr, this->data->cursor_x, this->data->cursor_y);
|
||||
this->data->init_attr = attr;
|
||||
this->data->attr = attr;
|
||||
a = make_cell(this, ' ', attr);
|
||||
for (i = 0; i < 256; i++)
|
||||
this->data->empty_line[i] = a;
|
||||
} else {
|
||||
close(this->data->fd);
|
||||
this->data->fd = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (this->data->mode < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void finalize(screen_t *this) {
|
||||
if (this->data->fd != -1)
|
||||
(void) close(this->data->fd);
|
||||
}
|
||||
|
||||
static void updateLineN(screen_t *this, const void *line, int y, int len) {
|
||||
if (len > 0 && len <= 2 * this->data->cols && gotoxy(this, 0, y) == 0) {
|
||||
int i;
|
||||
unsigned char new_line[len];
|
||||
unsigned char *l1 = new_line;
|
||||
const unsigned char *l2 = (const unsigned char *) line;
|
||||
|
||||
for (i = 0; i < len; i += 2) {
|
||||
*l1++ = *l2++;
|
||||
*l1++ = this->data->map[*l2++];
|
||||
}
|
||||
write(this->data->fd, new_line, len);
|
||||
}
|
||||
}
|
||||
|
||||
static void clearLine(screen_t *this, int y) {
|
||||
if (gotoxy(this, 0, y) == 0)
|
||||
write(this->data->fd, this->data->empty_line, 2 * this->data->cols);
|
||||
}
|
||||
|
||||
static void clear(screen_t *this) {
|
||||
int y;
|
||||
|
||||
for (y = 0; y < this->data->rows; y++)
|
||||
clearLine(this, y);
|
||||
}
|
||||
|
||||
static int scrollUp(screen_t *this, int lines) {
|
||||
int sr = this->data->rows;
|
||||
int sc = this->data->cols;
|
||||
int y;
|
||||
|
||||
if (lines <= 0 || lines > sr)
|
||||
return 0;
|
||||
|
||||
#if USE_SCROLLBACK
|
||||
/* copy to scrollback buffer */
|
||||
for (y = 0; y < lines; y++) {
|
||||
Cell buf[sc];
|
||||
gotoxy(this, 0, y);
|
||||
read(this->data->fd, buf, sizeof(buf));
|
||||
sb_push(this, buf, sizeof(buf));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* move screen up */
|
||||
if (lines < sr) {
|
||||
Cell buf[(sr - lines) * sc];
|
||||
gotoxy(this, 0, lines);
|
||||
read(this->data->fd, buf, sizeof(buf));
|
||||
gotoxy(this, 0, 0);
|
||||
write(this->data->fd, buf, sizeof(buf));
|
||||
}
|
||||
|
||||
/* fill in blank lines at bottom */
|
||||
for (y = sr - lines; y < sr; y++)
|
||||
clearLine(this, y);
|
||||
|
||||
this->data->scroll_counter += lines;
|
||||
return lines;
|
||||
}
|
||||
|
||||
static int scrollDown(screen_t *this, int lines) {
|
||||
int sr = this->data->rows;
|
||||
int sc = this->data->cols;
|
||||
int y;
|
||||
|
||||
if (lines <= 0 || lines > sr)
|
||||
return 0;
|
||||
|
||||
/* move screen down */
|
||||
if (lines < sr) {
|
||||
Cell buf[(sr - lines) * sc];
|
||||
gotoxy(this, 0, 0);
|
||||
read(this->data->fd, buf, sizeof(buf));
|
||||
gotoxy(this, 0, lines);
|
||||
write(this->data->fd, buf, sizeof(buf));
|
||||
}
|
||||
|
||||
/* copy top lines from scrollback buffer */
|
||||
for (y = lines; --y >= 0;) {
|
||||
#if USE_SCROLLBACK
|
||||
const Cell *buf = sb_pop(this);
|
||||
if (buf == nullptr)
|
||||
clearLine(this, y);
|
||||
else
|
||||
updateLineN(this, buf, y, sc * 2);
|
||||
#else
|
||||
clearLine(this, y);
|
||||
#endif
|
||||
}
|
||||
|
||||
this->data->scroll_counter -= lines;
|
||||
return lines;
|
||||
}
|
||||
|
||||
static int getScrollCounter(const screen_t *this) { return this->data->scroll_counter; }
|
||||
|
||||
static int getCursorShape(const screen_t *this) {
|
||||
UNUSED(this);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void setCursorShape(screen_t *this, int shape) {
|
||||
UNUSED(this);
|
||||
UNUSED(shape);
|
||||
}
|
||||
|
||||
static int kbhit(screen_t *this) {
|
||||
const int fd = STDIN_FILENO;
|
||||
const unsigned usec = 0;
|
||||
struct timeval tv;
|
||||
fd_set fds;
|
||||
|
||||
UNUSED(this);
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fd, &fds);
|
||||
tv.tv_sec = usec / 1000000;
|
||||
tv.tv_usec = usec % 1000000;
|
||||
return (select(fd + 1, &fds, nullptr, nullptr, &tv) > 0);
|
||||
}
|
||||
|
||||
static int intro(screen_t *this, void (*show_frames)(screen_t *)) {
|
||||
int shape;
|
||||
struct termios term_old, term_new;
|
||||
int term_r;
|
||||
|
||||
if ((this->data->init_attr & mask_bg) != BG_BLACK)
|
||||
return 0;
|
||||
|
||||
term_r = tcgetattr(STDIN_FILENO, &term_old);
|
||||
if (term_r == 0) {
|
||||
term_new = term_old;
|
||||
term_new.c_lflag &= ~(ISIG | ICANON | ECHO);
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &term_new);
|
||||
}
|
||||
|
||||
shape = getCursorShape(this);
|
||||
setCursorShape(this, 0x2000);
|
||||
show_frames(this);
|
||||
if (this->data->rows > 24)
|
||||
setCursor(this, this->data->cursor_x, this->data->cursor_y + 1);
|
||||
setCursorShape(this, shape);
|
||||
|
||||
while (kbhit(this))
|
||||
(void) fgetc(stdin);
|
||||
if (term_r == 0)
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &term_old);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const screen_t driver = {sobject_destroy,
|
||||
finalize,
|
||||
nullptr, /* atExit */
|
||||
init,
|
||||
refresh,
|
||||
getMode,
|
||||
getPage,
|
||||
getRows,
|
||||
getCols,
|
||||
isMono,
|
||||
getFg,
|
||||
getBg,
|
||||
getCursor,
|
||||
getCursorShape,
|
||||
setFg,
|
||||
setBg,
|
||||
setCursor,
|
||||
setCursorShape,
|
||||
nullptr, /* hideCursor */
|
||||
putChar,
|
||||
putCharAttr,
|
||||
putString,
|
||||
putStringAttr,
|
||||
clear,
|
||||
clearLine,
|
||||
updateLineN,
|
||||
scrollUp,
|
||||
scrollDown,
|
||||
getScrollCounter,
|
||||
kbhit,
|
||||
intro,
|
||||
(struct screen_data_t *) nullptr};
|
||||
|
||||
/* public constructor */
|
||||
screen_t *screen_vcsa_construct(void) { return sobject_construct(&driver, sizeof(*driver.data)); }
|
||||
|
||||
#endif /* (USE_SCREEN) && (USE_SCREEN_VCSA) */
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
@@ -0,0 +1,415 @@
|
||||
/* s_win32.cpp -- Win32 console screen driver
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
and/or modify them under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING.
|
||||
If not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
#include "../conf.h"
|
||||
|
||||
#if (USE_SCREEN_WIN32)
|
||||
|
||||
#include "screen.h"
|
||||
|
||||
#define this self
|
||||
|
||||
#define mask_fg 0x0f
|
||||
#define mask_bg 0xf0
|
||||
|
||||
/*************************************************************************
|
||||
// direct screen access
|
||||
**************************************************************************/
|
||||
|
||||
#if (ACC_CC_MSC && (_MSC_VER >= 1000 && _MSC_VER < 1200))
|
||||
/* avoid -W4 warnings in <conio.h> */
|
||||
#pragma warning(disable : 4032)
|
||||
/* avoid -W4 warnings in <windows.h> */
|
||||
#pragma warning(disable : 4201 4214 4514)
|
||||
#endif
|
||||
#if defined(__RSXNT__)
|
||||
#define timeval win32_timeval /* struct timeval already in <sys/time.h> */
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#if (HAVE_CONIO_H)
|
||||
#include <conio.h>
|
||||
#endif
|
||||
|
||||
struct screen_data_t {
|
||||
HANDLE hi;
|
||||
HANDLE ho;
|
||||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||||
#if 0
|
||||
char title[512];
|
||||
#endif
|
||||
|
||||
int mode;
|
||||
int cols;
|
||||
int rows;
|
||||
int cursor_x;
|
||||
int cursor_y;
|
||||
int scroll_counter;
|
||||
|
||||
WORD attr;
|
||||
WORD init_attr;
|
||||
|
||||
CHAR_INFO empty_cell;
|
||||
CHAR_INFO empty_line[256];
|
||||
};
|
||||
|
||||
#define P(x) ((SHORT) (x))
|
||||
|
||||
static const COORD pos00 = {0, 0};
|
||||
static const COORD size11 = {1, 1};
|
||||
|
||||
/* atExit information */
|
||||
static struct {
|
||||
int is_valid;
|
||||
HANDLE ho;
|
||||
CONSOLE_CURSOR_INFO cci;
|
||||
} ae;
|
||||
|
||||
static void refresh(screen_t *this) { UNUSED(this); }
|
||||
|
||||
static int getMode(const screen_t *this) { return this->data->mode; }
|
||||
|
||||
static int getPage(const screen_t *this) {
|
||||
UNUSED(this);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int getRows(const screen_t *this) { return this->data->rows; }
|
||||
|
||||
static int getCols(const screen_t *this) { return this->data->cols; }
|
||||
|
||||
static int isMono(const screen_t *this) {
|
||||
UNUSED(this);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int getFg(const screen_t *this) { return this->data->attr & mask_fg; }
|
||||
|
||||
static int getBg(const screen_t *this) { return this->data->attr & mask_bg; }
|
||||
|
||||
static void setFg(screen_t *this, int fg) {
|
||||
this->data->attr = (WORD) ((this->data->attr & mask_bg) | (fg & mask_fg));
|
||||
SetConsoleTextAttribute(this->data->ho, this->data->attr);
|
||||
}
|
||||
|
||||
static void setBg(screen_t *this, int bg) {
|
||||
this->data->attr = (WORD) ((this->data->attr & mask_fg) | (bg & mask_bg));
|
||||
SetConsoleTextAttribute(this->data->ho, this->data->attr);
|
||||
}
|
||||
|
||||
static void setCursor(screen_t *this, int x, int y) {
|
||||
if (x >= 0 && y >= 0 && x < this->data->cols && y < this->data->rows) {
|
||||
COORD coord = {P(x), P(y)};
|
||||
SetConsoleCursorPosition(this->data->ho, coord);
|
||||
this->data->cursor_x = x;
|
||||
this->data->cursor_y = y;
|
||||
}
|
||||
}
|
||||
|
||||
static void getCursor(const screen_t *this, int *x, int *y) {
|
||||
int cx = this->data->cursor_x;
|
||||
int cy = this->data->cursor_y;
|
||||
#if 1
|
||||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||||
if (GetConsoleScreenBufferInfo(this->data->ho, &csbi)) {
|
||||
cx = csbi.dwCursorPosition.X;
|
||||
cy = csbi.dwCursorPosition.Y;
|
||||
#if 0
|
||||
assert(cx == this->data->cursor_x);
|
||||
assert(cy == this->data->cursor_y);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
if (x)
|
||||
*x = cx;
|
||||
if (y)
|
||||
*y = cy;
|
||||
}
|
||||
|
||||
static void putCharAttr(screen_t *this, int ch, int attr, int x, int y) {
|
||||
CHAR_INFO ci;
|
||||
SMALL_RECT region = {P(x), P(y), P(x), P(y)};
|
||||
ci.Char.UnicodeChar = 0;
|
||||
ci.Char.AsciiChar = (CHAR) ch;
|
||||
ci.Attributes = (WORD) attr;
|
||||
WriteConsoleOutputA(this->data->ho, &ci, size11, pos00, ®ion);
|
||||
}
|
||||
|
||||
static void putChar(screen_t *this, int ch, int x, int y) {
|
||||
this->putCharAttr(this, ch, this->data->attr, x, y);
|
||||
}
|
||||
|
||||
static void putStringAttr(screen_t *this, const char *s, int attr, int x, int y) {
|
||||
int i;
|
||||
int l = (int) strlen(s);
|
||||
if (l <= 0)
|
||||
return;
|
||||
assert(l <= 256);
|
||||
assert(x + l <= this->data->cols);
|
||||
CHAR_INFO ci[256];
|
||||
COORD size = {P(l), 1};
|
||||
SMALL_RECT region = {P(x), P(y), P(x + l - 1), P(y)};
|
||||
for (i = 0; i < l; i++) {
|
||||
ci[i].Char.UnicodeChar = 0;
|
||||
ci[i].Char.AsciiChar = *s++;
|
||||
ci[i].Attributes = (WORD) attr;
|
||||
}
|
||||
WriteConsoleOutputA(this->data->ho, &ci[0], size, pos00, ®ion);
|
||||
}
|
||||
|
||||
static void putString(screen_t *this, const char *s, int x, int y) {
|
||||
this->putStringAttr(this, s, this->data->attr, x, y);
|
||||
}
|
||||
|
||||
/* private */
|
||||
static int cci2shape(const CONSOLE_CURSOR_INFO *cci) {
|
||||
int shape = cci->dwSize & 255;
|
||||
if (!cci->bVisible)
|
||||
shape |= 0x2000;
|
||||
return shape;
|
||||
}
|
||||
|
||||
static int getCursorShape(const screen_t *this) {
|
||||
CONSOLE_CURSOR_INFO cci;
|
||||
GetConsoleCursorInfo(this->data->ho, &cci);
|
||||
return cci2shape(&cci);
|
||||
}
|
||||
|
||||
static void setCursorShape(screen_t *this, int shape) {
|
||||
CONSOLE_CURSOR_INFO cci;
|
||||
cci.dwSize = shape & 255;
|
||||
cci.bVisible = (shape & 0x2000) ? 0 : 1;
|
||||
SetConsoleCursorInfo(this->data->ho, &cci);
|
||||
}
|
||||
|
||||
static int hideCursor(screen_t *this) {
|
||||
CONSOLE_CURSOR_INFO cci;
|
||||
int shape;
|
||||
|
||||
GetConsoleCursorInfo(this->data->ho, &cci);
|
||||
shape = cci2shape(&cci);
|
||||
if (cci.bVisible) {
|
||||
cci.bVisible = 0;
|
||||
SetConsoleCursorInfo(this->data->ho, &cci);
|
||||
}
|
||||
return shape;
|
||||
}
|
||||
|
||||
static int init(screen_t *this, int fd) {
|
||||
HANDLE hi, ho;
|
||||
CONSOLE_SCREEN_BUFFER_INFO *csbi;
|
||||
DWORD mode;
|
||||
WORD attr;
|
||||
int i;
|
||||
|
||||
if (!this || !this->data)
|
||||
return -1;
|
||||
|
||||
this->data->hi = INVALID_HANDLE_VALUE;
|
||||
this->data->ho = INVALID_HANDLE_VALUE;
|
||||
this->data->mode = -1;
|
||||
if (fd < 0 || !acc_isatty(fd))
|
||||
return -1;
|
||||
|
||||
hi = GetStdHandle(STD_INPUT_HANDLE);
|
||||
ho = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
if (hi == INVALID_HANDLE_VALUE || ho == INVALID_HANDLE_VALUE)
|
||||
return -1;
|
||||
if (!GetConsoleMode(ho, &mode))
|
||||
return -1;
|
||||
csbi = &this->data->csbi;
|
||||
if (!GetConsoleScreenBufferInfo(ho, csbi))
|
||||
return -1;
|
||||
if (!GetConsoleCursorInfo(ho, &ae.cci))
|
||||
return -1;
|
||||
#if 0
|
||||
if (!GetConsoleTitle(this->data->title, sizeof(this->data->title)))
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
this->data->cols = csbi->srWindow.Right - csbi->srWindow.Left + 1;
|
||||
this->data->rows = csbi->srWindow.Bottom - csbi->srWindow.Top + 1;
|
||||
if (csbi->srWindow.Left != 0 || csbi->srWindow.Top != 0)
|
||||
return -1;
|
||||
if (this->data->cols != csbi->dwSize.X)
|
||||
return -1;
|
||||
#else
|
||||
this->data->cols = csbi->dwSize.X;
|
||||
this->data->rows = csbi->dwSize.Y;
|
||||
#if 0
|
||||
if (csbi->srWindow.Left != 0)
|
||||
return -1;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
this->data->cursor_x = csbi->dwCursorPosition.X;
|
||||
this->data->cursor_y = csbi->dwCursorPosition.Y;
|
||||
|
||||
ae.ho = ho;
|
||||
ae.is_valid = 1;
|
||||
|
||||
attr = csbi->wAttributes;
|
||||
this->data->hi = hi;
|
||||
this->data->ho = ho;
|
||||
this->data->mode = 3; // ???
|
||||
this->data->attr = attr;
|
||||
this->data->init_attr = attr;
|
||||
this->data->empty_cell.Char.UnicodeChar = 0;
|
||||
this->data->empty_cell.Char.AsciiChar = ' ';
|
||||
this->data->empty_cell.Attributes = attr;
|
||||
for (i = 0; i < 256; i++)
|
||||
this->data->empty_line[i] = this->data->empty_cell;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void updateLineN(screen_t *this, const void *line, int y, int len) {
|
||||
if (y >= 0 && y < this->data->rows && len > 0 && len <= 2 * this->data->cols) {
|
||||
#if 0
|
||||
const char *s = (const char *) line;
|
||||
int l = len / 2;
|
||||
int i;
|
||||
|
||||
assert(l <= 256);
|
||||
CHAR_INFO ci[256];
|
||||
COORD size = { P(l), 1 };
|
||||
SMALL_RECT region = { 0, P(y), P(0 + l - 1), P(y) };
|
||||
for (i = 0; i < l; i++)
|
||||
{
|
||||
ci[i].Char.UnicodeChar = 0;
|
||||
ci[i].Char.AsciiChar = *s++;
|
||||
ci[i].Attributes = *s++;
|
||||
}
|
||||
WriteConsoleOutputA(this->data->ho, &ci[0], size, pos00, ®ion);
|
||||
#endif
|
||||
UNUSED(line);
|
||||
}
|
||||
}
|
||||
|
||||
static void clearLine(screen_t *this, int y) {
|
||||
if (y >= 0 && y < this->data->rows) {
|
||||
COORD size = {P(this->data->cols), 1};
|
||||
SMALL_RECT region = {0, P(y), P(this->data->cols - 1), P(y)};
|
||||
WriteConsoleOutputA(this->data->ho, this->data->empty_line, size, pos00, ®ion);
|
||||
}
|
||||
}
|
||||
|
||||
static void clear(screen_t *this) {
|
||||
int y;
|
||||
for (y = 0; y < this->data->rows; y++)
|
||||
this->clearLine(this, y);
|
||||
}
|
||||
|
||||
/* private */
|
||||
static int do_scroll(screen_t *this, int lines, int way) {
|
||||
if (lines <= 0 || lines > this->data->rows)
|
||||
return 0;
|
||||
if (lines == this->data->rows) {
|
||||
this->clear(this);
|
||||
return lines;
|
||||
}
|
||||
|
||||
SMALL_RECT rect = {0, 0, P(this->data->cols - 1), P(this->data->rows - 1)};
|
||||
// SMALL_RECT clip = rect;
|
||||
COORD dest = {0, 0};
|
||||
switch (way) {
|
||||
case 0:
|
||||
rect.Top = P(rect.Top + lines);
|
||||
break;
|
||||
case 1:
|
||||
rect.Bottom = P(rect.Bottom - lines);
|
||||
dest.Y = P(dest.Y + lines);
|
||||
break;
|
||||
}
|
||||
// ScrollConsoleScreenBuffer(this->data->ho, &rect, &clip, dest, &this->data->empty_cell);
|
||||
ScrollConsoleScreenBuffer(this->data->ho, &rect, nullptr, dest, &this->data->empty_cell);
|
||||
|
||||
return lines;
|
||||
}
|
||||
|
||||
static int scrollUp(screen_t *this, int lines) {
|
||||
lines = do_scroll(this, lines, 0);
|
||||
this->data->scroll_counter += lines;
|
||||
return lines;
|
||||
}
|
||||
|
||||
static int scrollDown(screen_t *this, int lines) {
|
||||
lines = do_scroll(this, lines, 1);
|
||||
this->data->scroll_counter -= lines;
|
||||
return lines;
|
||||
}
|
||||
|
||||
static int getScrollCounter(const screen_t *this) { return this->data->scroll_counter; }
|
||||
|
||||
static int s_kbhit(screen_t *this) {
|
||||
UNUSED(this);
|
||||
#if (HAVE_CONIO_H)
|
||||
#if defined(__RSXNT__)
|
||||
return 0;
|
||||
#elif defined(__BORLANDC__) || defined(__WATCOMC__)
|
||||
return kbhit();
|
||||
#else
|
||||
return _kbhit();
|
||||
#endif
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int intro(screen_t *this, void (*show_frames)(screen_t *)) {
|
||||
UNUSED(this);
|
||||
UNUSED(show_frames);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void atExit(void) {
|
||||
static int done = 0;
|
||||
if (done)
|
||||
return;
|
||||
done = 1;
|
||||
if (ae.is_valid) {
|
||||
}
|
||||
}
|
||||
|
||||
static const screen_t driver = {sobject_destroy, nullptr, /* finalize */
|
||||
atExit, init, refresh,
|
||||
getMode, getPage, getRows,
|
||||
getCols, isMono, getFg,
|
||||
getBg, getCursor, getCursorShape,
|
||||
setFg, setBg, setCursor,
|
||||
setCursorShape, hideCursor, putChar,
|
||||
putCharAttr, putString, putStringAttr,
|
||||
clear, clearLine, updateLineN,
|
||||
scrollUp, scrollDown, getScrollCounter,
|
||||
s_kbhit, intro, (struct screen_data_t *) nullptr};
|
||||
|
||||
/* public constructor */
|
||||
screen_t *screen_win32_construct(void) { return sobject_construct(&driver, sizeof(*driver.data)); }
|
||||
|
||||
#endif /* (USE_SCREEN_WIN32) */
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
@@ -0,0 +1,105 @@
|
||||
/* screen.h --
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
and/or modify them under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING.
|
||||
If not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef UPX_SCREEN_H__
|
||||
#define UPX_SCREEN_H__ 1
|
||||
|
||||
#if (USE_SCREEN)
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
struct screen_data_t;
|
||||
struct screen_t;
|
||||
typedef struct screen_t screen_t;
|
||||
|
||||
struct screen_t {
|
||||
/* public: */
|
||||
void (*destroy)(screen_t *s);
|
||||
void (*finalize)(screen_t *s);
|
||||
void (*atExit)(void); /* atexit/signal handler */
|
||||
|
||||
int (*init)(screen_t *s, int fd);
|
||||
|
||||
void (*refresh)(screen_t *s);
|
||||
|
||||
int (*getMode)(const screen_t *s);
|
||||
int (*getPage)(const screen_t *s);
|
||||
int (*getRows)(const screen_t *s);
|
||||
int (*getCols)(const screen_t *s);
|
||||
int (*isMono)(const screen_t *s);
|
||||
|
||||
int (*getFg)(const screen_t *s);
|
||||
int (*getBg)(const screen_t *s);
|
||||
void (*getCursor)(const screen_t *s, int *x, int *y);
|
||||
int (*getCursorShape)(const screen_t *s);
|
||||
|
||||
void (*setFg)(screen_t *s, int);
|
||||
void (*setBg)(screen_t *s, int);
|
||||
void (*setCursor)(screen_t *s, int x, int y);
|
||||
void (*setCursorShape)(screen_t *s, int shape);
|
||||
int (*hideCursor)(screen_t *s);
|
||||
|
||||
void (*putChar)(screen_t *s, int c, int x, int y);
|
||||
void (*putCharAttr)(screen_t *s, int c, int attr, int x, int y);
|
||||
void (*putString)(screen_t *s, const char *, int x, int y);
|
||||
void (*putStringAttr)(screen_t *s, const char *, int attr, int x, int y);
|
||||
|
||||
void (*clear)(screen_t *s);
|
||||
void (*clearLine)(screen_t *s, int);
|
||||
void (*updateLineN)(screen_t *s, const void *, int y, int len);
|
||||
|
||||
int (*scrollUp)(screen_t *s, int);
|
||||
int (*scrollDown)(screen_t *s, int);
|
||||
int (*getScrollCounter)(const screen_t *s);
|
||||
|
||||
int (*kbhit)(screen_t *s);
|
||||
|
||||
int (*intro)(screen_t *s, void (*)(screen_t *));
|
||||
|
||||
/* private: */
|
||||
struct screen_data_t *data;
|
||||
};
|
||||
|
||||
screen_t *sobject_construct(const screen_t *c, size_t data_size);
|
||||
void sobject_destroy(screen_t *);
|
||||
screen_t *sobject_get_screen(void);
|
||||
|
||||
screen_t *screen_curses_construct(void);
|
||||
screen_t *screen_djgpp2_construct(void);
|
||||
screen_t *screen_vcsa_construct(void);
|
||||
screen_t *screen_win32_construct(void);
|
||||
|
||||
void screen_show_frames(screen_t *);
|
||||
|
||||
#endif /* USE_SCREEN */
|
||||
|
||||
#endif /* already included */
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
Reference in New Issue
Block a user