test: Quote command variables in case these contain spaces
[dpkg.git] / dselect / bindings.cc
blobfe65c451b8d2726aa6a4830d9c87f2530b0d08fd
1 /*
2 * dselect - Debian package maintenance user interface
3 * bindings.cc - keybinding manager object definitions and default bindings
5 * Copyright © 1995 Ian Jackson <ijackson@chiark.greenend.org.uk>
7 * This is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 #include <config.h>
22 #include <compat.h>
24 #include <string.h>
25 #include <stdio.h>
27 #include <dpkg/i18n.h>
28 #include <dpkg/dpkg.h>
29 #include <dpkg/dpkg-db.h>
31 #include "dselect.h"
32 #include "bindings.h"
34 keybindings::keybindings(const interpretation *ints, const orgbinding *orgbindings) {
35 interps= ints;
36 bindings = nullptr;
37 const orgbinding *b= orgbindings;
38 while (b->action) { bind(b->key,b->action); b++; }
39 describestart();
42 bool
43 keybindings::bind(int key, const char *action)
45 if (key == -1)
46 return false;
48 const interpretation *interp = interps;
49 while (interp->action && strcmp(interp->action, action))
50 interp++;
51 if (!interp->action)
52 return false;
54 const description *desc = descriptions;
55 while (desc->action && strcmp(desc->action, action))
56 desc++;
58 binding *b = bindings;
59 while (b && b->key != key)
60 b = b->next;
62 if (!b) {
63 b = new binding;
64 b->key = key;
65 b->next = bindings;
66 bindings = b;
68 b->interp = interp;
69 b->desc = desc->desc;
71 return true;
74 const char *keybindings::find(const char *action) {
75 binding *b = bindings;
76 while (b && strcmp(action, b->interp->action))
77 b = b->next;
78 if (!b) return _("[not bound]");
79 const char *n= key2name(b->key);
80 if (n) return n;
81 static char buf[50];
82 sprintf(buf,_("[unk: %d]"),b->key);
83 return buf;
86 const keybindings::interpretation *keybindings::operator()(int key) {
87 binding *b = bindings;
88 while (b && b->key != key)
89 b = b->next;
90 if (!b)
91 return nullptr;
92 return b->interp;
95 const char **keybindings::describenext() {
96 binding *search;
97 int count;
98 for (;;) {
99 if (!iterate->action)
100 return nullptr;
101 for (count=0, search=bindings; search; search=search->next)
102 if (strcmp(search->interp->action, iterate->action) == 0)
103 count++;
104 if (count) break;
105 iterate++;
107 const char **retarray= new const char *[count+2];
108 retarray[0]= iterate->desc;
109 for (count=1, search=bindings; search; search=search->next)
110 if (strcmp(search->interp->action, iterate->action) == 0)
111 retarray[count++]= key2name(search->key);
112 retarray[count] = nullptr;
113 iterate++;
114 return retarray;
117 const char *keybindings::key2name(int key) {
118 const keyname *search = keynames;
119 while (search->key != -1 && search->key != key)
120 search++;
121 return search->kname;
124 int keybindings::name2key(const char *name) {
125 const keyname *search = keynames;
126 while (search->kname && strcasecmp(search->kname, name))
127 search++;
128 return search->key;
131 keybindings::~keybindings() {
132 binding *search, *next;
133 for (search=bindings; search; search=next) {
134 next= search->next;
135 delete search;
139 const keybindings::description keybindings::descriptions[]= {
140 // Actions which apply to both types of list.
141 { "iscrollon", N_("Scroll onwards through help/information") },
142 { "iscrollback", N_("Scroll backwards through help/information") },
143 { "up", N_("Move up") },
144 { "down", N_("Move down") },
145 { "top", N_("Go to top of list") },
146 { "bottom", N_("Go to end of list") },
147 { "help", N_("Request help (cycle through help screens)") },
148 { "info", N_("Cycle through information displays") },
149 { "redraw", N_("Redraw display") },
150 { "scrollon1", N_("Scroll onwards through list by 1 line") },
151 { "scrollback1", N_("Scroll backwards through list by 1 line") },
152 { "iscrollon1", N_("Scroll onwards through help/information by 1 line") },
153 { "iscrollback1", N_("Scroll backwards through help/information by 1 line") },
154 { "scrollon", N_("Scroll onwards through list") },
155 { "scrollback", N_("Scroll backwards through list") },
157 // Actions which apply only to lists of packages.
158 { "install", N_("Mark package(s) for installation") },
159 { "remove", N_("Mark package(s) for deinstallation") },
160 { "purge", N_("Mark package(s) for deinstall and purge") },
161 { "morespecific", N_("Make highlight more specific") },
162 { "lessspecific", N_("Make highlight less specific") },
163 { "search", N_("Search for a package whose name contains a string") },
164 { "searchagain", N_("Repeat last search") },
165 { "swaporder", N_("Swap sort order priority/section") },
166 { "quitcheck", N_("Quit, confirming, and checking dependencies") },
167 { "quitnocheck", N_("Quit, confirming without check") },
168 { "quitrejectsug", N_("Quit, rejecting conflict/dependency suggestions") },
169 { "abortnocheck", N_("Abort - quit without making changes") },
170 { "revert", N_("Revert to old state for all packages") },
171 { "revertsuggest", N_("Revert to suggested state for all packages") },
172 { "revertdirect", N_("Revert to directly requested state for all packages") },
173 { "revertinstalled", N_("Revert to currently installed state for all packages") },
175 // Actions which apply only to lists of methods.
176 { "select-and-quit", N_("Select currently-highlighted access method") },
177 { "abort", N_("Quit without changing selected access method") },
178 { nullptr, nullptr }