Fix "layout reg" crash
[external/binutils.git] / gdb / tui / tui-regs.c
1 /* TUI display registers in window.
2
3    Copyright (C) 1998-2017 Free Software Foundation, Inc.
4
5    Contributed by Hewlett-Packard Company.
6
7    This file is part of GDB.
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
21
22 #include "defs.h"
23 #include "arch-utils.h"
24 #include "tui/tui.h"
25 #include "tui/tui-data.h"
26 #include "symtab.h"
27 #include "gdbtypes.h"
28 #include "gdbcmd.h"
29 #include "frame.h"
30 #include "regcache.h"
31 #include "inferior.h"
32 #include "target.h"
33 #include "tui/tui-layout.h"
34 #include "tui/tui-win.h"
35 #include "tui/tui-windata.h"
36 #include "tui/tui-wingeneral.h"
37 #include "tui/tui-file.h"
38 #include "tui/tui-regs.h"
39 #include "tui/tui-io.h"
40 #include "reggroups.h"
41 #include "valprint.h"
42 #include "completer.h"
43
44 #include "gdb_curses.h"
45
46
47 /*****************************************
48 ** STATIC LOCAL FUNCTIONS FORWARD DECLS    **
49 ******************************************/
50 static void
51 tui_display_register (struct tui_data_element *data,
52                       struct tui_gen_win_info *win_info);
53
54 static enum tui_status tui_show_register_group (struct reggroup *group,
55                                                 struct frame_info *frame,
56                                                 int refresh_values_only);
57
58 static enum tui_status tui_get_register (struct frame_info *frame,
59                                          struct tui_data_element *data,
60                                          int regnum, int *changedp);
61
62
63
64 /*****************************************
65 ** PUBLIC FUNCTIONS                     **
66 ******************************************/
67
68 /* Answer the number of the last line in the regs display.  If there
69    are no registers (-1) is returned.  */
70 int
71 tui_last_regs_line_no (void)
72 {
73   int num_lines = (-1);
74
75   if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
76     {
77       num_lines = (TUI_DATA_WIN->detail.data_display_info.regs_content_count /
78                   TUI_DATA_WIN->detail.data_display_info.regs_column_count);
79       if (TUI_DATA_WIN->detail.data_display_info.regs_content_count %
80           TUI_DATA_WIN->detail.data_display_info.regs_column_count)
81         num_lines++;
82     }
83   return num_lines;
84 }
85
86
87 /* Answer the line number that the register element at element_no is
88    on.  If element_no is greater than the number of register elements
89    there are, -1 is returned.  */
90 int
91 tui_line_from_reg_element_no (int element_no)
92 {
93   if (element_no < TUI_DATA_WIN->detail.data_display_info.regs_content_count)
94     {
95       int i, line = (-1);
96
97       i = 1;
98       while (line == (-1))
99         {
100           if (element_no <
101               (TUI_DATA_WIN->detail.data_display_info.regs_column_count * i))
102             line = i - 1;
103           else
104             i++;
105         }
106
107       return line;
108     }
109   else
110     return (-1);
111 }
112
113
114 /* Answer the index of the first element in line_no.  If line_no is
115    past the register area (-1) is returned.  */
116 int
117 tui_first_reg_element_no_inline (int line_no)
118 {
119   if ((line_no * TUI_DATA_WIN->detail.data_display_info.regs_column_count)
120       <= TUI_DATA_WIN->detail.data_display_info.regs_content_count)
121     return ((line_no + 1) *
122             TUI_DATA_WIN->detail.data_display_info.regs_column_count) -
123       TUI_DATA_WIN->detail.data_display_info.regs_column_count;
124   else
125     return (-1);
126 }
127
128
129 /* Show the registers of the given group in the data window
130    and refresh the window.  */
131 void
132 tui_show_registers (struct reggroup *group)
133 {
134   enum tui_status ret = TUI_FAILURE;
135   struct tui_data_info *display_info;
136
137   /* Make sure the curses mode is enabled.  */
138   tui_enable ();
139
140   /* Make sure the register window is visible.  If not, select an
141      appropriate layout.  */
142   if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->generic.is_visible)
143     tui_set_layout_by_name (DATA_NAME);
144
145   display_info = &TUI_DATA_WIN->detail.data_display_info;
146   if (group == 0)
147     group = general_reggroup;
148
149   /* Say that registers should be displayed, even if there is a
150      problem.  */
151   display_info->display_regs = TRUE;
152
153   if (target_has_registers && target_has_stack && target_has_memory)
154     {
155       ret = tui_show_register_group (group, get_selected_frame (NULL),
156                                      group == display_info->current_group);
157     }
158   if (ret == TUI_FAILURE)
159     {
160       display_info->current_group = 0;
161       tui_erase_data_content (NO_REGS_STRING);
162     }
163   else
164     {
165       int i;
166
167       /* Clear all notation of changed values.  */
168       for (i = 0; i < display_info->regs_content_count; i++)
169         {
170           struct tui_gen_win_info *data_item_win;
171           struct tui_win_element *win;
172
173           data_item_win = &display_info->regs_content[i]
174             ->which_element.data_window;
175           win = data_item_win->content[0];
176           win->which_element.data.highlight = FALSE;
177         }
178       display_info->current_group = group;
179       tui_display_all_data ();
180     }
181 }
182
183
184 /* Set the data window to display the registers of the register group
185    using the given frame.  Values are refreshed only when
186    refresh_values_only is TRUE.  */
187
188 static enum tui_status
189 tui_show_register_group (struct reggroup *group,
190                          struct frame_info *frame, 
191                          int refresh_values_only)
192 {
193   struct gdbarch *gdbarch = get_frame_arch (frame);
194   enum tui_status ret = TUI_FAILURE;
195   int nr_regs;
196   int allocated_here = FALSE;
197   int regnum, pos;
198   char title[80];
199   struct tui_data_info *display_info = &TUI_DATA_WIN->detail.data_display_info;
200
201   /* Make a new title showing which group we display.  */
202   snprintf (title, sizeof (title) - 1, "Register group: %s",
203             reggroup_name (group));
204   xfree (TUI_DATA_WIN->generic.title);
205   TUI_DATA_WIN->generic.title = xstrdup (title);
206
207   /* See how many registers must be displayed.  */
208   nr_regs = 0;
209   for (regnum = 0;
210        regnum < gdbarch_num_regs (gdbarch)
211                 + gdbarch_num_pseudo_regs (gdbarch);
212        regnum++)
213     {
214       const char *name;
215
216       /* Must be in the group.  */
217       if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
218         continue;
219
220       /* If the register name is empty, it is undefined for this
221          processor, so don't display anything.  */
222       name = gdbarch_register_name (gdbarch, regnum);
223       if (name == 0 || *name == '\0')
224         continue;
225
226       nr_regs++;
227     }
228
229   if (display_info->regs_content_count > 0 && !refresh_values_only)
230     {
231       tui_free_data_content (display_info->regs_content,
232                              display_info->regs_content_count);
233       display_info->regs_content_count = 0;
234     }
235
236   if (display_info->regs_content_count <= 0)
237     {
238       display_info->regs_content = tui_alloc_content (nr_regs, DATA_WIN);
239       allocated_here = TRUE;
240       refresh_values_only = FALSE;
241     }
242
243   if (display_info->regs_content != (tui_win_content) NULL)
244     {
245       if (!refresh_values_only || allocated_here)
246         {
247           TUI_DATA_WIN->generic.content = NULL;
248           TUI_DATA_WIN->generic.content_size = 0;
249           tui_add_content_elements (&TUI_DATA_WIN->generic, nr_regs);
250           display_info->regs_content
251             = (tui_win_content) TUI_DATA_WIN->generic.content;
252           display_info->regs_content_count = nr_regs;
253         }
254
255       /* Now set the register names and values.  */
256       pos = 0;
257       for (regnum = 0;
258            regnum < gdbarch_num_regs (gdbarch)
259                     + gdbarch_num_pseudo_regs (gdbarch);
260            regnum++)
261         {
262           struct tui_gen_win_info *data_item_win;
263           struct tui_data_element *data;
264           const char *name;
265
266           /* Must be in the group.  */
267           if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
268             continue;
269
270           /* If the register name is empty, it is undefined for this
271              processor, so don't display anything.  */
272           name = gdbarch_register_name (gdbarch, regnum);
273           if (name == 0 || *name == '\0')
274             continue;
275
276           data_item_win =
277             &display_info->regs_content[pos]->which_element.data_window;
278           data = &data_item_win->content[0]->which_element.data;
279           if (data)
280             {
281               if (!refresh_values_only)
282                 {
283                   data->item_no = regnum;
284                   data->name = name;
285                   data->highlight = FALSE;
286                 }
287               tui_get_register (frame, data, regnum, 0);
288             }
289           pos++;
290         }
291
292       TUI_DATA_WIN->generic.content_size =
293         display_info->regs_content_count + display_info->data_content_count;
294       ret = TUI_SUCCESS;
295     }
296
297   return ret;
298 }
299
300 /* Function to display the registers in the content from
301    'start_element_no' until the end of the register content or the end
302    of the display height.  No checking for displaying past the end of
303    the registers is done here.  */
304 void
305 tui_display_registers_from (int start_element_no)
306 {
307   struct tui_data_info *display_info = &TUI_DATA_WIN->detail.data_display_info;
308
309   if (display_info->regs_content != (tui_win_content) NULL 
310       && display_info->regs_content_count > 0)
311     {
312       int i = start_element_no;
313       int j, item_win_width, cur_y;
314
315       int max_len = 0;
316       for (i = 0; i < display_info->regs_content_count; i++)
317         {
318           struct tui_data_element *data;
319           struct tui_gen_win_info *data_item_win;
320           char *p;
321           int len;
322
323           data_item_win
324             = &display_info->regs_content[i]->which_element.data_window;
325           data = &data_item_win->content[0]->which_element.data;
326           len = 0;
327           p = data->content;
328           if (p != 0)
329             while (*p)
330               {
331                 if (*p++ == '\t')
332                   len = 8 * ((len / 8) + 1);
333                 else
334                   len++;
335               }
336
337           if (len > max_len)
338             max_len = len;
339         }
340       item_win_width = max_len + 1;
341       i = start_element_no;
342
343       display_info->regs_column_count =
344         (TUI_DATA_WIN->generic.width - 2) / item_win_width;
345       if (display_info->regs_column_count == 0)
346         display_info->regs_column_count = 1;
347       item_win_width =
348         (TUI_DATA_WIN->generic.width - 2) / display_info->regs_column_count;
349
350       /* Now create each data "sub" window, and write the display into
351          it.  */
352       cur_y = 1;
353       while (i < display_info->regs_content_count 
354              && cur_y <= TUI_DATA_WIN->generic.viewport_height)
355         {
356           for (j = 0;
357                j < display_info->regs_column_count
358                  && i < display_info->regs_content_count;
359                j++)
360             {
361               struct tui_gen_win_info *data_item_win;
362               struct tui_data_element *data_element_ptr;
363
364               /* Create the window if necessary.  */
365               data_item_win = &display_info->regs_content[i]
366                 ->which_element.data_window;
367               data_element_ptr = &data_item_win->content[0]->which_element.data;
368               if (data_item_win->handle != (WINDOW*) NULL
369                   && (data_item_win->height != 1
370                       || data_item_win->width != item_win_width
371                       || data_item_win->origin.x != (item_win_width * j) + 1
372                       || data_item_win->origin.y != cur_y))
373                 {
374                   tui_delete_win (data_item_win->handle);
375                   data_item_win->handle = 0;
376                 }
377                   
378               if (data_item_win->handle == (WINDOW *) NULL)
379                 {
380                   data_item_win->height = 1;
381                   data_item_win->width = item_win_width;
382                   data_item_win->origin.x = (item_win_width * j) + 1;
383                   data_item_win->origin.y = cur_y;
384                   tui_make_window (data_item_win, DONT_BOX_WINDOW);
385                   scrollok (data_item_win->handle, FALSE);
386                 }
387               touchwin (data_item_win->handle);
388
389               /* Get the printable representation of the register
390                  and display it.  */
391               tui_display_register (data_element_ptr, data_item_win);
392               i++;              /* Next register.  */
393             }
394           cur_y++;              /* Next row.  */
395         }
396     }
397 }
398
399
400 /* Function to display the registers in the content from
401    'start_element_no' on 'start_line_no' until the end of the register
402    content or the end of the display height.  This function checks
403    that we won't display off the end of the register display.  */
404 static void
405 tui_display_reg_element_at_line (int start_element_no,
406                                  int start_line_no)
407 {
408   if (TUI_DATA_WIN->detail.data_display_info.regs_content
409       != (tui_win_content) NULL
410       && TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
411     {
412       int element_no = start_element_no;
413
414       if (start_element_no != 0 && start_line_no != 0)
415         {
416           int last_line_no, first_line_on_last_page;
417
418           last_line_no = tui_last_regs_line_no ();
419           first_line_on_last_page
420             = last_line_no - (TUI_DATA_WIN->generic.height - 2);
421           if (first_line_on_last_page < 0)
422             first_line_on_last_page = 0;
423
424           /* If there is no other data displayed except registers, and
425              the element_no causes us to scroll past the end of the
426              registers, adjust what element to really start the
427              display at.  */
428           if (TUI_DATA_WIN->detail.data_display_info.data_content_count <= 0
429               && start_line_no > first_line_on_last_page)
430             element_no
431               = tui_first_reg_element_no_inline (first_line_on_last_page);
432         }
433       tui_display_registers_from (element_no);
434     }
435 }
436
437
438
439 /* Function to display the registers starting at line line_no in the
440    data window.  Answers the line number that the display actually
441    started from.  If nothing is displayed (-1) is returned.  */
442 int
443 tui_display_registers_from_line (int line_no, 
444                                  int force_display)
445 {
446   if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
447     {
448       int line, element_no;
449
450       if (line_no < 0)
451         line = 0;
452       else if (force_display)
453         { /* If we must display regs (force_display is true), then
454              make sure that we don't display off the end of the
455              registers.  */
456           if (line_no >= tui_last_regs_line_no ())
457             {
458               if ((line = tui_line_from_reg_element_no (
459                  TUI_DATA_WIN->detail.data_display_info.regs_content_count - 1)) < 0)
460                 line = 0;
461             }
462           else
463             line = line_no;
464         }
465       else
466         line = line_no;
467
468       element_no = tui_first_reg_element_no_inline (line);
469       if (element_no
470           < TUI_DATA_WIN->detail.data_display_info.regs_content_count)
471         tui_display_reg_element_at_line (element_no, line);
472       else
473         line = (-1);
474
475       return line;
476     }
477
478   return (-1);                  /* Nothing was displayed.  */
479 }
480
481
482 /* This function check all displayed registers for changes in values,
483    given a particular frame.  If the values have changed, they are
484    updated with the new value and highlighted.  */
485 void
486 tui_check_register_values (struct frame_info *frame)
487 {
488   if (TUI_DATA_WIN != NULL
489       && TUI_DATA_WIN->generic.is_visible)
490     {
491       struct tui_data_info *display_info
492         = &TUI_DATA_WIN->detail.data_display_info;
493
494       if (display_info->regs_content_count <= 0 
495           && display_info->display_regs)
496         tui_show_registers (display_info->current_group);
497       else
498         {
499           int i;
500
501           for (i = 0; (i < display_info->regs_content_count); i++)
502             {
503               struct tui_data_element *data;
504               struct tui_gen_win_info *data_item_win_ptr;
505               int was_hilighted;
506
507               data_item_win_ptr = &display_info->regs_content[i]->
508                 which_element.data_window;
509               data = &data_item_win_ptr->content[0]->which_element.data;
510               was_hilighted = data->highlight;
511
512               tui_get_register (frame, data,
513                                 data->item_no, &data->highlight);
514
515               if (data->highlight || was_hilighted)
516                 {
517                   tui_display_register (data, data_item_win_ptr);
518                 }
519             }
520         }
521     }
522 }
523
524 /* Display a register in a window.  If hilite is TRUE, then the value
525    will be displayed in reverse video.  */
526 static void
527 tui_display_register (struct tui_data_element *data,
528                       struct tui_gen_win_info *win_info)
529 {
530   if (win_info->handle != (WINDOW *) NULL)
531     {
532       int i;
533
534       if (data->highlight)
535         /* We ignore the return value, casting it to void in order to avoid
536            a compiler warning.  The warning itself was introduced by a patch
537            to ncurses 5.7 dated 2009-08-29, changing this macro to expand
538            to code that causes the compiler to generate an unused-value
539            warning.  */
540         (void) wstandout (win_info->handle);
541       
542       wmove (win_info->handle, 0, 0);
543       for (i = 1; i < win_info->width; i++)
544         waddch (win_info->handle, ' ');
545       wmove (win_info->handle, 0, 0);
546       if (data->content)
547         waddstr (win_info->handle, data->content);
548
549       if (data->highlight)
550         /* We ignore the return value, casting it to void in order to avoid
551            a compiler warning.  The warning itself was introduced by a patch
552            to ncurses 5.7 dated 2009-08-29, changing this macro to expand
553            to code that causes the compiler to generate an unused-value
554            warning.  */
555         (void) wstandend (win_info->handle);
556       tui_refresh_win (win_info);
557     }
558 }
559
560 /* Helper for "tui reg next", wraps a call to REGGROUP_NEXT, but adds wrap
561    around behaviour.  Returns the next register group, or NULL if the
562    register window is not currently being displayed.  */
563
564 static struct reggroup *
565 tui_reg_next (struct gdbarch *gdbarch)
566 {
567   struct reggroup *group = NULL;
568
569   if (TUI_DATA_WIN != NULL)
570     {
571       group = TUI_DATA_WIN->detail.data_display_info.current_group;
572       group = reggroup_next (gdbarch, group);
573       if (group == NULL)
574         group = reggroup_next (gdbarch, NULL);
575     }
576   return group;
577 }
578
579 /* Helper for "tui reg prev", wraps a call to REGGROUP_PREV, but adds wrap
580    around behaviour.  Returns the previous register group, or NULL if the
581    register window is not currently being displayed.  */
582
583 static struct reggroup *
584 tui_reg_prev (struct gdbarch *gdbarch)
585 {
586   struct reggroup *group = NULL;
587
588   if (TUI_DATA_WIN != NULL)
589     {
590       group = TUI_DATA_WIN->detail.data_display_info.current_group;
591       group = reggroup_prev (gdbarch, group);
592       if (group == NULL)
593         group = reggroup_prev (gdbarch, NULL);
594     }
595   return group;
596 }
597
598 /* Implement the 'tui reg' command.  Changes the register group displayed
599    in the tui register window.  Displays the tui register window if it is
600    not already on display.  */
601
602 static void
603 tui_reg_command (char *args, int from_tty)
604 {
605   struct gdbarch *gdbarch = get_current_arch ();
606
607   if (args != NULL)
608     {
609       struct reggroup *group, *match = NULL;
610       size_t len = strlen (args);
611
612       /* Make sure the curses mode is enabled.  */
613       tui_enable ();
614
615       /* Make sure the register window is visible.  If not, select an
616          appropriate layout.  We need to do this before trying to run the
617          'next' or 'prev' commands.  */
618       if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->generic.is_visible)
619         tui_set_layout_by_name (DATA_NAME);
620
621       if (strncmp (args, "next", len) == 0)
622         match = tui_reg_next (gdbarch);
623       else if (strncmp (args, "prev", len) == 0)
624         match = tui_reg_prev (gdbarch);
625
626       /* This loop matches on the initial part of a register group
627          name.  If this initial part in ARGS matches only one register
628          group then the switch is made.  */
629       for (group = reggroup_next (gdbarch, NULL);
630            group != NULL;
631            group = reggroup_next (gdbarch, group))
632         {
633           if (strncmp (reggroup_name (group), args, len) == 0)
634             {
635               if (match != NULL)
636                 error (_("ambiguous register group name '%s'"), args);
637               match = group;
638             }
639         }
640
641       if (match == NULL)
642         error (_("unknown register group '%s'"), args);
643
644       tui_show_registers (match);
645     }
646   else
647     {
648       struct reggroup *group;
649       int first;
650
651       printf_unfiltered (_("\"tui reg\" must be followed by the name of "
652                            "either a register group,\nor one of 'next' "
653                            "or 'prev'.  Known register groups are:\n"));
654
655       for (first = 1, group = reggroup_next (gdbarch, NULL);
656            group != NULL;
657            first = 0, group = reggroup_next (gdbarch, group))
658         {
659           if (!first)
660             printf_unfiltered (", ");
661           printf_unfiltered ("%s", reggroup_name (group));
662         }
663
664       printf_unfiltered ("\n");
665     }
666 }
667
668 /* Complete names of register groups, and add the special "prev" and "next"
669    names.  */
670
671 static VEC (char_ptr) *
672 tui_reggroup_completer (struct cmd_list_element *ignore,
673                         const char *text, const char *word)
674 {
675   VEC (char_ptr) *result = NULL;
676   static const char *extra[] = { "next", "prev", NULL };
677   size_t len = strlen (word);
678   const char **tmp;
679
680   result = reggroup_completer (ignore, text, word);
681
682   for (tmp = extra; *tmp != NULL; ++tmp)
683     {
684       if (strncmp (word, *tmp, len) == 0)
685         VEC_safe_push (char_ptr, result, xstrdup (*tmp));
686     }
687
688   return result;
689 }
690
691 /* Provide a prototype to silence -Wmissing-prototypes.  */
692 extern initialize_file_ftype _initialize_tui_regs;
693
694 void
695 _initialize_tui_regs (void)
696 {
697   struct cmd_list_element **tuicmd, *cmd;
698
699   tuicmd = tui_get_cmd_list ();
700
701   cmd = add_cmd ("reg", class_tui, tui_reg_command, _("\
702 TUI command to control the register window."), tuicmd);
703   set_cmd_completer (cmd, tui_reggroup_completer);
704 }
705
706
707 /*****************************************
708 ** STATIC LOCAL FUNCTIONS                 **
709 ******************************************/
710
711 static void
712 tui_restore_gdbout (void *ui)
713 {
714   gdb_stdout = (struct ui_file*) ui;
715   pagination_enabled = 1;
716 }
717
718 /* Get the register from the frame and return a printable
719    representation of it.  */
720
721 static char *
722 tui_register_format (struct frame_info *frame, int regnum)
723 {
724   struct gdbarch *gdbarch = get_frame_arch (frame);
725   struct ui_file *old_stdout;
726   struct cleanup *cleanups;
727   char *p, *s;
728   char *ret;
729
730   string_file stream;
731
732   pagination_enabled = 0;
733   old_stdout = gdb_stdout;
734   gdb_stdout = &stream;
735   cleanups = make_cleanup (tui_restore_gdbout, (void*) old_stdout);
736   gdbarch_print_registers_info (gdbarch, &stream, frame, regnum, 1);
737
738   /* Remove the possible \n.  */
739   std::string &str = stream.string ();
740   if (!str.empty () && str.back () == '\n')
741     str.resize (str.size () - 1);
742
743   /* Expand tabs into spaces, since ncurses on MS-Windows doesn't.  */
744   ret = tui_expand_tabs (str.c_str (), 0);
745
746   do_cleanups (cleanups);
747
748   return ret;
749 }
750
751 /* Get the register value from the given frame and format it for the
752    display.  When changep is set, check if the new register value has
753    changed with respect to the previous call.  */
754 static enum tui_status
755 tui_get_register (struct frame_info *frame,
756                   struct tui_data_element *data, 
757                   int regnum, int *changedp)
758 {
759   enum tui_status ret = TUI_FAILURE;
760
761   if (changedp)
762     *changedp = FALSE;
763   if (target_has_registers)
764     {
765       char *prev_content = data->content;
766
767       data->content = tui_register_format (frame, regnum);
768
769       if (changedp != NULL
770           && strcmp (prev_content, data->content) != 0)
771         *changedp = 1;
772
773       xfree (prev_content);
774
775       ret = TUI_SUCCESS;
776     }
777   return ret;
778 }