⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gui.c

📁 * A ncurses user interface. * Network statistics to view the amount of packets and data in many
💻 C
字号:
/**  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 Library 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.** Author:*	NAME:	James Stevenson*	EMAIL:	mistral@stev.org*	WWW:	http://www.stev.org*/#include <stdio.h>#include <stdlib.h>#include <ctype.h>#include <ncurses.h>#include <sys/time.h>#include "list.h"#include "gui.h"/** *	gui_print - Print to a window *	@win:	Window to print on *	@fmt:	Same as printf * *	This is the same as the printf's in libc */void gui_print(WINDOW *win, char *fmt, ...) {	va_list ap;	va_start(ap, fmt);	vwprintw(win, fmt, ap);	va_end(ap);}/** *	gui_scroll - A generic scroll fucntion for lists bigger that a screen *	@usec:	The number of usecs to wait for input *	@sec:	The number of seconds to wait for input *	@height: The maximum value the offset can be set to *	@offset: A pointer to an interger that will be modified depending *			on what key was pressed * *	makes it easyier to have a list that the user can scroll up and *	down it will return the key if it did not understand *	the key was pressed */int gui_scroll(int usec, int sec, int height, int *offset) {	int key;	if (gui_wait(usec, sec)) {		key = getch();		switch(key) {			case ERR:				return ERR;				break;			case KEY_UP: /* move up the ist so offset-- */				if (*offset > 0)					--*offset;				return 0;				break;			case KEY_DOWN: /* go forward */				if (*offset < height)					++*offset;				return 0;				break;			case KEY_PPAGE: /* page up */				if (*offset > GUI_SCROLL_PAGE) {					*offset -= GUI_SCROLL_PAGE;				} else {					*offset = 0;				}				return 0;				break;			case KEY_NPAGE: /* go down a page */				if (*offset < height - GUI_SCROLL_PAGE) {					*offset += GUI_SCROLL_PAGE;				} else {					*offset = height - 1;				}				return 0;				break;			default: /* we did not do anything so just ret the keypress */				return key;				break;		} /* end of switch(key) */	} /* if (gui_utils_wait) */	/* when we get this far no keypress was done so an error occured */	return -1;}/** *	gui_menu - Draw a menu on the screen *	@p:	A valid pointer to a gui_t struct *	@menu:	A gui_menu_t type *	@y:	The y position *	@x:	The x position *	@height: The height of the menu *	@width:	The width of the menu * *	The gui_menu_y should contain an array of the following *	char *text;		text to display in the window *	char *des;		text to display in the footer *	int type; 		the type of entry *	void (*func) (struct list_t *windows, int x, int y) fucntion pointer *	The type should be set to one of GUI_MENU_ and the last item in the array must *	be GUI_MENU_END */int gui_menu(struct gui_t *p, struct gui_menu_t menu[], int y, int x, int height, int width) {	WINDOW *tmp = NULL, *in = NULL;	/* and inner and outer window */	char *old_foot;	/* backup of the footer */	int i, sel = 0, max;	/* i for loops sel for seleted item max for max items */	int ret, old;	tmp = newwin(height, width, y, x);	if (!tmp)		return -1;	in = derwin(tmp, height - 2, width - 2, 1, 1);	if (!in) { /* we failed free some stuff off */		delwin(tmp);		return -2;	}		if (p->color) {		wbkgd(tmp, COLOR_PAIR(COL_BACK));		wbkgd(in, COLOR_PAIR(COL_BACK));	}	old_foot = p->footer;	gui_footer(p, "Use Up/Down Arrows to select Left to backout Right to exec");	if (list_add(p->windows, tmp) < 0) {		delwin(in);		delwin(tmp);		return -1;	}	if (list_add(p->windows, in) < 0) {		delwin(in);		delwin(tmp);		return -1;	}	gui_redraw(p);	werase(tmp);	werase(in);	box(tmp, 0, 0);		i = 0;	while(menu[i].type != GUI_MENU_END) {		gui_menu_line(in, i, &menu[i]);		i++;	}	max = i;	old = sel;restart:	/* jump to here to re read a char */	/* refix the seleted item */	gui_menu_line(in, old, &menu[old]);	wattron(in, COLOR_PAIR(COL_SELECT) | A_BOLD);	gui_menu_line(in, sel, &menu[sel]);	wattroff(in, COLOR_PAIR(COL_SELECT) | A_BOLD);	wrefresh(in);	wrefresh(tmp);	if (gui_wait(0, 5) >= 0) {		ret = getch();		switch(ret) {			case ERR:				gui_footer(p, menu[sel].des);				goto restart;				break;			case KEY_UP:				if (sel > 0) {					old = sel;					sel--;				}				if (menu[sel].type == GUI_MENU_SEP && sel > 0)					sel--;				gui_footer(p, menu[sel].des);				goto restart;				break;			case KEY_DOWN:				if (sel < max - 1) {					old = sel;					sel++;				}				if (menu[sel].type == GUI_MENU_SEP && sel < max - 1)					sel++;				gui_footer(p, menu[sel].des);				goto restart;				break;			case KEY_RIGHT:				if (!menu[sel].func) {					gui_footer(p, "Function not avilable");					goto restart;				}				menu[sel].func(p, y + sel, x + width);				gui_redraw(p);				goto restart;				break;			case KEY_LEFT:				ret = 0;				goto out;				break;			default:	/* an invalid key press */				goto restart;				break;		} /* end of switch(ret) */	} else {		ret = -2;		goto out;	}	/* we should never get here */	ret = -5;out: /* set ret and jump to here */	list_del(p->windows, list_len(p->windows) - 1);	list_del(p->windows, list_len(p->windows) - 1);		if (in) {		werase(in);		wrefresh(in);		delwin(in);	}	if (tmp) {		werase(tmp);		wrefresh(tmp);		delwin(tmp);	}	gui_footer(p, old_foot);	gui_redraw(p);	return ret;}/** *	gui_menu_line - Draw a line in a menu *	@in:	A Valid window to draw onto *	@y:		How far down the window *	@p:		A pointer to a valid gui_menu_t type * *	only called from gui_menu * */void gui_menu_line(WINDOW *in, int y, struct gui_menu_t *p) {	switch(p->type) {		case GUI_MENU_SEP:			mvwhline(in, y, 0, 0, in->_maxx + 1);			break;		case GUI_MENU_SUB:			mvwprintw(in, y, 0, "%s", p->text);			mvwaddch(in, y, in->_maxx, ACS_RARROW);			break;		case GUI_MENU_FUNC:			mvwprintw(in, y, 0, "%s", p->text);			break;	} /* end switch */	return;}/** *	gui_msg - draw a message box on the screen *	@p:	A valid pointer to struct gui_t *	@msg:	A text string of a message format it with newlines *			and make sure the box around it is big enough to  *			hold the contents *	@opts:	This may be either GUI_MSG_ANY or a combination of *			GUI_MSG_OK | GUI_MSG_IGNORE | GUI_MSG_CANCEL *	@y:	The y position of the box *	@x:	The x position of the box *	@height: The height of the box *	@width:	The width of the box * *	This should be used to draw a box on the screen with a message in it *	the return value will be < 0 if an error occurs or *	GUI_MSG_ANY if it is used *	or one of the other GUI_MSG_* defines but only one of the ones passed *	in the parameter opts */int gui_msg(struct gui_t *p, char *msg, int opts, int y, int x, int height, int width) {	WINDOW *tmp;	/* the new window */	WINDOW *in;		/* the window we draw in */	char *backup, *new_footer, buff[1024];	int c, ret;	/* char to read */		tmp = newwin(height, width, y, x);	if (!tmp)		return -1;	in = derwin(tmp, height - 2, width - 2, 1, 1);	if (!in) { /* we failed free some stuff off */		delwin(tmp);		return -2;	}	if (p->color) {		wbkgd(tmp, COLOR_PAIR(COL_BACK));		wbkgd(in, COLOR_PAIR(COL_BACK));	}	gui_redraw(p);	werase(tmp);	werase(in);	box(tmp, 0, 0);		mvwprintw(in, 0, 0, "%s", msg);		if (opts == GUI_MSG_ANY) {			new_footer = "Press *ANY* key to continue";	} else {		new_footer = &buff[0];		if (opts & GUI_MSG_OK)			new_footer += sprintf(new_footer, "Ok ");		if (opts & GUI_MSG_CANCEL)			new_footer += sprintf(new_footer, "Cancel ");		if (opts & GUI_MSG_IGNORE)			new_footer += sprintf(new_footer, "Ignore ");		new_footer = &buff[0];	}	backup = p->footer;	gui_footer(p, new_footer);	wrefresh(tmp);	wrefresh(tmp);	/* Ok here is where it gets ugly */restart:	ret = gui_wait(0, 10);	if (ret == 0)		goto restart;	if (ret) {		c = getch();		if (c == ERR)			goto restart;		if (opts & GUI_MSG_OK && tolower(c) == 'o') {			ret = GUI_MSG_OK;			goto out;		}		if (opts & GUI_MSG_IGNORE && tolower(c) == 'i') {			ret = GUI_MSG_IGNORE;			goto out;		}		if (opts & GUI_MSG_CANCEL && tolower(c) == 'c') {			ret = GUI_MSG_CANCEL;			goto out;		}		if (opts == GUI_MSG_ANY) {			ret = GUI_MSG_ANY;			goto out;		}		/* if we get to here the correct button was not pressed */		goto restart;	} else {		return -3;	/* this is an error */	}out:	gui_footer(p, backup);	werase(tmp);	wrefresh(tmp);	gui_redraw(p);	delwin(tmp);	return 0;}/** *	gui_wait - wait for input on stdin *	@usecs:	the number of usecs to wait *	@seconds: the number of seconds to wait * *	This will return 1 if there is input *	0 if a timeout occured *	< 0 if an error occured **/int gui_wait(int usecs, int seconds) {	fd_set fds;	int ret;	struct timeval tv;	FD_ZERO(&fds);	FD_SET(fileno(stdin), &fds);	tv.tv_sec = seconds;	tv.tv_usec = usecs;	ret = select(fileno(stdin) + 1, &fds, NULL, NULL, &tv);	if (ret) {		if (FD_ISSET(fileno(stdin), &fds))			return 1;	} else {		if (ret == 0) /* this is not am error just a timeout */			return 0;		return -1;	}	return -1; /* if we get this far it means we have failed */}/** *	gui_footer - Change the gui footer *	@p:	A valid pointer to struct gui_t *	@footer: New text for the footer to hold * *	This will change the contents of the footer on the window *	it will not save the text that is already there */int gui_footer(struct gui_t *p, char *footer) {	p->footer = footer;	werase(p->fwin);	mvwprintw(p->fwin, 0, 0, "%s", p->footer);	wrefresh(p->fwin);	return 0;}/** *	gui_redraw - redraw a list of windows *	@p:	a valid pointer to a struct of gui_t * *	This is used to redraw all the windows *	in the gui_t type */int gui_redraw(struct gui_t *p) {	int i, len;	WINDOW *win;	len = list_len(p->windows);	/* twin is a special case */	redrawwin(p->twin);	wnoutrefresh(p->twin);	for(i=0;i<len;i++) {		win = list_get(p->windows, i);		redrawwin(win);		wnoutrefresh(win);	}	doupdate();     	return 0;}/** *	gui_setup - setup a new screen * *	Returns a pointer to a struct *	of type gui_t or NULL on failure */struct gui_t *gui_setup() {	struct gui_t *tmp;		tmp = malloc(sizeof(struct gui_t));	if (!tmp)		return NULL; /* just jump out there is nothing else alloced */	tmp->windows = list_init();	if (!tmp->windows)		goto cleanup_malloc;	/* get a new window */	tmp->twin = initscr();	if (!tmp->twin)		goto cleanup_list;	/* lets see if we want colors */	if (has_colors()) {		if (start_color() == ERR) {			tmp->color = 0;		} else {			tmp->color = 1;			init_pair(COL_BACK, COLOR_WHITE, COLOR_BLUE);			init_pair(COL_FOOTER, COLOR_YELLOW, COLOR_CYAN);			init_pair(COL_SELECT, COLOR_CYAN, COLOR_BLUE);		}	} else {		tmp->color = 0;	}	/* lets setup our footer window */	tmp->fwin = newwin(1, tmp->twin->_maxx - 2, tmp->twin->_maxy, 1);	if (!tmp->fwin)		goto cleanup_twin;	if (tmp->color)		wbkgd(tmp->fwin, COLOR_PAIR(COL_FOOTER));	if (list_add(tmp->windows, tmp->fwin) < 0)		goto cleanup_fwin;	gui_footer(tmp, "");	/* set up some more defaults on the main window */	if (tmp->color)		wbkgd(tmp->twin, COLOR_PAIR(COL_BACK));	/* set up some nice defaults */	keypad(tmp->twin, TRUE);	noecho();	cbreak();	nodelay(tmp->twin, TRUE);	/* clear the window */	werase(tmp->twin);	box(tmp->twin, 0, 0);	gui_redraw(tmp);	return tmp;cleanup_fwin:	delwin(tmp->fwin);cleanup_twin:	endwin();cleanup_list:	list_free(tmp->windows);cleanup_malloc:	free(tmp);	/* free off gui */	return NULL;}/** *	gui_end	- cleanup the screen *	@p:	A valid pointer to a struct gui_t * *	Cleanup the struct gui_t *	the pointer you pass to this *	should not be used again *	return < 0 if an error occurs */int gui_end(struct gui_t *p) {		while(list_len(p->windows)) {		delwin(list_get(p->windows, list_len(p->windows) - 1));		list_del(p->windows, list_len(p->windows) - 1);	}	list_free(p->windows);		endwin();	/* kill off the top window */	free(p);	/* free off any memory we are using */	return 0;}/* EOF */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -