xref: /dragonfly/contrib/gdb-7/gdb/tui/tui-winsource.c (revision de8e141f24382815c10a4012d209bbbf7abf1112)
1 /* TUI display source/assembly window.
2 
3    Copyright (C) 1998-2013 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 <ctype.h>
24 #include "symtab.h"
25 #include "frame.h"
26 #include "breakpoint.h"
27 #include "value.h"
28 #include "source.h"
29 #include "objfiles.h"
30 #include "filenames.h"
31 
32 #include "tui/tui.h"
33 #include "tui/tui-data.h"
34 #include "tui/tui-stack.h"
35 #include "tui/tui-win.h"
36 #include "tui/tui-wingeneral.h"
37 #include "tui/tui-winsource.h"
38 #include "tui/tui-source.h"
39 #include "tui/tui-disasm.h"
40 
41 #include "gdb_string.h"
42 #include "gdb_curses.h"
43 #include "gdb_assert.h"
44 
45 /* Function to display the "main" routine.  */
46 void
tui_display_main(void)47 tui_display_main (void)
48 {
49   if ((tui_source_windows ())->count > 0)
50     {
51       struct gdbarch *gdbarch;
52       CORE_ADDR addr;
53 
54       tui_get_begin_asm_address (&gdbarch, &addr);
55       if (addr != (CORE_ADDR) 0)
56           {
57             struct symtab_and_line sal;
58 
59             tui_update_source_windows_with_addr (gdbarch, addr);
60             sal = find_pc_line (addr, 0);
61           if (sal.symtab)
62              tui_update_locator_fullname (symtab_to_fullname (sal.symtab));
63           else
64              tui_update_locator_fullname ("??");
65           }
66     }
67 }
68 
69 
70 
71 /* Function to display source in the source window.  This function
72    initializes the horizontal scroll to 0.  */
73 void
tui_update_source_window(struct tui_win_info * win_info,struct gdbarch * gdbarch,struct symtab * s,struct tui_line_or_address line_or_addr,int noerror)74 tui_update_source_window (struct tui_win_info *win_info,
75                                 struct gdbarch *gdbarch,
76                                 struct symtab *s,
77                                 struct tui_line_or_address line_or_addr,
78                                 int noerror)
79 {
80   win_info->detail.source_info.horizontal_offset = 0;
81   tui_update_source_window_as_is (win_info, gdbarch, s, line_or_addr, noerror);
82 
83   return;
84 }
85 
86 
87 /* Function to display source in the source/asm window.  This function
88    shows the source as specified by the horizontal offset.  */
89 void
tui_update_source_window_as_is(struct tui_win_info * win_info,struct gdbarch * gdbarch,struct symtab * s,struct tui_line_or_address line_or_addr,int noerror)90 tui_update_source_window_as_is (struct tui_win_info *win_info,
91                                         struct gdbarch *gdbarch,
92                                         struct symtab *s,
93                                         struct tui_line_or_address line_or_addr,
94                                         int noerror)
95 {
96   enum tui_status ret;
97 
98   if (win_info->generic.type == SRC_WIN)
99     ret = tui_set_source_content (s, line_or_addr.u.line_no, noerror);
100   else
101     ret = tui_set_disassem_content (gdbarch, line_or_addr.u.addr);
102 
103   if (ret == TUI_FAILURE)
104     {
105       tui_clear_source_content (win_info, EMPTY_SOURCE_PROMPT);
106       tui_clear_exec_info_content (win_info);
107     }
108   else
109     {
110       tui_update_breakpoint_info (win_info, 0);
111       tui_show_source_content (win_info);
112       tui_update_exec_info (win_info);
113       if (win_info->generic.type == SRC_WIN)
114           {
115             struct symtab_and_line sal;
116 
117             init_sal (&sal);
118             sal.line = line_or_addr.u.line_no +
119               (win_info->generic.content_size - 2);
120             sal.symtab = s;
121             sal.pspace = s->objfile->pspace;
122             set_current_source_symtab_and_line (&sal);
123             /* If the focus was in the asm win, put it in the src win if
124                we don't have a split layout.  */
125             if (tui_win_with_focus () == TUI_DISASM_WIN
126                 && tui_current_layout () != SRC_DISASSEM_COMMAND)
127               tui_set_win_focus_to (TUI_SRC_WIN);
128           }
129     }
130 
131 
132   return;
133 }
134 
135 
136 /* Function to ensure that the source and/or disassemly windows
137    reflect the input address.  */
138 void
tui_update_source_windows_with_addr(struct gdbarch * gdbarch,CORE_ADDR addr)139 tui_update_source_windows_with_addr (struct gdbarch *gdbarch, CORE_ADDR addr)
140 {
141   if (addr != 0)
142     {
143       struct symtab_and_line sal;
144       struct tui_line_or_address l;
145 
146       switch (tui_current_layout ())
147           {
148           case DISASSEM_COMMAND:
149           case DISASSEM_DATA_COMMAND:
150             tui_show_disassem (gdbarch, addr);
151             break;
152           case SRC_DISASSEM_COMMAND:
153             tui_show_disassem_and_update_source (gdbarch, addr);
154             break;
155           default:
156             sal = find_pc_line (addr, 0);
157             l.loa = LOA_LINE;
158             l.u.line_no = sal.line;
159             tui_show_symtab_source (gdbarch, sal.symtab, l, FALSE);
160             break;
161           }
162     }
163   else
164     {
165       int i;
166 
167       for (i = 0; i < (tui_source_windows ())->count; i++)
168           {
169             struct tui_win_info *win_info = (tui_source_windows ())->list[i];
170 
171             tui_clear_source_content (win_info, EMPTY_SOURCE_PROMPT);
172             tui_clear_exec_info_content (win_info);
173           }
174     }
175 }
176 
177 /* Function to ensure that the source and/or disassemly windows
178    reflect the input address.  */
179 void
tui_update_source_windows_with_line(struct symtab * s,int line)180 tui_update_source_windows_with_line (struct symtab *s, int line)
181 {
182   struct gdbarch *gdbarch;
183   CORE_ADDR pc;
184   struct tui_line_or_address l;
185 
186   if (!s)
187     return;
188 
189   gdbarch = get_objfile_arch (s->objfile);
190 
191   switch (tui_current_layout ())
192     {
193     case DISASSEM_COMMAND:
194     case DISASSEM_DATA_COMMAND:
195       find_line_pc (s, line, &pc);
196       tui_update_source_windows_with_addr (gdbarch, pc);
197       break;
198     default:
199       l.loa = LOA_LINE;
200       l.u.line_no = line;
201       tui_show_symtab_source (gdbarch, s, l, FALSE);
202       if (tui_current_layout () == SRC_DISASSEM_COMMAND)
203           {
204             find_line_pc (s, line, &pc);
205             tui_show_disassem (gdbarch, pc);
206           }
207       break;
208     }
209 
210   return;
211 }
212 
213 void
tui_clear_source_content(struct tui_win_info * win_info,int display_prompt)214 tui_clear_source_content (struct tui_win_info *win_info,
215                                 int display_prompt)
216 {
217   if (win_info != NULL)
218     {
219       int i;
220 
221       win_info->generic.content_in_use = FALSE;
222       tui_erase_source_content (win_info, display_prompt);
223       for (i = 0; i < win_info->generic.content_size; i++)
224           {
225             struct tui_win_element *element =
226               (struct tui_win_element *) win_info->generic.content[i];
227 
228             element->which_element.source.has_break = FALSE;
229             element->which_element.source.is_exec_point = FALSE;
230           }
231     }
232 }
233 
234 
235 void
tui_erase_source_content(struct tui_win_info * win_info,int display_prompt)236 tui_erase_source_content (struct tui_win_info *win_info,
237                                 int display_prompt)
238 {
239   int x_pos;
240   int half_width = (win_info->generic.width - 2) / 2;
241 
242   if (win_info->generic.handle != (WINDOW *) NULL)
243     {
244       werase (win_info->generic.handle);
245       tui_check_and_display_highlight_if_needed (win_info);
246       if (display_prompt == EMPTY_SOURCE_PROMPT)
247           {
248             char *no_src_str;
249 
250             if (win_info->generic.type == SRC_WIN)
251               no_src_str = NO_SRC_STRING;
252             else
253               no_src_str = NO_DISASSEM_STRING;
254             if (strlen (no_src_str) >= half_width)
255               x_pos = 1;
256             else
257               x_pos = half_width - strlen (no_src_str);
258             mvwaddstr (win_info->generic.handle,
259                          (win_info->generic.height / 2),
260                          x_pos,
261                          no_src_str);
262 
263             /* elz: Added this function call to set the real contents of
264                the window to what is on the screen, so that later calls
265                to refresh, do display the correct stuff, and not the old
266                image.  */
267 
268             tui_set_source_content_nil (win_info, no_src_str);
269           }
270       tui_refresh_win (&win_info->generic);
271     }
272 }
273 
274 
275 /* Redraw the complete line of a source or disassembly window.  */
276 static void
tui_show_source_line(struct tui_win_info * win_info,int lineno)277 tui_show_source_line (struct tui_win_info *win_info, int lineno)
278 {
279   struct tui_win_element *line;
280   int x, y;
281 
282   line = (struct tui_win_element *) win_info->generic.content[lineno - 1];
283   if (line->which_element.source.is_exec_point)
284     wattron (win_info->generic.handle, A_STANDOUT);
285 
286   mvwaddstr (win_info->generic.handle, lineno, 1,
287              line->which_element.source.line);
288   if (line->which_element.source.is_exec_point)
289     wattroff (win_info->generic.handle, A_STANDOUT);
290 
291   /* Clear to end of line but stop before the border.  */
292   getyx (win_info->generic.handle, y, x);
293   while (x + 1 < win_info->generic.width)
294     {
295       waddch (win_info->generic.handle, ' ');
296       getyx (win_info->generic.handle, y, x);
297     }
298 }
299 
300 void
tui_show_source_content(struct tui_win_info * win_info)301 tui_show_source_content (struct tui_win_info *win_info)
302 {
303   if (win_info->generic.content_size > 0)
304     {
305       int lineno;
306 
307       for (lineno = 1; lineno <= win_info->generic.content_size; lineno++)
308         tui_show_source_line (win_info, lineno);
309     }
310   else
311     tui_erase_source_content (win_info, TRUE);
312 
313   tui_check_and_display_highlight_if_needed (win_info);
314   tui_refresh_win (&win_info->generic);
315   win_info->generic.content_in_use = TRUE;
316 }
317 
318 
319 /* Scroll the source forward or backward horizontally.  */
320 void
tui_horizontal_source_scroll(struct tui_win_info * win_info,enum tui_scroll_direction direction,int num_to_scroll)321 tui_horizontal_source_scroll (struct tui_win_info *win_info,
322                                     enum tui_scroll_direction direction,
323                                     int num_to_scroll)
324 {
325   if (win_info->generic.content != NULL)
326     {
327       struct gdbarch *gdbarch = win_info->detail.source_info.gdbarch;
328       int offset;
329       struct symtab *s = NULL;
330 
331       if (win_info->generic.type == SRC_WIN)
332           {
333             struct symtab_and_line cursal
334               = get_current_source_symtab_and_line ();
335 
336             if (cursal.symtab == NULL)
337               s = find_pc_symtab (get_frame_pc (get_selected_frame (NULL)));
338             else
339               s = cursal.symtab;
340           }
341 
342       if (direction == LEFT_SCROLL)
343           offset = win_info->detail.source_info.horizontal_offset
344             + num_to_scroll;
345       else
346           {
347             offset = win_info->detail.source_info.horizontal_offset
348               - num_to_scroll;
349             if (offset < 0)
350               offset = 0;
351           }
352       win_info->detail.source_info.horizontal_offset = offset;
353       tui_update_source_window_as_is (win_info, gdbarch, s,
354                                               ((struct tui_win_element *)
355                                                win_info->generic.content[0])->which_element.source.line_or_addr,
356                                               FALSE);
357     }
358 
359   return;
360 }
361 
362 
363 /* Set or clear the has_break flag in the line whose line is
364    line_no.  */
365 
366 void
tui_set_is_exec_point_at(struct tui_line_or_address l,struct tui_win_info * win_info)367 tui_set_is_exec_point_at (struct tui_line_or_address l,
368                                 struct tui_win_info *win_info)
369 {
370   int changed = 0;
371   int i;
372   tui_win_content content = (tui_win_content) win_info->generic.content;
373 
374   i = 0;
375   while (i < win_info->generic.content_size)
376     {
377       int new_state;
378       struct tui_line_or_address content_loa =
379           content[i]->which_element.source.line_or_addr;
380 
381       gdb_assert (l.loa == LOA_ADDRESS || l.loa == LOA_LINE);
382       gdb_assert (content_loa.loa == LOA_LINE
383                       || content_loa.loa == LOA_ADDRESS);
384       if (content_loa.loa == l.loa
385             && ((l.loa == LOA_LINE && content_loa.u.line_no == l.u.line_no)
386               || (content_loa.u.addr == l.u.addr)))
387         new_state = TRUE;
388       else
389           new_state = FALSE;
390       if (new_state != content[i]->which_element.source.is_exec_point)
391         {
392           changed++;
393           content[i]->which_element.source.is_exec_point = new_state;
394           tui_show_source_line (win_info, i + 1);
395         }
396       i++;
397     }
398   if (changed)
399     tui_refresh_win (&win_info->generic);
400 }
401 
402 /* Update the execution windows to show the active breakpoints.
403    This is called whenever a breakpoint is inserted, removed or
404    has its state changed.  */
405 void
tui_update_all_breakpoint_info(void)406 tui_update_all_breakpoint_info (void)
407 {
408   struct tui_list *list = tui_source_windows ();
409   int i;
410 
411   for (i = 0; i < list->count; i++)
412     {
413       struct tui_win_info *win = list->list[i];
414 
415       if (tui_update_breakpoint_info (win, FALSE))
416         {
417           tui_update_exec_info (win);
418         }
419     }
420 }
421 
422 
423 /* Scan the source window and the breakpoints to update the has_break
424    information for each line.
425 
426    Returns 1 if something changed and the execution window must be
427    refreshed.  */
428 
429 int
tui_update_breakpoint_info(struct tui_win_info * win,int current_only)430 tui_update_breakpoint_info (struct tui_win_info *win,
431                                   int current_only)
432 {
433   int i;
434   int need_refresh = 0;
435   struct tui_source_info *src = &win->detail.source_info;
436 
437   for (i = 0; i < win->generic.content_size; i++)
438     {
439       struct breakpoint *bp;
440       extern struct breakpoint *breakpoint_chain;
441       int mode;
442       struct tui_source_element *line;
443 
444       line = &((struct tui_win_element *)
445                  win->generic.content[i])->which_element.source;
446       if (current_only && !line->is_exec_point)
447          continue;
448 
449       /* Scan each breakpoint to see if the current line has something to
450          do with it.  Identify enable/disabled breakpoints as well as
451          those that we already hit.  */
452       mode = 0;
453       for (bp = breakpoint_chain;
454            bp != (struct breakpoint *) NULL;
455            bp = bp->next)
456         {
457             struct bp_location *loc;
458 
459             gdb_assert (line->line_or_addr.loa == LOA_LINE
460                           || line->line_or_addr.loa == LOA_ADDRESS);
461 
462             for (loc = bp->loc; loc != NULL; loc = loc->next)
463               {
464                 if ((win == TUI_SRC_WIN
465                        && loc->symtab != NULL
466                        && filename_cmp (src->fullname,
467                                             symtab_to_fullname (loc->symtab)) == 0
468                        && line->line_or_addr.loa == LOA_LINE
469                        && loc->line_number == line->line_or_addr.u.line_no)
470                       || (win == TUI_DISASM_WIN
471                           && line->line_or_addr.loa == LOA_ADDRESS
472                           && loc->address == line->line_or_addr.u.addr))
473                     {
474                       if (bp->enable_state == bp_disabled)
475                         mode |= TUI_BP_DISABLED;
476                       else
477                         mode |= TUI_BP_ENABLED;
478                       if (bp->hit_count)
479                         mode |= TUI_BP_HIT;
480                       if (bp->loc->cond)
481                         mode |= TUI_BP_CONDITIONAL;
482                       if (bp->type == bp_hardware_breakpoint)
483                         mode |= TUI_BP_HARDWARE;
484                     }
485               }
486         }
487       if (line->has_break != mode)
488         {
489           line->has_break = mode;
490           need_refresh = 1;
491         }
492     }
493   return need_refresh;
494 }
495 
496 
497 /* Function to initialize the content of the execution info window,
498    based upon the input window which is either the source or
499    disassembly window.  */
500 enum tui_status
tui_set_exec_info_content(struct tui_win_info * win_info)501 tui_set_exec_info_content (struct tui_win_info *win_info)
502 {
503   enum tui_status ret = TUI_SUCCESS;
504 
505   if (win_info->detail.source_info.execution_info
506       != (struct tui_gen_win_info *) NULL)
507     {
508       struct tui_gen_win_info *exec_info_ptr
509           = win_info->detail.source_info.execution_info;
510 
511       if (exec_info_ptr->content == NULL)
512           exec_info_ptr->content =
513             (void **) tui_alloc_content (win_info->generic.height,
514                                                    exec_info_ptr->type);
515       if (exec_info_ptr->content != NULL)
516           {
517             int i;
518 
519           tui_update_breakpoint_info (win_info, 1);
520             for (i = 0; i < win_info->generic.content_size; i++)
521               {
522                 struct tui_win_element *element;
523                 struct tui_win_element *src_element;
524               int mode;
525 
526                 element = (struct tui_win_element *) exec_info_ptr->content[i];
527                 src_element = (struct tui_win_element *)
528                     win_info->generic.content[i];
529 
530               memset(element->which_element.simple_string, ' ',
531                      sizeof(element->which_element.simple_string));
532               element->which_element.simple_string[TUI_EXECINFO_SIZE - 1] = 0;
533 
534                 /* Now update the exec info content based upon the state
535                  of each line as indicated by the source content.  */
536               mode = src_element->which_element.source.has_break;
537               if (mode & TUI_BP_HIT)
538                 element->which_element.simple_string[TUI_BP_HIT_POS] =
539                   (mode & TUI_BP_HARDWARE) ? 'H' : 'B';
540               else if (mode & (TUI_BP_ENABLED | TUI_BP_DISABLED))
541                 element->which_element.simple_string[TUI_BP_HIT_POS] =
542                   (mode & TUI_BP_HARDWARE) ? 'h' : 'b';
543 
544               if (mode & TUI_BP_ENABLED)
545                 element->which_element.simple_string[TUI_BP_BREAK_POS] = '+';
546               else if (mode & TUI_BP_DISABLED)
547                 element->which_element.simple_string[TUI_BP_BREAK_POS] = '-';
548 
549               if (src_element->which_element.source.is_exec_point)
550                 element->which_element.simple_string[TUI_EXEC_POS] = '>';
551               }
552             exec_info_ptr->content_size = win_info->generic.content_size;
553           }
554       else
555           ret = TUI_FAILURE;
556     }
557 
558   return ret;
559 }
560 
561 
562 void
tui_show_exec_info_content(struct tui_win_info * win_info)563 tui_show_exec_info_content (struct tui_win_info *win_info)
564 {
565   struct tui_gen_win_info *exec_info
566     = win_info->detail.source_info.execution_info;
567   int cur_line;
568 
569   werase (exec_info->handle);
570   tui_refresh_win (exec_info);
571   for (cur_line = 1; (cur_line <= exec_info->content_size); cur_line++)
572     mvwaddstr (exec_info->handle,
573                  cur_line,
574                  0,
575                  ((struct tui_win_element *)
576                     exec_info->content[cur_line - 1])->which_element.simple_string);
577   tui_refresh_win (exec_info);
578   exec_info->content_in_use = TRUE;
579 }
580 
581 
582 void
tui_erase_exec_info_content(struct tui_win_info * win_info)583 tui_erase_exec_info_content (struct tui_win_info *win_info)
584 {
585   struct tui_gen_win_info *exec_info
586     = win_info->detail.source_info.execution_info;
587 
588   werase (exec_info->handle);
589   tui_refresh_win (exec_info);
590 }
591 
592 void
tui_clear_exec_info_content(struct tui_win_info * win_info)593 tui_clear_exec_info_content (struct tui_win_info *win_info)
594 {
595   win_info->detail.source_info.execution_info->content_in_use = FALSE;
596   tui_erase_exec_info_content (win_info);
597 
598   return;
599 }
600 
601 /* Function to update the execution info window.  */
602 void
tui_update_exec_info(struct tui_win_info * win_info)603 tui_update_exec_info (struct tui_win_info *win_info)
604 {
605   tui_set_exec_info_content (win_info);
606   tui_show_exec_info_content (win_info);
607 }
608 
609 enum tui_status
tui_alloc_source_buffer(struct tui_win_info * win_info)610 tui_alloc_source_buffer (struct tui_win_info *win_info)
611 {
612   char *src_line_buf;
613   int i, line_width, max_lines;
614 
615   max_lines = win_info->generic.height; /* Less the highlight box.  */
616   line_width = win_info->generic.width - 1;
617   /*
618    * Allocate the buffer for the source lines.  Do this only once
619    * since they will be re-used for all source displays.  The only
620    * other time this will be done is when a window's size changes.
621    */
622   if (win_info->generic.content == NULL)
623     {
624       src_line_buf = (char *)
625           xmalloc ((max_lines * line_width) * sizeof (char));
626       if (src_line_buf == (char *) NULL)
627           {
628             fputs_unfiltered ("Unable to Allocate Memory for "
629                                   "Source or Disassembly Display.\n",
630                                   gdb_stderr);
631             return TUI_FAILURE;
632           }
633       /* Allocate the content list.  */
634       if ((win_info->generic.content =
635              (void **) tui_alloc_content (max_lines, SRC_WIN)) == NULL)
636           {
637             xfree (src_line_buf);
638             fputs_unfiltered ("Unable to Allocate Memory for "
639                                   "Source or Disassembly Display.\n",
640                                   gdb_stderr);
641             return TUI_FAILURE;
642           }
643       for (i = 0; i < max_lines; i++)
644           ((struct tui_win_element *)
645            win_info->generic.content[i])->which_element.source.line =
646             src_line_buf + (line_width * i);
647     }
648 
649   return TUI_SUCCESS;
650 }
651 
652 
653 /* Answer whether a particular line number or address is displayed
654    in the current source window.  */
655 int
tui_line_is_displayed(int line,struct tui_win_info * win_info,int check_threshold)656 tui_line_is_displayed (int line,
657                            struct tui_win_info *win_info,
658                            int check_threshold)
659 {
660   int is_displayed = FALSE;
661   int i, threshold;
662 
663   if (check_threshold)
664     threshold = SCROLL_THRESHOLD;
665   else
666     threshold = 0;
667   i = 0;
668   while (i < win_info->generic.content_size - threshold
669            && !is_displayed)
670     {
671       is_displayed = (((struct tui_win_element *)
672                            win_info->generic.content[i])->which_element.source.line_or_addr.loa
673                           == LOA_LINE)
674           && (((struct tui_win_element *)
675                win_info->generic.content[i])->which_element.source.line_or_addr.u.line_no
676               == (int) line);
677       i++;
678     }
679 
680   return is_displayed;
681 }
682 
683 
684 /* Answer whether a particular line number or address is displayed
685    in the current source window.  */
686 int
tui_addr_is_displayed(CORE_ADDR addr,struct tui_win_info * win_info,int check_threshold)687 tui_addr_is_displayed (CORE_ADDR addr,
688                            struct tui_win_info *win_info,
689                            int check_threshold)
690 {
691   int is_displayed = FALSE;
692   int i, threshold;
693 
694   if (check_threshold)
695     threshold = SCROLL_THRESHOLD;
696   else
697     threshold = 0;
698   i = 0;
699   while (i < win_info->generic.content_size - threshold
700            && !is_displayed)
701     {
702       is_displayed = (((struct tui_win_element *)
703                            win_info->generic.content[i])->which_element.source.line_or_addr.loa
704                           == LOA_ADDRESS)
705           && (((struct tui_win_element *)
706                win_info->generic.content[i])->which_element.source.line_or_addr.u.addr
707               == addr);
708       i++;
709     }
710 
711   return is_displayed;
712 }
713 
714 
715 /*****************************************
716 ** STATIC LOCAL FUNCTIONS               **
717 ******************************************/
718