~ubuntu-branches/ubuntu/saucy/ecb/saucy

« back to all changes in this revision

Viewing changes to ecb-util.el

  • Committer: Bazaar Package Importer
  • Author(s): Joerg Jaspert
  • Date: 2004-09-01 22:15:18 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040901221518-0jfdt2apb2rj69ey
Tags: 2.27-1
And include latest Upstream too...

Show diffs side-by-side

added added

removed removed

Lines of Context:
26
26
;; GNU Emacs; see the file COPYING.  If not, write to the Free Software
27
27
;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28
28
 
29
 
;; $Id: ecb-util.el,v 1.97 2004/02/16 08:56:24 berndl Exp $
 
29
;; $Id: ecb-util.el,v 1.111 2004/08/25 15:09:06 berndl Exp $
30
30
 
31
31
;;; Commentary:
32
32
;;
60
60
(silentcomp-defvar noninteractive)
61
61
(silentcomp-defun window-edges)
62
62
(silentcomp-defun buffer-local-value)
 
63
(silentcomp-defun posn-point)
 
64
(silentcomp-defun posn-window)
 
65
(silentcomp-defun event-start)
63
66
;; XEmacs
64
67
(silentcomp-defun mswindows-cygwin-to-win32-path)
65
68
(silentcomp-defun make-dialog-box)
81
84
(silentcomp-defun thing-boundaries)
82
85
(silentcomp-defun thing-symbol)
83
86
 
 
87
(silentcomp-defun custom-file)
84
88
 
85
89
;; Some constants
86
90
(defconst ecb-running-xemacs (string-match "XEmacs\\|Lucid" emacs-version))
87
91
(defconst ecb-running-emacs-21 (and (not ecb-running-xemacs)
88
92
                                    (> emacs-major-version 20)))
89
93
 
90
 
(defconst ecb-directory-sep-char ?/)
 
94
;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: Test this with native
 
95
;; Windows-XEmacs if it works with this change correct and also if it works
 
96
;; without this change incorrect!
 
97
(defconst ecb-directory-sep-char
 
98
  (if ecb-running-xemacs directory-sep-char ?/))
91
99
(defconst ecb-directory-sep-string (char-to-string ecb-directory-sep-char))
92
100
 
93
101
(defconst ecb-temp-dir
125
133
           (display-images-p)
126
134
         window-system)))
127
135
 
 
136
;; -------------------------------------------------------------------
 
137
;; Tracing - currently not used because we use the trace.el library!
 
138
;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: Offer conveniant wrappers for the
 
139
;; trace-function-background stuff so users can easily trace a set of
 
140
;; ecb-functions if there occur problems where a backtrace can not be
 
141
;; generated.
 
142
 
 
143
(defvar ecb-trace-defun-enter t)
 
144
(defvar ecb-trace-defun-leave t)
 
