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