xref: /dflybsd-src/usr.sbin/installer/dfuife_curses/curses_util.c (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
186d7f5d3SJohn Marino /*
286d7f5d3SJohn Marino  * Copyright (c)2004 Cat's Eye Technologies.  All rights reserved.
386d7f5d3SJohn Marino  *
486d7f5d3SJohn Marino  * Redistribution and use in source and binary forms, with or without
586d7f5d3SJohn Marino  * modification, are permitted provided that the following conditions
686d7f5d3SJohn Marino  * are met:
786d7f5d3SJohn Marino  *
886d7f5d3SJohn Marino  *   Redistributions of source code must retain the above copyright
986d7f5d3SJohn Marino  *   notice, this list of conditions and the following disclaimer.
1086d7f5d3SJohn Marino  *
1186d7f5d3SJohn Marino  *   Redistributions in binary form must reproduce the above copyright
1286d7f5d3SJohn Marino  *   notice, this list of conditions and the following disclaimer in
1386d7f5d3SJohn Marino  *   the documentation and/or other materials provided with the
1486d7f5d3SJohn Marino  *   distribution.
1586d7f5d3SJohn Marino  *
1686d7f5d3SJohn Marino  *   Neither the name of Cat's Eye Technologies nor the names of its
1786d7f5d3SJohn Marino  *   contributors may be used to endorse or promote products derived
1886d7f5d3SJohn Marino  *   from this software without specific prior written permission.
1986d7f5d3SJohn Marino  *
2086d7f5d3SJohn Marino  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2186d7f5d3SJohn Marino  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2286d7f5d3SJohn Marino  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
2386d7f5d3SJohn Marino  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
2486d7f5d3SJohn Marino  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
2586d7f5d3SJohn Marino  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
2686d7f5d3SJohn Marino  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2786d7f5d3SJohn Marino  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2886d7f5d3SJohn Marino  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
2986d7f5d3SJohn Marino  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3086d7f5d3SJohn Marino  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
3186d7f5d3SJohn Marino  * OF THE POSSIBILITY OF SUCH DAMAGE.
3286d7f5d3SJohn Marino  */
3386d7f5d3SJohn Marino 
3486d7f5d3SJohn Marino /*
3586d7f5d3SJohn Marino  * curses_util.c
3686d7f5d3SJohn Marino  * $Id: curses_util.c,v 1.7 2005/02/08 07:49:03 cpressey Exp $
3786d7f5d3SJohn Marino  */
3886d7f5d3SJohn Marino 
3986d7f5d3SJohn Marino #include <ctype.h>
4086d7f5d3SJohn Marino #include <ncurses.h>
4186d7f5d3SJohn Marino #include <panel.h>
4286d7f5d3SJohn Marino #include <stdio.h>
4386d7f5d3SJohn Marino #include <stdlib.h>
4486d7f5d3SJohn Marino #include <string.h>
4586d7f5d3SJohn Marino 
4686d7f5d3SJohn Marino #include "curses_util.h"
4786d7f5d3SJohn Marino 
4886d7f5d3SJohn Marino unsigned int ymax, xmax;
4986d7f5d3SJohn Marino int monochrome = 1;
5086d7f5d3SJohn Marino int allocated_colors = 0;
5186d7f5d3SJohn Marino 
5286d7f5d3SJohn Marino struct curses_attr {
5386d7f5d3SJohn Marino 	int pair_no;
5486d7f5d3SJohn Marino 	int bold;
5586d7f5d3SJohn Marino };
5686d7f5d3SJohn Marino 
5786d7f5d3SJohn Marino struct curses_attr colors_tab[CURSES_COLORS_MAX];
5886d7f5d3SJohn Marino 
5986d7f5d3SJohn Marino int colors[8] = {
6086d7f5d3SJohn Marino 	COLOR_BLACK,
6186d7f5d3SJohn Marino 	COLOR_RED,
6286d7f5d3SJohn Marino 	COLOR_GREEN,
6386d7f5d3SJohn Marino 	COLOR_YELLOW,
6486d7f5d3SJohn Marino 	COLOR_BLUE,
6586d7f5d3SJohn Marino 	COLOR_MAGENTA,
6686d7f5d3SJohn Marino 	COLOR_CYAN,
6786d7f5d3SJohn Marino 	COLOR_WHITE
6886d7f5d3SJohn Marino };
6986d7f5d3SJohn Marino 
7086d7f5d3SJohn Marino /*
7186d7f5d3SJohn Marino  * If there is an established color pair with the given fg and bg
7286d7f5d3SJohn Marino  * colors, return it.  Else allocate a new pair with these colors
7386d7f5d3SJohn Marino  * and return that.
7486d7f5d3SJohn Marino  */
7586d7f5d3SJohn Marino static int
curses_colors_find(int fg,int bg)7686d7f5d3SJohn Marino curses_colors_find(int fg, int bg)
7786d7f5d3SJohn Marino {
7886d7f5d3SJohn Marino 	int pair_no;
7986d7f5d3SJohn Marino 	short fge, bge;
8086d7f5d3SJohn Marino 
8186d7f5d3SJohn Marino 	for (pair_no = 0;
8286d7f5d3SJohn Marino 	     pair_no <= allocated_colors && pair_no < COLOR_PAIRS;
8386d7f5d3SJohn Marino 	     pair_no++) {
8486d7f5d3SJohn Marino 		pair_content(pair_no, &fge, &bge);
8586d7f5d3SJohn Marino 		if (fg == fge && bg == bge)
8686d7f5d3SJohn Marino 			return(pair_no);
8786d7f5d3SJohn Marino 	}
8886d7f5d3SJohn Marino 
8986d7f5d3SJohn Marino 	/*
9086d7f5d3SJohn Marino 	 * No pair was found, allocate a new one.
9186d7f5d3SJohn Marino 	 */
9286d7f5d3SJohn Marino 	if (allocated_colors < (COLOR_PAIRS-1)) {
9386d7f5d3SJohn Marino 		allocated_colors++;
9486d7f5d3SJohn Marino 		init_pair(allocated_colors, fg, bg);
9586d7f5d3SJohn Marino 		return(allocated_colors);
9686d7f5d3SJohn Marino 	}
9786d7f5d3SJohn Marino 
9886d7f5d3SJohn Marino 	/*
9986d7f5d3SJohn Marino 	 * No space to allocate a new one, return error.
10086d7f5d3SJohn Marino 	 */
10186d7f5d3SJohn Marino 	return(-1);
10286d7f5d3SJohn Marino }
10386d7f5d3SJohn Marino 
10486d7f5d3SJohn Marino static void
curses_colors_cfg(int role,int fg,int bg,int bold)10586d7f5d3SJohn Marino curses_colors_cfg(int role, int fg, int bg, int bold)
10686d7f5d3SJohn Marino {
10786d7f5d3SJohn Marino 	int pair_no;
10886d7f5d3SJohn Marino 
10986d7f5d3SJohn Marino 	pair_no = curses_colors_find(fg, bg);
11086d7f5d3SJohn Marino 	if (pair_no != -1) {
11186d7f5d3SJohn Marino 		colors_tab[role].pair_no = pair_no;
11286d7f5d3SJohn Marino 		colors_tab[role].bold = bold;
11386d7f5d3SJohn Marino 	} else {
11486d7f5d3SJohn Marino 		colors_tab[role].pair_no = 0;
11586d7f5d3SJohn Marino 		colors_tab[role].bold = bold;
11686d7f5d3SJohn Marino 	}
11786d7f5d3SJohn Marino }
11886d7f5d3SJohn Marino 
11986d7f5d3SJohn Marino void
curses_colors_init(int force_monochrome)12086d7f5d3SJohn Marino curses_colors_init(int force_monochrome)
12186d7f5d3SJohn Marino {
12286d7f5d3SJohn Marino 	if (!force_monochrome) {
12386d7f5d3SJohn Marino 		if (has_colors()) {
12486d7f5d3SJohn Marino 			monochrome = 0;
12586d7f5d3SJohn Marino 			start_color();
12686d7f5d3SJohn Marino 		}
12786d7f5d3SJohn Marino 	}
12886d7f5d3SJohn Marino 
12986d7f5d3SJohn Marino 	/*
13086d7f5d3SJohn Marino 	 * By default, make it look kinda like the default libdialog.
13186d7f5d3SJohn Marino 	 */
13286d7f5d3SJohn Marino 	curses_colors_cfg(CURSES_COLORS_NORMAL,    COLOR_BLACK,  COLOR_GREY,  0);
13386d7f5d3SJohn Marino 	curses_colors_cfg(CURSES_COLORS_BACKDROP,  COLOR_WHITE,  COLOR_BLUE,  0);
13486d7f5d3SJohn Marino 	curses_colors_cfg(CURSES_COLORS_MENUBAR,   COLOR_BLACK,  COLOR_GREY,  0);
13586d7f5d3SJohn Marino 	curses_colors_cfg(CURSES_COLORS_STATUSBAR, COLOR_BLACK,  COLOR_GREY,  0);
13686d7f5d3SJohn Marino 	curses_colors_cfg(CURSES_COLORS_BORDER,	   COLOR_WHITE,  COLOR_GREY,  1);
13786d7f5d3SJohn Marino 	curses_colors_cfg(CURSES_COLORS_FORMTITLE, COLOR_YELLOW, COLOR_GREY,  1);
13886d7f5d3SJohn Marino 	curses_colors_cfg(CURSES_COLORS_LABEL,     COLOR_BLACK,  COLOR_GREY,  0);
13986d7f5d3SJohn Marino 	curses_colors_cfg(CURSES_COLORS_CONTROL,   COLOR_BLACK,  COLOR_GREY,  0);
14086d7f5d3SJohn Marino 	curses_colors_cfg(CURSES_COLORS_TEXT,      COLOR_BLACK,  COLOR_GREY,  0);
14186d7f5d3SJohn Marino 	curses_colors_cfg(CURSES_COLORS_FOCUS,     COLOR_WHITE,  COLOR_BLUE,  1);
14286d7f5d3SJohn Marino 	curses_colors_cfg(CURSES_COLORS_SCROLLAREA,COLOR_GREY,   COLOR_BLACK, 0);
14386d7f5d3SJohn Marino 	curses_colors_cfg(CURSES_COLORS_SCROLLBAR, COLOR_WHITE,  COLOR_BLUE,  1);
14486d7f5d3SJohn Marino 	curses_colors_cfg(CURSES_COLORS_ACCEL,     COLOR_WHITE,  COLOR_GREY,  1);
14586d7f5d3SJohn Marino 	curses_colors_cfg(CURSES_COLORS_ACCELFOCUS,COLOR_YELLOW, COLOR_BLUE,  1);
14686d7f5d3SJohn Marino }
14786d7f5d3SJohn Marino 
14886d7f5d3SJohn Marino void
curses_colors_set(WINDOW * w,int a)14986d7f5d3SJohn Marino curses_colors_set(WINDOW *w, int a)
15086d7f5d3SJohn Marino {
15186d7f5d3SJohn Marino 	if (!monochrome)
15286d7f5d3SJohn Marino 		wattrset(w, COLOR_PAIR(colors_tab[a].pair_no));
15386d7f5d3SJohn Marino 	if (colors_tab[a].bold)
15486d7f5d3SJohn Marino 		wattron(w, A_BOLD);
15586d7f5d3SJohn Marino 	else
15686d7f5d3SJohn Marino 		wattroff(w, A_BOLD);
15786d7f5d3SJohn Marino }
15886d7f5d3SJohn Marino 
15986d7f5d3SJohn Marino void
curses_window_blank(WINDOW * w)16086d7f5d3SJohn Marino curses_window_blank(WINDOW *w)
16186d7f5d3SJohn Marino {
16286d7f5d3SJohn Marino 	unsigned int i;
16386d7f5d3SJohn Marino 
16486d7f5d3SJohn Marino 	for (i = 0; i <= ymax; i++) {
16586d7f5d3SJohn Marino 		wmove(w, i, 0);
16686d7f5d3SJohn Marino 		whline(w, ' ', xmax);
16786d7f5d3SJohn Marino 	}
16886d7f5d3SJohn Marino 
16986d7f5d3SJohn Marino 	wrefresh(w);
17086d7f5d3SJohn Marino }
17186d7f5d3SJohn Marino 
17286d7f5d3SJohn Marino void
curses_frame_draw(int x,int y,int width,int height)17386d7f5d3SJohn Marino curses_frame_draw(int x, int y, int width, int height)
17486d7f5d3SJohn Marino {
17586d7f5d3SJohn Marino 	int i;
17686d7f5d3SJohn Marino 
17786d7f5d3SJohn Marino 	mvaddch(y, x, ACS_ULCORNER);
17886d7f5d3SJohn Marino 	hline(ACS_HLINE, width - 2);
17986d7f5d3SJohn Marino 	mvaddch(y, x + width - 1, ACS_URCORNER);
18086d7f5d3SJohn Marino 
18186d7f5d3SJohn Marino 	mvaddch(y + height - 1, x, ACS_LLCORNER);
18286d7f5d3SJohn Marino 	hline(ACS_HLINE, width - 2);
18386d7f5d3SJohn Marino 	mvaddch(y + height - 1, x + width - 1, ACS_LRCORNER);
18486d7f5d3SJohn Marino 
18586d7f5d3SJohn Marino 	move(y + 1, x);
18686d7f5d3SJohn Marino 	vline(ACS_VLINE, height - 2);
18786d7f5d3SJohn Marino 
18886d7f5d3SJohn Marino 	move(y + 1, x + width - 1);
18986d7f5d3SJohn Marino 	vline(ACS_VLINE, height - 2);
19086d7f5d3SJohn Marino 
19186d7f5d3SJohn Marino 	for (i = y + 1; i < y + height - 1; i++) {
19286d7f5d3SJohn Marino 		move(i, x + 1);
19386d7f5d3SJohn Marino 		hline(' ', width - 2);
19486d7f5d3SJohn Marino 	}
19586d7f5d3SJohn Marino }
19686d7f5d3SJohn Marino 
19786d7f5d3SJohn Marino void
curses_load_backdrop(WINDOW * w,const char * filename)19886d7f5d3SJohn Marino curses_load_backdrop(WINDOW *w, const char *filename)
19986d7f5d3SJohn Marino {
20086d7f5d3SJohn Marino 	FILE *f;
20186d7f5d3SJohn Marino 	char line[80];
20286d7f5d3SJohn Marino 	int row = 1;
20386d7f5d3SJohn Marino 	int my, mx;
20486d7f5d3SJohn Marino 
20586d7f5d3SJohn Marino 	getmaxyx(w, my, mx);
20686d7f5d3SJohn Marino 	wclear(w);
20786d7f5d3SJohn Marino 	curses_colors_set(w, CURSES_COLORS_BACKDROP);
20886d7f5d3SJohn Marino 	curses_window_blank(w);
20986d7f5d3SJohn Marino 
21086d7f5d3SJohn Marino 	if ((f = fopen(filename, "r")) != NULL) {
21186d7f5d3SJohn Marino 		while (fgets(line, 79, f) != NULL) {
21286d7f5d3SJohn Marino 			if (row > my)
21386d7f5d3SJohn Marino 				break;
21486d7f5d3SJohn Marino 			if (line[strlen(line) - 1] == '\n')
21586d7f5d3SJohn Marino 				line[strlen(line) - 1] = '\0';
21686d7f5d3SJohn Marino 			mvwaddnstr(w, row++, 0, line, mx);
21786d7f5d3SJohn Marino 		}
21886d7f5d3SJohn Marino 		fclose(f);
21986d7f5d3SJohn Marino 	}
22086d7f5d3SJohn Marino }
22186d7f5d3SJohn Marino 
22286d7f5d3SJohn Marino void
curses_debug_str(const char * s)22386d7f5d3SJohn Marino curses_debug_str(const char *s)
22486d7f5d3SJohn Marino {
22586d7f5d3SJohn Marino 	char b[256];
22686d7f5d3SJohn Marino 
22786d7f5d3SJohn Marino 	move(1, 0);
22886d7f5d3SJohn Marino 	sprintf(b, "[%77s]", s);
22986d7f5d3SJohn Marino 	addstr(b);
23086d7f5d3SJohn Marino 	refresh();
23186d7f5d3SJohn Marino }
23286d7f5d3SJohn Marino 
23386d7f5d3SJohn Marino void
curses_debug_int(int i)23486d7f5d3SJohn Marino curses_debug_int(int i)
23586d7f5d3SJohn Marino {
23686d7f5d3SJohn Marino 	char b[256];
23786d7f5d3SJohn Marino 
23886d7f5d3SJohn Marino 	move(1, 0);
23986d7f5d3SJohn Marino 	sprintf(b, "[%06d]", i);
24086d7f5d3SJohn Marino 	addstr(b);
24186d7f5d3SJohn Marino 	refresh();
24286d7f5d3SJohn Marino }
24386d7f5d3SJohn Marino 
24486d7f5d3SJohn Marino void
curses_debug_key(int i)24586d7f5d3SJohn Marino curses_debug_key(int i)
24686d7f5d3SJohn Marino {
24786d7f5d3SJohn Marino 	char b[256];
24886d7f5d3SJohn Marino 
24986d7f5d3SJohn Marino 	move(1, 0);
25086d7f5d3SJohn Marino 	sprintf(b, "[%06d] %s", i, keyname(i));
25186d7f5d3SJohn Marino 	addstr(b);
25286d7f5d3SJohn Marino 	refresh();
25386d7f5d3SJohn Marino }
25486d7f5d3SJohn Marino 
25586d7f5d3SJohn Marino void
curses_debug_float(float f)25686d7f5d3SJohn Marino curses_debug_float(float f)
25786d7f5d3SJohn Marino {
25886d7f5d3SJohn Marino 	char b[256];
25986d7f5d3SJohn Marino 
26086d7f5d3SJohn Marino 	move(1, 0);
26186d7f5d3SJohn Marino 	sprintf(b, "[%09.3f]", f);
26286d7f5d3SJohn Marino 	addstr(b);
26386d7f5d3SJohn Marino 	refresh();
26486d7f5d3SJohn Marino }
26586d7f5d3SJohn Marino 
26686d7f5d3SJohn Marino /*
26786d7f5d3SJohn Marino  * Word wrapping.
26886d7f5d3SJohn Marino  *
26986d7f5d3SJohn Marino  * text:	The text to word-wrap, as one long string.  Spaces will be
27086d7f5d3SJohn Marino  *		compressed, but end-of-line characters will be honoured.
27186d7f5d3SJohn Marino  * line:	A buffer (must be allocated by the caller) to hold a single
27286d7f5d3SJohn Marino  *		line extracted from text.
27386d7f5d3SJohn Marino  * width:	The maximum width of a line.
27486d7f5d3SJohn Marino  * spos:	Pointer to the source position in text.  Should be initially
27586d7f5d3SJohn Marino  *		set to zero, and retained between calls to this function.
27686d7f5d3SJohn Marino  * Returns:	A boolean indicating whether the end of text was reached.
27786d7f5d3SJohn Marino  *		Typically this function should be called repeatedly until
27886d7f5d3SJohn Marino  *		it returns true.
27986d7f5d3SJohn Marino  */
28086d7f5d3SJohn Marino int
extract_wrapped_line(const char * text,char * line,int width,int * spos)28186d7f5d3SJohn Marino extract_wrapped_line(const char *text, char *line, int width, int *spos)
28286d7f5d3SJohn Marino {
28386d7f5d3SJohn Marino 	int dpos = 0;
28486d7f5d3SJohn Marino 	int saved_spos, saved_dpos;
28586d7f5d3SJohn Marino 
28686d7f5d3SJohn Marino 	for (;;) {
28786d7f5d3SJohn Marino 		/*
28886d7f5d3SJohn Marino 		 * Skip over whitespace.  If we find a newline or the
28986d7f5d3SJohn Marino 		 * end of the text, return a blank line.  Leave *spos
29086d7f5d3SJohn Marino 		 * at the position of the 1st non-whitespace character.
29186d7f5d3SJohn Marino 		 */
29286d7f5d3SJohn Marino 		while (isspace(text[*spos]) && text[*spos] != '\0') {
29386d7f5d3SJohn Marino 			if (text[*spos] == '\n') {
29486d7f5d3SJohn Marino 				line[dpos] = '\0';
29586d7f5d3SJohn Marino 				(*spos)++;
29686d7f5d3SJohn Marino 				return(0);
29786d7f5d3SJohn Marino 			}
29886d7f5d3SJohn Marino 			(*spos)++;
29986d7f5d3SJohn Marino 		}
30086d7f5d3SJohn Marino 
30186d7f5d3SJohn Marino 		/*
30286d7f5d3SJohn Marino 		 * Save start position and destination position.
30386d7f5d3SJohn Marino 		 */
30486d7f5d3SJohn Marino 		saved_spos = *spos;
30586d7f5d3SJohn Marino 		saved_dpos = dpos;
30686d7f5d3SJohn Marino 
30786d7f5d3SJohn Marino 		/*
30886d7f5d3SJohn Marino 		 * Read a word from *spos onward.
30986d7f5d3SJohn Marino 		 */
31086d7f5d3SJohn Marino 		while (!isspace(text[*spos]) &&
31186d7f5d3SJohn Marino 		       text[*spos] != '\0' &&
31286d7f5d3SJohn Marino 		       dpos < width) {
31386d7f5d3SJohn Marino 			line[dpos++] = text[(*spos)++];
31486d7f5d3SJohn Marino 		}
31586d7f5d3SJohn Marino 
31686d7f5d3SJohn Marino 		if (text[*spos] == '\0') {
31786d7f5d3SJohn Marino 			/*
31886d7f5d3SJohn Marino 			 * End of string - return this word as the last.
31986d7f5d3SJohn Marino 			 */
32086d7f5d3SJohn Marino 			line[dpos] = '\0';
32186d7f5d3SJohn Marino 			return(1);
32286d7f5d3SJohn Marino 		} else if (dpos >= width) {
32386d7f5d3SJohn Marino 			/*
32486d7f5d3SJohn Marino 			 * Last word is too long to fit on this line.
32586d7f5d3SJohn Marino 			 */
32686d7f5d3SJohn Marino 			if (dpos - saved_dpos >= width) {
32786d7f5d3SJohn Marino 				/*
32886d7f5d3SJohn Marino 				 * In fact, it's too long to fit on any line!
32986d7f5d3SJohn Marino 				 * Truncate it.
33086d7f5d3SJohn Marino 				 */
33186d7f5d3SJohn Marino 				line[width - 1] = '\0';
33286d7f5d3SJohn Marino 				*spos = saved_spos + (dpos - saved_dpos);
33386d7f5d3SJohn Marino 				return(0);
33486d7f5d3SJohn Marino 			} else {
33586d7f5d3SJohn Marino 				/*
33686d7f5d3SJohn Marino 				 * Save it for the next pass.
33786d7f5d3SJohn Marino 				 */
33886d7f5d3SJohn Marino 				*spos = saved_spos;
33986d7f5d3SJohn Marino 				line[saved_dpos - 1] = '\0';
34086d7f5d3SJohn Marino 				return(0);
34186d7f5d3SJohn Marino 			}
34286d7f5d3SJohn Marino 		} else {
34386d7f5d3SJohn Marino 			line[dpos++] = ' ';
34486d7f5d3SJohn Marino 		}
34586d7f5d3SJohn Marino 	}
34686d7f5d3SJohn Marino }
347