[geany/geany-plugins] 0e1fa2: scope - added Registers, small changes and fixes; v0.90

Dimitar Zhekov git-noreply at xxxxx
Mon Jun 24 18:07:01 UTC 2013


Branch:      refs/heads/master
Author:      Dimitar Zhekov <dimitar.zhekov at gmail.com>
Committer:   Dimitar Zhekov <dimitar.zhekov at gmail.com>
Date:        Mon, 24 Jun 2013 18:07:01 UTC
Commit:      0e1fa2d3980cf1891b2d9603e522d3fd827da23d
             https://github.com/geany/geany-plugins/commit/0e1fa2d3980cf1891b2d9603e522d3fd827da23d

Log Message:
-----------
scope - added Registers, small changes and fixes; v0.90


Modified Paths:
--------------
    scope/ChangeLog
    scope/NEWS
    scope/NOTES
    scope/TODO
    scope/data/scope.glade
    scope/docs/codes.html
    scope/docs/scope.html
    scope/src/Makefile.am
    scope/src/break.c
    scope/src/common.h
    scope/src/conterm.c
    scope/src/debug.c
    scope/src/debug.h
    scope/src/inspect.c
    scope/src/inspect.h
    scope/src/local.c
    scope/src/parse.c
    scope/src/program.c
    scope/src/register.c
    scope/src/register.h
    scope/src/scope.c
    scope/src/stack.c
    scope/src/thread.c
    scope/src/utils.c
    scope/src/utils.h
    scope/src/views.c
    scope/src/views.h

Modified: scope/ChangeLog
37 files changed, 37 insertions(+), 0 deletions(-)
===================================================================
@@ -1,3 +1,40 @@
+2013-06-24  Dimitar Zhekov  <dimitar.zhekov at gmail.com>
+
+ * data/scope.glade, docs/codes.html, docs/scope.html,
+   src/Makefile.am, src/break.c, src/common.h, src/debug.c,
+   src/inspect.c, src/inspect.h, src/parse.c, src/program.c,
+   src/register.c, src/register.h, src/scope.c, src/stack.c,
+   src/thread.c, src/views.c, src/views.h:
+   Added Registers next to Inspect.
+ * docs/codes.html:
+   Small syntax changes, explanation about the <> values.
+ * docs/scope.html, src/break.c, src/debug.c, src/debug.h,
+   src/local.c, src/stack.c, src/views.c, src/thread.c,
+   src/views.c, src/views.h:
+   Small syntax changes/fixes.
+ * src/conterm.c:
+   Clear the console with a single function call.
+ * src/inspect.c:
+   Fixed hexadecimal format.
+   Only set "editable" if an eleemnt is selected.
+ * src/common.h, src/local.src/utils.c, src/utils.h:
+   A (mostly) common mechanism to send/receive thread+frame.
+ * src/utils.c:
+   Display win32 error texts instead of codes.
+ * src/views.c:
+   Changing the thread/frame honours "Update all views".
+   Fixed the automatic text selection when the command dialog
+   is invoked.
+ * docs/scope.html, src/scope.c:
+   Increased version to 0.90.
+
+
+2013-05-23  Dimitar Zhekov  <dimitar.zhekov at gmail.com>
+
+ * scope/src/inspect.c:
+   Fixed new value receiving after Format change.
+
+
 2013-05-17  Dimitar Zhekov  <dimitar.zhekov at gmail.com>
 
  * scope/src/prefs.c:


Modified: scope/NEWS
9 files changed, 9 insertions(+), 0 deletions(-)
===================================================================
@@ -1,3 +1,12 @@
+Scope 0.90 (2013-05-17)
+
+    * Added Registers next to Inspect.
+
+    * Display win32 error texts instead of codes.
+
+    * Changing the thread/frame honours "Update all views".
+
+
 Scope 0.89 (2013-05-17)
 
     * Small fixes and improvements. This should be the last version


Modified: scope/NOTES
79 files changed, 31 insertions(+), 48 deletions(-)
===================================================================
@@ -1,3 +1,7 @@
+register modified is 07 since we may have watches and inspects containing
+registers, and changing a register ($dh, $mm1.uint64) may change another
+($dx, $st1); even if local variables can't be changed, that's enough
+
 when switching to stack...memory and update is not possible, the subpage
 contents will be kept if an update command for this page was sent on the
 last thread stop/changed; otherwise it'll be cleared
@@ -5,14 +9,14 @@ last thread stop/changed; otherwise it'll be cleared
 "^done,value=\"", '7' matches 07-var-assign, handled later as "^done", '7'
 
 the only way to fix unnecessary inspect drop target expansion is to block
-INTO, so deriving GtkTreeStore and altering GtkTreeDragDest make no sense
+INTO, so deriving GtkTreeStore and altering GtkTreeDragDest makes no sense
 
 "new_children: If new children were added to a dynamic varobj [...]"
 "A varobj's contents may be provided by a Python-based pretty-printer
 In this case the varobj is known as a dynamic varobj" - not supported
 
 shift-clicking send/busy to send a command without closing the dialog can be
-implemented, but is very ugly; shortcut for GDB command plus typing in the
+implemented, but is very ugly; shortcut for "GDB command" plus typing in the
 debug console should suffice
 
 gtk tooltips send lots of queries, and can't be explicitly shown/hidden;
@@ -28,21 +32,21 @@ mixed with the program stdin/stdout, leading to gigo
 in foreground execution, GDB waits for the program to report that _some_
 thread has stopped before prompting for another command
 
-clicking a button with response 0, and then gtk_dialog_response(ACCEPT) via
-program code or clicking an accept button, may still generate 0
+clicking a button with response 0, and then clicking an accept button or
+gtk_dialog_response(ACCEPT), may generate 0 instead of accept
 
 breakpoints don't need unapply: they can be disabled, and all relevant
 columns are editable
 
--var-create for globals symbols allows any frame
+-var-create for global symbols allows any frame
 -set-update-range seems to have no effect on my system
 
-global object may be evaluated (including as variable objects) in hang
+global objects may be evaluated (including as variable objects) in hang
 state, but modification requires running inferior
 
 parse with string in VR_COMPACT / VR_NEUTRAL is slower for texts with less
 than 100 characters, but with such shorts texts, the difference is
-insignificant; with large texts, using string is faster, but not much
+insignificant; for large texts, using string is faster, but not much
 
 CPU load on F8 with vte console: ~88%
 with context: ~80%, null output: ~75%
@@ -50,11 +54,11 @@ with context: ~80%, null output: ~75%
 win~1 hang with poll_pipe(): 1 second for 3h25m
 win~1 send on 50ms: 2 seconds for 1h, 1445 KB sent
 
-GtkTextView with wrapping CHAR: the last character of a wrapped line can not
-be selected with the mouse, keyboard selection is ok
+GtkTextView with wrapping CHAR: the last character of a wrapped line can be
+selected with the mouse only by moving to the next line
 
-Geany under Win~1 with FF also running eats 7-8% CPU time other
-applications/conditions may cause this CPU load too
+Geany under Win~1, with FF also running, eats 7-8% CPU time, other
+applications/conditions may cause such CPU load too; scope doesn't matter
 
 http://sourceware.org/bugzilla/show_bug.cgi?id=9659
 
@@ -65,7 +69,7 @@ set print elements 10: "\a01\002\003\004\005\006\a\b\t\n"...
 '\000' <repeats 100 times>, '\001' <repeats 100 times>
 
 GDB does specify that individual breakpoint location may be enabled or
-disabled, but not deleted; no mention of condition, ignore, script though
+disabled, but not deleted; no mention of condition/ignore/script though
 
 pending breakpoints are handled either at thread stopped, or by async
 modified message; parsing =library-loaded seems pointless
@@ -82,10 +86,6 @@ count		-i	-break-passcount	-break-after
 script = -break-commands
 fast trace = -break-insert -a -h
 
-source files check list:
-	:break :debug :inspect :local :menu :parse :plugme :prefs
-	:program :scope :stack :thread :unused :utils :views :watch
-
 " " is valid executable name, but not valid source name - gdb requires
 certain suffixes (.c .c++ etc.); thus we can validate_column(file, TRUE)
 
@@ -94,27 +94,20 @@ project close: geany close message, then scope message
 
 gdb manual states that "which commands will work in the context of a running
 thread is highly target dependent", but "commands that try to operate on
-thread's stack will not work, on any target"; some commands are ds_sendable
-or ds_not_busy, even if unlikely to execute (for example global watchpoint)
-
-scid is required because the list positions are async-gdb-output volatile
-
-there is no reason to keep the stack frame selection, the upper-frame values
-are unlikely to change
+thread's stack will not work, on any target"; some commands are DS_SENDABLE
+or DS_NOT_BUSY, even if unlikely to execute (like a global watchpoint)
 
-there is no reason to clear thread list on regular thread info, the async
-messages keep it current
+scid is required because all list positions are async-gdb-output volatile
 
 break filename may be specified as known source name (test.c) or absolute
-name (/home/build/test.c); names relative to inferior working directory
-do not work any more than these relative to gdb directory
+name (/home/build/test.c); neither inferior nor gdb relative names work
 
 would be nice to have 02-thread-info to fully refresh the thread list, if we
-missed a thread message, but needs effort, and we compute gdb status (and
-send commands) based on threads, so that's a circular dependency
+missed a thread message, but needs some effort, and we compute gdb status
+(and send commands) based on threads, so that'll be very tricky
 
-gdb recommends full refresh after error but errors in refresh (04) commands
-must be ignored to avoid an endless loop
+gdb recommends full refresh after error, but at least the errors from
+refresh (04) commands errors must be ignored avoid an endless loop
 
 applying break/watchpoints to a thread is promlematic: -break-list does not
 contain such info, and the thread identifiers are different on restart
