;;; ns-platform-support.el ;; Copyright (C) 1993, 1994, 2005, 2006, 2007, 2008, 2009 ;; Adrian Robert ;; This file is not part of GNU Emacs. ;; This file is not part of Aquamacs. ;; This is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; This software is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see . ;; These functions have been spun out from Emacs.app, since they ;; are not part of Emacs 23 due to the addition of specific functions ;; not available in compatible manner on free platforms. ;; To install and use: ;; Put this file into the Emacs load path. ;; Add to your initialization file (e.g., ~/.emacs): ;; (require 'ns-platform-support) ;; (ns-extended-platform-support-mode 1) ;; ;; The minor mode can be turned on and off using ;; M-x ns-extended-platform-support-mode RET. ;; Code by Adrian Robert and others. ;; ns-arrange functions contributed ;; by Eberhard Mandler (defun ns-arrange-all-frames () "Arranges all frames according to topline" (interactive) (ns-arrange-frames t)) (defun ns-arrange-visible-frames () "Arranges all visible frames according to topline" (interactive) (ns-arrange-frames nil)) (defun ns-arrange-frames (vis) (let ((frame (next-frame)) (end-frame (selected-frame)) (inc-x 20) ;relative position of frames (inc-y 22) (x-pos 100) ;start position (y-pos 40) (done nil)) (while (not done) ;cycle through all frames (if (not (or vis (eq (frame-visible-p frame) t))) (setq x-pos x-pos); do nothing; true case (set-frame-position frame x-pos y-pos) (setq x-pos (+ x-pos inc-x)) (setq y-pos (+ y-pos inc-y)) (raise-frame frame)) (select-frame frame) (setq frame (next-frame)) (setq done (equal frame end-frame))) (set-frame-position end-frame x-pos y-pos) (raise-frame frame) (select-frame frame))) ;;;; File menu, replaces standard under ns-extended-platform-support (defvar menu-bar-ns-file-menu (make-sparse-keymap "File")) (define-key menu-bar-ns-file-menu [one-window] '("Remove Splits" . delete-other-windows)) (define-key menu-bar-ns-file-menu [split-window] '("Split Window" . split-window-vertically)) (define-key menu-bar-ns-file-menu [separator-print] '("--")) (defvar ns-ps-print-menu-map (make-sparse-keymap "Postscript Print")) (define-key ns-ps-print-menu-map [ps-print-region] '("Region (B+W)" . ps-print-region)) (define-key ns-ps-print-menu-map [ps-print-buffer] '("Buffer (B+W)" . ps-print-buffer)) (define-key ns-ps-print-menu-map [ps-print-region-faces] '("Region" . ps-print-region-with-faces)) (define-key ns-ps-print-menu-map [ps-print-buffer-faces] '("Buffer" . ps-print-buffer-with-faces)) (define-key menu-bar-ns-file-menu [postscript-print] (cons "Postscript Print" ns-ps-print-menu-map)) (define-key menu-bar-ns-file-menu [print-region] '("Print Region" . print-region)) (define-key menu-bar-ns-file-menu [print-buffer] '("Print Buffer" . ns-print-buffer)) (define-key menu-bar-ns-file-menu [separator-save] '("--")) (define-key menu-bar-ns-file-menu [recover-session] '("Recover Crashed Session" . recover-session)) (define-key menu-bar-ns-file-menu [revert-buffer] '("Revert Buffer" . revert-buffer)) (define-key menu-bar-ns-file-menu [write-file] '("Save Buffer As..." . ns-write-file-using-panel)) (define-key menu-bar-ns-file-menu [save-buffer] '("Save Buffer" . save-buffer)) (define-key menu-bar-ns-file-menu [kill-buffer] '("Kill Current Buffer" . kill-this-buffer)) (define-key menu-bar-ns-file-menu [delete-this-frame] '("Close Frame" . delete-frame)) (define-key menu-bar-ns-file-menu [separator-open] '("--")) (define-key menu-bar-ns-file-menu [insert-file] '("Insert File..." . insert-file)) (define-key menu-bar-ns-file-menu [dired] '("Open Directory..." . ns-open-file-using-panel)) (define-key menu-bar-ns-file-menu [open-file] '("Open File..." . ns-open-file-using-panel)) (define-key menu-bar-ns-file-menu [make-frame] '("New Frame" . make-frame)) (defun menu-bar-update-frames () ;; If user discards the Windows item, play along. (when (lookup-key (current-global-map) [menu-bar windows]) (let ((frames (frame-list)) (frames-menu (make-sparse-keymap "Select Frame"))) (setcdr frames-menu (nconc (mapcar (lambda (frame) (nconc (list (frame-parameter frame 'window-id) (frame-parameter frame 'name)) `(lambda () (interactive) (menu-bar-select-frame ,frame)))) frames) (cdr frames-menu))) (define-key frames-menu [separator-frames] '("--")) (define-key frames-menu [popup-color-panel] '("Colors..." . ns-popup-color-panel)) (define-key frames-menu [popup-font-panel] '("Font Panel..." . ns-popup-font-panel)) (define-key frames-menu [separator-arrange] '("--")) (define-key frames-menu [arrange-all-frames] '("Arrange All Frames" . ns-arrange-all-frames)) (define-key frames-menu [arrange-visible-frames] '("Arrange Visible Frames" . ns-arrange-visible-frames)) ;; Don't use delete-frame as event name ;; because that is a special event. (define-key (current-global-map) [menu-bar windows] (cons "Window" frames-menu))))) (defun force-menu-bar-update-buffers () ;; This is a hack to get around fact that we already checked ;; frame-or-buffer-changed-p and reset it, so menu-bar-update-buffers ;; does not pick up any change. (menu-bar-update-buffers t)) (add-hook 'menu-bar-update-fab-hook 'menu-bar-update-frames) (add-hook 'menu-bar-update-fab-hook 'force-menu-bar-update-buffers) (defun menu-bar-update-frames-and-buffers () (if (frame-or-buffer-changed-p) (run-hooks 'menu-bar-update-fab-hook))) ;; Toggle some additi7onal Nextstep-like features that may interfere ;; with users' expectations coming from emacs on other platforms. (define-minor-mode ns-extended-platform-support-mode "Toggle Nextstep extended platform support features. When this mode is active (no modeline indicator): - File menu is altered slightly in keeping with conventions. - Screen position is preserved in scrolling. - Transient mark mode is activated" :init-value nil :global t :group 'ns (if ns-extended-platform-support-mode (progn (defun ns-show-manual () "Show Emacs.app section in the Emacs manual" (interactive) (info "(emacs) Mac OS / GNUstep")) (setq where-is-preferred-modifier 'super) (setq scroll-preserve-screen-position t) (transient-mark-mode 1) ;; Change file menu to simplify and add a couple of ;; Nextstep-specific items (easy-menu-remove-item global-map '("menu-bar") 'file) (easy-menu-add-item global-map '(menu-bar) (cons "File" menu-bar-ns-file-menu) 'edit) (define-key menu-bar-help-menu [ns-manual] '(menu-item "Read the Emacs.app Manual Chapter" ns-show-manual)) (define-key global-map [menu-bar windows] (make-sparse-keymap "Window")) (setq menu-bar-update-hook (delq 'menu-bar-update-buffers menu-bar-update-hook)) (add-hook 'menu-bar-update-hook 'menu-bar-update-frames-and-buffers) (menu-bar-update-frames) (force-menu-bar-update-buffers)) (progn ;; Undo everything above. (fmakunbound 'ns-show-manual) (setq where-is-preferred-modifier 'nil) (setq scroll-preserve-screen-position nil) (transient-mark-mode 0) (easy-menu-remove-item global-map '("menu-bar") 'file) (easy-menu-add-item global-map '(menu-bar) (cons "File" menu-bar-file-menu) 'edit) (easy-menu-remove-item global-map '("menu-bar" "help-menu") 'ns-manual) (setq menu-bar-update-hook (delq 'menu-bar-update-frames-and-buffers menu-bar-update-hook)) (add-hook 'menu-bar-update-hook 'menu-bar-update-buffers) (define-key global-map [menu-bar windows] nil)))) ;; Functions to set environment variables by running a subshell. ;;; Idea based on Nextstep 4.2 distribution, this version of code ;;; based on mac-read-environment-vars-from-shell () by David Reitter. ;;; Mostly used only under ns-extended-platform-support-mode. (defun ns-make-command-string (cmdlist) (mapconcat 'identity cmdlist " ; ")) ;;;###autoload (defun ns-grabenv (&optional shell-path startup) "Set the Emacs environment using the output of a shell command. This runs a shell subprocess, and interpret its output as a series of environment variables to insert into the emacs environment. SHELL-PATH gives the path to the shell; if nil, this defaults to the current setting of `shell-file-name'. STARTUP is a list of commands for the shell to execute; if nil, this defaults to \"printenv\"." (interactive) (with-temp-buffer (let ((shell-file-name (if shell-path shell-path shell-file-name)) (cmd (ns-make-command-string (if startup startup '("printenv"))))) (shell-command cmd t) (while (search-forward-regexp "^\\([A-Za-z_0-9]+\\)=\\(.*\\)$" nil t) (setenv (match-string 1) (if (equal (match-string 1) "PATH") (concat (getenv "PATH") ":" (match-string 2)) (match-string 2))))))) (provide 'ns-platform-support)