multiple updates:
[emacs-init.git] / gnuplot / gnuplot-gui.el
1 ;;;; gnuplot-gui.el -- GUI interface to setting options in gnuplot-mode
2
3 ;; Copyright (C) 1998-2000 Bruce Ravel
4
5 ;; Author:     Bruce Ravel <ravel@phys.washington.edu>
6 ;; Maintainer: Bruce Ravel <ravel@phys.washington.edu>
7 ;; Created:    19 December 1998
8 ;; Updated:    16 November 2000
9 ;; Version:    (same as gnuplot.el)
10 ;; Keywords:   gnuplot, plotting, interactive, GUI
11
12 ;; This file is not part of GNU Emacs.
13
14 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
15 ;; This program is free software; you can redistribute it and/or modify
16 ;; it under the terms of the GNU General Public License as published by
17 ;; the Free Software Foundation; either version 2, or (at your option)
18 ;; any later version.
19 ;;
20 ;; This lisp script is distributed in the hope that it will be useful,
21 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
22 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
23 ;;
24 ;; Permission is granted to distribute copies of this lisp script
25 ;; provided the copyright notice and this permission are preserved in
26 ;; all copies.
27 ;;
28 ;; You should have received a copy of the GNU General Public License
29 ;; along with this program; if not, you can either send email to this
30 ;; program's maintainer or write to: The Free Software Foundation,
31 ;; Inc.; 675 Massachusetts Avenue; Cambridge, MA 02139, USA.
32 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
33 ;; send bug reports to the authors (ravel@phys.washington.edu)
34 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
35 ;;
36 ;;; Commentary:
37 ;;
38 ;; This file provides a graphical user interface to setting arguments
39 ;; to gnuplot commands.  Positioning point near a command and invoking
40 ;; `gnuplot-gui-set-options-and-insert' (C-c C-c or shift-mouse-2)
41 ;; will pop open a frame with widgets for setting the various
42 ;; arguments appropriate the the item that was near point.  The goal
43 ;; is to provide point-and-click functionality to gnuplot-mode.
44 ;;
45 ;; gnuplot-gui is designed for gnuplot 3.7, but since much of 3.7 is
46 ;; backward compatible to 3.5, it will work well for that version
47 ;; also.
48 ;;
49 ;; gnuplot-gui.el was developed using Emacs 19.34 and is known to work
50 ;; on Emacs 20.x and XEmacs 20.x.  I do not know what is the earliest
51 ;; version for which it will work, but I make no guarantees for
52 ;; versions before 19.34.  Note that this makes heavy use of the
53 ;; widget package, so this will not work on Emacs 19.34 unless you
54 ;; install the widget package separately.
55 ;;
56 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
57 ;;
58 ;;; To do:
59 ;;
60 ;; Widgets I need:
61 ;; -- 'position: two or three comma separated numbers used to denote a
62 ;;               position or a tic start/end/increment (see arrow,
63 ;;               need a prefix)
64 ;; -- 'modifier: colon separated fields used for datafile modifiers
65 ;;
66 ;; command types which are currently unsupported or contain mistakes
67 ;; -- unsupported: cntrparam
68 ;; -- plot, splot, fit: rather lame
69 ;; -- label: position information missing
70 ;; -- label: font string handled in overly simple manner
71 ;; -- hidden3d: not really suited to 'list, but all options are exclusive...
72 ;; -- pointstyle argument to "set label"
73 ;;
74 ;; overall:
75 ;; -- continuation lines (ugh!)
76 ;; -- multiple frames end up displaying same window after setting options
77 ;;
78 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
79 ;;; Code:
80
81 (require 'gnuplot)
82 (eval-and-compile
83   (condition-case ()
84       (progn
85         (require 'widget)
86         (require 'wid-edit))
87     (error nil)))
88 (require 'cl)
89 (eval-when-compile                      ; suppress some compiler warnings
90   (defvar gnuplot-xemacs-p nil)
91   (defvar gnuplot-quote-character nil)
92   (defvar gnuplot-info-display nil)
93   (defvar gnuplot-mode-map nil))
94
95 ;; (eval-when-compile
96 ;;   (require 'wid-edit))
97
98 (eval-and-compile                       ; I need this!
99   (if (fboundp 'split-string)
100       ()
101     (defun split-string (string &optional pattern)
102       "Return a list of substrings of STRING which are separated by PATTERN.
103 If PATTERN is omitted, it defaults to \"[ \\f\\t\\n\\r\\v]+\"."
104       (or pattern
105           (setq pattern "[ \f\t\n\r\v]+"))
106       ;; The FSF version of this function takes care not to cons in case
107       ;; of infloop.  Maybe we should synch?
108       (let (parts (start 0))
109         (while (string-match pattern string start)
110           (setq parts (cons (substring string start (match-beginning 0)) parts)
111                 start (match-end 0)))
112         (nreverse (cons (substring string start) parts)))) ))
113
114
115 \f
116 ;;; customizable variables
117
118 (defgroup gnuplot-gui nil
119   "Graphical interface to setting arguments in gnuplot scrips."
120   :prefix "gnuplot-gui-"
121   :group 'gnuplot)
122
123 (defcustom gnuplot-gui-popup-flag nil
124   "*Non-nil means to open arguments pop-ups automatically.
125 This would be done after menu insertion of Gnuplot commands."
126   :group 'gnuplot-gui
127   :type 'boolean)
128
129 (defvar gnuplot-gui-frame nil
130   "Frame used to hold the buffer for setting options.")
131 (defcustom gnuplot-gui-frame-plist
132   '(height 18 width 65 border-width 0
133            user-position t top 150 left 150
134            internal-border-width 0 unsplittable t
135            default-toolbar-visible-p nil has-modeline-p nil
136            menubar-visible-p nil)
137   "Frame plist for the input run-time display frame in XEmacs."
138   :type '(repeat (group :inline t
139                         (symbol :tag "Property")
140                         (sexp :tag "Value")))
141   :group 'gnuplot-gui)
142 (defcustom gnuplot-gui-frame-parameters
143   '((height . 18)
144     (width . 65)
145     (user-position . t)
146     (top . 150)
147     (left . 150)
148     (border-width . 0)
149     (menu-bar-lines . 0)
150     (unsplittable . t))
151   "Frame parameters for the input run-time display frame in Emacs."
152   :group 'gnuplot-gui
153   :type '(repeat (sexp :tag "Parameter:")))
154
155 (defcustom gnuplot-gui-fontname-list
156   '(" " "\"Helvetica\"" "\"Times-Roman\"")
157   "List of known font names.
158 These *must* be quoted, like so \"\\\"Helvetica\\\"\".  This allows
159 for fonts with names like \"\\\"Arial Bold Italic\\\"\" to be treated
160 as single entries in the menu-buttons.  And it is really important that
161 the first entry in the list be a blank string."
162   :group 'gnuplot-gui
163   :type '(repeat (string :tag "Font name:")))
164
165 ;; some global variables
166 (defvar gnuplot-current-frame nil)
167 (defvar gnuplot-current-buffer nil)
168 (defvar gnuplot-current-buffer-point nil)
169 (defvar gnuplot-gui-alist nil)
170 (defvar gnuplot-gui-current-string nil)
171
172 \f
173 ;;; various tools for handling data structures and text in the buffer
174
175 ;; tools for accessing the elements of the lists in `gnuplot-gui-all-types'
176 (defsubst gnuplot-gui-type-tag     (obj) (elt obj 0))
177 (defsubst gnuplot-gui-type-symbol  (obj) (elt obj 1))
178 (defsubst gnuplot-gui-type-default (obj) (elt obj 2))
179 (defsubst gnuplot-gui-type-prefix  (obj) (elt obj 3)) ; also 'range seperator
180 (defsubst gnuplot-gui-type-fourth  (obj) (elt obj 4))
181 (defsubst gnuplot-gui-type-list    (obj) (cddr obj))
182
183 (defun gnuplot-this-word ()
184   "Return the word under point."
185   (let ((begin (save-excursion (beginning-of-line) (point-marker)))
186         (end   (save-excursion (end-of-line)       (point-marker))))
187     (save-excursion
188       (or (looking-at "\\<") (= (current-column) 0) (forward-word -1))
189       (if (> (point) begin) (setq begin (point-marker)))
190       (forward-word 1)
191       (if (> (point) end) (goto-char end))
192       (buffer-substring-no-properties begin (point)))))
193
194
195 \f
196 ;;; data structures containing regarding options in Gnuplot 3.7
197
198 ;; various constants used for options that take the same sorts of arguments
199 (defconst gnuplot-gui-mtics-list
200   '(("FREQUENCY"   'number " ")
201     ("DEFAULT"     'list " " "default")))
202 (defconst gnuplot-gui-data-list
203   '(("DATA TYPE"   'list " " "time")))
204 (defconst gnuplot-gui-label-list
205   '(("LABEL"       'string " ")
206     ("POSITION"    'position " " "" 2)
207     ("FONTNAME"    'list " " gnuplot-gui-fontname-list)
208     ("FONTSIZE"    'fontsize " ")))
209 (defconst gnuplot-gui-range-list
210   '(("RANGE"       'range (" " . " ") ":")
211     ("REVERSE"     'list " " "reverse" "noreverse")
212     ("WRITEBACK"   'list " " "writeback" "nowriteback")))
213 (defconst gnuplot-gui-tics-list
214   '(("WHERE"       'list " " "axis" "border")
215     ("MIRROR"      'list " " "mirror" "nomirror")
216     ("ROTATE"      'list " " "rotate" "norotate")
217     ("SERIES"      'position " " "" 3)
218     ("LABEL ARRAY" 'labels () )))
219 (defconst gnuplot-gui-zeroaxis-list
220   '(("LINETYPE"    'number " ")))
221
222 (defvar gnuplot-gui-terminal-types nil
223   "Associated list of terminal descriptions.
224 See the doc-string for `gnuplot-gui-all-types'.")
225 (setq gnuplot-gui-terminal-types
226       (list (cons "aifm"
227                   '(("COLOR"     'list " " "monochrome" "gray" "color")
228                     ("FONTNAME"  'list " " gnuplot-gui-fontname-list)
229                     ("FONTSIZE"  'fontsize " ")))
230             (cons "cgm"
231                   '(("MODE"      'list   " " "landscape" "portrait" "default")
232                     ("COLOR"     'list   " " "color" "monochrome")
233                     ("ROTATION"  'list   " " "rotate" "norotate")
234                     ("WIDTH"     'number " " "width")
235                     ("LINEWIDTH" 'number " " "linewidth")
236                     ("FONTNAME"  'list   " " "\"Arial\"" "\"Arial Italic\""
237                      "\"Arial Bold\"" "\"Arial Bold Italic\""
238                      "\"Times Roman\"" "\"Times Roman Italic\""
239                      "\"Times Roman Bold\"" "\"Times Roman Bold Italic\""
240                      "\"Helvetica\"" "\"Roman\"")
241                     ("FONTSIZE"  'fontsize " ")))
242             (cons "corel"
243                   '(("COLOR"            'list " " "default" "color" "monochrome")
244                     ("FONTNAME"         'list " " "\"SwitzerlandLight\""
245                      "\"Helvetica\"" "\"Times-Roman\"")
246                     ("FONTSIZE "        'number " ")
247                     ("X-SIZE   "        'number " ")
248                     ("Y-SIZE   "        'number " ")
249                     ("LINEWIDTH"        'number " ")))
250             (cons "dumb"
251                   '(("LINEFEED"         'list   " " "feed" "nofeed")
252                     ("X-SIZE"           'number " ")
253                     ("Y-SIZE"           'number " ")))
254             (cons "emf"
255                   '(("COLOR"            'list " " "color" "monochrome")
256                     ("LINE"             'list " " "solid" "dashed")
257                     ("FONTNAME"         'string " ")
258                     ("FONTSIZE"         'number " ")))
259             (cons "emtex"
260                   '(("FONTNAME"         'list     " " "courier" "roman")
261                     ("FONTSIZE"         'fontsize " ")))
262             (cons "fig"
263                   '(("COLOR"            'list   " " "color" "monochrome")
264                     ("FRAMESIZE"        'list   " " "small" "big")
265                     ("POINTSMAX"        'number " " "pointsmax")
266                     ("ORIENTATION"      'list   " " "landscape" "portrait")
267                     ("UNITS"            'list   " " "metric" "inches")
268                     ("FONT SIZE"        'number " " "fontsize")
269                     ("SIZE"             'pair   (" " . " ") "size")
270                     ("LINE THICKNESS"   'number " " "thickness")
271                     ("LAYER DEPTH"      'number " " "depth")))
272             (cons "hp500c"
273                   '(("RESOLUTION"       'list " " "75" "100" "150" "300")
274                     ("COMPRESSION"      'list " " "rle" "tiff")))
275             (cons "hpgl"
276                   '(("PENS"             'number " ")
277                     ("EJECT"            'list   " " "eject")))
278             (cons "hpdj"
279                   '(("RESOLUTION"       'list " " "75" "100" "150" "300")))
280             (cons "hpljii"
281                   '(("RESOLUTION"       'list " " "75" "100" "150" "300")))
282             (cons "hppj"
283                   '(("FONT"             'list " " "FNT9X17" "FNT5X9" "FNT13X25")))
284             (cons "imagen"
285                   '(("FONT SIZE"        'number " ")
286                     ("LAYOUT"           'list   " " "portrait" "landscape")
287                     ("NUMBER OF GRAPHS" 'range (" " . " ") ",")))
288             (cons "gpic"
289                   '(("X ORIGIN"         'number " ")
290                     ("Y ORIGIN"         'number " " ",")))
291             (cons "latex"
292                   '(("FONTNAME"         'list " " "courier" "roman")
293                     ("FONTSIZE"         'fontsize " ")))
294             (cons "mif"
295                   '(("COLOUR"           'list " " "colour" "monochrome")
296                     ("LINETYPE"         'list " " "polyline" "vectors")))
297             (cons "nec-cp6"
298                   '(("MODE"             'list " " "monochrome" "colour" "draft")))
299             (cons "pbm"
300                   '(("SIZE"      'list " " "small" "medium" "large")
301                     ("COLOR"     'list " " "monochrome" "gray" "color")))
302             (cons "pcl5L"
303                   '(("MODE"      'list " " "landscape" "portrait")
304                     ("FONTNAME"  'list " " "stick" "univers" "cg_times")
305                     ("FONTSIZE"  'fontsize " ")))
306             (cons "png"
307                   '(("SIZE"      'list " " "small" "medium" "large")
308                     ("COLOR"     'list " " "monochrome" "gray" "color")))
309             (cons "postscript"
310                   '(("MODE"      'list " " "landscape" "portrait" "eps" "default")
311                     ("ENHANCED"  'list " " "enhanced" "noenhanced")
312                     ("COLOR"     'list " " "color" "monochrome")
313                     ("SOLID"     'list " " "solid" "dashed")
314                     ("DUPLEXING" 'list " " "defaultplex" "simplex" "duplex")
315                     ("FONTNAME"  'list " " gnuplot-gui-fontname-list)
316                     ("FONTSIZE"  'fontsize " ")))
317             (cons "pslatex"
318                   '(("COLOR"     'list " " "monochrome" "color")
319                     ("DASHED"    'list " " "dashed")
320                     ("ROTATION"  'list " " "rotate" "norotate")
321                     ("AUXFILE"   'list " " "auxfile")))
322             (cons "pstex"
323                   '(("COLOR"     'list " " "monochrome" "color")
324                     ("DASHED"    'list " " "dashed")
325                     ("ROTATION"  'list " " "rotate" "norotate")
326                     ("AUXFILE"   'list " " "auxfile")))
327             (cons "pstricks"
328                   '(("HACK TEXT"        'list " " "hacktext" "nohacktext")
329                     ("PLOT SCALING"     'list " " "nounit" "unit")))
330             (cons "regis"
331                   '(("COLOR DEPTH"      'list "4" "16")))
332             (cons "tgif"
333                   '(("LAYOUT"           'list   " " "portrait" "landscape")
334                     ("NUMBER OF GRAPHS" 'range (" " . " ") ",")
335                     ("LINE TYPE"        'list " " "solid" "dashed")
336                     ("FONTNAME"         'list " " gnuplot-gui-fontname-list)
337                     ("FONTSIZE"         'fontsize " ")))
338             (cons "tpic"
339                   '(("POINTSIZE"        'number " ")
340                     ("LINEWIDTH"        'number " ")
341                     ("INTERVAL "        'number " ")))
342             (cons "vgagl"               ; for pm3d patch (also persist, raise in x11) <MT>
343                   '(("BACKGROUND"       'position  " " "background" 3)
344                     ("INTERPOLATION"    'list " " "uniform" "interpolate")
345                     ("DUMP"             'file " ")
346                     ("MODE"             'string  " " "")))
347             (cons "x11"
348                   '(("RESET"            'list " " "reset")
349                     ("TERMINAL NUMBER"  'number " ")
350                     ("PERSIST"          'list " " "persist" "nopersist")
351                     ("RAISE"            'list " " "raise" "noraise"))) ))
352
353 (defvar gnuplot-gui-terminal-list nil)
354 (setq gnuplot-gui-terminal-list
355       (append (list " ") (mapcar 'car gnuplot-gui-terminal-types)))
356
357 (defvar gnuplot-gui-set-types nil
358   "Associated list of set option descriptions.
359 See the doc-string for `gnuplot-gui-all-types'.")
360 (setq gnuplot-gui-set-types
361       (list (cons "angles"
362                   '(("UNITS" 'list " " "degrees" "radians")))
363             (cons "arrow"
364                   '(("TAG"       'tag " ")
365                     ("FROM"      'position " " "from" 3)
366                     ("TO"        'position " " "to" 3)
367                     ("HEAD"      'list " " "head" "nohead")
368                     ("LINESTYLE" 'number " " "ls")
369                     ("LINETYPE " 'number " " "lt")
370                     ("LINEWIDTH" 'number " " "lw")))
371             (cons "noarrow"
372                   '(("TAG" 'tag " ")))
373             (cons "autoscale"
374                   '(("AXIS" 'list " " "x" "y" "z" "x2" "y2" "xy"
375                      "xmin" "ymin" "zmin" "x2min" "y2min" "xymin"
376                      "xmax" "ymax" "zmax" "x2max" "y2max" "xymax")))
377             (cons "noautoscale"
378                   '(("AXIS" 'list " " "x" "y" "z" "x2" "y2" "xy"
379                      "xmin" "ymin" "zmin" "x2min" "y2min" "xymin"
380                      "xmax" "ymax" "zmax" "x2max" "y2max" "xymax")))
381             (cons "bar"
382                   '(("SIZE" 'list " " "small" "large")))
383             (cons "border"
384                   '(("BORDER CODE" 'number " ")
385                     ("LINE STYLE"  'list   " " "lines"
386                      "dots" "points" "linespoints")
387                     ("LINESTYLE"   'number " " "ls")
388                     ("LINETYPE"    'number " " "lt")
389                     ("LINEWIDTH"   'number " " "lw")
390                     ))
391             (cons "boxwidth"
392                   '(("WIDTH" 'number " ")))
393             (cons "clabel"
394                   '(("FORMAT" 'format " ")))
395             (cons "clip"
396                   '(("CLIP TYPE" 'list " " "points" "one" "two")))
397             (cons "noclip"
398                   '(("CLIP TYPE" 'list " " "points" "one" "two")))
399             ;;(cons "cntrparam"
400                 ;;  '(("INTERPOLATION" 'list " " "linear" "cubicspline" "bspline")
401                 ;;    ("POINTS" 'number " " "points")
402                 ;;    ("ORDER"  'number " " "order")))
403             (cons "contour"
404                   '(("WHERE"     'list " " "base" "surface" "both")))
405             (cons "dgrid3d"
406                    '(("ROW,COLUMN,NORM" 'position " " "" 3)))
407             (cons "encoding"
408                   '(("ENCODING" 'list " " "default" "iso_8859_1"
409                      "cp850" "cp437")))
410             (cons "format"
411                   '(("AXIS"   'list " " "x" "y" "z" "xy" "x2" "y2")
412                     ("FORMAT" 'format  " ")))
413             (cons "dummy"
414                   '(("VAR 1" 'string " " "")
415                     ("VAR 2" 'string " " ",")))
416             (cons "grid"
417                   '(("XTICS"  'list " " "xtics" "mxtics" "noxtics" "nomxtics")
418                     ("YTICS"  'list " " "ytics" "mytics" "noytics" "nomytics")
419                     ("ZTICS"  'list " " "ztics" "mztics" "noztics" "nomztics")
420                     ("X2TICS" 'list " " "x2tics" "mx2tics" "nox2tics" "nomx2tics")
421                     ("Y2TICS" 'list " " "y2tics" "my2tics" "noy2tics" "nomy2tics")
422                     ("POLAR"  'number " " "polar")
423                     ("MAJOR LINETYPE" 'number " ")
424                     ("MINOR LINETYPE" 'number " ")))
425             (cons "hidden3d"
426                   '(("ALGORITHM" 'list " " "defaults"
427                     "offset"
428                     "nooffset"
429                     ;;"trianglepattern  # bitpattern between 0 and 7"
430                     "trianglepattern 0" "trianglepattern 1"
431                     "trianglepattern 2" "trianglepattern 3"
432                     "trianglepattern 4" "trianglepattern 5"
433                     "trianglepattern 6" "trianglepattern 7"
434                     ;;"undefined        # level between 0 and 3"
435                     "undefined 0" "undefined 1" "undefined 2" "undefined 3"
436                     "noundefined" "altdiagonal" "noaltdiagonal"
437                     "bentover" "nobentover")))
438             (cons "historysize"
439                   '(("SIZE" 'number " ")))
440             (cons "isosamples"
441                   '(("ISO_U LINES" 'number " ")
442                     ("ISO_V LINES" 'number " " ",")))
443             (cons "key"
444                   '(("LOCATION"      'list " " "left" "right" "top" "bottom"
445                                            "outside" "below")
446                     ("POSITION"      'position  " " "" 3)
447                     ("JUSTIFICATION" 'list " " "Left" "Right")
448                     ("REVERSE"       'list " " "reverse" "noreverse")
449                     ("SAMPLE LENGTH" 'number " " "samplen")
450                     ("SPACING"       'number " " "spacing")
451                     ("WIDTH"         'number " " "width")
452                     ("TITLE"         'string " " "title ")
453                     ("BOX LINETYPE"  'number " " "box") ;; linetype data
454                     ("NOBOX"         'list   " " "nobox")))
455             (cons "label"
456                   '(("TAG" 'tag " ")
457                     ("LABEL TEXT" 'string " ")
458                     ("POSITION"   'position " " "at" 3)
459                     ;; first, second, graph, screen
460                     ("JUSTIFICATION" 'list " " "left" "right" "center")
461                     ("ROTATE"        'list " " "rotate" "norotate")
462                     ("FONT"          'string " " "font"))) ;; font "name,size"
463             (cons "nolabel"
464                   '(("TAG"        'tag " ")))
465             (cons "linestyle"
466                   '(("TAG      "  'tag " ")
467                     ("LINE STYLE" 'list " " "boxerrorbars" "boxes"
468                      "boxxyerrorbars" "candlesticks" "dots"
469                      "financebars" "fsteps" "histeps" "impulses"
470                      "lines" "linespoints" "points" "steps" "vector"
471                      "xerrorbars" "xyerrorbars" "yerrorbars")
472                     ("LINETYPE " 'number " " "lt")
473                     ("LINEWIDTH" 'number " " "lw")
474                     ("POINTTYPE" 'number " " "pt")
475                     ("POINTSIZE" 'number " " "ps")))
476             (cons "locale"
477                   '(("LOCALE" 'string " ")))
478             (cons "logscale"
479                   '(("AXIS" 'list " " "x" "y" "z" "xy" "xz" "yz" "xyz"
480                      "x2" "y2")
481                     ("BASE" 'number " ")))
482             (cons "nologscale"
483                   '(("AXIS" 'list " " "x" "y" "z" "xy" "xz" "yz" "xyz"
484                      "x2" "y2")))
485             (cons "mapping"
486                   '(("COORDINATE SYSTEM" 'list " " "cartesian" "spherical"
487                      "cylindrical")))
488                                         ; _margin
489             (cons "bmargin"
490                   '(("BOTTOM MARGIN" 'number " ")))
491             (cons "lmargin"
492                   '(("LEFT MARGIN"   'number " ")))
493             (cons "rmargin"
494                   '(("RIGHT MARGIN"  'number " ")))
495             (cons "tmargin"
496                   '(("TOP MARGIN"    'number " ")))
497
498             (cons "missing"
499                   '(("CHARACTER" 'string " " 1)))
500                                         ; m_tics
501             (cons "mxtics"  gnuplot-gui-mtics-list)
502             (cons "mytics"  gnuplot-gui-mtics-list)
503             (cons "mztics"  gnuplot-gui-mtics-list)
504             (cons "mx2tics" gnuplot-gui-mtics-list)
505             (cons "my2tics" gnuplot-gui-mtics-list)
506
507                                         ; pm3d additions <MT>
508             (cons "mouse"
509                   '(("DOUBLECLICK"     'number " " "doubleclick")
510                     ("ZOOM"            'list   " " "zoomcoordinates" "nozoomcoordinates")
511                     ("POLAR"           'list   " " "polarcoordinates" "nopolarcoordinates")
512                     ("FORMAT"          'string " " "format")
513                     ("CLIPBOARDFORMAT" 'string " " "clipboardformat")
514                     ("MOUSEFORMAT"     'string " " "mouseformat")
515                     ("LABELS"          'list   " " "labels" "nolabels")
516                     ("LABELOPTIONS"    'string " " "labeloptions")
517                     ("ZOOMJUMP"        'list   " " "zoomjump" "nozoomjump")
518                     ("VERBOSE"         'list   " " "verbose" "noverbose")))
519             (cons "palette"
520                   '(("COLOR"       'list     " " "gray" "color")
521                     ("RGBFORMULAE" 'position " " "rgbformulae" 3)
522                     ("PARITY"      'list     " " "positive" "negative")
523                     ("FORMULAE"    'list     " " "nops_allcF" "ps_allcF")
524                     ("MAXCOLORS"   'number   " ")
525                     ("COLOR_BOX"   'list     " " "nocb" "cbdefault" "cbuser")
526                     ("ORIENTATION" 'list     " " "cbvertical" "cbhorizontal")
527                     ("ORIGIN"      'position " " "origin" 2)
528                     ("SIZE"        'position " " "size" 2)
529                     ("BORDER"      'number   " ")
530                     ("NOBORDER"    'list     " " "bdefault" "noborder")))
531             (cons "pm3d"
532                   '(("AT"         'list*  " " "b" "s" "t" "bs" "bt" "st" "bst")
533                     ("SCANS"      'list   " " "scansautomatic" "scansforward" "scansbackward")
534                     ("FLUSH"      'list*  " " "begin" "center" "end")
535                     ("CLIP"       'list   " " "clip1in" "clip4in")
536                     ("ZRANGE"     'range (" " . " ") ":")
537                     ("HIDDEN3D"   'number " ")
538                     ("NOHIDDEN3D" 'list   " " "nohidden3d")
539                     ("FILLING"    'list   " " "transparent" "solid")
540                     ("MAP"        'list   " " "map")))
541
542             (cons "offsets"
543                   '(("LEFT  " 'number " ")
544                     ("RIGHT " 'number " " ",")
545                     ("TOP   " 'number " " ",")
546                     ("BOTTOM" 'number " " ",")))
547             (cons "origin"
548                   '(("X ORIGIN"   'number " ")
549                     ("Y ORIGIN"   'number " " ",")))
550             (cons "output"
551                   '(("FILENAME"   'file " ")))
552             (cons "pointsize"
553                   '(("MULTIPLIER" 'number " ")))
554             (cons "samples"
555                   '(("2D PLOT"    'number " ")
556                     ("3D PLOT"    'number " " ",")))
557             (cons "size"
558                   '(("ASPECT"           'list " " "square" "nosquare"
559                                                   "ratio" "noratio")
560                     ("X-SCALE OR RATIO" 'number " ")
561                     ("Y-SCALE"          'number " " ",")))
562             (cons "style"
563                   '(("DATA TYPE"  'list " " "data" "function")
564                     ("PLOT STYLE" 'list " " "boxerrorbars" "boxes"
565                      "boxxyerrorbars" "candlesticks" "dots"
566                      "financebars" "fsteps" "histeps" "impulses"
567                      "lines" "linespoints" "points" "steps" "vector"
568                      "xerrorbars" "xyerrorbars" "yerrorbars")))
569             (cons "terminal"
570                   '(("TERMINAL TYPE" 'list " " gnuplot-gui-terminal-list)))
571             (cons "tics"
572                   '(("DIRECTION"  'list " " "in" "out")))
573             (cons "ticslevel"
574                   '(("RELATIVE HEIGHT" 'number " ")))
575             (cons "ticscale"
576                   '(("MAJOR" 'number " ")
577                     ("MINOR" 'number " ")))
578             (cons "timestamp"
579                   '(("FORMAT STRING" 'format " ")
580                     ("WHERE"         'list " " "top" "bottom")
581                     ("ROTATE"        'list " " "rotate" "norotate")
582                     ("X-OFFSET"      'number " ")
583                     ("Y-OFFSET"      'number " " ",")
584                     ("FONTNAME"      'list " " gnuplot-gui-fontname-list)))
585             (cons "timefmt"
586                   '(("FORMAT STRING" 'string " ")))
587             (cons "title"
588                   '(("TITLE" 'string " ")))
589             (cons "view"
590                   '(("X-ROTATION" 'number " ")
591                     ("Z-ROTATION" 'number " " ",")
592                     ("SCALE"      'number " " ",")
593                     ("Z-SCALE"    'number " " ",")))
594             ;; ("SCALE" 'position " " "," 4)
595                                         ; _data
596             (cons "xdata"      gnuplot-gui-data-list)
597             (cons "ydata"      gnuplot-gui-data-list)
598             (cons "zdata"      gnuplot-gui-data-list)
599             (cons "x2data"     gnuplot-gui-data-list)
600             (cons "y2data"     gnuplot-gui-data-list)
601                                         ; _label
602             (cons "xlabel"     gnuplot-gui-label-list)
603             (cons "ylabel"     gnuplot-gui-label-list)
604             (cons "zlabel"     gnuplot-gui-label-list)
605             (cons "x2label"    gnuplot-gui-label-list)
606             (cons "y2label"    gnuplot-gui-label-list)
607                                         ; _range, note that the [] syntax for
608                                         ;         the writeback argument is
609                                         ;         not properly supported
610             (cons "xrange"     gnuplot-gui-range-list)
611             (cons "yrange"     gnuplot-gui-range-list)
612             (cons "zrange"     gnuplot-gui-range-list)
613             (cons "x2range"    gnuplot-gui-range-list)
614             (cons "y2range"    gnuplot-gui-range-list)
615             (cons "trange"     gnuplot-gui-range-list)
616             (cons "rrange"     gnuplot-gui-range-list)
617             (cons "urange"     gnuplot-gui-range-list)
618             (cons "vrange"     gnuplot-gui-range-list)
619                                         ; _tics
620             (cons "xtics"      gnuplot-gui-tics-list)
621             (cons "ytics"      gnuplot-gui-tics-list)
622             (cons "ztics"      gnuplot-gui-tics-list)
623             (cons "x2tics"     gnuplot-gui-tics-list)
624             (cons "y2tics"     gnuplot-gui-tics-list)
625                                         ; zeroaxis
626             (cons "zeroaxis"   gnuplot-gui-zeroaxis-list)
627             (cons "xzeroaxis"  gnuplot-gui-zeroaxis-list)
628             (cons "yzeroaxis"  gnuplot-gui-zeroaxis-list)
629             (cons "y2zeroaxis" gnuplot-gui-zeroaxis-list)
630             (cons "x2zeroaxis" gnuplot-gui-zeroaxis-list)
631
632             (cons "zero"
633                   '(("THRESHOLD" 'number " ")))
634             ))
635
636 (defvar gnuplot-gui-command-types nil
637   "Associated list of command descriptions.
638 See the doc-string for `gnuplot-gui-all-types'.")
639 (setq gnuplot-gui-command-types
640       (list (cons "cd"
641                   '(("FILENAME"       'file   " ")))
642             (cons "call"
643                   '(("INPUT FILE"     'file   " ")
644                     ("PARAMETER LIST" 'string " ")))
645             (cons "load"
646                   '(("INPUT FILE"     'file   " ")))
647             (cons "pause"
648                   '(("TIME"           'number " ")
649                     ("MESSAGE"        'string " ")))
650             (cons "print"
651                   '(("EXPRESSION"     'string " ")))
652             (cons "save"
653                   '(("SAVE"           'list   " " "functions" "variables" "set")
654                     ("FILE"           'file   " ")))
655             (cons "update"
656                   '(("INITIAL FILE"   'file   " " t)
657                     ("UPDATED FILE"   'file   " " t))) ))
658
659
660 (defcustom gnuplot-gui-plot-splot-fit-style 'simple
661   "Control the complexity of the GUI display for plot, splot, and fit.
662 The values are 'simple, which causes a limited set of plot, splot, or
663 fit options to be displayed, and 'complete, which attempts to display
664 all options.  The 'complete setting is prone to making errors when
665 parsing values already in the script buffer."
666   :group 'gnuplot-gui
667   :type '(radio (const :tag "Simple listing"   simple)
668                 (const :tag "Complete listing" complete)))
669
670
671 (defconst gnuplot-gui-plot-simple-list
672   '(("X RANGE"     'range (" " . " ") ":")
673     ("Y RANGE"     'range (" " . " ") ":")
674     ("DATA FILE"   'file   " ")
675     ("THRU"        'string* " " "thru")
676     ("USING"       'modifier " ")
677     ("TITLE"       'string " ")
678     ("WITH"        'list* " " "boxerrorbars" "boxes"
679      "boxxyerrorbars" "candlesticks" "dots" "financebars"
680      "fsteps" "histeps" "impulses" "lines" "linespoints"
681      "points" "steps" "vector" "xerrorbars" "xyerrorbars"
682      "yerrorbars")))
683 (defconst gnuplot-gui-plot-full-list
684   '(;;("T RANGE"     'range (" " . " ") ":")
685     ("X RANGE"     'range (" " . " ") ":")
686     ("Y RANGE"     'range (" " . " ") ":")
687     ("xa"          'text   "\t---------------------")
688     ("FUNCTION"    'string " ")
689     ("xc"          'text   "   or")
690     ("DATA FILE"   'file   " ")
691     ("INDEX"       'modifier " ")
692     ("EVERY"       'modifier " ")
693     ("THRU"        'string* " " "thru")
694     ("USING"       'modifier " ")
695     ("SMOOTH"      'list* " " "unique" "csplines" "acsplines"
696      "bezier" "sbezier")
697     ;; datafile modifiers
698     ("AXES"        'list* " " "x1y1" "x2y2" "x1y2" "x2y1")
699     ("TITLE"       'string " ")
700     ("NOTITLE"     'list   " " "notitle")
701     ("xf"          'text   "\t---------------------")
702     ("xi"          'text   "Select a standard plotting style")
703     ("WITH"        'list* " " "boxerrorbars" "boxes"
704      "boxxyerrorbars" "candlesticks" "dots" "financebars"
705      "fsteps" "histeps" "impulses" "lines" "linespoints"
706      "points" "steps" "vector" "xerrorbars" "xyerrorbars"
707      "yerrorbars")
708     ("xo"          'text   "     or a previously defined style")
709     ("LINE STYLE " 'number " " "ls")
710     ("xr"          'text   "     or specify a style in-line")
711     ("LINE TYPE  " 'number " " "lt")
712     ("LINE WIDTH " 'number " " "lw")
713     ("POINT TYPE " 'number " " "pt")
714     ("POINT STYLE" 'number " " "ps")
715     ))
716 (defconst gnuplot-gui-splot-simple-list
717   '(("DATA FILE"   'file   " ")
718     ("TITLE"       'string " ")
719     ("WITH"        'list* " " "lines" "linespoints" "points" "dots" "impulses")))
720 (defconst gnuplot-gui-splot-full-list
721   '(;;("U RANGE"     'range (" " . " ") ":")
722     ;;("V RANGE"     'range (" " . " ") ":")
723     ("X RANGE"     'range (" " . " ") ":")
724     ("Y RANGE"     'range (" " . " ") ":")
725     ("Z RANGE"     'range (" " . " ") ":")
726     ("xa"          'text   "\t---------------------")
727     ("FUNCTION"    'string " ")
728     ("xc"          'text   "   or")
729     ("DATA FILE"   'file   " ")
730     ("INDEX"       'modifier " ")
731     ("EVERY"       'modifier " ")
732     ("THRU"        'string* " " "thru")
733     ("USING"       'modifier " ")
734     ("SMOOTH"      'list* " " "unique" "csplines" "acsplines"
735      "bezier" "sbezier")
736     ("TITLE"       'string " ")
737     ("NOTITLE"     'list   " " "notitle")
738     ("WITH"        'list* " " "lines" "linespoints" "points" "dots" "impulses")))
739 (defconst gnuplot-gui-fit-simple-list
740   '(("FUNCTION"     'string* " " "")
741     ("DATA FILE"    'file    " ")
742     ("VIA (params)" 'string* " " "via") ))
743 (defconst gnuplot-gui-fit-full-list
744   '(("X RANGE"      'range  (" " . " ") ":")
745     ("Y RANGE"      'range  (" " . " ") ":")
746     ("xa"           'text    "----- fitting functionn and file --------")
747     ("FUNCTION"     'string* " " "")
748     ("DATA FILE"    'file    " ")
749     ("xb"           'text    "----- datafile modifiers ----------------")
750     ("INDEX"        'modifier " ")
751     ("EVERY"        'modifier " ")
752     ("THRU"         'string* " " "thru")
753     ("USING"        'modifier " ")
754     ("SMOOTH"       'list* " " "unique" "csplines" "acsplines"
755      "bezier" "sbezier")
756     ("xc"           'text    "----- parameters (file or parameters) ---")
757     ("VIA (file)"   'string  " " "via")
758     ("VIA (params)" 'string* " " "via") ))
759
760 (defvar gnuplot-gui-plot-splot-fit nil
761   "Associated list of plot, splot, and fit descriptions.
762 See the doc-string for `gnuplot-gui-all-types'.")
763 (setq gnuplot-gui-plot-splot-fit
764       (list (cons "plot"  (if (equal gnuplot-gui-plot-splot-fit-style 'complete)
765                               gnuplot-gui-plot-full-list
766                             gnuplot-gui-plot-simple-list))
767             (cons "splot" (if (equal gnuplot-gui-plot-splot-fit-style 'complete)
768                               gnuplot-gui-splot-full-list
769                             gnuplot-gui-splot-simple-list))
770             (cons "fit"   (if (equal gnuplot-gui-plot-splot-fit-style 'complete)
771                               gnuplot-gui-fit-full-list
772                             gnuplot-gui-fit-simple-list))) )
773
774
775 (defvar gnuplot-gui-test-type nil)
776 (setq gnuplot-gui-test-type
777       (list (cons "test"
778                   '(("TAG"      'tag      " ")
779                     ("LIST"     'list     " " "1" "2" "3")
780                     ("LIST*"    'list*    " " "1" "2" "3")
781                     ("NUMBER"   'number   " " "number")
782                     ("RANGE"    'range   (" " . " ") ":")
783                     ("PAIR"     'pair    (" " . " ") "pair")
784                     ("LABELS"   'labels   ())
785                     ("FILE"     'file     " ")
786                     ("TEXT"     'text     "this is text")
787                     ("STRING"   'string   " ")
788                     ("STRING*"  'string*  " " "string*")
789                     ("FORMAT"   'format   " ")
790                     ("POSITION" 'position " " "at" 3)
791                     ("FONTSIZE" 'fontsize " ") ))))
792
793 (defvar gnuplot-gui-all-types nil
794     "Associated list of terminal, set option, and command arguments.
795
796 Each entry in the list is a cons cell of the form
797       (OPTION . ALIST)
798 where OPTION is one of the recognized options in Gnuplot, either a
799 command, something that is set, or a terminal type.  Only those
800 commands, set options, and terminal types that actually take arguments
801 are in this associated list.
802
803 ALIST is itself an associated list where each entry is of the form:
804
805       (TAG TYPE DEFAULT REST)
806
807 TAG is the name used on the widget and indicates one of the options
808 for this command, set option, or terminal type.
809
810 TYPE is one of
811      'list       a menu-list of strings
812      'list*      a menu-list of strings with a prefix
813      'number     a number with an optional prefix
814      'tag        like number but must be the first argument
815      'fontsize   like number but must be the last argument
816      'range      a pair of numbers like [#,#] or [#:#]
817      'pair       a pair of numbers with no punctuation and a prefix
818      'file       a quoted string and a file browser
819      'string     a quoted string with an optional prefix
820      'string*    an unquoted string with a prefix
821      'format     a quoted string and an info-link to (gnuplot)format
822      'labels     an array as needed for xtics, ytics, etc
823      'position   2 or 3 comma separated numbers with an optional prefix
824
825 DEFAULT is the default value for this option.  Note that the default
826 for 'range and 'pair is a cons cell and the default for 'labels is a
827 list.  For most things, the best choice of DEFAULT is a string of
828 white space or a cons cell of two strings of white space.  Strings of
829 white space are better defaults than empty strings or nil.
830
831 The value of REST depends upon TYPE:
832
833   For 'list &    REST is the list of options that will go into the
834       'list*       menu-button.  This can also be a symbol which
835                    evaluates to a list containing the options to go into
836                    the menu-button.  This list variable must contain the
837                    DEFAULT.
838   For 'number    REST is the prefix string (if it exists) for that number.
839   For 'range     REST is the separator, \":\" for plot ranges and
840                    \",\" for plot dimensions (see for example the tgif
841                    terminal type)
842   For 'string &  REST may a number denoting the width of the editable-text
843       'string*     field or it may be a string denoting a prefix.  By
844                    default, the width is half the width of the frame
845                    and there is no prefix.  It may be useful to
846                    specify \"1\" when the input is a single character
847                    as in 'set missing'.
848   For 'file      REST determines the label placed before the file insertion
849                    field.  If non-nil, then TAG is used.  If nil, then
850                    the default \"File\" is used.
851   For 'position  REST is the prefix and the number of comma separated numbers
852   For others     REST is not used.
853
854 Here is an example entry for the png terminal type:
855
856   (cons \"png\"
857         '((\"SIZE\"  'list \" \" \"small\" \"medium\" \"large\")
858           (\"COLOR\" 'list \" \" \"monochrome\" \"gray\" \"color\")))
859
860 This alist is formed at load time by appending together
861 `gnuplot-gui-terminal-types', `gnuplot-gui-set-types' and
862 `gnuplot-gui-command-types'.")
863
864 (setq gnuplot-gui-all-types (append gnuplot-gui-terminal-types
865                                     gnuplot-gui-set-types
866                                     gnuplot-gui-command-types
867                                     gnuplot-gui-plot-splot-fit
868                                     gnuplot-gui-test-type
869                                     ))
870
871
872 (defun gnuplot-gui-swap-simple-complete ()
873   (interactive)
874   (setq gnuplot-gui-plot-splot-fit-style
875         (if (equal gnuplot-gui-plot-splot-fit-style 'complete)
876             'simple 'complete))
877   (if (equal gnuplot-gui-plot-splot-fit-style 'complete)
878       (progn
879         (setcdr (assoc "plot"  gnuplot-gui-all-types) gnuplot-gui-plot-full-list)
880         (setcdr (assoc "splot" gnuplot-gui-all-types) gnuplot-gui-splot-full-list)
881         (setcdr (assoc "fit"   gnuplot-gui-all-types) gnuplot-gui-fit-full-list))
882     (setcdr (assoc "plot"  gnuplot-gui-all-types) gnuplot-gui-plot-simple-list)
883     (setcdr (assoc "splot" gnuplot-gui-all-types) gnuplot-gui-splot-simple-list)
884     (setcdr (assoc "fit"   gnuplot-gui-all-types) gnuplot-gui-fit-simple-list))
885   (message "Using %s lists for plot, splot, and fit."
886            gnuplot-gui-plot-splot-fit-style) )
887
888
889
890 \f
891 ;;; user interface to the widget-y stuff
892
893 (defun gnuplot-gui-mouse-set (event)
894   "Use the mouse to begin setting options using a GUI interface.
895 EVENT is a mouse event.  Bound to \\[gnuplot-gui-mouse-set]
896 Note that \"plot\", \"splot\", \"fit\", and \"cntrparam\" are not
897 currently supported."
898   (interactive "@e")
899   (when (fboundp 'widget-create)
900     (save-excursion
901       (mouse-set-point event)
902       (gnuplot-gui-set-options-and-insert))))
903
904 (defun gnuplot-gui-get-frame-param (param)
905   (if gnuplot-xemacs-p
906       (plist-get gnuplot-gui-frame-plist param)
907     (cdr (assoc param gnuplot-gui-frame-parameters))))
908 (defun gnuplot-gui-set-frame-param (param value)
909   (if gnuplot-xemacs-p
910       (plist-put gnuplot-gui-frame-plist param value)
911     (setcdr (assoc param gnuplot-gui-frame-parameters) value)))
912
913 (defun gnuplot-gui-set-options-and-insert ()
914   "Insert arguments using a GUI interface.
915 Determine contents of current line and set up the appropriate GUI
916 frame.  Bound to \\[gnuplot-gui-set-options-and-insert]
917 Note that \"cntrparam\" is not currently supported."
918   (interactive)
919   (when (fboundp 'widget-create)
920     (let ((begin  (gnuplot-point-at-beginning-of-command))
921           (end    (save-excursion (end-of-line)       (point-marker)))
922           (termin (concat "\\(,\\s-*" (regexp-quote "\\") "\\|;\\)"))
923           (set nil) (term nil))
924       (save-excursion
925         ;; there can be more then one command per line
926         (if (re-search-forward termin end "to_limit")
927             (progn (backward-char (length (match-string 1)))
928                    (setq end (point-marker))))
929         (goto-char begin)
930         (skip-syntax-forward "-" end)
931         ;; various constructions are recognized here. at the end of this
932         ;; cond, point should be just after the word whose arguments are
933         ;; to be set
934         (cond ((looking-at "set\\s-+")
935                (setq set t)
936                (goto-char (match-end 0))
937                (if (looking-at "\\sw+") (goto-char (match-end 0)))
938                (when (string-match "^ter" (gnuplot-this-word)) ; terminal?
939                  (setq term t)
940                  (forward-word 1))
941                (when (string-match "^\\(da\\|fu\\)" (gnuplot-this-word))
942                  (unless (looking-at "\\s-+st")
943                    (insert " style") (forward-word 1))
944                  (forward-word 1)))
945               ((looking-at (concat "\\(cd\\|ca\\|lo\\|pa\\|pr\\|sa\\|u\\)"
946                                    "\\w*"
947                                    "[\\s-\\']"))
948                (forward-word 1))
949               ;;(goto-char (match-end 0)))
950               (t
951                (forward-word 1)))
952         (if (> (point) end) (goto-char end))
953         (let* ((w (gnuplot-this-word))
954                (wd (try-completion w gnuplot-gui-all-types))
955                (word "") wrd list)
956           (cond ((equal wd t)                     (setq word w))
957                 ((equal wd nil)                   (setq word w))
958                 ((assoc wd gnuplot-gui-all-types) (setq word wd))
959                 (t                                (setq wd nil)))
960           (cond ((equal (string-match "^\\s-*$" w) 0)
961                  (message "Blank line"))
962                 ((and wd (stringp word))
963                  (gnuplot-gui-correct-command word set term begin)
964                  (setq gnuplot-gui-alist nil
965                        gnuplot-gui-current-string
966                        (buffer-substring-no-properties (point) end))
967                  (gnuplot-gui-set-alist word gnuplot-gui-current-string)
968                  (let* ((old-height (gnuplot-gui-get-frame-param 'height))
969                         (old-top    (gnuplot-gui-get-frame-param 'top)))
970                    (when (or
971                           (and (equal gnuplot-gui-plot-splot-fit-style 'complete)
972                                (member* word '("plot" "splot" "fit")
973                                         :test 'string=))
974                           (equal word "test"))
975                      (gnuplot-gui-set-frame-param 'height 32)
976                      (gnuplot-gui-set-frame-param 'top    50))
977                    (gnuplot-gui-prompt-for-frame word)
978                    (when (or
979                           (and (equal gnuplot-gui-plot-splot-fit-style 'complete)
980                                (member* word '("plot" "splot" "fit")
981                                         :test 'string=))
982                           (equal word "test"))
983                      (gnuplot-gui-set-frame-param 'height old-height)
984                      (gnuplot-gui-set-frame-param 'top    old-top)) ))
985                 ((setq wrd (car (all-completions w '(("cntrparam")))))
986                  (message
987                   "Setting arguments for %S is currently unsuported in gnuplot-mode"
988                   wrd))
989                 ((setq list (all-completions w gnuplot-gui-all-types))
990                  (message "%S could be one of %S" w list))
991                 (t
992                  (message
993                   "%S is not a gnuplot command which takes options" w)))) ))))
994
995 (defun gnuplot-gui-toggle-popup ()
996   (interactive)
997   (setq gnuplot-gui-popup-flag (not gnuplot-gui-popup-flag))
998   (message (if gnuplot-gui-popup-flag
999                "Argument popup will appear after insertions."
1000              "Argument popup will no longer appear after insertions.")))
1001
1002
1003 (defun gnuplot-gui-y-n (foo))
1004 (if gnuplot-xemacs-p
1005     (defalias 'gnuplot-gui-y-n 'y-or-n-p-maybe-dialog-box)
1006   (defalias 'gnuplot-gui-y-n 'y-or-n-p))
1007
1008 (defun gnuplot-gui-correct-command (word set term begin)
1009   "Check syntax of set command and terminal specifications.
1010 WORD is the item being set. SET and TERM are non-nil if the words
1011 \"set\" and \"terminal\" were found preceding WORD in the buffer.
1012 BEGIN is the beginning of the command."
1013   (save-excursion
1014     (cond ((assoc word gnuplot-gui-terminal-types)
1015            (when (and (not (and set term))
1016                       (gnuplot-gui-y-n
1017                        (format
1018                         "%S must be preceded by \"set terminal\".  Add it? "
1019                         word)))
1020              (backward-word 1)
1021              (let ((e (point-marker)))
1022                (goto-char begin)
1023                (skip-syntax-forward "-" e)
1024                (delete-region (point) e)
1025                (insert "set terminal "))))
1026           ((assoc word gnuplot-gui-set-types)
1027            (when (and (not set)
1028                       (gnuplot-gui-y-n
1029                        (format
1030                         "%S must be preceded by \"set\".  Add \"set\"? " word)))
1031              (backward-word 1)
1032              (let ((e (point-marker)))
1033                (goto-char begin)
1034                (skip-syntax-forward "-" e)
1035                (delete-region (point) e)
1036                (insert "set "))))))
1037   (message nil))
1038
1039
1040 \f
1041 ;;; handle the actual arguments
1042
1043 (defun gnuplot-gui-fix-arg-list (list)
1044   "Correct the result of splitting `gnuplot-gui-current-string'.
1045 LIST is the split string.  This removes empty and all-blank strings
1046 from the list and concatenates the strings that are part of a quoted
1047 argument, for example an axis label or a font name.  It also replaces
1048 bounding single quotes with double quotes, since double quotes are
1049 used in `gnuplot-gui-all-types'."
1050   (let (fixed-list quote quoted)        ; remove blanks
1051     (setq list (remove* "\\s-+" list :test 'string-match)
1052           list (remove* ""      list :test 'string=))
1053     (while list                         ; concatinate parts of quoted string
1054       (if (not (string-match "^\\([\]\[()'\"]\\)" (car list)))
1055           (setq fixed-list (append fixed-list (list (car list))))
1056         (setq quote (match-string 1 (car list))
1057               quoted (car list))
1058         (if (string= quote "[") (setq quote "]"))
1059         (if (string= quote "(") (setq quote ")"))
1060         (while (and list
1061                     (or (equal (length quoted) 1)
1062                         (not (string-match (concat (regexp-quote quote) "$")
1063                                            quoted))))
1064           (setq quoted (concat quoted " " (cadr list))
1065                 list (cdr list)))
1066         (if (string= quote "'")
1067             (setq quoted (concat "\"" (substring quoted 1))
1068                   quoted (concat (substring quoted 0 -1) "\"")))
1069         (setq fixed-list (append fixed-list (list quoted))))
1070       (setq list (cdr list)) )
1071     fixed-list))
1072
1073 (defun gnuplot-gui-set-alist (word string)
1074   "Set defaults for arguments, using text from buffer if appropriate.
1075 WORD is the Gnuplot expression whose arguments are being set.  STRING
1076 is text from the buffer containing the previous values for WORD's
1077 arguments."
1078   (let ((alist    (cdr (assoc word gnuplot-gui-all-types)))
1079         (arg-list (gnuplot-gui-fix-arg-list (split-string string)) ))
1080     ;; arg-list contains the arguments taken from the buffer
1081     (setq gnuplot-gui-alist nil)
1082     (while alist
1083       (let* ((list      (car alist))
1084              (tag       (gnuplot-gui-type-tag     list))
1085              (symbol    (eval (gnuplot-gui-type-symbol list)))
1086              (default   (gnuplot-gui-type-default list))
1087              (prefix    (gnuplot-gui-type-prefix  list))
1088              (values    (gnuplot-gui-type-list    list))
1089              (this-cons (cond ((stringp default) (cons tag default))
1090                               ((consp default) ; set cons valued default w/care
1091                                (cons tag (cons (car default) (cdr default))))
1092                               (t (cons tag default))))
1093              (temp-list arg-list) )
1094         ;;(message "%S" temp-list)      ; want to lop values off arg-list
1095                                         ; as they are found
1096         (if (symbolp (cadr values))
1097           (setq values (symbol-value (cadr values))))
1098         ;; check if an argument of this type is in arg-list
1099         ;; set the current cons cell if it is
1100         (while temp-list
1101           (cond
1102            ;; ---------------------------- list
1103            ((member* symbol '(list list*) :test 'equal)
1104             (let* ((case-fold-search nil)
1105                    (match-cons (member* (concat "^" (car temp-list))
1106                                         values :test 'string-match)))
1107               (if (and (car match-cons) ; " " may be first elem. of list
1108                        (not (string= " " (car match-cons))))
1109                   (setq this-cons (cons tag (car match-cons))
1110                         arg-list (remove* (car temp-list) arg-list
1111                                           :test 'string= :count 1)
1112                         temp-list nil)
1113                 (setq temp-list (cdr temp-list)))))
1114            ;; ---------------------------- tag (first number in list)
1115            ((equal symbol 'tag)
1116             (if (string-match "^[-0-9.]+$" (car arg-list))
1117                 (setq this-cons (cons  tag (car arg-list))
1118                       temp-list nil)
1119               (setq temp-list (cdr temp-list))) )
1120            ;; ---------------------------- fontsize (last number in list)
1121            ((equal symbol 'fontsize)
1122             (if (string-match "^[-0-9.]+$" (car (last arg-list)))
1123                 (setq this-cons (cons  tag (car (last arg-list)))
1124                       temp-list nil)
1125               (setq temp-list (cdr temp-list))) )
1126            ;; ---------------------------- number with prefix
1127            ((equal symbol 'number)
1128             (cond ((and (string= prefix (car temp-list))
1129                         (string-match "^[-0-9.]+$" (cadr temp-list)))
1130                    (setq this-cons (cons tag (cadr temp-list))
1131                          arg-list (remove* (car temp-list) arg-list
1132                                            :test 'string= :count 1)
1133                          arg-list (remove* (cadr temp-list) arg-list
1134                                            :test 'string= :count 1)
1135                          temp-list nil))
1136                   ;; --------------------- number without prefix
1137                   ((and (not prefix)
1138                         (string-match "^[-0-9.]+$" (car temp-list)))
1139                    (setq this-cons (cons tag (car temp-list))
1140                          arg-list (remove* (car temp-list) arg-list
1141                                            :test 'string= :count 1)
1142                          temp-list nil))
1143                   (t
1144                    (setq temp-list (cdr temp-list)))))
1145            ;; ---------------------------- pair with prefix
1146            ((equal symbol 'pair)
1147             (if (and (string= prefix (car temp-list))
1148                      (string-match "^[-0-9.]+$" (cadr temp-list)))
1149                 (let ((this-car (cadr temp-list))
1150                       (this-cdr (if (string-match "^[-0-9.]+$" (caddr temp-list))
1151                                     (caddr temp-list) "")))
1152                   (setq this-cons (cons tag (cons this-car this-cdr))
1153                         temp-list nil))
1154               (setq temp-list (cdr temp-list))))
1155            ;; ---------------------------- range
1156            ((equal symbol 'range)
1157             (if (string-match (concat "\\[\\s-*" ; opening bracket
1158                                       "\\([^:, \t]*\\)" ; first argument
1159                                       "\\s-*[:,]\\s-*" ; separator
1160                                       "\\([^\] \t]*\\)" ; second argument
1161                                       "\\s-*\\]") ; closing bracket
1162                               (car temp-list))
1163                 (setq this-cons
1164                       (cons tag (cons (match-string 1 (car temp-list))
1165                                       (match-string 2 (car temp-list))))
1166                       arg-list (remove* (car temp-list) arg-list
1167                                         :test 'string= :count 1)
1168                       temp-list nil)
1169               (setq temp-list (cdr temp-list)) ))
1170            ;; ---------------------------- labels
1171            ((equal symbol 'labels)
1172             (if (string-match (concat "(" ; opening paren
1173                                       "\\([^\)]*\\)" ; string
1174                                       ")") ; closing paren
1175                               (car temp-list))
1176                 (let* ((list (split-string (car temp-list) "[ \t(),]+"))
1177                        (list (remove* "" list :test 'string=))
1178                        (return ()))
1179                   (while list
1180                     (if (string-match "['\"]\\([^'\"]*\\)['\"]" (car list))
1181                         (setq return (append return
1182                                              (list (match-string 1 (car list))))
1183                               list (cdr list)
1184                               return (append return (list (car list))) )
1185                       (setq return (append return (list "" (car list)))))
1186                     (setq list (cdr list)) )
1187                   (setq this-cons (cons tag return)
1188                         arg-list (remove* (car temp-list) arg-list
1189                                           :test 'string= :count 1)
1190                         temp-list nil))
1191               (setq temp-list (cdr temp-list))) )
1192            ;; ---------------------------- string, file, format
1193            ((member* symbol '(string file format) :test 'equal)
1194             (if (string-match (concat "['\"]" ; opening quote
1195                                       "\\([^'\"]*\\)" ; string
1196                                       "['\"]") ; closing quote
1197                               (car temp-list))
1198                 (setq this-cons (cons tag (match-string 0 (car temp-list)))
1199                       arg-list (remove* (car temp-list) arg-list
1200                                         :test 'string= :count 1)
1201                       temp-list nil)
1202               (setq temp-list (cdr temp-list)) ))
1203            ;; ---------------------------- string*
1204            ((equal symbol 'string*)
1205             (if (string= prefix (car temp-list))
1206                 (setq this-cons (cons tag (cadr temp-list))
1207                       arg-list (remove* (car temp-list) arg-list
1208                                         :test 'string= :count 1)
1209                       arg-list (remove* (cadr temp-list) arg-list
1210                                         :test 'string= :count 1)
1211                       temp-list nil)
1212               (setq temp-list (cdr temp-list)) ) )
1213            ;; ---------------------------- other or unknown
1214            (t
1215             (setq temp-list nil))
1216            ))
1217         (setq gnuplot-gui-alist
1218               (append gnuplot-gui-alist (list this-cons))))
1219       (setq alist (cdr alist))) ))
1220
1221
1222 (defun gnuplot-gui-post-process-alist (type)
1223   "A few types need some additional processing.
1224 'range, 'pair, and 'labels are cons or list valued and need to b made
1225 into strings.  This is called right before inserting the arguments
1226 into the buffer.  TYPE is the object whose arguments are being set."
1227   (let ((alist gnuplot-gui-alist)
1228         (types (cdr (assoc type gnuplot-gui-all-types))) )
1229     (while alist  ;; loop thru alist looking for tyeps needing post-processing
1230       (let* ((list   (assoc (caar alist) types))
1231              (value  (cdr (assoc (caar alist) gnuplot-gui-alist)))
1232              (prefix (gnuplot-gui-type-prefix list))
1233              (symb   (gnuplot-gui-type-symbol list)) )
1234         (cond
1235          ;;-------------------------- flat text
1236          ((equal (eval symb) 'text)
1237           (setcdr (assoc (caar alist) gnuplot-gui-alist) ""))
1238          ;;-------------------------- range [#:#] or [#,#]
1239          ((equal (eval symb) 'range)
1240           (if (and (string-match "^\\s-*$" (car value))
1241                    (string-match "^\\s-*$" (cdr value)))
1242               (setcdr (assoc (caar alist) gnuplot-gui-alist) "")
1243             (setcdr (assoc (caar alist) gnuplot-gui-alist)
1244                     (concat "[" (car value) prefix (cdr value) "]")) ) )
1245          ;;-------------------------- pair
1246          ((equal (eval symb) 'pair)
1247           (if (and (string-match "^\\s-*$" (car value))
1248                    (string-match "^\\s-*$" (cdr value)))
1249               (setcdr (assoc (caar alist) gnuplot-gui-alist) "")
1250             (setcdr (assoc (caar alist) gnuplot-gui-alist)
1251                     (concat prefix " " (car value) " " (cdr value) )) ) )
1252          ;;-------------------------- labels
1253          ((equal (eval symb) 'labels)
1254           (if (consp value)
1255               (let ((word "") (list value))
1256                 (while list
1257                   (if (string-match "^\\s-*$" (car list))
1258                       (setq word (concat word (format "%s, " (cadr list))))
1259                     (setq word (concat word (format "%S %s, " (car list)
1260                                                     (cadr list)))))
1261                   (setq list (cddr list)) )
1262                 (setq value (concat "(" (substring word 0 -2) ")")))
1263             (setq value "") )
1264           (setcdr (assoc (caar alist) gnuplot-gui-alist) value) ))
1265
1266         (setq alist (cdr alist))) )))
1267
1268 \f
1269 ;;; GUI frames
1270
1271 (defun gnuplot-gui-prompt-for-frame (&optional option save-frame)
1272   (setq option (or option (completing-read "Option: " gnuplot-gui-all-types
1273                                            nil t nil t)))
1274   (gnuplot-gui-make-frame
1275    option (cdr (assoc option gnuplot-gui-all-types)) save-frame) )
1276
1277
1278 (defface gnuplot-gui-error-face '((((class color) (background light))
1279                                   (:foreground "grey30"))
1280                                  (((class color) (background dark))
1281                                   (:foreground "grey70")))
1282   "Face used to display message about unknown widget types."
1283   :group 'gnuplot-faces)
1284
1285 (defface gnuplot-gui-flat-text-face '((((class color) (background light))
1286                                        (:foreground "MediumBlue"))
1287                                       (((class color) (background dark))
1288                                        (:foreground "LightSteelBlue")))
1289   "Face used to display message about unknown widget types."
1290   :group 'gnuplot-faces)
1291
1292 (defun gnuplot-gui-make-frame (item alist &optional save-frame)
1293   "Open the frame and populate it with widgets.
1294 ITEM is the object for which arguments are being set.  ALIST is
1295 the alist of arguments for ITEM taken from `gnuplot-gui-all-types'.
1296 SAVE-FRAME is non-nil when the widgets are being reset."
1297   (unless save-frame
1298     (setq gnuplot-current-frame (selected-frame)
1299           gnuplot-current-buffer (current-buffer)
1300           gnuplot-current-buffer-point (point-marker))
1301     (unless (and gnuplot-gui-frame (frame-live-p gnuplot-gui-frame))
1302       (setq gnuplot-gui-frame (if gnuplot-xemacs-p
1303                                   (make-frame gnuplot-gui-frame-plist)
1304                                 (make-frame gnuplot-gui-frame-parameters))))
1305     (select-frame gnuplot-gui-frame)
1306     ;;(set-frame-position gnuplot-gui-frame 150 150) ;; so herky-jerky
1307     (if gnuplot-xemacs-p
1308         (set-mouse-position (selected-window) 0 0)
1309       (set-mouse-position gnuplot-gui-frame 0 0)))
1310   (kill-buffer (get-buffer-create "*Gnuplot GUI*"))
1311   (switch-to-buffer (get-buffer-create "*Gnuplot GUI*"))
1312   (kill-all-local-variables)
1313   (if gnuplot-xemacs-p
1314       (progn
1315         (set (make-local-variable 'frame-title-format)
1316              "Set Gnuplot Options")
1317         (set (make-local-variable 'frame-icon-title-format)
1318              "Set Gnuplot Options"))
1319     (modify-frame-parameters (selected-frame)
1320                              '((title . "Set Gnuplot Options"))) )
1321   (widget-insert "\nSet options for \"" item "\"  ")
1322   (let (tag help val)
1323     (cond ((string-match "^[xyz]2?tics" item)
1324            (setq tag  "info on tic labels"
1325                  help "Open a frame displaying the info entry for tic labels"
1326                  val  "xtics"))
1327           ((string-match "^no" item)
1328            (setq tag  (concat "info on " (substring item 2))
1329                  help (format "Open a frame displaying the info entry for %S"
1330                               item)
1331                  val  item))
1332           (t
1333            (setq tag  (concat "info on " item)
1334                  help (format "Open a frame displaying the info entry for %S"
1335                               item)
1336                  val  item)))
1337     (widget-create 'gnuplot-gui-info-link :tag tag :help-echo help :value val))
1338
1339   (widget-insert "\n\n")
1340   (while alist
1341     (let* ((this    (car   alist))
1342            (tag     (gnuplot-gui-type-tag    this))
1343            (wtype   (gnuplot-gui-type-symbol this))
1344            (prefix  (gnuplot-gui-type-prefix this))
1345            (default (cdr (assoc tag gnuplot-gui-alist)))
1346            (list    (gnuplot-gui-type-list   this)))
1347       (if (symbolp (cadr list))
1348           (setq list (symbol-value (cadr list))))
1349       (widget-insert "\t")              ; insert the appropriate widget
1350       (cond
1351        ;;------------------------------ list, list* ------------
1352        ((member* (eval wtype) '(list list*) :test 'equal)
1353         (let ((starred (if (equal (eval wtype) 'list*) t nil)))
1354           (gnuplot-gui-menu-choice tag default list starred)))
1355        ;;------------------------------ number, tag, fontsize --
1356        ((member* (eval wtype) '(number tag fontsize) :test 'equal)
1357         (gnuplot-gui-number tag default prefix))
1358        ;;------------------------------ position ---------------
1359        ;;------------------------------ range, pair ------------
1360        ((member* (eval wtype) '(range pair) :test 'equal)
1361         (let ((is-range (equal (eval wtype) 'range)))
1362           (gnuplot-gui-range tag default prefix is-range)))
1363        ;;------------------------------ string, string* --------
1364        ((member* (eval wtype) '(string string*) :test 'equal)
1365         (let ((starred (if (equal (eval wtype) 'string) nil t)))
1366           (gnuplot-gui-string tag default prefix starred)))
1367        ;;------------------------------ format -----------------
1368        ((equal (eval wtype) 'format)
1369         (gnuplot-gui-format tag default))
1370        ;;------------------------------ file -------------------
1371        ((equal (eval wtype) 'file)
1372         (gnuplot-gui-file tag default prefix))
1373        ;;------------------------------ labels -----------------
1374        ((equal (eval wtype) 'labels)
1375         (gnuplot-gui-labels tag default))
1376        ;;------------------------------ text -------------------
1377        ((equal (eval wtype) 'text)
1378         (let ((str (gnuplot-gui-type-default this)))
1379           (put-text-property 0 (length str) 'face 'gnuplot-gui-flat-text-face str)
1380           (widget-insert str "\n")))
1381        ;;------------------------------ unknown ----------------
1382        (t
1383         (let ((str (concat "<" (downcase tag) "> ('"
1384                            (symbol-name (eval wtype))
1385                            " arguments are not yet supported)\n")))
1386           (put-text-property 0 (length str) 'face 'gnuplot-gui-error-face str)
1387           (widget-insert str)) )))
1388     (setq alist (cdr alist)))
1389   ;; insert control buttons: [Set options]   [Reset]   [Clear]   [Cancel]
1390   (widget-insert "\n\t")
1391   (widget-create 'push-button
1392                  :value "Set options"
1393                  :doc item
1394                  :button-face 'gnuplot-gui-button-face
1395                  :help-echo "Push this button to set options"
1396                  :notify
1397                  (lambda (widget &rest ignore)
1398                    (kill-buffer (get-buffer-create "*Gnuplot GUI*"))
1399                    (delete-frame)
1400                    (select-frame gnuplot-current-frame)
1401                    (switch-to-buffer gnuplot-current-buffer)
1402                    (goto-char gnuplot-current-buffer-point)
1403                    (gnuplot-gui-post-process-alist
1404                     (widget-get widget :doc))
1405                    (let ((alist gnuplot-gui-alist) marker
1406                          (eol (save-excursion (end-of-line) (point-marker) )) )
1407                      (if (re-search-forward ";" eol "to_limit")
1408                          (backward-char 1))
1409                      (delete-region gnuplot-current-buffer-point (point-marker))
1410                      (delete-horizontal-space)
1411                      (setq marker (point-marker))
1412                      (while alist
1413                        (let ((val (cdar alist)))
1414                          (if (string-match "^\\s-+$" val) ()
1415                            (if (string-match "^['\"]\\(.*\\)['\"]$" val)
1416                                (setq val (concat gnuplot-quote-character
1417                                                  (match-string 1 val)
1418                                                  gnuplot-quote-character)))
1419                            (insert (format " %s" val))))
1420                        (setq alist (cdr alist)))
1421                      (setq eol (point-marker))
1422                      (goto-char marker)
1423                      (while (< (point) eol) ; a few odd cases
1424                        (unless (looking-at (concat "[" (regexp-quote "(")
1425                                                    (regexp-quote "*") ",]"))
1426                          (just-one-space))
1427                        (forward-sexp)))
1428                    (delete-horizontal-space)
1429                    (if (string= "terminal" (widget-get widget :doc))
1430                        (gnuplot-gui-set-options-and-insert)) ))
1431   (widget-insert "   ")
1432   (widget-create 'push-button :value "Reset"
1433                  :help-echo "Push this button to reset all values"
1434                  :button-face 'gnuplot-gui-button-face
1435                  :doc item
1436                  :notify
1437                  (lambda (widget &rest ignore)
1438                    (let ((word (widget-get widget :doc)))
1439                      (gnuplot-gui-set-alist word gnuplot-gui-current-string)
1440                      (gnuplot-gui-prompt-for-frame word t))))
1441   (widget-insert "   ")
1442   (widget-create 'push-button :value "Clear"
1443                  :help-echo "Push this button to clear all values"
1444                  :button-face 'gnuplot-gui-button-face
1445                  :doc item
1446                  :notify
1447                  (lambda (widget &rest ignore)
1448                    (let* ((word (widget-get widget :doc))
1449                           (alist (cdr (assoc word gnuplot-gui-all-types))))
1450                      (while alist
1451                        (setcdr (assoc (gnuplot-gui-type-tag (car alist))
1452                                       gnuplot-gui-alist)
1453                                (gnuplot-gui-type-default (car alist)))
1454                        (setq alist (cdr alist)))
1455                      (gnuplot-gui-prompt-for-frame word t))) )
1456   (widget-insert "   ")
1457   (widget-create 'push-button :value "Cancel"
1458                  :help-echo "Quit setting options and dismiss frame"
1459                  :button-face 'gnuplot-gui-button-face
1460                  :notify (lambda (widget &rest ignore)
1461                            (kill-buffer (get-buffer-create "*Gnuplot GUI*"))
1462                            (setq gnuplot-gui-alist nil
1463                                  gnuplot-gui-current-string nil)
1464                            (delete-frame)
1465                            (select-frame gnuplot-current-frame)))
1466   (goto-char (point-min))
1467   (use-local-map widget-keymap)
1468   (widget-setup))
1469
1470 \f
1471 ;;; widgets
1472
1473 (defface gnuplot-gui-menu-face '((((class color) (background light))
1474                                   (:bold t :foreground "darkolivegreen"))
1475                                  (((class color) (background dark))
1476                                   (:bold t :foreground "seagreen"))
1477                                  (t
1478                                   (:italic t)))
1479   "Face used for menu-buttons."
1480   :group 'gnuplot-faces)
1481 (defface gnuplot-gui-button-face '((((class color) (background light))
1482                                   (:bold t :foreground "sienna"))
1483                                  (((class color) (background dark))
1484                                   (:bold t :foreground "tan"))
1485                                  (t
1486                                   (:italic t)))
1487   "Face used for push-buttons.
1488 Only used in Emacs.  XEmacs displays push-buttons with a pixmap."
1489   :group 'gnuplot-faces)
1490 (defface gnuplot-gui-labels-face '((((class color) (background light))
1491                                     (:bold t :foreground "darkslateblue"))
1492                                    (((class color) (background dark))
1493                                     (:bold t :foreground "lightslateblue"))
1494                                    (t
1495                                     (:italic t)))
1496   "Face used for insert and delete button in the labels widget."
1497   :group 'gnuplot-faces)
1498
1499 (defun gnuplot-gui-menu-choice (item default list &optional starred)
1500   "Create a menu widget for the Gnuplot GUI.
1501 ITEM is the object whose arguments are set by this widget, DEFAULT
1502 is the default argument value, LIST contains the items for the pop-up
1503 menu.  STARRED is true if this a 'list* widget."
1504   (let ((widget
1505          (apply 'widget-create
1506                 'menu-choice :value default :tag item :doc starred
1507                 :button-face 'gnuplot-gui-menu-face
1508                 :button-prefix "[" :button-suffix "]"
1509                 :help-echo (format "Mouse-2 to view the %S menu" (downcase item))
1510                 :notify
1511                 (lambda (widget &rest ignore)
1512                   (let ((lab (if (widget-get widget :doc)
1513                                  (concat (downcase (widget-get widget :tag)) " ")
1514                                "" )))
1515                     (setcdr (assoc (widget-get widget :tag) gnuplot-gui-alist)
1516                             (if (string= (widget-value widget) " ") ""
1517                               (format "%s%s" lab (widget-value widget))) )))
1518                 (mapcar (lambda (x) (list 'item :value x))
1519                         list))))
1520     (widget-value-set widget default)
1521     (if (and starred (not (string-match "^\\s-*$" default)))
1522         (setcdr (assoc item gnuplot-gui-alist)
1523                 (format "%s %s" (downcase item) default)))
1524     widget))
1525
1526 (defun gnuplot-gui-number (item default &optional prefix)
1527   "Create a number widget for the Gnuplot GUI.
1528 ITEM is the object whose arguments are set by this widget, DEFAULT
1529 is the default value for the widget, PREFIX is a text string preceding
1530 the numerical argument."
1531   (let ((help-label (or prefix (downcase item))))
1532     (widget-insert (capitalize item) ": ")
1533     (widget-create 'editable-field
1534                    :size 2 :tag item :value default :doc prefix
1535                    :help-echo (format "Insert new value of %S here" help-label)
1536                    :notify (lambda (widget &rest ignore)
1537                              (let ((val (widget-value widget))
1538                                    (pre (concat (widget-get widget :doc) " ")))
1539                                (setcdr (assoc (widget-get widget :tag)
1540                                               gnuplot-gui-alist)
1541                                        (if (string-match
1542                                             "^\\s-*[-0-9.*]+\\s-*$" val)
1543                                            (format "%s%s" pre val) "") )))))
1544   (unless (string-match "^\\s-*$" default)
1545     (setcdr (assoc item gnuplot-gui-alist) (format "%s %s" prefix default)))
1546   (widget-insert " " (make-string (- 40 (current-column)) ?.)
1547                  " (numeric value)\n"))
1548
1549 (defun gnuplot-gui-string (item default &optional width_or_prefix starred)
1550   "Create a string widget for the Gnuplot GUI.
1551 ITEM is the object whose arguments are set by this widget, DEFAULT is
1552 the default value for the widget, and WIDTH_OR_PREFIX is the width of
1553 the text entry field (which defaults to half the frame width) or the
1554 prefix for the string.  STARRED is t if quotes are not to be used."
1555   (let ((help-label (downcase item)) width (prefix "") (pp ""))
1556     (cond ((stringp width_or_prefix)
1557            (setq prefix width_or_prefix
1558                  pp prefix)
1559            (if starred (setq prefix (concat prefix "_star"))) )
1560           ((numberp width_or_prefix)
1561            (setq width width_or_prefix)))
1562     (setq width (or width (/ (frame-width) 2)))
1563     (if (string-match "^['\"]" default)
1564         (setq default (replace-match "" nil nil default)))
1565     (if (string-match "['\"]$" default)
1566         (setq default (replace-match "" nil nil default)))
1567     (widget-insert (capitalize item) ": ")
1568     (widget-create
1569      'editable-field
1570      :size width :tag item :doc prefix :value default
1571      :help-echo (format "Insert new value of %S here" help-label)
1572      :notify (lambda (widget &rest ignore)
1573                (let ((val (widget-value widget))
1574                      (q gnuplot-quote-character)
1575                      (p (widget-get widget :doc)) )
1576                  (setcdr (assoc (widget-get widget :tag) gnuplot-gui-alist)
1577                          (if (string-match "^\\s-*$" val)
1578                              ""
1579                            (progn
1580                              (if (string-match "_star$" p)
1581                                  (setq p (concat (substring p 0 -5) " ")
1582                                        q ""))
1583                              (if (string-match "^\\s-+" val)
1584                                  (setq val (replace-match "" nil nil val)))
1585                              (if (string-match "\\s-+$" val)
1586                                  (setq val (replace-match "" nil nil val)))
1587                              (format "%s%s%s%s" p q val q)))))))
1588     (unless (string-match "^\\s-*$" default)
1589       (setcdr (assoc item gnuplot-gui-alist) (format "%s %s" pp default)))
1590     (widget-insert "\n")))
1591
1592 (defun gnuplot-gui-format (item default)
1593   "Create a string widget for the Gnuplot GUI.
1594 ITEM is the object whose arguments are set by this widget, DEFAULT is
1595 the default value for the widget, and WIDTH_OR_PREFIX is the width of
1596 the text entry field (which defaults to half the frame width) or the
1597 prefix for the string."
1598   (if (string-match "^['\"]" default)
1599       (setq default (replace-match "" nil nil default)))
1600   (if (string-match "['\"]$" default)
1601       (setq default (replace-match "" nil nil default)))
1602   (widget-insert (capitalize item) ": ")
1603   (widget-create 'editable-field
1604                  :size (/ (frame-width) 3) :tag item :value default
1605                  :help-echo (format "Insert new format string here")
1606                  :notify (lambda (widget &rest ignore)
1607                            (let ((val (widget-value widget)))
1608                              (setcdr (assoc (widget-get widget :tag)
1609                                             gnuplot-gui-alist)
1610                                      (format "%s%s%s"
1611                                              gnuplot-quote-character
1612                                              val
1613                                              gnuplot-quote-character)))))
1614   (widget-insert "   ")
1615   (widget-create 'gnuplot-gui-info-link
1616                  :tag (concat "info on format")
1617                  :help-echo "Open a frame displaying the info entry for format"
1618                  :value "format")
1619   (widget-insert "\n"))
1620
1621
1622 ;; swiped from widget-color-complete
1623 (defun gnuplot-gui-file-completion (widget)
1624   "Complete the filename in WIDGET."
1625   (let* ((str (buffer-substring-no-properties (widget-field-start widget)
1626                                               (point)))
1627          (file (or (file-name-nondirectory str) ""))
1628          (dir  (or (file-name-directory str) "./"))
1629          (val  (file-name-completion file dir)) )
1630     (cond ((eq val t)
1631            (message "Exact match"))
1632           ((null val)
1633            (error "Can't find completion for \"%s\"" str))
1634           ((not (string-equal str val))
1635            (insert (substring val (length file))))
1636           (t
1637            (message "Making completion list...")
1638            (let ((list (file-name-all-completions file dir)))
1639              (with-output-to-temp-buffer "*Completions*"
1640                (display-completion-list list)))
1641            (message "Making completion list...done")))))
1642
1643 (defun gnuplot-gui-file (item default &optional tag)
1644   "Create a file widget for the Gnuplot GUI.
1645 ITEM is the object whose arguments is set by this widget, DEFAULT is
1646 the default value for the argument.  TAG is non-nil if ITEM rather than
1647 \"File:\" is to be used as the tag."
1648   (setq tag (if tag (capitalize item) "File"))
1649   (if (string-match "^['\"]" default)
1650       (setq default (replace-match "" nil nil default)))
1651   (if (string-match "['\"]$" default)
1652       (setq default (replace-match "" nil nil default)))
1653   (let ((widg (widget-create
1654                'file
1655                :value default :tag tag
1656                :size (- (/ (frame-width) 2) 3)
1657                :doc item :help-echo "Insert a filename here"
1658                :complete 'gnuplot-gui-file-completion
1659                :notify
1660                (lambda (widget &rest ignore)
1661                  (setcdr (assoc (widget-get widget :doc) gnuplot-gui-alist)
1662                          (format "%s%s%s" gnuplot-quote-character
1663                                  (widget-value widget)
1664                                  gnuplot-quote-character)) )) ))
1665     (widget-insert " ")
1666     (widget-create
1667      'push-button :value "Browse"
1668      :doc item :help-echo "Browse directories for a filename."
1669      :parent widg
1670      :notify (lambda (widget &rest ignore)
1671                (let ((fname (file-relative-name (read-file-name "File: ")
1672                                                 default-directory))
1673                      (q gnuplot-quote-character))
1674                  (widget-value-set (widget-get widget :parent) fname)
1675                  (setcdr (assoc (widget-get widget :doc) gnuplot-gui-alist)
1676                          (format "%s%s%s" q fname q))
1677                  (widget-setup))))
1678     (widget-insert "\n")))
1679
1680 (defun gnuplot-gui-labels (item default)
1681   "Create a labels widget for the Gnuplot GUI.
1682 ITEM is the object whose arguments is set by this widget, DEFAULT is
1683 the default value for the argument."
1684   (widget-create
1685    '(editable-list
1686      (list :inline t :tag "Tic label"
1687            (string :tag "label" :size 10
1688                    :help-echo "Enter the tic label here" )
1689            (string :tag "  position" :size 10
1690                    :help-echo "Enter an expression for the tic location here" )))
1691                  :tag (capitalize item)
1692                  :value default
1693                  :format "%{%t%}:\n%v\t  %i\n"
1694                  :entry-format "\t  %i %d %v\n"
1695                  :button-face 'gnuplot-gui-labels-face
1696                  :notify (lambda (widget &rest ignore)
1697                            (setcdr (assoc (upcase (widget-get widget :tag))
1698                                           gnuplot-gui-alist)
1699                                    (widget-value widget)))))
1700
1701 (defun gnuplot-gui-range (item default separator is-range)
1702   "Create a range or pair widget for the Gnuplot GUI.
1703 ITEM is the object whose arguments are set by this widget, DEFAULT is
1704 the default value for the widget, SEPARATOR is a text string preceding
1705 the numerical argument, or the prefix for a pair operator.  IS-RANGE
1706 is non-nil if this is a 'range widget."
1707   (widget-insert (capitalize item) ": ")
1708   (if is-range (widget-insert "["))
1709   (widget-create 'editable-field
1710                  :size 4 :tag item :value (car default)
1711                  :help-echo (format "Insert the first value of the %S here"
1712                                     (downcase item))
1713                  :notify (lambda (widget &rest ignore)
1714                            (setcar (cdr (assoc (widget-get widget :tag)
1715                                                gnuplot-gui-alist))
1716                                    (format "%s" (widget-value widget)))))
1717   (if is-range (widget-insert separator) (widget-insert "  "))
1718   (widget-create 'editable-field
1719                  :size 4 :tag item :value (cdr default)
1720                  :help-echo (format "Insert the second value of the %S here"
1721                                     (downcase item))
1722                  :notify (lambda (widget &rest ignore)
1723                            (setcdr (cdr (assoc (widget-get widget :tag)
1724                                                gnuplot-gui-alist))
1725                                    (format "%s" (widget-value widget)))))
1726   (if is-range (widget-insert "]"))
1727   (widget-insert " " (make-string (- 39 (current-column)) ?.)
1728                  " (numeric values)\n"))
1729
1730
1731 ;; suppress compiler warning
1732 ;;(eval-when-compile (defun gnuplot-info-lookup-symbol (sym mode)))
1733 (define-widget 'gnuplot-gui-info-link 'info-link
1734   "A link to an info file for the Gnuplot GUI."
1735   :action '(lambda (widget &optional event)
1736              (let ((gnuplot-info-display 'frame))
1737                (if gnuplot-keywords-pending             ; <HW>
1738                    (gnuplot-setup-info-look))
1739                (gnuplot-info-lookup-symbol (widget-value widget)
1740                                            'gnuplot-mode))))
1741
1742 \f
1743 ;;; just about done
1744
1745 (provide 'gnuplot-gui)
1746 ;;;============================================================================
1747 ;;;
1748 ;;; gnuplot-gui.el ends here