Personal emacs config
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

231 lines
9.4 KiB

  1. ;; Copyright (C) 2010, 2012-2015, 2017-2018 Free Software Foundation, Inc
  2. ;; Author: Rocky Bernstein <rocky@gnu.org>
  3. ;; This program is free software; you can redistribute it and/or modify
  4. ;; it under the terms of the GNU General Public License as published by
  5. ;; the Free Software Foundation, either version 3 of the License, or
  6. ;; (at your option) any later version.
  7. ;; This program is distributed in the hope that it will be useful,
  8. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. ;; GNU General Public License for more details.
  11. ;; You should have received a copy of the GNU General Public License
  12. ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. ;; Code associated with breakpoints
  14. (require 'image)
  15. (require 'load-relative)
  16. (require-relative-list '("loc" "bp-image-data") "realgud-")
  17. (defun realgud-bp-remove-icons (&optional begin-pos end-pos bpnum)
  18. "Remove breakpoint icons (overlays) in BEGIN-POS .. END-POS.
  19. The default value for BEGIN-POS is `point'. The default value
  20. for END-POS is BEGIN-POS. When BPNUM is non-nil, only remove
  21. overlays with that breakpoint number.
  22. The way we determine if an overlay is ours is by inspecting the
  23. overlay for a realgud property."
  24. (interactive "r")
  25. (setq begin-pos (or begin-pos (point))
  26. end-pos (or end-pos begin-pos))
  27. (dolist (overlay (overlays-in begin-pos end-pos))
  28. (when (overlay-get overlay 'realgud)
  29. (when (or (null bpnum) (equal bpnum (overlay-get overlay 'realgud-bp-num)))
  30. (delete-overlay overlay)))))
  31. (defvar realgud-bp-enabled-icon nil
  32. "Icon for an enabled breakpoint in display margin.")
  33. (defvar realgud-bp-disabled-icon nil
  34. "Icon for a disabled breakpoint in display margin.")
  35. (defun realgud-set-bp-icons()
  36. "Load breakpoint icons, if needed."
  37. (when (display-images-p)
  38. (unless realgud-bp-enabled-icon
  39. (setq realgud-bp-enabled-icon
  40. (find-image `((:type xpm :data
  41. ,realgud-bp-xpm-data
  42. :ascent 100 :pointer hand)
  43. (:type svg :data
  44. ,realgud-bp-enabled-svg-data
  45. :ascent 100 :pointer hand)
  46. (:type tiff :data
  47. ,realgud-bp-enabled-tiff-data
  48. :ascent 100 :pointer hand)
  49. (:type pbm :data
  50. ,realgud-bp-enabled-pbm-data
  51. :ascent 100 :pointer hand)))))
  52. (unless realgud-bp-disabled-icon
  53. (setq realgud-bp-disabled-icon
  54. (find-image `((:type xpm :data
  55. ,realgud-bp-xpm-data
  56. :conversion disabled ; different than 'enabled'
  57. :ascent 100 :pointer hand)
  58. (:type svg :data
  59. ,realgud-bp-disabled-svg-data
  60. :ascent 100 :pointer hand)
  61. (:type tiff :data
  62. ,realgud-bp-disabled-tiff-data
  63. :ascent 100 :pointer hand)
  64. (:type pbm :data
  65. ,realgud-bp-disabled-pbm-data
  66. :ascent 100 :pointer hand)
  67. (:type svg :data
  68. ,realgud-bp-disabled-svg-data
  69. :ascent 100 :pointer hand)))))))
  70. (declare-function define-fringe-bitmap "fringe.c"
  71. (bitmap bits &optional height width align))
  72. (when (display-images-p)
  73. ;; Taken from gdb-mi
  74. (define-fringe-bitmap 'realgud-bp-filled
  75. "\x3c\x7e\xff\xff\xff\xff\x7e\x3c")
  76. (define-fringe-bitmap 'realgud-bp-hollow
  77. "\x3c\x42\x81\x81\x81\x81\x42\x3c"))
  78. (defgroup realgud-bp nil
  79. "RealGUD breakpoints UI"
  80. :group 'realgud
  81. :prefix 'realgud-bp-)
  82. (defface realgud-bp-enabled-face
  83. '((t :foreground "red" :weight bold))
  84. "Face for enabled breakpoints (in the fringe or margin)."
  85. :group 'realgud-bp)
  86. (defface realgud-bp-disabled-face
  87. '((t :foreground "grey" :weight bold))
  88. "Face for disabled breakpoints (in the fringe or margin).
  89. Only used in text terminals: fringe icons always use
  90. `realgud-bp-enabled-face'."
  91. :group 'realgud-bp)
  92. (defface realgud-bp-line-enabled-face
  93. '((t (:box (:color "red"))))
  94. "Face for lines with enabled breakpoints."
  95. :group 'realgud-bp)
  96. (defface realgud-bp-line-disabled-face
  97. '((t (:box (:color "grey"))))
  98. "Face for lines with disabled breakpoints."
  99. :group 'realgud-bp)
  100. (defcustom realgud-bp-fringe-indicator-style '(filled-rectangle . hollow-rectangle)
  101. "Which fringe icon to use for breakpoints."
  102. :type '(choice (const :tag "Disc" (realgud-bp-filled . realgud-bp-hollow))
  103. (const :tag "Square" (filled-square . hollow-square))
  104. (const :tag "Rectangle" (filled-rectangle . hollow-rectangle)))
  105. :group 'realgud-bp)
  106. (defcustom realgud-bp-use-fringe t
  107. "Whether to use the fringe to display breakpoints.
  108. If nil, use margins instead."
  109. :type '(boolean)
  110. :group 'realgud-bp)
  111. (defun realgud-bp--fringe-width ()
  112. "Compute width of left fringe."
  113. (let ((window (get-buffer-window (current-buffer))))
  114. (or left-fringe-width
  115. (and window (car (window-fringes window)))
  116. 0)))
  117. (defun realgud-bp-add-fringe-icon (overlay icon)
  118. "Add a fringe icon to OVERLAY.
  119. ICON is a symbol registered with `define-fringe-bitmap'."
  120. ;; Ensure that the fringe is wide enough
  121. (unless (>= (realgud-bp--fringe-width) 8)
  122. (set-fringe-mode `(8 . ,right-fringe-width)))
  123. ;; Add the fringe icon
  124. (let* ((fringe-spec `(left-fringe ,icon realgud-bp-enabled-face)))
  125. (overlay-put overlay 'before-string (propertize "x" 'display fringe-spec))))
  126. (defun realgud-bp-add-margin-indicator (overlay text image face)
  127. "Add a margin breakpoint indicator to OVERLAY.
  128. TEXT is a string, IMAGE an IMAGE spec or nil; TEXT gets
  129. highlighted with FACE."
  130. ;; Ensure that the margin is large enough (Taken from gdb-mi)
  131. (when (< left-margin-width 2)
  132. (save-current-buffer
  133. (setq left-margin-width 2)
  134. (let ((window (get-buffer-window (current-buffer) 0)))
  135. (if window
  136. (set-window-margins
  137. window left-margin-width right-margin-width)))))
  138. ;; Add the margin string
  139. (let* ((indicator (or image (propertize text 'face face)))
  140. (spec `((margin left-margin) ,indicator)))
  141. (overlay-put overlay 'before-string (propertize text 'display spec))))
  142. (defun realgud-bp-put-icon (pos enable? bp-num &optional buf)
  143. "Add a breakpoint icon at POS according to breakpoint-display-style.
  144. Use the fringe if available, and the margin otherwise. Record
  145. breakpoint status ENABLE? and breakpoint number BP-NUM in
  146. overlay. BUF is the buffer that POS refers to; it defaults to
  147. the current buffer."
  148. (let* ((bp-text) (bp-face) (line-face) (margin-icon) (fringe-icon))
  149. (realgud-set-bp-icons)
  150. (if enable?
  151. (setq bp-text "B"
  152. bp-face 'realgud-bp-enabled-face
  153. line-face 'realgud-bp-line-enabled-face
  154. margin-icon realgud-bp-enabled-icon
  155. fringe-icon (car realgud-bp-fringe-indicator-style))
  156. (setq bp-text "b"
  157. bp-face 'realgud-bp-disabled-face
  158. line-face 'realgud-bp-line-disabled-face
  159. margin-icon realgud-bp-disabled-icon
  160. fringe-icon (cdr realgud-bp-fringe-indicator-style)))
  161. (let ((help-echo (format "%s%s: mouse-1 to clear" bp-text bp-num)))
  162. (setq bp-text (propertize bp-text 'help-echo help-echo)))
  163. (with-current-buffer (or buf (current-buffer))
  164. (realgud-bp-remove-icons pos (1+ pos) bp-num)
  165. (let* ((eol (save-excursion (goto-char pos) (point-at-eol)))
  166. (ov (make-overlay pos (1+ eol) (current-buffer) t nil)))
  167. (if (and realgud-bp-use-fringe (display-images-p))
  168. (realgud-bp-add-fringe-icon ov fringe-icon)
  169. (realgud-bp-add-margin-indicator ov bp-text margin-icon bp-face))
  170. (overlay-put ov 'face line-face)
  171. (overlay-put ov 'realgud t)
  172. (overlay-put ov 'realgud-bp-num bp-num)
  173. (overlay-put ov 'realgud-bp-enabled enable?)))))
  174. (defun realgud-bp-del-icon (pos &optional buf bpnum)
  175. "Delete breakpoint icon at POS.
  176. BUF is the buffer which pos refers to (default: current buffer).
  177. If BPNUM is non-nil, only remove overlays maching that breakpoint
  178. number."
  179. (with-current-buffer (or buf (current-buffer))
  180. (realgud-bp-remove-icons pos (1+ pos) bpnum)))
  181. (defun realgud-bp-add-info (loc)
  182. "Record bp information for location LOC."
  183. (if (realgud-loc? loc)
  184. (let* ((marker (realgud-loc-marker loc))
  185. (bp-num (realgud-loc-num loc)))
  186. (realgud-bp-put-icon marker t bp-num))))
  187. (defun realgud-bp-del-info (loc)
  188. "Remove bp information for location LOC."
  189. (if (realgud-loc? loc)
  190. (let* ((marker (realgud-loc-marker loc))
  191. (bp-num (realgud-loc-num loc)))
  192. (realgud-bp-del-icon marker (current-buffer) bp-num))))
  193. (defun realgud-bp-enable-disable-info (bp-num enable? loc buf)
  194. "Enable or disable bp with BP-NUM at location LOC in BUF."
  195. (if (realgud-loc? loc)
  196. (let* ((marker (realgud-loc-marker loc))
  197. (bp-num-check (realgud-loc-num loc)))
  198. (if (eq bp-num bp-num-check)
  199. (realgud-bp-put-icon marker enable? bp-num buf)
  200. (message "Internal error - bp number found %s doesn't match requested %s"
  201. bp-num-check bp-num)
  202. ))))
  203. (provide-me "realgud-")