1 /*
2 netrik -- The ANTRIK Internet Viewer
3 Copyright (C) Olaf D. Buddenhagen AKA antrik, et al (see AUTHORS)
4 Published under the GNU GPL; see LICENSE for details.
5 */
6 /*
7 * screen.c -- all screen handling functions (curses wrappers).
8 *
9 * (C) 2001, 2002, 2003 antrik
10 *
11 * Presently the full screen functions aren't used by the main program...
12 */
13 #include <curses.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <term.h>
18
19 #include "cfg.h"
20 #include "screen.h"
21 #include "winch.h"
22
23 /* init curses full screen mode;
24 * includes initializing color mode and color pairs */
start_curses(void)25 void start_curses(void)
26 {
27 initscr(); /* init curses */
28
29 /* set options */
30 if((cfg.color && start_color()==ERR)
31 || cbreak()==ERR /* unbuffered input */
32 || noecho()==ERR /* no key echo */
33 || intrflush(stdscr, FALSE)==ERR /* don't flush output on signals */
34 || keypad(stdscr, TRUE)==ERR /* translate function key sequences */
35 ) {
36 endwin();
37 fprintf(stderr, "error initializing curses in fullscreen mode\n");
38 exit(1);
39 }
40 nonl(); /* don't mess with cr on keyboard input */
41 idlok(stdscr, TRUE); /* allow hardware scrolling */
42
43 /* prepare color pairs */
44 if(cfg.color) {
45 int pair; /* currently processed color pair */
46
47 for(pair=1; pair<64; ++pair) { /* 8x8 color pairs (all combinations of fg and bg color); pair 0 is hard-wired (to white on black instead of black on black) */
48 int fg, bg;
49
50 fg=(pair+7)%8; bg=pair/8; /* fg colorspace rotated, so white on black will be mapped to pair 0 */
51 if(!cfg.force_colors) {
52 if(use_default_colors()!=ERR) { /* can use default colors */
53 if(bg==COLOR_BLACK)
54 bg=-1; /* use terminal default */
55 if(fg==COLOR_WHITE)
56 fg=-1;
57 }
58 }
59 if(init_pair(pair, fg, bg)==ERR) { /* set foreground and background of pair */
60 endwin();
61 fprintf(stderr, "error initializing curses in fullscreen mode (can't set color pair %d)\n", pair);
62 exit(1);
63 }
64 }
65
66 if(cfg.force_colors)
67 bkgdset(COLOR_PAIR(0));
68 }
69 }
70
71 /* set screen attributes (color, bold)
72 * (standard colors for white foreground/black background are handled in init) */
set_color(color)73 void set_color(color)
74 int color;
75 {
76 int attrs=A_NORMAL;
77
78 int fg=(color+1)&0x07; /* foreground color */
79 int bg=(color&0x70)>>4; /* background */
80
81 if(!cfg.color)
82 return;
83
84 /* prepare attributes */
85 if(color&0x80) { /* bright background */
86 if(cfg.inverse_bold) { /* can obtain bright background only with reverse video */
87 attrs|=A_BOLD|A_REVERSE; /* set bright background (reversed bright foreground) */
88 fg^=bg; bg^=fg; fg^=bg; /* swap */
89 bg=(bg-1)&7; fg=(fg+1)&7; /* undo color rotation for new background (old forground) and apply to new forground instead */
90 } else /* can set bright background directly */
91 attrs|=A_BLINK;
92 }
93 if(color&0x08) /* bright foreground */
94 attrs|=A_BOLD;
95
96 attrs|=COLOR_PAIR(bg<<3|fg);
97
98 attrset(attrs);
99 }
100
101 /* leave curses full screen mode (possibly temporarily) */
end_fullscreen(void)102 void end_fullscreen(void)
103 {
104 /* free bottom line (scroll one line) */
105 move(0,0);
106 deleteln();
107 refresh();
108
109 endwin();
110
111 enable_winch(); /* allow SIGWINCH outside fullscreen mode, so it can be handled by readline() (curses will adapt when restarting fullscreen) */
112 }
113
114
115 /* terminal control sequences */
116 static char *setaf; /* foreground color */
117 static char *setab; /* background color */
118
119 /* init curses (not full screen) and read some control sequence strings
120 * return screen width */
init_curses(void)121 int init_curses(void)
122 {
123 int width;
124
125 if(setupterm(NULL, 1, NULL)==ERR) { /* init */
126 fprintf(stderr, "Error initializing curses in raw mode.\n");
127 exit(1);
128 }
129
130 width=tigetnum("cols");
131 if(width<=0) {
132 fprintf(stderr, "Error initializing curses in raw mode. (Can't get screen size.)\n");
133 exit(1);
134 }
135
136 if(cfg.color) {
137 setaf=tigetstr("setaf"); /* set foreground color */
138 setab=tigetstr("setab"); /* background color */
139 if(setaf==NULL || setab==NULL) {
140 cfg.color=0;
141 fprintf(stderr, "Can't get color capabilities -- starting in monochrome mode.\n\nIf this is what you want, use --monochrome option to suppress this warning. Otherwise, please check your $TERM environment variable. (See README for details.)\n\nPress <return> to continue.\n");
142 getchar();
143 }
144
145 /* determine whether terminal needs workaround to display bright background colors */
146 if(cfg.inverse_bold < 0) { /* not forced by command line option -> guess */
147 char *term;
148
149 term=getenv("TERM");
150 if(term==NULL)
151 term="";
152
153 cfg.inverse_bold=(strstr(term, "xterm")!=NULL); /* xterm needs it */
154 }
155 }
156
157 return width;
158 }
159
160 /* set screen attributes (color, bold) in raw mode
161 * color white is not set; standard attributes are kept instead;
162 * likewise for black background */
set_color_raw(color)163 void set_color_raw(color)
164 int color;
165 {
166 chtype attrs=A_NORMAL;
167
168 int fg=color&0x07; /* foreground color */
169 int bg=(color&0x70)>>4; /* background */
170
171 if(!cfg.color)
172 return;
173
174 /* prepare attributes */
175 if(color&0x80) { /* bright background */
176 if(cfg.inverse_bold) { /* can obtain bright background only with reverse video */
177 attrs|=A_BOLD|A_REVERSE; /* set bright background (reversed bright foreground) */
178 fg^=bg; bg^=fg; fg^=bg; /* swap */
179 } else /* can set bright background directly */
180 attrs|=A_BLINK;
181 }
182 if(color&0x08) /* bright foreground */
183 attrs|=A_BOLD;
184
185 /* set */
186 vidattr(attrs);
187 if(bg!=COLOR_BLACK) /* not black (or force_colors) -> set background */
188 putp(tparm(setab, bg));
189 if(fg!=COLOR_WHITE) /* not white (or force_colors) -> set color */
190 putp(tparm(setaf, fg));
191 }
192
193 /* reset screen attributes to default */
reset_color_raw(void)194 void reset_color_raw(void)
195 {
196 if(!cfg.color)
197 return;
198
199 vidattr(A_BOLD); vidattr(A_NORMAL); /* force reset (curses doesn't know about color changes in raw mode...) */
200 }
201