2 * dselect - Debian package maintenance user interface
3 * baselist.cc - list of somethings
5 * Copyright © 1994,1995 Ian Jackson <ijackson@chiark.greenend.org.uk>
6 * Copyright © 2001 Wichert Akkerman <wakkerma@debian.org>
7 * Copyright © 2007-2013 Guillem Jover <guillem@debian.org>
9 * This is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <https://www.gnu.org/licenses/>.
26 #include <sys/ioctl.h>
34 #include <dpkg/i18n.h>
35 #include <dpkg/c-ctype.h>
36 #include <dpkg/dpkg.h>
37 #include <dpkg/dpkg-db.h>
42 void mywerase(WINDOW
*win
) {
45 for (y
=0; y
<my
; y
++) {
46 wmove(win
,y
,0); for (x
=0; x
<mx
; x
++) waddch(win
,' ');
52 baselist::resize_window()
54 debug(dbg_general
, "baselist::resize_window(), baselist=%p", this);
57 if (doupdate() == ERR
)
58 ohshite(_("cannot update screen after window resize"));
62 baselist::add_column(column
&col
, const char *title
, int width
)
68 col_cur_x
+= col
.width
+ gap_width
;
72 baselist::end_column(column
&col
, const char *title
)
76 col
.width
= total_width
- col
.x
;
78 col_cur_x
+= col
.width
+ gap_width
;
82 baselist::draw_column_head(const column
&col
)
84 mvwaddnstr(colheadspad
, 0, col
.x
, col
.title
, col
.width
);
88 baselist::draw_column_sep(const column
&col
, int y
)
90 mvwaddch(listpad
, y
, col
.x
- 1, ' ');
94 baselist::draw_column_item(const column
&col
, int y
, const char *item
)
96 mvwprintw(listpad
, y
, col
.x
, "%-*.*s", col
.width
, col
.width
, item
);
99 void baselist::setheights() {
100 int y
= ymax
- (title_height
+ colheads_height
+ thisstate_height
);
103 internerr("widget y=%d < 1", y
);
105 if (showinfo
==2 && y
>=7) {
109 } else if (showinfo
==1 && y
>=10) {
111 info_height
= (y
-1)/2;
118 colheads_row
= title_height
;
119 list_row
= colheads_row
+ colheads_height
;
120 thisstate_row
= list_row
+ list_height
;
121 info_row
= thisstate_row
+ thisstate_height
;
122 whatinfo_row
= ymax
- 1;
125 void baselist::startdisplay() {
126 debug(dbg_general
, "baselist[%p]::startdisplay()", this);
127 cbreak(); noecho(); nonl(); keypad(stdscr
,TRUE
);
128 clear(); wnoutrefresh(stdscr
);
131 if (has_colors() && start_color()==OK
&& COLOR_PAIRS
>= numscreenparts
) {
133 printf("allocing\n");
134 for (i
= 1; i
< numscreenparts
; i
++) {
135 if (init_pair(i
, color
[i
].fore
, color
[i
].back
) != OK
)
136 ohshite(_("cannot allocate color pair"));
137 part_attr
[i
] = COLOR_PAIR(i
) | color
[i
].attr
;
140 /* User defined attributes for B&W mode are not currently supported. */
141 part_attr
[title
] = A_REVERSE
;
142 part_attr
[thisstate
] = A_STANDOUT
;
144 part_attr
[listsel
] = A_STANDOUT
;
145 part_attr
[selstate
] = A_BOLD
;
146 part_attr
[selstatesel
] = A_STANDOUT
;
147 part_attr
[colheads
]= A_BOLD
;
148 part_attr
[query
] = part_attr
[title
];
149 part_attr
[info_body
] = part_attr
[list
];
150 part_attr
[info_head
] = A_BOLD
;
151 part_attr
[whatinfo
] = part_attr
[thisstate
];
152 part_attr
[helpscreen
] = A_NORMAL
;
155 // set up windows and pads, based on screen size
156 getmaxyx(stdscr
,ymax
,xmax
);
157 title_height
= ymax
>=6;
158 colheads_height
= ymax
>=5;
159 thisstate_height
= ymax
>=3;
164 titlewin
= newwin(1,xmax
, 0,0);
165 if (!titlewin
) ohshite(_("failed to create title window"));
166 wattrset(titlewin
, part_attr
[title
]);
168 whatinfowin
= newwin(1,xmax
, whatinfo_row
,0);
169 if (!whatinfowin
) ohshite(_("failed to create whatinfo window"));
170 wattrset(whatinfowin
, part_attr
[whatinfo
]);
172 listpad
= newpad(ymax
, total_width
);
173 if (!listpad
) ohshite(_("failed to create baselist pad"));
175 colheadspad
= newpad(1, total_width
);
176 if (!colheadspad
) ohshite(_("failed to create heading pad"));
177 wattrset(colheadspad
, part_attr
[colheads
]);
179 thisstatepad
= newpad(1, total_width
);
180 if (!thisstatepad
) ohshite(_("failed to create thisstate pad"));
181 wattrset(thisstatepad
, part_attr
[thisstate
]);
183 infopad
= newpad(MAX_DISPLAY_INFO
, total_width
);
184 if (!infopad
) ohshite(_("failed to create info pad"));
185 wattrset(infopad
, part_attr
[info_body
]);
186 wbkgdset(infopad
, ' ' | part_attr
[info_body
]);
188 querywin
= newwin(1,xmax
,ymax
-1,0);
189 if (!querywin
) ohshite(_("failed to create query window"));
190 wbkgdset(querywin
, ' ' | part_attr
[query
]);
192 if (cursorline
>= topofscreen
+ list_height
) topofscreen
= cursorline
;
193 if (topofscreen
> nitems
- list_height
) topofscreen
= nitems
- list_height
;
194 if (topofscreen
< 0) topofscreen
= 0;
196 infotopofscreen
= 0; leftofscreen
= 0;
201 "baselist::startdisplay() done ...\n\n"
202 " xmax=%d, ymax=%d;\n\n"
203 " title_height=%d, colheads_height=%d, list_height=%d;\n"
204 " thisstate_height=%d, info_height=%d, whatinfo_height=%d;\n\n"
205 " colheads_row=%d, thisstate_row=%d, info_row=%d;\n"
206 " whatinfo_row=%d, list_row=%d;\n\n",
207 xmax
, ymax
, title_height
, colheads_height
, list_height
,
208 thisstate_height
, info_height
, whatinfo_height
,
209 colheads_row
, thisstate_row
, info_row
, whatinfo_row
, list_row
);
212 void baselist::enddisplay() {
217 delwin(thisstatepad
);
219 wmove(stdscr
,ymax
,0); wclrtoeol(stdscr
);
224 void baselist::redrawall() {
227 wattrset(listpad
, part_attr
[list
]);
229 ldrawnstart
= ldrawnend
= -1; // start is first drawn; end is first undrawn; -1=none
235 void baselist::redraw1item(int index
) {
236 redraw1itemsel(index
, index
== cursorline
);
239 baselist::baselist(keybindings
*kb
) {
240 debug(dbg_general
, "baselist[%p]::baselist()", this);
247 total_width
= max(TOTAL_LIST_WIDTH
, COLS
);
257 thisstate_height
= 0;
272 colheadspad
= nullptr;
273 thisstatepad
= nullptr;
276 whatinfowin
= nullptr;
286 void baselist::itd_keys() {
287 whatinfovb(_("Keybindings"));
289 const int givek
= xmax
/3;
290 bindings
->describestart();
292 while ((ta
= bindings
->describenext()) != nullptr) {
293 const char **tap
= ta
+1;
295 waddstr(infopad
, gettext(*tap
));
296 tap
++; if (!*tap
) break;
297 waddstr(infopad
, ", ");
302 mvwaddstr(infopad
, y
,givek
, ta
[0]);
303 waddch(infopad
,'\n');
308 void baselist::dosearch() {
310 debug(dbg_general
, "baselist[%p]::dosearch(); searchstring='%s'",
312 for (offset
= 1, index
= max(topofscreen
, cursorline
+ 1);
315 if (index
>= nitems
) index
-= nitems
;
316 if (matchsearch(index
)) {
317 topofscreen
= index
-1;
318 if (topofscreen
> nitems
- list_height
) topofscreen
= nitems
-list_height
;
319 if (topofscreen
< 0) topofscreen
= 0;
327 void baselist::refreshinfo() {
328 pnoutrefresh(infopad
, infotopofscreen
,leftofscreen
, info_row
,0,
329 min(info_row
+ info_height
- 1, info_row
+ MAX_DISPLAY_INFO
- 1),
330 min(total_width
- leftofscreen
- 1, xmax
- 1));
332 if (whatinfo_height
) {
333 mywerase(whatinfowin
);
334 mvwaddstr(whatinfowin
,0,0, whatinfovb
.string());
335 if (infolines
> info_height
) {
336 wprintw(whatinfowin
,_(" -- %d%%, press "),
337 (infotopofscreen
+ info_height
) * 100 / infolines
);
338 if (infotopofscreen
+ info_height
< infolines
) {
339 wprintw(whatinfowin
,_("%s for more"), bindings
->find("iscrollon"));
340 if (infotopofscreen
) waddstr(whatinfowin
, ", ");
343 wprintw(whatinfowin
, _("%s to go back"),bindings
->find("iscrollback"));
344 waddch(whatinfowin
,'.');
346 wnoutrefresh(whatinfowin
);
350 void baselist::wordwrapinfo(int offset
, const char *m
) {
351 ssize_t usemax
= xmax
- 5;
352 debug(dbg_general
, "baselist[%p]::wordwrapinfo(%d, '%s')", this, offset
, m
);
353 bool wrapping
= false;
356 int offleft
=offset
; while (*m
== ' ' && offleft
>0) { m
++; offleft
--; }
357 const char *p
= strchrnul(m
, '\n');
360 while (l
&& c_isspace(m
[l
- 1]))
362 if (!l
|| (*m
== '.' && l
== 1)) {
363 if (wrapping
) waddch(infopad
,'\n');
364 waddch(infopad
, '\n');
366 } else if (*m
== ' ' || usemax
< 10) {
367 if (wrapping
) waddch(infopad
,'\n');
368 waddnstr(infopad
, m
, l
);
369 waddch(infopad
, '\n');
372 int x
, y DPKG_ATTR_UNUSED
;
377 waddch(infopad
,'\n');
384 ssize_t dosend
= usemax
- x
;
389 while (i
> 0 && m
[i
] != ' ') i
--;
390 if (i
> 0 || x
> 0) dosend
=i
;
392 if (dosend
) waddnstr(infopad
, m
, dosend
);
393 while (dosend
< l
&& m
[dosend
] == ' ') dosend
++;
394 l
-= dosend
; m
+= dosend
;
396 waddch(infopad
,'\n');
402 if (getcury(infopad
) == (MAX_DISPLAY_INFO
- 1)) {
404 "[The package description is too long and has been truncated...]");
409 debug(dbg_general
, "baselist[%p]::wordwrapinfo() done", this);
412 baselist::~baselist() { }