@@ -122,30 +115,20 @@ contain such info, and the thread identifiers are different on restart
 tested with "unsuccessful" program pty creation - no idea where the terminal
 I/O comes from or goes to
 
-we don't reload terminal prefs on save settings since they are either empty,
-for new file, or old (the signal is before save)
+we don't reload terminal prefs on save settings since the signal is before
+save and they are they are either empty (for new .conf file) or old
 
 scite mark "arrow" is actually triangle
 
-> Run in a debugger with the G_DEBUG env var set to "fatal-warnings",
-> so the program will abort and let you see where/when/how it happened.
-
--var-list-children expands an expression (or
-variable?) with a single command
-
--var-delete -c VAR deletes the children only
-
--var-info|evaluate-expression for unexpanded?
-
 --all | --thread-group N commands:
 	-exec-continue
 	-exec-interrupt
 	-exec-run
 
-"If the `--thread-group' options is specified, then
-all threads in that thread group are resumed."
+"If the `--thread-group' options is specified, then all threads in that
+thread group are resumed."
 
-*stopped "all" means all threads from this group?
+*stopped "all" means from this group or everything?
 
-running "all" does not specify a thread; the first running is "all", others
-are thread - but that's from experience only, gdb.info says nothing
+running "all" does not specify a thread/group; the first running is "all",
+others are thread - but that's from observation, gdb.info says nothing


Modified: scope/TODO
2 files changed, 2 insertions(+), 0 deletions(-)
===================================================================
@@ -1,3 +1,5 @@
+proper support for @ inspect frame
+
 various tests, source code checks etc.
 
 add clear icon to entries? not very useful


Modified: scope/data/scope.glade
172 files changed, 167 insertions(+), 5 deletions(-)
===================================================================
@@ -1197,6 +1197,99 @@
       </object>
     </child>
   </object>
+  <object class="GtkMenu" id="register_menu">
+    <child>
+      <object class="GtkImageMenuItem" id="register_refresh">
+        <property name="label">gtk-refresh</property>
+        <property name="visible">True</property>
+        <property name="use_underline">True</property>
+        <property name="use_stock">True</property>
+      </object>
+    </child>
+    <child>
+      <object class="GtkSeparatorMenuItem" id="register_separator1">
+        <property name="visible">True</property>
+      </object>
+    </child>
+    <child>
+      <object class="GtkImageMenuItem" id="register_copy">
+        <property name="label">gtk-copy</property>
+        <property name="visible">True</property>
+        <property name="use_underline">True</property>
+        <property name="use_stock">True</property>
+      </object>
+    </child>
+    <child>
+      <object class="GtkMenuItem" id="register_format">
+        <property name="visible">True</property>
+        <property name="label" translatable="yes">_Format</property>
+        <property name="use_underline">True</property>
+        <child type="submenu">
+          <object class="GtkMenu" id="register_format_menu">
+            <child>
+              <object class="GtkRadioMenuItem" id="register_format_natural">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">_Natural</property>
+                <property name="use_underline">True</property>
+              </object>
+            </child>
+            <child>
+              <object class="GtkRadioMenuItem" id="register_format_hex">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">_Hex</property>
+                <property name="use_underline">True</property>
+                <property name="group">register_format_natural</property>
+              </object>
+            </child>
+            <child>
+              <object class="GtkRadioMenuItem" id="register_format_decimal">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">_Decimal</property>
+                <property name="use_underline">True</property>
+                <property name="group">register_format_natural</property>
+              </object>
+            </child>
+            <child>
+              <object class="GtkRadioMenuItem" id="register_format_octal">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">_Octal</property>
+                <property name="use_underline">True</property>
+                <property name="group">register_format_natural</property>
+              </object>
+            </child>
+            <child>
+              <object class="GtkRadioMenuItem" id="register_format_binary">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">_Binary</property>
+                <property name="use_underline">True</property>
+                <property name="group">register_format_natural</property>
+              </object>
+            </child>
+            <child>
+              <object class="GtkRadioMenuItem" id="register_format_raw">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">_Raw</property>
+                <property name="use_underline">True</property>
+                <property name="group">register_format_natural</property>
+              </object>
+            </child>
+          </object>
+        </child>
+      </object>
+    </child>
+    <child>
+      <object class="GtkSeparatorMenuItem" id="register_separator2">
+        <property name="visible">True</property>
+      </object>
+    </child>
+    <child>
+      <object class="GtkImageMenuItem" id="register_query">
+        <property name="visible">True</property>
+        <property name="label">_Query</property>
+        <property name="use_underline">True</property>
+      </object>
+    </child>
+  </object>
   <object class="GtkMenuItem" id="popup_item">
     <property name="visible">True</property>
     <property name="label" translatable="yes">Debu_g</property>
@@ -1432,6 +1525,25 @@
       <column type="gchararray" utf8_collate="false"/>
     </columns>
   </object>
+  <object class="ScpTreeStore" id="register_store">
+    <property name="sublevels">True</property>
+    <columns>
+      <!-- column-name register_store_path -->
+      <column type="gchararray" utf8_collate="false"/>
+      <!-- column-name register_store_display -->
+      <column type="gchararray" utf8_collate="false"/>
+      <!-- column-name register_store_value -->
+      <column type="gchararray" utf8_collate="false"/>
+      <!-- column-name register_hb_mode -->
+      <column type="gint"/>
+      <!-- column-name register_store_name -->
+      <column type="gchararray" utf8_collate="false"/>
+      <!-- column-name register_store_id -->
+      <column type="gint"/>
+      <!-- column-name register_store_format -->
+      <column type="gint"/>
+    </columns>
+  </object>
   <object class="ScpTreeStore" id="command_store">
     <property name="sublevels">False</property>
     <columns>
@@ -2132,6 +2244,52 @@
       </object>
     </child>
   </object>
+  <object class="GtkFrame" id="register_page">
+    <property name="visible">True</property>
+    <property name="can_focus">True</property>
+    <property name="label_xalign">0</property>
+    <property name="shadow_type">in</property>
+    <child>
+      <object class="GtkScrolledWindow" id="register_window">
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="hscrollbar_policy">automatic</property>
+        <property name="vscrollbar_policy">automatic</property>
+        <child>
+          <object class="GtkTreeView" id="register_view">
+            <property name="can_focus">True</property>
+            <property name="model">register_store</property>
+            <property name="headers_visible">False</property>
+            <property name="headers_clickable">False</property>
+            <child>
+              <object class="GtkTreeViewColumn" id="register_name_column">
+                <property name="resizable">True</property>
+                <property name="sizing">autosize</property>
+                <child>
+                  <object class="GtkCellRendererText" id="register_name"/>
+                  <attributes>
+                    <attribute name="text">4</attribute>
+                  </attributes>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="GtkTreeViewColumn" id="register_display_column">
+                <property name="resizable">True</property>
+                <property name="expand">True</property>
+                <child>
+                  <object class="GtkCellRendererText" id="register_display"/>
+                  <attributes>
+                    <attribute name="text">1</attribute>
+                  </attributes>
+                </child>
+              </object>
+            </child>
+          </object>
+        </child>
+      </object>
+    </child>
+  </object>
   <object class="GtkDialog" id="command_dialog">
     <property name="modal">True</property>
     <property name="type_hint">normal</property>
@@ -2682,7 +2840,7 @@
                         <property name="spacing">6</property>
                         <child>
                           <object class="GtkCheckButton" id="program_delete_all_items">
-                            <property name="label" translatable="yes">_Delete all breakpoints, watches and inspects</property>
+                            <property name="label" translatable="yes">_Delete all breakpoints, watches, inspects and registers</property>
                             <property name="visible">True</property>
                             <property name="can_focus">True</property>
                             <property name="receives_default">False</property>
@@ -3772,13 +3930,17 @@
     <property name="visible">True</property>
     <property name="label" translatable="yes">Inspect</property>
   </object>
+  <object class="GtkLabel" id="register_label">
+    <property name="visible">True</property>
+    <property name="label" translatable="yes">Registers</property>
+  </object>
   <object class="GtkSizeGroup" id="program_size_group">
     <widgets>
-      <widget name="program_load_script_label"/>
-      <widget name="program_working_dir_label"/>
-      <widget name="program_environment_label"/>
-      <widget name="program_arguments_label"/>
       <widget name="program_executable_label"/>
+      <widget name="program_arguments_label"/>
+      <widget name="program_environment_label"/>
+      <widget name="program_working_dir_label"/>
+      <widget name="program_load_script_label"/>
     </widgets>
   </object>
   <object class="GtkSizeGroup" id="inspect_size_group">


Modified: scope/docs/codes.html
50 files changed, 42 insertions(+), 8 deletions(-)
===================================================================
@@ -35,6 +35,10 @@
 	<td class="tab">un/check break enabled column</td>
 	<td class="tab">set breakpoint enabled column, remark breakpoint</td></tr>
 
+<tr><td class="nowrap">02[01]<scid>-break-disable</td>
+	<td class="tab">un/check break enabled column</td>
+	<td class="tab">set breakpoint enabled column, remark breakpoint</td></tr>
+
 <tr><td class="nowrap">022<id>-break-after</td>
 	<td class="tab">breakpoint <em>Ignore</em> column edited</td>
 	<td class="tab"><id>-break-info</td></tr>
@@ -87,10 +91,22 @@
 	<td class="tab"><em>Syncronize</em> stack</td>
 	<td class="tab">select the current gdb frame</td></tr>
 
-<tr><td class="nowrap">02<tid><fid>-stack-list-variables</td>
+<tr><td class="nowrap">02<fid>-stack-list-variables</td>
 	<td class="tab"><em>Refresh</em> locals</td>
 	<td class="tab">clear locals list and load local variables into it</td></tr>
 
+<tr><td class="nowrap">02-data-list-register-names</td>
+	<td class="tab"><em>Query</em> register names</td>
+	<td class="tab">029<fid>-data-list-register-values <all></td>
+
+<tr><td class="nowrap">029<fid>-data-list-register-values</td>
+	<td class="tab"><em>Refresh</em> registers, see above</td>
+	<td class="tab">update register values</td>
+
+<tr><td class="nowrap">02<f><fid>-data-list-register-values</td>
+	<td class="tab">change register <em>Format</em></td>
+	<td class="tab">update register value and/or format</td>
+
 <tr><td class="nowrap"> </td><td class="tab"> </td><td class="tab"> </td></tr>
 
 <tr><td class="nowrap">03<scid>-data-evaluate-expression</td>
@@ -101,7 +117,7 @@
 
 <tr><td class="nowrap">04-break-list</td>
 	<td class="tab">views idle update</td>
-	<td class="tab">same as 02-break-list</td></tr>
+	<td class="tab">same as 02</td></tr>
 
 <tr><td class="nowrap">04-thread-info <id></td>
 	<td class="tab">thread created -> fetch target id</td>
@@ -121,15 +137,15 @@
 
 <tr><td class="nowrap">04<tid>-stack-list-frames</td>
 	<td class="tab">views idle update</td>
-	<td class="tab">same as 02<tid>-stack-list-frames</td></tr>
+	<td class="tab">same as 02</td></tr>
 
 <tr><td class="nowrap">04<tid>-stack-list-arguments</td>
 	<td class="tab">views idle update</td>
-	<td class="tab">same as 02<tid>-stack-list-arguments</td></tr>
+	<td class="tab">same as 02</td></tr>
 
-<tr><td class="nowrap">04<tid><fid>-stack-list-variables</td>
+<tr><td class="nowrap">04<fid>-stack-list-variables</td>
 	<td class="tab">views idle update</td>
-	<td class="tab">same as 02<tid>-stack-list-variables</td></tr>
+	<td class="tab">same as 02</td></tr>
 
 <tr><td class="nowrap">04-data-read-memory-bytes</td>
 	<td class="tab">views idle update</td>
@@ -139,6 +155,14 @@
 	<td class="tab">at stopped thread without address</td>
 	<td class="tab">fill the thread columns</td></tr>
 
+<tr><td class="nowrap">04<fid>-data-list-changed-registers</td>
+	<td class="tab">views idle update</td>
+	<td class="tab">049<fid>-data-list-register-values <changed></td>
+
+<tr><td class="nowrap">049<fid>-data-list-register-values</td>
+	<td class="tab">views idle update, see above</td>
+	<td class="tab">same as 02</td>
+
 <tr><td class="nowrap"> </td><td class="tab"> </td><td class="tab"> </td></tr>
 
 <tr><td class="nowrap">05</td>
@@ -147,11 +171,11 @@
 
 <tr><td class="nowrap">05</td>
 	<td class="tab">after temp break insert <em>location</em></td>
-	<td class="tab">-exec-run if active breaks & no errors</td></tr>
+	<td class="tab">same as above</td></tr>
 
 <tr><td class="nowrap">05</td>
 	<td class="tab">after temp break insert <em>1st loc</em></td>
-	<td class="tab">-exec-run if active breaks & no errors</td></tr>
+	<td class="tab">same as above</td></tr>
 
 <tr><td class="nowrap">05-list-features</td>
 	<td class="tab">first time gdb startup</td>
@@ -213,5 +237,15 @@
 
 </table>
 
+<br>
+
+<table>
+<tr><td><scid></td><td class="tab">internal id assigned by scope</td></tr>
+<tr><td><id></td><td class="tab">gdb id</td>
+<tr><td><tid></td><td class="tab">selected thread id</td>
+<tr><td><fid></td><td class="tab">selected thread and frame id: <length of thread id
+- 1><thread id><frame id></td></tr>
+</table>
+
 </body>
 </html>


Modified: scope/docs/scope.html
23 files changed, 16 insertions(+), 7 deletions(-)
===================================================================
@@ -51,7 +51,10 @@
 		<li><a href="#local_watch">Locals/Watches</a></li>
 		<li><a href="#console">Debug Console</a></li>
 	</ul></li>
-	<li><a href="#inspect">Inspect page</a></li>
+	<li>Side panel<ul>
+		<li><a href="#inspect">Inspect</a></li>
+		<li><a href="#register">Registers</a></li>
+	</ul></li>
 </ul></li>
 <li><a href="#preferences">Preferences</a></li>
 <li><a href="#notes">Notes</a><ul>
@@ -143,7 +146,7 @@
 Tools.</li>
 <li>Debug page in the lower panel, with subpages that display the program output, threads,
 breakpoints etc.</li>
-<li>Inspect page in the side panel.</li>
+<li>Inspect and Registers page in the side panel.</li>
 <li>Toolbar items - identical to their Debug menu counterparts.</li>
 <li>Command Dialog - to enter gdb commands. Will be closed automatically if gdb exits.</li>
 <li>A small label on the right of your Geany status bar, which displays the current debugging
@@ -412,8 +415,8 @@
 <p><b><a name="watch">Watches</a></b></p>
 
 <p>This is a flat list of expressions, evaluated each time the current thread stops or changes
-(subject to <em>update_all_views</em>), in the context of the current thread and frame. Unlike
-<em>Inspect</em>, any gdb-evaluatable expressions may be used, there is no need to apply 
+(subject to <em>Update all views</em>), in the context of the current thread and frame. Unlike
+<em>Inspect</em>, any gdb-evaluatable expressions may be used, and there is no need to apply 
 them.</p>
 
 <p><b><a name="local_watch">Locals/Watches</a></b></p>
@@ -456,7 +459,7 @@
 immediately resuming the program execution; or the prompt may be followed by asynchronous
 messages. The Scope state (Busy, Debug etc.) is more accurate.</p>
 
-<p><b><a name="inspect">Inspect Page</a></b></p>
+<p><b><a name="inspect">Inspect</a></b></p>
 
 <p>All -var-* commands except -var-update will be ignored when entered from the command line,
 because their output does not provide enough information to identify the variable object.</p>
@@ -482,6 +485,12 @@
 <p>The format and 7-bit mode are saved only for the top-level variables, not for children (but
 see <a href="#keeping_modes">Keeping modes</a>).</p>
 
+<p><b><a name="registers">Registers</a></b></p>
+
+<p>Scope will query the register names once after a program is loaded, or when the gdb
+executable is changed. If you switch to a different architecture, but your gdb name remains
+the same, invoke <em>Query</em> from the local menu.</p>
+
 <h3><a name="preferences">Preferences</a></h3>
 
 <p>Once again, trivial items are not included.</p>
@@ -491,7 +500,7 @@
 <p><em>gdb_buffer_length</em> - the maximum length of a single gdb output message. Longer
 messages will be cut, and an "overflow" will be displayed in the debug console, possibly
 followed by a few other parsing errors. Default = 16383. Actual value is (the nearest larger
-power of 2) - 1, for example 16384 becomes 65535.
+power of 2) - 1, for example 32768 becomes 65535.
 
 <p><em>gdb_wait_death</em> - hundreds of seconds to wait(3) gdb death on scope unload.
 Default = 20. When closing Geany, gdb will be destroyed by the operating system.</p>
@@ -713,7 +722,7 @@
 
 <b><a name="copyright">Copyright</a></b>
 
-<p>Scope 0.88, Copyright (C) 2013 Dimitar Toshkov Zhekov</p>
+<p>Scope 0.90, Copyright (C) 2013 Dimitar Toshkov Zhekov</p>
 
 <p>The menu and toolbar icons are from <a href="http://netbeans.org">Netbeans</a>, except for
 BreakPoint.</p>


Modified: scope/src/Makefile.am
2 files changed, 2 insertions(+), 0 deletions(-)
===================================================================
@@ -31,6 +31,8 @@ scope_la_SOURCES = \
 	prefs.h \
 	program.c \
 	program.h \
+	register.c \
+	register.h \
 	scope.c \
 	scope.h \
 	stack.c \


