chiark / gitweb /
lib/dpkg/tarfn.c: Kludge `tar_header_decode' to handle spurious `errno'.
[dpkg] / dselect / basecmds.cc
1 /*
2  * dselect - Debian package maintenance user interface
3  * basecmds.cc - base list keyboard commands display
4  *
5  * Copyright © 1994,1995 Ian Jackson <ijackson@chiark.greenend.org.uk>
6  * Copyright © 2000,2001 Wichert Akkerman <wakkerma@debian.org>
7  *
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.
12  *
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.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20  */
21
22 #include <config.h>
23 #include <compat.h>
24
25 #include <string.h>
26 #include <stdio.h>
27
28 #include <dpkg/i18n.h>
29 #include <dpkg/dpkg.h>
30 #include <dpkg/dpkg-db.h>
31
32 #include "dselect.h"
33 #include "helpmsgs.h"
34
35 void baselist::kd_scrollon() {
36   topofscreen += list_height;
37   if (topofscreen > nitems - list_height) topofscreen= nitems - list_height;
38   if (topofscreen < 0) topofscreen= 0;
39   if (cursorline < topofscreen)
40     setcursor(topofscreen);
41   refreshlist();
42 }
43
44 void baselist::kd_scrollon1() {
45   if (topofscreen >= nitems - list_height) return;
46   topofscreen++;
47   if (cursorline < topofscreen)
48     setcursor(topofscreen);
49   refreshlist();
50 }
51
52 void baselist::kd_scrollback() {
53   topofscreen -= list_height;
54   if (topofscreen < 0) topofscreen= 0;
55   if (cursorline >= topofscreen + list_height)
56     setcursor(topofscreen + list_height - 1);
57   refreshlist();
58 }
59
60 void baselist::kd_scrollback1() {
61   if (topofscreen <= 0) return;
62   topofscreen--;
63   if (cursorline >= topofscreen + list_height)
64     setcursor(topofscreen + list_height - 1);
65   refreshlist();
66 }
67
68 void baselist::kd_top() {
69   topofscreen= 0; setcursor(0);
70 }
71
72 void baselist::kd_bottom() {
73   topofscreen= nitems - list_height;
74   if (topofscreen < 0) topofscreen= 0;
75   setcursor(min(topofscreen + list_height - 1, nitems - 1));
76 }
77
78 void baselist::kd_redraw() {
79 //#define RFSH(x) werase(x); redrawwin(x)
80 //  RFSH(listpad);
81 //  RFSH(infopad);
82 //  RFSH(colheadspad);
83 //  RFSH(thisstatepad);
84 //  RFSH(titlewin);
85 //  RFSH(whatinfowin); /* FIXME: why does ncurses need this? */
86   clearok(curscr,TRUE);
87   redrawall();
88   debug(dbg_general, "baselist[%p]::kd_redraw() done", this);
89 }
90
91 void baselist::kd_searchagain() {
92   if (!searchstring[0]) { beep(); return; }
93   dosearch();
94 }
95
96 bool
97 baselist::checksearch(char *str)
98 {
99   return true;
100 }
101
102 bool
103 baselist::matchsearch(int index)
104 {
105   int lendiff, searchlen, i;
106   const char *name;
107
108   name = itemname(index);
109   if (!name)
110     return false;       /* Skip things without a name (separators). */
111
112   searchlen=strlen(searchstring);
113   lendiff = strlen(name) - searchlen;
114   for (i=0; i<=lendiff; i++)
115     if (strncasecmp(name + i, searchstring, searchlen) == 0)
116       return true;
117
118   return false;
119 }
120
121 void baselist::kd_search() {
122   char newsearchstring[128];
123   strcpy(newsearchstring,searchstring);
124   werase(querywin);
125   mvwaddstr(querywin,0,0, _("Search for ? "));
126   echo(); /* FIXME: ncurses documentation or implementation. */
127   if (wgetnstr(querywin,newsearchstring,sizeof(newsearchstring)-1) == ERR)
128     searchstring[0]= 0;
129   raise(SIGWINCH); /* FIXME: ncurses and xterm arrow keys. */
130   noecho(); /* FIXME: ncurses. */
131   if (whatinfo_height) { touchwin(whatinfowin); refreshinfo(); }
132   else if (info_height) { touchwin(infopad); refreshinfo(); }
133   else if (thisstate_height) redrawthisstate();
134   else { touchwin(listpad); refreshlist(); }
135   if (newsearchstring[0]) {
136     if (!checksearch(newsearchstring)) {
137       beep();
138       return;
139     }
140     strcpy(searchstring,newsearchstring);
141     dosearch();
142   } else
143     kd_searchagain();
144 }
145
146 void
147 baselist::displayerror(const char *str)
148 {
149   const char *pr = _("Error: ");
150   int prlen=strlen(pr);
151
152   beep();
153   werase(querywin);
154   mvwaddstr(querywin,0,0,pr);
155   mvwaddstr(querywin,0,prlen,str);
156   wgetch(querywin);
157   if (whatinfo_height) { touchwin(whatinfowin); refreshinfo(); }
158   else if (info_height) { touchwin(infopad); refreshinfo(); }
159   else if (thisstate_height) redrawthisstate();
160 }
161
162
163 void baselist::displayhelp(const struct helpmenuentry *helpmenu, int key) {
164   int maxx, maxy, i, nextkey;
165
166   getmaxyx(stdscr,maxy,maxx);
167   wbkgdset(stdscr, ' ' | part_attr[helpscreen]);
168   clearok(stdscr,TRUE);
169   for (;;) {
170     werase(stdscr);
171     const struct helpmenuentry *hme = helpmenu;
172     while (hme->key && hme->key != key)
173       hme++;
174     if (hme->key) {
175       int x, y DPKG_ATTR_UNUSED;
176
177       attrset(part_attr[helpscreen]);
178       mvaddstr(1,0, gettext(hme->msg->text));
179       attrset(part_attr[title]);
180       mvaddstr(0,0, _("Help: "));
181       addstr(gettext(hme->msg->title));
182       getyx(stdscr,y,x);
183       while (++x<maxx) addch(' ');
184       attrset(part_attr[thisstate]);
185       mvaddstr(maxy-1,0,
186 _("Press ? for help menu, . for next topic, <space> to exit help."));
187       getyx(stdscr,y,x);
188       while (++x<maxx) addch(' ');
189       move(maxy,maxx);
190       attrset(A_NORMAL);
191       nextkey= hme[1].key;
192     } else {
193       mvaddstr(1,1, _("Help information is available under the following topics:"));
194       for (i=0, hme=helpmenu; hme->key; hme++,i++) {
195         attrset(A_BOLD);
196         mvaddch(i+3,3, hme->key);
197         attrset(A_NORMAL);
198         mvaddstr(i+3,6, gettext(hme->msg->title));
199       }
200       mvaddstr(i+4,1,
201                _("Press a key from the list above, <space> or 'q' to exit help,\n"
202                  "  or '.' (full stop) to read each help page in turn. "));
203       nextkey= helpmenu[0].key;
204     }
205     refresh();
206     key= getch();
207     if (key == EOF) ohshite(_("error reading keyboard in help"));
208     if (key == ' ' || key == 'q') {
209       break;
210     } else if (key == '?' || key == 'h') {
211       key= 0;
212     } else if (key == '.') {
213       key= nextkey;
214     }
215   }
216   werase(stdscr);
217   clearok(stdscr,TRUE);
218   wnoutrefresh(stdscr);
219
220   redrawtitle();
221   refreshcolheads();
222   refreshlist();
223   redrawthisstate();
224   refreshinfo();
225   wnoutrefresh(whatinfowin);
226 }
227
228 void baselist::kd_help() {
229   displayhelp(helpmenulist(),0);
230 }
231
232 void baselist::setcursor(int index) {
233   if (listpad && cursorline != -1) {
234     redrawitemsrange(cursorline,cursorline+1);
235     redraw1itemsel(cursorline,0);
236   }
237   if (cursorline != index) infotopofscreen= 0;
238   cursorline= index;
239   if (listpad) {
240     redrawitemsrange(cursorline,cursorline+1);
241     redraw1itemsel(cursorline,1);
242     refreshlist();
243     redrawthisstate();
244   }
245   redrawinfo();
246 }
247
248 void baselist::kd_down() {
249   int ncursor= cursorline;
250   // scroll by one line unless the bottom is already visible
251   // or we're in the top half of the screen ...
252   if (topofscreen < nitems - list_height &&
253       ncursor >= topofscreen + list_height - 3) topofscreen++;
254   // move cursor if there are any more ...
255   if (cursorline+1 < nitems) ncursor++;
256   setcursor(ncursor);
257 }
258
259 void baselist::kd_up() {
260   int ncursor= cursorline;
261   // scroll by one line if there are any lines not shown yet
262   // and we're not in the bottom half the screen ...
263   if (topofscreen > 0 &&
264       ncursor <= topofscreen + 2) topofscreen--;
265   // move cursor if there are any to move it to ...
266   if (cursorline > 0) ncursor--;
267   setcursor(ncursor);
268 }
269
270 void baselist::kd_iscrollon() {
271   infotopofscreen += info_height;
272   if (infotopofscreen > infolines - info_height)
273     infotopofscreen= infolines - info_height;
274   if (infotopofscreen < 0) infotopofscreen= 0;
275   refreshinfo();
276 }
277
278 void baselist::kd_iscrollback() {
279   infotopofscreen -= info_height;
280   if (infotopofscreen < 0) infotopofscreen= 0;
281   refreshinfo();
282 }
283
284 void baselist::kd_iscrollon1() {
285   if (infotopofscreen >= infolines - info_height) return;
286   infotopofscreen++; refreshinfo();
287 }
288
289 void baselist::kd_iscrollback1() {
290   if (infotopofscreen <= 0) return;
291   infotopofscreen--; refreshinfo();
292 }
293
294 void baselist::kd_panon() {
295   leftofscreen += xmax/3;
296   if (leftofscreen > total_width - xmax) leftofscreen= total_width - xmax;
297   if (leftofscreen < 0) leftofscreen= 0;
298   refreshcolheads(); refreshlist(); redrawthisstate(); refreshinfo();
299 }
300
301 void baselist::kd_panback() {
302   leftofscreen -= xmax/3;
303   if (leftofscreen < 0) leftofscreen= 0;
304   refreshcolheads(); refreshlist(); redrawthisstate(); refreshinfo();
305 }
306
307 void baselist::kd_panon1() {
308   leftofscreen++;
309   if (leftofscreen > total_width - xmax) leftofscreen= total_width - xmax;
310   if (leftofscreen < 0) leftofscreen= 0;
311   refreshcolheads(); refreshlist(); redrawthisstate(); refreshinfo();
312 }
313
314 void baselist::kd_panback1() {
315   leftofscreen--;
316   if (leftofscreen < 0) leftofscreen= 0;
317   refreshcolheads(); refreshlist(); redrawthisstate(); refreshinfo();
318 }