📄 curses.c
字号:
/* The file contins routines for managing curses Copyright (C) 2000 Kalum Somaratna This program is free software; you can redistribute it and/or modify it 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; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#ifdef HAVE_CONFIG_H# include <config.h>#endif /* * HAVE_CONFIG_H */#include <sys/types.h>#include <sys/time.h>#include <unistd.h>#include <stdio.h>#include <string.h>#include <pthread.h>#ifdef HAVE_NCURSES_H#include <ncurses.h>#else#include <curses.h>#endif /* * HAVE_CURSES */#include <ctype.h>#include <assert.h>#include <errno.h>#include "interface.h"#include "misc.h"#include "runtime.h"#include "logfile.h"#include "ftpsearch.h"#include "debug.h"/* This is used to convert the connection.status enums to a user * friendly text message *//* the enums are defined in connection.h and are as belor *typedef enum { * IDLE = 0, * CONNECTING, * LOGGININ, * DOWNLOADING, * COMPLETED, * LOGINFAIL, * CONREJECTED, * REMOTEFATAL, * LOCALFATAL *} dl_status; * * And here are the texts for the above enums.*/const char *dl_status_txt[] = { "Idle", "Connecting", "Logging in", "Downloading", "Completed",/* I have decided to change the login failed message * to something else like "login rejected" because people * might get alarmed and abort the download rather than * letting prozilla handle it */ "Login Denied", "Connect Refused", "Remote Fatal", "Local Fatal", "Timed Out", "Max attempts reached",};#define CTRL(x) ((x) & 0x1F)void curses_exit_resume(connection_data * connections, int num_connections);void curses_exit_no_resume(connection_data * connections, int num_connections);void curses_draw_display(const connection_data * connections, int num_connections, ftp_mirror * mirrors, int num_servers);void curses_display_est_time(int row, int col, off_t bytes_left, float current_speed);static int top_con = 0; /* * the connection that is on the top of the display */#define MAX_CON_VIEWS 4/* * needed for the message(...) function */pthread_mutex_t curses_msg_mutex = PTHREAD_MUTEX_INITIALIZER;char message_buffer[MAX_MSG_SIZE];/* Added for current_dl_speed */time_t time_stamp;off_t bytes_got_last_time;int start = 1;float current_dl_speed = 0.0;voidcurses_draw_display(const connection_data * connections, int num_connections, ftp_mirror * mirrors, int num_servers){ int i, j; off_t total_bytes_got = 0; off_t file_size; /* * To get a accurate estimate of the D/L time when resuming, * * we need to know the number of bytes that have been already * * been stored to the disk in the earlier D/L session. * * We will store it in variable below */ off_t prev_total_bytes_got = 0; struct timeval cur_time; float total_speed = 0.0; file_size = connections[0].main_file_size; attrset(COLOR_PAIR(HIGHLIGHT_PAIR) | A_BOLD); mvaddstr(0, 0, "Connection Status Received"); attrset(COLOR_PAIR(NULL_PAIR)); for (i = 0; i < MAX_CON_VIEWS; i++) { move(i + 1, 0); clrtoeol(); if (i + top_con < num_connections) { if (connections[top_con + i].main_file_size != -1) { float bytes_pp = (float) (connections[top_con + i].local_startpos + connections[top_con + i].remote_endpos - connections[top_con + i].remote_startpos) / 1024; mvprintw(i + 1, 0, " %2d %15s %10.1fK of %5.1fK", top_con + i + 1, dl_status_txt[connections[top_con + i].status], (float) (connections[top_con + i]. remote_bytes_received + connections[top_con + i].orig_local_startpos) / 1024, (bytes_pp < 0) ? 0 : bytes_pp); } else { mvprintw(i + 1, 0, " %d %15s %15.1fK", top_con + i + 1, dl_status_txt[connections[top_con + i].status], (float) (connections[top_con + i]. remote_bytes_received + connections[top_con + i].orig_local_startpos) / 1024); } } } for (j = 0; j < num_connections; j++) { /* * If even 1 connection has started DLing then set the start time */ if ((rt.dl_start_time.tv_sec == 0 && rt.dl_start_time.tv_usec == 0) && connections[j].status == DOWNLOADING) gettimeofday(&rt.dl_start_time, NULL); total_bytes_got += connections[j].remote_bytes_received; prev_total_bytes_got += connections[j].orig_local_startpos; }/* debug_prz("prev_total= %Ld", (long long) prev_total_bytes_got); */ gettimeofday(&cur_time, NULL); total_speed = (total_bytes_got) / ((cur_time.tv_sec - rt.dl_start_time.tv_sec) > 0 ? (cur_time.tv_sec - rt.dl_start_time.tv_sec) : 1); /* FIXME: Initialize this somewhere else, e.g. main.c or init.c * I don't want to change more than one file for now */ /* this is only fulfilled the very first time * after starting prozilla */ if (start == 1) { time_stamp = time(NULL); bytes_got_last_time = total_bytes_got; start = 0; } /* FIXME_END */ if (time_stamp + 1 == time(NULL)) { current_dl_speed = total_bytes_got - bytes_got_last_time; time_stamp = time(NULL); bytes_got_last_time = total_bytes_got; } /* * message("%ld bytes received\r",total_bytes_got); */ attrset(COLOR_PAIR(HIGHLIGHT_PAIR) | A_BOLD); mvprintw(6, 0, "%s", connections[0].u.url); attrset(COLOR_PAIR(HIGHLIGHT_PAIR)); if (file_size == -1) { mvprintw(8, 0, "File Size = UNKNOWN"); mvprintw(9, 0, "Total bytes received = %.1fK", (float) (total_bytes_got + prev_total_bytes_got) / 1024); } else { mvprintw(8, 0, "File Size = %LdK",(long long) file_size / 1024); mvprintw(9, 0, "Total bytes received = %.1fK (%.2f%%)", (float) (total_bytes_got + prev_total_bytes_got) / 1024, (file_size > 0) ? (float) (total_bytes_got + prev_total_bytes_got) * 100 / (float) file_size : 0); } /* * Added current speed display */ move(10, 0); clrtoeol(); printw("Current speed = %1.2fKb/s, Average D/L speed = %1.2fKb/s", current_dl_speed / 1024, total_speed / 1024); /* * Added estimated time display */ curses_display_est_time(11, 0, file_size - (total_bytes_got + prev_total_bytes_got), total_speed); attrset(COLOR_PAIR(NULL_PAIR)); /* * Does the server support resume */ if (connections[0].u.resume_support) { attrset(COLOR_PAIR(HIGHLIGHT_PAIR) | A_BOLD); mvprintw(13, 0, "Resume Supported"); attrset(COLOR_PAIR(NULL_PAIR)); if(num_connections>MAX_CON_VIEWS) { mvprintw(14, 0, "Up and Down Arrow keys to scroll display"); } mvprintw(15, 0, "Ctrl-R to exit and resume later"); mvprintw(16, 0, "Ctrl-X to exit without resuming later"); mvprintw(17, 0, "Ctrl-L to repaint the screen"); if (rt.ftp_search == TRUE && num_servers > 1) { int cur_server = get_mirror_list_pos(connections[0].u.url, mirrors, num_servers); move(18, 0); clrtoeol(); if (cur_server > 0 && cur_server < num_servers - 1) mvprintw(18, 0, "Ctrl-N to try the next server or CTRL-P for previous one"); else if (cur_server == 0) mvprintw(18, 0, "Ctrl-N to try the next server"); else if (cur_server == num_servers - 1) mvprintw(18, 0, "CTRL-P for previous one"); } } else { attrset(COLOR_PAIR(WARN_PAIR) | A_BOLD); mvprintw(13, 0, "Resume NOT Supported"); attrset(COLOR_PAIR(NULL_PAIR)); if(num_connections>MAX_CON_VIEWS) { mvprintw(15, 0, "Up and Down Arrow keys to scroll display"); } mvprintw(16, 0, "Ctrl-X to exit without resuming later"); mvprintw(17, 0, "Ctrl-L to repaint the screen"); if (rt.ftp_search == TRUE && num_servers > 1) { int cur_server = get_mirror_list_pos(connections[0].u.url, mirrors, num_servers); move(18, 0); clrtoeol(); if (cur_server > 0 && cur_server < num_servers - 1) mvprintw(18, 0, "Ctrl-N to try the next server or CTRL-P for previous one"); else if (cur_server == 0) mvprintw(18, 0, "Ctrl-N to try the next server"); else if (cur_server == num_servers - 1) mvprintw(18, 0, "CTRL-P for previous one");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -