]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
This commit was manufactured by cvs2svn to create branch 'drow-cplus-
authornobody <>
Mon, 9 Feb 2004 10:55:25 +0000 (10:55 +0000)
committernobody <>
Mon, 9 Feb 2004 10:55:25 +0000 (10:55 +0000)
branch'.

Cherrypick from master 2004-02-09 10:55:24 UTC Michael Chastain <mec@google.com> '2004-02-09  Michael Chastain  <mec.gnu@mindspring.com>':
    gdb/auxv.c
    gdb/auxv.h
    gdb/config/sparc/obsd.mt
    gdb/config/sparc/obsd64.mt
    gdb/sparc64obsd-tdep.c
    gdb/sparcobsd-tdep.c
    gdb/testsuite/gdb.asm/openbsd.inc
    gdb/testsuite/gdb.base/chng-syms.c
    gdb/testsuite/gdb.base/chng-syms.exp
    gdb/testsuite/gdb.base/pending.c
    gdb/testsuite/gdb.base/pending.exp
    gdb/testsuite/gdb.base/pendshr.c
    gdb/testsuite/gdb.threads/thread-specific.c
    gdb/testsuite/gdb.threads/thread-specific.exp
    gdb/tui/tui-command.c
    gdb/tui/tui-command.h
    gdb/tui/tui-data.c
    gdb/tui/tui-data.h
    gdb/tui/tui-disasm.c
    gdb/tui/tui-disasm.h
    gdb/tui/tui-io.c
    gdb/tui/tui-io.h
    gdb/tui/tui-layout.c
    gdb/tui/tui-layout.h
    gdb/tui/tui-regs.c
    gdb/tui/tui-regs.h
    gdb/tui/tui-source.c
    gdb/tui/tui-source.h
    gdb/tui/tui-stack.c
    gdb/tui/tui-stack.h
    gdb/tui/tui-win.c
    gdb/tui/tui-win.h
    gdb/tui/tui-windata.c
    gdb/tui/tui-windata.h
    gdb/tui/tui-wingeneral.c
    gdb/tui/tui-wingeneral.h
    gdb/tui/tui-winsource.c
    gdb/tui/tui-winsource.h
    sim/testsuite/sim/mips/ChangeLog
    sim/testsuite/sim/mips/basic.exp
    sim/testsuite/sim/mips/sanity.s
    sim/testsuite/sim/mips/testutils.inc

42 files changed:
gdb/auxv.c [new file with mode: 0644]
gdb/auxv.h [new file with mode: 0644]
gdb/config/sparc/obsd.mt [new file with mode: 0644]
gdb/config/sparc/obsd64.mt [new file with mode: 0644]
gdb/sparc64obsd-tdep.c [new file with mode: 0644]
gdb/sparcobsd-tdep.c [new file with mode: 0644]
gdb/testsuite/gdb.asm/openbsd.inc [new file with mode: 0644]
gdb/testsuite/gdb.base/chng-syms.c [new file with mode: 0644]
gdb/testsuite/gdb.base/chng-syms.exp [new file with mode: 0644]
gdb/testsuite/gdb.base/pending.c [new file with mode: 0644]
gdb/testsuite/gdb.base/pending.exp [new file with mode: 0644]
gdb/testsuite/gdb.base/pendshr.c [new file with mode: 0644]
gdb/testsuite/gdb.threads/thread-specific.c [new file with mode: 0644]
gdb/testsuite/gdb.threads/thread-specific.exp [new file with mode: 0644]
gdb/tui/tui-command.c [new file with mode: 0644]
gdb/tui/tui-command.h [new file with mode: 0644]
gdb/tui/tui-data.c [new file with mode: 0644]
gdb/tui/tui-data.h [new file with mode: 0644]
gdb/tui/tui-disasm.c [new file with mode: 0644]
gdb/tui/tui-disasm.h [new file with mode: 0644]
gdb/tui/tui-io.c [new file with mode: 0644]
gdb/tui/tui-io.h [new file with mode: 0644]
gdb/tui/tui-layout.c [new file with mode: 0644]
gdb/tui/tui-layout.h [new file with mode: 0644]
gdb/tui/tui-regs.c [new file with mode: 0644]
gdb/tui/tui-regs.h [new file with mode: 0644]
gdb/tui/tui-source.c [new file with mode: 0644]
gdb/tui/tui-source.h [new file with mode: 0644]
gdb/tui/tui-stack.c [new file with mode: 0644]
gdb/tui/tui-stack.h [new file with mode: 0644]
gdb/tui/tui-win.c [new file with mode: 0644]
gdb/tui/tui-win.h [new file with mode: 0644]
gdb/tui/tui-windata.c [new file with mode: 0644]
gdb/tui/tui-windata.h [new file with mode: 0644]
gdb/tui/tui-wingeneral.c [new file with mode: 0644]
gdb/tui/tui-wingeneral.h [new file with mode: 0644]
gdb/tui/tui-winsource.c [new file with mode: 0644]
gdb/tui/tui-winsource.h [new file with mode: 0644]
sim/testsuite/sim/mips/ChangeLog [new file with mode: 0644]
sim/testsuite/sim/mips/basic.exp [new file with mode: 0644]
sim/testsuite/sim/mips/sanity.s [new file with mode: 0644]
sim/testsuite/sim/mips/testutils.inc [new file with mode: 0644]

diff --git a/gdb/auxv.c b/gdb/auxv.c
new file mode 100644 (file)
index 0000000..c28014c
--- /dev/null
@@ -0,0 +1,301 @@
+/* Auxiliary vector support for GDB, the GNU debugger.
+
+   Copyright 2004 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include "defs.h"
+#include "target.h"
+#include "gdbtypes.h"
+#include "command.h"
+#include "inferior.h"
+#include "valprint.h"
+#include "gdb_assert.h"
+
+#include "auxv.h"
+#include "elf/common.h"
+
+#include <unistd.h>
+#include <fcntl.h>
+
+
+/* This function is called like a to_xfer_partial hook,
+   but must be called with TARGET_OBJECT_AUXV.
+   It handles access via /proc/PID/auxv, which is the common method.
+   This function is appropriate for doing:
+          #define NATIVE_XFER_AUXV     procfs_xfer_auxv
+   for a native target that uses inftarg.c's child_xfer_partial hook.  */
+
+LONGEST
+procfs_xfer_auxv (struct target_ops *ops,
+                 int /* enum target_object */ object,
+                 const char *annex,
+                 void *readbuf,
+                 const void *writebuf,
+                 ULONGEST offset,
+                 LONGEST len)
+{
+  char *pathname;
+  int fd;
+  LONGEST n;
+
+  gdb_assert (object == TARGET_OBJECT_AUXV);
+  gdb_assert (readbuf || writebuf);
+
+  pathname = xstrprintf ("/proc/%d/auxv", PIDGET (inferior_ptid));
+  fd = open (pathname, writebuf != NULL ? O_WRONLY : O_RDONLY);
+  xfree (pathname);
+  if (fd < 0)
+    return -1;
+
+  if (offset != (ULONGEST) 0
+      && lseek (fd, (off_t) offset, SEEK_SET) != (off_t) offset)
+    n = -1;
+  else if (readbuf != NULL)
+    n = read (fd, readbuf, len);
+  else
+    n = write (fd, writebuf, len);
+
+  (void) close (fd);
+
+  return n;
+}
+
+/* Read all the auxv data into a contiguous xmalloc'd buffer,
+   stored in *DATA.  Return the size in bytes of this data.
+   If zero, there is no data and *DATA is null.
+   if < 0, there was an error and *DATA is null.  */
+LONGEST
+target_auxv_read (struct target_ops *ops, char **data)
+{
+  size_t auxv_alloc = 512, auxv_pos = 0;
+  char *auxv = xmalloc (auxv_alloc);
+  int n;
+
+  while (1)
+    {
+      n = target_read_partial (ops, TARGET_OBJECT_AUXV,
+                              NULL, &auxv[auxv_pos], 0,
+                              auxv_alloc - auxv_pos);
+      if (n <= 0)
+       break;
+      auxv_pos += n;
+      if (auxv_pos < auxv_alloc) /* Read all there was.  */
+       break;
+      gdb_assert (auxv_pos == auxv_alloc);
+      auxv_alloc *= 2;
+      auxv = xrealloc (auxv, auxv_alloc);
+    }
+
+  if (auxv_pos == 0)
+    {
+      xfree (auxv);
+      *data = NULL;
+      return n;
+    }
+
+  *data = auxv;
+  return auxv_pos;
+}
+
+/* Read one auxv entry from *READPTR, not reading locations >= ENDPTR.
+   Return 0 if *READPTR is already at the end of the buffer.
+   Return -1 if there is insufficient buffer for a whole entry.
+   Return 1 if an entry was read into *TYPEP and *VALP.  */
+int
+target_auxv_parse (struct target_ops *ops, char **readptr, char *endptr,
+                  CORE_ADDR *typep, CORE_ADDR *valp)
+{
+  const int sizeof_auxv_field = TYPE_LENGTH (builtin_type_void_data_ptr);
+  char *ptr = *readptr;
+
+  if (endptr == ptr)
+    return 0;
+
+  if (endptr - ptr < sizeof_auxv_field * 2)
+    return -1;
+
+  *typep = extract_unsigned_integer (ptr, sizeof_auxv_field);
+  ptr += sizeof_auxv_field;
+  *valp = extract_unsigned_integer (ptr, sizeof_auxv_field);
+  ptr += sizeof_auxv_field;
+
+  *readptr = ptr;
+  return 1;
+}
+
+/* Extract the auxiliary vector entry with a_type matching MATCH.
+   Return zero if no such entry was found, or -1 if there was
+   an error getting the information.  On success, return 1 after
+   storing the entry's value field in *VALP.  */
+int
+target_auxv_search (struct target_ops *ops, CORE_ADDR match, CORE_ADDR *valp)
+{
+  CORE_ADDR type, val;
+  char *data;
+  int n = target_auxv_read (ops, &data);
+  char *ptr = data;
+  int ents = 0;
+
+  if (n <= 0)
+    return n;
+
+  while (1)
+    switch (target_auxv_parse (ops, &ptr, data + n, &type, &val))
+      {
+      case 1:                  /* Here's an entry, check it.  */
+       if (type == match)
+         {
+           xfree (data);
+           *valp = val;
+           return 1;
+         }
+       break;
+      case 0:                  /* End of the vector.  */
+       xfree (data);
+       return 0;
+      default:                 /* Bogosity.  */
+       xfree (data);
+       return -1;
+      }
+
+  /*NOTREACHED*/
+}
+
+
+/* Print the contents of the target's AUXV on the specified file. */
+int
+fprint_target_auxv (struct ui_file *file, struct target_ops *ops)
+{
+  CORE_ADDR type, val;
+  char *data;
+  int len = target_auxv_read (ops, &data);
+  char *ptr = data;
+  int ents = 0;
+
+  if (len <= 0)
+    return len;
+
+  while (target_auxv_parse (ops, &ptr, data + len, &type, &val) > 0)
+    {
+      extern int addressprint;
+      const char *name = "???";
+      const char *description = "";
+      enum { dec, hex, str } flavor = hex;
+
+      switch (type)
+       {
+#define TAG(tag, text, kind) \
+       case tag: name = #tag; description = text; flavor = kind; break
+         TAG (AT_NULL, "End of vector", hex);
+         TAG (AT_IGNORE, "Entry should be ignored", hex);
+         TAG (AT_EXECFD, "File descriptor of program", dec);
+         TAG (AT_PHDR, "Program headers for program", hex);
+         TAG (AT_PHENT, "Size of program header entry", dec);
+         TAG (AT_PHNUM, "Number of program headers", dec);
+         TAG (AT_PAGESZ, "System page size", dec);
+         TAG (AT_BASE, "Base address of interpreter", hex);
+         TAG (AT_FLAGS, "Flags", hex);
+         TAG (AT_ENTRY, "Entry point of program", hex);
+         TAG (AT_NOTELF, "Program is not ELF", dec);
+         TAG (AT_UID, "Real user ID", dec);
+         TAG (AT_EUID, "Effective user ID", dec);
+         TAG (AT_GID, "Real group ID", dec);
+         TAG (AT_EGID, "Effective group ID", dec);
+         TAG (AT_CLKTCK, "Frequency of times()", dec);
+         TAG (AT_PLATFORM, "String identifying platform", str);
+         TAG (AT_HWCAP, "Machine-dependent CPU capability hints", hex);
+         TAG (AT_FPUCW, "Used FPU control word", dec);
+         TAG (AT_DCACHEBSIZE, "Data cache block size", dec);
+         TAG (AT_ICACHEBSIZE, "Instruction cache block size", dec);
+         TAG (AT_UCACHEBSIZE, "Unified cache block size", dec);
+         TAG (AT_IGNOREPPC, "Entry should be ignored", dec);
+         TAG (AT_SYSINFO, "Special system info/entry points", hex);
+         TAG (AT_SYSINFO_EHDR, "System-supplied DSO's ELF header", hex);
+         TAG (AT_SECURE, "Boolean, was exec setuid-like?", dec);
+         TAG (AT_SUN_UID, "Effective user ID", dec);
+         TAG (AT_SUN_RUID, "Real user ID", dec);
+         TAG (AT_SUN_GID, "Effective group ID", dec);
+         TAG (AT_SUN_RGID, "Real group ID", dec);
+         TAG (AT_SUN_LDELF, "Dynamic linker's ELF header", hex);
+         TAG (AT_SUN_LDSHDR, "Dynamic linker's section headers", hex);
+         TAG (AT_SUN_LDNAME, "String giving name of dynamic linker", str);
+         TAG (AT_SUN_LPAGESZ, "Large pagesize", dec);
+         TAG (AT_SUN_PLATFORM, "Platform name string", str);
+         TAG (AT_SUN_HWCAP, "Machine-dependent CPU capability hints", hex);
+         TAG (AT_SUN_IFLUSH, "Should flush icache?", dec);
+         TAG (AT_SUN_CPU, "CPU name string", str);
+         TAG (AT_SUN_EMUL_ENTRY, "COFF entry point address", hex);
+         TAG (AT_SUN_EMUL_EXECFD, "COFF executable file descriptor", dec);
+         TAG (AT_SUN_EXECNAME,
+              "Canonicalized file name given to execve", str);
+         TAG (AT_SUN_MMU, "String for name of MMU module", str);
+         TAG (AT_SUN_LDDATA, "Dynamic linker's data segment address", hex);
+       }
+
+      fprintf_filtered (file, "%-4s %-20s %-30s ",
+                       paddr_d (type), name, description);
+      switch (flavor)
+       {
+       case dec:
+         fprintf_filtered (file, "%s\n", paddr_d (val));
+         break;
+       case hex:
+         fprintf_filtered (file, "0x%s\n", paddr_nz (val));
+         break;
+       case str:
+         if (addressprint)
+           fprintf_filtered (file, "0x%s", paddr_nz (val));
+         val_print_string (val, -1, 1, file);
+         fprintf_filtered (file, "\n");
+         break;
+       }
+      ++ents;
+    }
+
+  xfree (data);
+
+  return ents;
+}
+
+static void
+info_auxv_command (char *cmd, int from_tty)
+{
+
+  if (! target_has_stack)
+    error ("The program has no auxiliary information now.");
+  else
+    {
+      int ents = fprint_target_auxv (gdb_stdout, &current_target);
+      if (ents < 0)
+       error ("No auxilary vector found, or failed reading it.");
+      else if (ents == 0)
+       error ("Auxilary vector is empty.");
+    }
+}
+
+
+extern initialize_file_ftype _initialize_auxv; /* -Wmissing-prototypes; */
+
+void
+_initialize_auxv (void)
+{
+  add_info ("auxv", info_auxv_command,
+           "Display the inferior's auxiliary vector.\n\
+This is information provided by the operating system at program startup.");
+}
diff --git a/gdb/auxv.h b/gdb/auxv.h
new file mode 100644 (file)
index 0000000..4ce0569
--- /dev/null
@@ -0,0 +1,75 @@
+/* Auxiliary vector support for GDB, the GNU debugger.
+
+   Copyright 2004 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef AUXV_H
+#define AUXV_H
+
+/* See "include/elf/common.h" for the definition of valid AT_* values.  */
+
+
+/* Avoid miscellaneous includes in this file, so that it can be
+   included by nm-*.h for the procfs_xfer_auxv decl if that is
+   used in NATIVE_XFER_AUXV.  */
+struct target_ops;             /* Forward declaration.  */
+
+
+/* Read all the auxv data into a contiguous xmalloc'd buffer,
+   stored in *DATA.  Return the size in bytes of this data.
+   If zero, there is no data and *DATA is null.
+   if < 0, there was an error and *DATA is null.  */
+extern LONGEST target_auxv_read (struct target_ops *ops, char **data);
+
+/* Read one auxv entry from *READPTR, not reading locations >= ENDPTR.
+   Return 0 if *READPTR is already at the end of the buffer.
+   Return -1 if there is insufficient buffer for a whole entry.
+   Return 1 if an entry was read into *TYPEP and *VALP.  */
+extern int target_auxv_parse (struct target_ops *ops,
+                             char **readptr, char *endptr,
+                             CORE_ADDR *typep, CORE_ADDR *valp);
+
+/* Extract the auxiliary vector entry with a_type matching MATCH.
+   Return zero if no such entry was found, or -1 if there was
+   an error getting the information.  On success, return 1 after
+   storing the entry's value field in *VALP.  */
+extern int target_auxv_search (struct target_ops *ops,
+                              CORE_ADDR match, CORE_ADDR *valp);
+
+/* Print the contents of the target's AUXV on the specified file. */
+extern int fprint_target_auxv (struct ui_file *file, struct target_ops *ops);
+
+
+/* This function is called like a to_xfer_partial hook,
+   but must be called with TARGET_OBJECT_AUXV.
+   It handles access via /proc/PID/auxv, which is the common method.
+   This function is appropriate for doing:
+          #define NATIVE_XFER_AUXV     procfs_xfer_auxv
+   for a native target that uses inftarg.c's child_xfer_partial hook.  */
+
+extern LONGEST procfs_xfer_auxv (struct target_ops *ops,
+                                int /* enum target_object */ object,
+                                const char *annex,
+                                void *readbuf,
+                                const void *writebuf,
+                                ULONGEST offset,
+                                LONGEST len);
+
+
+#endif
diff --git a/gdb/config/sparc/obsd.mt b/gdb/config/sparc/obsd.mt
new file mode 100644 (file)
index 0000000..800cb04
--- /dev/null
@@ -0,0 +1,4 @@
+# Target: OpenBSD/sparc
+TDEPFILES= sparc-tdep.o sparcnbsd-tdep.o sparcobsd-tdep.o nbsd-tdep.o \
+       corelow.o solib.o solib-svr4.o
+TM_FILE= tm-nbsd.h
diff --git a/gdb/config/sparc/obsd64.mt b/gdb/config/sparc/obsd64.mt
new file mode 100644 (file)
index 0000000..a692817
--- /dev/null
@@ -0,0 +1,5 @@
+# Target: OpenBSD/sparc64
+TDEPFILES= sparc64-tdep.o sparc64nbsd-tdep.o sparc64obsd-tdep.o \
+       sparc-tdep.o sparcnbsd-tdep.o nbsd-tdep.o \
+       corelow.o solib.o solib-svr4.o
+TM_FILE= tm-nbsd.h
diff --git a/gdb/sparc64obsd-tdep.c b/gdb/sparc64obsd-tdep.c
new file mode 100644 (file)
index 0000000..190a46b
--- /dev/null
@@ -0,0 +1,210 @@
+/* Target-dependent code for OpenBSD/sparc64.
+
+   Copyright 2004 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include "defs.h"
+#include "frame.h"
+#include "frame-unwind.h"
+#include "osabi.h"
+#include "regset.h"
+#include "symtab.h"
+#include "solib-svr4.h"
+#include "trad-frame.h"
+
+#include "gdb_assert.h"
+
+#include "sparc64-tdep.h"
+#include "nbsd-tdep.h"
+
+/* OpenBSD uses the traditional NetBSD core file format, even for
+   ports that use ELF.  The core files don't use multiple register
+   sets.  Instead, the general-purpose and floating-point registers
+   are lumped together in a single section.  Unlike on NetBSD, OpenBSD
+   uses a different layout for its general-purpose registers than the
+   layout used for ptrace(2).  */
+
+/* From <machine/reg.h>.  */
+const struct sparc_gregset sparc64obsd_core_gregset =
+{
+  0 * 8,                       /* "tstate" */
+  1 * 8,                       /* %pc */
+  2 * 8,                       /* %npc */
+  3 * 8,                       /* %y */
+  -1,                          /* %fprs */
+  -1,
+  7 * 8,                       /* %g1 */
+  22 * 8,                      /* %l0 */
+  4                            /* sizeof (%y) */
+};
+
+static void
+sparc64obsd_supply_gregset (const struct regset *regset,
+                           struct regcache *regcache,
+                           int regnum, const void *gregs, size_t len)
+{
+  const char *regs = gregs;
+
+  sparc64_supply_gregset (regset->descr, regcache, regnum, regs);
+  sparc64_supply_fpregset (regcache, regnum, regs + 288);
+}
+\f
+
+/* Signal trampolines.  */
+
+/* The OpenBSD kernel maps the signal trampoline at some random
+   location in user space, which means that the traditional BSD way of
+   detecting it won't work.
+
+   The signal trampoline will be mapped at an address that is page
+   aligned.  We recognize the signal trampoline by the looking for the
+   sigreturn system call.  */
+
+static const int sparc64obsd_page_size = 8192;
+
+static int
+sparc64obsd_pc_in_sigtramp (CORE_ADDR pc, char *name)
+{
+  CORE_ADDR start_pc = (pc & ~(sparc64obsd_page_size - 1));
+  unsigned long insn;
+
+  if (name)
+    return 0;
+
+  /* Check for "restore %g0, SYS_sigreturn, %g1".  */
+  insn = sparc_fetch_instruction (start_pc + 0xe8);
+  if (insn != 0x83e82067)
+    return 0;
+
+  /* Check for "t ST_SYSCALL".  */
+  insn = sparc_fetch_instruction (start_pc + 0xf0);
+  if (insn != 0x91d02000)
+    return 0;
+
+  return 1;
+}
+
+static struct sparc_frame_cache *
+sparc64obsd_frame_cache (struct frame_info *next_frame, void **this_cache)
+{
+  struct sparc_frame_cache *cache;
+  CORE_ADDR addr;
+
+  if (*this_cache)
+    return *this_cache;
+
+  cache = sparc_frame_cache (next_frame, this_cache);
+  gdb_assert (cache == *this_cache);
+
+  /* If we couldn't find the frame's function, we're probably dealing
+     with an on-stack signal trampoline.  */
+  if (cache->pc == 0)
+    {
+      cache->pc = frame_pc_unwind (next_frame);
+      cache->pc &= ~(sparc64obsd_page_size - 1);
+
+      /* Since we couldn't find the frame's function, the cache was
+         initialized under the assumption that we're frameless.  */
+      cache->frameless_p = 0;
+      addr = frame_unwind_register_unsigned (next_frame, SPARC_FP_REGNUM);
+      cache->base = addr;
+    }
+
+  /* We find the appropriate instance of `struct sigcontext' at a
+     fixed offset in the signal frame.  */
+  addr = cache->base + BIAS + 128 + 16;
+  cache->saved_regs = sparc64nbsd_sigcontext_saved_regs (addr, next_frame);
+
+  return cache;
+}
+
+static void
+sparc64obsd_frame_this_id (struct frame_info *next_frame, void **this_cache,
+                          struct frame_id *this_id)
+{
+  struct sparc_frame_cache *cache =
+    sparc64obsd_frame_cache (next_frame, this_cache);
+
+  (*this_id) = frame_id_build (cache->base, cache->pc);
+}
+
+static void
+sparc64obsd_frame_prev_register (struct frame_info *next_frame,
+                                void **this_cache,
+                                int regnum, int *optimizedp,
+                                enum lval_type *lvalp, CORE_ADDR *addrp,
+                                int *realnump, void *valuep)
+{
+  struct sparc_frame_cache *cache =
+    sparc64obsd_frame_cache (next_frame, this_cache);
+
+  trad_frame_prev_register (next_frame, cache->saved_regs, regnum,
+                           optimizedp, lvalp, addrp, realnump, valuep);
+}
+
+static const struct frame_unwind sparc64obsd_frame_unwind =
+{
+  SIGTRAMP_FRAME,
+  sparc64obsd_frame_this_id,
+  sparc64obsd_frame_prev_register
+};
+
+static const struct frame_unwind *
+sparc64obsd_sigtramp_frame_sniffer (struct frame_info *next_frame)
+{
+  CORE_ADDR pc = frame_pc_unwind (next_frame);
+  char *name;
+
+  find_pc_partial_function (pc, &name, NULL, NULL);
+  if (sparc64obsd_pc_in_sigtramp (pc, name))
+    return &sparc64obsd_frame_unwind;
+
+  return NULL;
+}
+\f
+
+static void
+sparc64obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  tdep->gregset = XMALLOC (struct regset);
+  tdep->gregset->descr = &sparc64obsd_core_gregset;
+  tdep->gregset->supply_regset = sparc64obsd_supply_gregset;
+  tdep->sizeof_gregset = 832;
+
+  set_gdbarch_pc_in_sigtramp (gdbarch, sparc64obsd_pc_in_sigtramp);
+  frame_unwind_append_sniffer (gdbarch, sparc64obsd_sigtramp_frame_sniffer);
+
+  sparc64_init_abi (info, gdbarch);
+
+  set_solib_svr4_fetch_link_map_offsets
+    (gdbarch, nbsd_lp64_solib_svr4_fetch_link_map_offsets);
+}
+
+\f
+/* Provide a prototype to silence -Wmissing-prototypes.  */
+void _initialize_sparc64obsd_tdep (void);
+
+void
+_initialize_sparc64obsd_tdep (void)
+{
+  gdbarch_register_osabi (bfd_arch_sparc, bfd_mach_sparc_v9,
+                         GDB_OSABI_OPENBSD_ELF, sparc64obsd_init_abi);
+}
diff --git a/gdb/sparcobsd-tdep.c b/gdb/sparcobsd-tdep.c
new file mode 100644 (file)
index 0000000..108e255
--- /dev/null
@@ -0,0 +1,171 @@
+/* Target-dependent code for OpenBSD/sparc.
+
+   Copyright 2004 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include "defs.h"
+#include "floatformat.h"
+#include "frame.h"
+#include "frame-unwind.h"
+#include "osabi.h"
+#include "solib-svr4.h"
+#include "symtab.h"
+#include "trad-frame.h"
+
+#include "gdb_assert.h"
+
+#include "sparc-tdep.h"
+#include "nbsd-tdep.h"
+
+/* Signal trampolines.  */
+
+/* The OpenBSD kernel maps the signal trampoline at some random
+   location in user space, which means that the traditional BSD way of
+   detecting it won't work.
+
+   The signal trampoline will be mapped at an address that is page
+   aligned.  We recognize the signal trampoline by the looking for the
+   sigreturn system call.  */
+
+static const int sparc32obsd_page_size = 4096;
+
+static int
+sparc32obsd_pc_in_sigtramp (CORE_ADDR pc, char *name)
+{
+  CORE_ADDR start_pc = (pc & ~(sparc32obsd_page_size - 1));
+  unsigned long insn;
+
+  if (name)
+    return 0;
+
+  /* Check for "restore %g0, SYS_sigreturn, %g1".  */
+  insn = sparc_fetch_instruction (start_pc + 0xec);
+  if (insn != 0x83e82067)
+    return 0;
+
+  /* Check for "t ST_SYSCALL".  */
+  insn = sparc_fetch_instruction (start_pc + 0xf4);
+  if (insn != 0x91d02000)
+    return 0;
+
+  return 1;
+}
+
+static struct sparc_frame_cache *
+sparc32obsd_frame_cache (struct frame_info *next_frame, void **this_cache)
+{
+  struct sparc_frame_cache *cache;
+  CORE_ADDR addr;
+
+  if (*this_cache)
+    return *this_cache;
+
+  cache = sparc_frame_cache (next_frame, this_cache);
+  gdb_assert (cache == *this_cache);
+
+  /* If we couldn't find the frame's function, we're probably dealing
+     with an on-stack signal trampoline.  */
+  if (cache->pc == 0)
+    {
+      cache->pc = frame_pc_unwind (next_frame);
+      cache->pc &= ~(sparc32obsd_page_size - 1);
+
+      /* Since we couldn't find the frame's function, the cache was
+         initialized under the assumption that we're frameless.  */
+      cache->frameless_p = 0;
+      addr = frame_unwind_register_unsigned (next_frame, SPARC_FP_REGNUM);
+      cache->base = addr;
+    }
+
+  cache->saved_regs = sparc32nbsd_sigcontext_saved_regs (next_frame);
+
+  return cache;
+}
+
+static void
+sparc32obsd_frame_this_id (struct frame_info *next_frame, void **this_cache,
+                          struct frame_id *this_id)
+{
+  struct sparc_frame_cache *cache =
+    sparc32obsd_frame_cache (next_frame, this_cache);
+
+  (*this_id) = frame_id_build (cache->base, cache->pc);
+}
+
+static void
+sparc32obsd_frame_prev_register (struct frame_info *next_frame,
+                                void **this_cache,
+                                int regnum, int *optimizedp,
+                                enum lval_type *lvalp, CORE_ADDR *addrp,
+                                int *realnump, void *valuep)
+{
+  struct sparc_frame_cache *cache =
+    sparc32obsd_frame_cache (next_frame, this_cache);
+
+  trad_frame_prev_register (next_frame, cache->saved_regs, regnum,
+                           optimizedp, lvalp, addrp, realnump, valuep);
+}
+
+static const struct frame_unwind sparc32obsd_frame_unwind =
+{
+  SIGTRAMP_FRAME,
+  sparc32obsd_frame_this_id,
+  sparc32obsd_frame_prev_register
+};
+
+static const struct frame_unwind *
+sparc32obsd_sigtramp_frame_sniffer (struct frame_info *next_frame)
+{
+  CORE_ADDR pc = frame_pc_unwind (next_frame);
+  char *name;
+
+  find_pc_partial_function (pc, &name, NULL, NULL);
+  if (sparc32obsd_pc_in_sigtramp (pc, name))
+    return &sparc32obsd_frame_unwind;
+
+  return NULL;
+}
+\f
+
+static void
+sparc32obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  /* OpenBSD doesn't support the 128-bit `long double' from the psABI.  */
+  set_gdbarch_long_double_bit (gdbarch, 64);
+  set_gdbarch_long_double_format (gdbarch, &floatformat_ieee_double_big);
+
+  set_gdbarch_pc_in_sigtramp (gdbarch, sparc32obsd_pc_in_sigtramp);
+  frame_unwind_append_sniffer (gdbarch, sparc32obsd_sigtramp_frame_sniffer);
+
+  set_solib_svr4_fetch_link_map_offsets
+    (gdbarch, nbsd_ilp32_solib_svr4_fetch_link_map_offsets);
+}
+
+\f
+/* Provide a prototype to silence -Wmissing-prototypes.  */
+void _initialize_sparc32obsd_tdep (void);
+
+void
+_initialize_sparc32obsd_tdep (void)
+{
+  gdbarch_register_osabi (bfd_arch_sparc, 0, GDB_OSABI_OPENBSD_ELF,
+                         sparc32obsd_init_abi);
+}
diff --git a/gdb/testsuite/gdb.asm/openbsd.inc b/gdb/testsuite/gdb.asm/openbsd.inc
new file mode 100644 (file)
index 0000000..90e3dbd
--- /dev/null
@@ -0,0 +1,12 @@
+       comment "openbsd .note"
+
+.section       ".note.openbsdbsd.ident", "a"
+       .p2align        2
+
+       .long   8
+       .long   4
+       .long   1
+       .ascii  "OpenBSD\0\0"
+       .long   200311
+
+       .p2align        2
diff --git a/gdb/testsuite/gdb.base/chng-syms.c b/gdb/testsuite/gdb.base/chng-syms.c
new file mode 100644 (file)
index 0000000..3394f5c
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ *   Test that GDB cleans up properly after errors that result when a 
+ * breakpoint is reset. 
+ */
+
+/* VARIABLE is a macro defined on the compiler command line. */
+
+#include <stdlib.h>
+
+int VARIABLE = 42;
+
+void stop_here ()
+{
+  VARIABLE *= 2;
+}
+
+int main ()
+{
+  stop_here ();
+  exit (0);
+}
+
diff --git a/gdb/testsuite/gdb.base/chng-syms.exp b/gdb/testsuite/gdb.base/chng-syms.exp
new file mode 100644 (file)
index 0000000..18f847f
--- /dev/null
@@ -0,0 +1,120 @@
+# Copyright 2004 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# Author: Paul N. Hilfinger (Hilfinger@gnat.com)
+
+# Test that GDB cleans up properly after errors that result when a 
+# breakpoint is reset. 
+
+if $tracelevel then {
+       strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+# IDT/SIM apparently doesn't have enough file descriptors to allow the
+# problem checked by this test to occur.
+if [istarget "mips-idt-*"] {
+    return 0;
+}
+
+set testfile "chng-syms"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-DVARIABLE=var1}] != "" } {
+    gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+set oldtimeout $timeout
+set timeout 10
+verbose "Timeout is now 10 seconds" 2
+
+proc expect_to_stop_here { ident } {
+    global gdb_prompt
+    global decimal
+
+    # the "at foo.c:36" output we get with -g.
+    # the "in func" output we get without -g.
+    gdb_expect {
+       -re "Breakpoint \[0-9\]*, stop_here .*$gdb_prompt $" { 
+           return 1
+       }
+       -re "$gdb_prompt $" { 
+           fail "running to stop_here $ident"
+           return 0
+       }
+       timeout { 
+           fail "running to stop_here $ident (timeout)"
+           return 0
+       }
+    }
+    return 1
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+gdb_test "break stop_here if (var1 == 42)" \
+    "Breakpoint.*at.* file .*$srcfile, line.*" \
+    "setting conditional breakpoint on function"
+gdb_run_cmd
+
+expect_to_stop_here "first time"
+    
+gdb_continue_to_end "breakpoint first time through"
+
+# Now we recompile the executable, but without a variable named "var1", first
+# waiting to insure that even on fast machines, the file modification times
+# are distinct. This will force GDB to reload the file on the 
+# next "run" command, causing an error when GDB tries to tries to reset 
+# the breakpoint.
+
+sleep 2
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-DVARIABLE=var2}] != "" } {
+
+# Complication: Since GDB generally holds an open file descriptor on the 
+# executable at this point, there are some systems in which the 
+# re-compilation will fail. In such cases, we'll consider the test 
+# (vacuously) passed providing that re-running it succeeds as before.
+
+    gdb_run_cmd
+    expect_to_stop_here "after re-compile fails"
+    gdb_continue_to_end "after re-compile fails"
+
+} else {
+
+    gdb_run_cmd
+    gdb_expect {
+       -re "Error in re-setting .*No symbol .var1..*Program exited normally.*" {
+           pass "running with invalidated bpt condition after executable changes" 
+       }
+       timeout {
+           fail "(timeout) running with invalidated bpt condition after executable changes" 
+       }
+    }
+
+}
+
+set timeout $oldtimeout
+verbose "Timeout is now $timeout seconds" 2
+return 0
diff --git a/gdb/testsuite/gdb.base/pending.c b/gdb/testsuite/gdb.base/pending.c
new file mode 100644 (file)
index 0000000..a83a451
--- /dev/null
@@ -0,0 +1,35 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2004 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+   Please email any bugs, comments, and/or additions to this file to:
+   bug-gdb@prep.ai.mit.edu  */
+
+#include <stdio.h>
+
+int k = 0;
+
+extern void pendfunc (int x);
+
+int main()
+{
+  pendfunc (3); /* break main here */
+  pendfunc (4);
+  k = 1;
+  pendfunc (3);
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.base/pending.exp b/gdb/testsuite/gdb.base/pending.exp
new file mode 100644 (file)
index 0000000..2cef30a
--- /dev/null
@@ -0,0 +1,266 @@
+#   Copyright 2003, 2004
+#   Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was created by Jeff Johnston. (jjohnstn@redhat.com)
+# The shared library compilation portion was copied from shlib-call.exp which was
+# written by Elena Zannoni (ezannoni@redhat.com).
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+#
+# test running programs
+#
+set prms_id 0
+set bug_id 0
+
+# are we on a target board?
+if ![isnative] then {
+    return 0
+}
+
+set testfile "pending"
+set libfile "pendshr"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if [get_compiler_info ${binfile}] {
+    return -1
+}
+
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}.o" object {debug}] != "" } {
+     gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+# Build the shared libraries this test case needs.
+#
+
+if {$gcc_compiled == 0} {
+    if [istarget "hppa*-hp-hpux*"] then {
+       set additional_flags "additional_flags=+z"
+    } elseif { [istarget "mips-sgi-irix*"] } {
+       # Disable SGI compiler's implicit -Dsgi
+       set additional_flags "additional_flags=-Usgi"
+    } else {
+       # don't know what the compiler is...
+       set additional_flags ""
+    }
+} else {
+    if { ([istarget "powerpc*-*-aix*"]
+       || [istarget "rs6000*-*-aix*"]) } {
+       set additional_flags ""
+    } else {
+       set additional_flags "additional_flags=-fpic"
+    }
+}
+
+if {[gdb_compile "${srcdir}/${subdir}/${libfile}.c" "${objdir}/${subdir}/${libfile}.o" object [list debug $additional_flags]] != ""} {
+     gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+if [istarget "hppa*-*-hpux*"] {
+    remote_exec build "ld -b ${objdir}/${subdir}/${libfile}.o -o ${objdir}/${subdir}/${libfile}.sl"
+} else {
+    set additional_flags "additional_flags=-shared"
+    if {[gdb_compile "${objdir}/${subdir}/${libfile}.o" "${objdir}/${subdir}/${libfile}.sl" executable [list debug $additional_flags]] != ""} {
+       gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+    }
+}
+
+if { ($gcc_compiled 
+      &&  ([istarget "powerpc*-*-aix*"]
+       || [istarget "rs6000*-*-aix*"] )) } {
+    set additional_flags "additional_flags=-L${objdir}/${subdir}"
+} elseif { [istarget "mips-sgi-irix*"] } {
+    set additional_flags "additional_flags=-rpath ${objdir}/${subdir}"
+} else {
+    set additional_flags ""
+}
+if {[gdb_compile "${objdir}/${subdir}/${testfile}.o ${objdir}/${subdir}/${libfile}.sl" "${binfile}" executable [list debug $additional_flags]] != ""} {
+     gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if [target_info exists gdb_stub] {
+    gdb_step_for_stub;
+}
+#
+# Test setting, querying, and modifying pending breakpoints
+#
+
+gdb_test_multiple "break pendfunc1" "set pending breakpoint" {
+     -re ".*Make breakpoint pending.*y or n. $" {
+           gdb_test "y" "Breakpoint.*pendfunc1.*pending." "set pending breakpoint"
+     }
+}
+
+gdb_test "info break" \
+    "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+\[0-9\]+\[\t \]+breakpoint     keep y.*PENDING.*pendfunc1.*" \
+"single pending breakpoint info"
+
+#
+# Test breaking at existing function
+#
+
+set mainline [gdb_get_line_number "break main here"]
+
+gdb_test "break main" \
+    "Breakpoint.*at.* file .*$srcfile, line $mainline.*" \
+    "breakpoint function"
+
+gdb_test "info break" \
+    "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+\[0-9\]+\[\t \]+breakpoint     keep y.*PENDING.*pendfunc1.*
+\[0-9\]+\[\t \]+breakpoint     keep y.* in main at .*$srcfile:$mainline" \
+"pending plus real breakpoint info"
+
+
+# 
+# Test not setting a pending breakpoint 
+#
+gdb_test_multiple "break pendfunc2" "Don't set pending breakpoint" {
+     -re ".*Make breakpoint pending.*y or n. $" {
+           gdb_test "n" "" "Don't set pending breakpoint"
+     }
+}
+
+#
+# Add condition to pending breakpoint 
+#
+
+gdb_test "condition 1 k == 1" ""
+
+gdb_test "info break" \
+    "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+\[0-9\]+\[\t \]+breakpoint     keep y.*PENDING.*pendfunc1.*
+\[\t \]+stop only if k == 1.*
+\[0-9\]+\[\t \]+breakpoint     keep y.* in main at .*$srcfile:$mainline" \
+"pending plus condition"
+
+#
+# Disable pending breakpoint
+#
+
+gdb_test "disable 1" ""
+
+gdb_test "info break" \
+    "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+\[0-9\]+\[\t \]+breakpoint     keep n.*PENDING.*pendfunc1.*
+\[\t \]+stop only if k == 1.*
+\[0-9\]+\[\t \]+breakpoint     keep y.* in main at .*$srcfile:$mainline" \
+"pending disabled"
+
+#
+# Add commands to pending breakpoint
+#
+gdb_test "commands 1\nprint k\nend" "" \
+        "Set commands for pending breakpoint"
+
+gdb_test "info break" \
+    "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+\[0-9\]+\[\t \]+breakpoint     keep n.*PENDING.*pendfunc1.*
+\[\t \]+stop only if k == 1.*
+\[\t \]+print k.*
+\[0-9\]+\[\t \]+breakpoint     keep y.* in main at .*$srcfile:$mainline" \
+"pending disabled plus commands"
+
+#
+# Try a pending break for a line in a source file with a condition
+#
+
+gdb_test_multiple "break pendshr.c:26 if x > 3" "Set pending breakpoint 2" {
+     -re ".*Make breakpoint pending.*y or n. $" {
+           gdb_test "y" "Breakpoint.*pendshr.c:26.*pending." \
+               "Set pending breakpoint 2"
+     }
+}
+
+gdb_test "info break" \
+    "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+\[0-9\]+\[\t \]+breakpoint     keep n.*PENDING.*pendfunc1.*
+\[\t \]+stop only if k == 1.*
+\[\t \]+print k.*
+\[0-9\]+\[\t \]+breakpoint     keep y.* in main at .*$srcfile:$mainline.*
+\[0-9\]+\[\t \]+breakpoint     keep y.*PENDING.*pendshr.c:26 if x > 3.*" \
+"multiple pending breakpoints"
+
+#
+# Run to main which should resolve a pending breakpoint
+#
+
+gdb_test "run" \
+"Breakpoint.*at.*
+Pending breakpoint \"pendshr.c:26 if x > 3\" resolved.*
+Breakpoint.*, main.*$mainline.*" \
+"running to main"
+
+#
+# Re-enable the first pending breakpoint which should resolve
+#
+
+gdb_test "enable 1" \
+"Breakpoint.*at.*
+Pending breakpoint \"pendfunc1.* resolved.*" \
+"re-enabling pending breakpoint that can resolve instantly"
+
+#
+# Continue to verify conditionals and commands for breakpoints are honored
+#
+
+gdb_test "continue" \
+".*Breakpoint.*pendfunc1.*at.*pendshr.c:26.*4;" \
+"continue to resolved breakpoint 2"
+
+gdb_test "continue" \
+".*Breakpoint.*pendfunc1.*at.*pendshr.c:26.*
+\[$\]1 = 1." \
+"continue to resolved breakpoint 1"
+
+delete_breakpoints
+
+gdb_breakpoint "main"
+
+#
+# Set non-existent pending breakpoint
+#
+gdb_test_multiple "break imaginary" "set imaginary pending breakpoint" {
+     -re ".*Make breakpoint pending.*y or n. $" {
+           gdb_test "y" "Breakpoint.*imaginary.*pending." \
+               "set imaginary pending breakpoint"
+     }
+}
+
+#
+# rerun program and make sure that any pending breakpoint remains and no
+# error messages are issued for the missing function
+#
+
+rerun_to_main
+gdb_test "info break" \
+    "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+\[0-9\]+\[\t \]+breakpoint     keep y.* in main at .*$srcfile:$mainline.*
+\[0-9\]+\[\t \]+breakpoint     keep y.*PENDING.*imaginary.*" \
+"verify pending breakpoint after restart"
diff --git a/gdb/testsuite/gdb.base/pendshr.c b/gdb/testsuite/gdb.base/pendshr.c
new file mode 100644 (file)
index 0000000..672fe8a
--- /dev/null
@@ -0,0 +1,33 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2004 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+   Please email any bugs, comments, and/or additions to this file to:
+   bug-gdb@prep.ai.mit.edu  */
+
+#include <stdio.h>
+
+void pendfunc1 (int x)
+{
+  int y = x + 4;
+  printf ("in pendfunc1, x is %d\n", x);
+}
+
+void pendfunc (int x)
+{
+  pendfunc1 (x);
+}
diff --git a/gdb/testsuite/gdb.threads/thread-specific.c b/gdb/testsuite/gdb.threads/thread-specific.c
new file mode 100644 (file)
index 0000000..88a462d
--- /dev/null
@@ -0,0 +1,66 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2004 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <pthread.h>
+
+void *thread_function(void *arg);
+
+unsigned int args[1];
+
+int main() {
+    int res;
+    pthread_t threads[2];
+    void *thread_result;
+    long i = 1;
+
+    args[0] = 1;
+    res = pthread_create(&threads[0],
+                        NULL,
+                        thread_function,
+                        (void *) 0);
+
+    /* thread-specific.exp: last thread start.  */
+    args[1] = 1;
+
+    /* Don't run forever.  Run just short of it :)  */
+    while (i > 0)
+      {
+       /* thread-specific.exp: main loop.  */
+       (i) ++;
+      }
+
+    exit(EXIT_SUCCESS);
+}
+
+void *thread_function(void *arg) {
+    int my_number =  (long) arg;
+    int *myp = &args[my_number];
+
+    /* Don't run forever.  Run just short of it :)  */
+    while (*myp > 0)
+      {
+       /* thread-specific.exp: thread loop.  */
+       (*myp) ++;
+      }
+
+    pthread_exit(NULL);
+}
diff --git a/gdb/testsuite/gdb.threads/thread-specific.exp b/gdb/testsuite/gdb.threads/thread-specific.exp
new file mode 100644 (file)
index 0000000..ffcaaad
--- /dev/null
@@ -0,0 +1,110 @@
+# Copyright 2004 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Daniel Jacobowitz <drow@mvista.com>.
+# It tests that the correct breakpoint is reported when we hit a
+# thread-specific breakpoint inserted for several threads.
+
+if $tracelevel then {
+       strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile "thread-specific"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "incdir=${objdir}"]] != "" } {
+    return -1
+}
+
+# Return a list of the valid thread IDs, with the initial thread first.
+proc get_thread_list { } {
+  global gdb_prompt
+  global expect_out
+
+  set thr_list ""
+
+  gdb_test_multiple "info threads" "get threads list" {
+    -re "info threads\r\n" {
+      exp_continue
+    }
+    -re "^\\*  *(\[0-9\]*) Thread \[^\n\]*main\[^\n\]*\n" {
+      set thr_list "$expect_out(1,string) $thr_list"
+      exp_continue
+    }
+    -re "^  *(\[0-9\]*) Thread \[^\n\]*\n" {
+      lappend thr_list $expect_out(1,string)
+      exp_continue
+    }
+    -re ".*$gdb_prompt $" {
+      if { [llength $thr_list] != 0 } {
+       pass "get threads list"
+      } else {
+       fail "get threads list (no threads)"
+      }
+    }
+  }
+
+  return $thr_list
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+gdb_load ${binfile}
+
+gdb_test "set print sevenbit-strings" ""
+gdb_test "set width 0" ""
+
+runto_main
+
+gdb_breakpoint [gdb_get_line_number "thread-specific.exp: last thread start"]
+gdb_continue_to_breakpoint "all threads started"
+
+set line [gdb_get_line_number "thread-specific.exp: thread loop"]
+set threads [get_thread_list]
+
+gdb_test_multiple "break $line thread [lindex $threads 0]" \
+  "breakpoint $line main thread" {
+    -re "Breakpoint (\[0-9\]*) at.* file .*$srcfile, line.*$gdb_prompt $" {
+      set main_breakpoint $expect_out(1,string)
+      pass "breakpoint $line main thread"
+    }
+}
+
+foreach thread [lrange $threads 1 end] {
+  gdb_breakpoint "$line thread $thread"
+}
+
+gdb_test_multiple "continue" "continue to thread-specific breakpoint" {
+       -re "Breakpoint $main_breakpoint, .* at .*\r\n$gdb_prompt $" {
+           fail "continue to thread-specific breakpoint (wrong breakpoint)"
+       }
+       -re "Breakpoint .* at .*\r\n$gdb_prompt $" {
+           pass "continue to thread-specific breakpoint"
+       }
+}
+
+return 0
diff --git a/gdb/tui/tui-command.c b/gdb/tui/tui-command.c
new file mode 100644 (file)
index 0000000..a182b4c
--- /dev/null
@@ -0,0 +1,136 @@
+/* Specific command window processing.
+
+   Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
+   Foundation, Inc.
+
+   Contributed by Hewlett-Packard Company.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include "defs.h"
+#include <ctype.h>
+#include "tui/tui.h"
+#include "tui/tui-data.h"
+#include "tui/tui-win.h"
+#include "tui/tui-io.h"
+
+#ifdef HAVE_NCURSES_H       
+#include <ncurses.h>
+#else
+#ifdef HAVE_CURSES_H
+#include <curses.h>
+#endif
+#endif
+
+
+/*****************************************
+** STATIC LOCAL FUNCTIONS FORWARD DECLS    **
+******************************************/
+
+
+
+/*****************************************
+** PUBLIC FUNCTIONS                        **
+******************************************/
+
+/* Dispatch the correct tui function based upon the control character.   */
+unsigned int
+tui_dispatch_ctrl_char (unsigned int ch)
+{
+  struct tui_win_info *win_info = tui_win_with_focus ();
+  WINDOW *w = TUI_CMD_WIN->generic.handle;
+
+  /*
+     ** If the command window has the logical focus, or no-one does
+     ** assume it is the command window; in this case, pass the
+     ** character on through and do nothing here.
+   */
+  if (win_info == NULL || win_info == TUI_CMD_WIN)
+    return ch;
+  else
+    {
+      unsigned int c = 0, ch_copy = ch;
+      int i;
+      char *term;
+
+      /* If this is an xterm, page next/prev keys aren't returned
+         ** by keypad as a single char, so we must handle them here.
+         ** Seems like a bug in the curses library?
+       */
+      term = (char *) getenv ("TERM");
+      for (i = 0; (term && term[i]); i++)
+       term[i] = toupper (term[i]);
+      if ((strcmp (term, "XTERM") == 0) && key_is_start_sequence (ch))
+       {
+         unsigned int page_ch = 0;
+         unsigned int tmp_char;
+
+         tmp_char = 0;
+         while (!key_is_end_sequence (tmp_char))
+           {
+             tmp_char = (int) wgetch (w);
+             if (tmp_char == ERR)
+               {
+                 return ch;
+               }
+             if (!tmp_char)
+               break;
+             if (tmp_char == 53)
+               page_ch = KEY_PPAGE;
+             else if (tmp_char == 54)
+               page_ch = KEY_NPAGE;
+             else
+               {
+                 return 0;
+               }
+           }
+         ch_copy = page_ch;
+       }
+
+      switch (ch_copy)
+       {
+       case KEY_NPAGE:
+         tui_scroll_forward (win_info, 0);
+         break;
+       case KEY_PPAGE:
+         tui_scroll_backward (win_info, 0);
+         break;
+       case KEY_DOWN:
+       case KEY_SF:
+         tui_scroll_forward (win_info, 1);
+         break;
+       case KEY_UP:
+       case KEY_SR:
+         tui_scroll_backward (win_info, 1);
+         break;
+       case KEY_RIGHT:
+         tui_scroll_left (win_info, 1);
+         break;
+       case KEY_LEFT:
+         tui_scroll_right (win_info, 1);
+         break;
+       case '\f':
+         tui_refresh_all_win ();
+         break;
+       default:
+         c = ch_copy;
+         break;
+       }
+      return c;
+    }
+}
diff --git a/gdb/tui/tui-command.h b/gdb/tui/tui-command.h
new file mode 100644 (file)
index 0000000..9653bf0
--- /dev/null
@@ -0,0 +1,30 @@
+/* Specific command window processing.
+
+   Copyright 1998, 1999, 2000, 2001, 2004 Free Software Foundation,
+   Inc.
+
+   Contributed by Hewlett-Packard Company.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef TUI_COMMAND_H
+#define TUI_COMMAND_H
+
+extern unsigned int tui_dispatch_ctrl_char (unsigned int);
+
+#endif
diff --git a/gdb/tui/tui-data.c b/gdb/tui/tui-data.c
new file mode 100644 (file)
index 0000000..1f41023
--- /dev/null
@@ -0,0 +1,928 @@
+/* TUI data manipulation routines.
+
+   Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
+   Foundation, Inc.
+
+   Contributed by Hewlett-Packard Company.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include "defs.h"
+#include "symtab.h"
+#include "tui/tui.h"
+#include "tui/tui-data.h"
+#include "tui/tui-wingeneral.h"
+
+#include "gdb_string.h"
+
+#ifdef HAVE_NCURSES_H       
+#include <ncurses.h>
+#else
+#ifdef HAVE_CURSES_H
+#include <curses.h>
+#endif
+#endif
+
+/****************************
+** GLOBAL DECLARATIONS
+****************************/
+struct tui_win_info *(tui_win_list[MAX_MAJOR_WINDOWS]);
+
+/***************************
+** Private data
+****************************/
+static enum tui_layout_type current_layout = UNDEFINED_LAYOUT;
+static int term_height, term_width;
+static struct tui_gen_win_info _locator;
+static struct tui_gen_win_info exec_info[2];
+static struct tui_win_info * src_win_list[2];
+static struct tui_list source_windows = {(void **) src_win_list, 0};
+static int default_tab_len = DEFAULT_TAB_LEN;
+static struct tui_win_info * win_with_focus = (struct tui_win_info *) NULL;
+static struct tui_layout_def layout_def =
+{SRC_WIN,                      /* DISPLAY_MODE */
+ FALSE,                                /* SPLIT */
+ TUI_UNDEFINED_REGS,           /* REGS_DISPLAY_TYPE */
+ TUI_SFLOAT_REGS};             /* FLOAT_REGS_DISPLAY_TYPE */
+static int win_resized = FALSE;
+
+
+/*********************************
+** Static function forward decls
+**********************************/
+static void free_content (tui_win_content, int, enum tui_win_type);
+static void free_content_elements (tui_win_content, int, enum tui_win_type);
+
+
+
+/*********************************
+** PUBLIC FUNCTIONS
+**********************************/
+
+int
+tui_win_is_source_type (enum tui_win_type win_type)
+{
+  return (win_type == SRC_WIN || win_type == DISASSEM_WIN);
+}
+
+int
+tui_win_is_auxillary (enum tui_win_type win_type)
+{
+  return (win_type > MAX_MAJOR_WINDOWS);
+}
+
+int
+tui_win_has_locator (struct tui_win_info *win_info)
+{
+  return (win_info != NULL \
+         && win_info->detail.source_info.has_locator);
+}
+
+void
+tui_set_win_highlight (struct tui_win_info *win_info, int highlight)
+{
+  if (win_info != NULL)
+    win_info->is_highlighted = highlight;
+}
+
+/******************************************
+** ACCESSORS & MUTATORS FOR PRIVATE DATA
+******************************************/
+
+/* Answer a whether the terminal window has been resized or not.   */
+int
+tui_win_resized (void)
+{
+  return win_resized;
+}
+
+
+/* Set a whether the terminal window has been resized or not.   */
+void
+tui_set_win_resized_to (int resized)
+{
+  win_resized = resized;
+}
+
+
+/* Answer a pointer to the current layout definition.   */
+struct tui_layout_def *
+tui_layout_def (void)
+{
+  return &layout_def;
+}
+
+
+/* Answer the window with the logical focus.    */
+struct tui_win_info *
+tui_win_with_focus (void)
+{
+  return win_with_focus;
+}
+
+
+/* Set the window that has the logical focus.   */
+void
+tui_set_win_with_focus (struct tui_win_info * win_info)
+{
+  win_with_focus = win_info;
+}
+
+
+/* Answer the length in chars, of tabs.    */
+int
+tui_default_tab_len (void)
+{
+  return default_tab_len;
+}
+
+
+/* Set the length in chars, of tabs.   */
+void
+tui_set_default_tab_len (int len)
+{
+  default_tab_len = len;
+}
+
+
+/* Accessor for the current source window.  Usually there is only one
+   source window (either source or disassembly), but both can be
+   displayed at the same time.  */
+struct tui_list *
+tui_source_windows (void)
+{
+  return &source_windows;
+}
+
+
+/* Clear the list of source windows.  Usually there is only one source
+   window (either source or disassembly), but both can be displayed at
+   the same time.  */
+void
+tui_clear_source_windows (void)
+{
+  source_windows.list[0] = NULL;
+  source_windows.list[1] = NULL;
+  source_windows.count = 0;
+}
+
+
+/* Clear the pertinant detail in the source windows.   */
+void
+tui_clear_source_windows_detail (void)
+{
+  int i;
+
+  for (i = 0; i < (tui_source_windows ())->count; i++)
+    tui_clear_win_detail ((struct tui_win_info *) (tui_source_windows ())->list[i]);
+}
+
+
+/* Add a window to the list of source windows.  Usually there is only
+   one source window (either source or disassembly), but both can be
+   displayed at the same time.  */
+void
+tui_add_to_source_windows (struct tui_win_info * win_info)
+{
+  if (source_windows.count < 2)
+    source_windows.list[source_windows.count++] = (void *) win_info;
+}
+
+
+/* Clear the pertinant detail in the windows.   */
+void
+tui_clear_win_detail (struct tui_win_info * win_info)
+{
+  if (win_info != NULL)
+    {
+      switch (win_info->generic.type)
+       {
+       case SRC_WIN:
+       case DISASSEM_WIN:
+         win_info->detail.source_info.start_line_or_addr.addr = 0;
+         win_info->detail.source_info.horizontal_offset = 0;
+         break;
+       case CMD_WIN:
+         win_info->detail.command_info.cur_line =
+           win_info->detail.command_info.curch = 0;
+         break;
+       case DATA_WIN:
+         win_info->detail.data_display_info.data_content =
+           (tui_win_content) NULL;
+         win_info->detail.data_display_info.data_content_count = 0;
+         win_info->detail.data_display_info.regs_content =
+           (tui_win_content) NULL;
+         win_info->detail.data_display_info.regs_content_count = 0;
+         win_info->detail.data_display_info.regs_display_type =
+           TUI_UNDEFINED_REGS;
+         win_info->detail.data_display_info.regs_column_count = 1;
+         win_info->detail.data_display_info.display_regs = FALSE;
+         break;
+       default:
+         break;
+       }
+    }
+}
+
+
+/* Accessor for the source execution info ptr.  */
+struct tui_gen_win_info *
+tui_source_exec_info_win_ptr (void)
+{
+  return &exec_info[0];
+}
+
+
+/* Accessor for the disassem execution info ptr.  */
+struct tui_gen_win_info *
+tui_disassem_exec_info_win_ptr (void)
+{
+  return &exec_info[1];
+}
+
+
+/* Accessor for the locator win info.  Answers a pointer to the static
+   locator win info struct.  */
+struct tui_gen_win_info *
+tui_locator_win_info_ptr (void)
+{
+  return &_locator;
+}
+
+
+/* Accessor for the term_height.  */
+int
+tui_term_height (void)
+{
+  return term_height;
+}
+
+
+/* Mutator for the term height.   */
+void
+tui_set_term_height_to (int h)
+{
+  term_height = h;
+}
+
+
+/* Accessor for the term_width.   */
+int
+tui_term_width (void)
+{
+  return term_width;
+}
+
+
+/* Mutator for the term_width.  */
+void
+tui_set_term_width_to (int w)
+{
+  term_width = w;
+}
+
+
+/* Accessor for the current layout.   */
+enum tui_layout_type
+tui_current_layout (void)
+{
+  return current_layout;
+}
+
+
+/* Mutator for the current layout.  */
+void
+tui_set_current_layout_to (enum tui_layout_type new_layout)
+{
+  current_layout = new_layout;
+}
+
+
+/* Set the origin of the window.  */
+void
+set_gen_win_origin (struct tui_gen_win_info * win_info, int x, int y)
+{
+  win_info->origin.x = x;
+  win_info->origin.y = y;
+}
+
+
+/*****************************
+** OTHER PUBLIC FUNCTIONS
+*****************************/
+
+
+/* Answer the next window in the list, cycling back to the top if
+   necessary.  */
+struct tui_win_info *
+tui_next_win (struct tui_win_info * cur_win)
+{
+  enum tui_win_type type = cur_win->generic.type;
+  struct tui_win_info * next_win = (struct tui_win_info *) NULL;
+
+  if (cur_win->generic.type == CMD_WIN)
+    type = SRC_WIN;
+  else
+    type = cur_win->generic.type + 1;
+  while (type != cur_win->generic.type && (next_win == NULL))
+    {
+      if (tui_win_list[type] && tui_win_list[type]->generic.is_visible)
+       next_win = tui_win_list[type];
+      else
+       {
+         if (type == CMD_WIN)
+           type = SRC_WIN;
+         else
+           type++;
+       }
+    }
+
+  return next_win;
+}
+
+
+/* Answer the prev window in the list, cycling back to the bottom if
+   necessary.  */
+struct tui_win_info *
+tui_prev_win (struct tui_win_info * cur_win)
+{
+  enum tui_win_type type = cur_win->generic.type;
+  struct tui_win_info * prev = (struct tui_win_info *) NULL;
+
+  if (cur_win->generic.type == SRC_WIN)
+    type = CMD_WIN;
+  else
+    type = cur_win->generic.type - 1;
+  while (type != cur_win->generic.type && (prev == NULL))
+    {
+      if (tui_win_list[type]->generic.is_visible)
+       prev = tui_win_list[type];
+      else
+       {
+         if (type == SRC_WIN)
+           type = CMD_WIN;
+         else
+           type--;
+       }
+    }
+
+  return prev;
+}
+
+
+/* Answer the window represented by name.    */
+struct tui_win_info *
+tui_partial_win_by_name (char *name)
+{
+  struct tui_win_info * win_info = (struct tui_win_info *) NULL;
+
+  if (name != (char *) NULL)
+    {
+      int i = 0;
+
+      while (i < MAX_MAJOR_WINDOWS && win_info == NULL)
+       {
+          if (tui_win_list[i] != 0)
+            {
+              char *cur_name = tui_win_name (&tui_win_list[i]->generic);
+              if (strlen (name) <= strlen (cur_name) &&
+                  strncmp (name, cur_name, strlen (name)) == 0)
+                win_info = tui_win_list[i];
+            }
+         i++;
+       }
+    }
+
+  return win_info;
+}
+
+
+/* Answer the name of the window.  */
+char *
+tui_win_name (struct tui_gen_win_info * win_info)
+{
+  char *name = (char *) NULL;
+
+  switch (win_info->type)
+    {
+    case SRC_WIN:
+      name = SRC_NAME;
+      break;
+    case CMD_WIN:
+      name = CMD_NAME;
+      break;
+    case DISASSEM_WIN:
+      name = DISASSEM_NAME;
+      break;
+    case DATA_WIN:
+      name = DATA_NAME;
+      break;
+    default:
+      name = "";
+      break;
+    }
+
+  return name;
+}
+
+
+void
+tui_initialize_static_data (void)
+{
+  tui_init_generic_part (tui_source_exec_info_win_ptr ());
+  tui_init_generic_part (tui_disassem_exec_info_win_ptr ());
+  tui_init_generic_part (tui_locator_win_info_ptr ());
+}
+
+
+struct tui_gen_win_info *
+tui_alloc_generic_win_info (void)
+{
+  struct tui_gen_win_info * win;
+
+  if ((win = (struct tui_gen_win_info *) xmalloc (
+                    sizeof (struct tui_gen_win_info *))) != (struct tui_gen_win_info *) NULL)
+    tui_init_generic_part (win);
+
+  return win;
+}
+
+
+void
+tui_init_generic_part (struct tui_gen_win_info * win)
+{
+  win->width =
+    win->height =
+    win->origin.x =
+    win->origin.y =
+    win->viewport_height =
+    win->content_size =
+    win->last_visible_line = 0;
+  win->handle = (WINDOW *) NULL;
+  win->content = NULL;
+  win->content_in_use =
+    win->is_visible = FALSE;
+  win->title = 0;
+}
+
+
+/*
+   ** init_content_element().
+ */
+void
+init_content_element (struct tui_win_element * element, enum tui_win_type type)
+{
+  element->highlight = FALSE;
+  switch (type)
+    {
+    case SRC_WIN:
+    case DISASSEM_WIN:
+      element->which_element.source.line = (char *) NULL;
+      element->which_element.source.line_or_addr.line_no = 0;
+      element->which_element.source.is_exec_point = FALSE;
+      element->which_element.source.has_break = FALSE;
+      break;
+    case DATA_WIN:
+      tui_init_generic_part (&element->which_element.data_window);
+      element->which_element.data_window.type = DATA_ITEM_WIN;
+      ((struct tui_gen_win_info *) & element->which_element.data_window)->content =
+       (void **) tui_alloc_content (1, DATA_ITEM_WIN);
+      ((struct tui_gen_win_info *)
+       & element->which_element.data_window)->content_size = 1;
+      break;
+    case CMD_WIN:
+      element->which_element.command.line = (char *) NULL;
+      break;
+    case DATA_ITEM_WIN:
+      element->which_element.data.name = (char *) NULL;
+      element->which_element.data.type = TUI_REGISTER;
+      element->which_element.data.item_no = UNDEFINED_ITEM;
+      element->which_element.data.value = NULL;
+      element->which_element.data.highlight = FALSE;
+      break;
+    case LOCATOR_WIN:
+      element->which_element.locator.file_name[0] =
+       element->which_element.locator.proc_name[0] = (char) 0;
+      element->which_element.locator.line_no = 0;
+      element->which_element.locator.addr = 0;
+      break;
+    case EXEC_INFO_WIN:
+      memset(element->which_element.simple_string, ' ',
+             sizeof(element->which_element.simple_string));
+      break;
+    default:
+      break;
+    }
+}
+
+void
+init_win_info (struct tui_win_info * win_info)
+{
+  tui_init_generic_part (&win_info->generic);
+  win_info->can_highlight =
+    win_info->is_highlighted = FALSE;
+  switch (win_info->generic.type)
+    {
+    case SRC_WIN:
+    case DISASSEM_WIN:
+      win_info->detail.source_info.execution_info = (struct tui_gen_win_info *) NULL;
+      win_info->detail.source_info.has_locator = FALSE;
+      win_info->detail.source_info.horizontal_offset = 0;
+      win_info->detail.source_info.start_line_or_addr.addr = 0;
+      win_info->detail.source_info.filename = 0;
+      break;
+    case DATA_WIN:
+      win_info->detail.data_display_info.data_content = (tui_win_content) NULL;
+      win_info->detail.data_display_info.data_content_count = 0;
+      win_info->detail.data_display_info.regs_content = (tui_win_content) NULL;
+      win_info->detail.data_display_info.regs_content_count = 0;
+      win_info->detail.data_display_info.regs_display_type =
+       TUI_UNDEFINED_REGS;
+      win_info->detail.data_display_info.regs_column_count = 1;
+      win_info->detail.data_display_info.display_regs = FALSE;
+      break;
+    case CMD_WIN:
+      win_info->detail.command_info.cur_line = 0;
+      win_info->detail.command_info.curch = 0;
+      break;
+    default:
+      win_info->detail.opaque = NULL;
+      break;
+    }
+}
+
+
+struct tui_win_info *
+tui_alloc_win_info (enum tui_win_type type)
+{
+  struct tui_win_info * win_info = (struct tui_win_info *) NULL;
+
+  win_info = (struct tui_win_info *) xmalloc (sizeof (struct tui_win_info));
+  if ((win_info != NULL))
+    {
+      win_info->generic.type = type;
+      init_win_info (win_info);
+    }
+
+  return win_info;
+}
+
+
+/* Allocates the content and elements in a block.  */
+tui_win_content
+tui_alloc_content (int num_elements, enum tui_win_type type)
+{
+  tui_win_content content = (tui_win_content) NULL;
+  char *element_block_ptr = (char *) NULL;
+  int i;
+
+  if ((content = (tui_win_content)
+  xmalloc (sizeof (struct tui_win_element *) * num_elements)) != (tui_win_content) NULL)
+    {                          /*
+                                  ** All windows, except the data window, can allocate the elements
+                                  ** in a chunk.  The data window cannot because items can be
+                                  ** added/removed from the data display by the user at any time.
+                                */
+      if (type != DATA_WIN)
+       {
+         if ((element_block_ptr = (char *)
+          xmalloc (sizeof (struct tui_win_element) * num_elements)) != (char *) NULL)
+           {
+             for (i = 0; i < num_elements; i++)
+               {
+                 content[i] = (struct tui_win_element *) element_block_ptr;
+                 init_content_element (content[i], type);
+                 element_block_ptr += sizeof (struct tui_win_element);
+               }
+           }
+         else
+           {
+             xfree (content);
+             content = (tui_win_content) NULL;
+           }
+       }
+    }
+
+  return content;
+}
+
+
+/* Adds the input number of elements to the windows's content.  If no
+   content has been allocated yet, alloc_content() is called to do
+   this.  The index of the first element added is returned, unless
+   there is a memory allocation error, in which case, (-1) is
+   returned.  */
+int
+tui_add_content_elements (struct tui_gen_win_info * win_info, int num_elements)
+{
+  struct tui_win_element * element_ptr;
+  int i, index_start;
+
+  if (win_info->content == NULL)
+    {
+      win_info->content = (void **) tui_alloc_content (num_elements, win_info->type);
+      index_start = 0;
+    }
+  else
+    index_start = win_info->content_size;
+  if (win_info->content != NULL)
+    {
+      for (i = index_start; (i < num_elements + index_start); i++)
+       {
+         if ((element_ptr = (struct tui_win_element *)
+              xmalloc (sizeof (struct tui_win_element))) != (struct tui_win_element *) NULL)
+           {
+             win_info->content[i] = (void *) element_ptr;
+             init_content_element (element_ptr, win_info->type);
+             win_info->content_size++;
+           }
+         else                  /* things must be really hosed now! We ran out of memory!? */
+           return (-1);
+       }
+    }
+
+  return index_start;
+}
+
+
+/* Delete all curses windows associated with win_info, leaving everything
+   else intact.  */
+void
+tui_del_window (struct tui_win_info * win_info)
+{
+  struct tui_gen_win_info * generic_win;
+
+  switch (win_info->generic.type)
+    {
+    case SRC_WIN:
+    case DISASSEM_WIN:
+      generic_win = tui_locator_win_info_ptr ();
+      if (generic_win != (struct tui_gen_win_info *) NULL)
+       {
+         tui_delete_win (generic_win->handle);
+         generic_win->handle = (WINDOW *) NULL;
+         generic_win->is_visible = FALSE;
+       }
+      if (win_info->detail.source_info.filename)
+        {
+          xfree (win_info->detail.source_info.filename);
+          win_info->detail.source_info.filename = 0;
+        }
+      generic_win = win_info->detail.source_info.execution_info;
+      if (generic_win != (struct tui_gen_win_info *) NULL)
+       {
+         tui_delete_win (generic_win->handle);
+         generic_win->handle = (WINDOW *) NULL;
+         generic_win->is_visible = FALSE;
+       }
+      break;
+    case DATA_WIN:
+      if (win_info->generic.content != NULL)
+       {
+         tui_del_data_windows (win_info->detail.data_display_info.regs_content,
+                               win_info->detail.data_display_info.regs_content_count);
+         tui_del_data_windows (win_info->detail.data_display_info.data_content,
+                               win_info->detail.data_display_info.data_content_count);
+       }
+      break;
+    default:
+      break;
+    }
+  if (win_info->generic.handle != (WINDOW *) NULL)
+    {
+      tui_delete_win (win_info->generic.handle);
+      win_info->generic.handle = (WINDOW *) NULL;
+      win_info->generic.is_visible = FALSE;
+    }
+}
+
+
+void
+tui_free_window (struct tui_win_info * win_info)
+{
+  struct tui_gen_win_info * generic_win;
+
+  switch (win_info->generic.type)
+    {
+    case SRC_WIN:
+    case DISASSEM_WIN:
+      generic_win = tui_locator_win_info_ptr ();
+      if (generic_win != (struct tui_gen_win_info *) NULL)
+       {
+         tui_delete_win (generic_win->handle);
+         generic_win->handle = (WINDOW *) NULL;
+       }
+      tui_free_win_content (generic_win);
+      if (win_info->detail.source_info.filename)
+        {
+          xfree (win_info->detail.source_info.filename);
+          win_info->detail.source_info.filename = 0;
+        }
+      generic_win = win_info->detail.source_info.execution_info;
+      if (generic_win != (struct tui_gen_win_info *) NULL)
+       {
+         tui_delete_win (generic_win->handle);
+         generic_win->handle = (WINDOW *) NULL;
+         tui_free_win_content (generic_win);
+       }
+      break;
+    case DATA_WIN:
+      if (win_info->generic.content != NULL)
+       {
+         tui_free_data_content (win_info->detail.data_display_info.regs_content,
+                                win_info->detail.data_display_info.regs_content_count);
+         win_info->detail.data_display_info.regs_content =
+           (tui_win_content) NULL;
+         win_info->detail.data_display_info.regs_content_count = 0;
+         tui_free_data_content (win_info->detail.data_display_info.data_content,
+                                win_info->detail.data_display_info.data_content_count);
+         win_info->detail.data_display_info.data_content =
+           (tui_win_content) NULL;
+         win_info->detail.data_display_info.data_content_count = 0;
+         win_info->detail.data_display_info.regs_display_type =
+           TUI_UNDEFINED_REGS;
+         win_info->detail.data_display_info.regs_column_count = 1;
+         win_info->detail.data_display_info.display_regs = FALSE;
+         win_info->generic.content = NULL;
+         win_info->generic.content_size = 0;
+       }
+      break;
+    default:
+      break;
+    }
+  if (win_info->generic.handle != (WINDOW *) NULL)
+    {
+      tui_delete_win (win_info->generic.handle);
+      win_info->generic.handle = (WINDOW *) NULL;
+      tui_free_win_content (&win_info->generic);
+    }
+  if (win_info->generic.title)
+    xfree (win_info->generic.title);
+  xfree (win_info);
+}
+
+
+void
+tui_free_all_source_wins_content (void)
+{
+  int i;
+
+  for (i = 0; i < (tui_source_windows ())->count; i++)
+    {
+      struct tui_win_info * win_info = (struct tui_win_info *) (tui_source_windows ())->list[i];
+
+      if (win_info != NULL)
+       {
+         tui_free_win_content (&(win_info->generic));
+         tui_free_win_content (win_info->detail.source_info.execution_info);
+       }
+    }
+}
+
+
+void
+tui_free_win_content (struct tui_gen_win_info * win_info)
+{
+  if (win_info->content != NULL)
+    {
+      free_content ((tui_win_content) win_info->content,
+                  win_info->content_size,
+                  win_info->type);
+      win_info->content = NULL;
+    }
+  win_info->content_size = 0;
+}
+
+
+void
+tui_del_data_windows (tui_win_content content, int content_size)
+{
+  int i;
+
+  /*
+     ** Remember that data window content elements are of type struct tui_gen_win_info *,
+     ** each of which whose single element is a data element.
+   */
+  for (i = 0; i < content_size; i++)
+    {
+      struct tui_gen_win_info * generic_win = &content[i]->which_element.data_window;
+
+      if (generic_win != (struct tui_gen_win_info *) NULL)
+       {
+         tui_delete_win (generic_win->handle);
+         generic_win->handle = (WINDOW *) NULL;
+         generic_win->is_visible = FALSE;
+       }
+    }
+}
+
+
+void
+tui_free_data_content (tui_win_content content, int content_size)
+{
+  int i;
+
+  /*
+     ** Remember that data window content elements are of type struct tui_gen_win_info *,
+     ** each of which whose single element is a data element.
+   */
+  for (i = 0; i < content_size; i++)
+    {
+      struct tui_gen_win_info * generic_win = &content[i]->which_element.data_window;
+
+      if (generic_win != (struct tui_gen_win_info *) NULL)
+       {
+         tui_delete_win (generic_win->handle);
+         generic_win->handle = (WINDOW *) NULL;
+         tui_free_win_content (generic_win);
+       }
+    }
+  free_content (content,
+              content_size,
+              DATA_WIN);
+}
+
+
+/**********************************
+** LOCAL STATIC FUNCTIONS        **
+**********************************/
+
+
+static void
+free_content (tui_win_content content, int content_size, enum tui_win_type win_type)
+{
+  if (content != (tui_win_content) NULL)
+    {
+      free_content_elements (content, content_size, win_type);
+      xfree (content);
+    }
+}
+
+
+/*
+   ** free_content_elements().
+ */
+static void
+free_content_elements (tui_win_content content, int content_size, enum tui_win_type type)
+{
+  if (content != (tui_win_content) NULL)
+    {
+      int i;
+
+      if (type == SRC_WIN || type == DISASSEM_WIN)
+       {
+         /* free whole source block */
+         xfree (content[0]->which_element.source.line);
+       }
+      else
+       {
+         for (i = 0; i < content_size; i++)
+           {
+             struct tui_win_element * element;
+
+             element = content[i];
+             if (element != (struct tui_win_element *) NULL)
+               {
+                 switch (type)
+                   {
+                   case DATA_WIN:
+                     xfree (element);
+                     break;
+                   case DATA_ITEM_WIN:
+                     /*
+                        ** Note that data elements are not allocated
+                        ** in a single block, but individually, as needed.
+                      */
+                     if (element->which_element.data.type != TUI_REGISTER)
+                       xfree ((void *)element->which_element.data.name);
+                     xfree (element->which_element.data.value);
+                     xfree (element);
+                     break;
+                   case CMD_WIN:
+                     xfree (element->which_element.command.line);
+                     break;
+                   default:
+                     break;
+                   }
+               }
+           }
+       }
+      if (type != DATA_WIN && type != DATA_ITEM_WIN)
+       xfree (content[0]);     /* free the element block */
+    }
+}
diff --git a/gdb/tui/tui-data.h b/gdb/tui/tui-data.h
new file mode 100644 (file)
index 0000000..8628172
--- /dev/null
@@ -0,0 +1,346 @@
+/* TUI data manipulation routines.
+
+   Copyright 1998, 1999, 2000, 2001, 2002, 2004 Free Software
+   Foundation, Inc.
+
+   Contributed by Hewlett-Packard Company.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef TUI_DATA_H
+#define TUI_DATA_H
+
+#if defined (HAVE_NCURSES_H)
+#include <ncurses.h>
+#elif defined (HAVE_CURSES_H)
+#include <curses.h>
+#endif
+
+/* Generic window information */
+struct tui_gen_win_info
+{
+  WINDOW *handle;      /* window handle */
+  enum tui_win_type type;      /* type of window */
+  int width;           /* window width */
+  int height;          /* window height */
+  struct tui_point origin;     /* origin of window */
+  void **content;      /* content of window */
+  int content_size;    /* Size of content (# of elements) */
+  int content_in_use;  /* Can it be used, or is it already used? */
+  int viewport_height; /* viewport height */
+  int last_visible_line;       /* index of last visible line */
+  int is_visible;              /* whether the window is visible or not */
+  char *title;          /* Window title to display.  */
+};
+
+/* Constant definitions */
+#define DEFAULT_TAB_LEN                8
+#define NO_SRC_STRING                  "[ No Source Available ]"
+#define NO_DISASSEM_STRING             "[ No Assembly Available ]"
+#define NO_REGS_STRING                 "[ Register Values Unavailable ]"
+#define NO_DATA_STRING                 "[ No Data Values Displayed ]"
+#define MAX_CONTENT_COUNT              100
+#define SRC_NAME                       "SRC"
+#define CMD_NAME                       "CMD"
+#define DATA_NAME                      "REGS"
+#define DISASSEM_NAME                  "ASM"
+#define TUI_NULL_STR                   ""
+#define DEFAULT_HISTORY_COUNT          25
+#define BOX_WINDOW                     TRUE
+#define DONT_BOX_WINDOW                FALSE
+#define HILITE                         TRUE
+#define NO_HILITE                      FALSE
+#define WITH_LOCATOR                   TRUE
+#define NO_LOCATOR                     FALSE
+#define EMPTY_SOURCE_PROMPT            TRUE
+#define NO_EMPTY_SOURCE_PROMPT         FALSE
+#define UNDEFINED_ITEM                 -1
+#define MIN_WIN_HEIGHT                 3
+#define MIN_CMD_WIN_HEIGHT             3
+
+/* Strings to display in the TUI status line.  */
+#define PROC_PREFIX                    "In: "
+#define LINE_PREFIX                    "Line: "
+#define PC_PREFIX                      "PC: "
+#define SINGLE_KEY                     "(SingleKey)"
+
+/* Minimum/Maximum length of some fields displayed in the TUI status line.  */
+#define MIN_LINE_WIDTH     4 /* Use at least 4 digits for line numbers.  */
+#define MIN_PROC_WIDTH    12
+#define MAX_TARGET_WIDTH  10
+#define MAX_PID_WIDTH     14
+
+#define TUI_FLOAT_REGS_NAME                  "$FREGS"
+#define TUI_FLOAT_REGS_NAME_LOWER            "$fregs"
+#define TUI_GENERAL_REGS_NAME                "$GREGS"
+#define TUI_GENERAL_REGS_NAME_LOWER          "$gregs"
+#define TUI_SPECIAL_REGS_NAME                "$SREGS"
+#define TUI_SPECIAL_REGS_NAME_LOWER          "$sregs"
+#define TUI_GENERAL_SPECIAL_REGS_NAME        "$REGS"
+#define TUI_GENERAL_SPECIAL_REGS_NAME_LOWER  "$regs"
+
+/* Scroll direction enum.  */
+enum tui_scroll_direction
+{
+  FORWARD_SCROLL,
+  BACKWARD_SCROLL,
+  LEFT_SCROLL,
+  RIGHT_SCROLL
+};
+
+
+/* General list struct.  */
+struct tui_list
+{
+  void **list;
+  int count;
+};
+
+
+/* The kinds of layouts available */
+enum tui_layout_type
+{
+  SRC_COMMAND,
+  DISASSEM_COMMAND,
+  SRC_DISASSEM_COMMAND,
+  SRC_DATA_COMMAND,
+  DISASSEM_DATA_COMMAND,
+  UNDEFINED_LAYOUT
+};
+
+/* Basic data types that can be displayed in the data window. */
+enum tui_data_type
+{
+  TUI_REGISTER,
+  TUI_SCALAR,
+  TUI_COMPLEX,
+  TUI_STRUCT
+};
+
+/* Types of register displays */
+enum tui_register_display_type
+{
+  TUI_UNDEFINED_REGS,
+  TUI_GENERAL_REGS,
+  TUI_SFLOAT_REGS,
+  TUI_DFLOAT_REGS,
+  TUI_SPECIAL_REGS,
+  TUI_GENERAL_AND_SPECIAL_REGS
+};
+
+/* Structure describing source line or line address */
+union tui_line_or_address
+{
+  int line_no;
+  CORE_ADDR addr;
+};
+
+/* Current Layout definition */
+struct tui_layout_def
+{
+  enum tui_win_type display_mode;
+  int split;
+  enum tui_register_display_type regs_display_type;
+  enum tui_register_display_type float_regs_display_type;
+};
+
+/* Elements in the Source/Disassembly Window */
+struct tui_source_element
+{
+  char *line;
+  union tui_line_or_address line_or_addr;
+  int is_exec_point;
+  int has_break;
+};
+
+
+/* Elements in the data display window content */
+struct tui_data_element
+{
+  const char *name;
+  int item_no;                 /* the register number, or data display number */
+  enum tui_data_type type;
+  void *value;
+  int highlight;
+};
+
+
+/* Elements in the command window content */
+struct tui_command_element
+{
+  char *line;
+};
+
+
+#define MAX_LOCATOR_ELEMENT_LEN        100
+
+/* Elements in the locator window content */
+struct tui_locator_element
+{
+  char file_name[MAX_LOCATOR_ELEMENT_LEN];
+  char proc_name[MAX_LOCATOR_ELEMENT_LEN];
+  int line_no;
+  CORE_ADDR addr;
+};
+
+/* Flags to tell what kind of breakpoint is at current line.  */
+#define TUI_BP_ENABLED      0x01
+#define TUI_BP_DISABLED     0x02
+#define TUI_BP_HIT          0x04
+#define TUI_BP_CONDITIONAL  0x08
+#define TUI_BP_HARDWARE     0x10
+
+/* Position of breakpoint markers in the exec info string.  */
+#define TUI_BP_HIT_POS      0
+#define TUI_BP_BREAK_POS    1
+#define TUI_EXEC_POS        2
+#define TUI_EXECINFO_SIZE   4
+
+typedef char tui_exec_info_content[TUI_EXECINFO_SIZE];
+
+/* An content element in a window */
+union tui_which_element
+{
+  struct tui_source_element source;    /* the source elements */
+  struct tui_gen_win_info data_window; /* data display elements */
+  struct tui_data_element data;        /* elements of data_window */
+  struct tui_command_element command;  /* command elements */
+  struct tui_locator_element locator;  /* locator elements */
+  tui_exec_info_content simple_string; /* simple char based elements */
+};
+
+struct tui_win_element
+{
+  int highlight;
+  union tui_which_element which_element;
+};
+
+
+/* This describes the content of the window. */
+typedef struct tui_win_element **tui_win_content;
+
+
+/* This struct defines the specific information about a data display window */
+struct tui_data_info
+{
+  tui_win_content data_content;        /* start of data display content */
+  int data_content_count;
+  tui_win_content regs_content;        /* start of regs display content */
+  int regs_content_count;
+  enum tui_register_display_type regs_display_type;
+  int regs_column_count;
+  int display_regs;            /* Should regs be displayed at all? */
+};
+
+
+struct tui_source_info
+{
+  int has_locator;             /* Does locator belongs to this window? */
+  /* Execution information window.  */
+  struct tui_gen_win_info *execution_info;
+  int horizontal_offset;       /* used for horizontal scroll */
+  union tui_line_or_address start_line_or_addr;
+  char* filename;
+};
+
+
+struct tui_command_info
+{
+  int cur_line;                /* The current line position */
+  int curch;                   /* The current cursor position */
+  int start_line;
+};
+
+
+/* This defines information about each logical window */
+struct tui_win_info
+{
+  struct tui_gen_win_info generic;     /* general window information */
+  union
+  {
+    struct tui_source_info source_info;
+    struct tui_data_info data_display_info;
+    struct tui_command_info command_info;
+    void *opaque;
+  }
+  detail;
+  int can_highlight;           /* Can this window ever be highlighted? */
+  int is_highlighted;          /* Is this window highlighted? */
+};
+
+extern int tui_win_is_source_type (enum tui_win_type win_type);
+extern int tui_win_is_auxillary (enum tui_win_type win_type);
+extern int tui_win_has_locator (struct tui_win_info *win_info);
+extern void tui_set_win_highlight (struct tui_win_info *win_info,
+                                  int highlight);
+
+
+/* Global Data */
+extern struct tui_win_info *(tui_win_list[MAX_MAJOR_WINDOWS]);
+
+#define TUI_SRC_WIN            tui_win_list[SRC_WIN]
+#define TUI_DISASM_WIN       tui_win_list[DISASSEM_WIN]
+#define TUI_DATA_WIN           tui_win_list[DATA_WIN]
+#define TUI_CMD_WIN            tui_win_list[CMD_WIN]
+
+/* Data Manipulation Functions */
+extern void tui_initialize_static_data (void);
+extern struct tui_gen_win_info *tui_alloc_generic_win_info (void);
+extern struct tui_win_info *tui_alloc_win_info (enum tui_win_type);
+extern void tui_init_generic_part (struct tui_gen_win_info *);
+extern void tui_init_win_info (struct tui_win_info *);
+extern tui_win_content tui_alloc_content (int, enum tui_win_type);
+extern int tui_add_content_elements (struct tui_gen_win_info *, int);
+extern void tui_init_content_element (struct tui_win_element *, enum tui_win_type);
+extern void tui_free_window (struct tui_win_info *);
+extern void tui_free_win_content (struct tui_gen_win_info *);
+extern void tui_free_data_content (tui_win_content, int);
+extern void tui_free_all_source_wins_content (void);
+extern void tui_del_window (struct tui_win_info *);
+extern void tui_del_data_windows (tui_win_content, int);
+extern struct tui_win_info *tui_partial_win_by_name (char *);
+extern char *tui_win_name (struct tui_gen_win_info *);
+extern enum tui_layout_type tui_current_layout (void);
+extern void tui_set_current_layout_to (enum tui_layout_type);
+extern int tui_term_height (void);
+extern void tui_set_term_height_to (int);
+extern int tui_term_width (void);
+extern void tui_set_term_width_to (int);
+extern void tui_set_gen_win_origin (struct tui_gen_win_info *, int, int);
+extern struct tui_gen_win_info *tui_locator_win_info_ptr (void);
+extern struct tui_gen_win_info *tui_source_exec_info_win_ptr (void);
+extern struct tui_gen_win_info *tui_disassem_exec_info_win_ptr (void);
+extern struct tui_list * tui_source_windows (void);
+extern void tui_clear_source_windows (void);
+extern void tui_clear_source_windows_detail (void);
+extern void tui_clear_win_detail (struct tui_win_info * win_info);
+extern void tui_add_to_source_windows (struct tui_win_info *);
+extern int tui_default_tab_len (void);
+extern void tui_set_default_tab_len (int);
+extern struct tui_win_info *tui_win_with_focus (void);
+extern void tui_set_win_with_focus (struct tui_win_info *);
+extern struct tui_layout_def * tui_layout_def (void);
+extern int tui_win_resized (void);
+extern void tui_set_win_resized_to (int);
+
+extern struct tui_win_info *tui_next_win (struct tui_win_info *);
+extern struct tui_win_info *tui_prev_win (struct tui_win_info *);
+
+extern void tui_add_to_source_windows (struct tui_win_info * win_info);
+
+#endif /* TUI_DATA_H */
diff --git a/gdb/tui/tui-disasm.c b/gdb/tui/tui-disasm.c
new file mode 100644 (file)
index 0000000..a431121
--- /dev/null
@@ -0,0 +1,403 @@
+/* Disassembly display.
+
+   Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
+   Foundation, Inc.
+
+   Contributed by Hewlett-Packard Company.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include "defs.h"
+#include "symtab.h"
+#include "breakpoint.h"
+#include "frame.h"
+#include "value.h"
+#include "source.h"
+#include "disasm.h"
+#include "gdb_string.h"
+#include "tui/tui.h"
+#include "tui/tui-data.h"
+#include "tui/tui-win.h"
+#include "tui/tui-layout.h"
+#include "tui/tui-winsource.h"
+#include "tui/tui-stack.h"
+#include "tui/tui-file.h"
+
+#ifdef HAVE_NCURSES_H       
+#include <ncurses.h>
+#else
+#ifdef HAVE_CURSES_H
+#include <curses.h>
+#endif
+#endif
+
+struct tui_asm_line 
+{
+  CORE_ADDR addr;
+  char* addr_string;
+  char* insn;
+};
+
+/* Function to set the disassembly window's content.
+   Disassemble count lines starting at pc.
+   Return address of the count'th instruction after pc.  */
+static CORE_ADDR
+tui_disassemble (struct tui_asm_line* lines, CORE_ADDR pc, int count)
+{
+  struct ui_file *gdb_dis_out;
+
+  /* now init the ui_file structure */
+  gdb_dis_out = tui_sfileopen (256);
+
+  /* Now construct each line */
+  for (; count > 0; count--, lines++)
+    {
+      if (lines->addr_string)
+        xfree (lines->addr_string);
+      if (lines->insn)
+        xfree (lines->insn);
+      
+      print_address (pc, gdb_dis_out);
+      lines->addr = pc;
+      lines->addr_string = xstrdup (tui_file_get_strbuf (gdb_dis_out));
+
+      ui_file_rewind (gdb_dis_out);
+
+      pc = pc + gdb_print_insn (pc, gdb_dis_out);
+
+      lines->insn = xstrdup (tui_file_get_strbuf (gdb_dis_out));
+
+      /* reset the buffer to empty */
+      ui_file_rewind (gdb_dis_out);
+    }
+  ui_file_delete (gdb_dis_out);
+  return pc;
+}
+
+/* Find the disassembly address that corresponds to FROM lines
+   above or below the PC.  Variable sized instructions are taken
+   into account by the algorithm.  */
+static CORE_ADDR
+tui_find_disassembly_address (CORE_ADDR pc, int from)
+{
+  CORE_ADDR new_low;
+  int max_lines;
+  int i;
+  struct tui_asm_line* lines;
+
+  max_lines = (from > 0) ? from : - from;
+  if (max_lines <= 1)
+     return pc;
+
+  lines = (struct tui_asm_line*) alloca (sizeof (struct tui_asm_line)
+                                         * max_lines);
+  memset (lines, 0, sizeof (struct tui_asm_line) * max_lines);
+
+  new_low = pc;
+  if (from > 0)
+    {
+      tui_disassemble (lines, pc, max_lines);
+      new_low = lines[max_lines - 1].addr;
+    }
+  else
+    {
+      CORE_ADDR last_addr;
+      int pos;
+      struct minimal_symbol* msymbol;
+              
+      /* Find backward an address which is a symbol
+         and for which disassembling from that address will fill
+         completely the window.  */
+      pos = max_lines - 1;
+      do {
+         new_low -= 1 * max_lines;
+         msymbol = lookup_minimal_symbol_by_pc_section (new_low, 0);
+
+         if (msymbol)
+            new_low = SYMBOL_VALUE_ADDRESS (msymbol);
+         else
+            new_low += 1 * max_lines;
+
+         tui_disassemble (lines, new_low, max_lines);
+         last_addr = lines[pos].addr;
+      } while (last_addr > pc && msymbol);
+
+      /* Scan forward disassembling one instruction at a time
+         until the last visible instruction of the window
+         matches the pc.  We keep the disassembled instructions
+         in the 'lines' window and shift it downward (increasing
+         its addresses).  */
+      if (last_addr < pc)
+        do
+          {
+            CORE_ADDR next_addr;
+                 
+            pos++;
+            if (pos >= max_lines)
+              pos = 0;
+
+            next_addr = tui_disassemble (&lines[pos], last_addr, 1);
+
+            /* If there are some problems while disassembling exit.  */
+            if (next_addr <= last_addr)
+              break;
+            last_addr = next_addr;
+          } while (last_addr <= pc);
+      pos++;
+      if (pos >= max_lines)
+         pos = 0;
+      new_low = lines[pos].addr;
+    }
+  for (i = 0; i < max_lines; i++)
+    {
+      xfree (lines[i].addr_string);
+      xfree (lines[i].insn);
+    }
+  return new_low;
+}
+
+/* Function to set the disassembly window's content.  */
+enum tui_status
+tui_set_disassem_content (CORE_ADDR pc)
+{
+  enum tui_status ret = TUI_FAILURE;
+  int i;
+  int offset = TUI_DISASM_WIN->detail.source_info.horizontal_offset;
+  int line_width, max_lines;
+  CORE_ADDR cur_pc;
+  struct tui_gen_win_info * locator = tui_locator_win_info_ptr ();
+  int tab_len = tui_default_tab_len ();
+  struct tui_asm_line* lines;
+  int insn_pos;
+  int addr_size, max_size;
+  char* line;
+  
+  if (pc == 0)
+    return TUI_FAILURE;
+
+  ret = tui_alloc_source_buffer (TUI_DISASM_WIN);
+  if (ret != TUI_SUCCESS)
+    return ret;
+
+  TUI_DISASM_WIN->detail.source_info.start_line_or_addr.addr = pc;
+  cur_pc = (CORE_ADDR)
+    (((struct tui_win_element *) locator->content[0])->which_element.locator.addr);
+
+  max_lines = TUI_DISASM_WIN->generic.height - 2;      /* account for hilite */
+
+  /* Get temporary table that will hold all strings (addr & insn).  */
+  lines = (struct tui_asm_line*) alloca (sizeof (struct tui_asm_line)
+                                         * max_lines);
+  memset (lines, 0, sizeof (struct tui_asm_line) * max_lines);
+
+  line_width = TUI_DISASM_WIN->generic.width - 1;
+
+  tui_disassemble (lines, pc, max_lines);
+
+  /* See what is the maximum length of an address and of a line.  */
+  addr_size = 0;
+  max_size = 0;
+  for (i = 0; i < max_lines; i++)
+    {
+      size_t len = strlen (lines[i].addr_string);
+      if (len > addr_size)
+        addr_size = len;
+
+      len = strlen (lines[i].insn) + tab_len;
+      if (len > max_size)
+        max_size = len;
+    }
+  max_size += addr_size + tab_len;
+
+  /* Allocate memory to create each line.  */
+  line = (char*) alloca (max_size);
+  insn_pos = (1 + (addr_size / tab_len)) * tab_len;
+
+  /* Now construct each line */
+  for (i = 0; i < max_lines; i++)
+    {
+      struct tui_win_element * element;
+      struct tui_source_element* src;
+      int cur_len;
+
+      element = (struct tui_win_element *) TUI_DISASM_WIN->generic.content[i];
+      src = &element->which_element.source;
+      strcpy (line, lines[i].addr_string);
+      cur_len = strlen (line);
+
+      /* Add spaces to make the instructions start on the same column */
+      while (cur_len < insn_pos)
+        {
+          strcat (line, " ");
+          cur_len++;
+        }
+
+      strcat (line, lines[i].insn);
+
+      /* Now copy the line taking the offset into account */
+      if (strlen (line) > offset)
+        strcpy (src->line, &line[offset]);
+      else
+        src->line[0] = '\0';
+
+      src->line_or_addr.addr = lines[i].addr;
+      src->is_exec_point = lines[i].addr == cur_pc;
+
+      /* See whether there is a breakpoint installed.  */
+      src->has_break = (!src->is_exec_point
+                       && breakpoint_here_p (pc) != no_breakpoint_here);
+
+      xfree (lines[i].addr_string);
+      xfree (lines[i].insn);
+    }
+  TUI_DISASM_WIN->generic.content_size = i;
+  return TUI_SUCCESS;
+}
+
+
+/* Function to display the disassembly window with disassembled code.   */
+void
+tui_show_disassem (CORE_ADDR start_addr)
+{
+  struct symtab *s = find_pc_symtab (start_addr);
+  struct tui_win_info * win_with_focus = tui_win_with_focus ();
+  union tui_line_or_address val;
+
+  val.addr = start_addr;
+  tui_add_win_to_layout (DISASSEM_WIN);
+  tui_update_source_window (TUI_DISASM_WIN, s, val, FALSE);
+  /*
+     ** if the focus was in the src win, put it in the asm win, if the
+     ** source view isn't split
+   */
+  if (tui_current_layout () != SRC_DISASSEM_COMMAND && win_with_focus == TUI_SRC_WIN)
+    tui_set_win_focus_to (TUI_DISASM_WIN);
+
+  return;
+}
+
+
+/* Function to display the disassembly window.   */
+void
+tui_show_disassem_and_update_source (CORE_ADDR start_addr)
+{
+  struct symtab_and_line sal;
+
+  tui_show_disassem (start_addr);
+  if (tui_current_layout () == SRC_DISASSEM_COMMAND)
+    {
+      union tui_line_or_address val;
+
+      /*
+         ** Update what is in the source window if it is displayed too,
+         ** note that it follows what is in the disassembly window and visa-versa
+       */
+      sal = find_pc_line (start_addr, 0);
+      val.line_no = sal.line;
+      tui_update_source_window (TUI_SRC_WIN, sal.symtab, val, TRUE);
+      if (sal.symtab)
+       {
+         set_current_source_symtab_and_line (&sal);
+         tui_update_locator_filename (sal.symtab->filename);
+       }
+      else
+       tui_update_locator_filename ("?");
+    }
+
+  return;
+}
+
+CORE_ADDR
+tui_get_begin_asm_address (void)
+{
+  struct tui_gen_win_info * locator;
+  struct tui_locator_element * element;
+  CORE_ADDR addr;
+
+  locator = tui_locator_win_info_ptr ();
+  element = &((struct tui_win_element *) locator->content[0])->which_element.locator;
+
+  if (element->addr == 0)
+    {
+      struct minimal_symbol *main_symbol;
+
+      /* Find address of the start of program.
+         Note: this should be language specific.  */
+      main_symbol = lookup_minimal_symbol ("main", NULL, NULL);
+      if (main_symbol == 0)
+        main_symbol = lookup_minimal_symbol ("MAIN", NULL, NULL);
+      if (main_symbol == 0)
+        main_symbol = lookup_minimal_symbol ("_start", NULL, NULL);
+      if (main_symbol)
+        addr = SYMBOL_VALUE_ADDRESS (main_symbol);
+      else
+        addr = 0;
+    }
+  else                         /* the target is executing */
+    addr = element->addr;
+
+  return addr;
+}
+
+/* Determine what the low address will be to display in the TUI's
+   disassembly window.  This may or may not be the same as the
+   low address input.  */
+CORE_ADDR
+tui_get_low_disassembly_address (CORE_ADDR low, CORE_ADDR pc)
+{
+  int pos;
+
+  /* Determine where to start the disassembly so that the pc is about in the
+     middle of the viewport.  */
+  pos = tui_default_win_viewport_height (DISASSEM_WIN, DISASSEM_COMMAND) / 2;
+  pc = tui_find_disassembly_address (pc, -pos);
+
+  if (pc < low)
+    pc = low;
+  return pc;
+}
+
+/* Scroll the disassembly forward or backward vertically.  */
+void
+tui_vertical_disassem_scroll (enum tui_scroll_direction scroll_direction,
+                             int num_to_scroll)
+{
+  if (TUI_DISASM_WIN->generic.content != NULL)
+    {
+      CORE_ADDR pc;
+      tui_win_content content;
+      struct symtab *s;
+      union tui_line_or_address val;
+      int max_lines, dir;
+      struct symtab_and_line cursal = get_current_source_symtab_and_line ();
+
+      content = (tui_win_content) TUI_DISASM_WIN->generic.content;
+      if (cursal.symtab == (struct symtab *) NULL)
+       s = find_pc_symtab (get_frame_pc (deprecated_selected_frame));
+      else
+       s = cursal.symtab;
+
+      /* account for hilite */
+      max_lines = TUI_DISASM_WIN->generic.height - 2;
+      pc = content[0]->which_element.source.line_or_addr.addr;
+      dir = (scroll_direction == FORWARD_SCROLL) ? max_lines : - max_lines;
+
+      val.addr = tui_find_disassembly_address (pc, dir);
+      tui_update_source_window_as_is (TUI_DISASM_WIN, s, val, FALSE);
+    }
+}
diff --git a/gdb/tui/tui-disasm.h b/gdb/tui/tui-disasm.h
new file mode 100644 (file)
index 0000000..e72aba1
--- /dev/null
@@ -0,0 +1,37 @@
+/* Disassembly display.
+
+   Copyright 1998, 1999, 2000, 2001, 2004 Free Software Foundation,
+   Inc.
+   
+   Contributed by Hewlett-Packard Company.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef TUI_DISASM_H
+#define TUI_DISASM_H
+
+#include "tui/tui.h"           /* For enum tui_status.  */
+#include "tui/tui-data.h"      /* For enum tui_scroll_direction.  */
+
+extern enum tui_status tui_set_disassem_content (CORE_ADDR);
+extern void tui_show_disassem (CORE_ADDR);
+extern void tui_show_disassem_and_update_source (CORE_ADDR);
+extern void tui_vertical_disassem_scroll (enum tui_scroll_direction, int);
+extern CORE_ADDR tui_get_begin_asm_address (void);
+
+#endif
diff --git a/gdb/tui/tui-io.c b/gdb/tui/tui-io.c
new file mode 100644 (file)
index 0000000..6ca2bee
--- /dev/null
@@ -0,0 +1,714 @@
+/* TUI support I/O functions.
+
+   Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
+   Foundation, Inc.
+
+   Contributed by Hewlett-Packard Company.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include "defs.h"
+#include "terminal.h"
+#include "target.h"
+#include "event-loop.h"
+#include "event-top.h"
+#include "command.h"
+#include "top.h"
+#include "readline/readline.h"
+#include "tui/tui.h"
+#include "tui/tui-data.h"
+#include "tui/tui-io.h"
+#include "tui/tui-command.h"
+#include "tui/tui-win.h"
+#include "tui/tui-wingeneral.h"
+#include "tui/tui-file.h"
+#include "ui-out.h"
+#include "cli-out.h"
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+
+#ifdef HAVE_NCURSES_H       
+#include <ncurses.h>
+#else
+#ifdef HAVE_CURSES_H
+#include <curses.h>
+#endif
+#endif
+
+int
+key_is_start_sequence (int ch)
+{
+  return (ch == 27);
+}
+
+int
+key_is_end_sequence (int ch)
+{
+  return (ch == 126);
+}
+
+int
+key_is_backspace (int ch)
+{
+  return (ch == 8);
+}
+
+int
+key_is_command_char (int ch)
+{
+  return ((ch == KEY_NPAGE) || (ch == KEY_PPAGE)
+         || (ch == KEY_LEFT) || (ch == KEY_RIGHT)
+         || (ch == KEY_UP) || (ch == KEY_DOWN)
+         || (ch == KEY_SF) || (ch == KEY_SR)
+         || (ch == (int)'\f') || key_is_start_sequence (ch));
+}
+
+/* Use definition from readline 4.3.  */
+#undef CTRL_CHAR
+#define CTRL_CHAR(c) ((c) < control_character_threshold && (((c) & 0x80) == 0))
+
+/* This file controls the IO interactions between gdb and curses.
+   When the TUI is enabled, gdb has two modes a curses and a standard
+   mode.
+
+   In curses mode, the gdb outputs are made in a curses command window.
+   For this, the gdb_stdout and gdb_stderr are redirected to the specific
+   ui_file implemented by TUI.  The output is handled by tui_puts().
+   The input is also controlled by curses with tui_getc().  The readline
+   library uses this function to get its input.  Several readline hooks
+   are installed to redirect readline output to the TUI (see also the
+   note below).
+
+   In normal mode, the gdb outputs are restored to their origin, that
+   is as if TUI is not used.  Readline also uses its original getc()
+   function with stdin.
+
+   Note SCz/2001-07-21: the current readline is not clean in its management of
+   the output.  Even if we install a redisplay handler, it sometimes writes on
+   a stdout file.  It is important to redirect every output produced by
+   readline, otherwise the curses window will be garbled.  This is implemented
+   with a pipe that TUI reads and readline writes to.  A gdb input handler
+   is created so that reading the pipe is handled automatically.
+   This will probably not work on non-Unix platforms.  The best fix is
+   to make readline clean enougth so that is never write on stdout.
+
+   Note SCz/2002-09-01: we now use more readline hooks and it seems that
+   with them we don't need the pipe anymore (verified by creating the pipe
+   and closing its end so that write causes a SIGPIPE).  The old pipe code
+   is still there and can be conditionally removed by
+   #undef TUI_USE_PIPE_FOR_READLINE.  */
+
+/* For gdb 5.3, prefer to continue the pipe hack as a backup wheel.  */
+#define TUI_USE_PIPE_FOR_READLINE
+/*#undef TUI_USE_PIPE_FOR_READLINE*/
+
+/* TUI output files.  */
+static struct ui_file *tui_stdout;
+static struct ui_file *tui_stderr;
+struct ui_out *tui_out;
+
+/* GDB output files in non-curses mode.  */
+static struct ui_file *tui_old_stdout;
+static struct ui_file *tui_old_stderr;
+struct ui_out *tui_old_uiout;
+
+/* Readline previous hooks.  */
+static Function *tui_old_rl_getc_function;
+static VFunction *tui_old_rl_redisplay_function;
+static VFunction *tui_old_rl_prep_terminal;
+static VFunction *tui_old_rl_deprep_terminal;
+static int tui_old_readline_echoing_p;
+
+/* Readline output stream.
+   Should be removed when readline is clean.  */
+static FILE *tui_rl_outstream;
+static FILE *tui_old_rl_outstream;
+#ifdef TUI_USE_PIPE_FOR_READLINE
+static int tui_readline_pipe[2];
+#endif
+
+/* The last gdb prompt that was registered in readline.
+   This may be the main gdb prompt or a secondary prompt.  */
+static char *tui_rl_saved_prompt;
+
+static unsigned int tui_handle_resize_during_io (unsigned int);
+
+static void
+tui_putc (char c)
+{
+  char buf[2];
+
+  buf[0] = c;
+  buf[1] = 0;
+  tui_puts (buf);
+}
+
+/* Print the string in the curses command window.  */
+void
+tui_puts (const char *string)
+{
+  static int tui_skip_line = -1;
+  char c;
+  WINDOW *w;
+
+  w = TUI_CMD_WIN->generic.handle;
+  while ((c = *string++) != 0)
+    {
+      /* Catch annotation and discard them.  We need two \032 and
+         discard until a \n is seen.  */
+      if (c == '\032')
+        {
+          tui_skip_line++;
+        }
+      else if (tui_skip_line != 1)
+        {
+          tui_skip_line = -1;
+          waddch (w, c);
+        }
+      else if (c == '\n')
+        tui_skip_line = -1;
+    }
+  getyx (w, TUI_CMD_WIN->detail.command_info.cur_line,
+         TUI_CMD_WIN->detail.command_info.curch);
+  TUI_CMD_WIN->detail.command_info.start_line = TUI_CMD_WIN->detail.command_info.cur_line;
+
+  /* We could defer the following.  */
+  wrefresh (w);
+  fflush (stdout);
+}
+
+/* Readline callback.
+   Redisplay the command line with its prompt after readline has
+   changed the edited text.  */
+void
+tui_redisplay_readline (void)
+{
+  int prev_col;
+  int height;
+  int col, line;
+  int c_pos;
+  int c_line;
+  int in;
+  WINDOW *w;
+  char *prompt;
+  int start_line;
+
+  /* Detect when we temporarily left SingleKey and now the readline
+     edit buffer is empty, automatically restore the SingleKey mode.  */
+  if (tui_current_key_mode == TUI_ONE_COMMAND_MODE && rl_end == 0)
+    tui_set_key_mode (TUI_SINGLE_KEY_MODE);
+
+  if (tui_current_key_mode == TUI_SINGLE_KEY_MODE)
+    prompt = "";
+  else
+    prompt = tui_rl_saved_prompt;
+  
+  c_pos = -1;
+  c_line = -1;
+  w = TUI_CMD_WIN->generic.handle;
+  start_line = TUI_CMD_WIN->detail.command_info.start_line;
+  wmove (w, start_line, 0);
+  prev_col = 0;
+  height = 1;
+  for (in = 0; prompt && prompt[in]; in++)
+    {
+      waddch (w, prompt[in]);
+      getyx (w, line, col);
+      if (col < prev_col)
+        height++;
+      prev_col = col;
+    }
+  for (in = 0; in < rl_end; in++)
+    {
+      unsigned char c;
+      
+      c = (unsigned char) rl_line_buffer[in];
+      if (in == rl_point)
+       {
+          getyx (w, c_line, c_pos);
+       }
+
+      if (CTRL_CHAR (c) || c == RUBOUT)
+       {
+          waddch (w, '^');
+          waddch (w, CTRL_CHAR (c) ? UNCTRL (c) : '?');
+       }
+      else
+       {
+          waddch (w, c);
+       }
+      if (c == '\n')
+        {
+          getyx (w, TUI_CMD_WIN->detail.command_info.start_line,
+                 TUI_CMD_WIN->detail.command_info.curch);
+        }
+      getyx (w, line, col);
+      if (col < prev_col)
+        height++;
+      prev_col = col;
+    }
+  wclrtobot (w);
+  getyx (w, TUI_CMD_WIN->detail.command_info.start_line,
+         TUI_CMD_WIN->detail.command_info.curch);
+  if (c_line >= 0)
+    {
+      wmove (w, c_line, c_pos);
+      TUI_CMD_WIN->detail.command_info.cur_line = c_line;
+      TUI_CMD_WIN->detail.command_info.curch = c_pos;
+    }
+  TUI_CMD_WIN->detail.command_info.start_line -= height - 1;
+
+  wrefresh (w);
+  fflush(stdout);
+}
+
+/* Readline callback to prepare the terminal.  It is called once
+   each time we enter readline.  Terminal is already setup in curses mode.  */
+static void
+tui_prep_terminal (int notused1)
+{
+  /* Save the prompt registered in readline to correctly display it.
+     (we can't use gdb_prompt() due to secondary prompts and can't use
+     rl_prompt because it points to an alloca buffer).  */
+  xfree (tui_rl_saved_prompt);
+  tui_rl_saved_prompt = xstrdup (rl_prompt);
+}
+
+/* Readline callback to restore the terminal.  It is called once
+   each time we leave readline.  There is nothing to do in curses mode.  */
+static void
+tui_deprep_terminal (void)
+{
+}
+
+#ifdef TUI_USE_PIPE_FOR_READLINE
+/* Read readline output pipe and feed the command window with it.
+   Should be removed when readline is clean.  */
+static void
+tui_readline_output (int code, gdb_client_data data)
+{
+  int size;
+  char buf[256];
+
+  size = read (tui_readline_pipe[0], buf, sizeof (buf) - 1);
+  if (size > 0 && tui_active)
+    {
+      buf[size] = 0;
+      tui_puts (buf);
+    }
+}
+#endif
+
+/* Return the portion of PATHNAME that should be output when listing
+   possible completions.  If we are hacking filename completion, we
+   are only interested in the basename, the portion following the
+   final slash.  Otherwise, we return what we were passed.
+
+   Comes from readline/complete.c  */
+static char *
+printable_part (char *pathname)
+{
+  char *temp;
+
+  temp = rl_filename_completion_desired ? strrchr (pathname, '/') : (char *)NULL;
+#if defined (__MSDOS__)
+  if (rl_filename_completion_desired && temp == 0 && isalpha (pathname[0]) && pathname[1] == ':')
+    temp = pathname + 1;
+#endif
+  return (temp ? ++temp : pathname);
+}
+
+/* Output TO_PRINT to rl_outstream.  If VISIBLE_STATS is defined and we
+   are using it, check for and output a single character for `special'
+   filenames.  Return the number of characters we output. */
+
+#define PUTX(c) \
+    do { \
+      if (CTRL_CHAR (c)) \
+        { \
+          tui_puts ("^"); \
+          tui_putc (UNCTRL (c)); \
+          printed_len += 2; \
+        } \
+      else if (c == RUBOUT) \
+       { \
+         tui_puts ("^?"); \
+         printed_len += 2; \
+       } \
+      else \
+       { \
+         tui_putc (c); \
+         printed_len++; \
+       } \
+    } while (0)
+
+static int
+print_filename (char *to_print, char *full_pathname)
+{
+  int printed_len = 0;
+  char *s;
+
+  for (s = to_print; *s; s++)
+    {
+      PUTX (*s);
+    }
+  return printed_len;
+}
+
+/* The user must press "y" or "n".  Non-zero return means "y" pressed.
+   Comes from readline/complete.c  */
+static int
+get_y_or_n (void)
+{
+  extern int _rl_abort_internal ();
+  int c;
+
+  for (;;)
+    {
+      c = rl_read_key ();
+      if (c == 'y' || c == 'Y' || c == ' ')
+       return (1);
+      if (c == 'n' || c == 'N' || c == RUBOUT)
+       return (0);
+      if (c == ABORT_CHAR)
+       _rl_abort_internal ();
+      beep ();
+    }
+}
+
+/* A convenience function for displaying a list of strings in
+   columnar format on readline's output stream.  MATCHES is the list
+   of strings, in argv format, LEN is the number of strings in MATCHES,
+   and MAX is the length of the longest string in MATCHES.
+
+   Comes from readline/complete.c and modified to write in
+   the TUI command window using tui_putc/tui_puts.  */
+static void
+tui_rl_display_match_list (char **matches, int len, int max)
+{
+  typedef int QSFUNC (const void *, const void *);
+  extern int _rl_qsort_string_compare (const void*, const void*);
+  extern int _rl_print_completions_horizontally;
+  
+  int count, limit, printed_len;
+  int i, j, k, l;
+  char *temp;
+
+  /* Screen dimension correspond to the TUI command window.  */
+  int screenwidth = TUI_CMD_WIN->generic.width;
+
+  /* If there are many items, then ask the user if she really wants to
+     see them all. */
+  if (len >= rl_completion_query_items)
+    {
+      char msg[256];
+
+      sprintf (msg, "\nDisplay all %d possibilities? (y or n)", len);
+      tui_puts (msg);
+      if (get_y_or_n () == 0)
+       {
+         tui_puts ("\n");
+         return;
+       }
+    }
+
+  /* How many items of MAX length can we fit in the screen window? */
+  max += 2;
+  limit = screenwidth / max;
+  if (limit != 1 && (limit * max == screenwidth))
+    limit--;
+
+  /* Avoid a possible floating exception.  If max > screenwidth,
+     limit will be 0 and a divide-by-zero fault will result. */
+  if (limit == 0)
+    limit = 1;
+
+  /* How many iterations of the printing loop? */
+  count = (len + (limit - 1)) / limit;
+
+  /* Watch out for special case.  If LEN is less than LIMIT, then
+     just do the inner printing loop.
+          0 < len <= limit  implies  count = 1. */
+
+  /* Sort the items if they are not already sorted. */
+  if (rl_ignore_completion_duplicates == 0)
+    qsort (matches + 1, len, sizeof (char *),
+           (QSFUNC *)_rl_qsort_string_compare);
+
+  tui_putc ('\n');
+
+  if (_rl_print_completions_horizontally == 0)
+    {
+      /* Print the sorted items, up-and-down alphabetically, like ls. */
+      for (i = 1; i <= count; i++)
+       {
+         for (j = 0, l = i; j < limit; j++)
+           {
+             if (l > len || matches[l] == 0)
+               break;
+             else
+               {
+                 temp = printable_part (matches[l]);
+                 printed_len = print_filename (temp, matches[l]);
+
+                 if (j + 1 < limit)
+                   for (k = 0; k < max - printed_len; k++)
+                     tui_putc (' ');
+               }
+             l += count;
+           }
+         tui_putc ('\n');
+       }
+    }
+  else
+    {
+      /* Print the sorted items, across alphabetically, like ls -x. */
+      for (i = 1; matches[i]; i++)
+       {
+         temp = printable_part (matches[i]);
+         printed_len = print_filename (temp, matches[i]);
+         /* Have we reached the end of this line? */
+         if (matches[i+1])
+           {
+             if (i && (limit > 1) && (i % limit) == 0)
+               tui_putc ('\n');
+             else
+               for (k = 0; k < max - printed_len; k++)
+                 tui_putc (' ');
+           }
+       }
+      tui_putc ('\n');
+    }
+}
+
+/* Setup the IO for curses or non-curses mode.
+   - In non-curses mode, readline and gdb use the standard input and
+   standard output/error directly.
+   - In curses mode, the standard output/error is controlled by TUI
+   with the tui_stdout and tui_stderr.  The output is redirected in
+   the curses command window.  Several readline callbacks are installed
+   so that readline asks for its input to the curses command window
+   with wgetch().  */
+void
+tui_setup_io (int mode)
+{
+  extern int readline_echoing_p;
+  if (mode)
+    {
+      /* Redirect readline to TUI.  */
+      tui_old_rl_redisplay_function = rl_redisplay_function;
+      tui_old_rl_deprep_terminal = rl_deprep_term_function;
+      tui_old_rl_prep_terminal = rl_prep_term_function;
+      tui_old_rl_getc_function = rl_getc_function;
+      tui_old_rl_outstream = rl_outstream;
+      tui_old_readline_echoing_p = readline_echoing_p;
+      rl_redisplay_function = tui_redisplay_readline;
+      rl_deprep_term_function = tui_deprep_terminal;
+      rl_prep_term_function = tui_prep_terminal;
+      rl_getc_function = tui_getc;
+      readline_echoing_p = 0;
+      rl_outstream = tui_rl_outstream;
+      rl_prompt = 0;
+      rl_completion_display_matches_hook = tui_rl_display_match_list;
+      rl_already_prompted = 0;
+
+      /* Keep track of previous gdb output.  */
+      tui_old_stdout = gdb_stdout;
+      tui_old_stderr = gdb_stderr;
+      tui_old_uiout = uiout;
+
+      /* Reconfigure gdb output.  */
+      gdb_stdout = tui_stdout;
+      gdb_stderr = tui_stderr;
+      gdb_stdlog = gdb_stdout; /* for moment */
+      gdb_stdtarg = gdb_stderr;        /* for moment */
+      uiout = tui_out;
+
+      /* Save tty for SIGCONT.  */
+      savetty ();
+    }
+  else
+    {
+      /* Restore gdb output.  */
+      gdb_stdout = tui_old_stdout;
+      gdb_stderr = tui_old_stderr;
+      gdb_stdlog = gdb_stdout; /* for moment */
+      gdb_stdtarg = gdb_stderr;        /* for moment */
+      uiout = tui_old_uiout;
+
+      /* Restore readline.  */
+      rl_redisplay_function = tui_old_rl_redisplay_function;
+      rl_deprep_term_function = tui_old_rl_deprep_terminal;
+      rl_prep_term_function = tui_old_rl_prep_terminal;
+      rl_getc_function = tui_old_rl_getc_function;
+      rl_outstream = tui_old_rl_outstream;
+      rl_completion_display_matches_hook = 0;
+      readline_echoing_p = tui_old_readline_echoing_p;
+      rl_already_prompted = 0;
+
+      /* Save tty for SIGCONT.  */
+      savetty ();
+    }
+}
+
+#ifdef SIGCONT
+/* Catch SIGCONT to restore the terminal and refresh the screen.  */
+static void
+tui_cont_sig (int sig)
+{
+  if (tui_active)
+    {
+      /* Restore the terminal setting because another process (shell)
+         might have changed it.  */
+      resetty ();
+
+      /* Force a refresh of the screen.  */
+      tui_refresh_all_win ();
+
+      /* Update cursor position on the screen.  */
+      wmove (TUI_CMD_WIN->generic.handle,
+             TUI_CMD_WIN->detail.command_info.start_line,
+             TUI_CMD_WIN->detail.command_info.curch);
+      wrefresh (TUI_CMD_WIN->generic.handle);
+    }
+  signal (sig, tui_cont_sig);
+}
+#endif
+
+/* Initialize the IO for gdb in curses mode.  */
+void
+tui_initialize_io (void)
+{
+#ifdef SIGCONT
+  signal (SIGCONT, tui_cont_sig);
+#endif
+
+  /* Create tui output streams.  */
+  tui_stdout = tui_fileopen (stdout);
+  tui_stderr = tui_fileopen (stderr);
+  tui_out = tui_out_new (tui_stdout);
+
+  /* Create the default UI.  It is not created because we installed
+     a init_ui_hook.  */
+  tui_old_uiout = uiout = cli_out_new (gdb_stdout);
+
+#ifdef TUI_USE_PIPE_FOR_READLINE
+  /* Temporary solution for readline writing to stdout:
+     redirect readline output in a pipe, read that pipe and
+     output the content in the curses command window.  */
+  if (pipe (tui_readline_pipe) != 0)
+    {
+      fprintf_unfiltered (gdb_stderr, "Cannot create pipe for readline");
+      exit (1);
+    }
+  tui_rl_outstream = fdopen (tui_readline_pipe[1], "w");
+  if (tui_rl_outstream == 0)
+    {
+      fprintf_unfiltered (gdb_stderr, "Cannot redirect readline output");
+      exit (1);
+    }
+  setvbuf (tui_rl_outstream, (char*) NULL, _IOLBF, 0);
+
+#ifdef O_NONBLOCK
+  (void) fcntl (tui_readline_pipe[0], F_SETFL, O_NONBLOCK);
+#else
+#ifdef O_NDELAY
+  (void) fcntl (tui_readline_pipe[0], F_SETFL, O_NDELAY);
+#endif
+#endif
+  add_file_handler (tui_readline_pipe[0], tui_readline_output, 0);
+#else
+  tui_rl_outstream = stdout;
+#endif
+}
+
+/* Get a character from the command window.  This is called from the readline
+   package.  */
+int
+tui_getc (FILE *fp)
+{
+  int ch;
+  WINDOW *w;
+
+  w = TUI_CMD_WIN->generic.handle;
+
+#ifdef TUI_USE_PIPE_FOR_READLINE
+  /* Flush readline output.  */
+  tui_readline_output (GDB_READABLE, 0);
+#endif
+
+  ch = wgetch (w);
+  ch = tui_handle_resize_during_io (ch);
+
+  /* The \n must be echoed because it will not be printed by readline.  */
+  if (ch == '\n')
+    {
+      /* When hitting return with an empty input, gdb executes the last
+         command.  If we emit a newline, this fills up the command window
+         with empty lines with gdb prompt at beginning.  Instead of that,
+         stay on the same line but provide a visual effect to show the
+         user we recognized the command.  */
+      if (rl_end == 0)
+        {
+          wmove (w, TUI_CMD_WIN->detail.command_info.cur_line, 0);
+
+          /* Clear the line.  This will blink the gdb prompt since
+             it will be redrawn at the same line.  */
+          wclrtoeol (w);
+          wrefresh (w);
+          napms (20);
+        }
+      else
+        {
+          wmove (w, TUI_CMD_WIN->detail.command_info.cur_line,
+                 TUI_CMD_WIN->detail.command_info.curch);
+          waddch (w, ch);
+        }
+    }
+  
+  if (key_is_command_char (ch))
+    {                          /* Handle prev/next/up/down here */
+      ch = tui_dispatch_ctrl_char (ch);
+    }
+  
+  if (ch == '\n' || ch == '\r' || ch == '\f')
+    TUI_CMD_WIN->detail.command_info.curch = 0;
+  if (ch == KEY_BACKSPACE)
+    return '\b';
+  
+  return ch;
+}
+
+
+/* Cleanup when a resize has occured.
+   Returns the character that must be processed.  */
+static unsigned int
+tui_handle_resize_during_io (unsigned int original_ch)
+{
+  if (tui_win_resized ())
+    {
+      tui_refresh_all_win ();
+      dont_repeat ();
+      tui_set_win_resized_to (FALSE);
+      return '\n';
+    }
+  else
+    return original_ch;
+}
diff --git a/gdb/tui/tui-io.h b/gdb/tui/tui-io.h
new file mode 100644 (file)
index 0000000..06d085d
--- /dev/null
@@ -0,0 +1,55 @@
+/* TUI support I/O functions.
+
+   Copyright 1998, 1999, 2000, 2001, 2002, 2004 Free Software
+   Foundation, Inc.
+
+   Contributed by Hewlett-Packard Company.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef TUI_IO_H
+#define TUI_IO_H
+
+struct ui_out;
+
+/* Print the string in the curses command window.  */
+extern void tui_puts (const char *);
+
+/* Setup the IO for curses or non-curses mode.  */
+extern void tui_setup_io (int mode);
+
+/* Initialize the IO for gdb in curses mode.  */
+extern void tui_initialize_io (void);
+
+/* Get a character from the command window.  */
+extern int tui_getc (FILE *);
+
+/* Readline callback.
+   Redisplay the command line with its prompt after readline has
+   changed the edited text.  */
+extern void tui_redisplay_readline (void);
+
+extern struct ui_out *tui_out;
+extern struct ui_out *tui_old_uiout;
+
+extern int key_is_start_sequence (int ch);
+extern int key_is_end_sequence (int ch);
+extern int key_is_backspace (int ch);
+extern int key_is_command_char (int ch);
+
+#endif
diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c
new file mode 100644 (file)
index 0000000..341d3cd
--- /dev/null
@@ -0,0 +1,1080 @@
+/* TUI layout window management.
+
+   Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
+   Foundation, Inc.
+
+   Contributed by Hewlett-Packard Company.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include "defs.h"
+#include "command.h"
+#include "symtab.h"
+#include "frame.h"
+#include "source.h"
+#include <ctype.h>
+
+#include "tui/tui.h"
+#include "tui/tui-data.h"
+#include "tui/tui-windata.h"
+#include "tui/tui-wingeneral.h"
+#include "tui/tui-stack.h"
+#include "tui/tui-regs.h"
+#include "tui/tui-win.h"
+#include "tui/tui-winsource.h"
+#include "tui/tui-disasm.h"
+
+#ifdef HAVE_NCURSES_H       
+#include <ncurses.h>
+#else
+#ifdef HAVE_CURSES_H
+#include <curses.h>
+#endif
+#endif
+
+/*******************************
+** Static Local Decls
+********************************/
+static void show_layout (enum tui_layout_type);
+static void init_gen_win_info (struct tui_gen_win_info *, enum tui_win_type, int, int, int, int);
+static void init_and_make_win (void **, enum tui_win_type, int, int, int, int, int);
+static void show_source_or_disasm_and_command (enum tui_layout_type);
+static void make_source_or_disasm_window (struct tui_win_info * *, enum tui_win_type, int, int);
+static void make_command_window (struct tui_win_info * *, int, int);
+static void make_source_window (struct tui_win_info * *, int, int);
+static void make_disasm_window (struct tui_win_info * *, int, int);
+static void make_data_window (struct tui_win_info * *, int, int);
+static void show_source_command (void);
+static void show_disasm_command (void);
+static void show_source_disasm_command (void);
+static void show_data (enum tui_layout_type);
+static enum tui_layout_type next_layout (void);
+static enum tui_layout_type prev_layout (void);
+static void tui_layout_command (char *, int);
+static void tui_toggle_layout_command (char *, int);
+static void tui_toggle_split_layout_command (char *, int);
+static CORE_ADDR extract_display_start_addr (void);
+static void tui_handle_xdb_layout (struct tui_layout_def *);
+
+
+/***************************************
+** DEFINITIONS
+***************************************/
+
+#define LAYOUT_USAGE     "Usage: layout prev | next | <layout_name> \n"
+
+/* Show the screen layout defined.  */
+static void
+show_layout (enum tui_layout_type layout)
+{
+  enum tui_layout_type cur_layout = tui_current_layout ();
+
+  if (layout != cur_layout)
+    {
+      /*
+         ** Since the new layout may cause changes in window size, we
+         ** should free the content and reallocate on next display of
+         ** source/asm
+       */
+      tui_free_all_source_wins_content ();
+      tui_clear_source_windows ();
+      if (layout == SRC_DATA_COMMAND || layout == DISASSEM_DATA_COMMAND)
+       {
+         show_data (layout);
+         tui_refresh_all (tui_win_list);
+       }
+      else
+       {
+         /* First make the current layout be invisible */
+         tui_make_all_invisible ();
+         tui_make_invisible (tui_locator_win_info_ptr ());
+
+         switch (layout)
+           {
+             /* Now show the new layout */
+           case SRC_COMMAND:
+             show_source_command ();
+             tui_add_to_source_windows (TUI_SRC_WIN);
+             break;
+           case DISASSEM_COMMAND:
+             show_disasm_command ();
+             tui_add_to_source_windows (TUI_DISASM_WIN);
+             break;
+           case SRC_DISASSEM_COMMAND:
+             show_source_disasm_command ();
+             tui_add_to_source_windows (TUI_SRC_WIN);
+             tui_add_to_source_windows (TUI_DISASM_WIN);
+             break;
+           default:
+             break;
+           }
+       }
+    }
+}
+
+
+/* Function to set the layout to SRC_COMMAND, DISASSEM_COMMAND,
+   SRC_DISASSEM_COMMAND, SRC_DATA_COMMAND, or DISASSEM_DATA_COMMAND.
+   If the layout is SRC_DATA_COMMAND, DISASSEM_DATA_COMMAND, or
+   UNDEFINED_LAYOUT, then the data window is populated according to
+   regs_display_type.  */
+enum tui_status
+tui_set_layout (enum tui_layout_type layout_type,
+               enum tui_register_display_type regs_display_type)
+{
+  enum tui_status status = TUI_SUCCESS;
+
+  if (layout_type != UNDEFINED_LAYOUT || regs_display_type != TUI_UNDEFINED_REGS)
+    {
+      enum tui_layout_type cur_layout = tui_current_layout (), new_layout = UNDEFINED_LAYOUT;
+      int regs_populate = FALSE;
+      CORE_ADDR addr = extract_display_start_addr ();
+      struct tui_win_info * new_win_with_focus = (struct tui_win_info *) NULL;
+      struct tui_win_info * win_with_focus = tui_win_with_focus ();
+      struct tui_layout_def * layout_def = tui_layout_def ();
+
+
+      if (layout_type == UNDEFINED_LAYOUT &&
+         regs_display_type != TUI_UNDEFINED_REGS)
+       {
+         if (cur_layout == SRC_DISASSEM_COMMAND)
+           new_layout = DISASSEM_DATA_COMMAND;
+         else if (cur_layout == SRC_COMMAND || cur_layout == SRC_DATA_COMMAND)
+           new_layout = SRC_DATA_COMMAND;
+         else if (cur_layout == DISASSEM_COMMAND ||
+                  cur_layout == DISASSEM_DATA_COMMAND)
+           new_layout = DISASSEM_DATA_COMMAND;
+       }
+      else
+       new_layout = layout_type;
+
+      regs_populate = (new_layout == SRC_DATA_COMMAND ||
+                     new_layout == DISASSEM_DATA_COMMAND ||
+                     regs_display_type != TUI_UNDEFINED_REGS);
+      if (new_layout != cur_layout || regs_display_type != TUI_UNDEFINED_REGS)
+       {
+         if (new_layout != cur_layout)
+           {
+             show_layout (new_layout);
+             /*
+                ** Now determine where focus should be
+              */
+             if (win_with_focus != TUI_CMD_WIN)
+               {
+                 switch (new_layout)
+                   {
+                   case SRC_COMMAND:
+                     tui_set_win_focus_to (TUI_SRC_WIN);
+                     layout_def->display_mode = SRC_WIN;
+                     layout_def->split = FALSE;
+                     break;
+                   case DISASSEM_COMMAND:
+                     /* the previous layout was not showing
+                        ** code. this can happen if there is no
+                        ** source available:
+                        ** 1. if the source file is in another dir OR
+                        ** 2. if target was compiled without -g
+                        ** We still want to show the assembly though!
+                      */
+                     addr = tui_get_begin_asm_address ();
+                     tui_set_win_focus_to (TUI_DISASM_WIN);
+                     layout_def->display_mode = DISASSEM_WIN;
+                     layout_def->split = FALSE;
+                     break;
+                   case SRC_DISASSEM_COMMAND:
+                     /* the previous layout was not showing
+                        ** code. this can happen if there is no
+                        ** source available:
+                        ** 1. if the source file is in another dir OR
+                        ** 2. if target was compiled without -g
+                        ** We still want to show the assembly though!
+                      */
+                     addr = tui_get_begin_asm_address ();
+                     if (win_with_focus == TUI_SRC_WIN)
+                       tui_set_win_focus_to (TUI_SRC_WIN);
+                     else
+                       tui_set_win_focus_to (TUI_DISASM_WIN);
+                     layout_def->split = TRUE;
+                     break;
+                   case SRC_DATA_COMMAND:
+                     if (win_with_focus != TUI_DATA_WIN)
+                       tui_set_win_focus_to (TUI_SRC_WIN);
+                     else
+                       tui_set_win_focus_to (TUI_DATA_WIN);
+                     layout_def->display_mode = SRC_WIN;
+                     layout_def->split = FALSE;
+                     break;
+                   case DISASSEM_DATA_COMMAND:
+                     /* the previous layout was not showing
+                        ** code. this can happen if there is no
+                        ** source available:
+                        ** 1. if the source file is in another dir OR
+                        ** 2. if target was compiled without -g
+                        ** We still want to show the assembly though!
+                      */
+                     addr = tui_get_begin_asm_address ();
+                     if (win_with_focus != TUI_DATA_WIN)
+                       tui_set_win_focus_to (TUI_DISASM_WIN);
+                     else
+                       tui_set_win_focus_to (TUI_DATA_WIN);
+                     layout_def->display_mode = DISASSEM_WIN;
+                     layout_def->split = FALSE;
+                     break;
+                   default:
+                     break;
+                   }
+               }
+             if (new_win_with_focus != (struct tui_win_info *) NULL)
+               tui_set_win_focus_to (new_win_with_focus);
+             /*
+                ** Now update the window content
+              */
+             if (!regs_populate &&
+                 (new_layout == SRC_DATA_COMMAND ||
+                  new_layout == DISASSEM_DATA_COMMAND))
+               tui_display_all_data ();
+
+             tui_update_source_windows_with_addr (addr);
+           }
+         if (regs_populate)
+           {
+             layout_def->regs_display_type =
+               (regs_display_type == TUI_UNDEFINED_REGS ?
+                TUI_GENERAL_REGS : regs_display_type);
+             tui_show_registers (layout_def->regs_display_type);
+           }
+       }
+    }
+  else
+    status = TUI_FAILURE;
+
+  return status;
+}
+
+/* Add the specified window to the layout in a logical way.  This
+   means setting up the most logical layout given the window to be
+   added.  */
+void
+tui_add_win_to_layout (enum tui_win_type type)
+{
+  enum tui_layout_type cur_layout = tui_current_layout ();
+
+  switch (type)
+    {
+    case SRC_WIN:
+      if (cur_layout != SRC_COMMAND &&
+         cur_layout != SRC_DISASSEM_COMMAND &&
+         cur_layout != SRC_DATA_COMMAND)
+       {
+         tui_clear_source_windows_detail ();
+         if (cur_layout == DISASSEM_DATA_COMMAND)
+           show_layout (SRC_DATA_COMMAND);
+         else
+           show_layout (SRC_COMMAND);
+       }
+      break;
+    case DISASSEM_WIN:
+      if (cur_layout != DISASSEM_COMMAND &&
+         cur_layout != SRC_DISASSEM_COMMAND &&
+         cur_layout != DISASSEM_DATA_COMMAND)
+       {
+         tui_clear_source_windows_detail ();
+         if (cur_layout == SRC_DATA_COMMAND)
+           show_layout (DISASSEM_DATA_COMMAND);
+         else
+           show_layout (DISASSEM_COMMAND);
+       }
+      break;
+    case DATA_WIN:
+      if (cur_layout != SRC_DATA_COMMAND &&
+         cur_layout != DISASSEM_DATA_COMMAND)
+       {
+         if (cur_layout == DISASSEM_COMMAND)
+           show_layout (DISASSEM_DATA_COMMAND);
+         else
+           show_layout (SRC_DATA_COMMAND);
+       }
+      break;
+    default:
+      break;
+    }
+}
+
+
+/* Answer the height of a window.  If it hasn't been created yet,
+   answer what the height of a window would be based upon its type and
+   the layout.  */
+int
+tui_default_win_height (enum tui_win_type type, enum tui_layout_type layout)
+{
+  int h;
+
+  if (tui_win_list[type] != (struct tui_win_info *) NULL)
+    h = tui_win_list[type]->generic.height;
+  else
+    {
+      switch (layout)
+       {
+       case SRC_COMMAND:
+       case DISASSEM_COMMAND:
+         if (TUI_CMD_WIN == NULL)
+           h = tui_term_height () / 2;
+         else
+           h = tui_term_height () - TUI_CMD_WIN->generic.height;
+         break;
+       case SRC_DISASSEM_COMMAND:
+       case SRC_DATA_COMMAND:
+       case DISASSEM_DATA_COMMAND:
+         if (TUI_CMD_WIN == NULL)
+           h = tui_term_height () / 3;
+         else
+           h = (tui_term_height () - TUI_CMD_WIN->generic.height) / 2;
+         break;
+       default:
+         h = 0;
+         break;
+       }
+    }
+
+  return h;
+}
+
+
+/* Answer the height of a window.  If it hasn't been created yet,
+   answer what the height of a window would be based upon its type and
+   the layout.  */
+int
+tui_default_win_viewport_height (enum tui_win_type type,
+                                enum tui_layout_type layout)
+{
+  int h;
+
+  h = tui_default_win_height (type, layout);
+
+  if (tui_win_list[type] == TUI_CMD_WIN)
+    h -= 1;
+  else
+    h -= 2;
+
+  return h;
+}
+
+
+/* Function to initialize gdb commands, for tui window layout
+   manipulation.  */
+void
+_initialize_tui_layout (void)
+{
+  add_com ("layout", class_tui, tui_layout_command,
+           "Change the layout of windows.\n\
+Usage: layout prev | next | <layout_name> \n\
+Layout names are:\n\
+   src   : Displays source and command windows.\n\
+   asm   : Displays disassembly and command windows.\n\
+   split : Displays source, disassembly and command windows.\n\
+   regs  : Displays register window. If existing layout\n\
+           is source/command or assembly/command, the \n\
+           register window is displayed. If the\n\
+           source/assembly/command (split) is displayed, \n\
+           the register window is displayed with \n\
+           the window that has current logical focus.\n");
+  if (xdb_commands)
+    {
+      add_com ("td", class_tui, tui_toggle_layout_command,
+               "Toggle between Source/Command and Disassembly/Command layouts.\n");
+      add_com ("ts", class_tui, tui_toggle_split_layout_command,
+               "Toggle between Source/Command or Disassembly/Command and \n\
+Source/Disassembly/Command layouts.\n");
+    }
+}
+
+
+/*************************
+** STATIC LOCAL FUNCTIONS
+**************************/
+
+
+/* Function to set the layout to SRC, ASM, SPLIT, NEXT, PREV, DATA,
+   REGS, $REGS, $GREGS, $FREGS, $SREGS.  */
+enum tui_status
+tui_set_layout_for_display_command (const char *layout_name)
+{
+  enum tui_status status = TUI_SUCCESS;
+
+  if (layout_name != (char *) NULL)
+    {
+      int i;
+      char *buf_ptr;
+      enum tui_layout_type new_layout = UNDEFINED_LAYOUT;
+      enum tui_register_display_type dpy_type = TUI_UNDEFINED_REGS;
+      enum tui_layout_type cur_layout = tui_current_layout ();
+
+      buf_ptr = (char *) xstrdup (layout_name);
+      for (i = 0; (i < strlen (layout_name)); i++)
+       buf_ptr[i] = toupper (buf_ptr[i]);
+
+      /* First check for ambiguous input */
+      if (strlen (buf_ptr) <= 1 && (*buf_ptr == 'S' || *buf_ptr == '$'))
+       {
+         warning ("Ambiguous command input.\n");
+         status = TUI_FAILURE;
+       }
+      else
+       {
+         if (subset_compare (buf_ptr, "SRC"))
+           new_layout = SRC_COMMAND;
+         else if (subset_compare (buf_ptr, "ASM"))
+           new_layout = DISASSEM_COMMAND;
+         else if (subset_compare (buf_ptr, "SPLIT"))
+           new_layout = SRC_DISASSEM_COMMAND;
+         else if (subset_compare (buf_ptr, "REGS") ||
+                  subset_compare (buf_ptr, TUI_GENERAL_SPECIAL_REGS_NAME) ||
+                  subset_compare (buf_ptr, TUI_GENERAL_REGS_NAME) ||
+                  subset_compare (buf_ptr, TUI_FLOAT_REGS_NAME) ||
+                  subset_compare (buf_ptr, TUI_SPECIAL_REGS_NAME))
+           {
+             if (cur_layout == SRC_COMMAND || cur_layout == SRC_DATA_COMMAND)
+               new_layout = SRC_DATA_COMMAND;
+             else
+               new_layout = DISASSEM_DATA_COMMAND;
+
+/* could ifdef out the following code. when compile with -z, there are null 
+   pointer references that cause a core dump if 'layout regs' is the first 
+   layout command issued by the user. HP has asked us to hook up this code 
+   - edie epstein
+ */
+             if (subset_compare (buf_ptr, TUI_FLOAT_REGS_NAME))
+               {
+                 if (TUI_DATA_WIN->detail.data_display_info.regs_display_type !=
+                     TUI_SFLOAT_REGS &&
+                     TUI_DATA_WIN->detail.data_display_info.regs_display_type !=
+                     TUI_DFLOAT_REGS)
+                   dpy_type = TUI_SFLOAT_REGS;
+                 else
+                   dpy_type =
+                     TUI_DATA_WIN->detail.data_display_info.regs_display_type;
+               }
+             else if (subset_compare (buf_ptr,
+                                     TUI_GENERAL_SPECIAL_REGS_NAME))
+               dpy_type = TUI_GENERAL_AND_SPECIAL_REGS;
+             else if (subset_compare (buf_ptr, TUI_GENERAL_REGS_NAME))
+               dpy_type = TUI_GENERAL_REGS;
+             else if (subset_compare (buf_ptr, TUI_SPECIAL_REGS_NAME))
+               dpy_type = TUI_SPECIAL_REGS;
+             else if (TUI_DATA_WIN)
+               {
+                 if (TUI_DATA_WIN->detail.data_display_info.regs_display_type !=
+                     TUI_UNDEFINED_REGS)
+                   dpy_type =
+                     TUI_DATA_WIN->detail.data_display_info.regs_display_type;
+                 else
+                   dpy_type = TUI_GENERAL_REGS;
+               }
+
+/* end of potential ifdef 
+ */
+
+/* if ifdefed out code above, then assume that the user wishes to display the 
+   general purpose registers 
+ */
+
+/*              dpy_type = TUI_GENERAL_REGS; 
+ */
+           }
+         else if (subset_compare (buf_ptr, "NEXT"))
+           new_layout = next_layout ();
+         else if (subset_compare (buf_ptr, "PREV"))
+           new_layout = prev_layout ();
+         else
+           status = TUI_FAILURE;
+         xfree (buf_ptr);
+
+         tui_set_layout (new_layout, dpy_type);
+       }
+    }
+  else
+    status = TUI_FAILURE;
+
+  return status;
+}
+
+
+static CORE_ADDR
+extract_display_start_addr (void)
+{
+  enum tui_layout_type cur_layout = tui_current_layout ();
+  CORE_ADDR addr;
+  CORE_ADDR pc;
+  struct symtab_and_line cursal = get_current_source_symtab_and_line ();
+
+  switch (cur_layout)
+    {
+    case SRC_COMMAND:
+    case SRC_DATA_COMMAND:
+      find_line_pc (cursal.symtab,
+                   TUI_SRC_WIN->detail.source_info.start_line_or_addr.line_no,
+                   &pc);
+      addr = pc;
+      break;
+    case DISASSEM_COMMAND:
+    case SRC_DISASSEM_COMMAND:
+    case DISASSEM_DATA_COMMAND:
+      addr = TUI_DISASM_WIN->detail.source_info.start_line_or_addr.addr;
+      break;
+    default:
+      addr = 0;
+      break;
+    }
+
+  return addr;
+}
+
+
+static void
+tui_handle_xdb_layout (struct tui_layout_def * layout_def)
+{
+  if (layout_def->split)
+    {
+      tui_set_layout (SRC_DISASSEM_COMMAND, TUI_UNDEFINED_REGS);
+      tui_set_win_focus_to (tui_win_list[layout_def->display_mode]);
+    }
+  else
+    {
+      if (layout_def->display_mode == SRC_WIN)
+       tui_set_layout (SRC_COMMAND, TUI_UNDEFINED_REGS);
+      else
+       tui_set_layout (DISASSEM_DATA_COMMAND, layout_def->regs_display_type);
+    }
+}
+
+
+static void
+tui_toggle_layout_command (char *arg, int from_tty)
+{
+  struct tui_layout_def * layout_def = tui_layout_def ();
+
+  /* Make sure the curses mode is enabled.  */
+  tui_enable ();
+  if (layout_def->display_mode == SRC_WIN)
+    layout_def->display_mode = DISASSEM_WIN;
+  else
+    layout_def->display_mode = SRC_WIN;
+
+  if (!layout_def->split)
+    tui_handle_xdb_layout (layout_def);
+}
+
+
+static void
+tui_toggle_split_layout_command (char *arg, int from_tty)
+{
+  struct tui_layout_def * layout_def = tui_layout_def ();
+
+  /* Make sure the curses mode is enabled.  */
+  tui_enable ();
+  layout_def->split = (!layout_def->split);
+  tui_handle_xdb_layout (layout_def);
+}
+
+
+static void
+tui_layout_command (char *arg, int from_tty)
+{
+  /* Make sure the curses mode is enabled.  */
+  tui_enable ();
+
+  /* Switch to the selected layout.  */
+  if (tui_set_layout_for_display_command (arg) != TUI_SUCCESS)
+    warning ("Invalid layout specified.\n%s", LAYOUT_USAGE);
+
+}
+
+/* Answer the previous layout to cycle to.  */
+static enum tui_layout_type
+next_layout (void)
+{
+  enum tui_layout_type new_layout;
+
+  new_layout = tui_current_layout ();
+  if (new_layout == UNDEFINED_LAYOUT)
+    new_layout = SRC_COMMAND;
+  else
+    {
+      new_layout++;
+      if (new_layout == UNDEFINED_LAYOUT)
+       new_layout = SRC_COMMAND;
+    }
+
+  return new_layout;
+}
+
+
+/* Answer the next layout to cycle to.  */
+static enum tui_layout_type
+prev_layout (void)
+{
+  enum tui_layout_type new_layout;
+
+  new_layout = tui_current_layout ();
+  if (new_layout == SRC_COMMAND)
+    new_layout = DISASSEM_DATA_COMMAND;
+  else
+    {
+      new_layout--;
+      if (new_layout == UNDEFINED_LAYOUT)
+       new_layout = DISASSEM_DATA_COMMAND;
+    }
+
+  return new_layout;
+}
+
+
+
+static void
+make_command_window (struct tui_win_info * * win_info_ptr, int height, int origin_y)
+{
+  init_and_make_win ((void **) win_info_ptr,
+                  CMD_WIN,
+                  height,
+                  tui_term_width (),
+                  0,
+                  origin_y,
+                  DONT_BOX_WINDOW);
+
+  (*win_info_ptr)->can_highlight = FALSE;
+}
+
+
+/*
+   ** make_source_window().
+ */
+static void
+make_source_window (struct tui_win_info * * win_info_ptr, int height, int origin_y)
+{
+  make_source_or_disasm_window (win_info_ptr, SRC_WIN, height, origin_y);
+
+  return;
+}                              /* make_source_window */
+
+
+/*
+   ** make_disasm_window().
+ */
+static void
+make_disasm_window (struct tui_win_info * * win_info_ptr, int height, int origin_y)
+{
+  make_source_or_disasm_window (win_info_ptr, DISASSEM_WIN, height, origin_y);
+
+  return;
+}                              /* make_disasm_window */
+
+
+static void
+make_data_window (struct tui_win_info * * win_info_ptr, int height, int origin_y)
+{
+  init_and_make_win ((void **) win_info_ptr,
+                  DATA_WIN,
+                  height,
+                  tui_term_width (),
+                  0,
+                  origin_y,
+                  BOX_WINDOW);
+}
+
+
+
+/* Show the Source/Command layout.  */
+static void
+show_source_command (void)
+{
+  show_source_or_disasm_and_command (SRC_COMMAND);
+}
+
+
+/* Show the Dissassem/Command layout.  */
+static void
+show_disasm_command (void)
+{
+  show_source_or_disasm_and_command (DISASSEM_COMMAND);
+}
+
+
+/* Show the Source/Disassem/Command layout.  */
+static void
+show_source_disasm_command (void)
+{
+  if (tui_current_layout () != SRC_DISASSEM_COMMAND)
+    {
+      int cmd_height, src_height, asm_height;
+
+      if (TUI_CMD_WIN != NULL)
+       cmd_height = TUI_CMD_WIN->generic.height;
+      else
+       cmd_height = tui_term_height () / 3;
+
+      src_height = (tui_term_height () - cmd_height) / 2;
+      asm_height = tui_term_height () - (src_height + cmd_height);
+
+      if (TUI_SRC_WIN == NULL)
+       make_source_window (&TUI_SRC_WIN, src_height, 0);
+      else
+       {
+         init_gen_win_info (&TUI_SRC_WIN->generic,
+                          TUI_SRC_WIN->generic.type,
+                          src_height,
+                          TUI_SRC_WIN->generic.width,
+                          TUI_SRC_WIN->detail.source_info.execution_info->width,
+                          0);
+         TUI_SRC_WIN->can_highlight = TRUE;
+         init_gen_win_info (TUI_SRC_WIN->detail.source_info.execution_info,
+                          EXEC_INFO_WIN,
+                          src_height,
+                          3,
+                          0,
+                          0);
+         tui_make_visible (&TUI_SRC_WIN->generic);
+         tui_make_visible (TUI_SRC_WIN->detail.source_info.execution_info);
+         TUI_SRC_WIN->detail.source_info.has_locator = FALSE;;
+       }
+      if (TUI_SRC_WIN != NULL)
+       {
+         struct tui_gen_win_info * locator = tui_locator_win_info_ptr ();
+
+         tui_show_source_content (TUI_SRC_WIN);
+         if (TUI_DISASM_WIN == NULL)
+           {
+             make_disasm_window (&TUI_DISASM_WIN, asm_height, src_height - 1);
+             init_and_make_win ((void **) & locator,
+                              LOCATOR_WIN,
+                              2 /* 1 */ ,
+                              tui_term_width (),
+                              0,
+                              (src_height + asm_height) - 1,
+                              DONT_BOX_WINDOW);
+           }
+         else
+           {
+             init_gen_win_info (locator,
+                              LOCATOR_WIN,
+                              2 /* 1 */ ,
+                              tui_term_width (),
+                              0,
+                              (src_height + asm_height) - 1);
+             TUI_DISASM_WIN->detail.source_info.has_locator = TRUE;
+             init_gen_win_info (
+                               &TUI_DISASM_WIN->generic,
+                               TUI_DISASM_WIN->generic.type,
+                               asm_height,
+                               TUI_DISASM_WIN->generic.width,
+                       TUI_DISASM_WIN->detail.source_info.execution_info->width,
+                               src_height - 1);
+             init_gen_win_info (TUI_DISASM_WIN->detail.source_info.execution_info,
+                              EXEC_INFO_WIN,
+                              asm_height,
+                              3,
+                              0,
+                              src_height - 1);
+             TUI_DISASM_WIN->can_highlight = TRUE;
+             tui_make_visible (&TUI_DISASM_WIN->generic);
+             tui_make_visible (TUI_DISASM_WIN->detail.source_info.execution_info);
+           }
+         if (TUI_DISASM_WIN != NULL)
+           {
+             TUI_SRC_WIN->detail.source_info.has_locator = FALSE;
+             TUI_DISASM_WIN->detail.source_info.has_locator = TRUE;
+             tui_make_visible (locator);
+             tui_show_locator_content ();
+             tui_show_source_content (TUI_DISASM_WIN);
+
+             if (TUI_CMD_WIN == NULL)
+               make_command_window (&TUI_CMD_WIN,
+                                   cmd_height,
+                                   tui_term_height () - cmd_height);
+             else
+               {
+                 init_gen_win_info (&TUI_CMD_WIN->generic,
+                                  TUI_CMD_WIN->generic.type,
+                                  TUI_CMD_WIN->generic.height,
+                                  TUI_CMD_WIN->generic.width,
+                                  0,
+                                  TUI_CMD_WIN->generic.origin.y);
+                 TUI_CMD_WIN->can_highlight = FALSE;
+                 tui_make_visible (&TUI_CMD_WIN->generic);
+               }
+             if (TUI_CMD_WIN != NULL)
+               tui_refresh_win (&TUI_CMD_WIN->generic);
+           }
+       }
+      tui_set_current_layout_to (SRC_DISASSEM_COMMAND);
+    }
+}
+
+
+/* Show the Source/Data/Command or the Dissassembly/Data/Command
+   layout.  */
+static void
+show_data (enum tui_layout_type new_layout)
+{
+  int total_height = (tui_term_height () - TUI_CMD_WIN->generic.height);
+  int src_height, data_height;
+  enum tui_win_type win_type;
+  struct tui_gen_win_info * locator = tui_locator_win_info_ptr ();
+
+
+  data_height = total_height / 2;
+  src_height = total_height - data_height;
+  tui_make_all_invisible ();
+  tui_make_invisible (locator);
+  make_data_window (&TUI_DATA_WIN, data_height, 0);
+  TUI_DATA_WIN->can_highlight = TRUE;
+  if (new_layout == SRC_DATA_COMMAND)
+    win_type = SRC_WIN;
+  else
+    win_type = DISASSEM_WIN;
+  if (tui_win_list[win_type] == NULL)
+    {
+      if (win_type == SRC_WIN)
+       make_source_window (&tui_win_list[win_type], src_height, data_height - 1);
+      else
+       make_disasm_window (&tui_win_list[win_type], src_height, data_height - 1);
+      init_and_make_win ((void **) & locator,
+                      LOCATOR_WIN,
+                      2 /* 1 */ ,
+                      tui_term_width (),
+                      0,
+                      total_height - 1,
+                      DONT_BOX_WINDOW);
+    }
+  else
+    {
+      init_gen_win_info (&tui_win_list[win_type]->generic,
+                      tui_win_list[win_type]->generic.type,
+                      src_height,
+                      tui_win_list[win_type]->generic.width,
+                  tui_win_list[win_type]->detail.source_info.execution_info->width,
+                      data_height - 1);
+      init_gen_win_info (tui_win_list[win_type]->detail.source_info.execution_info,
+                      EXEC_INFO_WIN,
+                      src_height,
+                      3,
+                      0,
+                      data_height - 1);
+      tui_make_visible (&tui_win_list[win_type]->generic);
+      tui_make_visible (tui_win_list[win_type]->detail.source_info.execution_info);
+      init_gen_win_info (locator,
+                      LOCATOR_WIN,
+                      2 /* 1 */ ,
+                      tui_term_width (),
+                      0,
+                      total_height - 1);
+    }
+  tui_win_list[win_type]->detail.source_info.has_locator = TRUE;
+  tui_make_visible (locator);
+  tui_show_locator_content ();
+  tui_add_to_source_windows (tui_win_list[win_type]);
+  tui_set_current_layout_to (new_layout);
+}
+
+/*
+   ** init_gen_win_info().
+ */
+static void
+init_gen_win_info (struct tui_gen_win_info * win_info, enum tui_win_type type,
+                 int height, int width, int origin_x, int origin_y)
+{
+  int h = height;
+
+  win_info->type = type;
+  win_info->width = width;
+  win_info->height = h;
+  if (h > 1)
+    {
+      win_info->viewport_height = h - 1;
+      if (win_info->type != CMD_WIN)
+       win_info->viewport_height--;
+    }
+  else
+    win_info->viewport_height = 1;
+  win_info->origin.x = origin_x;
+  win_info->origin.y = origin_y;
+
+  return;
+}                              /* init_gen_win_info */
+
+/*
+   ** init_and_make_win().
+ */
+static void
+init_and_make_win (void ** win_info_ptr, enum tui_win_type win_type,
+                 int height, int width, int origin_x, int origin_y, int box_it)
+{
+  void *opaque_win_info = *win_info_ptr;
+  struct tui_gen_win_info * generic;
+
+  if (opaque_win_info == NULL)
+    {
+      if (tui_win_is_auxillary (win_type))
+       opaque_win_info = (void *) tui_alloc_generic_win_info ();
+      else
+       opaque_win_info = (void *) tui_alloc_win_info (win_type);
+    }
+  if (tui_win_is_auxillary (win_type))
+    generic = (struct tui_gen_win_info *) opaque_win_info;
+  else
+    generic = &((struct tui_win_info *) opaque_win_info)->generic;
+
+  if (opaque_win_info != NULL)
+    {
+      init_gen_win_info (generic, win_type, height, width, origin_x, origin_y);
+      if (!tui_win_is_auxillary (win_type))
+       {
+         if (generic->type == CMD_WIN)
+           ((struct tui_win_info *) opaque_win_info)->can_highlight = FALSE;
+         else
+           ((struct tui_win_info *) opaque_win_info)->can_highlight = TRUE;
+       }
+      tui_make_window (generic, box_it);
+    }
+  *win_info_ptr = opaque_win_info;
+}
+
+
+static void
+make_source_or_disasm_window (struct tui_win_info * * win_info_ptr, enum tui_win_type type,
+                             int height, int origin_y)
+{
+  struct tui_gen_win_info * execution_info = (struct tui_gen_win_info *) NULL;
+
+  /*
+     ** Create the exeuction info window.
+   */
+  if (type == SRC_WIN)
+    execution_info = tui_source_exec_info_win_ptr ();
+  else
+    execution_info = tui_disassem_exec_info_win_ptr ();
+  init_and_make_win ((void **) & execution_info,
+                  EXEC_INFO_WIN,
+                  height,
+                  3,
+                  0,
+                  origin_y,
+                  DONT_BOX_WINDOW);
+  /*
+     ** Now create the source window.
+   */
+  init_and_make_win ((void **) win_info_ptr,
+                  type,
+                  height,
+                  tui_term_width () - execution_info->width,
+                  execution_info->width,
+                  origin_y,
+                  BOX_WINDOW);
+
+  (*win_info_ptr)->detail.source_info.execution_info = execution_info;
+}
+
+
+/* Show the Source/Command or the Disassem layout.   */
+static void
+show_source_or_disasm_and_command (enum tui_layout_type layout_type)
+{
+  if (tui_current_layout () != layout_type)
+    {
+      struct tui_win_info * *win_info_ptr;
+      int src_height, cmd_height;
+      struct tui_gen_win_info * locator = tui_locator_win_info_ptr ();
+
+      if (TUI_CMD_WIN != NULL)
+       cmd_height = TUI_CMD_WIN->generic.height;
+      else
+       cmd_height = tui_term_height () / 3;
+      src_height = tui_term_height () - cmd_height;
+
+
+      if (layout_type == SRC_COMMAND)
+       win_info_ptr = &TUI_SRC_WIN;
+      else
+       win_info_ptr = &TUI_DISASM_WIN;
+
+      if ((*win_info_ptr) == NULL)
+       {
+         if (layout_type == SRC_COMMAND)
+           make_source_window (win_info_ptr, src_height - 1, 0);
+         else
+           make_disasm_window (win_info_ptr, src_height - 1, 0);
+         init_and_make_win ((void **) & locator,
+                          LOCATOR_WIN,
+                          2 /* 1 */ ,
+                          tui_term_width (),
+                          0,
+                          src_height - 1,
+                          DONT_BOX_WINDOW);
+       }
+      else
+       {
+         init_gen_win_info (locator,
+                          LOCATOR_WIN,
+                          2 /* 1 */ ,
+                          tui_term_width (),
+                          0,
+                          src_height - 1);
+         (*win_info_ptr)->detail.source_info.has_locator = TRUE;
+         init_gen_win_info (
+                           &(*win_info_ptr)->generic,
+                           (*win_info_ptr)->generic.type,
+                           src_height - 1,
+                           (*win_info_ptr)->generic.width,
+                     (*win_info_ptr)->detail.source_info.execution_info->width,
+                           0);
+         init_gen_win_info ((*win_info_ptr)->detail.source_info.execution_info,
+                          EXEC_INFO_WIN,
+                          src_height - 1,
+                          3,
+                          0,
+                          0);
+         (*win_info_ptr)->can_highlight = TRUE;
+         tui_make_visible (&(*win_info_ptr)->generic);
+         tui_make_visible ((*win_info_ptr)->detail.source_info.execution_info);
+       }
+      if ((*win_info_ptr) != NULL)
+       {
+         (*win_info_ptr)->detail.source_info.has_locator = TRUE;
+         tui_make_visible (locator);
+         tui_show_locator_content ();
+         tui_show_source_content (*win_info_ptr);
+
+         if (TUI_CMD_WIN == NULL)
+           {
+             make_command_window (&TUI_CMD_WIN, cmd_height, src_height);
+             tui_refresh_win (&TUI_CMD_WIN->generic);
+           }
+         else
+           {
+             init_gen_win_info (&TUI_CMD_WIN->generic,
+                              TUI_CMD_WIN->generic.type,
+                              TUI_CMD_WIN->generic.height,
+                              TUI_CMD_WIN->generic.width,
+                              TUI_CMD_WIN->generic.origin.x,
+                              TUI_CMD_WIN->generic.origin.y);
+             TUI_CMD_WIN->can_highlight = FALSE;
+             tui_make_visible (&TUI_CMD_WIN->generic);
+           }
+       }
+      tui_set_current_layout_to (layout_type);
+    }
+}
diff --git a/gdb/tui/tui-layout.h b/gdb/tui/tui-layout.h
new file mode 100644 (file)
index 0000000..5df1f0b
--- /dev/null
@@ -0,0 +1,38 @@
+/* TUI layout window management.
+
+   Copyright 1998, 1999, 2000, 2001, 2002, 2004 Free Software
+   Foundation, Inc.
+
+   Contributed by Hewlett-Packard Company.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef TUI_LAYOUT_H
+#define TUI_LAYOUT_H
+
+#include "tui/tui.h"
+#include "tui/tui-data.h"
+
+extern void tui_add_win_to_layout (enum tui_win_type);
+extern int tui_default_win_height (enum tui_win_type, enum tui_layout_type);
+extern int tui_default_win_viewport_height (enum tui_win_type,
+                                           enum tui_layout_type);
+extern enum tui_status tui_set_layout (enum tui_layout_type,
+                                      enum tui_register_display_type);
+
+#endif /*TUI_LAYOUT_H */
diff --git a/gdb/tui/tui-regs.c b/gdb/tui/tui-regs.c
new file mode 100644 (file)
index 0000000..d3ff1eb
--- /dev/null
@@ -0,0 +1,984 @@
+/* TUI display registers in window.
+
+   Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
+   Foundation, Inc.
+
+   Contributed by Hewlett-Packard Company.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include "defs.h"
+#include "tui/tui.h"
+#include "tui/tui-data.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "gdbcmd.h"
+#include "frame.h"
+#include "regcache.h"
+#include "inferior.h"
+#include "target.h"
+#include "gdb_string.h"
+#include "tui/tui-layout.h"
+#include "tui/tui-win.h"
+#include "tui/tui-windata.h"
+#include "tui/tui-wingeneral.h"
+#include "tui/tui-file.h"
+
+#ifdef HAVE_NCURSES_H       
+#include <ncurses.h>
+#else
+#ifdef HAVE_CURSES_H
+#include <curses.h>
+#endif
+#endif
+
+/*****************************************
+** LOCAL DEFINITIONS                    **
+******************************************/
+#define DOUBLE_FLOAT_LABEL_WIDTH    6
+#define DOUBLE_FLOAT_LABEL_FMT      "%6.6s: "
+#define DOUBLE_FLOAT_VALUE_WIDTH    30 /*min of 16 but may be in sci notation */
+
+#define SINGLE_FLOAT_LABEL_WIDTH    6
+#define SINGLE_FLOAT_LABEL_FMT      "%6.6s: "
+#define SINGLE_FLOAT_VALUE_WIDTH    25 /* min of 8 but may be in sci notation */
+
+#define SINGLE_LABEL_WIDTH    16
+#define SINGLE_LABEL_FMT      "%10.10s: "
+#define SINGLE_VALUE_WIDTH    20 /* minimum of 8 but may be in sci notation */
+
+/* In the code HP gave Cygnus, this was actually a function call to a
+   PA-specific function, which was supposed to determine whether the
+   target was a 64-bit or 32-bit processor.  However, the 64-bit
+   support wasn't complete, so we didn't merge that in, so we leave
+   this here as a stub.  */
+#define IS_64BIT 0
+
+/*****************************************
+** STATIC DATA                          **
+******************************************/
+
+
+/*****************************************
+** STATIC LOCAL FUNCTIONS FORWARD DECLS    **
+******************************************/
+static enum tui_status tui_set_regs_content
+  (int, int, struct frame_info *, enum tui_register_display_type, int);
+static const char *tui_register_name (int);
+static enum tui_status tui_get_register_raw_value (int, char *, struct frame_info *);
+static void tui_set_register_element
+  (int, struct frame_info *, struct tui_data_element *, int);
+static void tui_display_register (int, struct tui_gen_win_info *, enum precision_type);
+static void tui_register_format
+  (char *, int, int, struct tui_data_element *, enum precision_type);
+static enum tui_status tui_set_general_regs_content (int);
+static enum tui_status tui_set_special_regs_content (int);
+static enum tui_status tui_set_general_and_special_regs_content (int);
+static enum tui_status tui_set_float_regs_content (enum tui_register_display_type, int);
+static int tui_reg_value_has_changed
+  (struct tui_data_element *, struct frame_info *, char *);
+static void tui_show_float_command (char *, int);
+static void tui_show_general_command (char *, int);
+static void tui_show_special_command (char *, int);
+static void tui_v_show_registers_command_support (enum tui_register_display_type);
+static void _tui_toggle_float_regs_command (char *, int);
+static void tui_scroll_regs_forward_command (char *, int);
+static void tui_scroll_regs_backward_command (char *, int);
+
+
+
+/*****************************************
+** PUBLIC FUNCTIONS                     **
+******************************************/
+
+/* Answer the number of the last line in the regs display.  If there
+   are no registers (-1) is returned.  */
+int
+tui_last_regs_line_no (void)
+{
+  int num_lines = (-1);
+
+  if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
+    {
+      num_lines = (TUI_DATA_WIN->detail.data_display_info.regs_content_count /
+                 TUI_DATA_WIN->detail.data_display_info.regs_column_count);
+      if (TUI_DATA_WIN->detail.data_display_info.regs_content_count %
+         TUI_DATA_WIN->detail.data_display_info.regs_column_count)
+       num_lines++;
+    }
+  return num_lines;
+}
+
+
+/* Answer the line number that the register element at element_no is
+   on.  If element_no is greater than the number of register elements
+   there are, -1 is returned.  */
+int
+tui_line_from_reg_element_no (int element_no)
+{
+  if (element_no < TUI_DATA_WIN->detail.data_display_info.regs_content_count)
+    {
+      int i, line = (-1);
+
+      i = 1;
+      while (line == (-1))
+       {
+         if (element_no <
+             (TUI_DATA_WIN->detail.data_display_info.regs_column_count * i))
+           line = i - 1;
+         else
+           i++;
+       }
+
+      return line;
+    }
+  else
+    return (-1);
+}
+
+
+/* Answer the index of the first element in line_no.  If line_no is past
+   the register area (-1) is returned.  */
+int
+tui_first_reg_element_no_inline (int line_no)
+{
+  if ((line_no * TUI_DATA_WIN->detail.data_display_info.regs_column_count)
+      <= TUI_DATA_WIN->detail.data_display_info.regs_content_count)
+    return ((line_no + 1) *
+           TUI_DATA_WIN->detail.data_display_info.regs_column_count) -
+      TUI_DATA_WIN->detail.data_display_info.regs_column_count;
+  else
+    return (-1);
+}
+
+
+/* Answer the index of the last element in line_no.  If line_no is
+   past the register area (-1) is returned.  */
+int
+tui_last_reg_element_no_in_line (int line_no)
+{
+  if ((line_no * TUI_DATA_WIN->detail.data_display_info.regs_column_count) <=
+      TUI_DATA_WIN->detail.data_display_info.regs_content_count)
+    return ((line_no + 1) *
+           TUI_DATA_WIN->detail.data_display_info.regs_column_count) - 1;
+  else
+    return (-1);
+}
+
+
+/* Calculate the number of columns that should be used to display the
+   registers.  */
+int
+tui_calculate_regs_column_count (enum tui_register_display_type dpy_type)
+{
+  int col_count, col_width;
+
+  if (IS_64BIT || dpy_type == TUI_DFLOAT_REGS)
+    col_width = DOUBLE_FLOAT_VALUE_WIDTH + DOUBLE_FLOAT_LABEL_WIDTH;
+  else
+    {
+      if (dpy_type == TUI_SFLOAT_REGS)
+       col_width = SINGLE_FLOAT_VALUE_WIDTH + SINGLE_FLOAT_LABEL_WIDTH;
+      else
+       col_width = SINGLE_VALUE_WIDTH + SINGLE_LABEL_WIDTH;
+    }
+  col_count = (TUI_DATA_WIN->generic.width - 2) / col_width;
+
+  return col_count;
+}
+
+
+/* Show the registers int the data window as indicated by dpy_type.  If
+   there is any other registers being displayed, then they are
+   cleared.  What registers are displayed is dependent upon dpy_type.  */
+void
+tui_show_registers (enum tui_register_display_type dpy_type)
+{
+  enum tui_status ret = TUI_FAILURE;
+  int refresh_values_only = FALSE;
+
+  /* Say that registers should be displayed, even if there is a problem */
+  TUI_DATA_WIN->detail.data_display_info.display_regs = TRUE;
+
+  if (target_has_registers)
+    {
+      refresh_values_only =
+       (dpy_type == TUI_DATA_WIN->detail.data_display_info.regs_display_type);
+      switch (dpy_type)
+       {
+       case TUI_GENERAL_REGS:
+         ret = tui_set_general_regs_content (refresh_values_only);
+         break;
+       case TUI_SFLOAT_REGS:
+       case TUI_DFLOAT_REGS:
+         ret = tui_set_float_regs_content (dpy_type, refresh_values_only);
+         break;
+
+/* could ifdef out */
+
+       case TUI_SPECIAL_REGS:
+         ret = tui_set_special_regs_content (refresh_values_only);
+         break;
+       case TUI_GENERAL_AND_SPECIAL_REGS:
+         ret = tui_set_general_and_special_regs_content (refresh_values_only);
+         break;
+
+/* end of potential if def */
+
+       default:
+         break;
+       }
+    }
+  if (ret == TUI_FAILURE)
+    {
+      TUI_DATA_WIN->detail.data_display_info.regs_display_type = TUI_UNDEFINED_REGS;
+      tui_erase_data_content (NO_REGS_STRING);
+    }
+  else
+    {
+      int i;
+
+      /* Clear all notation of changed values */
+      for (i = 0; (i < TUI_DATA_WIN->detail.data_display_info.regs_content_count); i++)
+       {
+         struct tui_gen_win_info * data_item_win;
+
+         data_item_win = &TUI_DATA_WIN->detail.data_display_info.
+           regs_content[i]->which_element.data_window;
+         (&((struct tui_win_element *)
+            data_item_win->content[0])->which_element.data)->highlight = FALSE;
+       }
+      TUI_DATA_WIN->detail.data_display_info.regs_display_type = dpy_type;
+      tui_display_all_data ();
+    }
+  (tui_layout_def ())->regs_display_type = dpy_type;
+
+  return;
+}
+
+
+/* Function to display the registers in the content from
+   'start_element_no' until the end of the register content or the end
+   of the display height.  No checking for displaying past the end of
+   the registers is done here.  */
+void
+tui_display_registers_from (int start_element_no)
+{
+  if (TUI_DATA_WIN->detail.data_display_info.regs_content != (tui_win_content) NULL &&
+      TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
+    {
+      int i = start_element_no;
+      int j, value_chars_wide, item_win_width, cur_y, label_width;
+      enum precision_type precision;
+
+      precision = (TUI_DATA_WIN->detail.data_display_info.regs_display_type
+                  == TUI_DFLOAT_REGS) ?
+       double_precision : unspecified_precision;
+      if (IS_64BIT ||
+         TUI_DATA_WIN->detail.data_display_info.regs_display_type == TUI_DFLOAT_REGS)
+       {
+         value_chars_wide = DOUBLE_FLOAT_VALUE_WIDTH;
+         label_width = DOUBLE_FLOAT_LABEL_WIDTH;
+       }
+      else
+       {
+         if (TUI_DATA_WIN->detail.data_display_info.regs_display_type ==
+             TUI_SFLOAT_REGS)
+           {
+             value_chars_wide = SINGLE_FLOAT_VALUE_WIDTH;
+             label_width = SINGLE_FLOAT_LABEL_WIDTH;
+           }
+         else
+           {
+             value_chars_wide = SINGLE_VALUE_WIDTH;
+             label_width = SINGLE_LABEL_WIDTH;
+           }
+       }
+      item_win_width = value_chars_wide + label_width;
+      /*
+         ** Now create each data "sub" window, and write the display into it.
+       */
+      cur_y = 1;
+      while (i < TUI_DATA_WIN->detail.data_display_info.regs_content_count &&
+            cur_y <= TUI_DATA_WIN->generic.viewport_height)
+       {
+         for (j = 0;
+              (j < TUI_DATA_WIN->detail.data_display_info.regs_column_count &&
+               i < TUI_DATA_WIN->detail.data_display_info.regs_content_count); j++)
+           {
+             struct tui_gen_win_info * data_item_win;
+             struct tui_data_element * data_element_ptr;
+
+             /* create the window if necessary */
+             data_item_win = &TUI_DATA_WIN->detail.data_display_info.
+               regs_content[i]->which_element.data_window;
+             data_element_ptr = &((struct tui_win_element *)
+                                data_item_win->content[0])->which_element.data;
+             if (data_item_win->handle == (WINDOW *) NULL)
+               {
+                 data_item_win->height = 1;
+                 data_item_win->width = (precision == double_precision) ?
+                   item_win_width + 2 : item_win_width + 1;
+                 data_item_win->origin.x = (item_win_width * j) + 1;
+                 data_item_win->origin.y = cur_y;
+                 tui_make_window (data_item_win, DONT_BOX_WINDOW);
+                  scrollok (data_item_win->handle, FALSE);
+               }
+              touchwin (data_item_win->handle);
+
+             /*
+                ** Get the printable representation of the register
+                ** and display it
+              */
+             tui_display_register (
+                           data_element_ptr->item_no, data_item_win, precision);
+             i++;              /* next register */
+           }
+         cur_y++;              /* next row; */
+       }
+    }
+
+  return;
+}
+
+
+/* Function to display the registers in the content from
+   'start_element_no' on 'start_line_no' until the end of the register
+   content or the end of the display height.  This function checks
+   that we won't display off the end of the register display.  */
+void
+tui_display_reg_element_at_line (int start_element_no, int start_line_no)
+{
+  if (TUI_DATA_WIN->detail.data_display_info.regs_content != (tui_win_content) NULL &&
+      TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
+    {
+      int element_no = start_element_no;
+
+      if (start_element_no != 0 && start_line_no != 0)
+       {
+         int last_line_no, first_line_on_last_page;
+
+         last_line_no = tui_last_regs_line_no ();
+         first_line_on_last_page = last_line_no - (TUI_DATA_WIN->generic.height - 2);
+         if (first_line_on_last_page < 0)
+           first_line_on_last_page = 0;
+         /*
+            ** If there is no other data displayed except registers,
+            ** and the element_no causes us to scroll past the end of the
+            ** registers, adjust what element to really start the display at.
+          */
+         if (TUI_DATA_WIN->detail.data_display_info.data_content_count <= 0 &&
+             start_line_no > first_line_on_last_page)
+           element_no = tui_first_reg_element_no_inline (first_line_on_last_page);
+       }
+      tui_display_registers_from (element_no);
+    }
+}
+
+
+
+/* Function to display the registers starting at line line_no in the
+   data window.  Answers the line number that the display actually
+   started from.  If nothing is displayed (-1) is returned.  */
+int
+tui_display_registers_from_line (int line_no, int force_display)
+{
+  if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
+    {
+      int line, element_no;
+
+      if (line_no < 0)
+       line = 0;
+      else if (force_display)
+       {                       /*
+                                  ** If we must display regs (force_display is true), then make
+                                  ** sure that we don't display off the end of the registers.
+                                */
+         if (line_no >= tui_last_regs_line_no ())
+           {
+             if ((line = tui_line_from_reg_element_no (
+                TUI_DATA_WIN->detail.data_display_info.regs_content_count - 1)) < 0)
+               line = 0;
+           }
+         else
+           line = line_no;
+       }
+      else
+       line = line_no;
+
+      element_no = tui_first_reg_element_no_inline (line);
+      if (element_no < TUI_DATA_WIN->detail.data_display_info.regs_content_count)
+       tui_display_reg_element_at_line (element_no, line);
+      else
+       line = (-1);
+
+      return line;
+    }
+
+  return (-1);                 /* nothing was displayed */
+}
+
+
+/* This function check all displayed registers for changes in values,
+   given a particular frame.  If the values have changed, they are
+   updated with the new value and highlighted.  */
+void
+tui_check_register_values (struct frame_info *frame)
+{
+  if (TUI_DATA_WIN != NULL && TUI_DATA_WIN->generic.is_visible)
+    {
+      if (TUI_DATA_WIN->detail.data_display_info.regs_content_count <= 0 &&
+         TUI_DATA_WIN->detail.data_display_info.display_regs)
+       tui_show_registers ((tui_layout_def ())->regs_display_type);
+      else
+       {
+         int i, j;
+         char raw_buf[MAX_REGISTER_SIZE];
+
+         for (i = 0;
+              (i < TUI_DATA_WIN->detail.data_display_info.regs_content_count); i++)
+           {
+             struct tui_data_element * data_element_ptr;
+             struct tui_gen_win_info * data_item_win_ptr;
+             int was_hilighted;
+
+             data_item_win_ptr = &TUI_DATA_WIN->detail.data_display_info.
+               regs_content[i]->which_element.data_window;
+             data_element_ptr = &((struct tui_win_element *)
+                            data_item_win_ptr->content[0])->which_element.data;
+             was_hilighted = data_element_ptr->highlight;
+             data_element_ptr->highlight =
+               tui_reg_value_has_changed (data_element_ptr, frame, &raw_buf[0]);
+             if (data_element_ptr->highlight)
+               {
+                  int size;
+
+                  size = DEPRECATED_REGISTER_RAW_SIZE (data_element_ptr->item_no);
+                 for (j = 0; j < size; j++)
+                   ((char *) data_element_ptr->value)[j] = raw_buf[j];
+                 tui_display_register (
+                                       data_element_ptr->item_no,
+                                       data_item_win_ptr,
+                       ((TUI_DATA_WIN->detail.data_display_info.regs_display_type ==
+                         TUI_DFLOAT_REGS) ?
+                        double_precision : unspecified_precision));
+               }
+             else if (was_hilighted)
+               {
+                 data_element_ptr->highlight = FALSE;
+                 tui_display_register (
+                                       data_element_ptr->item_no,
+                                       data_item_win_ptr,
+                       ((TUI_DATA_WIN->detail.data_display_info.regs_display_type ==
+                         TUI_DFLOAT_REGS) ?
+                        double_precision : unspecified_precision));
+               }
+           }
+       }
+    }
+  return;
+}
+
+
+/*
+   ** tui_toggle_float_regs().
+ */
+void
+tui_toggle_float_regs (void)
+{
+  struct tui_layout_def * layout_def = tui_layout_def ();
+
+  if (layout_def->float_regs_display_type == TUI_SFLOAT_REGS)
+    layout_def->float_regs_display_type = TUI_DFLOAT_REGS;
+  else
+    layout_def->float_regs_display_type = TUI_SFLOAT_REGS;
+
+  if (TUI_DATA_WIN != NULL && TUI_DATA_WIN->generic.is_visible &&
+      (TUI_DATA_WIN->detail.data_display_info.regs_display_type == TUI_SFLOAT_REGS ||
+       TUI_DATA_WIN->detail.data_display_info.regs_display_type == TUI_DFLOAT_REGS))
+    tui_show_registers (layout_def->float_regs_display_type);
+
+  return;
+}                              /* tui_toggle_float_regs */
+
+
+void
+_initialize_tui_regs (void)
+{
+  if (xdb_commands)
+    {
+      add_com ("fr", class_tui, tui_show_float_command,
+              "Display only floating point registers\n");
+      add_com ("gr", class_tui, tui_show_general_command,
+              "Display only general registers\n");
+      add_com ("sr", class_tui, tui_show_special_command,
+              "Display only special registers\n");
+      add_com ("+r", class_tui, tui_scroll_regs_forward_command,
+              "Scroll the registers window forward\n");
+      add_com ("-r", class_tui, tui_scroll_regs_backward_command,
+              "Scroll the register window backward\n");
+      add_com ("tf", class_tui, _tui_toggle_float_regs_command,
+              "Toggle between single and double precision floating point registers.\n");
+      add_cmd (TUI_FLOAT_REGS_NAME_LOWER,
+              class_tui,
+              _tui_toggle_float_regs_command,
+              "Toggle between single and double precision floating point \
+registers.\n",
+              &togglelist);
+    }
+}
+
+
+/*****************************************
+** STATIC LOCAL FUNCTIONS                 **
+******************************************/
+
+
+/*
+   ** tui_register_name().
+   **        Return the register name.
+ */
+static const char *
+tui_register_name (int reg_num)
+{
+  return REGISTER_NAME (reg_num);
+}
+extern int pagination_enabled;
+
+static void
+tui_restore_gdbout (void *ui)
+{
+  ui_file_delete (gdb_stdout);
+  gdb_stdout = (struct ui_file*) ui;
+  pagination_enabled = 1;
+}
+
+/*
+   ** tui_register_format
+   **        Function to format the register name and value into a buffer,
+   **        suitable for printing or display
+ */
+static void
+tui_register_format (char *buf, int buf_len, int reg_num,
+                    struct tui_data_element * data_element,
+                    enum precision_type precision)
+{
+  struct ui_file *stream;
+  struct ui_file *old_stdout;
+  const char *name;
+  struct cleanup *cleanups;
+  char *p;
+  int pos;
+
+  name = REGISTER_NAME (reg_num);
+  if (name == 0)
+    {
+      strcpy (buf, "");
+      return;
+    }
+  
+  pagination_enabled = 0;
+  old_stdout = gdb_stdout;
+  stream = tui_sfileopen (buf_len);
+  gdb_stdout = stream;
+  cleanups = make_cleanup (tui_restore_gdbout, (void*) old_stdout);
+  gdbarch_print_registers_info (current_gdbarch, stream, deprecated_selected_frame,
+                                reg_num, 1);
+
+  /* Save formatted output in the buffer.  */
+  p = tui_file_get_strbuf (stream);
+  pos = 0;
+  while (*p && *p == *name++ && buf_len)
+    {
+      *buf++ = *p++;
+      buf_len--;
+      pos++;
+    }
+  while (*p == ' ')
+    p++;
+  while (pos < 8 && buf_len)
+    {
+      *buf++ = ' ';
+      buf_len--;
+      pos++;
+    }
+  strncpy (buf, p, buf_len);
+
+  /* Remove the possible \n.  */
+  p = strchr (buf, '\n');
+  if (p)
+    *p = 0;
+
+  do_cleanups (cleanups);
+}
+
+
+#define NUM_GENERAL_REGS    32
+/* Set the content of the data window to consist of the general
+   registers.  */
+static enum tui_status
+tui_set_general_regs_content (int refresh_values_only)
+{
+  return (tui_set_regs_content (0,
+                             NUM_GENERAL_REGS - 1,
+                             deprecated_selected_frame,
+                             TUI_GENERAL_REGS,
+                             refresh_values_only));
+
+}
+
+
+#ifndef PCOQ_HEAD_REGNUM
+#define START_SPECIAL_REGS  0
+#else
+#define START_SPECIAL_REGS    PCOQ_HEAD_REGNUM
+#endif
+
+/* Set the content of the data window to consist of the special
+   registers.  */
+static enum tui_status
+tui_set_special_regs_content (int refresh_values_only)
+{
+  enum tui_status ret = TUI_FAILURE;
+  int end_reg_num;
+
+  end_reg_num = FP0_REGNUM - 1;
+  ret = tui_set_regs_content (START_SPECIAL_REGS,
+                           end_reg_num,
+                           deprecated_selected_frame,
+                           TUI_SPECIAL_REGS,
+                           refresh_values_only);
+
+  return ret;
+}
+
+
+/* Set the content of the data window to consist of the special
+   registers.  */
+static enum tui_status
+tui_set_general_and_special_regs_content (int refresh_values_only)
+{
+  enum tui_status ret = TUI_FAILURE;
+  int end_reg_num = (-1);
+
+  end_reg_num = FP0_REGNUM - 1;
+  ret = tui_set_regs_content (
+        0, end_reg_num, deprecated_selected_frame, TUI_SPECIAL_REGS, refresh_values_only);
+
+  return ret;
+}
+
+/* Set the content of the data window to consist of the float
+   registers.  */
+static enum tui_status
+tui_set_float_regs_content (enum tui_register_display_type dpy_type,
+                           int refresh_values_only)
+{
+  enum tui_status ret = TUI_FAILURE;
+  int start_reg_num;
+
+  start_reg_num = FP0_REGNUM;
+  ret = tui_set_regs_content (start_reg_num,
+                           NUM_REGS - 1,
+                           deprecated_selected_frame,
+                           dpy_type,
+                           refresh_values_only);
+
+  return ret;
+}
+
+
+/* Answer TRUE if the register's value has changed, FALSE otherwise.
+   If TRUE, new_value is filled in with the new value.  */
+static int
+tui_reg_value_has_changed (struct tui_data_element * data_element,
+                          struct frame_info *frame, char *new_value)
+{
+  int has_changed = FALSE;
+
+  if (data_element->item_no != UNDEFINED_ITEM &&
+      tui_register_name (data_element->item_no) != (char *) NULL)
+    {
+      char raw_buf[MAX_REGISTER_SIZE];
+      int i;
+
+      if (tui_get_register_raw_value (data_element->item_no, raw_buf, frame) == TUI_SUCCESS)
+       {
+          int size = DEPRECATED_REGISTER_RAW_SIZE (data_element->item_no);
+          
+         for (i = 0; (i < size && !has_changed); i++)
+           has_changed = (((char *) data_element->value)[i] != raw_buf[i]);
+         if (has_changed && new_value != (char *) NULL)
+           {
+             for (i = 0; i < size; i++)
+               new_value[i] = raw_buf[i];
+           }
+       }
+    }
+  return has_changed;
+}
+
+
+
+/* Get the register raw value.  The raw value is returned in reg_value.  */
+static enum tui_status
+tui_get_register_raw_value (int reg_num, char *reg_value, struct frame_info *frame)
+{
+  enum tui_status ret = TUI_FAILURE;
+
+  if (target_has_registers)
+    {
+      get_frame_register (frame, reg_num, reg_value);
+      /* NOTE: cagney/2003-03-13: This is bogus.  It is refering to
+         the register cache and not the frame which could have pulled
+         the register value off the stack.  */
+      if (register_cached (reg_num) >= 0)
+       ret = TUI_SUCCESS;
+    }
+  return ret;
+}
+
+
+
+/* Function to initialize a data element with the input and the
+   register value.  */
+static void
+tui_set_register_element (int reg_num, struct frame_info *frame,
+                         struct tui_data_element * data_element,
+                         int refresh_value_only)
+{
+  if (data_element != (struct tui_data_element *) NULL)
+    {
+      if (!refresh_value_only)
+       {
+         data_element->item_no = reg_num;
+         data_element->name = tui_register_name (reg_num);
+         data_element->highlight = FALSE;
+       }
+      if (data_element->value == NULL)
+       data_element->value = xmalloc (MAX_REGISTER_SIZE);
+      if (data_element->value != NULL)
+       tui_get_register_raw_value (reg_num, data_element->value, frame);
+    }
+}
+
+
+/* Set the content of the data window to consist of the registers
+   numbered from start_reg_num to end_reg_num.  Note that if
+   refresh_values_only is TRUE, start_reg_num and end_reg_num are
+   ignored.  */
+static enum tui_status
+tui_set_regs_content (int start_reg_num, int end_reg_num,
+                    struct frame_info *frame,
+                    enum tui_register_display_type dpy_type,
+                    int refresh_values_only)
+{
+  enum tui_status ret = TUI_FAILURE;
+  int num_regs = end_reg_num - start_reg_num + 1;
+  int allocated_here = FALSE;
+
+  if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0 &&
+      !refresh_values_only)
+    {
+      tui_free_data_content (TUI_DATA_WIN->detail.data_display_info.regs_content,
+                            TUI_DATA_WIN->detail.data_display_info.regs_content_count);
+      TUI_DATA_WIN->detail.data_display_info.regs_content_count = 0;
+    }
+  if (TUI_DATA_WIN->detail.data_display_info.regs_content_count <= 0)
+    {
+      TUI_DATA_WIN->detail.data_display_info.regs_content =
+       tui_alloc_content (num_regs, DATA_WIN);
+      allocated_here = TRUE;
+    }
+
+  if (TUI_DATA_WIN->detail.data_display_info.regs_content != (tui_win_content) NULL)
+    {
+      int i;
+
+      if (!refresh_values_only || allocated_here)
+       {
+         TUI_DATA_WIN->generic.content = NULL;
+         TUI_DATA_WIN->generic.content_size = 0;
+         tui_add_content_elements (&TUI_DATA_WIN->generic, num_regs);
+         TUI_DATA_WIN->detail.data_display_info.regs_content =
+           (tui_win_content) TUI_DATA_WIN->generic.content;
+         TUI_DATA_WIN->detail.data_display_info.regs_content_count = num_regs;
+       }
+      /*
+         ** Now set the register names and values
+       */
+      for (i = start_reg_num; (i <= end_reg_num); i++)
+       {
+         struct tui_gen_win_info * data_item_win;
+
+         data_item_win = &TUI_DATA_WIN->detail.data_display_info.
+           regs_content[i - start_reg_num]->which_element.data_window;
+         tui_set_register_element (
+                                  i,
+                                  frame,
+          &((struct tui_win_element *) data_item_win->content[0])->which_element.data,
+                                  !allocated_here && refresh_values_only);
+       }
+      TUI_DATA_WIN->detail.data_display_info.regs_column_count =
+       tui_calculate_regs_column_count (dpy_type);
+#ifdef LATER
+      if (TUI_DATA_WIN->detail.data_display_info.data_content_count > 0)
+       {
+         /* delete all the windows? */
+         /* realloc content equal to data_content_count + regs_content_count */
+         /* append TUI_DATA_WIN->detail.data_display_info.data_content to content */
+       }
+#endif
+      TUI_DATA_WIN->generic.content_size =
+       TUI_DATA_WIN->detail.data_display_info.regs_content_count +
+       TUI_DATA_WIN->detail.data_display_info.data_content_count;
+      ret = TUI_SUCCESS;
+    }
+
+  return ret;
+}
+
+
+/* Function to display a register in a window.  If hilite is TRUE,
+   than the value will be displayed in reverse video.  */
+static void
+tui_display_register (int reg_num,
+                     struct tui_gen_win_info * win_info,               /* the data item window */
+                     enum precision_type precision)
+{
+  if (win_info->handle != (WINDOW *) NULL)
+    {
+      int i;
+      char buf[40];
+      int value_chars_wide, label_width;
+      struct tui_data_element * data_element_ptr = &((tui_win_content)
+                                   win_info->content)[0]->which_element.data;
+
+      if (IS_64BIT ||
+         TUI_DATA_WIN->detail.data_display_info.regs_display_type == TUI_DFLOAT_REGS)
+       {
+         value_chars_wide = DOUBLE_FLOAT_VALUE_WIDTH;
+         label_width = DOUBLE_FLOAT_LABEL_WIDTH;
+       }
+      else
+       {
+         if (TUI_DATA_WIN->detail.data_display_info.regs_display_type ==
+             TUI_SFLOAT_REGS)
+           {
+             value_chars_wide = SINGLE_FLOAT_VALUE_WIDTH;
+             label_width = SINGLE_FLOAT_LABEL_WIDTH;
+           }
+         else
+           {
+             value_chars_wide = SINGLE_VALUE_WIDTH;
+             label_width = SINGLE_LABEL_WIDTH;
+           }
+       }
+
+      buf[0] = (char) 0;
+      tui_register_format (buf,
+                         value_chars_wide + label_width,
+                         reg_num,
+                         data_element_ptr,
+                         precision);
+
+      if (data_element_ptr->highlight)
+       wstandout (win_info->handle);
+
+      wmove (win_info->handle, 0, 0);
+      for (i = 1; i < win_info->width; i++)
+        waddch (win_info->handle, ' ');
+      wmove (win_info->handle, 0, 0);
+      waddstr (win_info->handle, buf);
+
+      if (data_element_ptr->highlight)
+       wstandend (win_info->handle);
+      tui_refresh_win (win_info);
+    }
+}
+
+
+static void
+tui_v_show_registers_command_support (enum tui_register_display_type dpy_type)
+{
+
+  if (TUI_DATA_WIN != NULL && TUI_DATA_WIN->generic.is_visible)
+    {                          /* Data window already displayed, show the registers */
+      if (TUI_DATA_WIN->detail.data_display_info.regs_display_type != dpy_type)
+       tui_show_registers (dpy_type);
+    }
+  else
+    (tui_layout_def ())->regs_display_type = dpy_type;
+
+  return;
+}
+
+
+static void
+tui_show_float_command (char *arg, int from_tty)
+{
+  if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->generic.is_visible ||
+      (TUI_DATA_WIN->detail.data_display_info.regs_display_type != TUI_SFLOAT_REGS &&
+       TUI_DATA_WIN->detail.data_display_info.regs_display_type != TUI_DFLOAT_REGS))
+    tui_v_show_registers_command_support ((tui_layout_def ())->float_regs_display_type);
+}
+
+
+static void
+tui_show_general_command (char *arg, int from_tty)
+{
+  tui_v_show_registers_command_support (TUI_GENERAL_REGS);
+}
+
+
+static void
+tui_show_special_command (char *arg, int from_tty)
+{
+  tui_v_show_registers_command_support (TUI_SPECIAL_REGS);
+}
+
+
+static void
+_tui_toggle_float_regs_command (char *arg, int from_tty)
+{
+  if (TUI_DATA_WIN != NULL && TUI_DATA_WIN->generic.is_visible)
+    tui_toggle_float_regs ();
+  else
+    {
+      struct tui_layout_def * layout_def = tui_layout_def ();
+
+      if (layout_def->float_regs_display_type == TUI_SFLOAT_REGS)
+       layout_def->float_regs_display_type = TUI_DFLOAT_REGS;
+      else
+       layout_def->float_regs_display_type = TUI_SFLOAT_REGS;
+    }
+}
+
+
+static void
+tui_scroll_regs_forward_command (char *arg, int from_tty)
+{
+  tui_scroll (FORWARD_SCROLL, TUI_DATA_WIN, 1);
+}
+
+
+static void
+tui_scroll_regs_backward_command (char *arg, int from_tty)
+{
+  tui_scroll (BACKWARD_SCROLL, TUI_DATA_WIN, 1);
+}
diff --git a/gdb/tui/tui-regs.h b/gdb/tui/tui-regs.h
new file mode 100644 (file)
index 0000000..c4de123
--- /dev/null
@@ -0,0 +1,41 @@
+/* TUI display registers in window.
+
+   Copyright 1998, 1999, 2000, 2001, 2004 Free Software Foundation,
+   Inc.
+
+   Contributed by Hewlett-Packard Company.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef TUI_REGS_H
+#define TUI_REGS_H
+
+#include "tui/tui-data.h"      /* For struct tui_register_display_type.  */
+
+extern void tui_check_register_values (struct frame_info *);
+extern void tui_show_registers (enum tui_register_display_type);
+extern void tui_display_registers_from (int);
+extern int tui_display_registers_from_line (int, int);
+extern int tui_last_regs_line_no (void);
+extern int tui_first_reg_element_inline (int);
+extern int tui_line_from_reg_element_no (int);
+extern void tui_toggle_float_regs (void);
+extern int tui_calculate_regs_column_count (enum tui_register_display_type);
+extern int tui_first_reg_element_no_inline (int lineno);
+
+#endif
diff --git a/gdb/tui/tui-source.c b/gdb/tui/tui-source.c
new file mode 100644 (file)
index 0000000..f97de2f
--- /dev/null
@@ -0,0 +1,357 @@
+/* TUI display source window.
+
+   Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
+   Foundation, Inc.
+
+   Contributed by Hewlett-Packard Company.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include "defs.h"
+#include <ctype.h>
+#include "symtab.h"
+#include "frame.h"
+#include "breakpoint.h"
+#include "source.h"
+#include "symtab.h"
+
+#include "tui/tui.h"
+#include "tui/tui-data.h"
+#include "tui/tui-stack.h"
+#include "tui/tui-winsource.h"
+#include "tui/tui-source.h"
+
+#ifdef HAVE_NCURSES_H       
+#include <ncurses.h>
+#else
+#ifdef HAVE_CURSES_H
+#include <curses.h>
+#endif
+#endif
+
+/* Function to display source in the source window.  */
+enum tui_status
+tui_set_source_content (struct symtab *s, int line_no, int noerror)
+{
+  enum tui_status ret = TUI_FAILURE;
+
+  if (s != (struct symtab *) NULL && s->filename != (char *) NULL)
+    {
+      FILE *stream;
+      int i, desc, c, line_width, nlines;
+      char *src_line = 0;
+
+      if ((ret = tui_alloc_source_buffer (TUI_SRC_WIN)) == TUI_SUCCESS)
+       {
+         line_width = TUI_SRC_WIN->generic.width - 1;
+         /* Take hilite (window border) into account, when calculating
+            the number of lines  */
+         nlines = (line_no + (TUI_SRC_WIN->generic.height - 2)) - line_no;
+         desc = open_source_file (s);
+         if (desc < 0)
+           {
+             if (!noerror)
+               {
+                 char *name = alloca (strlen (s->filename) + 100);
+                 sprintf (name, "%s:%d", s->filename, line_no);
+                 print_sys_errmsg (name, errno);
+               }
+             ret = TUI_FAILURE;
+           }
+         else
+           {
+             if (s->line_charpos == 0)
+               find_source_lines (s, desc);
+
+             if (line_no < 1 || line_no > s->nlines)
+               {
+                 close (desc);
+                 printf_unfiltered (
+                         "Line number %d out of range; %s has %d lines.\n",
+                                     line_no, s->filename, s->nlines);
+               }
+             else if (lseek (desc, s->line_charpos[line_no - 1], 0) < 0)
+               {
+                 close (desc);
+                 perror_with_name (s->filename);
+               }
+             else
+               {
+                 int offset, cur_line_no, cur_line, cur_len, threshold;
+                 struct tui_gen_win_info * locator = tui_locator_win_info_ptr ();
+                  struct tui_source_info * src = &TUI_SRC_WIN->detail.source_info;
+
+                  if (TUI_SRC_WIN->generic.title)
+                    xfree (TUI_SRC_WIN->generic.title);
+                  TUI_SRC_WIN->generic.title = xstrdup (s->filename);
+
+                  if (src->filename)
+                    xfree (src->filename);
+                  src->filename = xstrdup (s->filename);
+
+                 /* Determine the threshold for the length of the line
+                     and the offset to start the display.  */
+                 offset = src->horizontal_offset;
+                 threshold = (line_width - 1) + offset;
+                 stream = fdopen (desc, FOPEN_RT);
+                 clearerr (stream);
+                 cur_line = 0;
+                 cur_line_no = src->start_line_or_addr.line_no = line_no;
+                 if (offset > 0)
+                   src_line = (char *) xmalloc (
+                                          (threshold + 1) * sizeof (char));
+                 while (cur_line < nlines)
+                   {
+                     struct tui_win_element * element = (struct tui_win_element *)
+                     TUI_SRC_WIN->generic.content[cur_line];
+
+                     /* get the first character in the line */
+                     c = fgetc (stream);
+
+                     if (offset == 0)
+                       src_line = ((struct tui_win_element *)
+                                  TUI_SRC_WIN->generic.content[
+                                       cur_line])->which_element.source.line;
+                     /* Init the line with the line number */
+                     sprintf (src_line, "%-6d", cur_line_no);
+                     cur_len = strlen (src_line);
+                     i = cur_len -
+                       ((cur_len / tui_default_tab_len ()) * tui_default_tab_len ());
+                     while (i < tui_default_tab_len ())
+                       {
+                         src_line[cur_len] = ' ';
+                         i++;
+                         cur_len++;
+                       }
+                     src_line[cur_len] = (char) 0;
+
+                     /* Set whether element is the execution point and
+                        whether there is a break point on it.  */
+                     element->which_element.source.line_or_addr.line_no =
+                       cur_line_no;
+                     element->which_element.source.is_exec_point =
+                       (strcmp (((struct tui_win_element *)
+                       locator->content[0])->which_element.locator.file_name,
+                                s->filename) == 0
+                        && cur_line_no == ((struct tui_win_element *)
+                        locator->content[0])->which_element.locator.line_no);
+                     if (c != EOF)
+                       {
+                         i = strlen (src_line) - 1;
+                         do
+                           {
+                             if ((c != '\n') &&
+                                 (c != '\r') && (++i < threshold))
+                               {
+                                 if (c < 040 && c != '\t')
+                                   {
+                                     src_line[i++] = '^';
+                                     src_line[i] = c + 0100;
+                                   }
+                                 else if (c == 0177)
+                                   {
+                                     src_line[i++] = '^';
+                                     src_line[i] = '?';
+                                   }
+                                 else
+                                   {   /* Store the charcter in the line
+                                          buffer.  If it is a tab, then
+                                          translate to the correct number of
+                                          chars so we don't overwrite our
+                                          buffer.  */
+                                     if (c == '\t')
+                                       {
+                                         int j, max_tab_len = tui_default_tab_len ();
+
+                                         for (j = i - (
+                                              (i / max_tab_len) * max_tab_len);
+                                              ((j < max_tab_len) &&
+                                               i < threshold);
+                                              i++, j++)
+                                           src_line[i] = ' ';
+                                         i--;
+                                       }
+                                     else
+                                       src_line[i] = c;
+                                   }
+                                 src_line[i + 1] = 0;
+                               }
+                             else
+                               {       /* If we have not reached EOL, then eat
+                                           chars until we do  */
+                                 while (c != EOF && c != '\n' && c != '\r')
+                                   c = fgetc (stream);
+                               }
+                           }
+                         while (c != EOF && c != '\n' && c != '\r' &&
+                                i < threshold && (c = fgetc (stream)));
+                       }
+                     /* Now copy the line taking the offset into account */
+                     if (strlen (src_line) > offset)
+                       strcpy (((struct tui_win_element *) TUI_SRC_WIN->generic.content[
+                                       cur_line])->which_element.source.line,
+                               &src_line[offset]);
+                     else
+                       ((struct tui_win_element *)
+                        TUI_SRC_WIN->generic.content[
+                         cur_line])->which_element.source.line[0] = (char) 0;
+                     cur_line++;
+                     cur_line_no++;
+                   }
+                 if (offset > 0)
+                   xfree (src_line);
+                 fclose (stream);
+                 TUI_SRC_WIN->generic.content_size = nlines;
+                 ret = TUI_SUCCESS;
+               }
+           }
+       }
+    }
+  return ret;
+}
+
+
+/* elz: this function sets the contents of the source window to empty
+   except for a line in the middle with a warning message about the
+   source not being available. This function is called by
+   tui_erase_source_contents(), which in turn is invoked when the
+   source files cannot be accessed.  */
+
+void
+tui_set_source_content_nil (struct tui_win_info * win_info, char *warning_string)
+{
+  int line_width;
+  int n_lines;
+  int curr_line = 0;
+
+  line_width = win_info->generic.width - 1;
+  n_lines = win_info->generic.height - 2;
+
+  /* set to empty each line in the window, except for the one
+     which contains the message */
+  while (curr_line < win_info->generic.content_size)
+    {
+      /* set the information related to each displayed line
+         to null: i.e. the line number is 0, there is no bp,
+         it is not where the program is stopped */
+
+      struct tui_win_element * element =
+      (struct tui_win_element *) win_info->generic.content[curr_line];
+      element->which_element.source.line_or_addr.line_no = 0;
+      element->which_element.source.is_exec_point = FALSE;
+      element->which_element.source.has_break = FALSE;
+
+      /* set the contents of the line to blank */
+      element->which_element.source.line[0] = (char) 0;
+
+      /* if the current line is in the middle of the screen, then we
+         want to display the 'no source available' message in it.
+         Note: the 'weird' arithmetic with the line width and height
+         comes from the function tui_erase_source_content(). We need
+         to keep the screen and the window's actual contents in synch.  */
+
+      if (curr_line == (n_lines / 2 + 1))
+       {
+         int i;
+         int xpos;
+         int warning_length = strlen (warning_string);
+         char *src_line;
+
+         src_line = element->which_element.source.line;
+
+         if (warning_length >= ((line_width - 1) / 2))
+           xpos = 1;
+         else
+           xpos = (line_width - 1) / 2 - warning_length;
+
+         for (i = 0; i < xpos; i++)
+           src_line[i] = ' ';
+
+         sprintf (src_line + i, "%s", warning_string);
+
+         for (i = xpos + warning_length; i < line_width; i++)
+           src_line[i] = ' ';
+
+         src_line[i] = '\n';
+
+       }                       /* end if */
+
+      curr_line++;
+
+    }                          /* end while */
+}
+
+
+/* Function to display source in the source window.  This function
+   initializes the horizontal scroll to 0.  */
+void
+tui_show_symtab_source (struct symtab *s, union tui_line_or_address line, int noerror)
+{
+  TUI_SRC_WIN->detail.source_info.horizontal_offset = 0;
+  tui_update_source_window_as_is (TUI_SRC_WIN, s, line, noerror);
+}
+
+
+/* Answer whether the source is currently displayed in the source
+   window.  */
+int
+tui_source_is_displayed (char *fname)
+{
+  return (TUI_SRC_WIN->generic.content_in_use &&
+         (strcmp (((struct tui_win_element *) (tui_locator_win_info_ptr ())->
+                 content[0])->which_element.locator.file_name, fname) == 0));
+}
+
+
+/* Scroll the source forward or backward vertically.  */
+void
+tui_vertical_source_scroll (enum tui_scroll_direction scroll_direction,
+                           int num_to_scroll)
+{
+  if (TUI_SRC_WIN->generic.content != NULL)
+    {
+      union tui_line_or_address l;
+      struct symtab *s;
+      tui_win_content content = (tui_win_content) TUI_SRC_WIN->generic.content;
+      struct symtab_and_line cursal = get_current_source_symtab_and_line ();
+
+      if (cursal.symtab == (struct symtab *) NULL)
+       s = find_pc_symtab (get_frame_pc (deprecated_selected_frame));
+      else
+       s = cursal.symtab;
+
+      if (scroll_direction == FORWARD_SCROLL)
+       {
+         l.line_no = content[0]->which_element.source.line_or_addr.line_no +
+           num_to_scroll;
+         if (l.line_no > s->nlines)
+           /*line = s->nlines - win_info->generic.content_size + 1; */
+           /*elz: fix for dts 23398 */
+           l.line_no = content[0]->which_element.source.line_or_addr.line_no;
+       }
+      else
+       {
+         l.line_no = content[0]->which_element.source.line_or_addr.line_no -
+           num_to_scroll;
+         if (l.line_no <= 0)
+           l.line_no = 1;
+       }
+
+      print_source_lines (s, l.line_no, l.line_no + 1, 0);
+    }
+}
diff --git a/gdb/tui/tui-source.h b/gdb/tui/tui-source.h
new file mode 100644 (file)
index 0000000..3b61ca4
--- /dev/null
@@ -0,0 +1,40 @@
+/* TUI display source window.
+
+   Copyright 1998, 1999, 2000, 2001, 2002, 2004 Free Software
+   Foundation, Inc.
+
+   Contributed by Hewlett-Packard Company.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef TUI_SOURCE_H
+#define TUI_SOURCE_H
+
+#include "tui/tui-data.h"
+
+struct symtab;
+struct tui_win_info;
+
+extern void tui_set_source_content_nil (struct tui_win_info *, char *);
+
+extern enum tui_status tui_set_source_content (struct symtab *, int, int);
+extern void tui_show_symtab_source (struct symtab *, union tui_line_or_address, int);
+extern int tui_source_is_displayed (char *);
+extern void tui_vertical_source_scroll (enum tui_scroll_direction, int);
+
+#endif
diff --git a/gdb/tui/tui-stack.c b/gdb/tui/tui-stack.c
new file mode 100644 (file)
index 0000000..7285dab
--- /dev/null
@@ -0,0 +1,433 @@
+/* TUI display locator.
+
+   Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
+   Foundation, Inc.
+
+   Contributed by Hewlett-Packard Company.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include "defs.h"
+#include "symtab.h"
+#include "breakpoint.h"
+#include "frame.h"
+#include "command.h"
+#include "inferior.h"
+#include "target.h"
+#include "top.h"
+#include "gdb_string.h"
+#include "tui/tui.h"
+#include "tui/tui-data.h"
+#include "tui/tui-stack.h"
+#include "tui/tui-wingeneral.h"
+#include "tui/tui-source.h"
+#include "tui/tui-winsource.h"
+#include "tui/tui-file.h"
+
+#ifdef HAVE_NCURSES_H       
+#include <ncurses.h>
+#else
+#ifdef HAVE_CURSES_H
+#include <curses.h>
+#endif
+#endif
+
+/* Get a printable name for the function at the address.
+   The symbol name is demangled if demangling is turned on.
+   Returns a pointer to a static area holding the result.  */
+static char* tui_get_function_from_frame (struct frame_info *fi);
+
+/* Set the filename portion of the locator.  */
+static void tui_set_locator_filename (const char *filename);
+
+/* Update the locator, with the provided arguments.  */
+static void tui_set_locator_info (const char *filename, const char *procname,
+                                  int lineno, CORE_ADDR addr);
+
+static void tui_update_command (char *, int);
+\f
+
+/* Create the status line to display as much information as we
+   can on this single line: target name, process number, current
+   function, current line, current PC, SingleKey mode.  */
+static char*
+tui_make_status_line (struct tui_locator_element* loc)
+{
+  char* string;
+  char line_buf[50], *pname;
+  char* buf;
+  int status_size;
+  int i, proc_width;
+  const char* pid_name;
+  const char* pc_buf;
+  int target_width;
+  int pid_width;
+  int line_width;
+  int pc_width;
+  struct ui_file *pc_out;
+
+  if (ptid_equal (inferior_ptid, null_ptid))
+    pid_name = "No process";
+  else
+    pid_name = target_pid_to_str (inferior_ptid);
+
+  target_width = strlen (target_shortname);
+  if (target_width > MAX_TARGET_WIDTH)
+    target_width = MAX_TARGET_WIDTH;
+
+  pid_width = strlen (pid_name);
+  if (pid_width > MAX_PID_WIDTH)
+    pid_width = MAX_PID_WIDTH;
+
+  status_size = tui_term_width ();
+  string = (char *) xmalloc (status_size + 1);
+  buf = (char*) alloca (status_size + 1);
+
+  /* Translate line number and obtain its size.  */
+  if (loc->line_no > 0)
+    sprintf (line_buf, "%d", loc->line_no);
+  else
+    strcpy (line_buf, "??");
+  line_width = strlen (line_buf);
+  if (line_width < MIN_LINE_WIDTH)
+    line_width = MIN_LINE_WIDTH;
+
+  /* Translate PC address.  */
+  pc_out = tui_sfileopen (128);
+  print_address_numeric (loc->addr, 1, pc_out);
+  pc_buf = tui_file_get_strbuf (pc_out);
+  pc_width = strlen (pc_buf);
+  
+  /* First determine the amount of proc name width we have available.
+     The +1 are for a space separator between fields.
+     The -1 are to take into account the \0 counted by sizeof.  */
+  proc_width = (status_size
+                - (target_width + 1)
+                - (pid_width + 1)
+                - (sizeof (PROC_PREFIX) - 1 + 1)
+                - (sizeof (LINE_PREFIX) - 1 + line_width + 1)
+                - (sizeof (PC_PREFIX) - 1 + pc_width + 1)
+                - (tui_current_key_mode == TUI_SINGLE_KEY_MODE
+                   ? (sizeof (SINGLE_KEY) - 1 + 1)
+                   : 0));
+
+  /* If there is no room to print the function name, try by removing
+     some fields.  */
+  if (proc_width < MIN_PROC_WIDTH)
+    {
+      proc_width += target_width + 1;
+      target_width = 0;
+      if (proc_width < MIN_PROC_WIDTH)
+        {
+          proc_width += pid_width + 1;
+          pid_width = 0;
+          if (proc_width <= MIN_PROC_WIDTH)
+            {
+              proc_width += pc_width + sizeof (PC_PREFIX) - 1 + 1;
+              pc_width = 0;
+              if (proc_width < 0)
+                {
+                  proc_width += line_width + sizeof (LINE_PREFIX) - 1 + 1;
+                  line_width = 0;
+                  if (proc_width < 0)
+                    proc_width = 0;
+                }
+            }
+        }
+    }
+
+  /* Now convert elements to string form */
+  pname = loc->proc_name;
+
+  /* Now create the locator line from the string version
+     of the elements.  We could use sprintf() here but
+     that wouldn't ensure that we don't overrun the size
+     of the allocated buffer.  strcat_to_buf() will.  */
+  *string = (char) 0;
+
+  if (target_width > 0)
+    {
+      sprintf (buf, "%*.*s ",
+               -target_width, target_width, target_shortname);
+      strcat_to_buf (string, status_size, buf);
+    }
+  if (pid_width > 0)
+    {
+      sprintf (buf, "%*.*s ",
+               -pid_width, pid_width, pid_name);
+      strcat_to_buf (string, status_size, buf);
+    }
+  
+  /* Show whether we are in SingleKey mode.  */
+  if (tui_current_key_mode == TUI_SINGLE_KEY_MODE)
+    {
+      strcat_to_buf (string, status_size, SINGLE_KEY);
+      strcat_to_buf (string, status_size, " ");
+    }
+
+  /* procedure/class name */
+  if (proc_width > 0)
+    {
+      if (strlen (pname) > proc_width)
+        sprintf (buf, "%s%*.*s* ", PROC_PREFIX,
+                 1 - proc_width, proc_width - 1, pname);
+      else
+        sprintf (buf, "%s%*.*s ", PROC_PREFIX,
+                 -proc_width, proc_width, pname);
+      strcat_to_buf (string, status_size, buf);
+    }
+
+  if (line_width > 0)
+    {
+      sprintf (buf, "%s%*.*s ", LINE_PREFIX,
+               -line_width, line_width, line_buf);
+      strcat_to_buf (string, status_size, buf);
+    }
+  if (pc_width > 0)
+    {
+      strcat_to_buf (string, status_size, PC_PREFIX);
+      strcat_to_buf (string, status_size, pc_buf);
+    }
+  
+  
+  for (i = strlen (string); i < status_size; i++)
+    string[i] = ' ';
+  string[status_size] = (char) 0;
+
+  ui_file_delete (pc_out);
+  return string;
+}
+
+/* Get a printable name for the function at the address.
+   The symbol name is demangled if demangling is turned on.
+   Returns a pointer to a static area holding the result.  */
+static char*
+tui_get_function_from_frame (struct frame_info *fi)
+{
+  static char name[256];
+  struct ui_file *stream = tui_sfileopen (256);
+  char *p;
+
+  print_address_symbolic (get_frame_pc (fi), stream, demangle, "");
+  p = tui_file_get_strbuf (stream);
+
+  /* Use simple heuristics to isolate the function name.  The symbol can
+     be demangled and we can have function parameters.  Remove them because
+     the status line is too short to display them.  */
+  if (*p == '<')
+    p++;
+  strncpy (name, p, sizeof (name));
+  p = strchr (name, '(');
+  if (!p)
+    p = strchr (name, '>');
+  if (p)
+    *p = 0;
+  p = strchr (name, '+');
+  if (p)
+    *p = 0;
+  ui_file_delete (stream);
+  return name;
+}
+
+void
+tui_show_locator_content (void)
+{
+  char *string;
+  struct tui_gen_win_info * locator;
+
+  locator = tui_locator_win_info_ptr ();
+
+  if (locator != NULL && locator->handle != (WINDOW *) NULL)
+    {
+      struct tui_win_element * element;
+
+      element = (struct tui_win_element *) locator->content[0];
+
+      string = tui_make_status_line (&element->which_element.locator);
+      wmove (locator->handle, 0, 0);
+      wstandout (locator->handle);
+      waddstr (locator->handle, string);
+      wclrtoeol (locator->handle);
+      wstandend (locator->handle);
+      tui_refresh_win (locator);
+      wmove (locator->handle, 0, 0);
+      xfree (string);
+      locator->content_in_use = TRUE;
+    }
+}
+
+
+/* Set the filename portion of the locator.  */
+static void
+tui_set_locator_filename (const char *filename)
+{
+  struct tui_gen_win_info * locator = tui_locator_win_info_ptr ();
+  struct tui_locator_element * element;
+
+  if (locator->content[0] == NULL)
+    {
+      tui_set_locator_info (filename, NULL, 0, 0);
+      return;
+    }
+
+  element = &((struct tui_win_element *) locator->content[0])->which_element.locator;
+  element->file_name[0] = 0;
+  strcat_to_buf (element->file_name, MAX_LOCATOR_ELEMENT_LEN, filename);
+}
+
+/* Update the locator, with the provided arguments.  */
+static void
+tui_set_locator_info (const char *filename, const char *procname, int lineno,
+                      CORE_ADDR addr)
+{
+  struct tui_gen_win_info * locator = tui_locator_win_info_ptr ();
+  struct tui_locator_element * element;
+
+  /* Allocate the locator content if necessary.  */
+  if (locator->content_size <= 0)
+    {
+      locator->content = (void **) tui_alloc_content (1, locator->type);
+      locator->content_size = 1;
+    }
+
+  element = &((struct tui_win_element *) locator->content[0])->which_element.locator;
+  element->proc_name[0] = (char) 0;
+  strcat_to_buf (element->proc_name, MAX_LOCATOR_ELEMENT_LEN, procname);
+  element->line_no = lineno;
+  element->addr = addr;
+  tui_set_locator_filename (filename);
+}
+
+/* Update only the filename portion of the locator.  */
+void
+tui_update_locator_filename (const char *filename)
+{
+  tui_set_locator_filename (filename);
+  tui_show_locator_content ();
+}
+
+/* Function to print the frame information for the TUI.  */
+void
+tui_show_frame_info (struct frame_info *fi)
+{
+  struct tui_win_info * win_info;
+  int i;
+
+  if (fi)
+    {
+      int start_line, i;
+      CORE_ADDR low;
+      struct tui_gen_win_info * locator = tui_locator_win_info_ptr ();
+      int source_already_displayed;
+      struct symtab_and_line sal;
+
+      find_frame_sal (fi, &sal);
+
+      source_already_displayed = sal.symtab != 0
+        && tui_source_is_displayed (sal.symtab->filename);
+      tui_set_locator_info (sal.symtab == 0 ? "??" : sal.symtab->filename,
+                            tui_get_function_from_frame (fi),
+                            sal.line,
+                            get_frame_pc (fi));
+      tui_show_locator_content ();
+      start_line = 0;
+      for (i = 0; i < (tui_source_windows ())->count; i++)
+       {
+         union tui_which_element *item;
+         win_info = (struct tui_win_info *) (tui_source_windows ())->list[i];
+
+         item = &((struct tui_win_element *) locator->content[0])->which_element;
+         if (win_info == TUI_SRC_WIN)
+           {
+             start_line = (item->locator.line_no -
+                          (win_info->generic.viewport_height / 2)) + 1;
+             if (start_line <= 0)
+               start_line = 1;
+           }
+         else
+           {
+             if (find_pc_partial_function (get_frame_pc (fi), (char **) NULL,
+                                           &low, (CORE_ADDR) NULL) == 0)
+               error ("No function contains program counter for selected frame.\n");
+             else
+               low = tui_get_low_disassembly_address (low, get_frame_pc (fi));
+           }
+
+         if (win_info == TUI_SRC_WIN)
+           {
+             union tui_line_or_address l;
+             l.line_no = start_line;
+             if (!(source_already_displayed
+                   && tui_line_is_displayed (item->locator.line_no, win_info, TRUE)))
+               tui_update_source_window (win_info, sal.symtab, l, TRUE);
+             else
+               {
+                 l.line_no = item->locator.line_no;
+                 tui_set_is_exec_point_at (l, win_info);
+               }
+           }
+         else
+           {
+             if (win_info == TUI_DISASM_WIN)
+               {
+                 union tui_line_or_address a;
+                 a.addr = low;
+                 if (!tui_addr_is_displayed (item->locator.addr, win_info, TRUE))
+                   tui_update_source_window (win_info, sal.symtab, a, TRUE);
+                 else
+                   {
+                     a.addr = item->locator.addr;
+                     tui_set_is_exec_point_at (a, win_info);
+                   }
+               }
+           }
+         tui_update_exec_info (win_info);
+       }
+    }
+  else
+    {
+      tui_set_locator_info (NULL, NULL, 0, (CORE_ADDR) 0);
+      tui_show_locator_content ();
+      for (i = 0; i < (tui_source_windows ())->count; i++)
+       {
+         win_info = (struct tui_win_info *) (tui_source_windows ())->list[i];
+         tui_clear_source_content (win_info, EMPTY_SOURCE_PROMPT);
+         tui_update_exec_info (win_info);
+       }
+    }
+}
+
+/* Function to initialize gdb commands, for tui window stack
+   manipulation.  */
+void
+_initialize_tui_stack (void)
+{
+  add_com ("update", class_tui, tui_update_command,
+           "Update the source window and locator to display the current "
+           "execution point.\n");
+}
+
+/* Command to update the display with the current execution point.  */
+static void
+tui_update_command (char *arg, int from_tty)
+{
+  char cmd[sizeof("frame 0")];
+
+  strcpy (cmd, "frame 0");
+  execute_command (cmd, from_tty);
+}
diff --git a/gdb/tui/tui-stack.h b/gdb/tui/tui-stack.h
new file mode 100644 (file)
index 0000000..65725b3
--- /dev/null
@@ -0,0 +1,34 @@
+/* TUI display locator.
+
+   Copyright 1998, 1999, 2000, 2001, 2002, 2004 Free Software
+   Foundation, Inc.
+
+   Contributed by Hewlett-Packard Company.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef TUI_STACK_H
+#define TUI_STACK_H
+
+struct frame_info;
+
+extern void tui_update_locator_filename (const char *);
+extern void tui_show_locator_content (void);
+extern void tui_show_frame_info (struct frame_info *);
+
+#endif
diff --git a/gdb/tui/tui-win.c b/gdb/tui/tui-win.c
new file mode 100644 (file)
index 0000000..3950a7c
--- /dev/null
@@ -0,0 +1,1511 @@
+/* TUI window generic functions.
+
+   Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
+   Foundation, Inc.
+
+   Contributed by Hewlett-Packard Company.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* This module contains procedures for handling tui window functions
+   like resize, scrolling, scrolling, changing focus, etc.
+
+   Author: Susan B. Macchia  */
+
+#include "defs.h"
+#include "command.h"
+#include "symtab.h"
+#include "breakpoint.h"
+#include "frame.h"
+#include "cli/cli-cmds.h"
+#include "top.h"
+#include "source.h"
+
+#include "tui/tui.h"
+#include "tui/tui-data.h"
+#include "tui/tui-wingeneral.h"
+#include "tui/tui-stack.h"
+#include "tui/tui-regs.h"
+#include "tui/tui-disasm.h"
+#include "tui/tui-source.h"
+#include "tui/tui-winsource.h"
+#include "tui/tui-windata.h"
+
+#ifdef HAVE_NCURSES_H       
+#include <ncurses.h>
+#else
+#ifdef HAVE_CURSES_H
+#include <curses.h>
+#endif
+#endif
+
+#include "gdb_string.h"
+#include <ctype.h>
+#include <readline/readline.h>
+
+/*******************************
+** Static Local Decls
+********************************/
+static void make_visible_with_new_height (struct tui_win_info *);
+static void make_invisible_and_set_new_height (struct tui_win_info *, int);
+static enum tui_status tui_adjust_win_heights (struct tui_win_info *, int);
+static int new_height_ok (struct tui_win_info *, int);
+static void tui_set_tab_width_command (char *, int);
+static void tui_refresh_all_command (char *, int);
+static void tui_set_win_height_command (char *, int);
+static void tui_xdb_set_win_height_command (char *, int);
+static void tui_all_windows_info (char *, int);
+static void tui_set_focus_command (char *, int);
+static void tui_scroll_forward_command (char *, int);
+static void tui_scroll_backward_command (char *, int);
+static void tui_scroll_left_command (char *, int);
+static void tui_scroll_right_command (char *, int);
+static void parse_scrolling_args (char *, struct tui_win_info * *, int *);
+
+
+/***************************************
+** DEFINITIONS
+***************************************/
+#define WIN_HEIGHT_USAGE      "Usage: winheight <win_name> [+ | -] <#lines>\n"
+#define XDBWIN_HEIGHT_USAGE   "Usage: w <#lines>\n"
+#define FOCUS_USAGE           "Usage: focus {<win> | next | prev}\n"
+
+/***************************************
+** PUBLIC FUNCTIONS
+***************************************/
+
+#ifndef ACS_LRCORNER
+#  define ACS_LRCORNER '+'
+#endif
+#ifndef ACS_LLCORNER
+#  define ACS_LLCORNER '+'
+#endif
+#ifndef ACS_ULCORNER
+#  define ACS_ULCORNER '+'
+#endif
+#ifndef ACS_URCORNER
+#  define ACS_URCORNER '+'
+#endif
+#ifndef ACS_HLINE
+#  define ACS_HLINE '-'
+#endif
+#ifndef ACS_VLINE
+#  define ACS_VLINE '|'
+#endif
+
+/* Possible values for tui-border-kind variable.  */
+static const char *tui_border_kind_enums[] = {
+  "space",
+  "ascii",
+  "acs",
+  NULL
+};
+
+/* Possible values for tui-border-mode and tui-active-border-mode.  */
+static const char *tui_border_mode_enums[] = {
+  "normal",
+  "standout",
+  "reverse",
+  "half",
+  "half-standout",
+  "bold",
+  "bold-standout",
+  NULL
+};
+
+struct tui_translate
+{
+  const char *name;
+  int value;
+};
+
+/* Translation table for border-mode variables.
+   The list of values must be terminated by a NULL.
+   After the NULL value, an entry defines the default.  */
+struct tui_translate tui_border_mode_translate[] = {
+  { "normal",          A_NORMAL },
+  { "standout",                A_STANDOUT },
+  { "reverse",         A_REVERSE },
+  { "half",            A_DIM },
+  { "half-standout",   A_DIM | A_STANDOUT },
+  { "bold",            A_BOLD },
+  { "bold-standout",   A_BOLD | A_STANDOUT },
+  { 0, 0 },
+  { "normal",          A_NORMAL }
+};
+
+/* Translation tables for border-kind, one for each border
+   character (see wborder, border curses operations).
+   -1 is used to indicate the ACS because ACS characters
+   are determined at run time by curses (depends on terminal).  */
+struct tui_translate tui_border_kind_translate_vline[] = {
+  { "space",    ' ' },
+  { "ascii",    '|' },
+  { "acs",      -1 },
+  { 0, 0 },
+  { "ascii",    '|' }
+};
+
+struct tui_translate tui_border_kind_translate_hline[] = {
+  { "space",    ' ' },
+  { "ascii",    '-' },
+  { "acs",      -1 },
+  { 0, 0 },
+  { "ascii",    '-' }
+};
+
+struct tui_translate tui_border_kind_translate_ulcorner[] = {
+  { "space",    ' ' },
+  { "ascii",    '+' },
+  { "acs",      -1 },
+  { 0, 0 },
+  { "ascii",    '+' }
+};
+
+struct tui_translate tui_border_kind_translate_urcorner[] = {
+  { "space",    ' ' },
+  { "ascii",    '+' },
+  { "acs",      -1 },
+  { 0, 0 },
+  { "ascii",    '+' }
+};
+
+struct tui_translate tui_border_kind_translate_llcorner[] = {
+  { "space",    ' ' },
+  { "ascii",    '+' },
+  { "acs",      -1 },
+  { 0, 0 },
+  { "ascii",    '+' }
+};
+
+struct tui_translate tui_border_kind_translate_lrcorner[] = {
+  { "space",    ' ' },
+  { "ascii",    '+' },
+  { "acs",      -1 },
+  { 0, 0 },
+  { "ascii",    '+' }
+};
+
+
+/* Tui configuration variables controlled with set/show command.  */
+const char *tui_active_border_mode = "bold-standout";
+const char *tui_border_mode = "normal";
+const char *tui_border_kind = "acs";
+
+/* Tui internal configuration variables.  These variables are
+   updated by tui_update_variables to reflect the tui configuration
+   variables.  */
+chtype tui_border_vline;
+chtype tui_border_hline;
+chtype tui_border_ulcorner;
+chtype tui_border_urcorner;
+chtype tui_border_llcorner;
+chtype tui_border_lrcorner;
+
+int tui_border_attrs;
+int tui_active_border_attrs;
+
+/* Identify the item in the translation table.
+   When the item is not recognized, use the default entry.  */
+static struct tui_translate *
+translate (const char *name, struct tui_translate *table)
+{
+  while (table->name)
+    {
+      if (name && strcmp (table->name, name) == 0)
+        return table;
+      table++;
+    }
+
+  /* Not found, return default entry.  */
+  table++;
+  return table;
+}
+
+/* Update the tui internal configuration according to gdb settings.
+   Returns 1 if the configuration has changed and the screen should
+   be redrawn.  */
+int
+tui_update_variables (void)
+{
+  int need_redraw = 0;
+  struct tui_translate *entry;
+
+  entry = translate (tui_border_mode, tui_border_mode_translate);
+  if (tui_border_attrs != entry->value)
+    {
+      tui_border_attrs = entry->value;
+      need_redraw = 1;
+    }
+  entry = translate (tui_active_border_mode, tui_border_mode_translate);
+  if (tui_active_border_attrs != entry->value)
+    {
+      tui_active_border_attrs = entry->value;
+      need_redraw = 1;
+    }
+
+  /* If one corner changes, all characters are changed.
+     Only check the first one.  The ACS characters are determined at
+     run time by curses terminal management.  */
+  entry = translate (tui_border_kind, tui_border_kind_translate_lrcorner);
+  if (tui_border_lrcorner != (chtype) entry->value)
+    {
+      tui_border_lrcorner = (entry->value < 0) ? ACS_LRCORNER : entry->value;
+      need_redraw = 1;
+    }
+  entry = translate (tui_border_kind, tui_border_kind_translate_llcorner);
+  tui_border_llcorner = (entry->value < 0) ? ACS_LLCORNER : entry->value;
+
+  entry = translate (tui_border_kind, tui_border_kind_translate_ulcorner);
+  tui_border_ulcorner = (entry->value < 0) ? ACS_ULCORNER : entry->value;
+
+  entry = translate (tui_border_kind, tui_border_kind_translate_urcorner);
+  tui_border_urcorner = (entry->value < 0) ? ACS_URCORNER : entry->value;
+
+  entry = translate (tui_border_kind, tui_border_kind_translate_hline);
+  tui_border_hline = (entry->value < 0) ? ACS_HLINE : entry->value;
+
+  entry = translate (tui_border_kind, tui_border_kind_translate_vline);
+  tui_border_vline = (entry->value < 0) ? ACS_VLINE : entry->value;
+
+  return need_redraw;
+}
+
+static void
+set_tui_cmd (char *args, int from_tty)
+{
+}
+
+static void
+show_tui_cmd (char *args, int from_tty)
+{
+}
+
+/* Function to initialize gdb commands, for tui window manipulation.  */
+void
+_initialize_tui_win (void)
+{
+  struct cmd_list_element *c;
+  static struct cmd_list_element *tui_setlist;
+  static struct cmd_list_element *tui_showlist;
+
+  /* Define the classes of commands.
+     They will appear in the help list in the reverse of this order.  */
+  add_cmd ("tui", class_tui, NULL,
+          "Text User Interface commands.",
+          &cmdlist);
+
+  add_prefix_cmd ("tui", class_tui, set_tui_cmd,
+                  "TUI configuration variables",
+                 &tui_setlist, "set tui ",
+                 0/*allow-unknown*/, &setlist);
+  add_prefix_cmd ("tui", class_tui, show_tui_cmd,
+                  "TUI configuration variables",
+                 &tui_showlist, "show tui ",
+                 0/*allow-unknown*/, &showlist);
+
+  add_com ("refresh", class_tui, tui_refresh_all_command,
+           "Refresh the terminal display.\n");
+  if (xdb_commands)
+    add_com_alias ("U", "refresh", class_tui, 0);
+  add_com ("tabset", class_tui, tui_set_tab_width_command,
+           "Set the width (in characters) of tab stops.\n\
+Usage: tabset <n>\n");
+  add_com ("winheight", class_tui, tui_set_win_height_command,
+           "Set the height of a specified window.\n\
+Usage: winheight <win_name> [+ | -] <#lines>\n\
+Window names are:\n\
+src  : the source window\n\
+cmd  : the command window\n\
+asm  : the disassembly window\n\
+regs : the register display\n");
+  add_com_alias ("wh", "winheight", class_tui, 0);
+  add_info ("win", tui_all_windows_info,
+            "List of all displayed windows.\n");
+  add_com ("focus", class_tui, tui_set_focus_command,
+           "Set focus to named window or next/prev window.\n\
+Usage: focus {<win> | next | prev}\n\
+Valid Window names are:\n\
+src  : the source window\n\
+asm  : the disassembly window\n\
+regs : the register display\n\
+cmd  : the command window\n");
+  add_com_alias ("fs", "focus", class_tui, 0);
+  add_com ("+", class_tui, tui_scroll_forward_command,
+           "Scroll window forward.\nUsage: + [win] [n]\n");
+  add_com ("-", class_tui, tui_scroll_backward_command,
+           "Scroll window backward.\nUsage: - [win] [n]\n");
+  add_com ("<", class_tui, tui_scroll_left_command,
+           "Scroll window forward.\nUsage: < [win] [n]\n");
+  add_com (">", class_tui, tui_scroll_right_command,
+           "Scroll window backward.\nUsage: > [win] [n]\n");
+  if (xdb_commands)
+    add_com ("w", class_xdb, tui_xdb_set_win_height_command,
+             "XDB compatibility command for setting the height of a command window.\n\
+Usage: w <#lines>\n");
+
+  /* Define the tui control variables.  */
+  c = add_set_enum_cmd
+    ("border-kind", no_class,
+     tui_border_kind_enums, &tui_border_kind,
+     "Set the kind of border for TUI windows.\n"
+     "This variable controls the border of TUI windows:\n"
+     "space           use a white space\n"
+     "ascii           use ascii characters + - | for the border\n"
+     "acs             use the Alternate Character Set\n",
+     &tui_setlist);
+  add_show_from_set (c, &tui_showlist);
+
+  c = add_set_enum_cmd
+    ("border-mode", no_class,
+     tui_border_mode_enums, &tui_border_mode,
+     "Set the attribute mode to use for the TUI window borders.\n"
+     "This variable controls the attributes to use for the window borders:\n"
+     "normal          normal display\n"
+     "standout        use highlight mode of terminal\n"
+     "reverse         use reverse video mode\n"
+     "half            use half bright\n"
+     "half-standout   use half bright and standout mode\n"
+     "bold            use extra bright or bold\n"
+     "bold-standout   use extra bright or bold with standout mode\n",
+     &tui_setlist);
+  add_show_from_set (c, &tui_showlist);
+
+  c = add_set_enum_cmd
+    ("active-border-mode", no_class,
+     tui_border_mode_enums, &tui_active_border_mode,
+     "Set the attribute mode to use for the active TUI window border.\n"
+     "This variable controls the attributes to use for the active window border:\n"
+     "normal          normal display\n"
+     "standout        use highlight mode of terminal\n"
+     "reverse         use reverse video mode\n"
+     "half            use half bright\n"
+     "half-standout   use half bright and standout mode\n"
+     "bold            use extra bright or bold\n"
+     "bold-standout   use extra bright or bold with standout mode\n",
+     &tui_setlist);
+  add_show_from_set (c, &tui_showlist);
+}
+
+/* Update gdb's knowledge of the terminal size.  */
+void
+tui_update_gdb_sizes (void)
+{
+  char cmd[50];
+  int screenheight, screenwidth;
+
+  rl_get_screen_size (&screenheight, &screenwidth);
+  /* Set to TUI command window dimension or use readline values.  */
+  sprintf (cmd, "set width %d",
+           tui_active ? TUI_CMD_WIN->generic.width : screenwidth);
+  execute_command (cmd, 0);
+  sprintf (cmd, "set height %d",
+           tui_active ? TUI_CMD_WIN->generic.height : screenheight);
+  execute_command (cmd, 0);
+}
+
+
+/* Set the logical focus to win_info.    */
+void
+tui_set_win_focus_to (struct tui_win_info * win_info)
+{
+  if (win_info != NULL)
+    {
+      struct tui_win_info * win_with_focus = tui_win_with_focus ();
+
+      if (win_with_focus != NULL
+         && win_with_focus->generic.type != CMD_WIN)
+       tui_unhighlight_win (win_with_focus);
+      tui_set_win_with_focus (win_info);
+      if (win_info->generic.type != CMD_WIN)
+       tui_highlight_win (win_info);
+    }
+}
+
+
+void
+tui_scroll_forward (struct tui_win_info * win_to_scroll, int num_to_scroll)
+{
+  if (win_to_scroll != TUI_CMD_WIN)
+    {
+      int _num_to_scroll = num_to_scroll;
+
+      if (num_to_scroll == 0)
+       _num_to_scroll = win_to_scroll->generic.height - 3;
+      /*
+         ** If we are scrolling the source or disassembly window, do a
+         ** "psuedo" scroll since not all of the source is in memory,
+         ** only what is in the viewport.  If win_to_scroll is the
+         ** command window do nothing since the term should handle it.
+       */
+      if (win_to_scroll == TUI_SRC_WIN)
+       tui_vertical_source_scroll (FORWARD_SCROLL, _num_to_scroll);
+      else if (win_to_scroll == TUI_DISASM_WIN)
+       tui_vertical_disassem_scroll (FORWARD_SCROLL, _num_to_scroll);
+      else if (win_to_scroll == TUI_DATA_WIN)
+       tui_vertical_data_scroll (FORWARD_SCROLL, _num_to_scroll);
+    }
+}
+
+void
+tui_scroll_backward (struct tui_win_info * win_to_scroll, int num_to_scroll)
+{
+  if (win_to_scroll != TUI_CMD_WIN)
+    {
+      int _num_to_scroll = num_to_scroll;
+
+      if (num_to_scroll == 0)
+       _num_to_scroll = win_to_scroll->generic.height - 3;
+      /*
+         ** If we are scrolling the source or disassembly window, do a
+         ** "psuedo" scroll since not all of the source is in memory,
+         ** only what is in the viewport.  If win_to_scroll is the
+         ** command window do nothing since the term should handle it.
+       */
+      if (win_to_scroll == TUI_SRC_WIN)
+       tui_vertical_source_scroll (BACKWARD_SCROLL, _num_to_scroll);
+      else if (win_to_scroll == TUI_DISASM_WIN)
+       tui_vertical_disassem_scroll (BACKWARD_SCROLL, _num_to_scroll);
+      else if (win_to_scroll == TUI_DATA_WIN)
+       tui_vertical_data_scroll (BACKWARD_SCROLL, _num_to_scroll);
+    }
+}
+
+
+void
+tui_scroll_left (struct tui_win_info * win_to_scroll, int num_to_scroll)
+{
+  if (win_to_scroll != TUI_CMD_WIN)
+    {
+      int _num_to_scroll = num_to_scroll;
+
+      if (_num_to_scroll == 0)
+       _num_to_scroll = 1;
+      /*
+         ** If we are scrolling the source or disassembly window, do a
+         ** "psuedo" scroll since not all of the source is in memory,
+         ** only what is in the viewport. If win_to_scroll is the
+         ** command window do nothing since the term should handle it.
+       */
+      if (win_to_scroll == TUI_SRC_WIN || win_to_scroll == TUI_DISASM_WIN)
+       tui_horizontal_source_scroll (win_to_scroll, LEFT_SCROLL, _num_to_scroll);
+    }
+}
+
+
+void
+tui_scroll_right (struct tui_win_info * win_to_scroll, int num_to_scroll)
+{
+  if (win_to_scroll != TUI_CMD_WIN)
+    {
+      int _num_to_scroll = num_to_scroll;
+
+      if (_num_to_scroll == 0)
+       _num_to_scroll = 1;
+      /*
+         ** If we are scrolling the source or disassembly window, do a
+         ** "psuedo" scroll since not all of the source is in memory,
+         ** only what is in the viewport. If win_to_scroll is the
+         ** command window do nothing since the term should handle it.
+       */
+      if (win_to_scroll == TUI_SRC_WIN || win_to_scroll == TUI_DISASM_WIN)
+       tui_horizontal_source_scroll (win_to_scroll, RIGHT_SCROLL, _num_to_scroll);
+    }
+}
+
+
+/* Scroll a window.  Arguments are passed through a va_list.    */
+void
+tui_scroll (enum tui_scroll_direction direction,
+           struct tui_win_info * win_to_scroll,
+           int num_to_scroll)
+{
+  switch (direction)
+    {
+    case FORWARD_SCROLL:
+      tui_scroll_forward (win_to_scroll, num_to_scroll);
+      break;
+    case BACKWARD_SCROLL:
+      tui_scroll_backward (win_to_scroll, num_to_scroll);
+      break;
+    case LEFT_SCROLL:
+      tui_scroll_left (win_to_scroll, num_to_scroll);
+      break;
+    case RIGHT_SCROLL:
+      tui_scroll_right (win_to_scroll, num_to_scroll);
+      break;
+    default:
+      break;
+    }
+}
+
+
+void
+tui_refresh_all_win (void)
+{
+  enum tui_win_type type;
+
+  clearok (curscr, TRUE);
+  tui_refresh_all (tui_win_list);
+  for (type = SRC_WIN; type < MAX_MAJOR_WINDOWS; type++)
+    {
+      if (tui_win_list[type] && tui_win_list[type]->generic.is_visible)
+       {
+         switch (type)
+           {
+           case SRC_WIN:
+           case DISASSEM_WIN:
+             tui_show_source_content (tui_win_list[type]);
+             tui_check_and_display_highlight_if_needed (tui_win_list[type]);
+             tui_erase_exec_info_content (tui_win_list[type]);
+             tui_update_exec_info (tui_win_list[type]);
+             break;
+           case DATA_WIN:
+             tui_refresh_data_win ();
+             break;
+           default:
+             break;
+           }
+       }
+    }
+  tui_show_locator_content ();
+}
+
+
+/* Resize all the windows based on the the terminal size.  This
+   function gets called from within the readline sinwinch handler.  */
+void
+tui_resize_all (void)
+{
+  int height_diff, width_diff;
+  int screenheight, screenwidth;
+
+  rl_get_screen_size (&screenheight, &screenwidth);
+  width_diff = screenwidth - tui_term_width ();
+  height_diff = screenheight - tui_term_height ();
+  if (height_diff || width_diff)
+    {
+      enum tui_layout_type cur_layout = tui_current_layout ();
+      struct tui_win_info * win_with_focus = tui_win_with_focus ();
+      struct tui_win_info *first_win;
+      struct tui_win_info *second_win;
+      struct tui_gen_win_info * locator = tui_locator_win_info_ptr ();
+      enum tui_win_type win_type;
+      int new_height, split_diff, cmd_split_diff, num_wins_displayed = 2;
+
+      /* turn keypad off while we resize */
+      if (win_with_focus != TUI_CMD_WIN)
+       keypad (TUI_CMD_WIN->generic.handle, FALSE);
+      tui_update_gdb_sizes ();
+      tui_set_term_height_to (screenheight);
+      tui_set_term_width_to (screenwidth);
+      if (cur_layout == SRC_DISASSEM_COMMAND ||
+       cur_layout == SRC_DATA_COMMAND || cur_layout == DISASSEM_DATA_COMMAND)
+       num_wins_displayed++;
+      split_diff = height_diff / num_wins_displayed;
+      cmd_split_diff = split_diff;
+      if (height_diff % num_wins_displayed)
+       {
+         if (height_diff < 0)
+           cmd_split_diff--;
+         else
+           cmd_split_diff++;
+       }
+      /* now adjust each window */
+      clear ();
+      refresh ();
+      switch (cur_layout)
+       {
+       case SRC_COMMAND:
+       case DISASSEM_COMMAND:
+         first_win = (struct tui_win_info *) (tui_source_windows ())->list[0];
+         first_win->generic.width += width_diff;
+         locator->width += width_diff;
+         /* check for invalid heights */
+         if (height_diff == 0)
+           new_height = first_win->generic.height;
+         else if ((first_win->generic.height + split_diff) >=
+                  (screenheight - MIN_CMD_WIN_HEIGHT - 1))
+           new_height = screenheight - MIN_CMD_WIN_HEIGHT - 1;
+         else if ((first_win->generic.height + split_diff) <= 0)
+           new_height = MIN_WIN_HEIGHT;
+         else
+           new_height = first_win->generic.height + split_diff;
+
+         make_invisible_and_set_new_height (first_win, new_height);
+         TUI_CMD_WIN->generic.origin.y = locator->origin.y + 1;
+         TUI_CMD_WIN->generic.width += width_diff;
+         new_height = screenheight - TUI_CMD_WIN->generic.origin.y;
+         make_invisible_and_set_new_height (TUI_CMD_WIN, new_height);
+         make_visible_with_new_height (first_win);
+         make_visible_with_new_height (TUI_CMD_WIN);
+         if (first_win->generic.content_size <= 0)
+           tui_erase_source_content (first_win, EMPTY_SOURCE_PROMPT);
+         break;
+       default:
+         if (cur_layout == SRC_DISASSEM_COMMAND)
+           {
+             first_win = TUI_SRC_WIN;
+             first_win->generic.width += width_diff;
+             second_win = TUI_DISASM_WIN;
+             second_win->generic.width += width_diff;
+           }
+         else
+           {
+             first_win = TUI_DATA_WIN;
+             first_win->generic.width += width_diff;
+             second_win = (struct tui_win_info *) (tui_source_windows ())->list[0];
+             second_win->generic.width += width_diff;
+           }
+         /* Change the first window's height/width */
+         /* check for invalid heights */
+         if (height_diff == 0)
+           new_height = first_win->generic.height;
+         else if ((first_win->generic.height +
+                   second_win->generic.height + (split_diff * 2)) >=
+                  (screenheight - MIN_CMD_WIN_HEIGHT - 1))
+           new_height = (screenheight - MIN_CMD_WIN_HEIGHT - 1) / 2;
+         else if ((first_win->generic.height + split_diff) <= 0)
+           new_height = MIN_WIN_HEIGHT;
+         else
+           new_height = first_win->generic.height + split_diff;
+         make_invisible_and_set_new_height (first_win, new_height);
+
+         if (first_win == TUI_DATA_WIN && width_diff != 0)
+           first_win->detail.data_display_info.regs_column_count =
+             tui_calculate_regs_column_count (
+                         first_win->detail.data_display_info.regs_display_type);
+         locator->width += width_diff;
+
+         /* Change the second window's height/width */
+         /* check for invalid heights */
+         if (height_diff == 0)
+           new_height = second_win->generic.height;
+         else if ((first_win->generic.height +
+                   second_win->generic.height + (split_diff * 2)) >=
+                  (screenheight - MIN_CMD_WIN_HEIGHT - 1))
+           {
+             new_height = screenheight - MIN_CMD_WIN_HEIGHT - 1;
+             if (new_height % 2)
+               new_height = (new_height / 2) + 1;
+             else
+               new_height /= 2;
+           }
+         else if ((second_win->generic.height + split_diff) <= 0)
+           new_height = MIN_WIN_HEIGHT;
+         else
+           new_height = second_win->generic.height + split_diff;
+         second_win->generic.origin.y = first_win->generic.height - 1;
+         make_invisible_and_set_new_height (second_win, new_height);
+
+         /* Change the command window's height/width */
+         TUI_CMD_WIN->generic.origin.y = locator->origin.y + 1;
+         make_invisible_and_set_new_height (
+                            TUI_CMD_WIN, TUI_CMD_WIN->generic.height + cmd_split_diff);
+         make_visible_with_new_height (first_win);
+         make_visible_with_new_height (second_win);
+         make_visible_with_new_height (TUI_CMD_WIN);
+         if (first_win->generic.content_size <= 0)
+           tui_erase_source_content (first_win, EMPTY_SOURCE_PROMPT);
+         if (second_win->generic.content_size <= 0)
+           tui_erase_source_content (second_win, EMPTY_SOURCE_PROMPT);
+         break;
+       }
+      /*
+         ** Now remove all invisible windows, and their content so that they get
+         ** created again when called for with the new size
+       */
+      for (win_type = SRC_WIN; (win_type < MAX_MAJOR_WINDOWS); win_type++)
+       {
+         if (win_type != CMD_WIN && (tui_win_list[win_type] != NULL)
+             && !tui_win_list[win_type]->generic.is_visible)
+           {
+             tui_free_window (tui_win_list[win_type]);
+             tui_win_list[win_type] = (struct tui_win_info *) NULL;
+           }
+       }
+      tui_set_win_resized_to (TRUE);
+      /* turn keypad back on, unless focus is in the command window */
+      if (win_with_focus != TUI_CMD_WIN)
+       keypad (TUI_CMD_WIN->generic.handle, TRUE);
+    }
+}
+
+
+/* SIGWINCH signal handler for the tui.  This signal handler is always
+   called, even when the readline package clears signals because it is
+   set as the old_sigwinch() (TUI only).  */
+void
+tui_sigwinch_handler (int signal)
+{
+  /*
+     ** Say that a resize was done so that the readline can do it
+     ** later when appropriate.
+   */
+  tui_set_win_resized_to (TRUE);
+}
+
+
+
+/*************************
+** STATIC LOCAL FUNCTIONS
+**************************/
+
+
+static void
+tui_scroll_forward_command (char *arg, int from_tty)
+{
+  int num_to_scroll = 1;
+  struct tui_win_info * win_to_scroll;
+
+  /* Make sure the curses mode is enabled.  */
+  tui_enable ();
+  if (arg == (char *) NULL)
+    parse_scrolling_args (arg, &win_to_scroll, (int *) NULL);
+  else
+    parse_scrolling_args (arg, &win_to_scroll, &num_to_scroll);
+  tui_scroll (FORWARD_SCROLL, win_to_scroll, num_to_scroll);
+}
+
+
+static void
+tui_scroll_backward_command (char *arg, int from_tty)
+{
+  int num_to_scroll = 1;
+  struct tui_win_info * win_to_scroll;
+
+  /* Make sure the curses mode is enabled.  */
+  tui_enable ();
+  if (arg == (char *) NULL)
+    parse_scrolling_args (arg, &win_to_scroll, (int *) NULL);
+  else
+    parse_scrolling_args (arg, &win_to_scroll, &num_to_scroll);
+  tui_scroll (BACKWARD_SCROLL, win_to_scroll, num_to_scroll);
+}
+
+
+static void
+tui_scroll_left_command (char *arg, int from_tty)
+{
+  int num_to_scroll;
+  struct tui_win_info * win_to_scroll;
+
+  /* Make sure the curses mode is enabled.  */
+  tui_enable ();
+  parse_scrolling_args (arg, &win_to_scroll, &num_to_scroll);
+  tui_scroll (LEFT_SCROLL, win_to_scroll, num_to_scroll);
+}
+
+
+static void
+tui_scroll_right_command (char *arg, int from_tty)
+{
+  int num_to_scroll;
+  struct tui_win_info * win_to_scroll;
+
+  /* Make sure the curses mode is enabled.  */
+  tui_enable ();
+  parse_scrolling_args (arg, &win_to_scroll, &num_to_scroll);
+  tui_scroll (RIGHT_SCROLL, win_to_scroll, num_to_scroll);
+}
+
+
+/* Set focus to the window named by 'arg'.  */
+static void
+tui_set_focus (char *arg, int from_tty)
+{
+  if (arg != (char *) NULL)
+    {
+      char *buf_ptr = (char *) xstrdup (arg);
+      int i;
+      struct tui_win_info * win_info = (struct tui_win_info *) NULL;
+
+      for (i = 0; (i < strlen (buf_ptr)); i++)
+       buf_ptr[i] = toupper (arg[i]);
+
+      if (subset_compare (buf_ptr, "NEXT"))
+       win_info = tui_next_win (tui_win_with_focus ());
+      else if (subset_compare (buf_ptr, "PREV"))
+       win_info = tui_prev_win (tui_win_with_focus ());
+      else
+       win_info = tui_partial_win_by_name (buf_ptr);
+
+      if (win_info == (struct tui_win_info *) NULL || !win_info->generic.is_visible)
+       warning ("Invalid window specified. \n\
+The window name specified must be valid and visible.\n");
+      else
+       {
+         tui_set_win_focus_to (win_info);
+         keypad (TUI_CMD_WIN->generic.handle, (win_info != TUI_CMD_WIN));
+       }
+
+      if (TUI_DATA_WIN && TUI_DATA_WIN->generic.is_visible)
+       tui_refresh_data_win ();
+      xfree (buf_ptr);
+      printf_filtered ("Focus set to %s window.\n",
+                      tui_win_name ((struct tui_gen_win_info *) tui_win_with_focus ()));
+    }
+  else
+    warning ("Incorrect Number of Arguments.\n%s", FOCUS_USAGE);
+}
+
+static void
+tui_set_focus_command (char *arg, int from_tty)
+{
+  /* Make sure the curses mode is enabled.  */
+  tui_enable ();
+  tui_set_focus (arg, from_tty);
+}
+
+
+static void
+tui_all_windows_info (char *arg, int from_tty)
+{
+  enum tui_win_type type;
+  struct tui_win_info * win_with_focus = tui_win_with_focus ();
+
+  for (type = SRC_WIN; (type < MAX_MAJOR_WINDOWS); type++)
+    if (tui_win_list[type] && tui_win_list[type]->generic.is_visible)
+      {
+       if (win_with_focus == tui_win_list[type])
+         printf_filtered ("        %s\t(%d lines)  <has focus>\n",
+                          tui_win_name (&tui_win_list[type]->generic),
+                          tui_win_list[type]->generic.height);
+       else
+         printf_filtered ("        %s\t(%d lines)\n",
+                          tui_win_name (&tui_win_list[type]->generic),
+                          tui_win_list[type]->generic.height);
+      }
+}
+
+
+static void
+tui_refresh_all_command (char *arg, int from_tty)
+{
+  /* Make sure the curses mode is enabled.  */
+  tui_enable ();
+
+  tui_refresh_all_win ();
+}
+
+
+/* Set the height of the specified window.   */
+static void
+tui_set_tab_width_command (char *arg, int from_tty)
+{
+  /* Make sure the curses mode is enabled.  */
+  tui_enable ();
+  if (arg != (char *) NULL)
+    {
+      int ts;
+
+      ts = atoi (arg);
+      if (ts > 0)
+       tui_set_default_tab_len (ts);
+      else
+       warning ("Tab widths greater than 0 must be specified.\n");
+    }
+}
+
+
+/* Set the height of the specified window.   */
+static void
+tui_set_win_height (char *arg, int from_tty)
+{
+  /* Make sure the curses mode is enabled.  */
+  tui_enable ();
+  if (arg != (char *) NULL)
+    {
+      char *buf = xstrdup (arg);
+      char *buf_ptr = buf;
+      char *wname = (char *) NULL;
+      int new_height, i;
+      struct tui_win_info * win_info;
+
+      wname = buf_ptr;
+      buf_ptr = strchr (buf_ptr, ' ');
+      if (buf_ptr != (char *) NULL)
+       {
+         *buf_ptr = (char) 0;
+
+         /*
+            ** Validate the window name
+          */
+         for (i = 0; i < strlen (wname); i++)
+           wname[i] = toupper (wname[i]);
+         win_info = tui_partial_win_by_name (wname);
+
+         if (win_info == (struct tui_win_info *) NULL || !win_info->generic.is_visible)
+           warning ("Invalid window specified. \n\
+The window name specified must be valid and visible.\n");
+         else
+           {
+             /* Process the size */
+             while (*(++buf_ptr) == ' ')
+               ;
+
+             if (*buf_ptr != (char) 0)
+               {
+                 int negate = FALSE;
+                 int fixed_size = TRUE;
+                 int input_no;;
+
+                 if (*buf_ptr == '+' || *buf_ptr == '-')
+                   {
+                     if (*buf_ptr == '-')
+                       negate = TRUE;
+                     fixed_size = FALSE;
+                     buf_ptr++;
+                   }
+                 input_no = atoi (buf_ptr);
+                 if (input_no > 0)
+                   {
+                     if (negate)
+                       input_no *= (-1);
+                     if (fixed_size)
+                       new_height = input_no;
+                     else
+                       new_height = win_info->generic.height + input_no;
+                     /*
+                        ** Now change the window's height, and adjust all
+                        ** other windows around it
+                      */
+                     if (tui_adjust_win_heights (win_info,
+                                               new_height) == TUI_FAILURE)
+                       warning ("Invalid window height specified.\n%s",
+                                WIN_HEIGHT_USAGE);
+                     else
+                        tui_update_gdb_sizes ();
+                   }
+                 else
+                   warning ("Invalid window height specified.\n%s",
+                            WIN_HEIGHT_USAGE);
+               }
+           }
+       }
+      else
+       printf_filtered (WIN_HEIGHT_USAGE);
+
+      if (buf != (char *) NULL)
+       xfree (buf);
+    }
+  else
+    printf_filtered (WIN_HEIGHT_USAGE);
+}
+
+/* Set the height of the specified window, with va_list.    */
+static void
+tui_set_win_height_command (char *arg, int from_tty)
+{
+  /* Make sure the curses mode is enabled.  */
+  tui_enable ();
+  tui_set_win_height (arg, from_tty);
+}
+
+
+/* XDB Compatibility command for setting the window height.  This will
+   increase or decrease the command window by the specified amount.  */
+static void
+tui_xdb_set_win_height (char *arg, int from_tty)
+{
+  /* Make sure the curses mode is enabled.  */
+  tui_enable ();
+  if (arg != (char *) NULL)
+    {
+      int input_no = atoi (arg);
+
+      if (input_no > 0)
+       {                       /* Add 1 for the locator */
+         int new_height = tui_term_height () - (input_no + 1);
+
+         if (!new_height_ok (tui_win_list[CMD_WIN], new_height) ||
+             tui_adjust_win_heights (tui_win_list[CMD_WIN],
+                                   new_height) == TUI_FAILURE)
+           warning ("Invalid window height specified.\n%s",
+                    XDBWIN_HEIGHT_USAGE);
+       }
+      else
+       warning ("Invalid window height specified.\n%s",
+                XDBWIN_HEIGHT_USAGE);
+    }
+  else
+    warning ("Invalid window height specified.\n%s", XDBWIN_HEIGHT_USAGE);
+}
+
+/* Set the height of the specified window, with va_list.  */
+static void
+tui_xdb_set_win_height_command (char *arg, int from_tty)
+{
+  tui_xdb_set_win_height (arg, from_tty);
+}
+
+
+/* Function to adjust all window heights around the primary.   */
+static enum tui_status
+tui_adjust_win_heights (struct tui_win_info * primary_win_info, int new_height)
+{
+  enum tui_status status = TUI_FAILURE;
+
+  if (new_height_ok (primary_win_info, new_height))
+    {
+      status = TUI_SUCCESS;
+      if (new_height != primary_win_info->generic.height)
+       {
+         int diff;
+         struct tui_win_info * win_info;
+         struct tui_gen_win_info * locator = tui_locator_win_info_ptr ();
+         enum tui_layout_type cur_layout = tui_current_layout ();
+
+         diff = (new_height - primary_win_info->generic.height) * (-1);
+         if (cur_layout == SRC_COMMAND || cur_layout == DISASSEM_COMMAND)
+           {
+             struct tui_win_info * src_win_info;
+
+             make_invisible_and_set_new_height (primary_win_info, new_height);
+             if (primary_win_info->generic.type == CMD_WIN)
+               {
+                 win_info = (struct tui_win_info *) (tui_source_windows ())->list[0];
+                 src_win_info = win_info;
+               }
+             else
+               {
+                 win_info = tui_win_list[CMD_WIN];
+                 src_win_info = primary_win_info;
+               }
+             make_invisible_and_set_new_height (win_info,
+                                            win_info->generic.height + diff);
+             TUI_CMD_WIN->generic.origin.y = locator->origin.y + 1;
+             make_visible_with_new_height (win_info);
+             make_visible_with_new_height (primary_win_info);
+             if (src_win_info->generic.content_size <= 0)
+               tui_erase_source_content (src_win_info, EMPTY_SOURCE_PROMPT);
+           }
+         else
+           {
+             struct tui_win_info *first_win;
+             struct tui_win_info *second_win;
+
+             if (cur_layout == SRC_DISASSEM_COMMAND)
+               {
+                 first_win = TUI_SRC_WIN;
+                 second_win = TUI_DISASM_WIN;
+               }
+             else
+               {
+                 first_win = TUI_DATA_WIN;
+                 second_win = (struct tui_win_info *) (tui_source_windows ())->list[0];
+               }
+             if (primary_win_info == TUI_CMD_WIN)
+               {               /*
+                                  ** Split the change in height accross the 1st & 2nd windows
+                                  ** adjusting them as well.
+                                */
+                 int first_split_diff = diff / 2;      /* subtract the locator */
+                 int second_split_diff = first_split_diff;
+
+                 if (diff % 2)
+                   {
+                     if (first_win->generic.height >
+                         second_win->generic.height)
+                       if (diff < 0)
+                         first_split_diff--;
+                       else
+                         first_split_diff++;
+                     else
+                       {
+                         if (diff < 0)
+                           second_split_diff--;
+                         else
+                           second_split_diff++;
+                       }
+                   }
+                 /* make sure that the minimum hieghts are honored */
+                 while ((first_win->generic.height + first_split_diff) < 3)
+                   {
+                     first_split_diff++;
+                     second_split_diff--;
+                   }
+                 while ((second_win->generic.height + second_split_diff) < 3)
+                   {
+                     second_split_diff++;
+                     first_split_diff--;
+                   }
+                 make_invisible_and_set_new_height (
+                                                 first_win,
+                                first_win->generic.height + first_split_diff);
+                 second_win->generic.origin.y = first_win->generic.height - 1;
+                 make_invisible_and_set_new_height (
+                   second_win, second_win->generic.height + second_split_diff);
+                 TUI_CMD_WIN->generic.origin.y = locator->origin.y + 1;
+                 make_invisible_and_set_new_height (TUI_CMD_WIN, new_height);
+               }
+             else
+               {
+                 if ((TUI_CMD_WIN->generic.height + diff) < 1)
+                   {           /*
+                                  ** If there is no way to increase the command window
+                                  ** take real estate from the 1st or 2nd window.
+                                */
+                     if ((TUI_CMD_WIN->generic.height + diff) < 1)
+                       {
+                         int i;
+                         for (i = TUI_CMD_WIN->generic.height + diff;
+                              (i < 1); i++)
+                           if (primary_win_info == first_win)
+                             second_win->generic.height--;
+                           else
+                             first_win->generic.height--;
+                       }
+                   }
+                 if (primary_win_info == first_win)
+                   make_invisible_and_set_new_height (first_win, new_height);
+                 else
+                   make_invisible_and_set_new_height (
+                                                   first_win,
+                                                 first_win->generic.height);
+                 second_win->generic.origin.y = first_win->generic.height - 1;
+                 if (primary_win_info == second_win)
+                   make_invisible_and_set_new_height (second_win, new_height);
+                 else
+                   make_invisible_and_set_new_height (
+                                     second_win, second_win->generic.height);
+                 TUI_CMD_WIN->generic.origin.y = locator->origin.y + 1;
+                 if ((TUI_CMD_WIN->generic.height + diff) < 1)
+                   make_invisible_and_set_new_height (TUI_CMD_WIN, 1);
+                 else
+                   make_invisible_and_set_new_height (
+                                    TUI_CMD_WIN, TUI_CMD_WIN->generic.height + diff);
+               }
+             make_visible_with_new_height (TUI_CMD_WIN);
+             make_visible_with_new_height (second_win);
+             make_visible_with_new_height (first_win);
+             if (first_win->generic.content_size <= 0)
+               tui_erase_source_content (first_win, EMPTY_SOURCE_PROMPT);
+             if (second_win->generic.content_size <= 0)
+               tui_erase_source_content (second_win, EMPTY_SOURCE_PROMPT);
+           }
+       }
+    }
+
+  return status;
+}
+
+
+/* Function make the target window (and auxillary windows associated
+   with the targer) invisible, and set the new height and location.  */
+static void
+make_invisible_and_set_new_height (struct tui_win_info * win_info, int height)
+{
+  int i;
+  struct tui_gen_win_info * gen_win_info;
+
+  tui_make_invisible (&win_info->generic);
+  win_info->generic.height = height;
+  if (height > 1)
+    win_info->generic.viewport_height = height - 1;
+  else
+    win_info->generic.viewport_height = height;
+  if (win_info != TUI_CMD_WIN)
+    win_info->generic.viewport_height--;
+
+  /* Now deal with the auxillary windows associated with win_info */
+  switch (win_info->generic.type)
+    {
+    case SRC_WIN:
+    case DISASSEM_WIN:
+      gen_win_info = win_info->detail.source_info.execution_info;
+      tui_make_invisible (gen_win_info);
+      gen_win_info->height = height;
+      gen_win_info->origin.y = win_info->generic.origin.y;
+      if (height > 1)
+       gen_win_info->viewport_height = height - 1;
+      else
+       gen_win_info->viewport_height = height;
+      if (win_info != TUI_CMD_WIN)
+       gen_win_info->viewport_height--;
+
+      if (tui_win_has_locator (win_info))
+       {
+         gen_win_info = tui_locator_win_info_ptr ();
+         tui_make_invisible (gen_win_info);
+         gen_win_info->origin.y = win_info->generic.origin.y + height;
+       }
+      break;
+    case DATA_WIN:
+      /* delete all data item windows */
+      for (i = 0; i < win_info->generic.content_size; i++)
+       {
+         gen_win_info = (struct tui_gen_win_info *) & ((struct tui_win_element *)
+                     win_info->generic.content[i])->which_element.data_window;
+         tui_delete_win (gen_win_info->handle);
+         gen_win_info->handle = (WINDOW *) NULL;
+       }
+      break;
+    default:
+      break;
+    }
+}
+
+
+/* Function to make the windows with new heights visible.  This means
+   re-creating the windows' content since the window had to be
+   destroyed to be made invisible.  */
+static void
+make_visible_with_new_height (struct tui_win_info * win_info)
+{
+  struct symtab *s;
+
+  tui_make_visible (&win_info->generic);
+  tui_check_and_display_highlight_if_needed (win_info);
+  switch (win_info->generic.type)
+    {
+    case SRC_WIN:
+    case DISASSEM_WIN:
+      tui_free_win_content (win_info->detail.source_info.execution_info);
+      tui_make_visible (win_info->detail.source_info.execution_info);
+      if (win_info->generic.content != NULL)
+       {
+         union tui_line_or_address line_or_addr;
+         struct symtab_and_line cursal
+           = get_current_source_symtab_and_line ();
+
+         if (win_info->generic.type == SRC_WIN)
+           line_or_addr.line_no =
+             win_info->detail.source_info.start_line_or_addr.line_no;
+         else
+           line_or_addr.addr =
+             win_info->detail.source_info.start_line_or_addr.addr;
+         tui_free_win_content (&win_info->generic);
+         tui_update_source_window (win_info, cursal.symtab, line_or_addr, TRUE);
+       }
+      else if (deprecated_selected_frame != (struct frame_info *) NULL)
+       {
+         union tui_line_or_address line;
+         struct symtab_and_line cursal = get_current_source_symtab_and_line ();
+
+
+         s = find_pc_symtab (get_frame_pc (deprecated_selected_frame));
+         if (win_info->generic.type == SRC_WIN)
+           line.line_no = cursal.line;
+         else
+           {
+             find_line_pc (s, cursal.line, &line.addr);
+           }
+         tui_update_source_window (win_info, s, line, TRUE);
+       }
+      if (tui_win_has_locator (win_info))
+       {
+         tui_make_visible (tui_locator_win_info_ptr ());
+         tui_show_locator_content ();
+       }
+      break;
+    case DATA_WIN:
+      tui_display_all_data ();
+      break;
+    case CMD_WIN:
+      win_info->detail.command_info.cur_line = 0;
+      win_info->detail.command_info.curch = 0;
+      wmove (win_info->generic.handle,
+            win_info->detail.command_info.cur_line,
+            win_info->detail.command_info.curch);
+      break;
+    default:
+      break;
+    }
+}
+
+
+static int
+new_height_ok (struct tui_win_info * primary_win_info, int new_height)
+{
+  int ok = (new_height < tui_term_height ());
+
+  if (ok)
+    {
+      int diff;
+      enum tui_layout_type cur_layout = tui_current_layout ();
+
+      diff = (new_height - primary_win_info->generic.height) * (-1);
+      if (cur_layout == SRC_COMMAND || cur_layout == DISASSEM_COMMAND)
+       {
+         ok = ((primary_win_info->generic.type == CMD_WIN &&
+                new_height <= (tui_term_height () - 4) &&
+                new_height >= MIN_CMD_WIN_HEIGHT) ||
+               (primary_win_info->generic.type != CMD_WIN &&
+                new_height <= (tui_term_height () - 2) &&
+                new_height >= MIN_WIN_HEIGHT));
+         if (ok)
+           {                   /* check the total height */
+             struct tui_win_info * win_info;
+
+             if (primary_win_info == TUI_CMD_WIN)
+               win_info = (struct tui_win_info *) (tui_source_windows ())->list[0];
+             else
+               win_info = TUI_CMD_WIN;
+             ok = ((new_height +
+                    (win_info->generic.height + diff)) <= tui_term_height ());
+           }
+       }
+      else
+       {
+         int cur_total_height, total_height, min_height = 0;
+         struct tui_win_info *first_win;
+         struct tui_win_info *second_win;
+
+         if (cur_layout == SRC_DISASSEM_COMMAND)
+           {
+             first_win = TUI_SRC_WIN;
+             second_win = TUI_DISASM_WIN;
+           }
+         else
+           {
+             first_win = TUI_DATA_WIN;
+             second_win = (struct tui_win_info *) (tui_source_windows ())->list[0];
+           }
+         /*
+            ** We could simply add all the heights to obtain the same result
+            ** but below is more explicit since we subtract 1 for the
+            ** line that the first and second windows share, and add one
+            ** for the locator.
+          */
+         total_height = cur_total_height =
+           (first_win->generic.height + second_win->generic.height - 1)
+           + TUI_CMD_WIN->generic.height + 1 /*locator */ ;
+         if (primary_win_info == TUI_CMD_WIN)
+           {
+             /* locator included since first & second win share a line */
+             ok = ((first_win->generic.height +
+                    second_win->generic.height + diff) >=
+                   (MIN_WIN_HEIGHT * 2) &&
+                   new_height >= MIN_CMD_WIN_HEIGHT);
+             if (ok)
+               {
+                 total_height = new_height + (first_win->generic.height +
+                                         second_win->generic.height + diff);
+                 min_height = MIN_CMD_WIN_HEIGHT;
+               }
+           }
+         else
+           {
+             min_height = MIN_WIN_HEIGHT;
+             /*
+                ** First see if we can increase/decrease the command
+                ** window.  And make sure that the command window is
+                ** at least 1 line
+              */
+             ok = ((TUI_CMD_WIN->generic.height + diff) > 0);
+             if (!ok)
+               {               /*
+                                  ** Looks like we have to increase/decrease one of
+                                  ** the other windows
+                                */
+                 if (primary_win_info == first_win)
+                   ok = (second_win->generic.height + diff) >= min_height;
+                 else
+                   ok = (first_win->generic.height + diff) >= min_height;
+               }
+             if (ok)
+               {
+                 if (primary_win_info == first_win)
+                   total_height = new_height +
+                     second_win->generic.height +
+                     TUI_CMD_WIN->generic.height + diff;
+                 else
+                   total_height = new_height +
+                     first_win->generic.height +
+                     TUI_CMD_WIN->generic.height + diff;
+               }
+           }
+         /*
+            ** Now make sure that the proposed total height doesn't exceed
+            ** the old total height.
+          */
+         if (ok)
+           ok = (new_height >= min_height && total_height <= cur_total_height);
+       }
+    }
+
+  return ok;
+}
+
+
+static void
+parse_scrolling_args (char *arg, struct tui_win_info * * win_to_scroll,
+                     int *num_to_scroll)
+{
+  if (num_to_scroll)
+    *num_to_scroll = 0;
+  *win_to_scroll = tui_win_with_focus ();
+
+  /*
+     ** First set up the default window to scroll, in case there is no
+     ** window name arg
+   */
+  if (arg != (char *) NULL)
+    {
+      char *buf, *buf_ptr;
+
+      /* process the number of lines to scroll */
+      buf = buf_ptr = xstrdup (arg);
+      if (isdigit (*buf_ptr))
+       {
+         char *num_str;
+
+         num_str = buf_ptr;
+         buf_ptr = strchr (buf_ptr, ' ');
+         if (buf_ptr != (char *) NULL)
+           {
+             *buf_ptr = (char) 0;
+             if (num_to_scroll)
+               *num_to_scroll = atoi (num_str);
+             buf_ptr++;
+           }
+         else if (num_to_scroll)
+           *num_to_scroll = atoi (num_str);
+       }
+
+      /* process the window name if one is specified */
+      if (buf_ptr != (char *) NULL)
+       {
+         char *wname;
+         int i;
+
+         if (*buf_ptr == ' ')
+           while (*(++buf_ptr) == ' ')
+             ;
+
+         if (*buf_ptr != (char) 0)
+           wname = buf_ptr;
+         else
+           wname = "?";
+         
+         /* Validate the window name */
+         for (i = 0; i < strlen (wname); i++)
+           wname[i] = toupper (wname[i]);
+         *win_to_scroll = tui_partial_win_by_name (wname);
+
+         if (*win_to_scroll == (struct tui_win_info *) NULL ||
+             !(*win_to_scroll)->generic.is_visible)
+           warning ("Invalid window specified. \n\
+The window name specified must be valid and visible.\n");
+         else if (*win_to_scroll == TUI_CMD_WIN)
+           *win_to_scroll = (struct tui_win_info *) (tui_source_windows ())->list[0];
+       }
+      xfree (buf);
+    }
+}
diff --git a/gdb/tui/tui-win.h b/gdb/tui/tui-win.h
new file mode 100644 (file)
index 0000000..b76998c
--- /dev/null
@@ -0,0 +1,56 @@
+/* TUI window generic functions.
+
+   Copyright 1998, 1999, 2000, 2001, 2002, 2004 Free Software
+   Foundation, Inc.
+
+   Contributed by Hewlett-Packard Company.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef TUI_WIN_H
+#define TUI_WIN_H
+
+#include "tui/tui-data.h"
+
+struct tui_win_info;
+
+extern void tui_scroll_forward (struct tui_win_info *, int);
+extern void tui_scroll_backward (struct tui_win_info *, int);
+extern void tui_scroll_left (struct tui_win_info *, int);
+extern void tui_scroll_right (struct tui_win_info *, int);
+extern void tui_scroll (enum tui_scroll_direction, struct tui_win_info *, int);
+extern void tui_set_win_focus_to (struct tui_win_info *);
+extern void tui_resize_all (void);
+extern void tui_refresh_all_win (void);
+extern void tui_sigwinch_handler (int);
+
+extern chtype tui_border_ulcorner;
+extern chtype tui_border_urcorner;
+extern chtype tui_border_lrcorner;
+extern chtype tui_border_llcorner;
+extern chtype tui_border_vline;
+extern chtype tui_border_hline;
+extern int tui_border_attrs;
+extern int tui_active_border_attrs;
+
+extern int tui_update_variables (void);
+
+/* Update gdb's knowledge of the terminal size.  */
+extern void tui_update_gdb_sizes (void);
+
+#endif
diff --git a/gdb/tui/tui-windata.c b/gdb/tui/tui-windata.c
new file mode 100644 (file)
index 0000000..6f22d0c
--- /dev/null
@@ -0,0 +1,309 @@
+/* Data/register window display.
+
+   Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
+   Foundation, Inc.
+
+   Contributed by Hewlett-Packard Company.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include "defs.h"
+#include "tui/tui.h"
+#include "tui/tui-data.h"
+#include "tui/tui-wingeneral.h"
+#include "tui/tui-regs.h"
+
+#ifdef HAVE_NCURSES_H       
+#include <ncurses.h>
+#else
+#ifdef HAVE_CURSES_H
+#include <curses.h>
+#endif
+#endif
+
+
+/*****************************************
+** STATIC LOCAL FUNCTIONS FORWARD DECLS    **
+******************************************/
+
+
+
+/*****************************************
+** PUBLIC FUNCTIONS                        **
+******************************************/
+
+
+/* Answer the index first element displayed.  If none are displayed,
+   then return (-1).  */
+int
+tui_first_data_item_displayed (void)
+{
+  int element_no = (-1);
+  int i;
+
+  for (i = 0; (i < TUI_DATA_WIN->generic.content_size && element_no < 0); i++)
+    {
+      struct tui_gen_win_info * data_item_win;
+
+      data_item_win = &((tui_win_content)
+                     TUI_DATA_WIN->generic.content)[i]->which_element.data_window;
+      if (data_item_win->handle != (WINDOW *) NULL && data_item_win->is_visible)
+       element_no = i;
+    }
+
+  return element_no;
+}
+
+
+/* Answer the index of the first element in line_no.  If line_no is
+   past the data area (-1) is returned.  */
+int
+tui_first_data_element_no_in_line (int line_no)
+{
+  int first_element_no = (-1);
+
+  /*
+     ** First see if there is a register on line_no, and if so, set the
+     ** first element number
+   */
+  if ((first_element_no = tui_first_reg_element_no_inline (line_no)) == -1)
+    {                          /*
+                                  ** Looking at the general data, the 1st element on line_no
+                                */
+    }
+
+  return first_element_no;
+}
+
+
+/* Function to delete all the item windows in the data window.  This
+   is usually done when the data window is scrolled.  */
+void
+tui_delete_data_content_windows (void)
+{
+  int i;
+  struct tui_gen_win_info * data_item_win_ptr;
+
+  for (i = 0; (i < TUI_DATA_WIN->generic.content_size); i++)
+    {
+      data_item_win_ptr = &((tui_win_content)
+                     TUI_DATA_WIN->generic.content)[i]->which_element.data_window;
+      tui_delete_win (data_item_win_ptr->handle);
+      data_item_win_ptr->handle = (WINDOW *) NULL;
+      data_item_win_ptr->is_visible = FALSE;
+    }
+}
+
+
+void
+tui_erase_data_content (char *prompt)
+{
+  werase (TUI_DATA_WIN->generic.handle);
+  tui_check_and_display_highlight_if_needed (TUI_DATA_WIN);
+  if (prompt != (char *) NULL)
+    {
+      int half_width = (TUI_DATA_WIN->generic.width - 2) / 2;
+      int x_pos;
+
+      if (strlen (prompt) >= half_width)
+       x_pos = 1;
+      else
+       x_pos = half_width - strlen (prompt);
+      mvwaddstr (TUI_DATA_WIN->generic.handle,
+                (TUI_DATA_WIN->generic.height / 2),
+                x_pos,
+                prompt);
+    }
+  wrefresh (TUI_DATA_WIN->generic.handle);
+}
+
+
+/* This function displays the data that is in the data window's
+   content.  It does not set the content.  */
+void
+tui_display_all_data (void)
+{
+  if (TUI_DATA_WIN->generic.content_size <= 0)
+    tui_erase_data_content (NO_DATA_STRING);
+  else
+    {
+      tui_erase_data_content ((char *) NULL);
+      tui_delete_data_content_windows ();
+      tui_check_and_display_highlight_if_needed (TUI_DATA_WIN);
+      tui_display_registers_from (0);
+      /*
+         ** Then display the other data
+       */
+      if (TUI_DATA_WIN->detail.data_display_info.data_content !=
+         (tui_win_content) NULL &&
+         TUI_DATA_WIN->detail.data_display_info.data_content_count > 0)
+       {
+       }
+    }
+}
+
+
+/* Function to display the data starting at line, line_no, in the data
+   window.  */
+void
+tui_display_data_from_line (int line_no)
+{
+  int _line_no = line_no;
+
+  if (line_no < 0)
+    _line_no = 0;
+
+  tui_check_and_display_highlight_if_needed (TUI_DATA_WIN);
+
+  /* there is no general data, force regs to display (if there are any) */
+  if (TUI_DATA_WIN->detail.data_display_info.data_content_count <= 0)
+    tui_display_registers_from_line (_line_no, TRUE);
+  else
+    {
+      int element_no, start_line_no;
+      int regs_last_line = tui_last_regs_line_no ();
+
+
+      /* display regs if we can */
+      if (tui_display_registers_from_line (_line_no, FALSE) < 0)
+       {                       /*
+                                  ** _line_no is past the regs display, so calc where the
+                                  ** start data element is
+                                */
+         if (regs_last_line < _line_no)
+           {                   /* figure out how many lines each element is to obtain
+                                  the start element_no */
+           }
+       }
+      else
+       {                       /*
+                                  ** calculate the starting element of the data display, given
+                                  ** regs_last_line and how many lines each element is, up to
+                                  ** _line_no
+                                */
+       }
+      /* Now display the data , starting at element_no */
+    }
+}
+
+
+/* Display data starting at element element_no.   */
+void
+tui_display_data_from (int element_no, int reuse_windows)
+{
+  int first_line = (-1);
+
+  if (element_no < TUI_DATA_WIN->detail.data_display_info.regs_content_count)
+    first_line = tui_line_from_reg_element_no (element_no);
+  else
+    {                          /* calculate the first_line from the element number */
+    }
+
+  if (first_line >= 0)
+    {
+      tui_erase_data_content ((char *) NULL);
+      if (!reuse_windows)
+       tui_delete_data_content_windows ();
+      tui_display_data_from_line (first_line);
+    }
+}
+
+
+/* Function to redisplay the contents of the data window.  */
+void
+tui_refresh_data_win (void)
+{
+  tui_erase_data_content ((char *) NULL);
+  if (TUI_DATA_WIN->generic.content_size > 0)
+    {
+      int first_element = tui_first_data_item_displayed ();
+
+      if (first_element >= 0)  /* re-use existing windows */
+       tui_display_data_from (first_element, TRUE);
+    }
+}
+
+
+/* Function to check the data values and hilite any that have changed.  */
+void
+tui_check_data_values (struct frame_info *frame)
+{
+  tui_check_register_values (frame);
+
+  /* Now check any other data values that there are */
+  if (TUI_DATA_WIN != NULL && TUI_DATA_WIN->generic.is_visible)
+    {
+      int i;
+
+      for (i = 0; TUI_DATA_WIN->detail.data_display_info.data_content_count; i++)
+       {
+#ifdef LATER
+         tui_data_element_ptr data_element_ptr;
+         struct tui_gen_win_info * data_item_win_ptr;
+         Opaque new_value;
+
+         data_item_ptr = &TUI_DATA_WIN->detail.data_display_info.
+           data_content[i]->which_element.data_window;
+         data_element_ptr = &((tui_win_content)
+                            data_item_win_ptr->content)[0]->which_element.data;
+         if value
+           has changed (data_element_ptr, frame, &new_value)
+           {
+             data_element_ptr->value = new_value;
+             update the display with the new value, hiliting it.
+           }
+#endif
+       }
+    }
+}
+
+
+/* Scroll the data window vertically forward or backward.   */
+void
+tui_vertical_data_scroll (enum tui_scroll_direction scroll_direction, int num_to_scroll)
+{
+  int first_element_no;
+  int first_line = (-1);
+
+  first_element_no = tui_first_data_item_displayed ();
+  if (first_element_no < TUI_DATA_WIN->detail.data_display_info.regs_content_count)
+    first_line = tui_line_from_reg_element_no (first_element_no);
+  else
+    {                          /* calculate the first line from the element number which is in
+                                  ** the general data content
+                                */
+    }
+
+  if (first_line >= 0)
+    {
+      int last_element_no, last_line;
+
+      if (scroll_direction == FORWARD_SCROLL)
+       first_line += num_to_scroll;
+      else
+       first_line -= num_to_scroll;
+      tui_erase_data_content ((char *) NULL);
+      tui_delete_data_content_windows ();
+      tui_display_data_from_line (first_line);
+    }
+}
+
+
+/*****************************************
+** STATIC LOCAL FUNCTIONS               **
+******************************************/
diff --git a/gdb/tui/tui-windata.h b/gdb/tui/tui-windata.h
new file mode 100644 (file)
index 0000000..10123a3
--- /dev/null
@@ -0,0 +1,41 @@
+/* Data/register window display.
+
+   Copyright 1998, 1999, 2000, 2001, 2004 Free Software Foundation,
+   Inc.
+
+   Contributed by Hewlett-Packard Company.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef TUI_WINDATA_H
+#define TUI_WINDATA_H
+
+#include "tui/tui-data.h"
+
+extern void tui_erase_data_content (char *);
+extern void tui_display_all_data (void);
+extern void tui_check_data_values (struct frame_info *);
+extern void tui_display_data_from_line (int);
+extern int tui_first_data_item_displayed (void);
+extern int tui_first_data_element_no_in_line (int);
+extern void tui_delete_data_content_windows (void);
+extern void tui_refresh_data_win (void);
+extern void tui_display_data_from (int, int);
+extern void tui_vertical_data_scroll (enum tui_scroll_direction, int);
+
+#endif
diff --git a/gdb/tui/tui-wingeneral.c b/gdb/tui/tui-wingeneral.c
new file mode 100644 (file)
index 0000000..1bd9460
--- /dev/null
@@ -0,0 +1,282 @@
+/* General window behavior.
+
+   Copyright 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation,
+   Inc.
+
+   Contributed by Hewlett-Packard Company.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include "defs.h"
+#include "tui/tui.h"
+#include "tui/tui-data.h"
+#include "tui/tui-wingeneral.h"
+#include "tui/tui-win.h"
+
+#ifdef HAVE_NCURSES_H       
+#include <ncurses.h>
+#else
+#ifdef HAVE_CURSES_H
+#include <curses.h>
+#endif
+#endif
+
+/***********************
+** PUBLIC FUNCTIONS
+***********************/
+
+/* Refresh the window.   */
+void
+tui_refresh_win (struct tui_gen_win_info * win_info)
+{
+  if (win_info->type == DATA_WIN && win_info->content_size > 0)
+    {
+      int i;
+
+      for (i = 0; (i < win_info->content_size); i++)
+       {
+         struct tui_gen_win_info * data_item_win_ptr;
+
+         data_item_win_ptr = &((tui_win_content)
+                            win_info->content)[i]->which_element.data_window;
+         if (data_item_win_ptr != NULL
+             && data_item_win_ptr->handle != (WINDOW *) NULL)
+           wrefresh (data_item_win_ptr->handle);
+       }
+    }
+  else if (win_info->type == CMD_WIN)
+    {
+      /* Do nothing */
+    }
+  else
+    {
+      if (win_info->handle != (WINDOW *) NULL)
+       wrefresh (win_info->handle);
+    }
+
+  return;
+}
+
+
+/* Function to delete the curses window, checking for NULL.   */
+void
+tui_delete_win (WINDOW * window)
+{
+  if (window != (WINDOW *) NULL)
+    delwin (window);
+
+  return;
+}
+
+
+/* Draw a border arround the window.  */
+void
+box_win (struct tui_gen_win_info * win_info, int highlight_flag)
+{
+  if (win_info && win_info->handle)
+    {
+      WINDOW *win;
+      int attrs;
+
+      win = win_info->handle;
+      if (highlight_flag == HILITE)
+        attrs = tui_active_border_attrs;
+      else
+        attrs = tui_border_attrs;
+
+      wattron (win, attrs);
+      wborder (win, tui_border_vline, tui_border_vline,
+               tui_border_hline, tui_border_hline,
+               tui_border_ulcorner, tui_border_urcorner,
+               tui_border_llcorner, tui_border_lrcorner);
+      if (win_info->title)
+        mvwaddstr (win, 0, 3, win_info->title);
+      wattroff (win, attrs);
+    }
+}
+
+
+void
+tui_unhighlight_win (struct tui_win_info * win_info)
+{
+  if (win_info != NULL && win_info->generic.handle != (WINDOW *) NULL)
+    {
+      box_win ((struct tui_gen_win_info *) win_info, NO_HILITE);
+      wrefresh (win_info->generic.handle);
+      tui_set_win_highlight (win_info, 0);
+    }
+}
+
+
+void
+tui_highlight_win (struct tui_win_info * win_info)
+{
+  if (win_info != NULL
+      && win_info->can_highlight
+      && win_info->generic.handle != (WINDOW *) NULL)
+    {
+      box_win ((struct tui_gen_win_info *) win_info, HILITE);
+      wrefresh (win_info->generic.handle);
+      tui_set_win_highlight (win_info, 1);
+    }
+}
+
+void
+tui_check_and_display_highlight_if_needed (struct tui_win_info * win_info)
+{
+  if (win_info != NULL && win_info->generic.type != CMD_WIN)
+    {
+      if (win_info->is_highlighted)
+       tui_highlight_win (win_info);
+      else
+       tui_unhighlight_win (win_info);
+
+    }
+  return;
+}
+
+
+void
+tui_make_window (struct tui_gen_win_info * win_info, int box_it)
+{
+  WINDOW *handle;
+
+  handle = newwin (win_info->height,
+                  win_info->width,
+                  win_info->origin.y,
+                  win_info->origin.x);
+  win_info->handle = handle;
+  if (handle != (WINDOW *) NULL)
+    {
+      if (box_it == BOX_WINDOW)
+       box_win (win_info, NO_HILITE);
+      win_info->is_visible = TRUE;
+      scrollok (handle, TRUE);
+    }
+}
+
+
+/* We can't really make windows visible, or invisible.  So we have to
+   delete the entire window when making it visible, and create it
+   again when making it visible.  */
+static void
+make_visible (struct tui_gen_win_info *win_info, int visible)
+{
+  /* Don't tear down/recreate command window */
+  if (win_info->type == CMD_WIN)
+    return;
+
+  if (visible)
+    {
+      if (!win_info->is_visible)
+       {
+         tui_make_window (win_info,
+                          (win_info->type != CMD_WIN
+                           && !tui_win_is_auxillary (win_info->type)));
+         win_info->is_visible = TRUE;
+       }
+    }
+  else if (!visible &&
+          win_info->is_visible && win_info->handle != (WINDOW *) NULL)
+    {
+      win_info->is_visible = FALSE;
+      tui_delete_win (win_info->handle);
+      win_info->handle = (WINDOW *) NULL;
+    }
+
+  return;
+}
+
+void
+tui_make_visible (struct tui_gen_win_info *win_info)
+{
+  make_visible (win_info, 1);
+}
+
+void
+tui_make_invisible (struct tui_gen_win_info *win_info)
+{
+  make_visible (win_info, 0);
+}
+
+
+/* Makes all windows invisible (except the command and locator windows).   */
+static void
+make_all_visible (int visible)
+{
+  int i;
+
+  for (i = 0; i < MAX_MAJOR_WINDOWS; i++)
+    {
+      if (tui_win_list[i] != NULL
+         && ((tui_win_list[i])->generic.type) != CMD_WIN)
+       {
+         if (tui_win_is_source_type ((tui_win_list[i])->generic.type))
+           make_visible ((tui_win_list[i])->detail.source_info.execution_info,
+                         visible);
+         make_visible ((struct tui_gen_win_info *) tui_win_list[i], visible);
+       }
+    }
+
+  return;
+}
+
+void
+tui_make_all_visible (void)
+{
+  make_all_visible (1);
+}
+
+void
+tui_make_all_invisible (void)
+{
+  make_all_visible (0);
+}
+
+/* Function to refresh all the windows currently displayed.  */
+
+void
+tui_refresh_all (struct tui_win_info * * list)
+{
+  enum tui_win_type type;
+  struct tui_gen_win_info * locator = tui_locator_win_info_ptr ();
+
+  for (type = SRC_WIN; (type < MAX_MAJOR_WINDOWS); type++)
+    {
+      if (list[type] && list[type]->generic.is_visible)
+       {
+         if (type == SRC_WIN || type == DISASSEM_WIN)
+           {
+             touchwin (list[type]->detail.source_info.execution_info->handle);
+             tui_refresh_win (list[type]->detail.source_info.execution_info);
+           }
+         touchwin (list[type]->generic.handle);
+         tui_refresh_win (&list[type]->generic);
+       }
+    }
+  if (locator->is_visible)
+    {
+      touchwin (locator->handle);
+      tui_refresh_win (locator);
+    }
+}
+
+
+/*********************************
+** Local Static Functions
+*********************************/
diff --git a/gdb/tui/tui-wingeneral.h b/gdb/tui/tui-wingeneral.h
new file mode 100644 (file)
index 0000000..306d794
--- /dev/null
@@ -0,0 +1,45 @@
+/* General window behavior.
+
+   Copyright 1998, 1999, 2000, 2001, 2002, 2004 Free Software
+   Foundation, Inc.
+
+   Contributed by Hewlett-Packard Company.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef TUI_WINGENERAL_H
+#define TUI_WINGENERAL_H
+
+struct tui_win_info;
+struct tui_gen_win_info;
+
+extern void tui_unhighlight_win (struct tui_win_info *);
+extern void tui_make_visible (struct tui_gen_win_info *);
+extern void tui_make_invisible (struct tui_gen_win_info *);
+extern void tui_make_all_visible (void);
+extern void tui_make_all_invisible (void);
+extern void tui_make_window (struct tui_gen_win_info *, int);
+extern struct tui_win_info *tui_copy_win (struct tui_win_info *);
+extern void tui_box_win (struct tui_gen_win_info *, int);
+extern void tui_highlight_win (struct tui_win_info *);
+extern void tui_check_and_display_highlight_if_needed (struct tui_win_info *);
+extern void tui_refresh_all (struct tui_win_info **);
+extern void tui_delete_win (WINDOW * window);
+extern void tui_refresh_win (struct tui_gen_win_info *);
+
+#endif
diff --git a/gdb/tui/tui-winsource.c b/gdb/tui/tui-winsource.c
new file mode 100644 (file)
index 0000000..6b77c40
--- /dev/null
@@ -0,0 +1,659 @@
+/* TUI display source/assembly window.
+
+   Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
+   Foundation, Inc.
+
+   Contributed by Hewlett-Packard Company.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include "defs.h"
+#include <ctype.h>
+#include "symtab.h"
+#include "frame.h"
+#include "breakpoint.h"
+#include "value.h"
+#include "source.h"
+
+#include "tui/tui.h"
+#include "tui/tui-data.h"
+#include "tui/tui-stack.h"
+#include "tui/tui-win.h"
+#include "tui/tui-wingeneral.h"
+#include "tui/tui-winsource.h"
+#include "tui/tui-source.h"
+#include "tui/tui-disasm.h"
+
+#ifdef HAVE_NCURSES_H       
+#include <ncurses.h>
+#else
+#ifdef HAVE_CURSES_H
+#include <curses.h>
+#endif
+#endif
+
+/* Function to display the "main" routine.  */
+void
+tui_display_main (void)
+{
+  if ((tui_source_windows ())->count > 0)
+    {
+      CORE_ADDR addr;
+
+      addr = tui_get_begin_asm_address ();
+      if (addr != (CORE_ADDR) 0)
+       {
+         struct symtab_and_line sal;
+
+         tui_update_source_windows_with_addr (addr);
+         sal = find_pc_line (addr, 0);
+          if (sal.symtab)
+             tui_update_locator_filename (sal.symtab->filename);
+          else
+             tui_update_locator_filename ("??");
+       }
+    }
+}
+
+
+
+/* Function to display source in the source window.  This function
+   initializes the horizontal scroll to 0.  */
+void
+tui_update_source_window (struct tui_win_info * win_info, struct symtab *s,
+                         union tui_line_or_address line_or_addr, int noerror)
+{
+  win_info->detail.source_info.horizontal_offset = 0;
+  tui_update_source_window_as_is (win_info, s, line_or_addr, noerror);
+
+  return;
+}
+
+
+/* Function to display source in the source/asm window.  This function
+   shows the source as specified by the horizontal offset.  */
+void
+tui_update_source_window_as_is (struct tui_win_info * win_info, struct symtab *s,
+                               union tui_line_or_address line_or_addr, int noerror)
+{
+  enum tui_status ret;
+
+  if (win_info->generic.type == SRC_WIN)
+    ret = tui_set_source_content (s, line_or_addr.line_no, noerror);
+  else
+    ret = tui_set_disassem_content (line_or_addr.addr);
+
+  if (ret == TUI_FAILURE)
+    {
+      tui_clear_source_content (win_info, EMPTY_SOURCE_PROMPT);
+      tui_clear_exec_info_content (win_info);
+    }
+  else
+    {
+      tui_update_breakpoint_info (win_info, 0);
+      tui_show_source_content (win_info);
+      tui_update_exec_info (win_info);
+      if (win_info->generic.type == SRC_WIN)
+       {
+         struct symtab_and_line sal;
+         
+         sal.line = line_or_addr.line_no +
+           (win_info->generic.content_size - 2);
+         sal.symtab = s;
+         set_current_source_symtab_and_line (&sal);
+         /*
+            ** If the focus was in the asm win, put it in the src
+            ** win if we don't have a split layout
+          */
+         if (tui_win_with_focus () == TUI_DISASM_WIN &&
+             tui_current_layout () != SRC_DISASSEM_COMMAND)
+           tui_set_win_focus_to (TUI_SRC_WIN);
+       }
+    }
+
+
+  return;
+}
+
+
+/* Function to ensure that the source and/or disassemly windows
+   reflect the input address.  */
+void
+tui_update_source_windows_with_addr (CORE_ADDR addr)
+{
+  if (addr != 0)
+    {
+      struct symtab_and_line sal;
+      union tui_line_or_address l;
+      
+      switch (tui_current_layout ())
+       {
+       case DISASSEM_COMMAND:
+       case DISASSEM_DATA_COMMAND:
+         tui_show_disassem (addr);
+         break;
+       case SRC_DISASSEM_COMMAND:
+         tui_show_disassem_and_update_source (addr);
+         break;
+       default:
+         sal = find_pc_line (addr, 0);
+         l.line_no = sal.line;
+         tui_show_symtab_source (sal.symtab, l, FALSE);
+         break;
+       }
+    }
+  else
+    {
+      int i;
+
+      for (i = 0; i < (tui_source_windows ())->count; i++)
+       {
+         struct tui_win_info * win_info = (struct tui_win_info *) (tui_source_windows ())->list[i];
+
+         tui_clear_source_content (win_info, EMPTY_SOURCE_PROMPT);
+         tui_clear_exec_info_content (win_info);
+       }
+    }
+}
+
+/* Function to ensure that the source and/or disassemly windows
+   reflect the input address.  */
+void
+tui_update_source_windows_with_line (struct symtab *s, int line)
+{
+  CORE_ADDR pc;
+  union tui_line_or_address l;
+  
+  switch (tui_current_layout ())
+    {
+    case DISASSEM_COMMAND:
+    case DISASSEM_DATA_COMMAND:
+      find_line_pc (s, line, &pc);
+      tui_update_source_windows_with_addr (pc);
+      break;
+    default:
+      l.line_no = line;
+      tui_show_symtab_source (s, l, FALSE);
+      if (tui_current_layout () == SRC_DISASSEM_COMMAND)
+       {
+         find_line_pc (s, line, &pc);
+         tui_show_disassem (pc);
+       }
+      break;
+    }
+
+  return;
+}
+
+void
+tui_clear_source_content (struct tui_win_info * win_info, int display_prompt)
+{
+  if (win_info != NULL)
+    {
+      int i;
+
+      win_info->generic.content_in_use = FALSE;
+      tui_erase_source_content (win_info, display_prompt);
+      for (i = 0; i < win_info->generic.content_size; i++)
+       {
+         struct tui_win_element * element =
+         (struct tui_win_element *) win_info->generic.content[i];
+         element->which_element.source.has_break = FALSE;
+         element->which_element.source.is_exec_point = FALSE;
+       }
+    }
+}
+
+
+void
+tui_erase_source_content (struct tui_win_info * win_info, int display_prompt)
+{
+  int x_pos;
+  int half_width = (win_info->generic.width - 2) / 2;
+
+  if (win_info->generic.handle != (WINDOW *) NULL)
+    {
+      werase (win_info->generic.handle);
+      tui_check_and_display_highlight_if_needed (win_info);
+      if (display_prompt == EMPTY_SOURCE_PROMPT)
+       {
+         char *no_src_str;
+
+         if (win_info->generic.type == SRC_WIN)
+           no_src_str = NO_SRC_STRING;
+         else
+           no_src_str = NO_DISASSEM_STRING;
+         if (strlen (no_src_str) >= half_width)
+           x_pos = 1;
+         else
+           x_pos = half_width - strlen (no_src_str);
+         mvwaddstr (win_info->generic.handle,
+                    (win_info->generic.height / 2),
+                    x_pos,
+                    no_src_str);
+
+         /* elz: added this function call to set the real contents of
+            the window to what is on the  screen, so that later calls
+            to refresh, do display
+            the correct stuff, and not the old image */
+
+         tui_set_source_content_nil (win_info, no_src_str);
+       }
+      tui_refresh_win (&win_info->generic);
+    }
+}
+
+
+/* Redraw the complete line of a source or disassembly window.  */
+static void
+tui_show_source_line (struct tui_win_info * win_info, int lineno)
+{
+  struct tui_win_element * line;
+  int x, y;
+
+  line = (struct tui_win_element *) win_info->generic.content[lineno - 1];
+  if (line->which_element.source.is_exec_point)
+    wattron (win_info->generic.handle, A_STANDOUT);
+
+  mvwaddstr (win_info->generic.handle, lineno, 1,
+             line->which_element.source.line);
+  if (line->which_element.source.is_exec_point)
+    wattroff (win_info->generic.handle, A_STANDOUT);
+
+  /* Clear to end of line but stop before the border.  */
+  getyx (win_info->generic.handle, y, x);
+  while (x + 1 < win_info->generic.width)
+    {
+      waddch (win_info->generic.handle, ' ');
+      getyx (win_info->generic.handle, y, x);
+    }
+}
+
+void
+tui_show_source_content (struct tui_win_info * win_info)
+{
+  if (win_info->generic.content_size > 0)
+    {
+      int lineno;
+
+      for (lineno = 1; lineno <= win_info->generic.content_size; lineno++)
+        tui_show_source_line (win_info, lineno);
+    }
+  else
+    tui_erase_source_content (win_info, TRUE);
+
+  tui_check_and_display_highlight_if_needed (win_info);
+  tui_refresh_win (&win_info->generic);
+  win_info->generic.content_in_use = TRUE;
+}
+
+
+/* Scroll the source forward or backward horizontally.  */
+void
+tui_horizontal_source_scroll (struct tui_win_info * win_info,
+                             enum tui_scroll_direction direction,
+                             int num_to_scroll)
+{
+  if (win_info->generic.content != NULL)
+    {
+      int offset;
+      struct symtab *s;
+      struct symtab_and_line cursal = get_current_source_symtab_and_line ();
+
+      if (cursal.symtab == (struct symtab *) NULL)
+       s = find_pc_symtab (get_frame_pc (deprecated_selected_frame));
+      else
+       s = cursal.symtab;
+
+      if (direction == LEFT_SCROLL)
+       offset = win_info->detail.source_info.horizontal_offset + num_to_scroll;
+      else
+       {
+         if ((offset =
+            win_info->detail.source_info.horizontal_offset - num_to_scroll) < 0)
+           offset = 0;
+       }
+      win_info->detail.source_info.horizontal_offset = offset;
+      tui_update_source_window_as_is (win_info, s,
+                                     ((struct tui_win_element *)
+                                      win_info->generic.content[0])->which_element.source.line_or_addr,
+                                     FALSE);
+    }
+
+  return;
+}
+
+
+/* Set or clear the has_break flag in the line whose line is line_no.  */
+void
+tui_set_is_exec_point_at (union tui_line_or_address l, struct tui_win_info * win_info)
+{
+  int changed = 0;
+  int i;
+  tui_win_content content = (tui_win_content) win_info->generic.content;
+
+  i = 0;
+  while (i < win_info->generic.content_size)
+    {
+      int new_state;
+
+      if (content[i]->which_element.source.line_or_addr.addr == l.addr)
+        new_state = TRUE;
+      else
+       new_state = FALSE;
+      if (new_state != content[i]->which_element.source.is_exec_point)
+        {
+          changed++;
+          content[i]->which_element.source.is_exec_point = new_state;
+          tui_show_source_line (win_info, i + 1);
+        }
+      i++;
+    }
+  if (changed)
+    tui_refresh_win (&win_info->generic);
+}
+
+/* Update the execution windows to show the active breakpoints.
+   This is called whenever a breakpoint is inserted, removed or
+   has its state changed.  */
+void
+tui_update_all_breakpoint_info (void)
+{
+  struct tui_list *list = tui_source_windows ();
+  int i;
+
+  for (i = 0; i < list->count; i++)
+    {
+      struct tui_win_info * win = (struct tui_win_info *) list->list[i];
+
+      if (tui_update_breakpoint_info (win, FALSE))
+        {
+          tui_update_exec_info (win);
+        }
+    }
+}
+
+
+/* Scan the source window and the breakpoints to update the
+   has_break information for each line.
+   Returns 1 if something changed and the execution window
+   must be refreshed.  */
+int
+tui_update_breakpoint_info (struct tui_win_info * win, int current_only)
+{
+  int i;
+  int need_refresh = 0;
+  struct tui_source_info * src = &win->detail.source_info;
+
+  for (i = 0; i < win->generic.content_size; i++)
+    {
+      struct breakpoint *bp;
+      extern struct breakpoint *breakpoint_chain;
+      int mode;
+      struct tui_source_element* line;
+
+      line = &((struct tui_win_element *) win->generic.content[i])->which_element.source;
+      if (current_only && !line->is_exec_point)
+         continue;
+
+      /* Scan each breakpoint to see if the current line has something to
+         do with it.  Identify enable/disabled breakpoints as well as
+         those that we already hit.  */
+      mode = 0;
+      for (bp = breakpoint_chain;
+           bp != (struct breakpoint *) NULL;
+           bp = bp->next)
+        {
+          if ((win == TUI_SRC_WIN
+               && bp->source_file
+               && (strcmp (src->filename, bp->source_file) == 0)
+               && bp->line_number == line->line_or_addr.line_no)
+              || (win == TUI_DISASM_WIN
+                  && bp->loc->address == line->line_or_addr.addr))
+            {
+              if (bp->enable_state == bp_disabled)
+                mode |= TUI_BP_DISABLED;
+              else
+                mode |= TUI_BP_ENABLED;
+              if (bp->hit_count)
+                mode |= TUI_BP_HIT;
+              if (bp->cond)
+                mode |= TUI_BP_CONDITIONAL;
+              if (bp->type == bp_hardware_breakpoint)
+                mode |= TUI_BP_HARDWARE;
+            }
+        }
+      if (line->has_break != mode)
+        {
+          line->has_break = mode;
+          need_refresh = 1;
+        }
+    }
+  return need_refresh;
+}
+
+
+/* Function to initialize the content of the execution info window,
+   based upon the input window which is either the source or
+   disassembly window.  */
+enum tui_status
+tui_set_exec_info_content (struct tui_win_info * win_info)
+{
+  enum tui_status ret = TUI_SUCCESS;
+
+  if (win_info->detail.source_info.execution_info != (struct tui_gen_win_info *) NULL)
+    {
+      struct tui_gen_win_info * exec_info_ptr = win_info->detail.source_info.execution_info;
+
+      if (exec_info_ptr->content == NULL)
+       exec_info_ptr->content =
+         (void **) tui_alloc_content (win_info->generic.height,
+                                        exec_info_ptr->type);
+      if (exec_info_ptr->content != NULL)
+       {
+         int i;
+
+          tui_update_breakpoint_info (win_info, 1);
+         for (i = 0; i < win_info->generic.content_size; i++)
+           {
+             struct tui_win_element * element;
+             struct tui_win_element * src_element;
+              int mode;
+
+             element = (struct tui_win_element *) exec_info_ptr->content[i];
+             src_element = (struct tui_win_element *) win_info->generic.content[i];
+
+              memset(element->which_element.simple_string, ' ',
+                     sizeof(element->which_element.simple_string));
+              element->which_element.simple_string[TUI_EXECINFO_SIZE - 1] = 0;
+
+             /* Now update the exec info content based upon the state
+                 of each line as indicated by the source content.  */
+              mode = src_element->which_element.source.has_break;
+              if (mode & TUI_BP_HIT)
+                element->which_element.simple_string[TUI_BP_HIT_POS] =
+                  (mode & TUI_BP_HARDWARE) ? 'H' : 'B';
+              else if (mode & (TUI_BP_ENABLED | TUI_BP_DISABLED))
+                element->which_element.simple_string[TUI_BP_HIT_POS] =
+                  (mode & TUI_BP_HARDWARE) ? 'h' : 'b';
+
+              if (mode & TUI_BP_ENABLED)
+                element->which_element.simple_string[TUI_BP_BREAK_POS] = '+';
+              else if (mode & TUI_BP_DISABLED)
+                element->which_element.simple_string[TUI_BP_BREAK_POS] = '-';
+
+              if (src_element->which_element.source.is_exec_point)
+                element->which_element.simple_string[TUI_EXEC_POS] = '>';
+           }
+         exec_info_ptr->content_size = win_info->generic.content_size;
+       }
+      else
+       ret = TUI_FAILURE;
+    }
+
+  return ret;
+}
+
+
+void
+tui_show_exec_info_content (struct tui_win_info * win_info)
+{
+  struct tui_gen_win_info * exec_info = win_info->detail.source_info.execution_info;
+  int cur_line;
+
+  werase (exec_info->handle);
+  tui_refresh_win (exec_info);
+  for (cur_line = 1; (cur_line <= exec_info->content_size); cur_line++)
+    mvwaddstr (exec_info->handle,
+              cur_line,
+              0,
+              ((struct tui_win_element *)
+               exec_info->content[cur_line - 1])->which_element.simple_string);
+  tui_refresh_win (exec_info);
+  exec_info->content_in_use = TRUE;
+}
+
+
+void
+tui_erase_exec_info_content (struct tui_win_info * win_info)
+{
+  struct tui_gen_win_info * exec_info = win_info->detail.source_info.execution_info;
+
+  werase (exec_info->handle);
+  tui_refresh_win (exec_info);
+}
+
+void
+tui_clear_exec_info_content (struct tui_win_info * win_info)
+{
+  win_info->detail.source_info.execution_info->content_in_use = FALSE;
+  tui_erase_exec_info_content (win_info);
+
+  return;
+}
+
+/* Function to update the execution info window.  */
+void
+tui_update_exec_info (struct tui_win_info * win_info)
+{
+  tui_set_exec_info_content (win_info);
+  tui_show_exec_info_content (win_info);
+}
+
+enum tui_status
+tui_alloc_source_buffer (struct tui_win_info *win_info)
+{
+  char *src_line_buf;
+  int i, line_width, max_lines;
+  enum tui_status ret = TUI_FAILURE;
+
+  max_lines = win_info->generic.height;        /* less the highlight box */
+  line_width = win_info->generic.width - 1;
+  /*
+     ** Allocate the buffer for the source lines.  Do this only once since they
+     ** will be re-used for all source displays.  The only other time this will
+     ** be done is when a window's size changes.
+   */
+  if (win_info->generic.content == NULL)
+    {
+      src_line_buf = (char *) xmalloc ((max_lines * line_width) * sizeof (char));
+      if (src_line_buf == (char *) NULL)
+       fputs_unfiltered (
+          "Unable to Allocate Memory for Source or Disassembly Display.\n",
+                          gdb_stderr);
+      else
+       {
+         /* allocate the content list */
+         if ((win_info->generic.content =
+         (void **) tui_alloc_content (max_lines, SRC_WIN)) == NULL)
+           {
+             xfree (src_line_buf);
+             src_line_buf = (char *) NULL;
+             fputs_unfiltered (
+                                "Unable to Allocate Memory for Source or Disassembly Display.\n",
+                                gdb_stderr);
+           }
+       }
+      for (i = 0; i < max_lines; i++)
+       ((struct tui_win_element *)
+        win_info->generic.content[i])->which_element.source.line =
+         src_line_buf + (line_width * i);
+      ret = TUI_SUCCESS;
+    }
+  else
+    ret = TUI_SUCCESS;
+
+  return ret;
+}
+
+
+/* Answer whether the a particular line number or address is displayed
+   in the current source window.  */
+int
+tui_line_is_displayed (int line, struct tui_win_info * win_info,
+                      int check_threshold)
+{
+  int is_displayed = FALSE;
+  int i, threshold;
+
+  if (check_threshold)
+    threshold = SCROLL_THRESHOLD;
+  else
+    threshold = 0;
+  i = 0;
+  while (i < win_info->generic.content_size - threshold && !is_displayed)
+    {
+      is_displayed = (((struct tui_win_element *)
+                     win_info->generic.content[i])->which_element.source.line_or_addr.line_no
+                    == (int) line);
+      i++;
+    }
+
+  return is_displayed;
+}
+
+
+/* Answer whether the a particular line number or address is displayed
+   in the current source window.  */
+int
+tui_addr_is_displayed (CORE_ADDR addr, struct tui_win_info * win_info,
+                   int check_threshold)
+{
+  int is_displayed = FALSE;
+  int i, threshold;
+
+  if (check_threshold)
+    threshold = SCROLL_THRESHOLD;
+  else
+    threshold = 0;
+  i = 0;
+  while (i < win_info->generic.content_size - threshold && !is_displayed)
+    {
+      is_displayed = (((struct tui_win_element *)
+                     win_info->generic.content[i])->which_element.source.line_or_addr.addr
+                    == addr);
+      i++;
+    }
+
+  return is_displayed;
+}
+
+
+/*****************************************
+** STATIC LOCAL FUNCTIONS               **
+******************************************/
diff --git a/gdb/tui/tui-winsource.h b/gdb/tui/tui-winsource.h
new file mode 100644 (file)
index 0000000..e64589b
--- /dev/null
@@ -0,0 +1,73 @@
+/* TUI display source/assembly window.
+
+   Copyright 1998, 1999, 2000, 2001, 2002, 2004 Free Software
+   Foundation, Inc.
+
+   Contributed by Hewlett-Packard Company.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef TUI_SOURCEWIN_H
+#define TUI_SOURCEWIN_H
+
+#include "tui/tui-data.h"
+
+struct tui_win_info;
+
+/* Update the execution windows to show the active breakpoints.  This
+   is called whenever a breakpoint is inserted, removed or has its
+   state changed.  */
+extern void tui_update_all_breakpoint_info (void);
+
+/* Scan the source window and the breakpoints to update the hasBreak
+   information for each line.  Returns 1 if something changed and the
+   execution window must be refreshed.  */
+extern int tui_update_breakpoint_info (struct tui_win_info * win,
+                                      int current_only);
+
+/* Function to display the "main" routine.  */
+extern void tui_display_main (void);
+extern void tui_update_source_window (struct tui_win_info *, struct symtab *,
+                                     union tui_line_or_address, int);
+extern void tui_update_source_window_as_is (struct tui_win_info *,
+                                           struct symtab *,
+                                           union tui_line_or_address, int);
+extern void tui_update_source_windows_with_addr (CORE_ADDR);
+extern void tui_update_source_windows_with_line (struct symtab *, int);
+extern void tui_clear_source_content (struct tui_win_info *, int);
+extern void tui_erase_source_content (struct tui_win_info *, int);
+extern void tui_show_source_content (struct tui_win_info *);
+extern void tui_horizontal_source_scroll (struct tui_win_info *,
+                                         enum tui_scroll_direction, int);
+extern enum tui_status tui_set_exec_info_content (struct tui_win_info *);
+extern void tui_show_exec_info_content (struct tui_win_info *);
+extern void tui_erase_exec_info_content (struct tui_win_info *);
+extern void tui_clear_exec_info_content (struct tui_win_info *);
+extern void tui_update_exec_info (struct tui_win_info *);
+
+extern void tui_set_is_exec_point_at (union tui_line_or_address,
+                                     struct tui_win_info *);
+extern enum tui_status tui_alloc_source_buffer (struct tui_win_info *);
+extern int tui_line_is_displayed (int, struct tui_win_info *, int);
+extern int tui_addr_is_displayed (CORE_ADDR, struct tui_win_info *, int);
+
+
+/* Constant definitions. */
+#define        SCROLL_THRESHOLD            2   /* threshold for lazy scroll */
+
+#endif
diff --git a/sim/testsuite/sim/mips/ChangeLog b/sim/testsuite/sim/mips/ChangeLog
new file mode 100644 (file)
index 0000000..67e7bfa
--- /dev/null
@@ -0,0 +1,5 @@
+2004-01-26  Chris Demetriou  <cgd@broadcom.com>
+
+       * basic.exp: New file.
+       * testutils.inc: New file.
+       * sanity.s: New file.
diff --git a/sim/testsuite/sim/mips/basic.exp b/sim/testsuite/sim/mips/basic.exp
new file mode 100644 (file)
index 0000000..63dc086
--- /dev/null
@@ -0,0 +1,26 @@
+# MIPS simulator instruction tests
+
+# As gross as it is, we unset the linker script specifid by the target
+# board.  The MIPS libgloss linker scripts include libgcc (and possibly
+# other libraries), which the linker (used to link these tests rather
+# than the compiler) can't necessarily find.
+unset_currtarget_info ldscript
+
+# Only test mips*-elf (e.g., no mips-linux), and only test if the target
+# board really is a simulator (sim tests don't work on real HW).
+if {[istarget mips*-elf] && [board_info target exists is_simulator]} {
+
+    if {[istarget mipsisa64*-elf]} {
+       set models "mips1 mips2 mips3 mips4 mips32 mips64"
+    } elseif {[istarget mipsisa32*-elf]} {
+       set models "mips1 mips2 mips32"
+    } elseif {[istarget mips64*-elf]} {
+       set models "mips1 mips2 mips3"
+    } else {
+       # fall back to just testing mips1 code.
+       set models "mips1"
+    }
+    set cpu_option -march
+
+    run_sim_test sanity.s $models
+}
diff --git a/sim/testsuite/sim/mips/sanity.s b/sim/testsuite/sim/mips/sanity.s
new file mode 100644 (file)
index 0000000..74551ed
--- /dev/null
@@ -0,0 +1,20 @@
+# mips test sanity, expected to pass.
+# mach:         all
+# as:          -mabi=eabi
+# ld:          -N -Ttext=0x80010000
+# output:      *\\npass\\n
+
+       .include "testutils.inc"
+
+       setup
+
+       .set noreorder
+
+       .ent DIAG
+DIAG:
+
+       writemsg "Sanity is good!"
+
+       pass
+
+       .end DIAG
diff --git a/sim/testsuite/sim/mips/testutils.inc b/sim/testsuite/sim/mips/testutils.inc
new file mode 100644 (file)
index 0000000..f111f79
--- /dev/null
@@ -0,0 +1,149 @@
+# MIPS simulator testsuite utility functions.
+# Copyright (C) 2004 Free Software Foundation, Inc.
+# Contributed by Chris Demetriou of Broadcom Corporation.
+#
+# This file is part of the GNU simulators.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+
+# $1, $4, $5, %6, are used as temps by the macros defined here.
+
+       .macro writemsg msg
+       .data
+901:   .ascii  "\msg\n"
+902:
+       .previous
+       la      $5, 901b
+       li      $6, 902b - 901b
+       .set push
+       .set noreorder
+       jal     _dowrite
+       li      $4, 0
+       .set pop
+       .endm
+
+
+       # The MIPS simulator uses "break 0x3ff" as the code to exit,
+       # with the return value in $4 (a0).
+       .macro exit rc
+       li      $4, \rc
+       break   0x3ff
+       .endm
+
+
+       .macro setup
+
+       .global _start
+       .ent _start
+_start:
+       .set push
+       .set noreorder
+       j       DIAG
+       nop
+       .set pop
+       .end _start
+
+       .global _fail
+       .ent _fail
+_fail:
+       writemsg "fail"
+       exit 1
+       .end _fail
+
+       .global _pass
+       .ent _pass
+_pass:
+       writemsg "pass"
+       exit 0
+       .end _pass
+
+       # The MIPS simulator can use multiple different monitor types,
+       # so we hard-code the simulator "write" reserved instruction opcode,
+       # rather than jumping to a vector that invokes it.  The operation
+       # expects RA to point to the location at which to continue
+       # after writing.
+       .global _dowrite
+       .ent _dowrite
+_dowrite:
+       # Write opcode (reserved instruction).  See sim_monitor and its
+       # callers in sim/mips/interp.c.
+       .word   0x00000005 | ((8 << 1) << 6)
+       .end _dowrite
+
+       .endm   # setup
+
+
+       .macro pass
+       .set push
+       .set noreorder
+       j       _pass
+       nop     
+       .set pop
+       .endm
+
+
+       .macro fail
+       .set push
+       .set noreorder
+       j       _fail
+       nop     
+       .set pop
+       .endm
+
+
+       .macro load32 reg, val
+       li      \reg, \val
+       .endm
+
+
+       .macro load64 reg, val
+       dli     \reg, \val
+       .endm
+
+
+       .macro loadaddr reg, addr
+       la      \reg, \addr
+       .endm
+
+
+       .macro checkreg reg, expreg
+       .set push
+       .set noat
+       .set noreorder
+       beq     \expreg, \reg, 901f
+       nop
+       fail
+901:
+       .set pop
+       .endm
+
+
+       .macro check32 reg, val
+       .set push
+       .set noat
+       load32  $1, \val
+       checkreg \reg, $1
+       .set pop
+       .endm
+
+
+       .macro check64 reg, val
+       .set push
+       .set noat
+       load64  $1, \val
+       checkreg \reg, $1
+       .set pop
+       .endm