home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / languages / elisp / modes / xmr / xmr-mode.el < prev    next >
Encoding:
Text File  |  1992-04-05  |  42.3 KB  |  1,345 lines

  1. ;;; sccsinfo: @(#)xmr-mode.el    2.3 4/2/92 isy
  2.  
  3. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  4. ;;;
  5. ;;; File:     xmr-mode.el
  6. ;;; Author:   Ik Su Yoo <ik@ctt.bellcore.com>
  7. ;;; Date:     11/03/91
  8. ;;; Contents: Mode definition for editing X/Motif/WCL resource files.
  9. ;;;
  10. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  11. ;;;
  12. ;;; Copyright (C) 1992, 1991 Ik Su Yoo
  13. ;;;
  14. ;;; This file currently is not part of the GNU Emacs distribution.
  15. ;;;
  16. ;;; This file is distributed in the hope that it will be useful, but
  17. ;;; WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
  18. ;;; to anyone for the consequences of using it or for whether it serves any
  19. ;;; particular purpose or works at all, unless he says so in writing.
  20. ;;; Refer to the GNU Emacs General Public License for full details.
  21. ;;;
  22. ;;; Everyone is granted permission to copy, modify and redistribute this
  23. ;;; file, but only under the conditions described in the GNU Emacs General
  24. ;;; Public License. A copy of this license is supposed to have been given
  25. ;;; to you along with GNU Emacs so you can know your rights and
  26. ;;; responsibilities. It should be in a file named COPYING. Among other
  27. ;;; things, the copyright notice and this notice must be preserved on all
  28. ;;; copies.
  29. ;;;
  30. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  31. ;;;
  32. ;;; History:
  33. ;;;
  34. ;;;   11/20/91
  35. ;;;     - full name completion extended to regular Motif resource files
  36. ;;;     - bug fixed so that non-unique completion always gets reported
  37. ;;;     - bug fixed which didn't do full completion when the resource
  38. ;;;       name matched exactly
  39. ;;;   11/21/91
  40. ;;;     - bug fixed so that when TAB is pressed on a blank line, a line
  41. ;;;       containing comment, or a line that is the continuation of the
  42. ;;;       previous line, it does indentation rather than completion
  43. ;;;     - bug fixed so that the relative completion work when a line is
  44. ;;;       the continuation of the previous line
  45. ;;;     - added complete resource names as found in Xm.h
  46. ;;;   11/25/91
  47. ;;;     - added a function to go to a newline and automatically insert the
  48. ;;;       full object name
  49. ;;;   12/03/91
  50. ;;;     - added a function to display the widget hierarchy
  51. ;;;     - defined an abbrev table of widget class names
  52. ;;;   12/10/91
  53. ;;;     - added abbrev definitions for Motif constructors
  54. ;;;     - added commands to jump to next/previous object
  55. ;;;   12/12/91
  56. ;;;     - modified to assume that each object's specification is delimited
  57. ;;;       by blank lines at the beginning and the end
  58. ;;;     - as a consequence, XRM-PARSE-CONTEXT has been changed;
  59. ;;;       XMR-FULL-COMPLETION-RELATIVE-P no longer applies
  60. ;;;     - fixed a bug which assumed that there is no white space to the
  61. ;;;       left of the delimiting character `:'
  62. ;;;   12/17/91
  63. ;;;     - modified FIND-TAG feature so that it would look up the correct
  64. ;;;       callback function name from a file when figuring out the default
  65. ;;;       tag
  66. ;;;   01/18/92
  67. ;;;     - integrated with a manual browser
  68. ;;;     - added context sensitive resource name completion
  69. ;;;     - fixed a bug which didn't do name completion when the name was empty
  70. ;;;     - fixed xmr-run-program to work with Mri distributed with WCL 1.06
  71. ;;;     - enhanced xmr-display-widget-hierarchy indentation
  72. ;;;   01/31/92
  73. ;;;     - fixed a bug which inserted partially matched resource name into
  74. ;;;       the kill ring
  75. ;;;   03/20/92
  76. ;;;     - defined XMR mode Dmacros
  77. ;;;     - added a function to indent the current resource set or a region
  78. ;;;       containing resource sets
  79. ;;;     - the display name is made optional
  80. ;;;     - fixed xmr-uncomment-region to remove only the first comment
  81. ;;;       character
  82. ;;;     - added a function to rename the current object
  83. ;;;   03/21/92
  84. ;;;     - added a function to search forward/backward objects by name
  85. ;;;     - resource completion extended to include `.wc*' resources and
  86. ;;;       constraint resources
  87. ;;;   03/29/92
  88. ;;;     - fixed a bug in the hierarchy traversal mechanism which didn't
  89. ;;;       follow the `wcPopups' links
  90. ;;;     - added functions to traverse (up, down, left, or right) the widget
  91. ;;;       hierarchy
  92. ;;;     - cleaned up comments
  93. ;;;
  94. ;;; Bugs/limitations:
  95. ;;;
  96. ;;;   - Space after the value of wcClass, wcClassName, or wcConstructor is
  97. ;;;     not handled.
  98. ;;;
  99. ;;;   - The widget hierarchy traversal code is a bit slow.
  100. ;;;
  101. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  102.  
  103. ;;;
  104. ;;; XMR mode is an emacs extension that is useful for editing X/Motif/WCL
  105. ;;; resource files. Basically, it helps you to edit large resource files
  106. ;;; which can become tedious and repetitive. It offers the following
  107. ;;; features:
  108. ;;;
  109. ;;;   - Dmacros and name completion to simplify resource specification.
  110. ;;;
  111. ;;;   - On-line assistance and on-line help during resource specification.
  112. ;;;
  113. ;;;   - Automatic indentation of the resource specification.
  114. ;;;
  115. ;;;   - Navigational aid to traverse the widget hierarchy.
  116. ;;;
  117. ;;;   - Visually displaying the widget hierarchy in another buffer.
  118. ;;;
  119. ;;;   - Limited run-time integration.
  120. ;;;
  121. ;;;   - Commenting/uncommenting regions.
  122. ;;;
  123. ;;; Consult the README file for more details on these features.
  124. ;;;
  125. ;;; To autoload, add the following lines to your .emacs file:
  126. ;;;
  127. ;;;   (setq auto-mode-alist (cons '("\\.ad$" . xmr-mode) auto-mode-alist))
  128. ;;;   (autoload 'xmr-mode "xmr-mode")
  129. ;;;
  130. ;;; The following commands are available:
  131. ;;;
  132. ;;;   xmr-mode                
  133. ;;;
  134. ;;;     Selects the current major mode to be XMR mode.
  135. ;;;
  136. ;;;   xmr-complete-resource-name
  137. ;;;
  138. ;;;     Completes the (partial) resource name that is typed before the point.
  139. ;;;     Beeps when no completion is possible; displays the possibilities
  140. ;;;     when more than 1 completions are possible.
  141. ;;;
  142. ;;;   xmr-display-resource-name-completions    Ctrl-c-h
  143. ;;;
  144. ;;;     Displays the possible resource name completions in a temporary buffer.
  145. ;;;
  146. ;;;   xmr-display-resource-name-completions*    Ctrl-c-Ctrl-h
  147. ;;;
  148. ;;;   xmr-indent-or-complete            TAB
  149. ;;;
  150. ;;;     If the point is on or to the left of `:', it does name completion.
  151. ;;;     Otherwise, it does relative tabbing.
  152. ;;;
  153. ;;;   xmr-indent-or-complete            Meta-TAB
  154. ;;;
  155. ;;;   xmr-yank-previous-object-name        Meta-Ctrl-y
  156. ;;;
  157. ;;;     Yanks the previous object name found in the buffer and inserts it
  158. ;;;     at the current point. Consecutive calls to it will search further
  159. ;;;     back in the buffer.
  160. ;;;
  161. ;;;   xmr-newline-relative            Ctrl-j
  162. ;;;
  163. ;;;     Inserts a newline and automatically inserts the previous line's
  164. ;;;     full object name.
  165. ;;;
  166. ;;;   xmr-next-object                Meta-n
  167. ;;;
  168. ;;;     Moves the point to the beginning of the next object.
  169. ;;;
  170. ;;;   xmr-previous-object            Meta-p
  171. ;;;
  172. ;;;     Moves the point to the beginning of the previous object.
  173. ;;;
  174. ;;;   xmr-goto-parent                Ctrl-c-<
  175. ;;;
  176. ;;;     Moves the point to the beginning of the current object's parent.
  177. ;;;
  178. ;;;   xmr-goto-child                Ctrl-c->
  179. ;;;
  180. ;;;     Moves the point to the beginning of the current object's Nth child,
  181. ;;;     depending on the numeric argument.
  182. ;;;
  183. ;;;   xmr-goto-next-sibling            Ctrl-c-n
  184. ;;;
  185. ;;;     Moves the point to the beginning of the current object's right sibling.
  186. ;;;
  187. ;;;   xmr-goto-previous-sibling            Ctrl-c-p
  188. ;;;
  189. ;;;     Moves the point to the beginning of the current object's left sibling.
  190. ;;;
  191. ;;;   xmr-search-object-forward            Ctrl-c-s
  192. ;;;
  193. ;;;     Searches forward for the object of the given name.
  194. ;;;
  195. ;;;   xmr-search-object-backward        Ctrl-c-r
  196. ;;;
  197. ;;;     Searches backward for the object of the given name.
  198. ;;;
  199. ;;;   xmr-display-widget-hierarchy        Ctrl-c-t
  200. ;;;
  201. ;;;     Displays the widget hierarchy that can be parsed from the current
  202. ;;;     point in a temporary buffer.
  203. ;;;
  204. ;;;   xmr-comment-region            Ctrl-c-c
  205. ;;;
  206. ;;;     Inserts a comment character (`!') to the beginning of every line
  207. ;;;     contained in the region.
  208. ;;;
  209. ;;;   xmr-uncomment-region            Ctrl-c-u
  210. ;;;
  211. ;;;     Removes the comment characters from the beginning of every line
  212. ;;;     contained in the region.
  213. ;;;
  214. ;;;   xmr-run-program                Ctrl-c-Ctrl-r
  215. ;;;
  216. ;;;     Runs the program which makes use of the resource file.
  217. ;;;
  218. ;;;   xmr-man                    Ctrl-c-m
  219. ;;;
  220. ;;;     Display the man page for a Motif widget.
  221. ;;;
  222. ;;;   xmr-rename-object                Ctrl-c-s
  223. ;;;
  224. ;;;     Renames the current object.
  225. ;;;
  226. ;;;   xmr-indent-region                Meta-Ctrl-\
  227. ;;;
  228. ;;;     Formats the resource specification contained in the given region.
  229. ;;;
  230. ;;;   xmr-fill-paragraph            Meta-q
  231. ;;;
  232. ;;;     Formats the current object's resource specification.
  233. ;;;
  234. ;;; You may set the following variables according to your environment:
  235. ;;;
  236. ;;;   xmr-wcl-p
  237. ;;;
  238. ;;;     Set this to T (the default) if you are editing WCL resource files,
  239. ;;;     NIL if editing regular Motif resource files. If you edit both WCL
  240. ;;;     resource files and regular Motif resource files, setting this to T
  241. ;;;     globally won't effect the way the completion is done for the Motif
  242. ;;;     resource files.
  243. ;;;
  244. ;;;   xmr-full-completion-p
  245. ;;;
  246. ;;;     Set this to T (the default), if you want a full name completion.
  247. ;;;     What this means is that when you simply have a (partial) resource
  248. ;;;     name on a line by itself, the name completion process may figure
  249. ;;;     out the object name you intended and insert it for you
  250. ;;;     automatically, while at the same time doing the name completion.
  251. ;;;     For example:
  252. ;;;
  253. ;;;       *main.wcClass:    xmMainWindowWidgetClass
  254. ;;;       wi
  255. ;;;
  256. ;;;     When you type TAB after the "wi" above, it will result in the
  257. ;;;     following:
  258. ;;;
  259. ;;;       *main.wcClass:    xmMainWindowWidgetClass
  260. ;;;       *main.width
  261. ;;;
  262. ;;;   xmr-complete-resource-name-display-p
  263. ;;;
  264. ;;;     Set this to T, if you want to display the possible completions in a
  265. ;;;     temporary buffer. Set it to NIL (the default), if you simply want
  266. ;;;     to be told that there are multiple completions.
  267. ;;;
  268. ;;;   xmr-program-name
  269. ;;;
  270. ;;;     Set this to the name of the program to run using the XMR-RUN-PROGRAM
  271. ;;;     command. It defaults to "Mri".
  272. ;;;
  273. ;;;   xmr-display-name
  274. ;;;
  275. ;;;     Set this to the name of the display where your X server is running.
  276. ;;;     It defaults to NIL.
  277. ;;;
  278. ;;;   xmr-tree-indent
  279. ;;;
  280. ;;;     Set this to the string used to recursively indent when
  281. ;;;     displaying the widget hierarchy. The default is "| ".
  282. ;;;
  283. ;;;   xmr-rhs-column
  284. ;;;
  285. ;;;     Set this to the column where the resource values should be aligned
  286. ;;;     when indenting a region. The default is 40.
  287. ;;;
  288. ;;; The customization for each resource file is conveniently done by
  289. ;;; putting something like the following lines near the bottom of the file:
  290. ;;; 
  291. ;;;   !
  292. ;;;   ! Local Variables:
  293. ;;;   ! mode: xmr
  294. ;;;   ! comment-column: 0
  295. ;;;   ! comment-start: "!"
  296. ;;;   ! xmr-wcl-p: t
  297. ;;;   ! xmr-full-completion-p: t
  298. ;;;   ! xmr-complete-resource-name-display-p: nil
  299. ;;;   ! xmr-program-name: "/user/spock/xvulcan"
  300. ;;;   ! xmr-display-name: "enterprise:0"
  301. ;;;   ! xmr-tree-indent: "  "
  302. ;;;   ! xmr-rhs-column: 60
  303. ;;;   ! End:
  304. ;;;   !
  305. ;;;
  306.  
  307. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  308. ;;;
  309. ;;; helping functions and macros
  310. ;;;
  311. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  312.  
  313. (defmacro skip-forward-until-regexp (regexp)
  314.   (list 'while
  315.     (list 'and
  316.           (list 'not (list 'eobp))
  317.           (list 'not (list 'looking-at regexp)))
  318.     (list 'next-line 1)))
  319.  
  320. (defmacro skip-forward-while-regexp (regexp)
  321.   (list 'while
  322.     (list 'and
  323.           (list 'not (list 'eobp))
  324.           (list 'looking-at regexp))
  325.     (list 'next-line 1)))
  326.  
  327. (defmacro skip-backward-until-regexp (regexp)
  328.   (list 'while
  329.     (list 'and
  330.           (list 'not (list 'bobp))
  331.           (list 'not (list 'looking-at regexp)))
  332.     (list 'previous-line 1)))
  333.  
  334. (defmacro skip-backward-while-regexp (regexp)
  335.   (list 'while
  336.     (list 'and
  337.           (list 'not (list 'bobp))
  338.           (list 'looking-at regexp))
  339.     (list 'previous-line 1)))
  340.  
  341. ;;;
  342. ;;; True iff CH is an alphabet character.
  343. ;;;
  344. (defmacro alphabet-p (ch)
  345.   (list 'and
  346.     (list '>= (list 'downcase ch) ?a)
  347.     (list '<= (list 'downcase ch) ?z)))
  348.  
  349. ;;;
  350. ;;; Like MEMQ, but it works for strings.
  351. ;;;
  352. (defun string-member (string string-list)
  353.   (cond ((null string-list)
  354.      nil)
  355.     ((string= string (car string-list))
  356.      string-list)
  357.     (t
  358.      (string-member string (cdr string-list)))))
  359.  
  360. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  361. ;;;
  362. ;;; internal functions and variables
  363. ;;;
  364. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  365.  
  366. (defvar xmr-comment-prefix "!")
  367. (defvar xmr-delimiter ":")
  368. (defvar xmr-continue "\\")
  369. (defvar xmr-name-delimiter ".")
  370. (defvar xmr-name-delimiter* "*")
  371. (defvar xmr-list-delimiters ", \t\n\\")
  372.  
  373. (defvar xmr-wcclass-regexp "wcclass\\|wcconstructor\\|wcclassname")
  374. (defvar xmr-wcchildren-regexp "wcChildren")
  375. (defvar xmr-wcpopups-regexp "wcPopups")
  376. (defvar xmr-class-name-regexp "[a-zA-Z]+")
  377. (defvar xmr-object-name-regexp "[a-zA-Z0-9_]+")
  378. (defvar xmr-full-object-name-regexp "^[a-zA-Z0-9\*\._]+")
  379. (defvar xmr-resource-name-regexp "[a-zA-Z]+")
  380. (defvar xmr-name-delimiter-regexp "[\*\.]")
  381.  
  382. (defvar xmr-blank-line-regexp "^[ \t]*$")
  383.  
  384. ;;;
  385. ;;; Context information and the stack used to save and restore them.
  386. ;;;
  387. (defvar xmr-context-stack nil)
  388. (defvar xmr-current-class-name nil)
  389. (defvar xmr-current-object-name nil)
  390. (defvar xmr-parent-class-name nil)
  391. (defvar xmr-parent-object-name nil)
  392. (defvar xmr-children-names nil)
  393.  
  394. (defvar xmr-lhs-regexp (concat xmr-full-object-name-regexp
  395.                    xmr-name-delimiter-regexp
  396.                    xmr-resource-name-regexp))
  397.  
  398. (defvar xmr-resource-name-closure nil
  399.   "Controls the scope of the resource completion to include all resources or
  400. only non-inherited resources.")
  401.  
  402. ;;;
  403. ;;; Returns the largest suffix of name not containing a name delimiter.
  404. ;;;
  405. (defun xmr-clean-name (name)
  406.   (if (string-match (format ".*%s" xmr-name-delimiter-regexp) name)
  407.       (substring name (match-end 0))
  408.     name))
  409.  
  410. ;;;
  411. ;;; This function takes a constructor name, class name, or a class pointer
  412. ;;; name and returns the corresponding class name.
  413. ;;;
  414. (defun xmr-convert-class-name (thing)
  415.   (let (class-symbol
  416.     pos)
  417.     (cond ((string-match "^XmCreate" thing)
  418.        ;;
  419.        ;; constructor: XmCreate???
  420.        ;;
  421.        (setq class-symbol (intern (concat "Xm" (substring thing 8)))))
  422.       ((setq pos (string-match "WidgetClass" thing))
  423.        ;;
  424.        ;; class pointer: xm???WidgetClass
  425.        ;;
  426.        (setq class-symbol
  427.          (intern (concat (char-to-string (upcase (string-to-char thing)))
  428.                  (substring thing 1 pos)))))
  429.       ((setq pos (string-match "GadgetClass" thing))
  430.        (setq class-symbol
  431.          (intern (concat (char-to-string (upcase (string-to-char thing)))
  432.                  (substring thing 1 (+ pos (length "Gadget")))))))
  433.       (t
  434.        ;;
  435.        ;; class: Xm???
  436.        ;;
  437.        (setq class-symbol (intern thing))))
  438.     (and (setq class-symbol (car (memq class-symbol xmr-class-symbols)))
  439.      (symbol-name class-symbol))))
  440.  
  441. ;;;
  442. ;;; This function returns the class pointer name associated with the
  443. ;;; class name.
  444. ;;;
  445. (defun xmr-class-pointer (name)
  446.   (concat (char-to-string (downcase (string-to-char name)))
  447.       (substring name 1)
  448.       "WidgetClass"))
  449.  
  450. ;;;
  451. ;;; This function returns the constructor name associated with the class
  452. ;;; name.
  453. ;;;
  454. (defun xmr-class-constructor (name)
  455.   (if (char-equal (string-to-char name) ?X)
  456.       (concat "XmCreate" (substring name 2))))
  457.  
  458. ;;;
  459. ;;; This function returns the man page name associated with the class name.
  460. ;;;
  461. (defun xmr-class-manpage (name)
  462.   (get (and name (intern name)) 'manpage))
  463.  
  464. ;;;
  465. ;;; This function returns the list of resource names, excluding inherited
  466. ;;; resources, associated with the class name.
  467. ;;;
  468. (defun xmr-class-resources (name)
  469.   (let ((class-symbol (and name (intern name))))
  470.     (or (get class-symbol 'resources)
  471.     (get (get class-symbol 'resources-shadow) 'resources))))
  472.  
  473. ;;;
  474. ;;; This function returns the list of all resource names associated with the
  475. ;;; class name.
  476. ;;;
  477. (defun xmr-class-resources* (name)
  478.   (let ((class-symbol (and name (intern name))))
  479.     (or (get class-symbol 'resources*)
  480.     (get (get class-symbol 'resources-shadow) 'resources*))))
  481.  
  482. ;;;
  483. ;;; This function returns the list of all constraint resource names
  484. ;;; associated with the class name.
  485. ;;;
  486. (defun xmr-class-resources-constraint (name)
  487.   (let ((class-symbol (and name (intern name))))
  488.     (get class-symbol 'resources-constraint)))
  489.  
  490. ;;;
  491. ;;; This function returns T iff the point is currently on or to the left of
  492. ;;; the resource name/value delimiter.
  493. ;;;
  494. (defun xmr-left-of-delimiter-p ()
  495.   (save-excursion
  496.     (save-restriction
  497.       (let ((end (point)))
  498.     (beginning-of-line)
  499.     (narrow-to-region (point) end)
  500.     (not (search-forward xmr-delimiter nil t nil))))))
  501.  
  502. ;;;
  503. ;;; This function returns T iff the current line is the continuation of the
  504. ;;; previous line.
  505. ;;;
  506. (defun xmr-line-continued-p ()
  507.   (save-excursion
  508.     (beginning-of-line)
  509.     (if (bobp)
  510.     nil
  511.       (let ((limit (point)))
  512.     (backward-char 2)
  513.     (search-forward xmr-continue limit t)))))
  514.  
  515. ;;;
  516. ;;; This function returns T iff the current line "needs" name completion.
  517. ;;;
  518. (defun xmr-need-completion-p ()
  519.   (and (save-excursion
  520.      (beginning-of-line)
  521.      (and (not (looking-at "^[ \t]*$"))
  522.           (not (looking-at xmr-comment-prefix))))
  523.        (xmr-left-of-delimiter-p)
  524.        (not (xmr-line-continued-p))))
  525.  
  526. ;;;
  527. ;;; This function returns T iff the current line contains an object name.
  528. ;;;
  529. (defun xmr-line-contains-object-name-p ()
  530.   (save-excursion
  531.     (save-restriction
  532.       (let ((end (point)))
  533.     (beginning-of-line)
  534.     (narrow-to-region (point) end)
  535.     (re-search-forward xmr-name-delimiter-regexp nil t nil)))))
  536.  
  537. ;;;
  538. ;;; This function returns the completion alist to be used in completing
  539. ;;; resource names, depending on the current context. The context
  540. ;;; determines which resource names are available.
  541. ;;;
  542. (defun xmr-get-completion-alist ()
  543.   (append xmr-resources-permanent
  544.       (if xmr-resource-name-closure
  545.           (xmr-class-resources* xmr-current-class-name)
  546.         (xmr-class-resources xmr-current-class-name))
  547.       (xmr-class-resources-constraint xmr-parent-class-name)))
  548.  
  549. ;;;
  550. ;;; This function saves the current context into the stack.
  551. ;;;
  552. (defun xmr-push-context ()
  553.   (setq xmr-context-stack
  554.     (cons (list xmr-current-class-name
  555.             xmr-current-object-name
  556.             xmr-children-names)
  557.           xmr-context-stack)))
  558.  
  559. ;;;
  560. ;;; This function restores the most recently saved context from the stack.
  561. ;;;
  562. (defun xmr-pop-context ()
  563.   (let ((context (car xmr-context-stack)))
  564.     (setq xmr-context-stack (cdr xmr-context-stack))
  565.     (setq xmr-current-class-name (nth 0 context))
  566.     (setq xmr-current-object-name (nth 1 context))
  567.     (setq xmr-children-names (nth 2 context))))
  568.  
  569. ;;;
  570. ;;; Parse for the object name.
  571. ;;;
  572. (defun xmr-parse-object-name ()
  573.   (goto-char (point-min))
  574.   (if (not (re-search-forward (concat xmr-lhs-regexp
  575.                       "[ \t]*"
  576.                       xmr-delimiter)
  577.                   nil t nil))
  578.       ()
  579.     (backward-word 1)
  580.     (backward-char 1)
  581.     (set-mark (point))
  582.     (beginning-of-line)
  583.     (buffer-substring (point) (mark))))
  584.  
  585. ;;;
  586. ;;; Parse for the class name.
  587. ;;;
  588. (defun xmr-parse-object-class-name ()
  589.   (goto-char (point-min))
  590.   (if (not (re-search-forward xmr-wcclass-regexp nil t nil))
  591.       ()
  592.     (end-of-line)
  593.     (set-mark (point))
  594.     (backward-word 1)
  595.     (if (looking-at xmr-class-name-regexp)
  596.     (xmr-convert-class-name (buffer-substring (point) (mark))))))
  597.  
  598. (defun xmr-parse-parent-name ()
  599.   )
  600.  
  601. (defun xmr-parse-parent-class-name ()
  602.   )
  603.  
  604. ;;;
  605. ;;; Parse for the children names.
  606. ;;;
  607. (defun xmr-parse-children-names ()
  608.   (goto-char (point-min))
  609.   (cdr (xmr-parse-widget-hierarchy nil)))
  610.  
  611. ;;;
  612. ;;; This function parses the current context that includes the following
  613. ;;; information:
  614. ;;;
  615. ;;;   - object name
  616. ;;;   - object class name
  617. ;;;   - parent name
  618. ;;;   - parent class name
  619. ;;;   - children names
  620. ;;;
  621. ;;; If FULL-P is NIL, only the first two are looked for. Otherwise, all of
  622. ;;; the above are looked for.
  623. ;;;
  624. (defun xmr-parse-context (&optional full-p)
  625.   (save-excursion
  626.     (xmr-narrow-to-object)
  627.     (setq xmr-current-class-name (xmr-parse-object-class-name))
  628.     (setq xmr-current-object-name (xmr-parse-object-name))
  629.     (if full-p
  630.     (setq xmr-children-names (xmr-parse-children-names)))
  631.     ;;
  632.     ;; In order to parse the parent's information, we need to get out of
  633.     ;; the narrowed region.
  634.     ;;
  635.     (widen)
  636.     (let ((object-name (and xmr-current-object-name
  637.                 (xmr-clean-name xmr-current-object-name)))
  638.       pclass-name
  639.       children-names
  640.       found-p)
  641.       (if (null object-name)
  642.       ()
  643.     (while (and (not found-p)
  644.             (re-search-backward (format "%s\\|%s"
  645.                         xmr-wcchildren-regexp
  646.                         xmr-wcpopups-regexp)
  647.                     nil t nil))
  648.       (save-excursion
  649.         (save-restriction
  650.           (xmr-narrow-to-object)
  651.           (setq children-names (xmr-parse-children-names))
  652.           (if (not (string-member object-name children-names))
  653.           ()
  654.         (setq found-p t)
  655.         (setq xmr-parent-class-name (xmr-parse-object-class-name))
  656.         (setq xmr-parent-object-name (xmr-parse-object-name))))))))))
  657.  
  658. ;;;
  659. ;;; This function takes a (partial) resource name and displays the possible
  660. ;;; completions in a temporary buffer.
  661. ;;;
  662. (defun xmr-list-completions-in-buffer (name)
  663.   (with-output-to-temp-buffer "*XMR Completion*"
  664.       (display-completion-list (all-completions name
  665.                         (xmr-get-completion-alist)))))
  666.  
  667. ;;;
  668. ;;; This function narrows the buffer to contain only the current object
  669. ;;; specification. The object specification is assumed to be delimited at
  670. ;;; it beginning and end by at least 1 blank line.
  671. ;;;
  672. (defun xmr-narrow-to-object ()
  673.   (let ((point-save (point))
  674.     point-begin
  675.     point-end)
  676.     (beginning-of-line)
  677.     (skip-backward-until-regexp xmr-blank-line-regexp)
  678.     (if (looking-at xmr-blank-line-regexp)
  679.     (next-line 1))
  680.     (setq point-begin (point))
  681.     (goto-char point-save)
  682.     (skip-forward-until-regexp xmr-blank-line-regexp)
  683.     (setq point-end (point))
  684.     (narrow-to-region point-begin point-end)
  685.     (goto-char point-save)))
  686.  
  687. ;;;
  688. ;;; This function narrows the buffer to contain only the current word
  689. ;;; before the point.
  690. ;;;
  691. (defun xmr-narrow-to-word ()
  692.   (let ((point-save (point)))
  693.     ;;
  694.     ;; Narrow the region to the current line so that we don't back over
  695.     ;; to the previous line.
  696.     ;;
  697.     (beginning-of-line)
  698.     (save-restriction
  699.       (narrow-to-region (point) point-save)
  700.       (goto-char point-save)
  701.       (while (and (not (bobp))
  702.           (alphabet-p (preceding-char)))
  703.     (backward-char 1)))
  704.     ;;
  705.     ;; Narrow the region to the current word to be completed.
  706.     ;;
  707.     (narrow-to-region (point) point-save)))
  708.  
  709. ;;;
  710. ;;; This function calls an auxiliary function to display the given tree
  711. ;;; specification to a temporary buffer.
  712. ;;;
  713. (defun xmr-list-tree-in-buffer (tree)
  714.   (with-output-to-temp-buffer "*XMR Widget Hierarchy*"
  715.     (xmr-list-tree-in-buffer-aux tree 0)))
  716.  
  717. ;;;
  718. ;;; This function recursively prints the given tree specification. It first
  719. ;;; prints the root of TREE is printed indented. Then, the children
  720. ;;; subtrees are recursively printed with the indentation incremented
  721. ;;; appropriately.
  722. ;;;
  723. (defun xmr-list-tree-in-buffer-aux (tree indent)
  724.   (cond ((null tree))
  725.     ((not (listp tree))
  726.      ;;
  727.      ;; The TREE is a leaf node.
  728.      ;;
  729.      (while (> indent 0)
  730.        (princ xmr-tree-indent)
  731.        (setq indent (1- indent)))
  732.      (princ tree)
  733.      (terpri))
  734.     (t
  735.      ;;
  736.      ;; Print the root followed by the subtrees.
  737.      ;;
  738.      (xmr-list-tree-in-buffer-aux (car tree) indent)
  739.      (setq indent (1+ indent))
  740.      (mapcar '(lambda (subtree)
  741.             (xmr-list-tree-in-buffer-aux subtree indent))
  742.          (cdr tree)))))
  743.  
  744. ;;;
  745. ;;; This function parses the widget hierarchy specification in a WCL file,
  746. ;;; starting at the current point, and returns the hierarchy. It follows
  747. ;;; the `wcChildren' and `wcPopups' links and collects all the names
  748. ;;; contained in the process. The tree specification returned has the
  749. ;;; following syntax: 
  750. ;;;
  751. ;;;   - If it is a string, it is a leaf node.
  752. ;;;   - If it is a list, its head is the root and the tail is a list of the
  753. ;;;     children subtree specifications.
  754. ;;;
  755. ;;; For example, the following shows a tree and its corresponding tree
  756. ;;; specification:
  757. ;;;
  758. ;;;     A
  759. ;;;    / \
  760. ;;;   B  C    ->  (A B (C D E))
  761. ;;;     / \
  762. ;;;    D   E
  763. ;;;
  764. ;;; If RECURSIVE-P is non-NIL, the entire widget hierarchy is collected.
  765. ;;; Otherwise, only the current node and its children are collected.
  766. ;;;
  767. (defun xmr-parse-widget-hierarchy (&optional recursive-p)
  768.   (save-excursion
  769.     (let ((object-name (save-restriction
  770.              (xmr-narrow-to-object)
  771.              (xmr-parse-object-name)))
  772.       subtree)
  773.       (if (null object-name)
  774.       ()
  775.     ;;
  776.     ;; Start from the beginning of the object specification.
  777.     ;;
  778.     (skip-backward-until-regexp xmr-blank-line-regexp)
  779.     (setq subtree (xmr-parse-widget-hierarchy-aux object-name recursive-p))
  780.     (if (listp subtree)
  781.         subtree
  782.       (list subtree))))))
  783.   
  784. (defun xmr-parse-widget-hierarchy-aux (object-name recursive-p)
  785.   ;;
  786.   ;; Need to scan twice: once to follow the `wcChildren' link and
  787.   ;; another to follow the `wcPopups' link.
  788.   ;;
  789.   (let ((children-names (xmr-parse-widget-children
  790.              (concat object-name
  791.                  xmr-name-delimiter-regexp
  792.                  xmr-wcchildren-regexp)))
  793.     (popup-names (xmr-parse-widget-children
  794.               (concat object-name
  795.                   xmr-name-delimiter-regexp
  796.                   xmr-wcpopups-regexp))))
  797.     (setq children-names (append children-names popup-names))
  798.     (cond ((null children-names)
  799.        object-name)
  800.       ((not recursive-p)
  801.        (cons object-name children-names))
  802.       (t
  803.        (cons object-name
  804.          (mapcar '(lambda (name)
  805.                 (xmr-parse-widget-hierarchy-aux name recursive-p))
  806.              children-names))))))
  807.  
  808. (defun xmr-parse-widget-children (regexp)
  809.   (save-excursion
  810.     (if (not (re-search-forward regexp nil t nil))
  811.     ()
  812.       (let (start
  813.         end)
  814.     (save-restriction
  815.       ;;
  816.       ;; Narrow the working region to all lines that constitute the
  817.       ;; current children entry.
  818.       ;;
  819.       (beginning-of-line)
  820.       (setq start (point))
  821.       (end-of-line)
  822.       (backward-char 1)
  823.       (while (and (not (eobp))
  824.               (looking-at (regexp-quote xmr-continue)))
  825.         (next-line 1)
  826.         (end-of-line)
  827.         (backward-char))
  828.       (end-of-line)
  829.       (setq end (point))
  830.       (narrow-to-region start end)
  831.       (beginning-of-buffer)
  832.       ;;
  833.       ;; Start from the right of the "wcChildren" (or "wcPopups") entry and
  834.       ;; collect all the child names.
  835.       ;;
  836.       (re-search-forward (regexp-quote xmr-delimiter))
  837.       (xmr-parse-object-names (point) end))))))
  838.  
  839. ;;;
  840. ;;; This function returns the object names contained in the given region as
  841. ;;; a list of strings.
  842. ;;;
  843. (defun xmr-parse-object-names (start end)
  844.   (save-excursion
  845.     (if (>= start end)
  846.     ()
  847.       (goto-char start)
  848.       (re-search-forward (concat "[" xmr-list-delimiters "]*") end)
  849.       (set-mark (point))
  850.       (re-search-forward (concat "[^" xmr-list-delimiters "]+") end t nil)
  851.       (if (= (mark) (point))
  852.       ()
  853.     (cons (buffer-substring (mark) (point))
  854.           (xmr-parse-object-names (point) end))))))
  855.  
  856. ;;;
  857. ;;; This function prompts the user for a class name, which defaults to the
  858. ;;; current object's class name, and returns it in a list.
  859. ;;;
  860. (defun xmr-read-class-name (prompt)
  861.   (let* ((class-name (progn
  862.                (xmr-parse-context)
  863.                xmr-current-class-name))
  864.      (thing (read-string (if class-name
  865.                  (format "%s(default %s) " prompt class-name)
  866.                    prompt))))
  867.     (if (not (equal thing ""))
  868.     (setq class-name (or (xmr-convert-class-name thing) thing)))
  869.     (list class-name)))
  870.  
  871. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  872. ;;;
  873. ;;; external (interactive) functions and variables
  874. ;;;
  875. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  876.  
  877. (defvar xmr-wcl-p t
  878.   "T if editing WCL resource file; NIL if editing regular Motif resource file.")
  879.  
  880. (defvar xmr-full-completion-p t
  881.   "T if you want object name completion as well.")
  882.  
  883. (defvar xmr-complete-resource-name-display-p nil
  884.   "T if all matching names should be displayed during name completion.")
  885.  
  886. (defvar xmr-program-name "Mri"
  887.   "Name of the program to run to test the resource file.")
  888.  
  889. (defvar xmr-display-name nil
  890.   "Name of the X display. NIL means use the DISPLAY variable.")
  891.  
  892. (defvar xmr-tree-indent "| "
  893.   "String used to indent when displaying the widget tree.")
  894.  
  895. (defvar xmr-rhs-column 40
  896.   "Used for automatic indentation of the resource values.")
  897.  
  898. (defvar xmr-cbtable-filename nil
  899.   "?")
  900.  
  901. ;(defvar xmr-mode-syntax-table nil
  902. ;  "Syntax table used while in XMR mode.")
  903.  
  904. (defvar xmr-mode-abbrev-table nil
  905.   "Abbrev table used while in XMR mode.")
  906.  
  907. (defvar xmr-mode-map nil)
  908. (if xmr-mode-map
  909.     ()
  910.   (setq xmr-mode-map (make-sparse-keymap))
  911.   (define-key xmr-mode-map "\t" 'xmr-indent-or-complete)
  912.   (define-key xmr-mode-map "\C-c\t" 'xmr-indent-or-complete*)
  913.   (define-key xmr-mode-map "\C-ch" 'xmr-display-resource-name-completions)
  914.   (define-key xmr-mode-map "\C-c\C-h" 'xmr-display-resource-name-completions*)
  915.   (define-key xmr-mode-map "\C-cc" 'xmr-comment-region)
  916.   (define-key xmr-mode-map "\C-cu" 'xmr-uncomment-region)
  917.   (define-key xmr-mode-map "\C-c\C-r" 'xmr-run-program)
  918.   (define-key xmr-mode-map "\C-ct" 'xmr-display-widget-hierarchy)
  919.   (define-key xmr-mode-map "\C-j" 'xmr-newline-relative)
  920.   (define-key xmr-mode-map "\C-cm" 'xmr-man)
  921.   (define-key xmr-mode-map "\C-c\C-s" 'xmr-rename-object)
  922.   (define-key xmr-mode-map "\e\C-\\" 'xmr-indent-region)
  923.   (define-key xmr-mode-map "\eq" 'xmr-fill-paragraph)
  924.   (define-key xmr-mode-map "\en" 'xmr-next-object)
  925.   (define-key xmr-mode-map "\ep" 'xmr-previous-object)
  926.   (define-key xmr-mode-map "\C-c>" 'xmr-goto-child)
  927.   (define-key xmr-mode-map "\C-c<" 'xmr-goto-parent)
  928.   (define-key xmr-mode-map "\C-cn" 'xmr-goto-next-sibling)
  929.   (define-key xmr-mode-map "\C-cp" 'xmr-goto-previous-sibling)
  930.   (define-key xmr-mode-map "\C-cs" 'xmr-search-object-forward)
  931.   (define-key xmr-mode-map "\C-cr" 'xmr-search-object-backward)
  932.   )
  933.  
  934. ;;;
  935. ;;; 03/17/92 isy
  936. ;;;
  937. ;;; The abbrev stuff has been removed in favor of Dmacro.
  938. ;;;
  939. (define-abbrev-table 'xmr-mode-abbrev-table nil)
  940. ; (define-abbrev-table 'xmr-mode-abbrev-table
  941. ;   '(
  942. ;     ;;
  943. ;     ;; primitives
  944. ;     ;;
  945. ;     ("ab" "xmArrowButtonWidgetClass"    nil 0)
  946. ;     ("cb" "xmCascadeButtonWidgetClass"  nil 0)
  947. ;     ("pb" "xmPushButtonWidgetClass"     nil 0)
  948. ;     ("te" "xmTextWidgetClass"           nil 0)
  949. ;     ("li" "xmListWidgetClass"           nil 0)
  950. ;     ("tb" "xmToggleButtonWidgetClass"   nil 0)
  951. ;     ("se" "xmSeparatorWidgetClass"      nil 0)
  952. ;     ("la" "xmLabelWidgetClass"          nil 0)
  953. ;     ("sc" "xmScaleWidgetClass"          nil 0)
  954. ;     ("sb" "xmScrollBarWidgetClass"      nil 0)
  955. ;     ;;
  956. ;     ;; composites
  957. ;     ;;
  958. ;     ("bb" "xmBulletinBoardWidgetClass"  nil 0)
  959. ;     ("mw" "xmMainWindowWidgetClass"     nil 0)
  960. ;     ("fr" "xmFrameWidgetClass"          nil 0)
  961. ;     ("fo" "xmFormWidgetClass"           nil 0)
  962. ;     ("sw" "xmScrolledWindowWidgetClass" nil 0)
  963. ;     ("da" "xmDrawingAreaWidgetClass"    nil 0)
  964. ;     ("pw" "xmPanedWindowWidgetClass"    nil 0)
  965. ;     ("rc" "xmRowColumnWidgetClass"      nil 0)
  966. ;     ;;
  967. ;     ;; constructors
  968. ;     ;;
  969. ;     ("csli" "XmCreateScrolledList"        nil 0)
  970. ;     ("cste" "XmCreateScrolledText"        nil 0)
  971. ;     ("cmb"  "XmCreateMenuBar"             nil 0)
  972. ;     ("copm" "XmCreateOptionMenu"          nil 0)
  973. ;     ("cpom" "XmCreatePopupMenu"           nil 0)
  974. ;     ("cpum" "XmCreatePulldownMenu"        nil 0)
  975. ;     ("cfsb" "XmCreateFileSelectionBox"    nil 0)
  976. ;     ("cmeb" "XmCreateMessageBox"          nil 0)
  977. ;     ("crab" "XmCreateRadioBox"            nil 0)
  978. ;     ("cseb" "XmCreateSelectionBox"        nil 0)
  979. ;     ("cbbd" "XmCreateBulletinBoardDialog" nil 0)
  980. ;     ("cerd" "XmCreateErrorDialog"         nil 0)
  981. ;     ("cind" "XmCreateInformationDialog"   nil 0)
  982. ;     ("cfsd" "XmCreateFileSelectionDialog" nil 0)
  983. ;     ("cfod" "XmCreateFormDialog"          nil 0)
  984. ;     ("cmed" "XmCreateMessageDialog"       nil 0)
  985. ;     ("cprd" "XmCreatePromptDialog"        nil 0)
  986. ;     ("cqud" "XmCreateQuestionDialog"      nil 0)
  987. ;     ("csed" "XmCreateSelectionDialog"     nil 0)
  988. ;     ("cwad" "XmCreateWarningDialog"       nil 0)
  989. ;     ("cwod" "XmCreateWorkingDialog"       nil 0)
  990. ;     ))
  991.  
  992. (defun xmr-mode ()
  993.   "Major mode for editing X/Motif/WCL resource files.\\{xmr-mode-map}
  994. Turning on xmr-mode calls the value of the variable xmr-mode-hook,
  995. if that value is non-NIL."
  996.   (interactive)
  997.   (kill-all-local-variables)
  998.   (use-local-map text-mode-map)
  999.   (use-local-map indented-text-mode-map)
  1000.   (use-local-map xmr-mode-map)
  1001.   (setq local-abbrev-table xmr-mode-abbrev-table)
  1002.   (set-syntax-table text-mode-syntax-table)
  1003.   (make-local-variable 'indent-line-function)
  1004.   (setq indent-line-function 'indent-relative-maybe)
  1005.   (setq mode-name "XMR")
  1006.   (setq major-mode 'xmr-mode)
  1007.   (run-hooks 'xmr-mode-hook))
  1008.  
  1009. (defun xmr-complete-resource-name ()
  1010.   "Completes the (partial) resource name that is typed before the point.
  1011. If no completion is possible, it beeps; if more than 1 completion is
  1012. possible, it displays the possibilities in a temporary buffer."
  1013.   (interactive)
  1014.   (save-restriction
  1015.     (let ((point-save (point))
  1016.       (line-contains-object-name-p (xmr-line-contains-object-name-p)))
  1017.       (xmr-parse-context)
  1018.       (xmr-narrow-to-word)
  1019.       (let* ((xmr-alist (xmr-get-completion-alist))
  1020.          (part-name (buffer-string))
  1021.          (full-name (try-completion part-name xmr-alist)))
  1022.     (cond ((eq full-name t)
  1023.            ;;
  1024.            ;; There is an exact match. See if we still need to do a
  1025.            ;; full completion.
  1026.            ;;
  1027.            (delete-region (point-min) (point-max))
  1028.            (cond ((and xmr-current-object-name
  1029.                xmr-full-completion-p
  1030.                (not line-contains-object-name-p))
  1031.               (insert xmr-current-object-name)
  1032.               (insert xmr-name-delimiter)))
  1033.            (insert part-name)
  1034.            )
  1035.           ((null full-name)
  1036.            ;;
  1037.            ;; There is no completion. Inform the user and restore the
  1038.            ;; cursor to its original position.
  1039.            ;;
  1040.            (ding)
  1041.            (goto-char point-save))
  1042.           (t
  1043.            ;;
  1044.            ;; There is a completion. Use it to substitute and position
  1045.            ;; the cursor so that the user may go on typing.
  1046.            ;;
  1047.            (beginning-of-line)
  1048.            (kill-line)
  1049.            (cond ((and xmr-current-object-name
  1050.                xmr-full-completion-p
  1051.                (not line-contains-object-name-p))
  1052.               (insert xmr-current-object-name)
  1053.               (insert xmr-name-delimiter)))
  1054.            (insert full-name)
  1055.            ;;
  1056.            ;; Try the completion again to see whether the completion
  1057.            ;; was unique or not.
  1058.            ;;
  1059.            (setq full-name (try-completion full-name xmr-alist))
  1060.            (if (not (eq full-name t))
  1061.            (if (not xmr-complete-resource-name-display-p)
  1062.                (message "Resource name not unique.")
  1063.              (xmr-list-completions-in-buffer part-name)))))))))
  1064.  
  1065. (defun xmr-display-resource-name-completions ()
  1066.   "Displays the possible resource name completions in a temporary buffer."
  1067.   (interactive)
  1068.   (if (xmr-need-completion-p)
  1069.       (save-excursion
  1070.     (save-restriction
  1071.       (xmr-narrow-to-word)
  1072.       (xmr-list-completions-in-buffer (buffer-string))))))
  1073.  
  1074. (defun xmr-display-resource-name-completions* ()
  1075.   "Displays the possible resource name completions (including the inherited
  1076. ones) in a temporary buffer."
  1077.   (interactive)
  1078.   (let ((xmr-resource-name-closure t))
  1079.     (xmr-display-resource-name-completions)))
  1080.  
  1081. (defun xmr-indent-or-complete ()
  1082.   "If the resource name is currently being typed, does the name completion.
  1083. Else, it does indentation."
  1084.   (interactive)
  1085.   (if (xmr-need-completion-p)
  1086.       (xmr-complete-resource-name)
  1087.     (indent-relative)))
  1088.  
  1089. (defun xmr-indent-or-complete* ()
  1090.   (interactive)
  1091.   (let ((xmr-resource-name-closure t))
  1092.     (xmr-indent-or-complete)))
  1093.  
  1094. (defun xmr-newline-relative ()
  1095.   "Inserts a newline and automatically inserts the previous line's
  1096. full object name. Need to be at the end of the current line."
  1097.   (interactive)
  1098.   (if (or (not (eolp)) (bolp))
  1099.       (ding)
  1100.     (cond ((string= (char-to-string (preceding-char)) xmr-continue)
  1101.        (newline)
  1102.        (indent-relative))
  1103.       (t
  1104.        (xmr-parse-context)
  1105.        (if (not xmr-current-object-name)
  1106.            (ding)
  1107.          (newline)
  1108.          (insert xmr-current-object-name))))))
  1109.  
  1110. (defun xmr-next-object ()
  1111.   "Moves the point to the beginning of the next object."
  1112.   (interactive)
  1113.   (beginning-of-line)
  1114.   (skip-forward-until-regexp xmr-blank-line-regexp)
  1115.   (skip-forward-while-regexp xmr-blank-line-regexp))
  1116.  
  1117. (defun xmr-previous-object ()
  1118.   "Moves the point to the beginning of the previous object."
  1119.   (interactive)
  1120.   (beginning-of-line)
  1121.   (if (not (looking-at xmr-blank-line-regexp))
  1122.       (skip-backward-until-regexp xmr-blank-line-regexp))
  1123.   (skip-backward-while-regexp xmr-blank-line-regexp)
  1124.   (skip-backward-until-regexp xmr-blank-line-regexp)
  1125.   (skip-forward-while-regexp xmr-blank-line-regexp))
  1126.  
  1127. (defun xmr-goto-parent ()
  1128.   "Moves the point to the beginning of the current object's parent."
  1129.   (interactive)
  1130.   (xmr-parse-context t)
  1131.   (if xmr-parent-object-name
  1132.       (xmr-search-object-backward (xmr-clean-name xmr-parent-object-name))))
  1133.  
  1134. (defun xmr-goto-child (count)
  1135.   "Moves the point to the beginning of the current object's COUNT'th child."
  1136.   (interactive "P")
  1137.   (if (null count)
  1138.       (setq count 0)
  1139.     (setq count (- count 1)))
  1140.   (xmr-parse-context t)
  1141.   (xmr-search-object-forward (nth count xmr-children-names)))
  1142.  
  1143. (defun xmr-goto-next-sibling ()
  1144.   "Moves the point to the beginning of the current object's right sibling."
  1145.   (interactive)
  1146.   (xmr-parse-context t)
  1147.   (if (null xmr-parent-object-name)
  1148.       ()
  1149.     (let ((object-name (xmr-clean-name xmr-current-object-name))
  1150.       (point-save (point))
  1151.       subtree
  1152.       sibling-name)
  1153.       ;;
  1154.       ;; Determine the right sibling by looking at the object's parent's
  1155.       ;; children.
  1156.       ;;
  1157.       (xmr-search-object-backward (xmr-clean-name xmr-parent-object-name))
  1158.       (setq subtree (xmr-parse-widget-hierarchy nil))
  1159.       (setq sibling-name (car (cdr (string-member object-name
  1160.                           (cdr subtree)))))
  1161.       (if sibling-name
  1162.       (xmr-search-object-forward sibling-name)
  1163.     (goto-char point-save)))))
  1164.  
  1165. (defun xmr-goto-previous-sibling ()
  1166.   "Moves the point to the beginning of the current object's left sibling."
  1167.   (interactive)
  1168.   (xmr-parse-context t)
  1169.   (if (null xmr-parent-object-name)
  1170.       ()
  1171.     (let ((object-name (xmr-clean-name xmr-current-object-name))
  1172.       (point-save (point))
  1173.       subtree
  1174.       sibling-name)
  1175.       ;;
  1176.       ;; Determine the left sibling by looking at the object's parent's
  1177.       ;; children.
  1178.       ;;
  1179.       (xmr-search-object-backward (xmr-clean-name xmr-parent-object-name))
  1180.       (setq subtree (xmr-parse-widget-hierarchy nil))
  1181.       (setq sibling-name (car (cdr (string-member object-name
  1182.                           (reverse (cdr subtree))))))
  1183.       (if sibling-name
  1184.       (xmr-search-object-forward sibling-name)
  1185.     (goto-char point-save)))))
  1186.  
  1187. (defun xmr-search-object-forward (name)
  1188.   "Searches forward for the object of the given name."
  1189.   (interactive "sName: ")
  1190.   (if (re-search-forward (format "%s.\\(%s\\)" name xmr-wcclass-regexp)
  1191.              nil t nil)
  1192.       (beginning-of-line)
  1193.     (ding)))
  1194.  
  1195. (defun xmr-search-object-backward (name)
  1196.   "Searches backward for the object of the given name."
  1197.   (interactive "sName: ")
  1198.   (if (re-search-backward (format "%s.\\(%s\\)" name xmr-wcclass-regexp)
  1199.               nil t nil)
  1200.       (beginning-of-line)
  1201.     (ding)))
  1202.  
  1203. (defun xmr-display-widget-hierarchy ()
  1204.   "Displays the widget hierarchy that can be parsed (by following the
  1205. `wcChildren' links) from the current point in a temporary buffer."
  1206.   (interactive)
  1207.   (if xmr-wcl-p
  1208.       (xmr-list-tree-in-buffer (xmr-parse-widget-hierarchy t))))
  1209.  
  1210. ;;;
  1211. ;;; 01/27/92 courtesy of Ernst Lippe (lippe@serc.nl)
  1212. ;;;
  1213. (defun xmr-comment-region (start end)
  1214.    "Comments out the lines in the region."
  1215.   (interactive "r")
  1216.   (save-excursion
  1217.     (save-restriction 
  1218.       (narrow-to-region start end)
  1219.       (goto-char (point-min))
  1220.       (replace-regexp "^."
  1221.               (concat (regexp-quote xmr-comment-prefix) "\\&")))))
  1222.  
  1223. (defun xmr-uncomment-region (start end)
  1224.    "Uncomments commented lines in the region."
  1225.   (interactive "r")
  1226.   (save-excursion
  1227.     (save-restriction 
  1228.       (narrow-to-region start end)
  1229.       (goto-char (point-min))
  1230.       (while (< (point) (point-max))
  1231.     (if (eq (following-char) (string-to-char xmr-comment-prefix))
  1232.       (delete-char 1))
  1233.     (end-of-line)
  1234.     (if (< (point) (point-max))
  1235.         (forward-char 1))))))
  1236.  
  1237. (defun xmr-run-program ()
  1238.   "Runs the XMR program which uses the resource file."
  1239.   (interactive)
  1240.   (let ((shell "sh")
  1241.     (process-name "XMR Shell")
  1242.     (buffer-name "*XMR Shell Output*")
  1243.     (display-name (or xmr-display-name (getenv "DISPLAY"))))
  1244.     (cond ((null xmr-program-name)
  1245.        (error "XMR program name not set."))
  1246.       ((null display-name)
  1247.        (error "XMR display name not set."))
  1248.       (t
  1249.        ;;
  1250.        ;; Can have at most 1 process running at a time.
  1251.        ;;
  1252.        (if (or (not (eq (process-status process-name) 'run))
  1253.            (y-or-n-p "XMR program running, kill it? "))
  1254.          (condition-case ()
  1255.          (progn
  1256.            (interrupt-process process-name)
  1257.            (sit-for 1)
  1258.            (delete-process process-name))
  1259.            (error nil))
  1260.          (error "XMR program already running."))
  1261.        (start-process process-name buffer-name shell)
  1262.        ;;
  1263.        ;; set DISPLAY
  1264.        ;;
  1265.        (process-send-string process-name
  1266.                 (format "DISPLAY=%s;export DISPLAY\n"
  1267.                     display-name))
  1268.        ;;
  1269.        ;; set XENVIRONMENT
  1270.        ;;
  1271.        (process-send-string process-name
  1272.                 (format "XENVIRONMENT=%s; export XENVIRONMENT\n"
  1273.                     (buffer-file-name)))
  1274.        (if (string= "Mri" xmr-program-name) 
  1275.            (process-send-string process-name
  1276.                     (format "exec %s %s\n"
  1277.                         xmr-program-name
  1278.                         (file-name-nondirectory (buffer-file-name))))
  1279.          (process-send-string process-name
  1280.                   (format "exec %s\n" xmr-program-name)))))))
  1281.  
  1282. (defun xmr-man (class-name)
  1283.   "Display the man page for a Motif widget."
  1284.   (interactive (xmr-read-class-name "Man page for widget: "))
  1285.   (let ((manpage-name (and class-name (xmr-class-manpage class-name))))
  1286.     (cond ((null manpage-name)
  1287.        (message (format "Man page for %s not found." class-name))
  1288.        (ding))
  1289.       (t
  1290.        (save-excursion
  1291.          (man (format "%s(3X)" manpage-name)))
  1292.        (let ((pop-up-windows t))
  1293.          (display-buffer manual-buffer-name))))))
  1294.  
  1295. (defun xmr-rename-object ()
  1296.   "Renames the current object's name."
  1297.   (interactive)
  1298.   (xmr-parse-context)
  1299.   (if (null xmr-current-object-name)
  1300.       (ding)
  1301.     (let ((new-name (read-string "New name: ")))
  1302.       (if (equal new-name "")
  1303.       ()
  1304.     (save-excursion
  1305.       (save-restriction
  1306.         (xmr-narrow-to-object)
  1307.         (goto-char (point-min))
  1308.         (replace-regexp (concat "^" xmr-current-object-name)
  1309.                 new-name)))))))
  1310.  
  1311. (defun xmr-indent-region (start end)
  1312.   "Formats the resource specification contained in the given region."
  1313.  (interactive "r")
  1314.  (save-excursion
  1315.   (save-restriction
  1316.     (narrow-to-region start end)
  1317.     (goto-char (point-min))
  1318.     (while (re-search-forward (concat "^[^"
  1319.                       xmr-comment-prefix
  1320.                       " \t"
  1321.                       "].*"
  1322.                       xmr-delimiter)
  1323.                   nil t nil)
  1324.       (delete-horizontal-space)
  1325.       (while (< (current-column) xmr-rhs-column)
  1326.     (tab-to-tab-stop))))))
  1327.  
  1328. (defun xmr-fill-paragraph ()
  1329.   "Formats the current object's resource specification."
  1330.   (interactive)
  1331.   (save-excursion
  1332.     (save-restriction
  1333.       (xmr-narrow-to-object)
  1334.       (xmr-indent-region (point-min) (point-max)))))
  1335.  
  1336. ;;;
  1337. ;;; packages required
  1338. ;;;
  1339.  
  1340. (require 'manual "man")
  1341. (require 'xmr-database "xmr-database")
  1342. (if (memq 'dmacro features)
  1343.     (require 'xmr-dmacro "dm-xmr"))
  1344. (provide 'xmr-mode)
  1345.