2 * dselect - Debian package maintenance user interface
3 * pkgcmds.cc - package list keyboard commands
5 * Copyright © 1994,1995 Ian Jackson <ijackson@chiark.greenend.org.uk>
6 * Copyright © 2008-2014 Guillem Jover <guillem@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 <https://www.gnu.org/licenses/>.
28 #include <dpkg/dpkg.h>
29 #include <dpkg/dpkg-db.h>
35 packagelist
::affectedmatches(struct pkginfo
*pkg
, struct pkginfo
*comparewith
) {
36 switch (statsortorder
) {
38 if (comparewith
->clientdata
->ssavail
!= pkg
->clientdata
->ssavail
)
42 if (comparewith
->clientdata
->ssstate
!= pkg
->clientdata
->ssstate
)
48 internerr("unknown statsortorder %d", statsortorder
);
50 if (comparewith
->priority
!= PKG_PRIO_UNSET
&&
51 (comparewith
->priority
!= pkg
->priority
||
52 (comparewith
->priority
== PKG_PRIO_OTHER
&&
53 strcasecmp(comparewith
->otherpriority
, pkg
->otherpriority
))))
55 if (comparewith
->section
&&
56 strcasecmp(comparewith
->section
,
63 void packagelist
::affectedrange(int *startp
, int *endp
) {
64 if (table
[cursorline
]->pkg
->set
->name
) {
69 int index
= cursorline
;
70 while (index
< nitems
&& !table
[index
]->pkg
->set
->name
)
72 if (index
>= nitems
) {
73 *startp
= *endp
= cursorline
;
77 while (index
< nitems
&& affectedmatches(table
[index
]->pkg
,table
[cursorline
]->pkg
))
82 void packagelist
::movecursorafter(int ncursor
) {
83 if (ncursor
>= nitems
) ncursor
= nitems
-1;
84 topofscreen
+= ncursor
-cursorline
;
85 if (topofscreen
> nitems
- list_height
) topofscreen
= nitems
- list_height
;
86 if (topofscreen
< 0) topofscreen
= 0;
88 refreshlist(); redrawthisstate();
92 packagelist
::reallywant(pkgwant nwarg
, struct perpackagestate
*pkgstate
)
94 if (nwarg
!= PKG_WANT_SENTINEL
)
96 pkgstatus status
= pkgstate
->pkg
->status
;
97 if (status
== PKG_STAT_NOTINSTALLED
)
98 return PKG_WANT_PURGE
;
99 if (status
== PKG_STAT_CONFIGFILES
)
100 return PKG_WANT_DEINSTALL
;
101 return PKG_WANT_INSTALL
;
105 packagelist
::setwant(pkgwant nwarg
)
110 if (modstatdb_get_status() == msdbrw_readonly
) {
116 redrawitemsrange(cursorline
,cursorline
+1);
117 table
[cursorline
]->selected
= reallywant(nwarg
,table
[cursorline
]);
118 redraw1item(cursorline
);
122 packagelist
*sub
= new packagelist(bindings
, nullptr);
124 affectedrange(&top
,&bot
);
125 for (index
= top
; index
< bot
; index
++) {
126 if (!table
[index
]->pkg
->set
->name
)
128 nw
= reallywant(nwarg
,table
[index
]);
129 if (table
[index
]->selected
== nw
||
130 (table
[index
]->selected
== PKG_WANT_PURGE
&&
131 nw
== PKG_WANT_DEINSTALL
))
133 sub
->add(table
[index
]->pkg
,nw
);
136 repeatedlydisplay(sub
,dp_may
,this);
137 for (index
=top
; index
< bot
; index
++)
140 movecursorafter(bot
);
143 bool manual_install
= false;
145 void packagelist
::kd_select() {
146 manual_install
= true;
147 setwant(PKG_WANT_INSTALL
);
148 manual_install
= false;
150 void packagelist
::kd_hold() { setwant(PKG_WANT_HOLD
); }
151 void packagelist
::kd_deselect() { setwant(PKG_WANT_DEINSTALL
); }
152 void packagelist
::kd_unhold() { setwant(PKG_WANT_SENTINEL
); }
153 void packagelist
::kd_purge() { setwant(PKG_WANT_PURGE
); }
156 would_like_to_install(pkgwant wantvalue
, pkginfo
*pkg
)
158 /* Returns: 1 for yes, 0 for no, -1 for if they want to preserve an error condition. */
159 debug(dbg_general
, "would_like_to_install(%d, %s) status %d",
160 wantvalue
, pkg_name(pkg
, pnaw_always
), pkg
->status
);
162 if (wantvalue
== PKG_WANT_INSTALL
)
164 if (wantvalue
!= PKG_WANT_HOLD
)
166 if (pkg
->status
== PKG_STAT_INSTALLED
)
168 if (pkg
->status
== PKG_STAT_NOTINSTALLED
||
169 pkg
->status
== PKG_STAT_CONFIGFILES
)
174 const char *packagelist
::itemname(int index
) {
175 return table
[index
]->pkg
->set
->name
;
178 void packagelist
::kd_swapstatorder() {
179 if (sortorder
== so_unsorted
) return;
180 switch (statsortorder
) {
181 case sso_avail
: statsortorder
= sso_state
; break;
182 case sso_state
: statsortorder
= sso_unsorted
; break;
183 case sso_unsorted
: statsortorder
= sso_avail
; break;
185 internerr("unknown statsort %d", statsortorder
);
190 void packagelist
::kd_swaporder() {
192 case so_priority
: sortorder
= so_section
; break;
193 case so_section
: sortorder
= so_alpha
; break;
194 case so_alpha
: sortorder
= so_priority
; break;
195 case so_unsorted
: return;
197 internerr("unknown sort %d", sortorder
);
202 void packagelist
::resortredisplay() {
203 const char *oldname
= table
[cursorline
]->pkg
->set
->name
;
209 for (index
=0; index
<nitems
; index
++) {
210 if (table
[index
]->pkg
->set
->name
&&
211 strcasecmp(oldname
, table
[index
]->pkg
->set
->name
) == 0) {
217 topofscreen
= newcursor
-1;
218 if (topofscreen
> nitems
- list_height
) topofscreen
= nitems
-list_height
;
219 if (topofscreen
< 0) topofscreen
= 0;
223 ldrawnstart
= ldrawnend
= -1;
225 setcursor(newcursor
);
230 packagelist
::kd_archdisplay()
232 switch (archdisplayopt
) {
234 archdisplayopt
= ado_none
;
237 archdisplayopt
= ado_available
;
240 archdisplayopt
= ado_both
;
243 internerr("unknown archdisplayopt %d", archdisplayopt
);
247 ldrawnstart
= ldrawnend
= -1;
250 redrawitemsrange(topofscreen
, min(topofscreen
+ list_height
, nitems
));
254 void packagelist
::kd_versiondisplay() {
255 switch (versiondisplayopt
) {
256 case vdo_both
: versiondisplayopt
= vdo_none
; break;
257 case vdo_none
: versiondisplayopt
= vdo_available
; break;
258 case vdo_available
: versiondisplayopt
= vdo_both
; break;
260 internerr("unknown versiondisplayopt %d", versiondisplayopt
);
264 ldrawnstart
= ldrawnend
= -1;
267 redrawitemsrange(topofscreen
, min(topofscreen
+ list_height
, nitems
));
271 void packagelist
::kd_verbose() {
275 ldrawnstart
= ldrawnend
= -1;
278 redrawitemsrange(topofscreen
, min(topofscreen
+ list_height
, nitems
));
282 void packagelist
::kd_quit_noop() { }
284 void packagelist
::kd_revert_abort() {
286 for (index
=0; index
<nitems
; index
++) {
287 if (table
[index
]->pkg
->set
->name
)
288 table
[index
]->selected
= table
[index
]->original
;
289 ldrawnstart
= ldrawnend
= -1;
291 refreshlist(); redrawthisstate();
294 void packagelist
::kd_revertdirect() {
296 for (index
=0; index
<nitems
; index
++) {
297 if (table
[index
]->pkg
->set
->name
)
298 table
[index
]->selected
= table
[index
]->direct
;
299 ldrawnstart
= ldrawnend
= -1;
301 refreshlist(); redrawthisstate();
304 void packagelist
::kd_revertsuggest() {
306 for (index
=0; index
<nitems
; index
++) {
307 if (table
[index
]->pkg
->set
->name
)
308 table
[index
]->selected
= table
[index
]->suggested
;
309 ldrawnstart
= ldrawnend
= -1;
311 refreshlist(); redrawthisstate();
315 packagelist
::kd_revertinstalled()
319 for (i
= 0; i
< nitems
; i
++) {
320 if (table
[i
]->pkg
->set
->name
)
321 table
[i
]->selected
= reallywant(PKG_WANT_SENTINEL
, table
[i
]);
322 ldrawnstart
= ldrawnend
= -1;
329 /* FIXME: configurable purge/deselect */
331 void packagelist
::kd_toggleinfo() {
332 showinfo
= (showinfo
+2) % 3;
334 if (cursorline
>= topofscreen
+list_height
) topofscreen
+= list_height
;
335 if (topofscreen
> nitems
- list_height
) topofscreen
= nitems
-list_height
;
336 if (topofscreen
< 0) topofscreen
= 0;
338 redraw1item(cursorline
);
344 void packagelist
::kd_info() {
346 showinfo
= 2; kd_toggleinfo();