📄 ui.cpp
字号:
/* ui.cpp -- This file is part of the UPX executable compressor. Copyright (C) 1996-2007 Markus Franz Xaver Johannes Oberhumer Copyright (C) 1996-2007 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 <mfx@users.sourceforge.net> <ml1050@users.sourceforge.net> */#include "conf.h"#include "file.h"#include "ui.h"#include "screen.h"#include "packer.h"#if 1 && defined(USE_SCREEN)#define UI_USE_SCREEN#endifenum { M_QUIET, // nothing at all '-qqq' M_INFO, // print a one line info after compression '-qq' M_MSG, // print "compressing", then "\r" and M_INFO M_CB_TERM, // 1 line callback using stdout M_CB_SCREEN // 2 line callback using screen};struct UiPacker::State{ int mode; unsigned u_len; unsigned step; unsigned next_update; int pass; int total_passes; // message stuff char msg_buf[1+79+1]; int pos; // last progress bar position unsigned spin_counter; // for spinner int bar_pos; int bar_len; int pass_digits; // number of digits needed to print total_passes#if defined(UI_USE_SCREEN) screen_t *screen; int screen_init_done; int b_cx, b_cy; int s_cx, s_cy; int s_fg, s_bg; int c_fg; int scroll_up; int cursor_shape;#else void *screen;#endif};long UiPacker::total_files = 0;long UiPacker::total_files_done = 0;long UiPacker::total_c_len = 0;long UiPacker::total_u_len = 0;long UiPacker::total_fc_len = 0;long UiPacker::total_fu_len = 0;long UiPacker::update_c_len = 0;long UiPacker::update_u_len = 0;long UiPacker::update_fc_len = 0;long UiPacker::update_fu_len = 0;/*************************************************************************// constants**************************************************************************/static const char header_line1[] = " File size Ratio Format Name\n";static char header_line2[] = " -------------------- ------ ----------- -----------\n";static char progress_filler[] = ".*[]";static void init_global_constants(void){#if 0 && (ACC_OS_DOS16 || ACC_OS_DOS32) // FIXME: should test codepage here static bool done = false; if (done) return; done = true;#if 1 && defined(__DJGPP__) /* check for Windows NT/2000/XP */ if (_get_dos_version(1) == 0x0532) return;#endif char *p; for (p = header_line2; *p; p++) if (*p == '-') *p = '\xc4'; //strcpy(progress_filler, "\x07\xb0[]"); //strcpy(progress_filler, "\x07\xb1[]"); strcpy(progress_filler, "\xf9\xfe[]");#endif}/*************************************************************************//**************************************************************************/static const char *mkline(unsigned long fu_len, unsigned long fc_len, unsigned long u_len, unsigned long c_len, const char *format_name, const char *filename, bool decompress=false){ static char buf[2048]; char r[7+1]; char fn[13+1]; const char *f; // Large ratios can happen because of overlays that are // appended after a program is packed. unsigned ratio = get_ratio(fu_len, fc_len) + 50;#if 1 if (ratio >= 1000*1000) strcpy(r, "overlay");#else if (ratio >= 10*1000*1000) // >= "1000%" strcpy(r, "999.99%");#endif else upx_snprintf(r, sizeof(r), "%3u.%02u%%", ratio / 10000, (ratio % 10000) / 100); if (decompress) f = "%10ld <-%10ld %7s %13s %s"; else f = "%10ld ->%10ld %7s %13s %s"; center_string(fn, sizeof(fn), format_name); assert(strlen(fn) == 13); upx_snprintf(buf, sizeof(buf), f, fu_len, fc_len, r, fn, filename); UNUSED(u_len); UNUSED(c_len); return buf;}/*************************************************************************//**************************************************************************/UiPacker::UiPacker(const Packer *p_) : ui_pass(0), ui_total_passes(0), p(p_), s(NULL){ init_global_constants(); cb.reset(); s = new State; memset(s,0,sizeof(*s)); s->msg_buf[0] = '\r';#if defined(UI_USE_SCREEN) // FIXME - ugly hack s->screen = sobject_get_screen();#endif if (opt->verbose < 0) s->mode = M_QUIET; else if (opt->verbose == 0 || !acc_isatty(STDOUT_FILENO)) s->mode = M_INFO; else if (opt->verbose == 1 || opt->no_progress) s->mode = M_MSG; else if (s->screen == NULL) s->mode = M_CB_TERM; else s->mode = M_CB_SCREEN;}UiPacker::~UiPacker(){ cb.reset(); delete s; s = NULL;}/*************************************************************************// start callback**************************************************************************/void UiPacker::printInfo(int nl){ if (opt->all_methods && s->total_passes > 1) con_fprintf(stdout, "Compressing %s [%s]%s", p->fi->getName(), p->getName(), nl ? "\n" : ""); else { char method_name[32+1]; set_method_name(method_name, sizeof(method_name), p->ph.method, p->ph.level); con_fprintf(stdout, "Compressing %s [%s, %s]%s", p->fi->getName(), p->getName(), method_name, nl ? "\n" : ""); }}void UiPacker::startCallback(unsigned u_len, unsigned step, int pass, int total_passes){ s->u_len = u_len; s->step = step; s->next_update = step; s->pass = pass; s->total_passes = total_passes; //printf("startCallback %d %d\n", s->pass, s->total_passes); s->bar_len = 64; s->pos = -2; s->spin_counter = 0; s->bar_pos = 1; // because of the leading '\r' s->pass_digits = 0; cb.reset(); if (s->pass < 0) // no callback wanted return; if (s->mode <= M_INFO) return; if (s->mode == M_MSG) { if (pass <= 1) { printInfo(0); fflush(stdout); printSetNl(2); } return; }#if (ACC_CC_MSC && (_MSC_VER == 1300)) cb.nprogress = &UiPacker::progress_callback;#else cb.nprogress = progress_callback;#endif cb.user = this; // parameter for static function UiPacker::progress_callback() if (s->mode == M_CB_TERM) { const char *fname = fn_basename(p->fi->getName()); int l = (int) strlen(fname); if (l > 0 && l <= 30) { strcpy(&s->msg_buf[s->bar_pos], fname); s->bar_pos += l; s->msg_buf[s->bar_pos++] = ' '; s->msg_buf[s->bar_pos++] = ' '; s->bar_len -= l + 2; } } // set pass if (total_passes > 1) { int buflen, l; do { s->pass_digits++; total_passes /= 10; } while (total_passes > 0); buflen = sizeof(s->msg_buf) - s->bar_pos; l = upx_snprintf(&s->msg_buf[s->bar_pos], buflen, "%*d/%*d ", s->pass_digits, s->pass, s->pass_digits, s->total_passes); if (l > 0 && s->bar_len - l > 10) { s->bar_len -= l; s->bar_pos += l; } }#if defined(UI_USE_SCREEN) if (s->mode == M_CB_SCREEN) { if (!s->screen_init_done) { s->screen_init_done = 1; if (s->screen->hideCursor) s->cursor_shape = s->screen->hideCursor(s->screen); s->s_fg = s->screen->getFg(s->screen); s->s_bg = s->screen->getBg(s->screen); s->screen->getCursor(s->screen,&s->s_cx,&s->s_cy); s->scroll_up = s->screen->getScrollCounter(s->screen); printInfo(1); s->screen->getCursor(s->screen,&s->b_cx,&s->b_cy); s->scroll_up = s->screen->getScrollCounter(s->screen) - s->scroll_up; } }#endif /* UI_USE_SCREEN */}// may only get called directly after startCallback()void UiPacker::firstCallback(){ if (s->pos == -2) doCallback(0, 0);}// make sure we reach 100% in the progress barvoid UiPacker::finalCallback(unsigned u_len, unsigned c_len){ s->next_update = u_len; doCallback(u_len, c_len);}/*************************************************************************// end callback**************************************************************************/void UiPacker::endCallback(){ bool done = (s->total_passes <= 0 || s->pass >= s->total_passes); endCallback(done);}void UiPacker::endCallback(bool done){ if (s->pass < 0) // no callback wanted return; if (s->mode == M_CB_TERM) { if (done) printClearLine(stdout); else printSetNl(2); } // restore screen#if defined(UI_USE_SCREEN) if (s->mode == M_CB_SCREEN) { if (done) { int cx, cy, sy; assert(s->screen_init_done); s->screen_init_done = 0; assert(s->s_cx == 0 && s->b_cx == 0); s->screen->getCursor(s->screen, &cx, &cy); sy = UPX_MAX(0, s->s_cy - s->scroll_up); while (cy >= sy) s->screen->clearLine(s->screen, cy--); s->screen->setCursor(s->screen, s->s_cx, sy); s->screen->setFg(s->screen,s->s_fg); s->screen->setBg(s->screen,s->s_bg); if (s->cursor_shape > 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -