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
);
123 packagelist
*sub
= new packagelist(bindings
, nullptr);
125 affectedrange(&top
,&bot
);
126 for (int index
= top
; index
< bot
; index
++) {
127 if (!table
[index
]->pkg
->set
->name
)
129 nw
= reallywant(nwarg
,table
[index
]);
130 if (table
[index
]->selected
== nw
||
131 (table
[index
]->selected
== PKG_WANT_PURGE
&&
132 nw
== PKG_WANT_DEINSTALL
))
134 sub
->add(table
[index
]->pkg
,nw
);
137 repeatedlydisplay(sub
,dp_may
,this);
138 for (int index
= top
; index
< bot
; index
++)
141 movecursorafter(bot
);
144 bool manual_install
= false;
146 void packagelist::kd_select() {
147 manual_install
= true;
148 setwant(PKG_WANT_INSTALL
);
149 manual_install
= false;
151 void packagelist::kd_hold() { setwant(PKG_WANT_HOLD
); }
152 void packagelist::kd_deselect() { setwant(PKG_WANT_DEINSTALL
); }
153 void packagelist::kd_unhold() { setwant(PKG_WANT_SENTINEL
); }
154 void packagelist::kd_purge() { setwant(PKG_WANT_PURGE
); }
157 would_like_to_install(pkgwant wantvalue
, pkginfo
*pkg
)
159 /* Returns: 1 for yes, 0 for no, -1 for if they want to preserve an error condition. */
160 debug(dbg_general
, "would_like_to_install(%d, %s) status %d",
161 wantvalue
, pkg_name(pkg
, pnaw_always
), pkg
->status
);
163 if (wantvalue
== PKG_WANT_INSTALL
)
165 if (wantvalue
!= PKG_WANT_HOLD
)
167 if (pkg
->status
== PKG_STAT_INSTALLED
)
169 if (pkg
->status
== PKG_STAT_NOTINSTALLED
||
170 pkg
->status
== PKG_STAT_CONFIGFILES
)
175 const char *packagelist::itemname(int index
) {
176 return table
[index
]->pkg
->set
->name
;
179 void packagelist::kd_swapstatorder() {
180 if (sortorder
== so_unsorted
) return;
181 switch (statsortorder
) {
182 case sso_avail
: statsortorder
= sso_state
; break;
183 case sso_state
: statsortorder
= sso_unsorted
; break;
184 case sso_unsorted
: statsortorder
= sso_avail
; break;
186 internerr("unknown statsort %d", statsortorder
);
191 void packagelist::kd_swaporder() {
193 case so_priority
: sortorder
= so_section
; break;
194 case so_section
: sortorder
= so_alpha
; break;
195 case so_alpha
: sortorder
= so_priority
; break;
196 case so_unsorted
: return;
198 internerr("unknown sort %d", sortorder
);
203 void packagelist::resortredisplay() {
204 const char *oldname
= table
[cursorline
]->pkg
->set
->name
;
210 for (index
=0; index
<nitems
; index
++) {
211 if (table
[index
]->pkg
->set
->name
&&
212 strcasecmp(oldname
, table
[index
]->pkg
->set
->name
) == 0) {
218 topofscreen
= newcursor
-1;
219 if (topofscreen
> nitems
- list_height
) topofscreen
= nitems
-list_height
;
220 if (topofscreen
< 0) topofscreen
= 0;
224 ldrawnstart
= ldrawnend
= -1;
226 setcursor(newcursor
);
231 packagelist::kd_archdisplay()
233 switch (archdisplayopt
) {
235 archdisplayopt
= ado_none
;
238 archdisplayopt
= ado_available
;
241 archdisplayopt
= ado_both
;
244 internerr("unknown archdisplayopt %d", archdisplayopt
);
248 ldrawnstart
= ldrawnend
= -1;
251 redrawitemsrange(topofscreen
, min(topofscreen
+ list_height
, nitems
));
255 void packagelist::kd_versiondisplay() {
256 switch (versiondisplayopt
) {
257 case vdo_both
: versiondisplayopt
= vdo_none
; break;
258 case vdo_none
: versiondisplayopt
= vdo_available
; break;
259 case vdo_available
: versiondisplayopt
= vdo_both
; break;
261 internerr("unknown versiondisplayopt %d", versiondisplayopt
);
265 ldrawnstart
= ldrawnend
= -1;
268 redrawitemsrange(topofscreen
, min(topofscreen
+ list_height
, nitems
));
272 void packagelist::kd_verbose() {
276 ldrawnstart
= ldrawnend
= -1;
279 redrawitemsrange(topofscreen
, min(topofscreen
+ list_height
, nitems
));
283 void packagelist::kd_quit_noop() { }
285 void packagelist::kd_revert_abort() {
287 for (index
=0; index
<nitems
; index
++) {
288 if (table
[index
]->pkg
->set
->name
)
289 table
[index
]->selected
= table
[index
]->original
;
290 ldrawnstart
= ldrawnend
= -1;
292 refreshlist(); redrawthisstate();
295 void packagelist::kd_revertdirect() {
297 for (index
=0; index
<nitems
; index
++) {
298 if (table
[index
]->pkg
->set
->name
)
299 table
[index
]->selected
= table
[index
]->direct
;
300 ldrawnstart
= ldrawnend
= -1;
302 refreshlist(); redrawthisstate();
305 void packagelist::kd_revertsuggest() {
307 for (index
=0; index
<nitems
; index
++) {
308 if (table
[index
]->pkg
->set
->name
)
309 table
[index
]->selected
= table
[index
]->suggested
;
310 ldrawnstart
= ldrawnend
= -1;
312 refreshlist(); redrawthisstate();
316 packagelist::kd_revertinstalled()
320 for (i
= 0; i
< nitems
; i
++) {
321 if (table
[i
]->pkg
->set
->name
)
322 table
[i
]->selected
= reallywant(PKG_WANT_SENTINEL
, table
[i
]);
323 ldrawnstart
= ldrawnend
= -1;
330 /* FIXME: configurable purge/deselect */
332 void packagelist::kd_toggleinfo() {
333 showinfo
= (showinfo
+2) % 3;
335 if (cursorline
>= topofscreen
+list_height
) topofscreen
+= list_height
;
336 if (topofscreen
> nitems
- list_height
) topofscreen
= nitems
-list_height
;
337 if (topofscreen
< 0) topofscreen
= 0;
339 redraw1item(cursorline
);
345 void packagelist::kd_info() {
347 showinfo
= 2; kd_toggleinfo();