3d42104e8885dacd21a6b20379e49d60fb03a946
[bpt/emacs.git] / lisp / term / w32-win.el
1 ;;; win32-win.el --- parse switches controlling interface with win32
2
3 ;; Copyright (C) 1993, 1994 Free Software Foundation, Inc.
4
5 ;; Author: Kevin Gallo
6 ;; Keywords: terminals
7
8 ;; This file is part of GNU Emacs.
9
10 ;; GNU Emacs is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 2, or (at your option)
13 ;; any later version.
14
15 ;; GNU Emacs is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details.
19
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs; see the file COPYING. If not, write to the
22 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
24
25 ;;; Commentary:
26
27 ;; win32-win.el: this file is loaded from ../lisp/startup.el when it recognizes
28 ;; that win32 windows are to be used. Command line switches are parsed and those
29 ;; pertaining to win32 are processed and removed from the command line. The
30 ;; win32 display is opened and hooks are set for popping up the initial window.
31
32 ;; startup.el will then examine startup files, and eventually call the hooks
33 ;; which create the first window (s).
34
35 ;;; Code:
36 \f
37
38 ;; These are the standard X switches from the Xt Initialize.c file of
39 ;; Release 4.
40
41 ;; Command line Resource Manager string
42
43 ;; +rv *reverseVideo
44 ;; +synchronous *synchronous
45 ;; -background *background
46 ;; -bd *borderColor
47 ;; -bg *background
48 ;; -bordercolor *borderColor
49 ;; -borderwidth .borderWidth
50 ;; -bw .borderWidth
51 ;; -display .display
52 ;; -fg *foreground
53 ;; -fn *font
54 ;; -font *font
55 ;; -foreground *foreground
56 ;; -geometry .geometry
57 ;; -i .iconType
58 ;; -itype .iconType
59 ;; -iconic .iconic
60 ;; -name .name
61 ;; -reverse *reverseVideo
62 ;; -rv *reverseVideo
63 ;; -selectionTimeout .selectionTimeout
64 ;; -synchronous *synchronous
65 ;; -xrm
66
67 ;; An alist of X options and the function which handles them. See
68 ;; ../startup.el.
69
70 (if (not (eq window-system 'win32))
71 (error "%s: Loading win32-win.el but not compiled for win32" (invocation-name)))
72
73 (require 'frame)
74 (require 'mouse)
75 (require 'scroll-bar)
76 (require 'faces)
77 (require 'select)
78 (require 'menu-bar)
79
80 ;; Because Windows scrollbars look and act quite differently compared
81 ;; with the standard X scroll-bars, we don't try to use the normal
82 ;; scroll bar routines.
83
84 (defun win32-handle-scroll-bar-event (event)
85 "Handle Win32 scroll bar events to do normal Window style scrolling."
86 (interactive "e")
87 (let* ((position (event-start event))
88 (window (nth 0 position))
89 (portion-whole (nth 2 position))
90 (bar-part (nth 4 position)))
91 (save-excursion
92 (select-window window)
93 (cond
94 ((eq bar-part 'up)
95 (scroll-down 1))
96 ((eq bar-part 'above-handle)
97 (scroll-down))
98 ((eq bar-part 'handle)
99 (scroll-bar-drag-1 event))
100 ((eq bar-part 'below-handle)
101 (scroll-up))
102 ((eq bar-part 'down)
103 (scroll-up 1))
104 ))))
105
106 ;; The following definition is used for debugging.
107 ;(defun win32-handle-scroll-bar-event (event) (interactive "e") (princ event))
108
109 (global-set-key [vertical-scroll-bar mouse-1] 'win32-handle-scroll-bar-event)
110
111 ;; (scroll-bar-mode nil)
112
113 (defvar x-invocation-args)
114
115 (defvar x-command-line-resources nil)
116
117 (defconst x-option-alist
118 '(("-bw" . x-handle-numeric-switch)
119 ("-d" . x-handle-display)
120 ("-display" . x-handle-display)
121 ("-name" . x-handle-name-rn-switch)
122 ("-rn" . x-handle-name-rn-switch)
123 ("-T" . x-handle-switch)
124 ("-r" . x-handle-switch)
125 ("-rv" . x-handle-switch)
126 ("-reverse" . x-handle-switch)
127 ("-fn" . x-handle-switch)
128 ("-font" . x-handle-switch)
129 ("-ib" . x-handle-numeric-switch)
130 ("-g" . x-handle-geometry)
131 ("-geometry" . x-handle-geometry)
132 ("-fg" . x-handle-switch)
133 ("-foreground". x-handle-switch)
134 ("-bg" . x-handle-switch)
135 ("-background". x-handle-switch)
136 ("-ms" . x-handle-switch)
137 ("-itype" . x-handle-switch)
138 ("-i" . x-handle-switch)
139 ("-iconic" . x-handle-iconic)
140 ("-xrm" . x-handle-xrm-switch)
141 ("-cr" . x-handle-switch)
142 ("-vb" . x-handle-switch)
143 ("-hb" . x-handle-switch)
144 ("-bd" . x-handle-switch)))
145
146 (defconst x-long-option-alist
147 '(("--border-width" . "-bw")
148 ("--display" . "-d")
149 ("--name" . "-name")
150 ("--title" . "-T")
151 ("--reverse-video" . "-reverse")
152 ("--font" . "-font")
153 ("--internal-border" . "-ib")
154 ("--geometry" . "-geometry")
155 ("--foreground-color" . "-fg")
156 ("--background-color" . "-bg")
157 ("--mouse-color" . "-ms")
158 ("--icon-type" . "-itype")
159 ("--iconic" . "-iconic")
160 ("--xrm" . "-xrm")
161 ("--cursor-color" . "-cr")
162 ("--vertical-scroll-bars" . "-vb")
163 ("--border-color" . "-bd")))
164
165 (defconst x-switch-definitions
166 '(("-name" name)
167 ("-T" name)
168 ("-r" reverse t)
169 ("-rv" reverse t)
170 ("-reverse" reverse t)
171 ("-fn" font)
172 ("-font" font)
173 ("-ib" internal-border-width)
174 ("-fg" foreground-color)
175 ("-foreground" foreground-color)
176 ("-bg" background-color)
177 ("-background" background-color)
178 ("-ms" mouse-color)
179 ("-cr" cursor-color)
180 ("-itype" icon-type t)
181 ("-i" icon-type t)
182 ("-vb" vertical-scroll-bars t)
183 ("-hb" horizontal-scroll-bars t)
184 ("-bd" border-color)
185 ("-bw" border-width)))
186
187 ;; Handler for switches of the form "-switch value" or "-switch".
188 (defun x-handle-switch (switch)
189 (let ((aelt (assoc switch x-switch-definitions)))
190 (if aelt
191 (if (nth 2 aelt)
192 (setq default-frame-alist
193 (cons (cons (nth 1 aelt) (nth 2 aelt))
194 default-frame-alist))
195 (setq default-frame-alist
196 (cons (cons (nth 1 aelt)
197 (car x-invocation-args))
198 default-frame-alist)
199 x-invocation-args (cdr x-invocation-args))))))
200
201 ;; Make -iconic apply only to the initial frame!
202 (defun x-handle-iconic (switch)
203 (setq initial-frame-alist
204 (cons '(visibility . icon) initial-frame-alist)))
205
206 ;; Handler for switches of the form "-switch n"
207 (defun x-handle-numeric-switch (switch)
208 (let ((aelt (assoc switch x-switch-definitions)))
209 (if aelt
210 (setq default-frame-alist
211 (cons (cons (nth 1 aelt)
212 (string-to-int (car x-invocation-args)))
213 default-frame-alist)
214 x-invocation-args
215 (cdr x-invocation-args)))))
216
217 ;; Handle the -xrm option.
218 (defun x-handle-xrm-switch (switch)
219 (or (consp x-invocation-args)
220 (error "%s: missing argument to `%s' option" (invocation-name) switch))
221 (setq x-command-line-resources (car x-invocation-args))
222 (setq x-invocation-args (cdr x-invocation-args)))
223
224 ;; Handle the geometry option
225 (defun x-handle-geometry (switch)
226 (let ((geo (x-parse-geometry (car x-invocation-args))))
227 (setq initial-frame-alist
228 (append initial-frame-alist
229 (if (or (assq 'left geo) (assq 'top geo))
230 '((user-position . t)))
231 (if (or (assq 'height geo) (assq 'width geo))
232 '((user-size . t)))
233 geo)
234 x-invocation-args (cdr x-invocation-args))))
235
236 ;; Handle the -name and -rn options. Set the variable x-resource-name
237 ;; to the option's operand; if the switch was `-name', set the name of
238 ;; the initial frame, too.
239 (defun x-handle-name-rn-switch (switch)
240 (or (consp x-invocation-args)
241 (error "%s: missing argument to `%s' option" (invocation-name) switch))
242 (setq x-resource-name (car x-invocation-args)
243 x-invocation-args (cdr x-invocation-args))
244 (if (string= switch "-name")
245 (setq initial-frame-alist (cons (cons 'name x-resource-name)
246 initial-frame-alist))))
247
248 (defvar x-display-name nil
249 "The display name specifying server and frame.")
250
251 (defun x-handle-display (switch)
252 (setq x-display-name (car x-invocation-args)
253 x-invocation-args (cdr x-invocation-args)))
254
255 (defvar x-invocation-args nil)
256
257 (defun x-handle-args (args)
258 "Process the X-related command line options in ARGS.
259 This is done before the user's startup file is loaded. They are copied to
260 x-invocation args from which the X-related things are extracted, first
261 the switch (e.g., \"-fg\") in the following code, and possible values
262 \(e.g., \"black\") in the option handler code (e.g., x-handle-switch).
263 This returns ARGS with the arguments that have been processed removed."
264 (message "%s" args)
265 (setq x-invocation-args args
266 args nil)
267 (while x-invocation-args
268 (let* ((this-switch (car x-invocation-args))
269 (orig-this-switch this-switch)
270 completion argval aelt)
271 (setq x-invocation-args (cdr x-invocation-args))
272 ;; Check for long options with attached arguments
273 ;; and separate out the attached option argument into argval.
274 (if (string-match "^--[^=]*=" this-switch)
275 (setq argval (substring this-switch (match-end 0))
276 this-switch (substring this-switch 0 (1- (match-end 0)))))
277 (setq completion (try-completion this-switch x-long-option-alist))
278 (if (eq completion t)
279 ;; Exact match for long option.
280 (setq this-switch (cdr (assoc this-switch x-long-option-alist)))
281 (if (stringp completion)
282 (let ((elt (assoc completion x-long-option-alist)))
283 ;; Check for abbreviated long option.
284 (or elt
285 (error "Option `%s' is ambiguous" this-switch))
286 (setq this-switch (cdr elt)))
287 ;; Check for a short option.
288 (setq argval nil this-switch orig-this-switch)))
289 (setq aelt (assoc this-switch x-option-alist))
290 (if aelt
291 (if argval
292 (let ((x-invocation-args
293 (cons argval x-invocation-args)))
294 (funcall (cdr aelt) this-switch))
295 (funcall (cdr aelt) this-switch))
296 (setq args (cons this-switch args)))))
297 (setq args (nreverse args)))
298
299
300 \f
301 ;;
302 ;; Available colors
303 ;;
304
305 (defvar x-colors '("aquamarine"
306 "Aquamarine"
307 "medium aquamarine"
308 "MediumAquamarine"
309 "black"
310 "Black"
311 "blue"
312 "Blue"
313 "cadet blue"
314 "CadetBlue"
315 "cornflower blue"
316 "CornflowerBlue"
317 "dark slate blue"
318 "DarkSlateBlue"
319 "light blue"
320 "LightBlue"
321 "light steel blue"
322 "LightSteelBlue"
323 "medium blue"
324 "MediumBlue"
325 "medium slate blue"
326 "MediumSlateBlue"
327 "midnight blue"
328 "MidnightBlue"
329 "navy blue"
330 "NavyBlue"
331 "navy"
332 "Navy"
333 "sky blue"
334 "SkyBlue"
335 "slate blue"
336 "SlateBlue"
337 "steel blue"
338 "SteelBlue"
339 "coral"
340 "Coral"
341 "cyan"
342 "Cyan"
343 "firebrick"
344 "Firebrick"
345 "brown"
346 "Brown"
347 "gold"
348 "Gold"
349 "goldenrod"
350 "Goldenrod"
351 "green"
352 "Green"
353 "dark green"
354 "DarkGreen"
355 "dark olive green"
356 "DarkOliveGreen"
357 "forest green"
358 "ForestGreen"
359 "lime green"
360 "LimeGreen"
361 "medium sea green"
362 "MediumSeaGreen"
363 "medium spring green"
364 "MediumSpringGreen"
365 "pale green"
366 "PaleGreen"
367 "sea green"
368 "SeaGreen"
369 "spring green"
370 "SpringGreen"
371 "yellow green"
372 "YellowGreen"
373 "dark slate grey"
374 "DarkSlateGrey"
375 "dark slate gray"
376 "DarkSlateGray"
377 "dim grey"
378 "DimGrey"
379 "dim gray"
380 "DimGray"
381 "light grey"
382 "LightGrey"
383 "light gray"
384 "LightGray"
385 "gray"
386 "grey"
387 "Gray"
388 "Grey"
389 "khaki"
390 "Khaki"
391 "magenta"
392 "Magenta"
393 "maroon"
394 "Maroon"
395 "orange"
396 "Orange"
397 "orchid"
398 "Orchid"
399 "dark orchid"
400 "DarkOrchid"
401 "medium orchid"
402 "MediumOrchid"
403 "pink"
404 "Pink"
405 "plum"
406 "Plum"
407 "red"
408 "Red"
409 "indian red"
410 "IndianRed"
411 "medium violet red"
412 "MediumVioletRed"
413 "orange red"
414 "OrangeRed"
415 "violet red"
416 "VioletRed"
417 "salmon"
418 "Salmon"
419 "sienna"
420 "Sienna"
421 "tan"
422 "Tan"
423 "thistle"
424 "Thistle"
425 "turquoise"
426 "Turquoise"
427 "dark turquoise"
428 "DarkTurquoise"
429 "medium turquoise"
430 "MediumTurquoise"
431 "violet"
432 "Violet"
433 "blue violet"
434 "BlueViolet"
435 "wheat"
436 "Wheat"
437 "white"
438 "White"
439 "yellow"
440 "Yellow"
441 "green yellow"
442 "GreenYellow")
443 "The full list of X colors from the `rgb.text' file.")
444
445 (defun x-defined-colors (&optional frame)
446 "Return a list of colors supported for a particular frame.
447 The argument FRAME specifies which frame to try.
448 The value may be different for frames on different X displays."
449 (or frame (setq frame (selected-frame)))
450 (let ((all-colors x-colors)
451 (this-color nil)
452 (defined-colors nil))
453 (while all-colors
454 (setq this-color (car all-colors)
455 all-colors (cdr all-colors))
456 (and (face-color-supported-p frame this-color t)
457 (setq defined-colors (cons this-color defined-colors))))
458 defined-colors))
459 \f
460 ;;;; Function keys
461
462 (defun iconify-or-deiconify-frame ()
463 "Iconify the selected frame, or deiconify if it's currently an icon."
464 (interactive)
465 (if (eq (cdr (assq 'visibility (frame-parameters))) t)
466 (iconify-frame)
467 (make-frame-visible)))
468
469 (substitute-key-definition 'suspend-emacs 'iconify-or-deiconify-frame
470 global-map)
471
472 ;; Map certain keypad keys into ASCII characters
473 ;; that people usually expect.
474 (define-key function-key-map [tab] [?\t])
475 (define-key function-key-map [linefeed] [?\n])
476 (define-key function-key-map [clear] [11])
477 (define-key function-key-map [return] [13])
478 (define-key function-key-map [escape] [?\e])
479 (define-key function-key-map [M-tab] [?\M-\t])
480 (define-key function-key-map [M-linefeed] [?\M-\n])
481 (define-key function-key-map [M-clear] [?\M-\013])
482 (define-key function-key-map [M-return] [?\M-\015])
483 (define-key function-key-map [M-escape] [?\M-\e])
484
485 ;; These don't do the right thing (voelker)
486 ;(define-key function-key-map [backspace] [127])
487 ;(define-key function-key-map [delete] [127])
488 ;(define-key function-key-map [M-backspace] [?\M-\d])
489 ;(define-key function-key-map [M-delete] [?\M-\d])
490
491 ;; These tell read-char how to convert
492 ;; these special chars to ASCII.
493 (put 'tab 'ascii-character ?\t)
494 (put 'linefeed 'ascii-character ?\n)
495 (put 'clear 'ascii-character 12)
496 (put 'return 'ascii-character 13)
497 (put 'escape 'ascii-character ?\e)
498 ;; These don't seem to be necessary (voelker)
499 ;(put 'backspace 'ascii-character 127)
500 ;(put 'delete 'ascii-character 127)
501
502 \f
503 ;;;; Selections and cut buffers
504
505 ;;; We keep track of the last text selected here, so we can check the
506 ;;; current selection against it, and avoid passing back our own text
507 ;;; from x-cut-buffer-or-selection-value.
508 (defvar x-last-selected-text nil)
509
510 ;;; It is said that overlarge strings are slow to put into the cut buffer.
511 ;;; Note this value is overridden below.
512 (defvar x-cut-buffer-max 20000
513 "Max number of characters to put in the cut buffer.")
514
515 (defvar x-select-enable-clipboard t
516 "Non-nil means cutting and pasting uses the clipboard.
517 This is in addition to the primary selection.")
518
519 (defun x-select-text (text &optional push)
520 (if x-select-enable-clipboard
521 (win32-set-clipboard-data text))
522 (setq x-last-selected-text text))
523
524 ;;; Return the value of the current selection.
525 ;;; Consult the selection, then the cut buffer. Treat empty strings
526 ;;; as if they were unset.
527 (defun x-get-selection-value ()
528 (if x-select-enable-clipboard
529 (let (text)
530 ;; Don't die if x-get-selection signals an error.
531 (condition-case c
532 (setq text (win32-get-clipboard-data))
533 (error (message "win32-get-clipboard-data:%s" c)))
534 (if (string= text "") (setq text nil))
535 (cond
536 ((not text) nil)
537 ((eq text x-last-selected-text) nil)
538 ((string= text x-last-selected-text)
539 ;; Record the newer string, so subsequent calls can use the 'eq' test.
540 (setq x-last-selected-text text)
541 nil)
542 (t
543 (setq x-last-selected-text text))))))
544 \f
545 ;;; Do the actual Windows setup here; the above code just defines
546 ;;; functions and variables that we use now.
547
548 (setq command-line-args (x-handle-args command-line-args))
549
550 ;;; Make sure we have a valid resource name.
551 (or (stringp x-resource-name)
552 (let (i)
553 (setq x-resource-name (invocation-name))
554
555 ;; Change any . or * characters in x-resource-name to hyphens,
556 ;; so as not to choke when we use it in X resource queries.
557 (while (setq i (string-match "[.*]" x-resource-name))
558 (aset x-resource-name i ?-))))
559
560 ;; For the benefit of older Emacses (19.27 and earlier) that are sharing
561 ;; the same lisp directory, don't pass the third argument unless we seem
562 ;; to have the multi-display support.
563 (if (fboundp 'x-close-connection)
564 (x-open-connection ""
565 x-command-line-resources
566 ;; Exit Emacs with fatal error if this fails.
567 t)
568 (x-open-connection ""
569 x-command-line-resources))
570
571 (setq frame-creation-function 'x-create-frame-with-faces)
572
573 (setq x-cut-buffer-max (min (- (/ (x-server-max-request-size) 2) 100)
574 x-cut-buffer-max))
575
576 ;; Win32 expects the menu bar cut and paste commands to use the clipboard.
577 ;; This has ,? to match both on Sunos and on Solaris.
578 (menu-bar-enable-clipboard)
579
580 ;; Apply a geometry resource to the initial frame. Put it at the end
581 ;; of the alist, so that anything specified on the command line takes
582 ;; precedence.
583 (let* ((res-geometry (x-get-resource "geometry" "Geometry"))
584 parsed)
585 (if res-geometry
586 (progn
587 (setq parsed (x-parse-geometry res-geometry))
588 ;; If the resource specifies a position,
589 ;; call the position and size "user-specified".
590 (if (or (assq 'top parsed) (assq 'left parsed))
591 (setq parsed (cons '(user-position . t)
592 (cons '(user-size . t) parsed))))
593 ;; All geometry parms apply to the initial frame.
594 (setq initial-frame-alist (append initial-frame-alist parsed))
595 ;; The size parms apply to all frames.
596 (if (assq 'height parsed)
597 (setq default-frame-alist
598 (cons (cons 'height (cdr (assq 'height parsed)))
599 default-frame-alist)))
600 (if (assq 'width parsed)
601 (setq default-frame-alist
602 (cons (cons 'width (cdr (assq 'width parsed)))
603 default-frame-alist))))))
604
605 ;; Check the reverseVideo resource.
606 (let ((case-fold-search t))
607 (let ((rv (x-get-resource "reverseVideo" "ReverseVideo")))
608 (if (and rv
609 (string-match "^\\(true\\|yes\\|on\\)$" rv))
610 (setq default-frame-alist
611 (cons '(reverse . t) default-frame-alist)))))
612
613 ;; Set x-selection-timeout, measured in milliseconds.
614 (let ((res-selection-timeout
615 (x-get-resource "selectionTimeout" "SelectionTimeout")))
616 (setq x-selection-timeout 20000)
617 (if res-selection-timeout
618 (setq x-selection-timeout (string-to-number res-selection-timeout))))
619
620 (defun x-win-suspend-error ()
621 (error "Suspending an emacs running under Win32 makes no sense"))
622 (add-hook 'suspend-hook 'x-win-suspend-error)
623
624 ;;; Arrange for the kill and yank functions to set and check the clipboard.
625 (setq interprogram-cut-function 'x-select-text)
626 (setq interprogram-paste-function 'x-get-selection-value)
627
628 ;;; Turn off window-splitting optimization; win32 is usually fast enough
629 ;;; that this is only annoying.
630 (setq split-window-keep-point t)
631
632 ;; Don't show the frame name; that's redundant.
633 (setq-default mode-line-buffer-identification '("Emacs: %12b"))
634
635 ;;; Set to a system sound if you want a fancy bell.
636 (set-message-beep 'ok)
637
638 ;; Remap some functions to call win32 common dialogs
639
640 (defun internal-face-interactive (what &optional bool)
641 (let* ((fn (intern (concat "face-" what)))
642 (prompt (concat "Set " what " of face"))
643 (face (read-face-name (concat prompt ": ")))
644 (default (if (fboundp fn)
645 (or (funcall fn face (selected-frame))
646 (funcall fn 'default (selected-frame)))))
647 (fn-win (intern (concat (symbol-name window-system) "-select-" what)))
648 (value
649 (if (fboundp fn-win)
650 (funcall fn-win)
651 (if bool
652 (y-or-n-p (concat "Should face " (symbol-name face)
653 " be " bool "? "))
654 (read-string (concat prompt " " (symbol-name face) " to: ")
655 default)))))
656 (list face (if (equal value "") nil value))))
657
658 ;; Redefine the font selection to use the Win32 dialog
659
660 (defun mouse-set-font (&rest fonts)
661 (interactive)
662 (set-default-font (win32-select-font)))
663
664 ;;; win32-win.el ends here