split merge test into two tests
[dpkg/seanius.git] / dselect / baselist.cc
blob81accf59618550f6576c34a5cd2e267dd4b9ee99
1 /*
2 * dselect - Debian package maintenance user interface
3 * baselist.cc - list of somethings
5 * Copyright © 1994,1995 Ian Jackson <ian@chiark.greenend.org.uk>
6 * Copyright © 2001 Wichert Akkerman <wakkerma@debian.org>
8 * This is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include <config.h>
23 #include <compat.h>
25 #include <sys/ioctl.h>
26 #include <sys/termios.h>
28 #include <assert.h>
29 #include <ctype.h>
30 #include <string.h>
31 #include <unistd.h>
32 #include <stdio.h>
34 #include <dpkg/i18n.h>
35 #include <dpkg/dpkg.h>
36 #include <dpkg/dpkg-db.h>
38 #include "dselect.h"
39 #include "bindings.h"
41 void mywerase(WINDOW *win) {
42 int my,mx,y,x;
43 getmaxyx(win,my,mx);
44 for (y=0; y<my; y++) {
45 wmove(win,y,0); for (x=0; x<mx; x++) waddch(win,' ');
47 wmove(win,0,0);
50 baselist *baselist::signallist= 0;
51 void baselist::sigwinchhandler(int) {
52 struct winsize size;
53 if (debug) fprintf(debug,"baselist::sigwinchhandler(), signallist=%p\n",signallist);
54 baselist *p= signallist;
55 p->enddisplay();
56 endwin(); initscr();
57 if (ioctl(fileno(stdout), TIOCGWINSZ, &size) != 0) ohshite(_("ioctl(TIOCGWINSZ) failed"));
58 resizeterm(size.ws_row, size.ws_col); wrefresh(curscr);
59 p->startdisplay();
60 if (doupdate() == ERR) ohshite(_("doupdate in SIGWINCH handler failed"));
63 static void cu_sigwinch(int, void **argv) {
64 struct sigaction *osigactp= (struct sigaction*)argv[0];
65 sigset_t *oblockedp= (sigset_t*)argv[1];
67 if (sigaction(SIGWINCH,osigactp,0)) ohshite(_("failed to restore old SIGWINCH sigact"));
68 delete osigactp;
69 if (sigprocmask(SIG_SETMASK,oblockedp,0)) ohshite(_("failed to restore old signal mask"));
70 delete oblockedp;
73 void baselist::setupsigwinch() {
74 sigemptyset(&sigwinchset);
75 sigaddset(&sigwinchset,SIGWINCH);
77 osigactp= new(struct sigaction);
78 oblockedp= new(sigset_t);
79 if (sigprocmask(0,0,oblockedp)) ohshite(_("failed to get old signal mask"));
80 if (sigaction(SIGWINCH,0,osigactp)) ohshite(_("failed to get old SIGWINCH sigact"));
82 push_cleanup(cu_sigwinch,~0, 0,0, 2,(void*)osigactp,(void*)oblockedp);
84 if (sigprocmask(SIG_BLOCK,&sigwinchset,0)) ohshite(_("failed to block SIGWINCH"));
85 memset(&nsigact,0,sizeof(nsigact));
86 nsigact.sa_handler= sigwinchhandler;
87 sigemptyset(&nsigact.sa_mask);
88 //nsigact.sa_flags= SA_INTERRUPT;
89 if (sigaction(SIGWINCH,&nsigact,0)) ohshite(_("failed to set new SIGWINCH sigact"));
92 void baselist::setheights() {
93 int y= ymax - (title_height + colheads_height + thisstate_height);
94 assert(y>=1);
95 if (showinfo==2 && y>=7) {
96 list_height= 5;
97 whatinfo_height= 1;
98 info_height= y-6;
99 } else if (showinfo==1 && y>=10) {
100 list_height= y/2;
101 info_height= (y-1)/2;
102 whatinfo_height= 1;
103 } else {
104 list_height= y;
105 info_height= 0;
106 whatinfo_height= 0;
108 colheads_row= title_height;
109 list_row= colheads_row + colheads_height;
110 thisstate_row= list_row + list_height;
111 info_row= thisstate_row + thisstate_height;
112 whatinfo_row= ymax - 1;
115 void baselist::startdisplay() {
116 if (debug) fprintf(debug,"baselist[%p]::startdisplay()\n",this);
117 cbreak(); noecho(); nonl(); keypad(stdscr,TRUE);
118 clear(); wnoutrefresh(stdscr);
120 // find attributes
121 if (has_colors() && start_color()==OK && COLOR_PAIRS >= numscreenparts) {
122 int i;
123 printf("allocing\n");
124 for (i = 1; i < numscreenparts; i++) {
125 if (init_pair(i, color[i].fore, color[i].back) != OK)
126 ohshite(_("failed to allocate colour pair"));
128 /* TODO: should use an array of attr's, indexed by attr name. Oh well. */
129 list_attr= COLOR_PAIR(list) | color[list].attr;
130 listsel_attr= COLOR_PAIR(listsel) | color[listsel].attr;
131 title_attr= COLOR_PAIR(title) | color[title].attr;
132 thisstate_attr= COLOR_PAIR(thisstate) | color[thisstate].attr;
133 selstate_attr= COLOR_PAIR(selstate) | color[selstate].attr;
134 selstatesel_attr= COLOR_PAIR(selstatesel) | color[selstatesel].attr;
135 colheads_attr= COLOR_PAIR(colheads) | color[colheads].attr;
136 query_attr= COLOR_PAIR(query) | color[query].attr;
137 info_attr= COLOR_PAIR(info) | color[info].attr;
138 info_headattr= COLOR_PAIR(info_head) | color[info_head].attr;
139 whatinfo_attr= COLOR_PAIR(whatinfo) | color[whatinfo].attr;
140 helpscreen_attr= COLOR_PAIR(helpscreen) | color[helpscreen].attr;
141 } else {
142 /* User defined attributes for B&W mode are not currently supported. */
143 title_attr= A_REVERSE;
144 thisstate_attr= A_STANDOUT;
145 list_attr= 0;
146 listsel_attr= A_STANDOUT;
147 selstate_attr= A_BOLD;
148 selstatesel_attr= A_STANDOUT;
149 colheads_attr= A_BOLD;
150 query_attr= title_attr;
151 info_attr= list_attr;
152 info_headattr= A_BOLD;
153 whatinfo_attr= thisstate_attr;
154 helpscreen_attr= A_NORMAL;
157 // set up windows and pads, based on screen size
158 getmaxyx(stdscr,ymax,xmax);
159 title_height= ymax>=6;
160 colheads_height= ymax>=5;
161 thisstate_height= ymax>=3;
163 setheights();
164 setwidths();
166 titlewin= newwin(1,xmax, 0,0);
167 if (!titlewin) ohshite(_("failed to create title window"));
168 wattrset(titlewin,title_attr);
170 whatinfowin= newwin(1,xmax, whatinfo_row,0);
171 if (!whatinfowin) ohshite(_("failed to create whatinfo window"));
172 wattrset(whatinfowin,whatinfo_attr);
174 listpad = newpad(ymax, total_width);
175 if (!listpad) ohshite(_("failed to create baselist pad"));
177 colheadspad= newpad(1, total_width);
178 if (!colheadspad) ohshite(_("failed to create heading pad"));
179 wattrset(colheadspad,colheads_attr);
181 thisstatepad= newpad(1, total_width);
182 if (!thisstatepad) ohshite(_("failed to create thisstate pad"));
183 wattrset(thisstatepad,thisstate_attr);
185 infopad= newpad(MAX_DISPLAY_INFO, total_width);
186 if (!infopad) ohshite(_("failed to create info pad"));
187 wattrset(infopad,info_attr);
188 wbkgdset(infopad, ' ' | info_attr);
190 querywin= newwin(1,xmax,ymax-1,0);
191 if (!querywin) ohshite(_("failed to create query window"));
192 wbkgdset(querywin, ' ' | query_attr);
194 if (cursorline >= topofscreen + list_height) topofscreen= cursorline;
195 if (topofscreen > nitems - list_height) topofscreen= nitems - list_height;
196 if (topofscreen < 0) topofscreen= 0;
198 infotopofscreen= 0; leftofscreen= 0;
200 redrawall();
202 if (debug)
203 fprintf(debug,
204 "baselist::startdisplay() done ...\n\n"
205 " xmax=%d, ymax=%d;\n\n"
206 " title_height=%d, colheads_height=%d, list_height=%d;\n"
207 " thisstate_height=%d, info_height=%d, whatinfo_height=%d;\n\n"
208 " colheads_row=%d, thisstate_row=%d, info_row=%d;\n"
209 " whatinfo_row=%d, list_row=%d;\n\n",
210 xmax, ymax,
211 title_height, colheads_height, list_height,
212 thisstate_height, info_height, whatinfo_height,
213 colheads_row, thisstate_row, info_row,
214 whatinfo_row, list_row);
218 void baselist::enddisplay() {
219 delwin(titlewin);
220 delwin(whatinfowin);
221 delwin(listpad);
222 delwin(colheadspad);
223 delwin(thisstatepad);
224 delwin(infopad);
225 wmove(stdscr,ymax,0); wclrtoeol(stdscr);
226 listpad= 0;
229 void baselist::redrawall() {
230 redrawtitle();
231 redrawcolheads();
232 wattrset(listpad,list_attr); mywerase(listpad);
233 ldrawnstart= ldrawnend= -1; // start is first drawn; end is first undrawn; -1=none
234 refreshlist();
235 redrawthisstate();
236 redrawinfo();
239 void baselist::redraw1item(int index) {
240 redraw1itemsel(index, index == cursorline);
243 baselist::baselist(keybindings *kb) {
244 if (debug)
245 fprintf(debug,"baselist[%p]::baselist()\n",this);
247 bindings= kb;
248 nitems= 0;
250 xmax= -1;
251 list_height=0; info_height=0;
252 topofscreen= 0; leftofscreen= 0;
253 listpad= 0; cursorline= -1;
254 showinfo= 1;
256 searchstring[0]= 0;
259 void baselist::itd_keys() {
260 whatinfovb(_("Keybindings"));
262 const int givek= xmax/3;
263 bindings->describestart();
264 const char **ta;
265 while ((ta= bindings->describenext()) != 0) {
266 const char **tap= ta+1;
267 for (;;) {
268 waddstr(infopad, gettext(*tap));
269 tap++; if (!*tap) break;
270 waddstr(infopad, ", ");
272 int y,x;
273 getyx(infopad,y,x);
274 if (x >= givek) y++;
275 mvwaddstr(infopad, y,givek, ta[0]);
276 waddch(infopad,'\n');
280 void baselist::dosearch() {
281 int offset, index;
282 if (debug) fprintf(debug,"baselist[%p]::dosearch(); searchstring=`%s'\n",
283 this,searchstring);
284 for (offset=1, index=greaterint(topofscreen,cursorline+1);
285 offset<nitems;
286 offset++, index++) {
287 if (index >= nitems) index -= nitems;
288 if (matchsearch(index)) {
289 topofscreen= index-1;
290 if (topofscreen > nitems - list_height) topofscreen= nitems-list_height;
291 if (topofscreen < 0) topofscreen= 0;
292 setcursor(index);
293 return;
296 beep();
299 void baselist::refreshinfo() {
300 pnoutrefresh(infopad, infotopofscreen,leftofscreen, info_row,0,
301 lesserint(info_row + info_height - 1, info_row + MAX_DISPLAY_INFO - 1),
302 lesserint(total_width - leftofscreen - 1, xmax - 1));
304 if (whatinfo_height) {
305 mywerase(whatinfowin);
306 mvwaddstr(whatinfowin,0,0, whatinfovb.string());
307 if (infolines > info_height) {
308 wprintw(whatinfowin,_(" -- %d%%, press "),
309 (int)((infotopofscreen + info_height) * 100.0 / infolines));
310 if (infotopofscreen + info_height < infolines) {
311 wprintw(whatinfowin,_("%s for more"), bindings->find("iscrollon"));
312 if (infotopofscreen) waddstr(whatinfowin, ", ");
314 if (infotopofscreen)
315 wprintw(whatinfowin, _("%s to go back"),bindings->find("iscrollback"));
316 waddch(whatinfowin,'.');
318 wnoutrefresh(whatinfowin);
322 void baselist::wordwrapinfo(int offset, const char *m) {
323 int usemax= xmax-5;
324 if (debug) fprintf(debug,"baselist[%p]::wordwrapinfo(%d, `%s')\n",this,offset,m);
325 int wrapping=0;
326 for (;;) {
327 int offleft=offset; while (*m == ' ' && offleft>0) { m++; offleft--; }
328 const char *p= strchr(m,'\n');
329 int l= p ? (int)(p-m) : strlen(m);
330 while (l && isspace(m[l-1])) l--;
331 if (!l || (*m == '.' && l == 1)) {
332 if (wrapping) waddch(infopad,'\n');
333 waddch(infopad,'\n');
334 wrapping= 0;
335 } else if (*m == ' ' || usemax < 10) {
336 if (wrapping) waddch(infopad,'\n');
337 waddnstr(infopad, m, l);
338 waddch(infopad,'\n'); wrapping= 0;
339 } else {
340 int x,y;
341 if (wrapping) {
342 getyx(infopad, y,x);
343 if (x+1 >= usemax) {
344 waddch(infopad,'\n');
345 } else {
346 waddch(infopad,' ');
349 for (;;) {
350 getyx(infopad, y,x);
351 int dosend= usemax-x;
352 if (l <= dosend) {
353 dosend=l;
354 } else {
355 int i=dosend;
356 while (i > 0 && m[i] != ' ') i--;
357 if (i > 0 || x > 0) dosend=i;
359 if (dosend) waddnstr(infopad, m, dosend);
360 while (dosend < l && m[dosend] == ' ') dosend++;
361 l-= dosend; m+= dosend;
362 if (l <= 0) break;
363 waddch(infopad,'\n');
365 wrapping= 1;
367 if (!p) break;
368 if (getcury(infopad) == (MAX_DISPLAY_INFO - 1)) {
369 waddstr(infopad,
370 "[The package description is too long and has been truncated...]");
371 break;
373 m= ++p;
375 if (debug) fprintf(debug,"baselist[%p]::wordwrapinfo() done\n",this);
378 baselist::~baselist() { }
380 /* vi: sw=2 ts=8