Modified: scope/src/break.c
4 files changed, 2 insertions(+), 2 deletions(-)
===================================================================
@@ -913,7 +913,7 @@ void on_break_toggle(G_GNUC_UNUSED const MenuItem *menu_item)
 			if (found && found != utils_atoi0(id))
 			{
 				dialogs_show_msgbox(GTK_MESSAGE_INFO,
-					_("There are two or more breakpoints at %s:%d.\n"
+					_("There are two or more breakpoints at %s:%d.\n\n"
 					"Use the breakpoint list to remove the exact one."),
 					doc->file_name, doc_line);
 				return;
@@ -1130,7 +1130,7 @@ static gboolean on_break_query_tooltip(G_GNUC_UNUSED GtkWidget *widget, gint x,
 		{
 			if (has_tip)
 				g_string_append(text, ", ");
-			g_string_append(text, func);
+			g_string_append_printf(text, "%s()", func);
 			has_tip = TRUE;
 		}
 


Modified: scope/src/common.h
2 files changed, 2 insertions(+), 0 deletions(-)
===================================================================
@@ -24,6 +24,7 @@
 extern GeanyFunctions *geany_functions;
 
 typedef struct _MenuItem MenuItem;
+#define FRAME_ARGS '0' + (int) strlen(thread_id) - 1, thread_id, frame_id
 
 #include "break.h"
 #include "conterm.h"
@@ -37,6 +38,7 @@
 #include "plugme.h"
 #include "prefs.h"
 #include "program.h"
+#include "register.h"
 #include "stack.h"
 #include "scope.h"
 #include "store.h"


Modified: scope/src/conterm.c
5 files changed, 1 insertions(+), 4 deletions(-)
===================================================================
@@ -301,10 +301,7 @@ void dc_clear(void)
 	else
 #endif
 	{
-		GtkTextIter start, end;
-
-		gtk_text_buffer_get_bounds(context, &start, &end);
-		gtk_text_buffer_delete(context, &start, &end);
+		gtk_text_buffer_set_text(context, "", -1);
 		dc_chars = 0;
 	}
 }


Modified: scope/src/debug.c
11 files changed, 6 insertions(+), 5 deletions(-)
===================================================================
@@ -581,6 +581,7 @@ static void load_program(void)
 			if (option_open_panel_on_load)
 				open_debug_panel();
 
+			registers_query_names();
 			debug_send_commands();
 		}
 		else
@@ -729,18 +730,18 @@ void debug_send_format(gint tf, const char *format, ...)
 char *debug_send_evaluate(char token, gint scid, const gchar *expr)
 {
 	char *locale = utils_get_locale_from_utf8(expr);
-	GString *string = g_string_sized_new(strlen(locale));
+	GString *escaped = g_string_sized_new(strlen(locale));
 	const char *s;
 
 	for (s = locale; *s; s++)
 	{
 		if (*s == '"' || *s == '\\')
-			g_string_append_c(string, '\\');
-		g_string_append_c(string, *s);
+			g_string_append_c(escaped, '\\');
+		g_string_append_c(escaped, *s);
 	}
 
-	debug_send_format(F, "0%c%d-data-evaluate-expression \"%s\"", token, scid, string->str);
-	g_string_free(string, TRUE);
+	debug_send_format(F, "0%c%d-data-evaluate-expression \"%s\"", token, scid, escaped->str);
+	g_string_free(escaped, TRUE);
 	return locale;
 }
 


Modified: scope/src/debug.h
3 files changed, 1 insertions(+), 2 deletions(-)
===================================================================
@@ -65,8 +65,7 @@ enum
 enum { N, T, F };
 void debug_send_command(gint tf, const char *command);
 #define debug_send_thread(command) debug_send_command(T, (command))
-void debug_send_format(gint tf, const char *format, ...)
-	G_GNUC_PRINTF(2, 3);
+void debug_send_format(gint tf, const char *format, ...) G_GNUC_PRINTF(2, 3);
 char *debug_send_evaluate(char token, gint scid, const gchar *expr);  /* == locale(expr) */
 
 void debug_init(void);


Modified: scope/src/inspect.c
45 files changed, 13 insertions(+), 32 deletions(-)
===================================================================
@@ -245,8 +245,8 @@ static gint inspect_variable_store(GtkTreeIter *iter, const ParseVariable *var)
 	return format;
 }
 
-static const char *const inspect_formats[FORMAT_COUNT] = { "natural", "decimal", "hex",
-	"octal", "binary" };
+static const char *const inspect_formats[FORMAT_COUNT] = { "natural", "decimal",
+	"hexadecimal", "octal", "binary" };
 
 void on_inspect_variable(GArray *nodes)
 {
@@ -295,7 +295,7 @@ void on_inspect_format(GArray *nodes)
 			gchar *display = inspect_redisplay(&iter, value, NULL);
 
 			scp_tree_store_set(store, &iter, INSPECT_DISPLAY, display, INSPECT_VALUE,
-				&value, INSPECT_FORMAT, format, -1);
+				value, INSPECT_FORMAT, format, -1);
 			g_free(display);
 		}
 	}
@@ -499,15 +499,6 @@ gboolean inspects_update(void)
 	return TRUE;
 }
 
