mirror of
https://github.com/upx/upx
synced 2025-09-28 19:06:07 +08:00
287 lines
6.7 KiB
C++
287 lines
6.7 KiB
C++
/* c_screen.cpp -- screen driver console output
|
|
|
|
This file is part of the UPX executable compressor.
|
|
|
|
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
|
Copyright (C) 1996-2000 Laszlo Molnar
|
|
|
|
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@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
|
*/
|
|
|
|
|
|
#include "conf.h"
|
|
|
|
#if defined(USE_SCREEN)
|
|
|
|
#include "screen.h"
|
|
|
|
#define mask_fg 0x0f
|
|
#define mask_bg 0xf0
|
|
|
|
|
|
/*************************************************************************
|
|
//
|
|
**************************************************************************/
|
|
|
|
static screen_t *do_construct(screen_t *s, int fd)
|
|
{
|
|
if (!s)
|
|
return NULL;
|
|
if (s->init(s,fd) != 0)
|
|
{
|
|
s->destroy(s);
|
|
return NULL;
|
|
}
|
|
return s;
|
|
}
|
|
|
|
|
|
static screen_t *screen = NULL;
|
|
|
|
static void do_destroy(void)
|
|
{
|
|
if (screen)
|
|
{
|
|
screen->destroy(screen);
|
|
screen = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
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 = CON_INIT;
|
|
|
|
UNUSED(now);
|
|
assert(screen == NULL);
|
|
atexit(do_destroy);
|
|
#if defined(__DJGPP__)
|
|
if (!screen)
|
|
screen = do_construct(screen_djgpp2_construct(),fd);
|
|
#endif
|
|
#if defined(__MFX_WIN32)
|
|
if (!screen)
|
|
screen = do_construct(screen_win32_construct(),fd);
|
|
#endif
|
|
#if defined(USE_SCREEN_VCSA)
|
|
if (!screen)
|
|
screen = do_construct(screen_vcsa_construct(),fd);
|
|
#endif
|
|
#if defined(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;
|
|
if (screen->getCols(screen) < 80 || screen->getCols(screen) > 256)
|
|
return CON_INIT;
|
|
if (screen->getRows(screen) < 24)
|
|
return CON_INIT;
|
|
if (cur_fg == (cur_bg >> 4))
|
|
return CON_INIT;
|
|
if (cur_bg != BG_BLACK)
|
|
if (!screen->isMono(screen))
|
|
{
|
|
/* return CON_ANSI_MONO; */ /* we could emulate ANSI mono */
|
|
return CON_INIT;
|
|
}
|
|
|
|
if (o == CON_SCREEN)
|
|
n = CON_SCREEN;
|
|
if (o == CON_INIT) /* use by default */
|
|
n = CON_SCREEN;
|
|
if (o == CON_ANSI_COLOR) /* can emulate ANSI color */
|
|
n = CON_ANSI_COLOR;
|
|
if (o == CON_ANSI_MONO) /* can emulate ANSI mono */
|
|
n = CON_ANSI_MONO;
|
|
|
|
if (screen->atExit)
|
|
atexit(screen->atExit);
|
|
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 c_cx, c_cy;
|
|
char p[256+1];
|
|
int pi = 0, px = -1, py = -1;
|
|
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
|
|
// scrollScreen() under Win32 is *extremely* slow.
|
|
UNUSED(f);
|
|
screen->getCursor(screen,&cx,&cy);
|
|
c_cx = cx; c_cy = cy;
|
|
for (pass = 0; pass < 2; pass++)
|
|
{
|
|
const char *s = ss;
|
|
int scroll_y = 0;
|
|
while (*s)
|
|
{
|
|
for ( ; *s; s++)
|
|
{
|
|
if (*s == '\n')
|
|
{
|
|
c_cy++;
|
|
c_cx = 0;
|
|
}
|
|
else if (*s == '\r')
|
|
{
|
|
c_cx = 0;
|
|
#if 1
|
|
if (pass > 0 && c_cy < sy)
|
|
screen->clearLine(screen,c_cy);
|
|
#endif
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
if (c_cx >= sx)
|
|
{
|
|
c_cy++;
|
|
c_cx = 0;
|
|
}
|
|
if (pass > 0 && pi > 0 && py != c_cy)
|
|
{
|
|
screen->putString(screen,p,px,py);
|
|
pi = 0;
|
|
}
|
|
if (c_cy >= sy)
|
|
{
|
|
int l = c_cy - sy + 1;
|
|
if (pass > 0)
|
|
c_cy -= screen->scrollUp(screen,l);
|
|
else
|
|
{
|
|
scroll_y += l;
|
|
c_cy -= l;
|
|
}
|
|
if (c_cy < 0)
|
|
c_cy = 0;
|
|
c_cx = 0;
|
|
}
|
|
if (*s)
|
|
{
|
|
if (pass > 0)
|
|
{
|
|
if (pi == 0)
|
|
px = c_cx, py = c_cy;
|
|
p[pi++] = *s;
|
|
p[pi] = 0;
|
|
}
|
|
c_cx++;
|
|
s++;
|
|
}
|
|
}
|
|
if (pass == 0)
|
|
{
|
|
c_cx = cx;
|
|
if (scroll_y > 0)
|
|
{
|
|
c_cy -= screen->scrollUp(screen,scroll_y);
|
|
if (c_cy < 0)
|
|
c_cy = 0;
|
|
}
|
|
else
|
|
c_cy = cy;
|
|
}
|
|
}
|
|
if (pi > 0)
|
|
screen->putString(screen,p,px,py);
|
|
screen->setCursor(screen,c_cx,c_cy);
|
|
screen->refresh(screen);
|
|
}
|
|
|
|
|
|
static upx_bool intro(FILE *f)
|
|
{
|
|
UNUSED(f);
|
|
#if defined(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 */
|
|
|
|
|
|
/*
|
|
vi:ts=4:et
|
|
*/
|
|
|