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/>.
25 #include <sys/ioctl.h>
26 #include <sys/termios.h>
34 #include <dpkg/i18n.h>
35 #include <dpkg/dpkg.h>
36 #include <dpkg/dpkg-db.h>
41 void mywerase(WINDOW
*win
) {
44 for (y
=0; y
<my
; y
++) {
45 wmove(win
,y
,0); for (x
=0; x
<mx
; x
++) waddch(win
,' ');
50 baselist
*baselist::signallist
= 0;
51 void baselist::sigwinchhandler(int) {
53 if (debug
) fprintf(debug
,"baselist::sigwinchhandler(), signallist=%p\n",signallist
);
54 baselist
*p
= signallist
;
57 if (ioctl(fileno(stdout
), TIOCGWINSZ
, &size
) != 0) ohshite(_("ioctl(TIOCGWINSZ) failed"));
58 resizeterm(size
.ws_row
, size
.ws_col
); wrefresh(curscr
);
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"));
69 if (sigprocmask(SIG_SETMASK
,oblockedp
,0)) ohshite(_("failed to restore old signal mask"));
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
);
95 if (showinfo
==2 && y
>=7) {
99 } else if (showinfo
==1 && y
>=10) {
101 info_height
= (y
-1)/2;
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
);
121 if (has_colors() && start_color()==OK
&& COLOR_PAIRS
>= numscreenparts
) {
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
;
142 /* User defined attributes for B&W mode are not currently supported. */
143 title_attr
= A_REVERSE
;
144 thisstate_attr
= A_STANDOUT
;
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;
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;
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",
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() {
223 delwin(thisstatepad
);
225 wmove(stdscr
,ymax
,0); wclrtoeol(stdscr
);
229 void baselist::redrawall() {
232 wattrset(listpad
,list_attr
); mywerase(listpad
);
233 ldrawnstart
= ldrawnend
= -1; // start is first drawn; end is first undrawn; -1=none
239 void baselist::redraw1item(int index
) {
240 redraw1itemsel(index
, index
== cursorline
);
243 baselist::baselist(keybindings
*kb
) {
245 fprintf(debug
,"baselist[%p]::baselist()\n",this);
251 list_height
=0; info_height
=0;
252 topofscreen
= 0; leftofscreen
= 0;
253 listpad
= 0; cursorline
= -1;
259 void baselist::itd_keys() {
260 whatinfovb(_("Keybindings"));
262 const int givek
= xmax
/3;
263 bindings
->describestart();
265 while ((ta
= bindings
->describenext()) != 0) {
266 const char **tap
= ta
+1;
268 waddstr(infopad
, gettext(*tap
));
269 tap
++; if (!*tap
) break;
270 waddstr(infopad
, ", ");
275 mvwaddstr(infopad
, y
,givek
, ta
[0]);
276 waddch(infopad
,'\n');
280 void baselist::dosearch() {
282 if (debug
) fprintf(debug
,"baselist[%p]::dosearch(); searchstring=`%s'\n",
284 for (offset
=1, index
=greaterint(topofscreen
,cursorline
+1);
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;
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
, ", ");
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
) {
324 if (debug
) fprintf(debug
,"baselist[%p]::wordwrapinfo(%d, `%s')\n",this,offset
,m
);
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');
335 } else if (*m
== ' ' || usemax
< 10) {
336 if (wrapping
) waddch(infopad
,'\n');
337 waddnstr(infopad
, m
, l
);
338 waddch(infopad
,'\n'); wrapping
= 0;
344 waddch(infopad
,'\n');
351 int dosend
= usemax
-x
;
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
;
363 waddch(infopad
,'\n');
368 if (getcury(infopad
) == (MAX_DISPLAY_INFO
- 1)) {
370 "[The package description is too long and has been truncated...]");
375 if (debug
) fprintf(debug
,"baselist[%p]::wordwrapinfo() done\n",this);
378 baselist::~baselist() { }