-static GtkNotebook *geany_sidebar;
-static GtkWidget *inspect_page;
-
-gboolean inspects_current(void)
-{
-	gint page_num = gtk_notebook_get_current_page(geany_sidebar);
-	return gtk_notebook_get_nth_page(geany_sidebar, page_num) == inspect_page;
-}
-
 static void inspect_iter_apply(GtkTreeIter *iter, G_GNUC_UNUSED gpointer gdata)
 {
 	const char *frame;
@@ -629,15 +620,19 @@ void inspects_update_state(DebugState state)
 	static gboolean last_active = FALSE;
 	gboolean active = state != DS_INACTIVE;
 	GtkTreeIter iter;
-	const char *var1 = NULL;
-	gint numchild = 0;
 
-	if ((state & DS_SENDABLE) && gtk_tree_selection_get_selected(selection, NULL, &iter))
+	if (gtk_tree_selection_get_selected(selection, NULL, &iter))
 	{
-		scp_tree_store_get(store, &iter, INSPECT_VAR1, &var1, INSPECT_NUMCHILD, &numchild,
-			-1);
+		const char *var1 = NULL;
+		gint numchild = 0;
+
+		if (state & DS_SENDABLE)
+		{
+			scp_tree_store_get(store, &iter, INSPECT_VAR1, &var1, INSPECT_NUMCHILD,
+				&numchild, -1);
+		}
+		g_object_set(inspect_display, "editable", var1 && !numchild, NULL);
 	}
-	g_object_set(inspect_display, "editable", var1 && !numchild, NULL);
 
 	if (active != last_active)
 	{
@@ -1060,13 +1055,6 @@ static void on_inspect_menu_show(G_GNUC_UNUSED GtkWidget *widget, G_GNUC_UNUSED
 	}
 }
 
-static void on_geany_sidebar_switch_page(G_GNUC_UNUSED GtkNotebook *notebook, gpointer page,
-	G_GNUC_UNUSED gint page_num, G_GNUC_UNUSED gpointer gdata)
-{
-	if (page == inspect_page)
-		view_inspect_update();
-}
-
 void inspect_init(void)
 {
 	GtkWidget *menu;
@@ -1075,12 +1063,6 @@ void inspect_init(void)
 	jump_to_menu = GTK_CONTAINER(get_widget("inspect_jump_to_menu"));
 	apply_item = menu_item_find(inspect_menu_items, "inspect_apply");
 
-	inspect_page = get_widget("inspect_page");
-	geany_sidebar = GTK_NOTEBOOK(geany->main_widgets->sidebar_notebook);
-	g_signal_connect(geany_sidebar, "switch-page", G_CALLBACK(on_geany_sidebar_switch_page),
-		NULL);
-	gtk_notebook_append_page(geany_sidebar, inspect_page, get_widget("inspect_label"));
-
 	tree = view_connect("inspect_view", &store, &selection, inspect_cells, "inspect_window",
 		&inspect_display);
 	g_signal_connect(tree, "test-expand-row", G_CALLBACK(inspect_test_expand_row), NULL);
@@ -1119,7 +1101,6 @@ void inspect_init(void)
 
 void inspect_finalize(void)
 {
-	gtk_widget_destroy(inspect_page);
 	gtk_widget_destroy(inspect_dialog);
 	gtk_widget_destroy(expand_dialog);
 	g_free(jump_to_expr);


Modified: scope/src/inspect.h
1 files changed, 0 insertions(+), 1 deletions(-)
===================================================================
@@ -29,7 +29,6 @@
 
 void inspects_clear(void);
 gboolean inspects_update(void);
-gboolean inspects_current(void);
 void inspects_apply(void);
 
 #define EXPAND_MAX 99999


Modified: scope/src/local.c
15 files changed, 5 insertions(+), 10 deletions(-)
===================================================================
@@ -82,11 +82,7 @@ static void local_node_variable(const ParseNode *node, const LocalData *ld)
 
 void on_local_variables(GArray *nodes)
 {
-	const char *token = parse_grab_token(nodes);
-	size_t len = *token - '0' + 1;
-
-	if (thread_id && frame_id && len == strlen(thread_id) &&
-		!memcmp(++token, thread_id, len) && !strcmp(token + len, frame_id))
+	if (utils_matches_frame(parse_grab_token(nodes)))
 	{
 		GtkTreeIter iter;
 		LocalData ld = { NULL, stack_entry() };
@@ -105,10 +101,9 @@ void locals_clear(void)
 	store_clear(store);
 }
 
-static void local_send_update(char token)
+static void locals_send_update(char token)
 {
-	debug_send_format(F, "0%c%c%s%s-stack-list-variables 1", token,
-		'0' + (int) strlen(thread_id) - 1, thread_id, frame_id);
+	debug_send_format(F, "0%c%c%s%s-stack-list-variables 1", token, FRAME_ARGS);
 }
 
 gboolean locals_update(void)
@@ -117,7 +112,7 @@ gboolean locals_update(void)
 		return FALSE;
 
 	if (frame_id)
-		local_send_update('4');
+		locals_send_update('4');
 	else
 		locals_clear();
 
@@ -133,7 +128,7 @@ void locals_update_state(DebugState state)
 
 static void on_local_refresh(G_GNUC_UNUSED const MenuItem *menu_item)
 {
-	local_send_update('2');
+	locals_send_update('2');
 }
 
 static void on_local_unsorted(G_GNUC_UNUSED const MenuItem *menu_item)


Modified: scope/src/parse.c
5 files changed, 4 insertions(+), 1 deletions(-)
===================================================================
@@ -60,7 +60,7 @@ static void on_quiet_error(G_GNUC_UNUSED GArray *nodes)
 
 static void on_data_modified(G_GNUC_UNUSED GArray *nodes)
 {
-	views_data_dirty();
+	views_data_dirty(DS_BUSY);
 }
 
 typedef struct _ParseRoute
@@ -114,6 +114,9 @@ static void on_data_modified(G_GNUC_UNUSED GArray *nodes)
 	{ "^done,memory=[",               on_memory_read_bytes,    '\0', '\0', 1 },
 	{ "^done,features=[",             on_break_features,       '5',  '\0', 1 },
 	{ "^done,features=[",             on_target_features,      '7',  '\0', 1 },
+	{ "^done,register-names=[",       on_register_names,       '\0', '\0', 1 },
+	{ "^done,changed-registers=[",    on_register_changes,     '\0', '\0', 1 },
+	{ "^done,register-values=[",      on_register_values,      '*',  '\0', 1 },
 	{ "^running",                     on_debug_loaded,         '1',  '\0', 0 },
 	{ "^done",                        on_debug_loaded,         '1',  '\0', 0 },
 	{ "^done",                        on_break_done,           '2',  '\0', 0 },


Modified: scope/src/program.c
5 files changed, 4 insertions(+), 1 deletions(-)
===================================================================
@@ -189,6 +189,7 @@ static void save_program_settings(void)
 		breaks_save(config);
 		watches_save(config);
 		inspects_save(config);
+		registers_save(config);
 		parse_save(config);
 		utils_key_file_write_to_file(config, configfile);
 		g_free(configfile);
@@ -245,6 +246,7 @@ static void on_recent_menu_item_activate(G_GNUC_UNUSED GtkMenuItem *menuitem, co
 			breaks_load(config);
 			watches_load(config);
 			inspects_load(config);
+			registers_load(config);
 			parse_load(config);
 			message = g_strdup_printf(_("Loaded debug settings for %s."), name);
 			program_find(&iter, name);
@@ -410,11 +412,12 @@ static void on_program_ok_button_clicked(G_GNUC_UNUSED GtkButton *button,
 		gtk_widget_hide(program_dialog);
 
 		if (gtk_toggle_button_get_active(delete_all_items) &&
-			dialogs_show_question(_("Delete all breakpoints, watches and inspects?")))
+			dialogs_show_question(_("Delete all breakpoints, watches et cetera?")))
 		{
 			breaks_delete_all();
 			watches_delete_all();
 			inspects_delete_all();
+			registers_delete_all();
 		}
 	}
 }


Modified: scope/src/register.c
543 files changed, 543 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,543 @@
+/*
+ *  register.c
+ *
+ *  Copyright 2013 Dimitar Toshkov Zhekov <dimitar.zhekov at gmail.com>
+ *
+ *  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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "common.h"
+
+enum
+{
+	REGISTER_PATH,
+	REGISTER_DISPLAY,
+	REGISTER_VALUE,
+	REGISTER_HB_MODE,  /* natural register as char(s)?.. */
+	REGISTER_NAME,
+	REGISTER_ID,
+	REGISTER_FORMAT
+};
+
+static ScpTreeStore *store;
+static GtkTreeSelection *selection;
+
+enum
+{
+	FORMAT_NATURAL,
+	FORMAT_HEX,
+	FORMAT_DECIMAL,
+	FORMAT_OCTAL,
+	FORMAT_BINARY,
+	FORMAT_RAW,
+	FORMAT_COUNT
+};
+
+static const char register_formats[FORMAT_COUNT] = { 'N', 'x', 'd', 'o', 't', 'r' };
+
+static void register_iter_update(GtkTreeIter *iter, GString *commands[])
+{
+	gint id, format;
+
+	scp_tree_store_get(store, iter, REGISTER_ID, &id, REGISTER_FORMAT, &format, -1);
+	g_string_append_printf(commands[format], " %d", id);
+}
+
+static void register_node_update(const ParseNode *node, GString *commands[])
+{
+	iff (node->type == PT_VALUE, "changed-registers: contains array")
+	{
+		const char *id = (const char *) node->value;
+		GtkTreeIter iter;
+
+		iff (store_find(store, &iter, REGISTER_ID, id), "%s: rid not found", id)
+			register_iter_update(&iter, commands);
+	}
+}
+
+static void registers_send_update(GArray *nodes, char token)
+{
+	GString *commands[FORMAT_COUNT];
+	guint format;
+	gsize empty;
+
+	for (format = 0; format < FORMAT_COUNT; format++)
+	{
+		commands[format] = g_string_sized_new(0x7F);
+		g_string_append_printf(commands[format], "0%c9%c%s%s-data-list-register-values %c",
+			token, FRAME_ARGS, register_formats[format]);
+	}
+
+	empty = commands[FORMAT_NATURAL]->len;
+
+	if (nodes)
+		parse_foreach(nodes, (GFunc) register_node_update, commands);
+	else
+		store_foreach(store, (GFunc) register_iter_update, commands);
+
+	for (format = 0; format < FORMAT_COUNT; format++)
+	{
+		if (commands[format]->len > empty)
+			debug_send_command(F, commands[format]->str);
+
+		g_string_free(commands[format], TRUE);
+	}
+}
+
+typedef struct _IndexData
+{
+	guint index;
+	guint count;
+} IndexData;
+
+static void register_node_name(const ParseNode *node, IndexData *id)
+{
+	iff (node->type == PT_VALUE, "register-names: contains array")
+	{
+		const char *name = (const char *) node->value;
+
+		if (*name)
+		{
+			GtkTreeIter iter, iter1;
+
+			if (store_find(store, &iter1, REGISTER_NAME, name))
+			{
+				scp_tree_store_iter_nth_child(store, &iter, NULL, id->count);
+				scp_tree_store_swap(store, &iter, &iter1);
+			}
+			else
+			{
+				scp_tree_store_insert_with_values(store, &iter, NULL, id->count,
+					REGISTER_PATH, name, REGISTER_NAME, name, REGISTER_HB_MODE,
+					HB_DEFAULT, REGISTER_FORMAT, FORMAT_NATURAL, -1);
+			}
+
+			scp_tree_store_set(store, &iter, REGISTER_DISPLAY, NULL, REGISTER_VALUE,
+				NULL, REGISTER_ID, id->index, -1);
+			id->count++;
+		}
+
+		id->index++;
+	}
+}
+
+void on_register_names(GArray *nodes)
+{
+	IndexData id = { 0, 0 };
+	gboolean valid;
+	GtkTreeIter iter;
+	const char *token = parse_grab_token(nodes);
+
+	parse_foreach(parse_lead_array(nodes), (GFunc) register_node_name, &id);
+	valid = scp_tree_store_iter_nth_child(store, &iter, NULL, id.count);
+	while (valid)
+		valid = scp_tree_store_remove(store, &iter);
+
+	if (token)
+		registers_send_update(NULL, '2');
+}
+
+static gboolean query_all_registers = TRUE;
+
+void on_register_changes(GArray *nodes)
+{
+	const char *token = parse_grab_token(nodes);
+
+	if (token)
+	{
+		if (utils_matches_frame(token))
+			registers_send_update(parse_lead_array(nodes), '4');
+	}
+	else
+		query_all_registers = TRUE;  /* external changes */
+}
+
+static void register_set_value(GtkTreeIter *iter, char *value)
+{
+	if (*value == '{')
+	{
+		const char *parent;
+		GtkTreeIter child;
+		gboolean valid = scp_tree_store_iter_children(store, &child, iter);
+		gboolean next;
+
+		scp_tree_store_set(store, iter, REGISTER_DISPLAY, NULL, REGISTER_VALUE, NULL, -1);
+		scp_tree_store_get(store, iter, REGISTER_NAME, &parent, -1);
+
+		do
+		{
+			const char *name = ++value;
+			char *path, *end;
+
+			if ((value = strchr(name, '=')) == NULL)
+			{
+				dc_error("= expected");
+				break;
+			}
+
+			value[-(isspace(value[-1]) != 0)] = '\0';
+
+			if (!*name)
+			{
+				dc_error("name expected");
+				break;
+			}
+
+			if (isspace(*++value))
+				value++;
+
+			if (*value == '{')
+			{
+				if ((end = strchr(value, '}')) != NULL)
+					end++;
+			}
+			else if ((end = strchr(value, ',')) == NULL)
+				end = strchr(value, '}');
+
+			if (!end)
+			{
+				dc_error(", or } expected");
+				break;
+			}
+
+			next = *end == ',';
+			*end = '\0';
+			path = g_strdup_printf("%s.%s", parent, name);
+
+			if (!valid)
+				scp_tree_store_append(store, &child, iter);
+			scp_tree_store_set(store, &child, REGISTER_PATH, path, REGISTER_NAME, name,
+				REGISTER_DISPLAY, value, REGISTER_VALUE, value, -1);
+			valid &= scp_tree_store_iter_next(store, &child);
+
+			g_free(path);
+			value = end;
+			if (isspace(value[1]))
+				value++;
+
+		} while (next);
+
+		while (valid)
+			valid = scp_tree_store_remove(store, &child);
+	}
+	else
+	{
+		scp_tree_store_clear_children(store, iter, FALSE);
+		scp_tree_store_set(store, iter, REGISTER_DISPLAY, value, REGISTER_VALUE, value, -1);
+	}
+}
+
+typedef struct _ValueAction
+{
+	gint format;
+	gboolean assign;
+} ValueAction;
+
+static void register_node_value(const ParseNode *node, const ValueAction *va)
+{
+	iff (node->type == PT_ARRAY, "register-values: contains value")
+	{
+		GArray *nodes = (GArray *) node->value;
+		const char *number = parse_find_value(nodes, "number");
+		char *value = parse_find_value(nodes, "value");
+
+		iff (number && value, "no number or value")
+		{
+			GtkTreeIter iter;
+
+			if (store_find(store, &iter, REGISTER_ID, number), "%s: rid not found")
+			{
+				if (va->format < FORMAT_COUNT)
+					scp_tree_store_set(store, &iter, REGISTER_FORMAT, va->format, -1);
+
+				if (va->assign)
+					register_set_value(&iter, value);
+			}
+		}
+	}
+}
+
+void on_register_values(GArray *nodes)
+{
+	const char *token = parse_grab_token(nodes);
+	ValueAction va = { *token - '0', utils_matches_frame(token + 1) };
+
+	if (va.format < FORMAT_COUNT || va.assign)
+	{
+		parse_foreach(parse_lead_array(nodes), (GFunc) register_node_value, &va);
+
+		if (va.assign)
+			query_all_registers = FALSE;
+	}
+}
+
+static void on_register_display_edited(G_GNUC_UNUSED GtkCellRendererText *renderer,
+	gchar *path_str, gchar *new_text, G_GNUC_UNUSED gpointer gdata)
+{
+	view_display_edited(store, debug_state() & DS_DEBUG, path_str, "07-gdb-set var $%s=%s",
+		new_text);
+}
+
+static const TreeCell register_cells[] =
+{
+	{ "register_display", G_CALLBACK(on_register_display_edited) },
+	{ NULL, NULL }
+};
+
+static void register_iter_clear(GtkTreeIter *iter, G_GNUC_UNUSED gpointer gdata)
+{
+	if (scp_tree_store_iter_has_child(store, iter))
+		scp_tree_store_clear_children(store, iter, FALSE);
+	else
+		scp_tree_store_set(store, iter, REGISTER_DISPLAY, NULL, REGISTER_VALUE, NULL, -1);
+}
+
+void registers_clear(void)
+{
+	store_foreach(store, (GFunc) register_iter_clear, NULL);
+	query_all_registers = TRUE;
+}
+
+gboolean registers_update(void)
+{
+	if (g_strcmp0(frame_id, "0") && view_stack_update())
+		return FALSE;
+
+	if (frame_id)
+	{
+		if (query_all_registers)
+			registers_send_update(NULL, '4');
+		else
+			debug_send_format(F, "04%c%s%s-data-list-changed-registers", FRAME_ARGS);
+	}
+	else
+		registers_clear();
+
+	return TRUE;
+}
+
+static char *last_gdb_executable = NULL;
+
+void registers_query_names(void)
+{
+	if (g_strcmp0(pref_gdb_executable, last_gdb_executable))
+	{
+		g_free(last_gdb_executable);
+		last_gdb_executable = g_strdup(pref_gdb_executable);
+		debug_send_command(N, "-data-list-register-names");
+	}
+}
+
+static GtkWidget *tree;
+
+void registers_show(gboolean show)
+{
+	gtk_widget_set_visible(tree, show);
+}
+
+static GObject *register_display;
+
+void registers_update_state(DebugState state)
+{
+	GtkTreeIter iter;
+
+	if (gtk_tree_selection_get_selected(selection, NULL, &iter))
+	{
+		GtkTreeIter parent;
+
+		g_object_set(register_display, "editable", (state & DS_DEBUG) &&
+			(scp_tree_store_iter_parent(store, &parent, &iter) ||
+			!scp_tree_store_iter_has_child(store, &iter)), NULL);
+	}
+}
+
+void registers_delete_all(void)
+{
+	store_clear(store);
+}
+
+static gboolean register_load(GKeyFile *config, const char *section)
+{
+	char *name = utils_key_file_get_string(config, section, "name");
+	gint format = utils_get_setting_integer(config, section, "format", FORMAT_NATURAL);
+	gboolean valid = FALSE;
+	GtkTreeIter iter;
+
+	if (name && (unsigned) format < FORMAT_COUNT)
+	{
+		scp_tree_store_append_with_values(store, NULL, NULL, REGISTER_PATH, name,
+			REGISTER_NAME, name, REGISTER_HB_MODE, HB_DEFAULT, REGISTER_FORMAT,
+			format, -1);
+		valid = TRUE;
+	}
+
+	g_free(name);
+	return valid;
+}
+
+void registers_load(GKeyFile *config)
+{
+	registers_delete_all();
+	g_free(last_gdb_executable);
+	last_gdb_executable = NULL;
+	utils_load(config, "register", register_load);
+}
+
+static gboolean register_save(GKeyFile *config, const char *section, GtkTreeIter *iter)
+{
+	const char *name;
+	gint format;
+
+	scp_tree_store_get(store, iter, REGISTER_NAME, &name, REGISTER_FORMAT, &format, -1);
+
+	if (format == FORMAT_NATURAL)
+		return FALSE;
+
+	g_key_file_set_string(config, section, "name", name);
+	g_key_file_set_integer(config, section, "format", format);
+	return TRUE;
+}
+
+void registers_save(GKeyFile *config)
+{
+	store_save(store, config, "register", register_save);
+}
+
+static gboolean on_register_query_tooltip(G_GNUC_UNUSED GtkWidget *widget, gint x, gint y,
+	gboolean keyboard_tip, GtkTooltip *tooltip, GtkTreeViewColumn *register_name_column)
+{
+	GtkTreeView *tree = GTK_TREE_VIEW(widget);
+	GtkTreeIter iter;
+
+	if (gtk_tree_view_get_tooltip_context(tree, &x, &y, keyboard_tip, NULL, NULL, &iter))
+	{
+		gint id;
+		char *text;
+
+		gtk_tree_view_set_tooltip_cell(tree, tooltip, NULL, register_name_column, NULL);
+		scp_tree_store_get(store, &iter, REGISTER_ID, &id, -1);
+		text = g_strdup_printf("register %d", id);
+		gtk_tooltip_set_text(tooltip, text);
+		g_free(text);
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+static void on_register_refresh(G_GNUC_UNUSED const MenuItem *menu_item)
+{
+	registers_send_update(NULL, '2');
+}
+
+static void on_register_copy(const MenuItem *menu_item)
+{
+	menu_copy(selection, menu_item);
+}
+
+static void on_register_format_display(const MenuItem *menu_item)
+{
+	menu_mode_display(selection, menu_item, REGISTER_FORMAT);
+}
+
+static void on_register_format_update(const MenuItem *menu_item)
+{
+	GtkTreeIter iter;
+	gint format = GPOINTER_TO_INT(menu_item->gdata);
+	gint id;
+
+	gtk_tree_selection_get_selected(selection, NULL, &iter);
+	scp_tree_store_get(store, &iter, REGISTER_ID, &id, -1);
+
+	if (debug_state() & DS_DEBUG)
+	{
+		debug_send_format(N, "02%d%c%s%s-data-list-register-values %c %d", format,
+			FRAME_ARGS, register_formats[format], id);
+	}
+	else
+		scp_tree_store_set(store, &iter, REGISTER_FORMAT, format, -1);
+}
+
+static void on_register_query(G_GNUC_UNUSED const MenuItem *menu_item)
+{
+	debug_send_command(N, debug_state() & DS_DEBUG ? "02-data-list-register-names" :
+		"-data-list-register-names");
+}
+
+#define DS_FRESHABLE DS_DEBUG
+#define DS_COPYABLE (DS_BASICS | DS_EXTRA_1)
+#define DS_FORMATABLE (DS_INACTIVE | DS_DEBUG | DS_HANGING | DS_EXTRA_2)
+#define DS_QUERABLE DS_SENDABLE
+
+#define FORMAT_ITEM(format, FORMAT) \
+	{ ("register_format_"format), on_register_format_update, DS_FORMATABLE, NULL, \
+		GINT_TO_POINTER(FORMAT) }
+
+static MenuItem register_menu_items[] =
+{
+	{ "register_refresh",  on_register_refresh,        DS_FRESHABLE,  NULL, NULL },
+	{ "register_copy",     on_register_copy,           DS_COPYABLE,   NULL, NULL },
+	{ "register_format",   on_register_format_display, DS_FORMATABLE, NULL, NULL },
+	FORMAT_ITEM("natural", FORMAT_NATURAL),
+	FORMAT_ITEM("hex",     FORMAT_HEX),
+	FORMAT_ITEM("decimal", FORMAT_DECIMAL),
+	FORMAT_ITEM("octal",   FORMAT_OCTAL),
+	FORMAT_ITEM("binary",  FORMAT_BINARY),
+	FORMAT_ITEM("raw",     FORMAT_RAW),
+	{ "register_query",    on_register_query,          DS_QUERABLE,   NULL, NULL },
+	{ NULL, NULL, 0, NULL, NULL }
+};
+
+static guint register_menu_extra_state(void)
+{
+	GtkTreeIter iter;
+
+	if (gtk_tree_selection_get_selected(selection, NULL, &iter))
+	{
+		GtkTreeIter parent;
+
+		return (1 << DS_INDEX_1) |
+			(!scp_tree_store_iter_parent(store, &parent, &iter) << DS_INDEX_2);
+	}
+
+	return 0;
+}
+
+static MenuInfo register_menu_info = { register_menu_items, register_menu_extra_state, 0 };
+
+static void on_register_selection_changed(G_GNUC_UNUSED GtkTreeSelection *selection,
+	G_GNUC_UNUSED gpointer gdata)
+{
+	registers_update_state(debug_state());
+}
+
+void register_init(void)
+{
+	tree = GTK_WIDGET(view_connect("register_view", &store, &selection, register_cells,
+		"register_window", &register_display));
+	gtk_widget_set_has_tooltip(tree, TRUE);
+	g_signal_connect(tree, "query-tooltip", G_CALLBACK(on_register_query_tooltip),
+		get_column("register_name_column"));
+	menu_select("register_menu", &register_menu_info, selection);
+	g_signal_connect(selection, "changed", G_CALLBACK(on_register_selection_changed), NULL);
+}
+
+void registers_finalize(void)
+{
+	g_free(last_gdb_executable);
+}


Modified: scope/src/register.h
40 files changed, 40 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,40 @@
+/*
+ *  register.h
+ *
+ *  Copyright 2013 Dimitar Toshkov Zhekov <dimitar.zhekov at gmail.com>
+ *
+ *  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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef REGISTER_H
+
+void on_register_names(GArray *nodes);
+void on_register_changes(GArray *nodes);
+void on_register_values(GArray *nodes);
+
+void registers_clear(void);
+gboolean registers_update(void);
+void registers_query_names(void);
+void registers_show(gboolean show);
+
+void registers_update_state(DebugState state);
+void registers_delete_all(void);
+void registers_load(GKeyFile *config);
+void registers_save(GKeyFile *config);
+
+void register_init(void);
+void registers_finalize(void);
+
+#define REGISTER_H 1
+#endif


Modified: scope/src/scope.c
4 files changed, 3 insertions(+), 1 deletions(-)
===================================================================
@@ -32,7 +32,7 @@
 PLUGIN_VERSION_CHECK(215)
 
 PLUGIN_SET_TRANSLATABLE_INFO(LOCALEDIR, GETTEXT_PACKAGE, _("Scope Debugger"),
-	_("Relatively simple GDB front-end."), "0.88" ,
+	_("Relatively simple GDB front-end."), "0.90" ,
 	"Dimitar Toshkov Zhekov <dimitar.zhekov at gmail.com>")
 
 /* Keybinding(s) */
@@ -560,6 +560,7 @@ void plugin_init(G_GNUC_UNUSED GeanyData *gdata)
 	gtk_notebook_set_tab_pos(GTK_NOTEBOOK(debug_panel), pref_panel_tab_pos);
 	conterm_init();
 	inspect_init();
+	register_init();
 	parse_init();
 	debug_init();
 	views_init();
@@ -613,6 +614,7 @@ void plugin_cleanup(void)
 	tooltip_finalize();
 	program_finalize();
 	conterm_finalize();
+	registers_finalize();
 	inspect_finalize();
 	thread_finalize();
 	break_finalize();


Modified: scope/src/stack.c
5 files changed, 2 insertions(+), 3 deletions(-)
===================================================================
@@ -199,8 +199,7 @@ static void on_stack_selection_changed(GtkTreeSelection *selection,
 	else
 		frame_id = NULL;
 
-	view_dirty(VIEW_LOCALS);
-	view_dirty(VIEW_WATCHES);
+	views_context_dirty(debug_state(), TRUE);
 }
 
 static void stack_seek_selected(gboolean focus)
@@ -341,7 +340,7 @@ void stack_init(void)
 	view_set_sort_func(store, STACK_FILE, store_seek_compare);
 	view_set_line_data_func("stack_line_column", "stack_line", STACK_LINE);
 	gtk_widget_set_has_tooltip(GTK_WIDGET(tree), TRUE);
-	g_signal_connect(tree, "query-tooltip", G_CALLBACK(on_view_query_tooltip),
+	g_signal_connect(tree, "query-tooltip", G_CALLBACK(on_view_query_base_tooltip),
 		get_column("stack_base_name_column"));
 
 	g_signal_connect(tree, "key-press-event", G_CALLBACK(on_view_key_press),


Modified: scope/src/thread.c
12 files changed, 7 insertions(+), 5 deletions(-)
===================================================================
@@ -314,7 +314,7 @@ static void thread_iter_stopped(GtkTreeIter *iter, StopData *sd)
 		if (!addr)
 			thread_state = THREAD_QUERY_FRAME;
 
-		views_data_dirty();
+		views_data_dirty(DS_BUSY);
 	}
 	else if (!addr)
 		view_dirty(VIEW_THREADS);
@@ -328,7 +328,7 @@ static void thread_iter_stopped(GtkTreeIter *iter, StopData *sd)
 
 static void thread_node_stopped(const ParseNode *node, StopData *sd)
 {
-	iff (node->type == PT_VALUE, "%s: found array", node->name)
+	iff (node->type == PT_VALUE, "stopped-threads: contains array")
 	{
 		GtkTreeIter iter;
 
@@ -429,6 +429,7 @@ void on_thread_created(GArray *nodes)
 	{
 		/* startup */
 		breaks_reset();
+		registers_show(TRUE);
 	#ifdef G_OS_UNIX
 		terminal_clear();
 		if (terminal_auto_show)
@@ -483,6 +484,7 @@ void on_thread_exited(GArray *nodes)
 		if (!--thread_count)
 		{
 			/* shutdown */
+			registers_show(FALSE);
 		#ifdef G_OS_UNIX
 			if (terminal_auto_hide)
 				terminal_standalone(FALSE);
@@ -673,8 +675,8 @@ static void on_thread_selection_changed(GtkTreeSelection *selection,
 		thread_state = THREAD_BLANK;
 	}
 
-	views_data_dirty();
-	update_state(debug_state());
+	views_data_dirty(debug_state());
+	update_state(debug_state());  /* may be a different state */
 }
 
 static void thread_seek_selected(gboolean focus)
@@ -881,7 +883,7 @@ void thread_init(void)
 	view_set_sort_func(store, THREAD_GROUP_ID, thread_ident_compare);
 	view_set_sort_func(store, THREAD_TARGET_ID, thread_ident_compare);
 	gtk_widget_set_has_tooltip(GTK_WIDGET(tree), TRUE);
-	g_signal_connect(tree, "query-tooltip", G_CALLBACK(on_view_query_tooltip),
+	g_signal_connect(tree, "query-tooltip", G_CALLBACK(on_view_query_base_tooltip),
 		get_column("thread_base_name_column"));
 
 	groups = SCP_TREE_STORE(get_object("thread_group_store"));


Modified: scope/src/utils.c
12 files changed, 11 insertions(+), 1 deletions(-)
===================================================================
@@ -41,7 +41,9 @@ void show_errno(const char *prefix)
 
 void show_errno(const char *prefix)
 {
-	show_error(_("%s: error %lu."), prefix, (unsigned long) GetLastError());
+	gchar *error = g_win32_error_message(GetLastError());
+	show_error(_("%s: %s"), prefix, error);
+	g_free(error);
 }
 #endif  /* G_OS_UNIX */
 
@@ -604,6 +606,14 @@ static void on_insert_text(GtkEditable *editable, gchar *new_text, gint new_text
 		g_signal_stop_emission_by_name(editable, "insert-text");
 }
 
+gboolean utils_matches_frame(const char *token)
+{
+	size_t len = *token - '0' + 1;
+
+	return thread_id && len == strlen(thread_id) && strlen(++token) > len &&
+		!memcmp(token, thread_id, len) && !g_strcmp0(token + len, frame_id);
+}
+
 void validator_attach(GtkEditable *editable, gint validator)
 {
 	g_signal_connect(editable, "insert-text", G_CALLBACK(on_insert_text),


Modified: scope/src/utils.h
2 files changed, 2 insertions(+), 0 deletions(-)
===================================================================
@@ -25,6 +25,7 @@
 gboolean utils_set_nonblock(GPollFD *fd);
 void utils_handle_button_press(GtkWidget *widget, GdkEventButton *event);
 void utils_handle_button_release(GtkWidget *widget, GdkEventButton *event);
+
 gboolean utils_check_path(const char *pathname, gboolean file, int mode);  /* "" ok */
 const gchar *utils_skip_spaces(const gchar *text);
 void utils_strchrepl(char *text, char c, char repl);
@@ -86,6 +87,7 @@ void utils_load(GKeyFile *config, const char *prefix,
 
 gchar *utils_verify_selection(gchar *text);
 gchar *utils_get_default_selection(void);  /* +verify */
+gboolean utils_matches_frame(const char *token);
 
 enum
 {


Modified: scope/src/views.c
134 files changed, 89 insertions(+), 45 deletions(-)
===================================================================
@@ -23,10 +23,17 @@
 
 #include "common.h"
 
+typedef enum _ViewContext
+{
+	VC_NONE,
+	VC_DATA,
+	VC_FRAME
+} ViewContext;
+
 typedef struct _ViewInfo
 {
 	gboolean dirty;
-	gboolean data;
+	ViewContext context;
 	void (*clear)(void);
 	gboolean (*update)(void);
 	gboolean flush;
@@ -35,34 +42,21 @@
 
 static ViewInfo views[VIEW_COUNT] =
 {
-	{ FALSE, FALSE, NULL,           NULL,            FALSE, 0 },
-	{ FALSE, FALSE, threads_clear,  threads_update,  FALSE, DS_SENDABLE },
-	{ FALSE, FALSE, breaks_clear,   breaks_update,   FALSE, DS_SENDABLE },
-	{ FALSE, TRUE,  stack_clear,    stack_update,    TRUE,  DS_DEBUG },
-	{ FALSE, TRUE,  locals_clear,   locals_update,   TRUE,  DS_DEBUG },
-	{ FALSE, TRUE,  watches_clear,  watches_update,  TRUE,  DS_DEBUG },
-	{ FALSE, TRUE,  memory_clear,   memory_update,   TRUE,  DS_SENDABLE },
-	{ FALSE, FALSE, NULL,           dc_update,       FALSE, DS_DEBUG },
-	{ FALSE, TRUE,  inspects_clear, inspects_update, FALSE, DS_DEBUG },
-	{ FALSE, TRUE,  tooltip_clear,  tooltip_update,  FALSE, DS_SENDABLE },
-	{ FALSE, FALSE, menu_clear,     NULL,            FALSE, 0 }
+	{ FALSE, VC_NONE,  NULL,            NULL,             FALSE, 0 },
+	{ FALSE, VC_NONE,  threads_clear,   threads_update,   FALSE, DS_SENDABLE },
+	{ FALSE, VC_NONE,  breaks_clear,    breaks_update,    FALSE, DS_SENDABLE },
+	{ FALSE, VC_DATA,  stack_clear,     stack_update,     TRUE,  DS_DEBUG },
+	{ FALSE, VC_FRAME, locals_clear,    locals_update,    TRUE,  DS_DEBUG },
+	{ FALSE, VC_FRAME, watches_clear,   watches_update,   TRUE,  DS_DEBUG },
+	{ FALSE, VC_DATA,  memory_clear,    memory_update,    TRUE,  DS_SENDABLE },
+	{ FALSE, VC_NONE,  NULL,            dc_update,        FALSE, DS_DEBUG },
+	{ FALSE, VC_DATA,  inspects_clear,  inspects_update,  FALSE, DS_DEBUG },
+	{ FALSE, VC_FRAME, registers_clear, registers_update, TRUE,  DS_DEBUG },
+	{ FALSE, VC_DATA,  tooltip_clear,   tooltip_update,   FALSE, DS_SENDABLE },
+	{ FALSE, VC_NONE,  menu_clear,      NULL,             FALSE, 0 }
 };
 
-void view_dirty(ViewIndex index)
-{
-	views[index].dirty = TRUE;
-}
-
-void views_data_dirty(void)
-{
-	ViewIndex i;
-
-	for (i = 0; i < VIEW_COUNT; i++)
-		if (views[i].data)
-			view_dirty(i);
-}
-
-static void view_update_unconditional(ViewIndex index, DebugState state)
+static void view_update_dirty(ViewIndex index, DebugState state)
 {
 	ViewInfo *view = views + index;
 
@@ -81,7 +75,44 @@ static void view_update_unconditional(ViewIndex index, DebugState state)
 static void view_update(ViewIndex index, DebugState state)
 {
 	if (views[index].dirty)
-		view_update_unconditional(index, state);
+		view_update_dirty(index, state);
+}
+
+static GtkNotebook *geany_sidebar;
+static GtkWidget *inspect_page;
+static GtkWidget *register_page;
+
+static void views_sidebar_update(DebugState state)
+{
+	gint page_num = gtk_notebook_get_current_page(geany_sidebar);
+	GtkWidget *page = gtk_notebook_get_nth_page(geany_sidebar, page_num);
+
+	if (page == inspect_page)
+		view_update(VIEW_INSPECT, state);
+	else if (page == register_page)
+		view_update(VIEW_REGISTERS, state);
+}
+
+void view_dirty(ViewIndex index)
+{
+	views[index].dirty = TRUE;
+}
+
+void views_context_dirty(DebugState state, gboolean frame_only)
+{
+	ViewIndex i;
+
+	for (i = 0; i < VIEW_COUNT; i++)
+		if (views[i].context >= (frame_only ? VC_FRAME : VC_DATA))
+			view_dirty(i);
+
+	if (state != DS_BUSY)
+	{
+		if (option_update_all_views)
+			views_update(state);
+		else
+			views_sidebar_update(state);
+	}
 }
 
 static ViewIndex view_current = 0;
@@ -105,6 +136,7 @@ void views_update(DebugState state)
 	if (option_update_all_views)
 	{
 		ViewIndex i;
+		gboolean skip_frame = FALSE;
 
 		if (thread_state == THREAD_QUERY_FRAME)
 		{
@@ -116,12 +148,12 @@ void views_update(DebugState state)
 
 		for (i = 0; i < VIEW_COUNT; i++)
 		{
-			if (views[i].dirty)
+			if (views[i].dirty && (!skip_frame || views[i].context != VC_FRAME))
 			{
-				view_update_unconditional(i, state);
+				view_update_dirty(i, state);
 
 				if (i == VIEW_STACK && thread_state >= THREAD_STOPPED)
-					i = VIEW_WATCHES;
+					skip_frame = TRUE;
 			}
 		}
 	}
@@ -137,9 +169,7 @@ void views_update(DebugState state)
 
 		view_update(view_current, state);
 		view_update(VIEW_TOOLTIP, state);
-
-		if (inspects_current())
-			view_update(VIEW_INSPECT, state);
+		views_sidebar_update(state);
 	}
 }
 
@@ -148,18 +178,13 @@ gboolean view_stack_update(void)
 	if (views[VIEW_STACK].dirty)
 	{
 		DebugState state = thread_state >= THREAD_STOPPED ? DS_DEBUG : DS_READY;
-		view_update_unconditional(VIEW_STACK, state);
+		view_update_dirty(VIEW_STACK, state);
 		return state == DS_DEBUG;
 	}
 
 	return FALSE;
 }
 
-void view_inspect_update(void)
-{
-	view_update(VIEW_INSPECT, debug_state());
-}
-
 void on_view_changed(G_GNUC_UNUSED GtkNotebook *notebook, G_GNUC_UNUSED gpointer page,
 	gint page_num, G_GNUC_UNUSED gpointer gdata)
 {
@@ -191,7 +216,7 @@ gboolean on_view_button_1_press(GtkWidget *widget, GdkEventButton *event, ViewSe
 	return FALSE;
 }
 
-gboolean on_view_query_tooltip(GtkWidget *widget, gint x, gint y, gboolean keyboard_tip,
+gboolean on_view_query_base_tooltip(GtkWidget *widget, gint x, gint y, gboolean keyboard_tip,
 	GtkTooltip *tooltip, GtkTreeViewColumn *base_name_column)
 {
 	GtkTreeView *tree = GTK_TREE_VIEW(widget);
@@ -474,12 +499,12 @@ static void on_command_send_button_clicked(G_GNUC_UNUSED GtkButton *button,
 
 	thread_synchronize();
 	utils_strchrepl(text, '\n', ' ');
-	gtk_text_buffer_set_text(command_text, text, -1);
 	start = utils_skip_spaces(text);
 	locale = gtk_toggle_button_get_active(command_locale) ?
 		utils_get_locale_from_utf8(start) : g_strdup(start);
 	debug_send_command(N, locale);
 	g_free(locale);
+	gtk_text_buffer_set_text(command_text, "", -1);
 	gtk_widget_hide(command_dialog);
 
 	if (*start)
@@ -538,12 +563,15 @@ void view_command_line(const gchar *text, const gchar *title, const gchar *seek,
 			g_utf8_strlen(text, pos ? pos + strlen(seek) * seek_after - text : -1));
 		gtk_text_buffer_place_cursor(command_text, &iter);
 	}
+	else
+	{
+		gtk_text_buffer_get_start_iter(command_text, &start);
+		gtk_text_buffer_get_end_iter(command_text, &end);
+		gtk_text_buffer_select_range(command_text, &start, &end);
+	}
 
 	on_command_text_changed(command_text, NULL);
 	command_line_update_state(debug_state());
-	gtk_text_buffer_get_start_iter(command_text, &start);
-	gtk_text_buffer_get_end_iter(command_text, &end);
-	gtk_text_buffer_select_range(command_text, &start, &end);
 	gtk_combo_box_set_active_iter(command_history, NULL);
 	gtk_dialog_run(GTK_DIALOG(command_dialog));
 }
@@ -568,6 +596,12 @@ void views_update_state(DebugState state)
 	}
 }
 
+static void on_geany_sidebar_switch_page(G_GNUC_UNUSED GtkNotebook *notebook,
+	G_GNUC_UNUSED gpointer page, G_GNUC_UNUSED gint page_num, G_GNUC_UNUSED gpointer gdata)
+{
+	views_sidebar_update(debug_state());
+}
+
 void views_init(void)
 {
 	command_dialog = dialog_connect("command_dialog");
@@ -596,9 +630,19 @@ void views_init(void)
 	g_signal_connect(command_send, "clicked", G_CALLBACK(on_command_send_button_clicked),
 		NULL);
 	utils_enter_to_clicked(command_view, command_send);
+
+	geany_sidebar = GTK_NOTEBOOK(geany->main_widgets->sidebar_notebook);
+	g_signal_connect(geany_sidebar, "switch-page", G_CALLBACK(on_geany_sidebar_switch_page),
+		NULL);
+	inspect_page = get_widget("inspect_page");
+	gtk_notebook_append_page(geany_sidebar, inspect_page, get_widget("inspect_label"));
+	register_page = get_widget("register_page");
+	gtk_notebook_append_page(geany_sidebar, register_page, get_widget("register_label"));
 }
 
 void views_finalize(void)
 {
 	gtk_widget_destroy(GTK_WIDGET(command_dialog));
+	gtk_widget_destroy(inspect_page);
+	gtk_widget_destroy(register_page);
 }


Modified: scope/src/views.h
8 files changed, 5 insertions(+), 3 deletions(-)
===================================================================
@@ -30,23 +30,25 @@
 	VIEW_MEMORY,
 	VIEW_CONSOLE,
 	VIEW_INSPECT,
+	VIEW_REGISTERS,
 	VIEW_TOOLTIP,
 	VIEW_POPMENU,
 	VIEW_COUNT
 } ViewIndex;
 
 void view_dirty(ViewIndex index);
-void views_data_dirty(void);
+void views_context_dirty(DebugState state, gboolean frame_only);
+#define views_data_dirty(state) views_context_dirty((state), FALSE)
 void views_clear(void);
 void views_update(DebugState state);
 gboolean view_stack_update(void);
-void view_inspect_update(void);
+void view_local_update(void);
 
 void on_view_changed(GtkNotebook *notebook, gpointer page, gint page_num, gpointer gdata);
 typedef void (*ViewSeeker)(gboolean focus);
 gboolean on_view_key_press(GtkWidget *widget, GdkEventKey *event, ViewSeeker seeker);
 gboolean on_view_button_1_press(GtkWidget *widget, GdkEventButton *event, ViewSeeker seeker);
-gboolean on_view_query_tooltip(GtkWidget *widget, gint x, gint y, gboolean keyboard_tip,
+gboolean on_view_query_base_tooltip(GtkWidget *widget, gint x, gint y, gboolean keyboard_tip,
 	GtkTooltip *tooltip, GtkTreeViewColumn *base_name_column);
 
 enum



--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).


More information about the Plugins-Commits mailing list