tui-regs.c revision 1.12 1 1.1 christos /* TUI display registers in window.
2 1.1 christos
3 1.11 christos Copyright (C) 1998-2024 Free Software Foundation, Inc.
4 1.1 christos
5 1.1 christos Contributed by Hewlett-Packard Company.
6 1.1 christos
7 1.1 christos This file is part of GDB.
8 1.1 christos
9 1.1 christos This program is free software; you can redistribute it and/or modify
10 1.1 christos it under the terms of the GNU General Public License as published by
11 1.1 christos the Free Software Foundation; either version 3 of the License, or
12 1.1 christos (at your option) any later version.
13 1.1 christos
14 1.1 christos This program is distributed in the hope that it will be useful,
15 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
16 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 1.1 christos GNU General Public License for more details.
18 1.1 christos
19 1.1 christos You should have received a copy of the GNU General Public License
20 1.1 christos along with this program. If not, see <http://www.gnu.org/licenses/>. */
21 1.1 christos
22 1.1 christos #include "arch-utils.h"
23 1.1 christos #include "tui/tui.h"
24 1.1 christos #include "symtab.h"
25 1.12 christos #include "cli/cli-style.h"
26 1.1 christos #include "frame.h"
27 1.1 christos #include "regcache.h"
28 1.1 christos #include "inferior.h"
29 1.1 christos #include "target.h"
30 1.1 christos #include "tui/tui-layout.h"
31 1.1 christos #include "tui/tui-win.h"
32 1.1 christos #include "tui/tui-wingeneral.h"
33 1.1 christos #include "tui/tui-regs.h"
34 1.1 christos #include "reggroups.h"
35 1.5 christos #include "completer.h"
36 1.1 christos
37 1.1 christos #include "gdb_curses.h"
38 1.1 christos
39 1.9 christos /* A subclass of string_file that expands tab characters. */
40 1.9 christos class tab_expansion_file : public string_file
41 1.9 christos {
42 1.9 christos public:
43 1.1 christos
44 1.9 christos tab_expansion_file () = default;
45 1.1 christos
46 1.9 christos void write (const char *buf, long length_buf) override;
47 1.1 christos
48 1.9 christos private:
49 1.1 christos
50 1.9 christos int m_column = 0;
51 1.9 christos };
52 1.1 christos
53 1.9 christos void
54 1.9 christos tab_expansion_file::write (const char *buf, long length_buf)
55 1.9 christos {
56 1.9 christos for (long i = 0; i < length_buf; ++i)
57 1.9 christos {
58 1.9 christos if (buf[i] == '\t')
59 1.9 christos {
60 1.9 christos do
61 1.9 christos {
62 1.9 christos string_file::write (" ", 1);
63 1.9 christos ++m_column;
64 1.9 christos }
65 1.9 christos while ((m_column % 8) != 0);
66 1.9 christos }
67 1.9 christos else
68 1.9 christos {
69 1.9 christos string_file::write (&buf[i], 1);
70 1.9 christos if (buf[i] == '\n')
71 1.9 christos m_column = 0;
72 1.9 christos else
73 1.9 christos ++m_column;
74 1.9 christos }
75 1.9 christos }
76 1.9 christos }
77 1.1 christos
78 1.9 christos /* Get the register from the frame and return a printable
79 1.9 christos representation of it. */
80 1.1 christos
81 1.9 christos static std::string
82 1.11 christos tui_register_format (const frame_info_ptr &frame, int regnum)
83 1.1 christos {
84 1.9 christos struct gdbarch *gdbarch = get_frame_arch (frame);
85 1.9 christos
86 1.9 christos /* Expand tabs into spaces, since ncurses on MS-Windows doesn't. */
87 1.9 christos tab_expansion_file stream;
88 1.9 christos gdbarch_print_registers_info (gdbarch, &stream, frame, regnum, 1);
89 1.1 christos
90 1.9 christos /* Remove the possible \n. */
91 1.10 christos std::string str = stream.release ();
92 1.9 christos if (!str.empty () && str.back () == '\n')
93 1.11 christos str.pop_back ();
94 1.9 christos
95 1.9 christos return str;
96 1.9 christos }
97 1.9 christos
98 1.11 christos /* Compute the register value from the given frame and format it for
99 1.12 christos the display. Update 'content' and set 'm_highlight' if the
100 1.12 christos contents changed. */
101 1.11 christos void
102 1.11 christos tui_register_info::update (const frame_info_ptr &frame)
103 1.11 christos {
104 1.11 christos std::string new_content = tui_register_format (frame, m_regno);
105 1.12 christos m_highlight = content != new_content;
106 1.11 christos content = std::move (new_content);
107 1.9 christos }
108 1.9 christos
109 1.9 christos /* See tui-regs.h. */
110 1.9 christos
111 1.9 christos int
112 1.9 christos tui_data_window::last_regs_line_no () const
113 1.9 christos {
114 1.9 christos int num_lines = m_regs_content.size () / m_regs_column_count;
115 1.9 christos if (m_regs_content.size () % m_regs_column_count)
116 1.9 christos num_lines++;
117 1.1 christos return num_lines;
118 1.1 christos }
119 1.1 christos
120 1.9 christos /* See tui-regs.h. */
121 1.1 christos
122 1.1 christos int
123 1.9 christos tui_data_window::line_from_reg_element_no (int element_no) const
124 1.1 christos {
125 1.9 christos if (element_no < m_regs_content.size ())
126 1.1 christos {
127 1.1 christos int i, line = (-1);
128 1.1 christos
129 1.1 christos i = 1;
130 1.1 christos while (line == (-1))
131 1.1 christos {
132 1.9 christos if (element_no < m_regs_column_count * i)
133 1.1 christos line = i - 1;
134 1.1 christos else
135 1.1 christos i++;
136 1.1 christos }
137 1.1 christos
138 1.1 christos return line;
139 1.1 christos }
140 1.1 christos else
141 1.1 christos return (-1);
142 1.1 christos }
143 1.1 christos
144 1.9 christos /* See tui-regs.h. */
145 1.1 christos
146 1.1 christos int
147 1.9 christos tui_data_window::first_reg_element_no_inline (int line_no) const
148 1.1 christos {
149 1.9 christos if (line_no * m_regs_column_count <= m_regs_content.size ())
150 1.9 christos return ((line_no + 1) * m_regs_column_count) - m_regs_column_count;
151 1.1 christos else
152 1.1 christos return (-1);
153 1.1 christos }
154 1.1 christos
155 1.12 christos /* See tui-regs.h. */
156 1.12 christos
157 1.1 christos void
158 1.11 christos tui_data_window::set_register_group (const reggroup *group)
159 1.1 christos {
160 1.11 christos update_register_data (group);
161 1.9 christos rerender ();
162 1.1 christos }
163 1.1 christos
164 1.1 christos /* Set the data window to display the registers of the register group
165 1.11 christos using the given frame. */
166 1.1 christos
167 1.9 christos void
168 1.11 christos tui_data_window::update_register_data (const reggroup *group)
169 1.1 christos {
170 1.11 christos if (!target_has_registers ()
171 1.11 christos || !target_has_stack ()
172 1.11 christos || !target_has_memory ())
173 1.11 christos {
174 1.11 christos set_title (_("Registers"));
175 1.11 christos m_current_group = nullptr;
176 1.11 christos m_gdbarch = nullptr;
177 1.11 christos m_regs_content.clear ();
178 1.11 christos return;
179 1.11 christos }
180 1.11 christos
181 1.12 christos if (group == nullptr)
182 1.12 christos group = general_reggroup;
183 1.12 christos
184 1.11 christos frame_info_ptr frame = get_selected_frame (nullptr);
185 1.1 christos struct gdbarch *gdbarch = get_frame_arch (frame);
186 1.1 christos
187 1.11 christos if (m_current_group == group && m_gdbarch == gdbarch)
188 1.1 christos {
189 1.11 christos /* Nothing to do here. */
190 1.11 christos return;
191 1.11 christos }
192 1.1 christos
193 1.11 christos m_current_group = group;
194 1.11 christos m_gdbarch = gdbarch;
195 1.1 christos
196 1.11 christos /* Make a new title showing which group we display. */
197 1.11 christos this->set_title (string_printf ("Register group: %s", group->name ()));
198 1.1 christos
199 1.11 christos /* Create the registers. */
200 1.11 christos m_regs_content.clear ();
201 1.9 christos
202 1.11 christos for (int regnum = 0;
203 1.11 christos regnum < gdbarch_num_cooked_regs (gdbarch);
204 1.11 christos regnum++)
205 1.1 christos {
206 1.9 christos /* Must be in the group. */
207 1.9 christos if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
208 1.9 christos continue;
209 1.9 christos
210 1.9 christos /* If the register name is empty, it is undefined for this
211 1.9 christos processor, so don't display anything. */
212 1.11 christos const char *name = gdbarch_register_name (gdbarch, regnum);
213 1.10 christos if (*name == '\0')
214 1.9 christos continue;
215 1.9 christos
216 1.11 christos m_regs_content.emplace_back (regnum, frame);
217 1.1 christos }
218 1.9 christos }
219 1.9 christos
220 1.9 christos /* See tui-regs.h. */
221 1.1 christos
222 1.9 christos void
223 1.9 christos tui_data_window::display_registers_from (int start_element_no)
224 1.9 christos {
225 1.11 christos werase (handle.get ());
226 1.11 christos check_and_display_highlight_if_needed ();
227 1.11 christos
228 1.11 christos /* In case the regs window is not boxed, we'll write the last char in the
229 1.11 christos last line here, causing a scroll, so prevent that. */
230 1.11 christos scrollok (handle.get (), FALSE);
231 1.11 christos
232 1.9 christos int max_len = 0;
233 1.9 christos for (auto &&data_item_win : m_regs_content)
234 1.1 christos {
235 1.9 christos int len = data_item_win.content.size ();
236 1.9 christos
237 1.9 christos if (len > max_len)
238 1.9 christos max_len = len;
239 1.1 christos }
240 1.9 christos m_item_width = max_len + 1;
241 1.10 christos
242 1.10 christos int i;
243 1.10 christos /* Mark register windows above the visible area. */
244 1.10 christos for (i = 0; i < start_element_no; i++)
245 1.10 christos m_regs_content[i].y = 0;
246 1.1 christos
247 1.11 christos m_regs_column_count = (width - box_size ()) / m_item_width;
248 1.9 christos if (m_regs_column_count == 0)
249 1.9 christos m_regs_column_count = 1;
250 1.11 christos m_item_width = (width - box_size ()) / m_regs_column_count;
251 1.9 christos
252 1.9 christos /* Now create each data "sub" window, and write the display into
253 1.9 christos it. */
254 1.11 christos int cur_y = box_width ();
255 1.11 christos while (i < m_regs_content.size () && cur_y <= height - box_size ())
256 1.1 christos {
257 1.9 christos for (int j = 0;
258 1.9 christos j < m_regs_column_count && i < m_regs_content.size ();
259 1.9 christos j++)
260 1.1 christos {
261 1.9 christos /* Create the window if necessary. */
262 1.11 christos m_regs_content[i].x = box_width () + (m_item_width * j);
263 1.9 christos m_regs_content[i].y = cur_y;
264 1.9 christos m_regs_content[i].rerender (handle.get (), m_item_width);
265 1.9 christos i++; /* Next register. */
266 1.1 christos }
267 1.9 christos cur_y++; /* Next row. */
268 1.9 christos }
269 1.10 christos
270 1.10 christos /* Mark register windows below the visible area. */
271 1.10 christos for (; i < m_regs_content.size (); i++)
272 1.10 christos m_regs_content[i].y = 0;
273 1.9 christos }
274 1.1 christos
275 1.9 christos /* See tui-regs.h. */
276 1.9 christos
277 1.9 christos void
278 1.9 christos tui_data_window::display_reg_element_at_line (int start_element_no,
279 1.9 christos int start_line_no)
280 1.9 christos {
281 1.9 christos int element_no = start_element_no;
282 1.9 christos
283 1.9 christos if (start_element_no != 0 && start_line_no != 0)
284 1.9 christos {
285 1.9 christos int last_line_no, first_line_on_last_page;
286 1.1 christos
287 1.9 christos last_line_no = last_regs_line_no ();
288 1.11 christos first_line_on_last_page = last_line_no - (height - box_size ());
289 1.9 christos if (first_line_on_last_page < 0)
290 1.9 christos first_line_on_last_page = 0;
291 1.1 christos
292 1.9 christos /* If the element_no causes us to scroll past the end of the
293 1.9 christos registers, adjust what element to really start the
294 1.9 christos display at. */
295 1.9 christos if (start_line_no > first_line_on_last_page)
296 1.9 christos element_no = first_reg_element_no_inline (first_line_on_last_page);
297 1.1 christos }
298 1.9 christos display_registers_from (element_no);
299 1.1 christos }
300 1.1 christos
301 1.9 christos /* See tui-regs.h. */
302 1.1 christos
303 1.9 christos int
304 1.9 christos tui_data_window::display_registers_from_line (int line_no)
305 1.1 christos {
306 1.9 christos int element_no;
307 1.9 christos
308 1.9 christos if (line_no < 0)
309 1.9 christos line_no = 0;
310 1.9 christos else
311 1.1 christos {
312 1.9 christos /* Make sure that we don't display off the end of the
313 1.9 christos registers. */
314 1.9 christos if (line_no >= last_regs_line_no ())
315 1.9 christos {
316 1.9 christos line_no = line_from_reg_element_no (m_regs_content.size () - 1);
317 1.9 christos if (line_no < 0)
318 1.9 christos line_no = 0;
319 1.9 christos }
320 1.9 christos }
321 1.9 christos
322 1.9 christos element_no = first_reg_element_no_inline (line_no);
323 1.9 christos if (element_no < m_regs_content.size ())
324 1.9 christos display_reg_element_at_line (element_no, line_no);
325 1.9 christos else
326 1.9 christos line_no = (-1);
327 1.9 christos
328 1.9 christos return line_no;
329 1.9 christos }
330 1.1 christos
331 1.1 christos
332 1.9 christos /* Answer the index first element displayed. If none are displayed,
333 1.9 christos then return (-1). */
334 1.9 christos int
335 1.9 christos tui_data_window::first_data_item_displayed ()
336 1.9 christos {
337 1.9 christos for (int i = 0; i < m_regs_content.size (); i++)
338 1.9 christos {
339 1.11 christos if (m_regs_content[i].visible ())
340 1.9 christos return i;
341 1.1 christos }
342 1.9 christos
343 1.9 christos return -1;
344 1.1 christos }
345 1.1 christos
346 1.9 christos void
347 1.11 christos tui_data_window::erase_data_content ()
348 1.9 christos {
349 1.11 christos center_string (_("[ Register Values Unavailable ]"));
350 1.9 christos }
351 1.9 christos
352 1.9 christos /* See tui-regs.h. */
353 1.1 christos
354 1.9 christos void
355 1.9 christos tui_data_window::rerender ()
356 1.9 christos {
357 1.9 christos if (m_regs_content.empty ())
358 1.11 christos erase_data_content ();
359 1.9 christos else
360 1.11 christos display_registers_from (0);
361 1.12 christos refresh_window ();
362 1.9 christos }
363 1.9 christos
364 1.9 christos
365 1.9 christos /* Scroll the data window vertically forward or backward. */
366 1.9 christos void
367 1.9 christos tui_data_window::do_scroll_vertical (int num_to_scroll)
368 1.9 christos {
369 1.9 christos int first_element_no;
370 1.9 christos int first_line = (-1);
371 1.1 christos
372 1.9 christos first_element_no = first_data_item_displayed ();
373 1.9 christos if (first_element_no < m_regs_content.size ())
374 1.9 christos first_line = line_from_reg_element_no (first_element_no);
375 1.9 christos else
376 1.9 christos { /* Calculate the first line from the element number which is in
377 1.10 christos the general data content. */
378 1.1 christos }
379 1.1 christos
380 1.9 christos if (first_line >= 0)
381 1.9 christos {
382 1.9 christos first_line += num_to_scroll;
383 1.9 christos display_registers_from_line (first_line);
384 1.12 christos refresh_window ();
385 1.9 christos }
386 1.1 christos }
387 1.1 christos
388 1.1 christos /* This function check all displayed registers for changes in values,
389 1.1 christos given a particular frame. If the values have changed, they are
390 1.1 christos updated with the new value and highlighted. */
391 1.1 christos void
392 1.11 christos tui_data_window::check_register_values (const frame_info_ptr &frame)
393 1.1 christos {
394 1.12 christos /* If the frame architecture changed, we need to reset the register
395 1.12 christos group. */
396 1.12 christos if (frame == nullptr || get_frame_arch (frame) != m_gdbarch)
397 1.11 christos set_register_group (nullptr);
398 1.9 christos else
399 1.1 christos {
400 1.12 christos for (tui_register_info &data_item_win : m_regs_content)
401 1.9 christos {
402 1.12 christos bool was_hilighted = data_item_win.highlighted ();
403 1.9 christos
404 1.12 christos data_item_win.update (frame);
405 1.1 christos
406 1.12 christos if ((data_item_win.highlighted () || was_hilighted)
407 1.12 christos && data_item_win.visible ())
408 1.12 christos data_item_win.rerender (handle.get (), m_item_width);
409 1.1 christos }
410 1.12 christos refresh_window ();
411 1.1 christos }
412 1.1 christos }
413 1.1 christos
414 1.12 christos /* Display a register in a window. */
415 1.9 christos void
416 1.11 christos tui_register_info::rerender (WINDOW *handle, int field_width)
417 1.1 christos {
418 1.12 christos if (m_highlight)
419 1.9 christos /* We ignore the return value, casting it to void in order to avoid
420 1.9 christos a compiler warning. The warning itself was introduced by a patch
421 1.9 christos to ncurses 5.7 dated 2009-08-29, changing this macro to expand
422 1.9 christos to code that causes the compiler to generate an unused-value
423 1.9 christos warning. */
424 1.9 christos (void) wstandout (handle);
425 1.9 christos
426 1.9 christos mvwaddnstr (handle, y, x, content.c_str (), field_width - 1);
427 1.10 christos if (content.size () < field_width)
428 1.10 christos waddstr (handle, n_spaces (field_width - content.size ()));
429 1.1 christos
430 1.12 christos if (m_highlight)
431 1.9 christos /* We ignore the return value, casting it to void in order to avoid
432 1.9 christos a compiler warning. The warning itself was introduced by a patch
433 1.9 christos to ncurses 5.7 dated 2009-08-29, changing this macro to expand
434 1.9 christos to code that causes the compiler to generate an unused-value
435 1.9 christos warning. */
436 1.9 christos (void) wstandend (handle);
437 1.1 christos }
438 1.1 christos
439 1.10 christos /* Helper for "tui reg next", returns the next register group after
440 1.10 christos CURRENT_GROUP in the register group list for GDBARCH, with wrap around
441 1.12 christos behavior.
442 1.10 christos
443 1.10 christos If CURRENT_GROUP is nullptr (e.g. if the tui register window has only
444 1.10 christos just been displayed and has no current group selected) or the currently
445 1.10 christos selected register group can't be found (e.g. if the architecture has
446 1.10 christos changed since the register window was last updated), then the first
447 1.10 christos register group will be returned. */
448 1.10 christos
449 1.10 christos static const reggroup *
450 1.10 christos tui_reg_next (const reggroup *current_group, struct gdbarch *gdbarch)
451 1.10 christos {
452 1.10 christos const std::vector<const reggroup *> &groups = gdbarch_reggroups (gdbarch);
453 1.10 christos auto it = std::find (groups.begin (), groups.end (), current_group);
454 1.10 christos if (it != groups.end ())
455 1.10 christos it++;
456 1.10 christos if (it == groups.end ())
457 1.10 christos return groups.front ();
458 1.10 christos return *it;
459 1.10 christos }
460 1.10 christos
461 1.10 christos /* Helper for "tui reg prev", returns the register group previous to
462 1.10 christos CURRENT_GROUP in the register group list for GDBARCH, with wrap around
463 1.12 christos behavior.
464 1.10 christos
465 1.10 christos If CURRENT_GROUP is nullptr (e.g. if the tui register window has only
466 1.10 christos just been displayed and has no current group selected) or the currently
467 1.10 christos selected register group can't be found (e.g. if the architecture has
468 1.10 christos changed since the register window was last updated), then the last
469 1.10 christos register group will be returned. */
470 1.10 christos
471 1.10 christos static const reggroup *
472 1.10 christos tui_reg_prev (const reggroup *current_group, struct gdbarch *gdbarch)
473 1.10 christos {
474 1.10 christos const std::vector<const reggroup *> &groups = gdbarch_reggroups (gdbarch);
475 1.10 christos auto it = std::find (groups.rbegin (), groups.rend (), current_group);
476 1.10 christos if (it != groups.rend ())
477 1.10 christos it++;
478 1.10 christos if (it == groups.rend ())
479 1.10 christos return groups.back ();
480 1.10 christos return *it;
481 1.1 christos }
482 1.1 christos
483 1.5 christos /* Implement the 'tui reg' command. Changes the register group displayed
484 1.5 christos in the tui register window. Displays the tui register window if it is
485 1.5 christos not already on display. */
486 1.5 christos
487 1.1 christos static void
488 1.8 christos tui_reg_command (const char *args, int from_tty)
489 1.1 christos {
490 1.5 christos struct gdbarch *gdbarch = get_current_arch ();
491 1.5 christos
492 1.5 christos if (args != NULL)
493 1.5 christos {
494 1.5 christos size_t len = strlen (args);
495 1.5 christos
496 1.12 christos tui_batch_rendering suppress;
497 1.12 christos
498 1.5 christos /* Make sure the curses mode is enabled. */
499 1.5 christos tui_enable ();
500 1.5 christos
501 1.5 christos /* Make sure the register window is visible. If not, select an
502 1.5 christos appropriate layout. We need to do this before trying to run the
503 1.5 christos 'next' or 'prev' commands. */
504 1.12 christos if (tui_data_win () == nullptr || !tui_data_win ()->is_visible ())
505 1.9 christos tui_regs_layout ();
506 1.5 christos
507 1.10 christos const reggroup *match = nullptr;
508 1.12 christos const reggroup *current_group = tui_data_win ()->get_current_group ();
509 1.5 christos if (strncmp (args, "next", len) == 0)
510 1.9 christos match = tui_reg_next (current_group, gdbarch);
511 1.5 christos else if (strncmp (args, "prev", len) == 0)
512 1.9 christos match = tui_reg_prev (current_group, gdbarch);
513 1.10 christos else
514 1.5 christos {
515 1.10 christos /* This loop matches on the initial part of a register group
516 1.10 christos name. If this initial part in ARGS matches only one register
517 1.10 christos group then the switch is made. */
518 1.10 christos for (const struct reggroup *group : gdbarch_reggroups (gdbarch))
519 1.5 christos {
520 1.10 christos if (strncmp (group->name (), args, len) == 0)
521 1.10 christos {
522 1.10 christos if (match != NULL)
523 1.10 christos error (_("ambiguous register group name '%s'"), args);
524 1.10 christos match = group;
525 1.10 christos }
526 1.5 christos }
527 1.5 christos }
528 1.5 christos
529 1.5 christos if (match == NULL)
530 1.5 christos error (_("unknown register group '%s'"), args);
531 1.5 christos
532 1.12 christos tui_data_win ()->set_register_group (match);
533 1.5 christos }
534 1.5 christos else
535 1.5 christos {
536 1.12 christos gdb_printf (_("\"%ps\" must be followed by the name of "
537 1.10 christos "either a register group,\nor one of 'next' "
538 1.12 christos "or 'prev'. Known register groups are:\n"),
539 1.12 christos styled_string (command_style.style (), "tui reg"));
540 1.5 christos
541 1.10 christos bool first = true;
542 1.10 christos for (const struct reggroup *group : gdbarch_reggroups (gdbarch))
543 1.5 christos {
544 1.5 christos if (!first)
545 1.10 christos gdb_printf (", ");
546 1.10 christos first = false;
547 1.10 christos gdb_printf ("%s", group->name ());
548 1.5 christos }
549 1.5 christos
550 1.10 christos gdb_printf ("\n");
551 1.5 christos }
552 1.1 christos }
553 1.1 christos
554 1.5 christos /* Complete names of register groups, and add the special "prev" and "next"
555 1.5 christos names. */
556 1.5 christos
557 1.8 christos static void
558 1.5 christos tui_reggroup_completer (struct cmd_list_element *ignore,
559 1.8 christos completion_tracker &tracker,
560 1.5 christos const char *text, const char *word)
561 1.1 christos {
562 1.9 christos static const char * const extra[] = { "next", "prev", NULL };
563 1.5 christos
564 1.8 christos reggroup_completer (ignore, tracker, text, word);
565 1.1 christos
566 1.9 christos complete_on_enum (tracker, extra, text, word);
567 1.1 christos }
568 1.1 christos
569 1.9 christos void _initialize_tui_regs ();
570 1.1 christos void
571 1.9 christos _initialize_tui_regs ()
572 1.1 christos {
573 1.5 christos struct cmd_list_element **tuicmd, *cmd;
574 1.1 christos
575 1.1 christos tuicmd = tui_get_cmd_list ();
576 1.1 christos
577 1.5 christos cmd = add_cmd ("reg", class_tui, tui_reg_command, _("\
578 1.9 christos TUI command to control the register window.\n\
579 1.9 christos Usage: tui reg NAME\n\
580 1.9 christos NAME is the name of the register group to display"), tuicmd);
581 1.5 christos set_cmd_completer (cmd, tui_reggroup_completer);
582 1.1 christos }
583