# include <stdio.h>
# include <curses.h>
# include <signal.h>
# include <sys/time.h>
# define SMON_ITV 1 /* 屏幕监控时间间隔 */
# define L 256 /* 每行最大长度 */
static int BL, /* (表头除外)屏幕显示起始行 */
N, /* (表头除外)屏幕显示行数 */
Pages = 0, /* 显示信息共多少屏 */
scrs = 0, /* 当前屏幕序号,从 0开始 */
t_esc = 0; /* <Esc>按键次数 */
/******
空函数
******/
static void z_f_empty(int sig) {}
/**********
初始化屏幕
**********/
void z_initscr(void)
{
initscr();
noecho();
curs_set(0);
keypad(stdscr, TRUE);
}
/************
结束屏幕处理
************/
void z_endwin(void)
{
addstr(" ");
refresh();
clear();
refresh();
endwin();
}
/******************
结束屏幕处理,退出
******************/
static void z_win_exit(int sig)
{
z_endwin();
exit(0);
}
/**************************
文件是否还有未显示的数据行
**************************/
static int z_more_lines(FILE *pfp, long *n)
{
char buf[L + 1];
int i, rows;
i = 0;
rows = scrs * N;
rewind(pfp);
while( ! feof(pfp) ) {
memset(buf, 0, L + 1);
if( fgets(buf, L, pfp) == NULL ) break;
if( (++i) > rows ) return(1);
(*n) += strlen(buf);
}
return(0);
}
/************
显示一屏内容
************/
static int z_putstr(FILE *pfp)
{
int i, y, x;
char buf[L + 1], tms[20], pg[25];
x = 0;
y = BL;
z_get_dt(tms, 19, "l", 0);
sprintf(pg, "P: %d/%d", scrs + 1, Pages);
move(y, 0);
clrtobot();
standout();
mvaddstr(lines - 1, 0, "连续两次<Esc>键退出,↓↑翻屏");
standend();
clrtoeol();
mvprintw(lines - 1, 40, "%s %21s", tms + 5, pg);
for(i = 0; i < N; i++ ) {
memset(buf, 0, L + 1);
if( fgets(buf, L, pfp) == NULL ) break;
mvaddstr(y, x, buf);
y++;
}
refresh();
return(0);
}
/****************************
文件显示(需要事先初始化屏幕)
****************************/
int z_disscr(char *filename, char *phead)
{
FILE *fp;
char *p, v[L + 1];
long offset;
int f_show, ch, i, n, b, flines;
ch = 0;
if( (fp = fopen(filename, "r")) == NULL ) {
standout();
mvprintw(1, 0, "打开文件 %s 错误! 请检查目录设置及文件权限", filename);
standend();
refresh();
sleep(3);
return(-1);
}
/* 显示表头 */
i = 0;
if( phead != NULL && *phead ) {
p = phead;
do {
n = 0;
memset(v, 0, L + 1);
b = z_get_fieldv(&p, v, &n, L, "\n");
mvaddstr(i, 0, v);
if( (++i) > (lines - 3) ) break; /* 为正文与提示行预留版面 */
} while ( b );
}
BL = i;
N = lines - 1 - i;
/* 统计文件行数 */
if( (flines = z_filelines(filename)) < 0 ) return(-1);
/* 计算屏幕 */
Pages = flines / N;
if( flines % N ) Pages ++;
offset = 0;
z_more_lines(fp, &offset);
fseek(fp, offset, 0);
z_putstr(fp);
while( 1 ) {
mvprintw(lines - 1, 30, "%c", '.');
flushinp();
ch = getch();
if( ch == 27 ) { /*两次<Esc>键退出*/
if( t_esc == 1 ) {
fclose(fp);
return(-1);
}
else t_esc = 1;
}
else t_esc = 0;
f_show = 1;
if( ch != -1 ) offset = 0;
switch (ch) {
case 66:
case 69:
case 10:
case 32:
case KEY_DOWN:
case KEY_RIGHT: /*下翻一屏*/
scrs ++;
if( z_more_lines(fp, &offset) == 0 ) {
scrs --;
f_show = 0;
}
break;
case KEY_UP:
case KEY_LEFT: /*上翻一屏*/
case 67:
case 68:
if( scrs ) {
scrs --;
if( z_more_lines(fp, &offset) == 0 ) f_show = 0;
}
else f_show = 0;
break;
case -1: /*被定时信号中断*/
fclose(fp);
return(0);
default:
f_show = 0;
}
if( f_show ) {
fseek(fp, offset, 0);
z_putstr(fp);
}
}
fclose(fp);
return(0);
}
/************
设定信号处理
************/
static void z_sig_refresh(void)
{
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_handler = SIG_IGN;
sigaction(SIGINT, &sa, NULL);
sigaction(SIGQUIT, &sa, NULL);
sa.sa_handler = z_win_exit;
sigaction(SIGTERM, &sa, NULL);
sa.sa_handler = z_f_empty;
sigaction(SIGALRM, &sa, NULL);
}
/************
设定刷新时间
************/
void z_set_refresh(int sec, int usec)
{
struct itimerval rttimer;
z_sig_refresh();
/* 设定定时间隔 */
rttimer.it_value.tv_sec = sec;
rttimer.it_value.tv_usec = usec;
rttimer.it_interval.tv_sec = sec;
rttimer.it_interval.tv_usec = usec;
setitimer(ITIMER_REAL, &rttimer, NULL);
}