1;;
2;; Copyright (c) 2002 by The XFree86 Project, Inc.
3;;
4;; Permission is hereby granted, free of charge, to any person obtaining a
5;; copy of this software and associated documentation files (the "Software"),
6;; to deal in the Software without restriction, including without limitation
7;; the rights to use, copy, modify, merge, publish, distribute, sublicense,
8;; and/or sell copies of the Software, and to permit persons to whom the
9;; Software is furnished to do so, subject to the following conditions:
10;;
11;; The above copyright notice and this permission notice shall be included in
12;; all copies or substantial portions of the Software.
13;;
14;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17;; THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19;; OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20;; SOFTWARE.
21;;
22;; Except as contained in this notice, the name of the XFree86 Project shall
23;; not be used in advertising or otherwise to promote the sale, use or other
24;; dealings in this Software without prior written authorization from the
25;; XFree86 Project.
26;;
27;; Author: Paulo César Pereira de Andrade
28;;
29;;
30;; $XdotOrg: xc/programs/xedit/lisp/modules/xedit.lsp,v 1.2 2004/04/23 19:54:45 eich Exp $
31;; $XFree86: xc/programs/xedit/lisp/modules/xedit.lsp,v 1.9 2003/01/16 03:50:46 paulo Exp $
32;;
33
34(provide "xedit")
35
36#+debug	(make-package "XEDIT" :use '("LISP" "EXT"))
37(in-package "XEDIT")
38
39
40;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
41;;  TODO The user should be able to define *auto-modes* prior to the
42;; initialization here in a configuration file, since defvar only binds
43;; the variable if it is unbound or doesn't have a value defined.
44;;  *auto-modes* is a list of conses where every car is compiled
45;; to a regexp to match the name of the file being loaded. The caddr is
46;; either a string, a pathname, or a syntax-p.
47;;  When loading a file, if the regexp in the car matches, it will check
48;; the caddr value, and if it is a:
49;;	string:		executes (load "progmodes/<the-string>.lsp")
50;;	pathname:	executes (load <the-pathhame>)
51;;	syntax-p:	does nothing, already loaded
52;;
53;;  If it fails to load the file, or the returned value is not a
54;; syntax-p, the entry is removed.
55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
56(defvar *auto-modes* '(
57    ("\\.(c|cc|C|cxx|cpp|h|hpp|bm|xbm|xpm|y|h\\.in)$"
58	"C/C++"		"c"	. *c-mode*)
59    ("\\.(l|li?sp|scm)$"
60	"Lisp/Scheme"	"lisp"	. *lisp-mode*)
61    ("\\.sh$"
62	"Unix shell"	"sh"	. *sh-mode*)
63    ("\\.(diff|patch)"
64	"Patch file"	"patch"	. *patch-mode*)
65    ("/[Mm]akefile.*|\\.mk$"
66	"Makefile"	"make"	. *make-mode*)
67    ("\\.(ac|in|m4)$"
68	"Autotools"	"auto"	. *auto-mode*)
69    ("\\.spec$"
70	"RPM spec"	"rpm"	. *rpm-mode*)
71    ("\\.(pl|pm|ph)$"
72	"Perl"		"perl"	. *perl-mode*)
73    ("\\.(py)$"
74	"Python"	"python". *python-mode*)
75    ("\\.(sgml?|dtd)$"
76	"SGML"		"sgml"	. *sgml-mode*)
77    ("\\.html?$"
78	"HTML"		"html"	. *html-mode*)
79    ("\\.(man|\\d)$"
80	"Man page"	"man"	. *man-mode*)
81    ("app-defaults/\\w+|\\u[A-Za-z0-9_-]+\\.ad"
82	"X resource"	"xrdb"	. *xrdb-mode*)
83    ("\\<(XF86Config|xorg.conf)[^/]*"
84	"XF86Config"	"xconf"	. *xconf-mode*)
85    ("\\<(XFree86|Xorg)\\.\\d+\\.log(\\..*|$)"
86	"XFree86 log"	"xlog"	. *xlog-mode*)
87    ("Imakefile|(\\.(cf|rules|tmpl|def)$)"
88	"X imake"	"imake"	. *imake-mode*)
89))
90
91
92;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
93;; Compile the regexps in the *auto-modes* list.
94;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
95(dolist (mode *auto-modes*)
96    (rplaca mode (re-comp (car mode) :nosub t))
97)
98
99
100;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
101;; Find the progmode associated with the given filename.
102;; Returns nil if nothing matches.
103;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
104(defun auto-mode (filename &optional symbol &aux syntax)
105    (if (and symbol (symbolp symbol))
106	(if (boundp symbol)
107	    (return-from auto-mode (symbol-value symbol))
108	    (setq syntax (cddr (find symbol *auto-modes* :key #'cdddr)))
109	)
110	;; symbol optional argument is not a symbol
111	(do*
112	    (
113	    (mode   *auto-modes*    (cdr mode))
114	    (regex  (caar mode)     (caar mode))
115	    )
116	    ((endp mode))
117
118	    ;; only wants to know if the regex match.
119	    (when (listp (re-exec regex filename :count 0))
120		(setq syntax (cddar mode) symbol (cdr syntax))
121		(return)
122	    )
123	)
124    )
125
126    ;; if file was already loaded
127    (if (and symbol (boundp symbol))
128	(return-from auto-mode (symbol-value symbol))
129    )
130
131    (when (consp syntax)
132	;; point to the syntax file specification
133	(setq syntax (car syntax))
134
135	;; try to load the syntax definition file
136	(if (stringp syntax)
137	    (load
138		(string-concat
139		    (namestring *default-pathname-defaults*)
140		    "progmodes/"
141		    syntax
142		    ".lsp"
143		)
144	    )
145	    (load syntax)
146	)
147
148	(and symbol (boundp symbol) (symbol-value symbol))
149    )
150)
151
152
153;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
154;; Data types.
155;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
156;;  The main syntax structure, normally, only one should exist per
157;; syntax highlight module.
158;;  The structure is defined here so it is not required to load all
159;; the extra data associated with syntax-highlight at initialization
160;; time, and will never be loaded if no syntax-highlight mode is
161;; defined to the files being edited.
162(defstruct syntax
163    name		;;  A unique string to identify the syntax mode.
164			;; Should be the name of the language/file type.
165    options		;;  A hash table of options specified for the
166			;; language.
167
168    ;; Field(s) defined at "compile time"
169    labels		;;  Not exactly a list of labels, but all syntax
170			;; tables for the module.
171    quark		;;  A XrmQuark associated with the XawTextPropertyList
172			;; used by this syntax mode.
173    token-count		;;  Number of distinct syntoken structures in
174			;; the syntax table.
175)
176
177;;  Xlfd description, used when combining properties.
178;;  Field names are self descriptive.
179;;	XXX Fields should be initialized as strings, but fields
180;;	    that have an integer value should be allowed to
181;;	    be initialized as such.
182;;  Combining properties in supported in Xaw, but not yet in the
183;; syntax highlight code interface. Combining properties allow easier
184;; implementation for markup languages, for example:
185;;	<b>bold<i>italic</i></b>
186;;	would render "bold" using a bold version of the default font,
187;;	and "italic" using a bold and italic version of the default font
188(defstruct xlfd
189    foundry
190    family
191    weight
192    slant
193    setwidth
194    addstyle
195    pixel-size
196    point-size
197    res-x
198    res-y
199    spacing
200    avgwidth
201    registry
202    encoding
203)
204
205
206;;   At some time this structure should also hold information for at least:
207;;	o fontset
208;;	o foreground pixmap
209;;	o background pixmap
210;;   XXX This is also a TODO in Xaw.
211(defstruct synprop
212    quark	;;   XrmQuark identifier of the XawTextProperty
213		;; structure. This field is filled when "compiling"
214		;; the syntax-table.
215
216    name	;;   String name of property, must be unique per
217		;; property list.
218    font	;; Optional font string name of property.
219    foreground	;; Optional string representation of foreground color.
220    background	;; Optional string representation of background color.
221    xlfd	;;   Optional xlfd structure, when combining properties.
222		;; Currently combining properties logic not implemented,
223		;; but fonts may be specified using the xlfd definition.
224
225    ;; Boolean properties.
226    underline	;; Draw a line below the text.
227    overstrike	;; Draw a line over the text.
228
229    ;; XXX Are these working in Xaw?
230    subscript	;; Align text to the bottom of the line.
231    superscript	;; Align text to the top of the line.
232    ;;  Note: subscript and superscript only have effect when the text
233    ;; line has different height fonts displayed.
234)
235
236
237;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
238;;  Utility macro, to create a "special" variable holding
239;; a synprop structure.
240;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
241(defmacro defsynprop (variable name
242		      &key font foreground background xlfd underline
243			   overstrike subscript superscript)
244    `(progn
245	(proclaim '(special ,variable))
246	(setq ,variable
247	    (make-synprop
248		:name		,name
249		:font		,font
250		:foreground	,foreground
251		:background	,background
252		:xlfd		,xlfd
253		:underline	,underline
254		:overstrike	,overstrike
255		:subscript	,subscript
256		:superscript	,superscript
257	    )
258	)
259    )
260)
261
262
263;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
264;;  Convert a synprop structure  to a string in the format
265;; expected by Xaw.
266;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
267(defun synprop-to-string (synprop &aux values booleans xlfd)
268    (if (setq xlfd (synprop-xlfd synprop))
269	(dolist
270	    (element
271	       `(
272		("foundry"	    ,(xlfd-foundry xlfd))
273		("family"	    ,(xlfd-family xlfd))
274		("weight"	    ,(xlfd-weight xlfd))
275		("slant"	    ,(xlfd-slant xlfd))
276		("setwidth"	    ,(xlfd-setwidth xlfd))
277		("addstyle"	    ,(xlfd-addstyle xlfd))
278		("pixelsize"	    ,(xlfd-pixel-size xlfd))
279		("pointsize"	    ,(xlfd-point-size xlfd))
280		("resx" 	    ,(xlfd-res-x xlfd))
281		("resy" 	    ,(xlfd-res-y xlfd))
282		("spacing"	    ,(xlfd-spacing xlfd))
283		("avgwidth"	    ,(xlfd-avgwidth xlfd))
284		("registry"	    ,(xlfd-registry xlfd))
285		("encoding"	    ,(xlfd-encoding xlfd))
286		)
287	    )
288	    (if (cadr element)
289		(setq values (append values element))
290	    )
291	)
292    )
293    (dolist
294	(element
295	   `(
296	    ("font"		,(synprop-font synprop))
297	    ("foreground"	,(synprop-foreground synprop))
298	    ("background"	,(synprop-background synprop))
299	    )
300	)
301	(if (cadr element)
302	    (setq values (append values element))
303	)
304    )
305
306    ;;  Boolean attributes. These can be specified in the format
307    ;; <name>=<anything>, but do a nicer output as the format
308    ;; <name> is accepted.
309    (dolist
310	(element
311	    `(
312	    ("underline"	,(synprop-underline synprop))
313	    ("overstrike"	,(synprop-overstrike synprop))
314	    ("subscript"	,(synprop-subscript synprop))
315	    ("superscript"	,(synprop-superscript synprop))
316	    )
317	)
318	(if (cadr element)
319	    (setq booleans (append booleans element))
320	)
321    )
322
323    ;;  Play with format conditionals, list iteration, and goto, to
324    ;; make resulting string.
325    (format
326	nil
327	"~A~:[~;?~]~:[~3*~;~A=~A~{&~A=~A~}~]~:[~;&~]~:[~2*~;~A~{&~A~*~}~]"
328
329	(synprop-name synprop)				;; ~A
330	(or values booleans)				;; ~:[~;?~]
331	values						;; ~:[
332	    (car values) (cadr values) (cddr values)	;; ~A=~A~{&~A=~A~}
333	(and values booleans)				;; ~:[~;&~]
334	booleans					;; ~:[
335	    (car booleans) (cddr booleans)		;; ~A~{&~A~*~}
336    )
337)
338
339
340;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
341;;  Use xedit protocol to create a XawTextPropertyList with the
342;; given arguments.
343;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
344(defun compile-syntax-property-list (name properties
345				     &aux string-properties quark)
346
347    ;; Create a string representation of the properties.
348    (dolist (property properties)
349	(setq
350	    string-properties
351	    (append
352		string-properties
353		(list (synprop-to-string property))
354	    )
355	)
356    )
357
358    (setq
359	string-properties
360	(case (length string-properties)
361	    (0	"")
362	    (1	(car string-properties))
363	    (t	(format nil "~A~{,~A~}"
364		    (car string-properties)
365		    (cdr string-properties)
366		)
367	    )
368	)
369    )
370
371#+debug
372    (format *output* "~Cconvert-property-list ~S ~S~%"
373	*escape*
374	name
375	string-properties
376    )
377    (setq quark #-debug (convert-property-list name string-properties)
378		#+debug 0)
379
380    ;; Store the quark for properties not yet "initialized".
381    ;; XXX This is just a call to Xrm{Perm,}StringToQuark, and should
382    ;;     be made available if there were a wrapper/interface to
383    ;;     that Xlib function.
384    (dolist (property properties)
385	(unless (integerp (synprop-quark property))
386#+debug
387	    (format *output* "~Cxrm-string-to-quark ~S~%"
388		*escape*
389		(synprop-name property)
390	    )
391	    (setf
392		(synprop-quark property)
393#-debug		(xrm-string-to-quark (synprop-name property))
394#+debug		0
395	    )
396	)
397    )
398
399    quark
400)
401
402
403
404
405#+debug
406(progn
407    (defconstant *escape* #\$)
408
409    (defconstant *output* *standard-output*)
410
411    ;; Recognized identifiers for wrap mode.
412    (defconstant *wrap-modes* '(:never :line :word))
413
414    ;; Recognized identifiers for justification.
415    (defconstant *justifications* '(:left :right :center :full))
416
417    ;; XawTextScanType
418    (defconstant *scan-type*
419	'(:positions :white-space :eol :paragraph :all :alpha-numeric))
420
421    ;; XawTextScanDirection
422    (defconstant *scan-direction* '(:left :right))
423
424    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
425    ;; Debugging version of xedit functions.
426    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
427    (defun clear-entities (left right)
428	(format *output* "~Cclear-entities ~D ~D~%"
429	    *escape* left right))
430
431    (defun add-entity (offset length identifier)
432	(format *output* "~Cadd-entity ~D ~D ~D~%"
433	    *escape* offset length identifier))
434
435    (defun background (&optional (value nil specified))
436	(if specified
437	    (format *output* "~Cset-background ~S~%" *escape* value)
438	    (format *output* "~Cget-background~%" *escape*)))
439
440    (defun foreground (&optional (value nil specified))
441	(if specified
442	    (format *output* "~Cset-foreground ~S~%" *escape* value)
443	    (format *output* "~Cget-foreground~%" *escape*)))
444
445    (defun font (&optional (value nil specified))
446	(if specified
447	    (format *output* "~Cset-font ~S~%" *escape* value)
448	    (format *output* "~Cget-font~%" *escape*)))
449
450    (defun point (&optional (value nil specified))
451	(if specified
452	    (format *output* "~Cset-point ~D~%" *escape* value)
453	    (format *output* "~Cget-point~%" *escape*)))
454
455    (defun point-min ()
456	(format *output* "~Cpoint-min~%" *escape*))
457
458    (defun point-max ()
459	(format *output* "~Cpoint-max~%" *escape*))
460
461    (defun property-list (&optional (quark nil specified))
462	(format *output* "~property-list ~D~%" *escape* quark))
463
464    (defun insert (string)
465	(format *output* "~Cinsert ~S~%" *escape* string))
466
467    (defun read-text (offset length)
468	(format *output* "~Cread-text ~D ~D~%"
469	    *escape* offset length))
470
471    (defun replace-text (left right string)
472	(format *output* "~Creplace-text ~D ~D ~S~%"
473	    *escape* left right string))
474
475    (defun scan (offset type direction &key (count 1) include)
476	(unless (setq type (position type *scan-type*))
477	    (error "SCAN: type must be one of ~A, not ~A"
478		*scan-type* type))
479	(unless (setq direction (position direction *scan-direction*))
480	    (error "SCAN: direction must be one of ~A, not ~A"
481		*scan-direction* direction))
482	(format *output* "~Cscan ~D ~D ~D ~D ~D~%"
483	    *escape* offset type direction count (if include 1 0)))
484
485    (defun search-forward (string &optional case-sensitive)
486	(format *output* "~Csearch-forward ~S ~D~%"
487	    *escape* string (if case-sensitive 1 0)))
488
489    (defun search-backward (string &optional case-sensitive)
490	(format *output* "~Csearch-backward ~S ~D~%"
491	    *escape* string (if case-sensitive 1 0)))
492
493    (defun wrap-mode (&optional (value nil specified))
494	(if specified
495	    (progn
496		(unless (member value *wrap-modes*)
497		    (error "WRAP-MODE: argument must be one of ~A, not ~A"
498			*wrap-modes* value))
499		(format *output* "~Cset-wrap-mode ~S~%"
500		    *escape* (string value)))
501	    (format *output* "~Cget-wrap-mode~%" *escape*)))
502
503    (defun auto-fill (&optional (value nil specified))
504	(if specified
505	    (format *output* "~Cset-auto-fill ~S~%"
506		*escape* (if value "true" "false"))
507	    (format *output* "~Cget-auto-fill~%" *escape*)))
508
509    (defun justification (&optional (value nil specified))
510	(if specified
511	    (progn
512		(unless (member value *justifications*)
513		    (error "JUSTIFICATION: argument must be one of ~A, not ~A"
514			*justifications* value))
515		(format *output* "~Cset-justification ~S~%"
516		    *escape* (string value)))
517	    (format *output* "~Cget-justification~%" *escape*)))
518
519    (defun left-column (&optional (value nil specified))
520	(if specified
521	    (format *output* "~Cset-left-column ~D~%" *escape* value)
522	    (format *output* "~Cget-left-column~%" *escape*)))
523
524    (defun right-column (&optional (value nil specified))
525	(if specified
526	    (format *output* "~Cset-right-column ~D~%" *escape* value)
527	    (format *output* "~Cget-right-column~%" *escape*)))
528
529    (defun vertical-scrollbar (&optional (value nil specified))
530	(if specified
531	    (format *output* "~Cset-vert-scrollbar ~S~%"
532		*escape* (if value "always" "never"))
533	    (format *output* "~Cget-vert-scrollbar~%" *escape*)))
534
535    (defun horizontal-scrollbar (&optional (value nil specified))
536	(if specified
537	    (format *output* "~Cset-horiz-scrollbar ~S~%"
538		*escape* (if value "always" "never"))
539	    (format *output* "~Cget-horiz-scrollbar~%" *escape*)))
540
541    #|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
542    (defun create-buffer (name)
543	(format *output* "~Ccreate-buffer ~S~%" *escape* name))
544
545    (defun remove-buffer (name)
546	(format *output* "~Cremove-buffer ~S~%" *escape* name))
547
548    (defun buffer-name (&optional (value nil specified))
549	(if specified
550	    (format *output* "~Cset-buffer-name ~S~%" *escape* value)
551	    (format *output* "~Cget-buffer-name~%" *escape*)))
552
553    (defun buffer-filename (&optional (value nil specified))
554	(if specified
555	    (format *output* "~Cset-buffer-filename ~S~%"
556		*escape* (namestring value))
557	    (format *output* "~Cget-buffer-filename~%" *escape*)))
558
559    (defun current-buffer (&optional (value nil specified))
560	(if specified
561	    (format *output* "~Cset-current-buffer ~S~%" *escape* value)
562	    (format *output* "~Cget-current-buffer~%" *escape*)))
563
564    (defun other-buffer (&optional (value nil specified))
565	(if specified
566	    (format *output* "~Cset-other-buffer ~S~%" *escape* value)
567	    (format *output* "~Cget-other-buffer~%" *escape*)))
568    |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||#
569)
570