145
 
 
146
(defsubst ecb-defun-trace (mode fcn)
 
147
  (cond ((equal mode 'enter)
 
148
         (and ecb-trace-defun-enter
 
149
              (message "ECB-function %S entered!" fcn)))
 
150
        ((equal mode 'leave)
 
151
         (and ecb-trace-defun-leave
 
152
              (message "ECB-function %S leaved!" fcn)))))
 
153
 
 
154
(defmacro ecb-defun (name args docstring &rest body)
 
155
  `(eval-and-compile
 
156
     (defun ,name ,args
 
157
       ,docstring
 
158
       ,@(if (not (equal (caar body) 'interactive))
 
159
             (append (list `(ecb-defun-trace 'enter (quote ,name)))
 
160
                     (list `(prog1 (progn
 
161
                                     ,@body)
 
162
                              (ecb-defun-trace 'leave (quote ,name)))))
 
163
           (append (list (car body))
 
164
                   (list `(ecb-defun-trace 'enter (quote ,name)))
 
165
                   (list `(prog1 (progn
 
166
                                   ,@(cdr body))
 
167
                            (ecb-defun-trace 'leave (quote ,name)))))))))
 
168
 
 
169
 
 
170
;; -------------------------------------------------------------------
 
171
 
 
172
 
128
173
;; ---------- compatibility between GNU Emacs and XEmacs ---------------------
129
174
 
130
175
;; miscellaneous differences
132
177
(if ecb-running-xemacs
133
178
    (progn
134
179
;;; Compatibility
 
180
      (defun ecb-facep (face)
 
181
        (memq face (face-list)))
135
182
      (defun ecb-noninteractive ()
136
183
        "Return non-nil if running non-interactively, i.e. in batch mode."
137
184
        (noninteractive))
148
195
      (defalias 'ecb-frame-parameter 'frame-property)
149
196
      (defalias 'ecb-line-beginning-pos 'point-at-bol)
150
197
      (defalias 'ecb-line-end-pos 'point-at-eol)
 
198
      (defalias 'ecb-event-window 'event-window)
 
199
      (defalias 'ecb-event-point 'event-point)
 
200
      (defalias 'ecb-event-buffer 'event-buffer)
151
201
      (defalias 'ecb-window-full-width 'window-full-width)
152
202
      (defalias 'ecb-window-full-height 'window-height)
153
203
      (defun ecb-frame-char-width (&optional frame)
161
211
                (/ (nth 2 pix-edges) (ecb-frame-char-width))
162
212
                (/ (nth 3 pix-edges) (ecb-frame-char-height))))))
163
213
      
 
214
  (defalias 'ecb-facep 'facep)
164
215
  (defun ecb-noninteractive ()
165
216
    "Return non-nil if running non-interactively, i.e. in batch mode."
166
217
    noninteractive)
167
218
  (defalias 'ecb-subst-char-in-string 'subst-char-in-string)
168
 
  (defalias 'ecb-thing-at-point 'thing-at-point)
169
219
  (defalias 'ecb-frame-parameter 'frame-parameter)
170
220
  (defalias 'ecb-line-beginning-pos 'line-beginning-position)
171
221
  (defalias 'ecb-line-end-pos 'line-end-position)
 
222
  (defun ecb-event-window (event)
 
223
    (posn-window (event-start event)))
 
224
  (defun ecb-event-point (event)
 
225
    (posn-point (event-start event)))
 
226
  (defun ecb-event-buffer (event)
 
227
    (window-buffer (ecb-event-window event)))
172
228
  (defun ecb-window-full-width (&optional window)
173
229
    (let ((edges (window-edges window)))
174
230
      (- (nth 2 edges) (nth 0 edges))))
238
294
 
239
295
;; ---------- End of compatibility between GNU Emacs and XEmacs -------------
240
296
  
 
297
(if (fboundp 'compare-strings)
 
298
    (defalias 'ecb-compare-strings 'compare-strings)
 
299
  (defun ecb-compare-strings (str1 start1 end1 str2 start2 end2 &optional ignore-case)
 
300
    "Compare the contents of two strings.
 
301
In string STR1, skip the first START1 characters and stop at END1.
 
302
In string STR2, skip the first START2 characters and stop at END2.
 
303
END1 and END2 default to the full lengths of the respective strings.
 
304
 
 
305
Case is significant in this comparison if IGNORE-CASE is nil.
 
306
 
 
307
The value is t if the strings (or specified portions) match.
 
308
If string STR1 is less, the value is a negative number N;
 
309
  - 1 - N is the number of characters that match at the beginning.
 
310
If string STR1 is greater, the value is a positive number N;
 
311
  N - 1 is the number of characters that match at the beginning."
 
312
    (or start1 (setq start1 0))
 
313
    (or start2 (setq start2 0))
 
314
    (setq end1 (if end1
 
315
                   (min end1 (length str1))
 
316
                 (length str1)))
 
317
    (setq end2 (if end2
 
318
                   (min end2 (length str2))
 
319
                 (length str2)))
 
320
    (let ((i1 start1)
 
321
          (i2 start2)
 
322
          result c1 c2)
 
323
      (while (and (not result) (< i1 end1) (< i2 end2))
 
324
        (setq c1 (aref str1 i1)
 
325
              c2 (aref str2 i2)
 
326
              i1 (1+ i1)
 
327
              i2 (1+ i2))
 
328
        (if ignore-case
 
329
            (setq c1 (upcase c1)
 
330
                  c2 (upcase c2)))
 
331
        (setq result (cond ((< c1 c2) (- i1))
 
332
                           ((> c1 c2) i1))))
 
333
      (or result
 
334
          (cond ((< i1 end1) (1+ (- i1 start1)))
 
335
                ((< i2 end2) (1- (- start1 i1)))
 
336
                (t)))
 
337
      )))
 
338
 
 
339
(defsubst ecb-string= (str1 str2 &optional ignore-case)
 
340
  (let ((s1 (or (and (stringp str1) str1) (symbol-name str1)))
 
341
        (s2 (or (and (stringp str2) str2) (symbol-name str2))))
 
342
    (eq (ecb-compare-strings s1 nil nil s2 nil nil ignore-case) t)))
 
343
 
 
344
(defsubst ecb-string< (str1 str2 &optional ignore-case)
 
345
  (let ((s1 (or (and (stringp str1) str1) (symbol-name str1)))
 
346
        (s2 (or (and (stringp str2) str2) (symbol-name str2)))
 
347
        (result nil))
 
348
    (setq result (ecb-compare-strings s1 nil nil s2 nil nil ignore-case))
 
349
    (and (numberp result) (< result 0))))
 
350
 
241
351
;; Emacs 20 has no window-list function and the XEmacs and Emacs 21 one has no
242
352
;; specified ordering. The following one is stolen from XEmacs and has fixed
243
353
;; this lack of a well defined order. We preserve also point of current
285
395
        ;; of this function
286
396
        (goto-char current-point)))))
287
397
 
 
398
(defun ecb-canonical-windows-list ()
 
399
  "Return a list of all current visible windows in the `ecb-frame' \(starting
 
400
  from the left-most top-most window) in the order `other-window' would walk
 
401
  through these windows."
 
402
  (ecb-window-list ecb-frame 0 (frame-first-window ecb-frame)))
 
403
 
288
404
 
289
405
;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: Attention. Current mechanism of
290
406
;; (de)activating the basic advices and the intelligent window advices of
302
418
                                            (scroll-other-window . around)
303
419
                                            (custom-save-all . around)
304
420
                                            (count-windows . around)
305
 
                                            (narrow-to-region . before)
306
 
                                            (narrow-to-defun . before)
307
 
                                            (narrow-to-page . before)
308
 
                                            (widen . before)
309
421
                                            (scroll-all-mode . after))
310
422
                                        '((delete-frame . around)
311
423
                                          (compilation-set-window-height . around)
321
433
                                          (tmm-prompt . around)
322
434
                                          (scroll-other-window . around)
323
435
                                          (custom-save-all . around)
324
 
                                          (narrow-to-region . before)
325
 
                                          (narrow-to-defun . before)
326
 
                                          (narrow-to-page . before)
327
 
                                          (widen . before)
328
436
                                          (count-windows . around)
329
437
                                          (scroll-all-mode . after)))
330
438
  "These functions are always adviced if ECB is active. Each element of the
389
497
 
390
498
;; some basic advices
391
499
 
 
500
(defun ecb-custom-file ()
 
501
  "Filename of that file which is used by \(X)Emacs to store the
 
502
customize-options."
 
503
  (cond (ecb-running-xemacs
 
504
         custom-file)
 
505
        (ecb-running-emacs-21
 
506
         (custom-file))
 
507
        (t
 
508
         (or custom-file
 
509
             user-init-file))))
 
510
 
392
511
(defadvice custom-save-all (around ecb)
393
512
  "Save the customized options completely in the background, i.e. the
394
513
file-buffer where the value is saved \(see option `custom-file') is not parsed
395
514
by semantic and also killed afterwards."
396
515
  (if ecb-minor-mode
397
 
      (let ((ecb-window-sync nil)
 
516
      (let (;; XEmacs 21.4 does not set this so we do it here, to ensure that
 
517
            ;; the custom-file is loadede in an emacs-lisp-mode buffer, s.b.
 
518
            (default-major-mode 'emacs-lisp-mode)
 
519
            (ecb-window-sync nil)
398
520
            (kill-buffer-hook nil)
399
521
            ;; we prevent parsing the custom-file
400
522
            (semantic-before-toplevel-bovination-hook (lambda ()
401
523
                                                        nil))
 
524
            (semantic--before-fetch-tags-hook (lambda ()
 
525
                                                nil))
402
526
            (semantic-after-toplevel-cache-change-hook nil)
403
527
            (semantic-after-partial-cache-change-hook nil))
404
 
        ;; now we do the standard task
405
 
        ad-do-it
 
528
        ;; Klaus Berndl <klaus.berndl@sdm.de>: we must ensure that the
 
529
        ;; current-buffer has a lisp major-mode when the kernel of
 
530
        ;; `custom-save-all' is called because cause of a bug (IMHO) in the
 
531
        ;; `custom-save-delete' of GNU Emacs (which loads the file returned by
 
532
        ;; `custom-file' with `default-major-mode' set to nil which in turn
 
533
        ;; causes that new buffer will get the major-mode of the
 
534
        ;; current-buffer) the file `custom-file' will get the major-mode of
 
535
        ;; the current-buffer. So when the current-buffer has for example
 
536
        ;; major-mode `c++-mode' then the file `custom-file' will be loaded
 
537
        ;; into a buffer with major-mode c++-mode. The function
 
538
        ;; `custom-save-delete' then parses this buffer with (forward-sexp
 
539
        ;; (buffer-size)) which of course fails because forward-sexp tries to
 
540
        ;; parse the custom-file (which is an emacs-lisp-file) as a c++-file
 
541
        ;; with c++-paren-syntax.
 
542
        ;; Solution: Ensure that the buffer *scratch* is current when calling
 
543
        ;; custom-save-all so we have surely a lispy-buffer and therefore we
 
544
        ;; can be sure that custom-file is loaded as lispy-buffer.
 
545
        (save-excursion
 
546
          (set-buffer (get-buffer-create "*scratch*"))
 
547
          ;; now we do the standard task
 
548
          ad-do-it)
406
549
        ;; now we have to kill the custom-file buffer otherwise semantic would
407
550
        ;; parse the buffer of custom-file and the method-buffer would be
408
551
        ;; updated with the contents of custom-file which is definitely not
409
552
        ;; desired.
410
553
        (ignore-errors
411
 
          (kill-buffer (find-file-noselect (cond (ecb-running-xemacs
412
 
                                                  custom-file)
413
 
                                                 (ecb-running-emacs-21
414
 
                                                  (custom-file))
415
 
                                                 (t
416
 
                                                  (or custom-file
417
 
                                                      user-init-file)))))))
 
554
          (kill-buffer (find-file-noselect (ecb-custom-file)))))
418
555
    ad-do-it))
419
556
 
420
557
;; assoc helpers
427
564
                                elem)))
428
565
                  list)))
429
566
 
 
567
 
430
568
(defun ecb-add-assoc (key-value list)
431
569
  (cons key-value list))
432
570
 
492
630
      (member item list)
493
631
    (memq item list)))
494
632
 
 
633
(defsubst ecb-match-regexp-list (str regexp-list &optional elem-accessor
 
634
                                     return-accessor)
 
635
  "Return not nil if STR matches one of the regexps in REGEXP-LIST. If
 
636
ELEM-ACCESSOR is a function then it is used to get the regexp from the
 
637
processed elem of REGEXP-LIST. If nil the elem itself is used. If
 
638
RETURN-ACCESSOR is a function then it is used to get from the matching elem
 
639
the object to return. If nil then the matching elem itself is returned."
 
640
  (let ((elem-acc (or elem-accessor 'identity))
 
641
        (return-acc (or return-accessor 'identity)))
 
642
    (catch 'exit
 
643
      (dolist (elem regexp-list)
 
644
        (let ((case-fold-search t))
 
645
          (save-match-data
 
646
            (if (string-match (funcall elem-acc elem) str)
 
647
                (throw 'exit (funcall return-acc elem))))
 
648
          nil)))))
 
649
 
 
650
 
495
651
(defun ecb-set-elt (seq n val)
496
652
  "Set VAL as new N-th element of SEQ. SEQ can be any sequence. SEQ will be
497
 
changed."
498
 
  (if (listp seq) (setcar (nthcdr n seq) val) (aset seq n val)))
 
653
changed because this is desctructive function. SEQ is returned."
 
654
  (if (listp seq)
 
655
      (setcar (nthcdr n seq) val)
 
656
    (aset seq n val))
 
657
  seq)
 
658
 
 
659
(defun ecb-replace-first-occurence (seq old-elem new-elem)
 
660
  "Replace in SEQ the first occurence of OLD-ELEM with NEW-ELEM. Comparison is
 
661
done by `equal'. This is desctructive function. SEQ is returned."
 
662
  (let ((pos (ecb-position seq old-elem)))
 
663
    (if pos
 
664
        (ecb-set-elt seq pos new-elem)))
 
665
  seq)
 
666
 
 
667
(defun ecb-replace-all-occurences (seq old-elem new-elem)
 
668
  "Replace in SEQ all occurences of OLD-ELEM with NEW-ELEM. Comparison is
 
669
done by `equal'. This is desctructive function. SEQ is returned."
 
670
  (while (ecb-position seq old-elem)
 
671
    (setq seq (ecb-replace-first-occurence seq old-elem new-elem)))
 
672
  seq)
 
673
 
 
674
(defun ecb-remove-first-occurence-from-list (list elem)
 
675
  "Replace first occurence of ELEM from LIST. Comparison is done by `equal'.
 
676
This is desctructive function. LIST is returned."
 
677
  (delq nil (ecb-replace-first-occurence list elem nil)))
 
678
 
 
679
(defun ecb-remove-all-occurences-from-list (list elem)
 
680
  "Replace all occurences of ELEM from LIST. Comparison is done by `equal'.
 
681
This is desctructive function. LIST is returned."
 
682
  (delq nil
 
683
        (progn          
 
684
          (while (ecb-position list elem)
 
685
            (setq list (ecb-replace-first-occurence list elem nil)))
 
686
          list)))
499
687
 
500
688
;; canonical filenames
501
689
 
 
690
(defun ecb-fix-path (path)
 
691
  "Fixes an annoying behavior of the native windows-version of XEmacs:
 
692
When PATH contains only a drive-letter and a : then `expand-file-name' does
 
693
not interpret this PATH as root of that drive. So we add a trailing
 
694
`directory-sep-char' and return this new path because then `expand-file-name'
 
695
treats this as root-dir of that drive. For all \(X)Emacs-version besides the
 
696
native-windows-XEmacs PATH is returned."
 
697
  (if (and ecb-running-xemacs
 
698
           (equal system-type 'windows-nt))
 
699
      (if (and (= (length path) 2)
 
700
               (equal (aref path 1) ?:))
 
701
          (concat path ecb-directory-sep-string)
 
702
        path)
 
703
    path))
 
704
 
 
705
;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: What about the new cygwin-version
 
706
;; of GNU Emacs 21? We have to test if this function and all locations where
 
707
;; `ecb-fix-path' is used work correctly with the cygwin-port of GNU Emacs.
502
708
(defun ecb-fix-filename (path &optional filename substitute-env-vars)
503
709
  "Normalizes path- and filenames for ECB. If FILENAME is not nil its pure
504
710
filename \(i.e. without directory part) will be concatenated to PATH. The
506
712
not nil then in both PATH and FILENAME env-var substitution is done. If the
507
713
`system-type' is 'cygwin32 then the path is converted to win32-path-style!"
508
714
  (when (stringp path)
509
 
    (let (norm-path)    
510
 
      (setq norm-path (if (and ecb-running-xemacs (equal system-type 'cygwin32))
511
 
                          (mswindows-cygwin-to-win32-path path)
512
 
                        path))
 
715
    (let (norm-path)
 
716
      (setq norm-path (if ecb-running-xemacs
 
717
                          (cond ((equal system-type 'cygwin32)
 
718
                                 (mswindows-cygwin-to-win32-path
 
719
                                  (expand-file-name path)))
 
720
                                ((equal system-type 'windows-nt)
 
721
                                 (expand-file-name (ecb-fix-path path)))
 
722
                                (t (expand-file-name path)))
 
723
                        (expand-file-name path)))
 
724
      ;; For windows systems we normalize drive-letters to downcase
 
725
      (setq norm-path (if (and (member system-type '(windows-nt cygwin32))
 
726
                               (> (length norm-path) 1)
 
727
                               (equal (aref norm-path 1) ?:))
 
728
                          (concat (downcase (substring norm-path 0 2))
 
729
                                  (substring norm-path 2))
 
730
                        norm-path))
 
731
      ;; substitute environment-variables
513
732
      (setq norm-path (expand-file-name (if substitute-env-vars
514
733
                                            (substitute-in-file-name norm-path)
515
734
                                          norm-path)))
 
735
      ;; delete a trailing directory-separator if there is any
516
736
      (setq norm-path (if (and (> (length norm-path) 1)
517
737
                               (= (aref norm-path
518
738
                                        (1- (length norm-path))) ecb-directory-sep-char))
576
796
    (error "Window is not alive!")))
577
797
 
578
798
;; stolen from query.el and slightly enhanced
579
 
;; This for a small number of choices each of them a short string
 
799
;; This is for a small number of choices each of them a short string
580
800
(defun ecb-query-string (prompt choices &optional other-prompt)
581
801
  "Prints PROMPT and returns a string which must be one of CHOICES.
582
802
CHOICES is either a list of strings whereas the first choice is the default
601
821
                                     new-choices)
602
822
                             '('("" t))))
603
823
    (setq answer (completing-read prompt new-choices nil t))
604
 
    (cond ((string= answer "")
 
824
    (cond ((ecb-string= answer "")
605
825
           (setq answer default))
606
 
          ((string= answer "other")
 
826
          ((ecb-string= answer "other")
607
827
           (setq answer (read-string (concat other-prompt ": ")))))
608
828
    answer))
609
829
 
625
845
                                  completion-list
626
846
                                  nil t
627
847
                                  (try-completion "" completion-list))))
628
 
    (if (string= answer "")
 
848
    (if (ecb-string= answer "")
629
849
        (car choices)
630
850
      answer)))
631
851
 
648
868
                  (mapcar (function (lambda (x) (list x t)))
649
869
                          choices)
650
870
                  nil t)))
651
 
    (if (string= answer "")
 
871
    (if (ecb-string= answer "")
652
872
        (car choices)
653
873
      answer)))
654
874
 
671
891
                 (mapcar (function (lambda (x) (list x t)))
672
892
                         choices)
673
893
                 nil t)))
674
 
    (if (string= answer "")
 
894
    (if (ecb-string= answer "")
675
895
        (car choices)
676
896
      answer)))
677
897
 
736
956
  (let ((init (cond ((numberp init-value)
737
957
                     (number-to-string init-value))
738
958
                    ((stringp init-value)
739
 
                     (if (string= init-value "0")
 
959
                     (if (ecb-string= init-value "0")
740
960
                         init-value
741
961
                       (if (not (= 0 (string-to-number init-value)))
742
962
                           init-value
745
965
        result)
746
966
    (while (progn
747
967
             (setq result (read-string prompt init))
748
 
             (not (or (string= "0" result)
 
968
             (not (or (ecb-string= "0" result)
749
969
                      (not (= 0 (string-to-number result)))))))
750
970
    (string-to-number result)))
751
971
 
799
1019
(defun ecb-merge-face-into-text (text face)
800
1020
  "Merge FACE to the already precolored TEXT so the values of all
801
1021
face-attributes of FACE take effect and but the values of all face-attributes
802
 
of TEXT which are not set by FACE are preserved.
803
 
For XEmacs this merge does currently not work therefore here FACE replaces all
804
 
faces of TEXT!"
 
1022
of TEXT which are not set by FACE are preserved."
805
1023
  (if (null face)
806
1024
      text
807
 
    (let ((newtext (concat text)))
808
 
      (if ecb-running-xemacs
809
 
          (add-text-properties 0 (length newtext) (list 'face face) newtext)
810
 
        (alter-text-property 0 (length newtext) 'face
811
 
                             (lambda (current-face)
812
 
                               (let ((cf
813
 
                                      (cond ((facep current-face)
814
 
                                             (list current-face))
815
 
                                            ((listp current-face)
816
 
                                             current-face)
817
 
                                            (t nil)))
818
 
                                     (nf
819
 
                                      (cond ((facep face)
820
 
                                             (list face))
821
 
                                            ((listp face)
822
 
                                             face)
823
 
                                            (t nil))))
824
 
                                 ;; we must add the new-face in front of
825
 
                                 ;; current-face to get the right merge!
826
 
                                 (append nf cf)))
827
 
                             newtext))
828
 
      newtext)))
829
 
 
 
1025
    (if ecb-running-xemacs
 
1026
        (put-text-property 0 (length text) 'face
 
1027
                           (let* ((current-face (get-text-property 0
 
1028
                                                                   'face
 
1029
                                                                   text))
 
1030
                                  (cf
 
1031
                                   (cond ((ecb-facep current-face)
 
1032
                                          (list current-face))
 
1033
                                         ((listp current-face)
 
1034
                                          current-face)
 
1035
                                         (t nil)))
 
1036
                                  (nf
 
1037
                                   (cond ((ecb-facep face)
 
1038
                                          (list face))
 
1039
                                         ((listp face)
 
1040
                                          face)
 
1041
                                         (t nil))))
 
1042
                             ;; we must add the new-face in front of
 
1043
                             ;; current-face to get the right merge!
 
1044
                             (append nf cf))
 
1045
                           text)
 
1046
      (alter-text-property 0 (length text) 'face
 
1047
                           (lambda (current-face)
 
1048
                             (let ((cf
 
1049
                                    (cond ((ecb-facep current-face)
 
1050
                                           (list current-face))
 
1051
                                          ((listp current-face)
 
1052
                                           current-face)
 
1053
                                          (t nil)))
 
1054
                                   (nf
 
1055
                                    (cond ((ecb-facep face)
 
1056
                                           (list face))
 
1057
                                          ((listp face)
 
1058
                                           face)
 
1059
                                          (t nil))))
 
1060
                               ;; we must add the new-face in front of
 
1061
                               ;; current-face to get the right merge!
 
1062
                               (append nf cf)))
 
1063
                           text))
 
1064
    text))
830
1065
 
831
1066
(defun ecb-error (&rest args)
832
1067
  "Signals an error but prevents it from entering the debugger. This is
865
1100
  (let ((split-result (split-string str "^[\n\t ]*")))
866
1101
    (or (or (and (cdr split-result) ;; GNU Emacs > 21.3
867
1102
                 (car (cdr split-result)))
868
 
            (car split-result)) "")))
 
1103
            (car split-result))
 
1104
        "")))
869
1105
 
870
1106
(defun ecb-right-trim (str)
871
1107
  "Return a string stripped of all trailing whitespaces of STR."
995
1231
        ;; (if (not (sit-for timeout)) (read-event))
996
1232
        ))))
997
1233
 
998
 
(defun ecb-position (list elem)
999
 
  "Return the position of ELEM within LIST counting from 0. Comparison is done
 
1234
(defun ecb-position (seq elem)
 
1235
  "Return the position of ELEM within SEQ counting from 0. Comparison is done
1000
1236
with `equal'."
1001
 
  (let ((pos (1- (length (member elem (reverse list))))))
1002
 
    (if (< pos 0)
1003
 
        nil
1004
 
      pos)))
 
1237
  (if (listp seq)
 
1238
      (let ((pos (- (length seq) (length (member elem seq)))))
 
1239
        (if (= pos (length seq))
 
1240
            nil
 
1241
          pos))
 
1242
    (catch 'found
 
1243
      (dotimes (i (length seq))
 
1244
        (if (equal elem (aref seq i))
 
1245
            (throw 'found i)))
 
1246
      nil)))
 
1247
 
 
1248
(defun ecb-last (seq)
 
1249
  "Return the last elem of the sequence SEQ."
 
1250
  (if (listp seq)
 
1251
      (car (last seq))
 
1252
    (if seq
 
1253
        (aref seq (1- (length seq)))
 
1254
      nil)))
 
1255
 
 
1256
(defun ecb-first (seq)
 
1257
  "Return the first elem of the sequence SEQ."
 
1258
  (if (listp seq)
 
1259
      (car seq)
 
1260
    (if seq
 
1261
        (aref seq 0)
 
1262
      nil)))
 
1263
  
1005
1264
 
1006
1265
(defun ecb-next-listelem (list elem &optional nth-next)
1007
1266
  "Return that element of LIST which follows directly ELEM when ELEM is an
1022
1281
                   (length list))
1023
1282
              list))))
1024
1283
 
 
1284
(defun ecb-buffer-name (buffer-or-name)
 
1285
  "Return the buffer-name of BUFFER-OR-NAME."
 
1286
  (cond ((stringp buffer-or-name)
 
1287
         buffer-or-name)
 
1288
        ((bufferp buffer-or-name)
 
1289
         (buffer-name buffer-or-name))
 
1290
        (t
 
1291
         nil)))
 
1292
 
 
1293
(defun ecb-buffer-obj (buffer-or-name)
 
1294
  "Return the buffer-object of BUFFER-OR-NAME."
 
1295
  (cond ((stringp buffer-or-name)
 
1296
         (get-buffer buffer-or-name))
 
1297
        ((bufferp buffer-or-name)
 
1298
         buffer-or-name)
 
1299
        (t
 
1300
         nil)))
 
1301
 
1025
1302
(defun ecb-file-content-as-string (file)
1026
1303
  "If FILE exists and is readable returns the contents as a string otherwise
1027
1304
return nil.
1057
1334
                   (ecb-current-buffer-archive-extract-p))
1058
1335
               (ecb-current-buffer-archive-extract-p))))))
1059
1336
 
1060
 
(defun ecb-fit-str-to-width (str width)
1061
 
  "If STR is longer than WIDTH then fit it to WIDTH by stripping from left and
1062
 
prepend \"...\" to signalize that the string is stripped. If WIDTH >= length
 
1337
(defun ecb-fit-str-to-width (str width from)
 
1338
  "If STR is longer than WIDTH then fit it to WIDTH by stripping from left or
 
1339
right \(depends on FROM which can be 'left or 'right) and prepend \(rsp.
 
1340
append) \"...\" to signalize that the string is stripped. If WIDTH >= length
1063
1341
of STR the always STR is returned. If either WIDTH or length of STR is < 5
1064
1342
then an empty string is returned because stripping makes no sense here."
1065
1343
  (let ((len-str (length str)))
1068
1346
      (if (or (< len-str 5) ;; we want at least two characters visible of str
1069
1347
              (< width 5))
1070
1348
          ""
1071
 
        (concat "..." (substring str (* -1 (- width 3))))))))
 
1349
        (if (equal from 'left)
 
1350
            (concat "..." (substring str (* -1 (- width 3))))
 
1351
          (concat (substring str 0 (- width 3)) "..."))))))
 
1352
 
1072
1353
 
1073
1354
(defun ecb-make-windows-not-dedicated (&optional frame)
1074
1355
  "Make all windows of FRAME not dedicated."
1101
1382
                                  ;;   modeline via (:eval...) the new buffer
1102
1383
                                  ;;   scrolls autom. back to beginng of
1103
1384
                                  ;;   buffer.
1104
 
                                  ;; With the original window-list all is ok...
1105
 
                                  (ecb-window-list
1106
 
                                   ecb-frame 0
1107
 
                                   (frame-first-window ecb-frame))
 
1385
                                  ;; With the original window-list all is
 
1386
                                  ;; ok...
 
1387
                                  (ecb-canonical-windows-list)
1108
1388
                                (window-list)))))))
1109
1389
 
1110
1390
 
1118
1398
          (set-buffer buffer)
1119
1399
          (symbol-value sym)))))
1120
1400
 
 
1401
 
 
1402
 
1121
1403
;; ringstuff
1122
1404
 
1123
1405
(require 'ring)
1130
1412
(defun ecb-ring-elements (ring)
1131
1413
  "Return a list of the lements of RING."
1132
1414
  (mapcar #'identity (cddr ring)))
1133
 
      
1134
 
 
 
1415
 
 
1416
(defvar ecb-max-submenu-depth 4
 
1417
  "The maximum depth of nesting submenus for the tree-buffers.")
 
1418
 
 
1419
(defun ecb-create-menu-user-ext-type (curr-level max-level)
 
1420
  "Creates the :type-definition for the *-menu-user-extension options.
 
1421
This allows nested submenus for the popup-menus of the tree-buffers up to a
 
1422
maximum level of MAX-LEVEL. CURR-LEVEL must be 1 when used in a
 
1423
defcustom-clause and has to be <= MAX-LEVEL."
 
1424
  (list 'repeat (delq nil
 
1425
                      (list 'choice ':tag "Menu-entry" ':menu-tag "Menu-entry"
 
1426
                            ':value '(ignore "")
 
1427
                            (list 'const ':tag "Separator" ':value '("---"))
 
1428
                            (list 'list ':tag "Menu-command"
 
1429
                                  (list 'function ':tag "Function" ':value 'ignore)
 
1430
                                  (list 'string ':tag "Entry-name"))
 
1431
                            (if (= curr-level max-level)
 
1432
                                nil
 
1433
                              (list 'cons ':tag "Submenu"
 
1434
                                    (list 'string ':tag "Submenu-title")
 
1435
                                    (ecb-create-menu-user-ext-type (1+ curr-level)
 
1436
                                                                   max-level)))))))
1135
1437
(silentcomp-provide 'ecb-util)
1136
1438
 
1137
1439
;;; ecb-util.el ends here