Update FSF's address.
[bpt/emacs.git] / lisp / progmodes / fortran.el
CommitLineData
e5167999
ER
1;;; fortran.el --- Fortran mode for GNU Emacs
2
b578f267 3;; Copyright (c) 1986, 1993, 1994, 1995 Free Software Foundation, Inc.
9750e079 4
e5167999
ER
5;; Author: Michael D. Prange <prange@erl.mit.edu>
6;; Maintainer: bug-fortran-mode@erl.mit.edu
4254fe58 7;; Version 1.30.6 (July 27, 1995)
fd7fa35a 8;; Keywords: languages
1a06eabd 9
e5167999
ER
10;; This file is part of GNU Emacs.
11
12;; GNU Emacs is free software; you can redistribute it and/or modify
13;; it under the terms of the GNU General Public License as published by
14;; the Free Software Foundation; either version 2, or (at your option)
15;; any later version.
16
17;; GNU Emacs is distributed in the hope that it will be useful,
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;; GNU General Public License for more details.
21
22;; You should have received a copy of the GNU General Public License
b578f267
EN
23;; along with GNU Emacs; see the file COPYING. If not, write to the
24;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
25;; Boston, MA 02111-1307, USA.
e5167999
ER
26
27;;; Commentary:
28
23029d77
JB
29;; Fortran mode has been upgraded and is now maintained by Stephen A. Wood
30;; (saw@cebaf.gov). It now will use either fixed format continuation line
eb8c3be9 31;; markers (character in 6th column), or tab format continuation line style
23029d77
JB
32;; (digit after a TAB character.) A auto-fill mode has been added to
33;; automatically wrap fortran lines that get too long.
34
35;; We acknowledge many contributions and valuable suggestions by
b8cbdf43
RS
36;; Lawrence R. Dodd, Ralf Fassel, Ralph Finch, Stephen Gildea,
37;; Dr. Anil Gokhale, Ulrich Mueller, Mark Neale, Eric Prestemon,
38;; Gary Sabot and Richard Stallman.
39
b578f267
EN
40;; This file may be used with GNU Emacs version 18.xx if the following
41;; variable and function substitutions are made.
42;; Replace:
43;; frame-width with screen-width
44;; auto-fill-function with auto-fill-hook
45;; comment-indent-function with comment-indent-hook
46;; (setq unread-command-events (list c)) with (setq unread-command-char c)
3dd63760 47
b578f267 48;; Bugs to bug-fortran-mode@erl.mit.edu
b8cbdf43 49
e5167999
ER
50;;; Code:
51
b578f267
EN
52(defconst fortran-mode-version "version 1.30.6")
53
3dd63760
JB
54;;;###autoload
55(defvar fortran-tab-mode-default nil
e80f2147
RS
56 "*Default tabbing/carriage control style for empty files in Fortran mode.
57A value of t specifies tab-digit style of continuation control.
58A value of nil specifies that continuation lines are marked
59with a character in column 6.")
60
e80f2147 61;; Buffer local, used to display mode line.
23029d77 62(defvar fortran-tab-mode-string nil
5a8d870b 63 "String to appear in mode line when TAB format mode is on.")
3dd63760
JB
64
65(defvar fortran-do-indent 3
b8cbdf43 66 "*Extra indentation applied to DO blocks.")
3dd63760
JB
67
68(defvar fortran-if-indent 3
b8cbdf43
RS
69 "*Extra indentation applied to IF blocks.")
70
71(defvar fortran-structure-indent 3
5a8d870b 72 "*Extra indentation applied to STRUCTURE, UNION, MAP and INTERFACE blocks.")
3dd63760
JB
73
74(defvar fortran-continuation-indent 5
b8cbdf43 75 "*Extra indentation applied to Fortran continuation lines.")
3dd63760
JB
76
77(defvar fortran-comment-indent-style 'fixed
78 "*nil forces comment lines not to be touched,
23029d77
JB
79'fixed makes fixed comment indentation to `fortran-comment-line-extra-indent'
80columns beyond `fortran-minimum-statement-indent-fixed' (for
81`indent-tabs-mode' of nil) or `fortran-minimum-statement-indent-tab' (for
82`indent-tabs-mode' of t), and 'relative indents to current
83Fortran indentation plus `fortran-comment-line-extra-indent'.")
3dd63760 84
23029d77 85(defvar fortran-comment-line-extra-indent 0
b8cbdf43 86 "*Amount of extra indentation for text within full-line comments.")
3dd63760
JB
87
88(defvar comment-line-start nil
89 "*Delimiter inserted to start new full-line comment.")
90
91(defvar comment-line-start-skip nil
92 "*Regexp to match the start of a full-line comment.")
93
23029d77
JB
94(defvar fortran-minimum-statement-indent-fixed 6
95 "*Minimum statement indentation for fixed format continuation style.")
96
97(defvar fortran-minimum-statement-indent-tab (max tab-width 6)
98 "*Minimum statement indentation for TAB format continuation style.")
3dd63760
JB
99
100;; Note that this is documented in the v18 manuals as being a string
101;; of length one rather than a single character.
102;; The code in this file accepts either format for compatibility.
103(defvar fortran-comment-indent-char " "
104 "*Single-character string inserted for Fortran comment indentation.
105Normally a space.")
106
107(defvar fortran-line-number-indent 1
108 "*Maximum indentation for Fortran line numbers.
1095 means right-justify them within their five-column field.")
110
111(defvar fortran-check-all-num-for-matching-do nil
b8cbdf43 112 "*Non-nil causes all numbered lines to be treated as possible DO loop ends.")
3dd63760
JB
113
114(defvar fortran-blink-matching-if nil
c5af0a18
RS
115 "*Non-nil causes \\[fortran-indent-line] on ENDIF statement to blink on matching IF.
116Also, from an ENDDO statement blink on matching DO [WHILE] statement.")
3dd63760
JB
117
118(defvar fortran-continuation-string "$"
b8cbdf43 119 "*Single-character string used for Fortran continuation lines.
3dd63760
JB
120In fixed format continuation style, this character is inserted in
121column 6 by \\[fortran-split-line] to begin a continuation line.
122Also, if \\[fortran-indent-line] finds this at the beginning of a line, it will
123convert the line into a continuation line of the appropriate style.
124Normally $.")
125
126(defvar fortran-comment-region "c$$$"
127 "*String inserted by \\[fortran-comment-region]\
128 at start of each line in region.")
129
130(defvar fortran-electric-line-number t
131 "*Non-nil causes line number digits to be moved to the correct column as\
132 typed.")
133
134(defvar fortran-startup-message t
135 "*Non-nil displays a startup message when Fortran mode is first called.")
136
23029d77
JB
137(defvar fortran-column-ruler-fixed
138 "0 4 6 10 20 30 40 5\
f022dd89
SM
139\0 60 70\n\
140\[ ]|{ | | | | | | | | \
141\| | | | |}\n"
23029d77 142 "*String displayed above current line by \\[fortran-column-ruler].
5a8d870b 143This variable used in fixed format mode.")
23029d77
JB
144
145(defvar fortran-column-ruler-tab
146 "0 810 20 30 40 5\
f022dd89
SM
147\0 60 70\n\
148\[ ]| { | | | | | | | | \
149\| | | | |}\n"
23029d77 150 "*String displayed above current line by \\[fortran-column-ruler].
5a8d870b 151This variable used in TAB format mode.")
3dd63760
JB
152
153(defconst bug-fortran-mode "bug-fortran-mode@erl.mit.edu"
154 "Address of mailing list for Fortran mode bugs.")
155
3dd63760
JB
156(defvar fortran-mode-syntax-table nil
157 "Syntax table in use in Fortran mode buffers.")
158
159(defvar fortran-analyze-depth 100
23029d77 160 "Number of lines to scan to determine whether to use fixed or TAB format\
3dd63760
JB
161 style.")
162
b8cbdf43 163(defvar fortran-break-before-delimiters t
4254fe58 164 "*Non-nil causes `fortran-fill' to break lines before delimiters.")
b8cbdf43 165
3dd63760
JB
166(if fortran-mode-syntax-table
167 ()
168 (setq fortran-mode-syntax-table (make-syntax-table))
169 (modify-syntax-entry ?\; "w" fortran-mode-syntax-table)
170 (modify-syntax-entry ?\r " " fortran-mode-syntax-table)
171 (modify-syntax-entry ?+ "." fortran-mode-syntax-table)
172 (modify-syntax-entry ?- "." fortran-mode-syntax-table)
173 (modify-syntax-entry ?= "." fortran-mode-syntax-table)
174 (modify-syntax-entry ?* "." fortran-mode-syntax-table)
175 (modify-syntax-entry ?/ "." fortran-mode-syntax-table)
176 (modify-syntax-entry ?\' "\"" fortran-mode-syntax-table)
177 (modify-syntax-entry ?\" "\"" fortran-mode-syntax-table)
178 (modify-syntax-entry ?\\ "/" fortran-mode-syntax-table)
179 (modify-syntax-entry ?. "w" fortran-mode-syntax-table)
b8cbdf43 180 (modify-syntax-entry ?_ "w" fortran-mode-syntax-table)
563f09b5 181 (modify-syntax-entry ?\! "<" fortran-mode-syntax-table)
3dd63760
JB
182 (modify-syntax-entry ?\n ">" fortran-mode-syntax-table))
183
563f09b5
SM
184;; Comments are real pain in Fortran because there is no way to represent the
185;; standard comment syntax in an Emacs syntax table (we can for VAX-style).
186;; Therefore an unmatched quote in a standard comment will throw fontification
f022dd89
SM
187;; off on the wrong track. So we do syntactic fontification with regexps.
188
189;; Regexps done by simon@gnu with help from Ulrik Dickow <dickow@nbi.dk> and
190;; probably others Si's forgotten about (sorry).
563f09b5 191
f408b027 192(defconst fortran-font-lock-keywords-1 nil
f3d4eb7b 193 "Subdued level highlighting for Fortran mode.")
563f09b5 194
f408b027
SM
195(defconst fortran-font-lock-keywords-2 nil
196 "Medium level highlighting for Fortran mode.")
197
198(defconst fortran-font-lock-keywords-3 nil
199 "Gaudy level highlighting for Fortran mode.")
200
201(let ((comment-chars "c!*")
202 (fortran-type-types
f022dd89
SM
203; (make-regexp
204; (let ((simple-types '("character" "byte" "integer" "logical"
205; "none" "real" "complex"
206; "double[ \t]*precision" "double[ \t]*complex"))
207; (structured-types '("structure" "union" "map"))
208; (other-types '("record" "dimension" "parameter" "common" "save"
209; "external" "intrinsic" "data" "equivalence")))
210; (append
211; (mapcar (lambda (x) (concat "implicit[ \t]*" x)) simple-types)
212; simple-types
213; (mapcar (lambda (x) (concat "end[ \t]*" x)) structured-types)
214; structured-types
215; other-types)))
216 (concat "byte\\|c\\(haracter\\|om\\(mon\\|plex\\)\\)\\|"
217 "d\\(ata\\|imension\\|ouble"
218 "[ \t]*\\(complex\\|precision\\)\\)\\|"
219 "e\\(nd[ \t]*\\(map\\|structure\\|union\\)\\|"
220 "quivalence\\|xternal\\)\\|"
221 "i\\(mplicit[ \t]*\\(byte\\|"
222 "c\\(haracter\\|omplex\\)\\|"
223 "double[ \t]*\\(complex\\|precision\\)\\|"
224 "integer\\|logical\\|none\\|real\\)\\|"
225 "nt\\(eger\\|rinsic\\)\\)\\|"
226 "logical\\|map\\|none\\|parameter\\|re\\(al\\|cord\\)\\|"
563f09b5 227 "s\\(ave\\|tructure\\)\\|union"))
f408b027 228 (fortran-keywords
563f09b5
SM
229; ("continue" "format" "end" "enddo" "if" "then" "else" "endif"
230; "elseif" "while" "inquire" "stop" "return" "include" "open"
231; "close" "read" "write" "format" "print")
232 (concat "c\\(lose\\|ontinue\\)\\|"
233 "e\\(lse\\(\\|if\\)\\|nd\\(\\|do\\|if\\)\\)\\|format\\|"
234 "i\\(f\\|n\\(clude\\|quire\\)\\)\\|open\\|print\\|"
235 "re\\(ad\\|turn\\)\\|stop\\|then\\|w\\(hile\\|rite\\)"))
f408b027
SM
236 (fortran-logicals
237; ("and" "or" "not" "lt" "le" "eq" "ge" "gt" "ne" "true" "false")
238 "and\\|eq\\|false\\|g[et]\\|l[et]\\|n\\(e\\|ot\\)\\|or\\|true"))
563f09b5 239
f408b027 240 (setq fortran-font-lock-keywords-1
f022dd89
SM
241 (list
242 ;;
f408b027
SM
243 ;; Fontify syntactically (assuming strings cannot be quoted or span lines).
244 (cons (concat "^[" comment-chars "].*") 'font-lock-comment-face)
245 '(fortran-match-!-comment . font-lock-comment-face)
246 (list (concat "^[^" comment-chars "\t\n]" (make-string 71 ?.) "\\(.*\\)")
247 '(1 font-lock-comment-face))
248 '("'[^'\n]*'?" . font-lock-string-face)
f022dd89 249 ;;
f408b027
SM
250 ;; Program, subroutine and function declarations, plus calls.
251 (list (concat "\\<\\(block[ \t]*data\\|call\\|entry\\|function\\|"
252 "program\\|subroutine\\)\\>[ \t]*\\(\\sw+\\)?")
253 '(1 font-lock-keyword-face)
254 '(2 font-lock-function-name-face nil t))))
255
256 (setq fortran-font-lock-keywords-2
257 (append fortran-font-lock-keywords-1
258 (list
259 ;;
260 ;; Fontify all type specifiers (must be first; see below).
261 (cons (concat "\\<\\(" fortran-type-types "\\)\\>") 'font-lock-type-face)
262 ;;
263 ;; Fontify all builtin keywords (except logical, do and goto; see below).
264 (concat "\\<\\(" fortran-keywords "\\)\\>")
265 ;;
266 ;; Fontify all builtin operators.
267 (concat "\\.\\(" fortran-logicals "\\)\\.")
268 ;;
269 ;; Fontify do/goto keywords and targets, and goto tags.
270 (list "\\<\\(do\\|go *to\\)\\>[ \t]*\\([0-9]+\\)?"
271 '(1 font-lock-keyword-face)
272 '(2 font-lock-reference-face nil t))
273 (cons "^ *\\([0-9]+\\)" 'font-lock-reference-face))))
274
275 (setq fortran-font-lock-keywords-3
276 (append
277 ;;
278 ;; The list `fortran-font-lock-keywords-1'.
279 fortran-font-lock-keywords-1
280 ;;
281 ;; Fontify all type specifiers plus their declared items.
282 (list
283 (list (concat "\\<\\(" fortran-type-types "\\)\\>[ \t(/]*\\(*\\)?")
284 ;; Fontify the type specifier.
285 '(1 font-lock-type-face)
286 ;; Fontify each declaration item (or just the /.../ block name).
287 '(font-lock-match-c++-style-declaration-item-and-skip-to-next
288 ;; Start after any *(...) expression.
289 (and (match-beginning 15) (forward-sexp 1))
290 ;; No need to clean up.
291 nil
292 ;; Fontify as a variable name, functions are fontified elsewhere.
293 (1 font-lock-variable-name-face nil t))))
294 ;;
295 ;; Things extra to `fortran-font-lock-keywords-3' (must be done first).
296 (list
297 ;;
298 ;; Fontify goto-like `err=label'/`end=label' in read/write statements.
299 '(", *\\(e\\(nd\\|rr\\)\\)\\> *\\(= *\\([0-9]+\\)\\)?"
300 (1 font-lock-keyword-face) (4 font-lock-reference-face nil t))
301 ;;
302 ;; Highlight standard continuation character and in a TAB-formatted line.
303 '("^ \\([^ 0]\\)" 1 font-lock-string-face)
304 '("^\t\\([1-9]\\)" 1 font-lock-string-face))
305 ;;
306 ;; The list `fortran-font-lock-keywords-2' less that for types (see above).
307 (cdr (nthcdr (length fortran-font-lock-keywords-1)
308 fortran-font-lock-keywords-2))))
309 )
f022dd89 310
f3d4eb7b
SM
311(defvar fortran-font-lock-keywords fortran-font-lock-keywords-1
312 "Default expressions to highlight in Fortran mode.")
563f09b5 313
f408b027 314
3dd63760 315(defvar fortran-mode-map ()
b8cbdf43 316 "Keymap used in Fortran mode.")
3dd63760
JB
317(if fortran-mode-map
318 ()
319 (setq fortran-mode-map (make-sparse-keymap))
320 (define-key fortran-mode-map ";" 'fortran-abbrev-start)
321 (define-key fortran-mode-map "\C-c;" 'fortran-comment-region)
322 (define-key fortran-mode-map "\e\C-a" 'beginning-of-fortran-subprogram)
323 (define-key fortran-mode-map "\e\C-e" 'end-of-fortran-subprogram)
324 (define-key fortran-mode-map "\e;" 'fortran-indent-comment)
325 (define-key fortran-mode-map "\e\C-h" 'mark-fortran-subprogram)
326 (define-key fortran-mode-map "\e\n" 'fortran-split-line)
aa4ed68c 327 (define-key fortran-mode-map "\n" 'fortran-indent-new-line)
3dd63760
JB
328 (define-key fortran-mode-map "\e\C-q" 'fortran-indent-subprogram)
329 (define-key fortran-mode-map "\C-c\C-w" 'fortran-window-create-momentarily)
330 (define-key fortran-mode-map "\C-c\C-r" 'fortran-column-ruler)
331 (define-key fortran-mode-map "\C-c\C-p" 'fortran-previous-statement)
332 (define-key fortran-mode-map "\C-c\C-n" 'fortran-next-statement)
333 (define-key fortran-mode-map "\t" 'fortran-indent-line)
334 (define-key fortran-mode-map "0" 'fortran-electric-line-number)
335 (define-key fortran-mode-map "1" 'fortran-electric-line-number)
336 (define-key fortran-mode-map "2" 'fortran-electric-line-number)
337 (define-key fortran-mode-map "3" 'fortran-electric-line-number)
338 (define-key fortran-mode-map "4" 'fortran-electric-line-number)
339 (define-key fortran-mode-map "5" 'fortran-electric-line-number)
340 (define-key fortran-mode-map "6" 'fortran-electric-line-number)
341 (define-key fortran-mode-map "7" 'fortran-electric-line-number)
342 (define-key fortran-mode-map "8" 'fortran-electric-line-number)
343 (define-key fortran-mode-map "9" 'fortran-electric-line-number))
344\f
345(defvar fortran-mode-abbrev-table nil)
346(if fortran-mode-abbrev-table
347 ()
348 (let ((ac abbrevs-changed))
349 (define-abbrev-table 'fortran-mode-abbrev-table ())
350 (define-abbrev fortran-mode-abbrev-table ";au" "automatic" nil)
351 (define-abbrev fortran-mode-abbrev-table ";b" "byte" nil)
b8cbdf43 352 (define-abbrev fortran-mode-abbrev-table ";bd" "block data" nil)
3dd63760
JB
353 (define-abbrev fortran-mode-abbrev-table ";ch" "character" nil)
354 (define-abbrev fortran-mode-abbrev-table ";cl" "close" nil)
355 (define-abbrev fortran-mode-abbrev-table ";c" "continue" nil)
356 (define-abbrev fortran-mode-abbrev-table ";cm" "common" nil)
357 (define-abbrev fortran-mode-abbrev-table ";cx" "complex" nil)
358 (define-abbrev fortran-mode-abbrev-table ";df" "define" nil)
359 (define-abbrev fortran-mode-abbrev-table ";di" "dimension" nil)
360 (define-abbrev fortran-mode-abbrev-table ";do" "double" nil)
361 (define-abbrev fortran-mode-abbrev-table ";dc" "double complex" nil)
362 (define-abbrev fortran-mode-abbrev-table ";dp" "double precision" nil)
363 (define-abbrev fortran-mode-abbrev-table ";dw" "do while" nil)
364 (define-abbrev fortran-mode-abbrev-table ";e" "else" nil)
365 (define-abbrev fortran-mode-abbrev-table ";ed" "enddo" nil)
366 (define-abbrev fortran-mode-abbrev-table ";el" "elseif" nil)
367 (define-abbrev fortran-mode-abbrev-table ";en" "endif" nil)
368 (define-abbrev fortran-mode-abbrev-table ";eq" "equivalence" nil)
b8cbdf43 369 (define-abbrev fortran-mode-abbrev-table ";ew" "endwhere" nil)
3dd63760
JB
370 (define-abbrev fortran-mode-abbrev-table ";ex" "external" nil)
371 (define-abbrev fortran-mode-abbrev-table ";ey" "entry" nil)
372 (define-abbrev fortran-mode-abbrev-table ";f" "format" nil)
373 (define-abbrev fortran-mode-abbrev-table ";fa" ".false." nil)
374 (define-abbrev fortran-mode-abbrev-table ";fu" "function" nil)
375 (define-abbrev fortran-mode-abbrev-table ";g" "goto" nil)
376 (define-abbrev fortran-mode-abbrev-table ";im" "implicit" nil)
377 (define-abbrev fortran-mode-abbrev-table ";ib" "implicit byte" nil)
378 (define-abbrev fortran-mode-abbrev-table ";ic" "implicit complex" nil)
379 (define-abbrev fortran-mode-abbrev-table ";ich" "implicit character" nil)
380 (define-abbrev fortran-mode-abbrev-table ";ii" "implicit integer" nil)
381 (define-abbrev fortran-mode-abbrev-table ";il" "implicit logical" nil)
382 (define-abbrev fortran-mode-abbrev-table ";ir" "implicit real" nil)
383 (define-abbrev fortran-mode-abbrev-table ";inc" "include" nil)
384 (define-abbrev fortran-mode-abbrev-table ";in" "integer" nil)
385 (define-abbrev fortran-mode-abbrev-table ";intr" "intrinsic" nil)
386 (define-abbrev fortran-mode-abbrev-table ";l" "logical" nil)
387 (define-abbrev fortran-mode-abbrev-table ";n" "namelist" nil)
388 (define-abbrev fortran-mode-abbrev-table ";o" "open" nil) ; was ;op
389 (define-abbrev fortran-mode-abbrev-table ";pa" "parameter" nil)
390 (define-abbrev fortran-mode-abbrev-table ";pr" "program" nil)
391 (define-abbrev fortran-mode-abbrev-table ";ps" "pause" nil)
392 (define-abbrev fortran-mode-abbrev-table ";p" "print" nil)
393 (define-abbrev fortran-mode-abbrev-table ";rc" "record" nil)
394 (define-abbrev fortran-mode-abbrev-table ";re" "real" nil)
395 (define-abbrev fortran-mode-abbrev-table ";r" "read" nil)
396 (define-abbrev fortran-mode-abbrev-table ";rt" "return" nil)
397 (define-abbrev fortran-mode-abbrev-table ";rw" "rewind" nil)
398 (define-abbrev fortran-mode-abbrev-table ";s" "stop" nil)
399 (define-abbrev fortran-mode-abbrev-table ";sa" "save" nil)
400 (define-abbrev fortran-mode-abbrev-table ";st" "structure" nil)
401 (define-abbrev fortran-mode-abbrev-table ";sc" "static" nil)
402 (define-abbrev fortran-mode-abbrev-table ";su" "subroutine" nil)
403 (define-abbrev fortran-mode-abbrev-table ";tr" ".true." nil)
404 (define-abbrev fortran-mode-abbrev-table ";ty" "type" nil)
405 (define-abbrev fortran-mode-abbrev-table ";vo" "volatile" nil)
406 (define-abbrev fortran-mode-abbrev-table ";w" "write" nil)
b8cbdf43 407 (define-abbrev fortran-mode-abbrev-table ";wh" "where" nil)
3dd63760
JB
408 (setq abbrevs-changed ac)))
409\f
410;;;###autoload
411(defun fortran-mode ()
b8cbdf43
RS
412 "Major mode for editing Fortran code.
413\\[fortran-indent-line] indents the current Fortran line correctly.
414DO statements must not share a common CONTINUE.
3dd63760 415
b8cbdf43 416Type ;? or ;\\[help-command] to display a list of built-in\
3dd63760
JB
417 abbrevs for Fortran keywords.
418
419Key definitions:
420\\{fortran-mode-map}
421
422Variables controlling indentation style and extra features:
423
424 comment-start
425 Normally nil in Fortran mode. If you want to use comments
426 starting with `!', set this to the string \"!\".
427 fortran-do-indent
428 Extra indentation within do blocks. (default 3)
429 fortran-if-indent
430 Extra indentation within if blocks. (default 3)
b8cbdf43 431 fortran-structure-indent
5a8d870b
RS
432 Extra indentation within structure, union, map and interface blocks.
433 (default 3)
3dd63760 434 fortran-continuation-indent
b8cbdf43 435 Extra indentation applied to continuation statements. (default 5)
23029d77 436 fortran-comment-line-extra-indent
b8cbdf43 437 Amount of extra indentation for text within full-line comments. (default 0)
3dd63760
JB
438 fortran-comment-indent-style
439 nil means don't change indentation of text in full-line comments,
23029d77
JB
440 fixed means indent that text at `fortran-comment-line-extra-indent' beyond
441 the value of `fortran-minimum-statement-indent-fixed' (for fixed
442 format continuation style) or `fortran-minimum-statement-indent-tab'
443 (for TAB format continuation style).
444 relative means indent at `fortran-comment-line-extra-indent' beyond the
3dd63760
JB
445 indentation for a line of code.
446 (default 'fixed)
447 fortran-comment-indent-char
b8cbdf43 448 Single-character string to be inserted instead of space for
3dd63760 449 full-line comment indentation. (default \" \")
23029d77
JB
450 fortran-minimum-statement-indent-fixed
451 Minimum indentation for Fortran statements in fixed format mode. (def.6)
452 fortran-minimum-statement-indent-tab
453 Minimum indentation for Fortran statements in TAB format mode. (default 9)
3dd63760
JB
454 fortran-line-number-indent
455 Maximum indentation for line numbers. A line number will get
456 less than this much indentation if necessary to avoid reaching
457 column 5. (default 1)
458 fortran-check-all-num-for-matching-do
b8cbdf43 459 Non-nil causes all numbered lines to be treated as possible \"continue\"
3dd63760
JB
460 statements. (default nil)
461 fortran-blink-matching-if
c5af0a18
RS
462 Non-nil causes \\[fortran-indent-line] on an ENDIF statement to blink on
463 matching IF. Also, from an ENDDO statement, blink on matching DO [WHILE]
464 statement. (default nil)
3dd63760
JB
465 fortran-continuation-string
466 Single-character string to be inserted in column 5 of a continuation
467 line. (default \"$\")
468 fortran-comment-region
469 String inserted by \\[fortran-comment-region] at start of each line in
470 region. (default \"c$$$\")
471 fortran-electric-line-number
472 Non-nil causes line number digits to be moved to the correct column
473 as typed. (default t)
b8cbdf43 474 fortran-break-before-delimiters
4254fe58 475 Non-nil causes `fortran-fill' breaks lines before delimiters.
b8cbdf43 476 (default t)
3dd63760
JB
477 fortran-startup-message
478 Set to nil to inhibit message first time Fortran mode is used.
479
b8cbdf43 480Turning on Fortran mode calls the value of the variable `fortran-mode-hook'
3dd63760
JB
481with no args, if that value is non-nil."
482 (interactive)
483 (kill-all-local-variables)
484 (if fortran-startup-message
b8cbdf43 485 (message "Emacs Fortran mode %s. Bugs to %s"
3dd63760
JB
486 fortran-mode-version bug-fortran-mode))
487 (setq fortran-startup-message nil)
488 (setq local-abbrev-table fortran-mode-abbrev-table)
489 (set-syntax-table fortran-mode-syntax-table)
f3d4eb7b 490 ;; Font Lock mode support.
f408b027
SM
491 (make-local-variable 'font-lock-defaults)
492 (setq font-lock-defaults '((fortran-font-lock-keywords
493 fortran-font-lock-keywords-1
494 fortran-font-lock-keywords-2
495 fortran-font-lock-keywords-3)
496 t t ((?/ . "$/"))))
b8cbdf43
RS
497 (make-local-variable 'fortran-break-before-delimiters)
498 (setq fortran-break-before-delimiters t)
3dd63760
JB
499 (make-local-variable 'indent-line-function)
500 (setq indent-line-function 'fortran-indent-line)
e41b2db1
ER
501 (make-local-variable 'comment-indent-function)
502 (setq comment-indent-function 'fortran-comment-hook)
3dd63760
JB
503 (make-local-variable 'comment-line-start-skip)
504 (setq comment-line-start-skip
b8cbdf43 505 "^[Cc*]\\(\\([^ \t\n]\\)\\2\\2*\\)?[ \t]*\\|^#.*")
3dd63760
JB
506 (make-local-variable 'comment-line-start)
507 (setq comment-line-start "c")
508 (make-local-variable 'comment-start-skip)
509 (setq comment-start-skip "![ \t]*")
510 (make-local-variable 'comment-start)
511 (setq comment-start nil)
512 (make-local-variable 'require-final-newline)
513 (setq require-final-newline t)
514 (make-local-variable 'abbrev-all-caps)
515 (setq abbrev-all-caps t)
516 (make-local-variable 'indent-tabs-mode)
517 (setq indent-tabs-mode nil)
23029d77 518;;;(setq abbrev-mode t) ; ?? (abbrev-mode 1) instead??
b8cbdf43 519 (setq fill-column 72) ; Already local?
3dd63760
JB
520 (use-local-map fortran-mode-map)
521 (setq mode-name "Fortran")
522 (setq major-mode 'fortran-mode)
23029d77
JB
523;;;(make-local-variable 'fortran-tab-mode)
524 (make-local-variable 'fortran-comment-line-extra-indent)
525 (make-local-variable 'fortran-minimum-statement-indent-fixed)
526 (make-local-variable 'fortran-minimum-statement-indent-tab)
527 (make-local-variable 'fortran-column-ruler-fixed)
528 (make-local-variable 'fortran-column-ruler-tab)
3dd63760 529 (make-local-variable 'fortran-tab-mode-string)
23029d77
JB
530 (setq fortran-tab-mode-string " TAB-format")
531 (setq indent-tabs-mode (fortran-analyze-file-format))
3dd63760
JB
532 (run-hooks 'fortran-mode-hook))
533\f
534(defun fortran-comment-hook ()
535 (save-excursion
536 (skip-chars-backward " \t")
537 (max (+ 1 (current-column))
538 comment-column)))
539
540(defun fortran-indent-comment ()
541 "Align or create comment on current line.
542Existing comments of all types are recognized and aligned.
543If the line has no comment, a side-by-side comment is inserted and aligned
544if the value of comment-start is not nil.
545Otherwise, a separate-line comment is inserted, on this line
546or on a new line inserted before this line if this line is not blank."
547 (interactive)
548 (beginning-of-line)
549 ;; Recognize existing comments of either kind.
550 (cond ((looking-at comment-line-start-skip)
551 (fortran-indent-line))
23029d77 552 ((fortran-find-comment-start-skip) ; catches any inline comment and
b8cbdf43
RS
553 ; leaves point after comment-start-skip
554 (if comment-start-skip
555 (progn (goto-char (match-beginning 0))
556 (if (not (= (current-column) (fortran-comment-hook)))
557 (progn (delete-horizontal-space)
558 (indent-to (fortran-comment-hook)))))
559 (end-of-line))) ; otherwise goto end of line or sth else?
3dd63760
JB
560 ;; No existing comment.
561 ;; If side-by-side comments are defined, insert one,
562 ;; unless line is now blank.
563 ((and comment-start (not (looking-at "^[ \t]*$")))
564 (end-of-line)
565 (delete-horizontal-space)
566 (indent-to (fortran-comment-hook))
567 (insert comment-start))
568 ;; Else insert separate-line comment, making a new line if nec.
569 (t
570 (if (looking-at "^[ \t]*$")
571 (delete-horizontal-space)
572 (beginning-of-line)
573 (insert "\n")
574 (forward-char -1))
575 (insert comment-line-start)
576 (insert-char (if (stringp fortran-comment-indent-char)
577 (aref fortran-comment-indent-char 0)
b8cbdf43 578 fortran-comment-indent-char)
3dd63760
JB
579 (- (calculate-fortran-indent) (current-column))))))
580
581(defun fortran-comment-region (beg-region end-region arg)
582 "Comments every line in the region.
583Puts fortran-comment-region at the beginning of every line in the region.
584BEG-REGION and END-REGION are args which specify the region boundaries.
585With non-nil ARG, uncomments the region."
586 (interactive "*r\nP")
587 (let ((end-region-mark (make-marker)) (save-point (point-marker)))
588 (set-marker end-region-mark end-region)
589 (goto-char beg-region)
590 (beginning-of-line)
591 (if (not arg) ;comment the region
592 (progn (insert fortran-comment-region)
593 (while (and (= (forward-line 1) 0)
594 (< (point) end-region-mark))
595 (insert fortran-comment-region)))
596 (let ((com (regexp-quote fortran-comment-region))) ;uncomment the region
597 (if (looking-at com)
598 (delete-region (point) (match-end 0)))
599 (while (and (= (forward-line 1) 0)
600 (< (point) end-region-mark))
601 (if (looking-at com)
602 (delete-region (point) (match-end 0))))))
603 (goto-char save-point)
604 (set-marker end-region-mark nil)
605 (set-marker save-point nil)))
606\f
607(defun fortran-abbrev-start ()
b8cbdf43 608 "Typing ;\\[help-command] or ;? lists all the Fortran abbrevs.
3dd63760
JB
609Any other key combination is executed normally."
610 (interactive)
611 (let (c)
612 (insert last-command-char)
d654e8ce
RS
613 (if (or (eq (setq c (read-event)) ??) ;insert char if not equal to `?'
614 (eq c help-char))
3dd63760 615 (fortran-abbrev-help)
dbc4e1c1 616 (setq unread-command-events (list c)))))
3dd63760
JB
617
618(defun fortran-abbrev-help ()
619 "List the currently defined abbrevs in Fortran mode."
620 (interactive)
621 (message "Listing abbrev table...")
e80f2147 622 (display-buffer (fortran-prepare-abbrev-list-buffer))
3dd63760
JB
623 (message "Listing abbrev table...done"))
624
e80f2147
RS
625(defun fortran-prepare-abbrev-list-buffer ()
626 (save-excursion
627 (set-buffer (get-buffer-create "*Abbrevs*"))
628 (erase-buffer)
4632a893 629 (insert-abbrev-table-description 'fortran-mode-abbrev-table t)
e80f2147
RS
630 (goto-char (point-min))
631 (set-buffer-modified-p nil)
632 (edit-abbrevs-mode))
633 (get-buffer-create "*Abbrevs*"))
634
3dd63760
JB
635(defun fortran-column-ruler ()
636 "Inserts a column ruler momentarily above current line, till next keystroke.
5a8d870b
RS
637The ruler is defined by the value of `fortran-column-ruler-fixed' when in fixed
638format mode, and `fortran-column-ruler-tab' when in TAB format mode.
3dd63760
JB
639The key typed is executed unless it is SPC."
640 (interactive)
641 (momentary-string-display
23029d77
JB
642 (if indent-tabs-mode
643 fortran-column-ruler-tab
644 fortran-column-ruler-fixed)
645 (save-excursion
646 (beginning-of-line)
647 (if (eq (window-start (selected-window))
648 (window-point (selected-window)))
649 (progn (forward-line) (point))
650 (point)))
3dd63760
JB
651 nil "Type SPC or any command to erase ruler."))
652
653(defun fortran-window-create ()
654 "Makes the window 72 columns wide.
fe668515 655See also `fortran-window-create-momentarily'."
3dd63760
JB
656 (interactive)
657 (condition-case error
658 (progn
659 (let ((window-min-width 2))
23029d77
JB
660 (if (< (window-width) (frame-width))
661 (enlarge-window-horizontally (- (frame-width)
3dd63760
JB
662 (window-width) 1)))
663 (split-window-horizontally 73)
664 (other-window 1)
665 (switch-to-buffer " fortran-window-extra" t)
666 (select-window (previous-window))))
b8cbdf43 667 (error (message "No room for Fortran window.")
3dd63760
JB
668 'error)))
669
670(defun fortran-window-create-momentarily (&optional arg)
671 "Momentarily makes the window 72 columns wide.
672Optional ARG non-nil and non-unity disables the momentary feature.
fe668515 673See also `fortran-window-create'."
3dd63760
JB
674 (interactive "p")
675 (if (or (not arg)
676 (= arg 1))
677 (save-window-excursion
678 (if (not (equal (fortran-window-create) 'error))
679 (progn (message "Type SPC to continue editing.")
d654e8ce 680 (let ((char (read-event)))
3dd63760 681 (or (equal char (string-to-char " "))
dbc4e1c1 682 (setq unread-command-events (list char)))))))
3dd63760
JB
683 (fortran-window-create)))
684
685(defun fortran-split-line ()
686 "Break line at point and insert continuation marker and alignment."
687 (interactive)
688 (delete-horizontal-space)
689 (if (save-excursion (beginning-of-line) (looking-at comment-line-start-skip))
690 (insert "\n" comment-line-start " ")
23029d77 691 (if indent-tabs-mode
3dd63760
JB
692 (progn
693 (insert "\n\t")
694 (insert-char (fortran-numerical-continuation-char) 1))
b8cbdf43
RS
695 (insert "\n " fortran-continuation-string)));Space after \n important
696 (fortran-indent-line)) ;when the cont string is C, c or *.
3dd63760
JB
697
698(defun fortran-numerical-continuation-char ()
b56eb7c9 699 "Return a digit for tab-digit style of continuation lines.
3dd63760
JB
700If, previous line is a tab-digit continuation line, returns that digit
701plus one. Otherwise return 1. Zero not allowed."
702 (save-excursion
703 (forward-line -1)
704 (if (looking-at "\t[1-9]")
705 (+ ?1 (% (- (char-after (+ (point) 1)) ?0) 9))
706 ?1)))
707
708(defun delete-horizontal-regexp (chars)
709 "Delete all characters in CHARS around point.
710CHARS is like the inside of a [...] in a regular expression
711except that ] is never special and \ quotes ^, - or \."
712 (interactive "*s")
713 (skip-chars-backward chars)
714 (delete-region (point) (progn (skip-chars-forward chars) (point))))
715
716(defun fortran-electric-line-number (arg)
717 "Self insert, but if part of a Fortran line number indent it automatically.
718Auto-indent does not happen if a numeric arg is used."
3dd63760
JB
719 (interactive "P")
720 (if (or arg (not fortran-electric-line-number))
721 (if arg
b8cbdf43 722 (self-insert-command (prefix-numeric-value arg))
3dd63760
JB
723 (self-insert-command 1))
724 (if (or (and (= 5 (current-column))
725 (save-excursion
726 (beginning-of-line)
727 (looking-at " ")));In col 5 with only spaces to left.
23029d77
JB
728 (and (= (if indent-tabs-mode
729 fortran-minimum-statement-indent-tab
730 fortran-minimum-statement-indent-fixed) (current-column))
3dd63760
JB
731 (save-excursion
732 (beginning-of-line)
733 (looking-at "\t"));In col 8 with a single tab to the left.
734 (not (or (eq last-command 'fortran-indent-line)
735 (eq last-command
aa4ed68c 736 'fortran-indent-new-line))))
3dd63760
JB
737 (save-excursion
738 (re-search-backward "[^ \t0-9]"
739 (save-excursion
740 (beginning-of-line)
741 (point))
742 t)) ;not a line number
743 (looking-at "[0-9]") ;within a line number
744 )
b8cbdf43 745 (self-insert-command (prefix-numeric-value arg))
3dd63760
JB
746 (skip-chars-backward " \t")
747 (insert last-command-char)
748 (fortran-indent-line))))
749\f
750(defun beginning-of-fortran-subprogram ()
b8cbdf43 751 "Moves point to the beginning of the current Fortran subprogram."
3dd63760
JB
752 (interactive)
753 (let ((case-fold-search t))
754 (beginning-of-line -1)
755 (re-search-backward "^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]" nil 'move)
756 (if (looking-at "^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]")
757 (forward-line 1))))
758
759(defun end-of-fortran-subprogram ()
b8cbdf43 760 "Moves point to the end of the current Fortran subprogram."
3dd63760
JB
761 (interactive)
762 (let ((case-fold-search t))
763 (beginning-of-line 2)
764 (re-search-forward "^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]" nil 'move)
765 (goto-char (match-beginning 0))
766 (forward-line 1)))
767
768(defun mark-fortran-subprogram ()
b8cbdf43 769 "Put mark at end of Fortran subprogram, point at beginning.
3dd63760
JB
770The marks are pushed."
771 (interactive)
772 (end-of-fortran-subprogram)
773 (push-mark (point))
774 (beginning-of-fortran-subprogram))
b8cbdf43 775
3dd63760 776(defun fortran-previous-statement ()
b8cbdf43
RS
777 "Moves point to beginning of the previous Fortran statement.
778Returns `first-statement' if that statement is the first
3dd63760
JB
779non-comment Fortran statement in the file, and nil otherwise."
780 (interactive)
781 (let (not-first-statement continue-test)
782 (beginning-of-line)
783 (setq continue-test
b8cbdf43
RS
784 (and
785 (not (looking-at comment-line-start-skip))
786 (or (looking-at
3dd63760 787 (concat "[ \t]*" (regexp-quote fortran-continuation-string)))
b8cbdf43
RS
788 (or (looking-at " [^ 0\n]")
789 (looking-at "\t[1-9]")))))
3dd63760
JB
790 (while (and (setq not-first-statement (= (forward-line -1) 0))
791 (or (looking-at comment-line-start-skip)
792 (looking-at "[ \t]*$")
793 (looking-at " [^ 0\n]")
794 (looking-at "\t[1-9]")
795 (looking-at (concat "[ \t]*" comment-start-skip)))))
796 (cond ((and continue-test
797 (not not-first-statement))
798 (message "Incomplete continuation statement."))
799 (continue-test
800 (fortran-previous-statement))
801 ((not not-first-statement)
802 'first-statement))))
803
804(defun fortran-next-statement ()
b8cbdf43 805 "Moves point to beginning of the next Fortran statement.
3dd63760
JB
806Returns `last-statement' if that statement is the last
807non-comment Fortran statement in the file, and nil otherwise."
808 (interactive)
809 (let (not-last-statement)
810 (beginning-of-line)
b8cbdf43
RS
811 (while (and (setq not-last-statement
812 (and (= (forward-line 1) 0)
813 (not (eobp))))
3dd63760
JB
814 (or (looking-at comment-line-start-skip)
815 (looking-at "[ \t]*$")
816 (looking-at " [^ 0\n]")
817 (looking-at "\t[1-9]")
818 (looking-at (concat "[ \t]*" comment-start-skip)))))
819 (if (not not-last-statement)
820 'last-statement)))
821\f
822(defun fortran-blink-matching-if ()
c5af0a18
RS
823 ;; From a Fortran ENDIF statement, blink the matching IF statement.
824 (let ((top-of-window (window-start)) matching-if
3dd63760
JB
825 (endif-point (point)) message)
826 (if (save-excursion (beginning-of-line)
827 (skip-chars-forward " \t0-9")
828 (looking-at "end[ \t]*if\\b"))
829 (progn
c5af0a18
RS
830 (if (not (setq matching-if (fortran-beginning-if)))
831 (setq message "No matching if.")
832 (if (< matching-if top-of-window)
833 (save-excursion
834 (goto-char matching-if)
835 (beginning-of-line)
836 (setq message
837 (concat "Matches "
838 (buffer-substring
839 (point) (progn (end-of-line) (point))))))))
3dd63760 840 (if message
b8cbdf43 841 (message "%s" message)
3dd63760
JB
842 (goto-char matching-if)
843 (sit-for 1)
844 (goto-char endif-point))))))
947388af
RS
845
846(defun fortran-blink-matching-do ()
847 ;; From a Fortran ENDDO statement, blink on the matching DO or DO WHILE
848 ;; statement. This is basically copied from fortran-blink-matching-if.
c5af0a18 849 (let ((top-of-window (window-start)) matching-do
947388af
RS
850 (enddo-point (point)) message)
851 (if (save-excursion (beginning-of-line)
852 (skip-chars-forward " \t0-9")
853 (looking-at "end[ \t]*do\\b"))
854 (progn
c5af0a18
RS
855 (if (not (setq matching-do (fortran-beginning-do)))
856 (setq message "No matching do.")
857 (if (< matching-do top-of-window)
858 (save-excursion
859 (goto-char matching-do)
860 (beginning-of-line)
861 (setq message
862 (concat "Matches "
863 (buffer-substring
864 (point) (progn (end-of-line) (point))))))))
947388af
RS
865 (if message
866 (message "%s" message)
867 (goto-char matching-do)
868 (sit-for 1)
869 (goto-char enddo-point))))))
c5af0a18
RS
870
871(defun fortran-mark-do ()
872 "Put mark at end of Fortran DO [WHILE]-ENDDO construct, point at beginning.
873The marks are pushed."
874 (interactive)
875 (let (enddo-point do-point)
876 (if (setq enddo-point (fortran-end-do))
877 (if (not (setq do-point (fortran-beginning-do)))
878 (message "No matching do.")
879 ;; Set mark, move point.
880 (goto-char enddo-point)
881 (push-mark)
882 (goto-char do-point)))))
883
884(defun fortran-end-do ()
885 ;; Search forward for first unmatched ENDDO. Return point or nil.
886 (if (save-excursion (beginning-of-line)
887 (skip-chars-forward " \t0-9")
888 (looking-at "end[ \t]*do\\b"))
889 ;; Sitting on one.
890 (match-beginning 0)
891 ;; Search for one.
892 (save-excursion
893 (let ((count 1))
894 (while (and (not (= count 0))
895 (not (eq (fortran-next-statement) 'last-statement))
896 ;; Keep local to subprogram
897 (not (looking-at "^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]")))
898
899 (skip-chars-forward " \t0-9")
900 (cond ((looking-at "end[ \t]*do\\b")
901 (setq count (- count 1)))
902 ((looking-at "do[ \t]+[^0-9]")
903 (setq count (+ count 1)))))
904 (and (= count 0)
905 ;; All pairs accounted for.
906 (point))))))
907
908(defun fortran-beginning-do ()
909 ;; Search backwards for first unmatched DO [WHILE]. Return point or nil.
910 (if (save-excursion (beginning-of-line)
911 (skip-chars-forward " \t0-9")
912 (looking-at "do[ \t]+"))
913 ;; Sitting on one.
914 (match-beginning 0)
915 ;; Search for one.
916 (save-excursion
917 (let ((count 1))
918 (while (and (not (= count 0))
919 (not (eq (fortran-previous-statement) 'first-statement))
920 ;; Keep local to subprogram
921 (not (looking-at "^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]")))
922
923 (skip-chars-forward " \t0-9")
924 (cond ((looking-at "do[ \t]+[^0-9]")
925 (setq count (- count 1)))
926 ((looking-at "end[ \t]*do\\b")
927 (setq count (+ count 1)))))
928
929 (and (= count 0)
930 ;; All pairs accounted for.
931 (point))))))
932
933(defun fortran-mark-if ()
934 "Put mark at end of Fortran IF-ENDIF construct, point at beginning.
935The marks are pushed."
936 (interactive)
937 (let (endif-point if-point)
938 (if (setq endif-point (fortran-end-if))
939 (if (not (setq if-point (fortran-beginning-if)))
940 (message "No matching if.")
941 ;; Set mark, move point.
942 (goto-char endif-point)
943 (push-mark)
944 (goto-char if-point)))))
945
946(defun fortran-end-if ()
947 ;; Search forwards for first unmatched ENDIF. Return point or nil.
948 (if (save-excursion (beginning-of-line)
949 (skip-chars-forward " \t0-9")
950 (looking-at "end[ \t]*if\\b"))
951 ;; Sitting on one.
952 (match-beginning 0)
953 ;; Search for one. The point has been already been moved to first
954 ;; letter on line but this should not cause troubles.
955 (save-excursion
956 (let ((count 1))
957 (while (and (not (= count 0))
958 (not (eq (fortran-next-statement) 'last-statement))
959 ;; Keep local to subprogram.
960 (not (looking-at
961 "^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]")))
962
963 (skip-chars-forward " \t0-9")
964 (cond ((looking-at "end[ \t]*if\\b")
965 (setq count (- count 1)))
966
967 ((looking-at "if[ \t]*(")
968 (save-excursion
969 (if (or
970 (looking-at ".*)[ \t]*then\\b[ \t]*[^ \t(=a-z0-9]")
971 (let (then-test) ; Multi-line if-then.
972 (while
973 (and (= (forward-line 1) 0)
974 ;; Search forward for then.
975 (or (looking-at " [^ 0\n]")
976 (looking-at "\t[1-9]"))
977 (not
978 (setq then-test
979 (looking-at
980 ".*then\\b[ \t]*[^ \t(=a-z0-9]")))))
981 then-test))
982 (setq count (+ count 1)))))))
983
984 (and (= count 0)
985 ;; All pairs accounted for.
986 (point))))))
987
988(defun fortran-beginning-if ()
989 ;; Search backwards for first unmatched IF-THEN. Return point or nil.
990 (if (save-excursion
991 ;; May be sitting on multi-line if-then statement, first move to
992 ;; beginning of current statement. Note: `fortran-previous-statement'
993 ;; moves to previous statement *unless* current statement is first
994 ;; one. Only move forward if not first-statement.
995 (if (not (eq (fortran-previous-statement) 'first-statement))
996 (fortran-next-statement))
997 (skip-chars-forward " \t0-9")
998 (and
999 (looking-at "if[ \t]*(")
1000 (save-match-data
1001 (or (looking-at ".*)[ \t]*then\\b[ \t]*[^ \t(=a-z0-9]")
1002 ;; Multi-line if-then.
1003 (let (then-test)
1004 (while
1005 (and (= (forward-line 1) 0)
1006 ;; Search forward for then.
1007 (or (looking-at " [^ 0\n]")
1008 (looking-at "\t[1-9]"))
1009 (not
1010 (setq then-test
1011 (looking-at
1012 ".*then\\b[ \t]*[^ \t(=a-z0-9]")))))
1013 then-test)))))
1014 ;; Sitting on one.
1015 (match-beginning 0)
1016 ;; Search for one.
1017 (save-excursion
1018 (let ((count 1))
1019 (while (and (not (= count 0))
1020 (not (eq (fortran-previous-statement) 'first-statement))
1021 ;; Keep local to subprogram.
1022 (not (looking-at
1023 "^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]")))
1024
1025 (skip-chars-forward " \t0-9")
1026 (cond ((looking-at "if[ \t]*(")
1027 (save-excursion
1028 (if (or
1029 (looking-at ".*)[ \t]*then\\b[ \t]*[^ \t(=a-z0-9]")
1030 (let (then-test) ; Multi-line if-then.
1031 (while
1032 (and (= (forward-line 1) 0)
1033 ;; Search forward for then.
1034 (or (looking-at " [^ 0\n]")
1035 (looking-at "\t[1-9]"))
1036 (not
1037 (setq then-test
1038 (looking-at
1039 ".*then\\b[ \t]*[^ \t(=a-z0-9]")))))
1040 then-test))
1041 (setq count (- count 1)))))
1042 ((looking-at "end[ \t]*if\\b")
1043 (setq count (+ count 1)))))
1044
1045 (and (= count 0)
1046 ;; All pairs accounted for.
1047 (point))))))
3dd63760
JB
1048\f
1049(defun fortran-indent-line ()
b8cbdf43 1050 "Indents current Fortran line based on its contents and on previous lines."
3dd63760
JB
1051 (interactive)
1052 (let ((cfi (calculate-fortran-indent)))
1053 (save-excursion
1054 (beginning-of-line)
1055 (if (or (not (= cfi (fortran-current-line-indentation)))
1056 (and (re-search-forward "^[ \t]*[0-9]+" (+ (point) 4) t)
1057 (not (fortran-line-number-indented-correctly-p))))
1058 (fortran-indent-to-column cfi)
1059 (beginning-of-line)
1060 (if (and (not (looking-at comment-line-start-skip))
23029d77 1061 (fortran-find-comment-start-skip))
3dd63760
JB
1062 (fortran-indent-comment))))
1063 ;; Never leave point in left margin.
1064 (if (< (current-column) cfi)
1065 (move-to-column cfi))
23029d77 1066 (if (and auto-fill-function
b8cbdf43
RS
1067 (> (save-excursion (end-of-line) (current-column)) fill-column))
1068 (save-excursion
1069 (end-of-line)
4254fe58 1070 (fortran-fill)))
3dd63760 1071 (if fortran-blink-matching-if
947388af
RS
1072 (progn
1073 (fortran-blink-matching-if)
1074 (fortran-blink-matching-do)))))
3dd63760 1075
aa4ed68c 1076(defun fortran-indent-new-line ()
b8cbdf43
RS
1077 "Reindent the current Fortran line, insert a newline and indent the newline.
1078An abbrev before point is expanded if `abbrev-mode' is non-nil."
3dd63760
JB
1079 (interactive)
1080 (if abbrev-mode (expand-abbrev))
1081 (save-excursion
1082 (beginning-of-line)
1083 (skip-chars-forward " \t")
1084 (if (or (looking-at "[0-9]") ;Reindent only where it is most
1085 (looking-at "end") ;likely to be necessary
1086 (looking-at "else")
1087 (looking-at (regexp-quote fortran-continuation-string)))
1088 (fortran-indent-line)))
b8cbdf43 1089 (newline)
3dd63760 1090 (fortran-indent-line))
b8cbdf43 1091
3dd63760
JB
1092(defun fortran-indent-subprogram ()
1093 "Properly indents the Fortran subprogram which contains point."
1094 (interactive)
1095 (save-excursion
1096 (mark-fortran-subprogram)
1097 (message "Indenting subprogram...")
1098 (indent-region (point) (mark) nil))
1099 (message "Indenting subprogram...done."))
1100
1101(defun calculate-fortran-indent ()
b8cbdf43 1102 "Calculates the Fortran indent column based on previous lines."
3dd63760
JB
1103 (let (icol first-statement (case-fold-search t)
1104 (fortran-minimum-statement-indent
23029d77
JB
1105 (if indent-tabs-mode
1106 fortran-minimum-statement-indent-tab
1107 fortran-minimum-statement-indent-fixed)))
3dd63760
JB
1108 (save-excursion
1109 (setq first-statement (fortran-previous-statement))
1110 (if first-statement
1111 (setq icol fortran-minimum-statement-indent)
1112 (progn
1113 (if (= (point) (point-min))
1114 (setq icol fortran-minimum-statement-indent)
1115 (setq icol (fortran-current-line-indentation)))
1116 (skip-chars-forward " \t0-9")
1117 (cond ((looking-at "if[ \t]*(")
b8cbdf43 1118 (if (or (looking-at ".*)[ \t]*then\\b[ \t]*[^ \t_$(=a-z0-9]")
3dd63760
JB
1119 (let (then-test) ;multi-line if-then
1120 (while (and (= (forward-line 1) 0)
b8cbdf43 1121 ;;search forward for then
3dd63760
JB
1122 (or (looking-at " [^ 0\n]")
1123 (looking-at "\t[1-9]"))
1124 (not (setq then-test (looking-at
b8cbdf43
RS
1125 ".*then\\b[ \t]\
1126*[^ \t_$(=a-z0-9]")))))
3dd63760
JB
1127 then-test))
1128 (setq icol (+ icol fortran-if-indent))))
1129 ((looking-at "\\(else\\|elseif\\)\\b")
1130 (setq icol (+ icol fortran-if-indent)))
5a8d870b
RS
1131 ((looking-at "select[ \t]*case[ \t](.*)\\b")
1132 (setq icol (+ icol fortran-if-indent)))
1133 ((looking-at "case[ \t]*(.*)[ \t]*\n")
1134 (setq icol (+ icol fortran-if-indent)))
1135 ((looking-at "case[ \t]*default\\b")
1136 (setq icol (+ icol fortran-if-indent)))
b8cbdf43
RS
1137 ((looking-at "\\(otherwise\\|else[ \t]*where\\)\\b")
1138 (setq icol (+ icol fortran-if-indent)))
f93f92f1 1139 ((looking-at "where[ \t]*(.*)[ \t]*\n")
b8cbdf43 1140 (setq icol (+ icol fortran-if-indent)))
3dd63760
JB
1141 ((looking-at "do\\b")
1142 (setq icol (+ icol fortran-do-indent)))
b8cbdf43 1143 ((looking-at
5a8d870b 1144 "\\(structure\\|union\\|map\\|interface\\)\\b[ \t]*[^ \t=(a-z]")
b8cbdf43 1145 (setq icol (+ icol fortran-structure-indent)))
3dd63760 1146 ((looking-at "end\\b[ \t]*[^ \t=(a-z]")
b8cbdf43 1147 ;; Previous END resets indent to minimum
3dd63760
JB
1148 (setq icol fortran-minimum-statement-indent))))))
1149 (save-excursion
1150 (beginning-of-line)
1151 (cond ((looking-at "[ \t]*$"))
1152 ((looking-at comment-line-start-skip)
3dd63760 1153 (cond ((eq fortran-comment-indent-style 'relative)
23029d77 1154 (setq icol (+ icol fortran-comment-line-extra-indent)))
3dd63760 1155 ((eq fortran-comment-indent-style 'fixed)
b8cbdf43 1156 (setq icol (+ fortran-minimum-statement-indent
23029d77 1157 fortran-comment-line-extra-indent))))
b8cbdf43 1158 (setq fortran-minimum-statement-indent 0))
3dd63760 1159 ((or (looking-at (concat "[ \t]*"
b8cbdf43
RS
1160 (regexp-quote
1161 fortran-continuation-string)))
3dd63760
JB
1162 (looking-at " [^ 0\n]")
1163 (looking-at "\t[1-9]"))
1164 (setq icol (+ icol fortran-continuation-indent)))
b56eb7c9
RS
1165 ((looking-at "[ \t]*#") ; Check for cpp directive.
1166 (setq fortran-minimum-statement-indent 0 icol 0))
3dd63760
JB
1167 (first-statement)
1168 ((and fortran-check-all-num-for-matching-do
1169 (looking-at "[ \t]*[0-9]+")
1170 (fortran-check-for-matching-do))
1171 (setq icol (- icol fortran-do-indent)))
1172 (t
1173 (skip-chars-forward " \t0-9")
1174 (cond ((looking-at "end[ \t]*if\\b")
1175 (setq icol (- icol fortran-if-indent)))
1176 ((looking-at "\\(else\\|elseif\\)\\b")
1177 (setq icol (- icol fortran-if-indent)))
5a8d870b
RS
1178 ((looking-at "case[ \t]*(.*)[ \t]*\n")
1179 (setq icol (- icol fortran-if-indent)))
1180 ((looking-at "case[ \t]*default\\b")
1181 (setq icol (- icol fortran-if-indent)))
b8cbdf43
RS
1182 ((looking-at "\\(otherwise\\|else[ \t]*where\\)\\b")
1183 (setq icol (- icol fortran-if-indent)))
1184 ((looking-at "end[ \t]*where\\b")
1185 (setq icol (- icol fortran-if-indent)))
3dd63760
JB
1186 ((and (looking-at "continue\\b")
1187 (fortran-check-for-matching-do))
1188 (setq icol (- icol fortran-do-indent)))
1189 ((looking-at "end[ \t]*do\\b")
1190 (setq icol (- icol fortran-do-indent)))
b8cbdf43
RS
1191 ((looking-at
1192 "end[ \t]*\
5a8d870b 1193\\(structure\\|union\\|map\\|interface\\)\\b[ \t]*[^ \t=(a-z]")
b8cbdf43 1194 (setq icol (- icol fortran-structure-indent)))
5a8d870b
RS
1195 ((looking-at
1196 "end[ \t]*select\\b[ \t]*[^ \t=(a-z]")
1197 (setq icol (- icol fortran-if-indent)))
3dd63760
JB
1198 ((and (looking-at "end\\b[ \t]*[^ \t=(a-z]")
1199 (not (= icol fortran-minimum-statement-indent)))
1200 (message "Warning: `end' not in column %d. Probably\
1201 an unclosed block." fortran-minimum-statement-indent))))))
1202 (max fortran-minimum-statement-indent icol)))
1203\f
1204(defun fortran-current-line-indentation ()
1205 "Indentation of current line, ignoring Fortran line number or continuation.
1206This is the column position of the first non-whitespace character
1207aside from the line number and/or column 5/8 line-continuation character.
1208For comment lines, returns indentation of the first
1209non-indentation text within the comment."
1210 (save-excursion
1211 (beginning-of-line)
1212 (cond ((looking-at comment-line-start-skip)
1213 (goto-char (match-end 0))
1214 (skip-chars-forward
b8cbdf43
RS
1215 (if (stringp fortran-comment-indent-char)
1216 fortran-comment-indent-char
1217 (char-to-string fortran-comment-indent-char))))
3dd63760 1218 ((or (looking-at " [^ 0\n]")
b8cbdf43 1219 (looking-at "\t[1-9]"))
3dd63760
JB
1220 (goto-char (match-end 0)))
1221 (t
1222 ;; Move past line number.
b8cbdf43
RS
1223 (skip-chars-forward "[ \t0-9]");From Uli
1224 ))
3dd63760
JB
1225 ;; Move past whitespace.
1226 (skip-chars-forward " \t")
1227 (current-column)))
1228
1229(defun fortran-indent-to-column (col)
1230 "Indents current line with spaces to column COL.
1231notes: 1) A non-zero/non-blank character in column 5 indicates a continuation
1232 line, and this continuation character is retained on indentation;
b8cbdf43
RS
1233 2) If `fortran-continuation-string' is the first non-whitespace
1234 character, this is a continuation line;
3dd63760
JB
1235 3) A non-continuation line which has a number as the first
1236 non-whitespace character is a numbered line.
b8cbdf43 1237 4) A TAB followed by a digit indicates a continuation line."
3dd63760
JB
1238 (save-excursion
1239 (beginning-of-line)
1240 (if (looking-at comment-line-start-skip)
1241 (if fortran-comment-indent-style
1242 (let ((char (if (stringp fortran-comment-indent-char)
1243 (aref fortran-comment-indent-char 0)
b8cbdf43 1244 fortran-comment-indent-char)))
3dd63760
JB
1245 (goto-char (match-end 0))
1246 (delete-horizontal-regexp (concat " \t" (char-to-string char)))
1247 (insert-char char (- col (current-column)))))
1248 (if (looking-at "\t[1-9]")
23029d77 1249 (if indent-tabs-mode
3dd63760
JB
1250 (goto-char (match-end 0))
1251 (delete-char 2)
1252 (insert " ")
1253 (insert fortran-continuation-string))
1254 (if (looking-at " [^ 0\n]")
23029d77 1255 (if indent-tabs-mode
3dd63760
JB
1256 (progn (delete-char 6)
1257 (insert "\t")
1258 (insert-char (fortran-numerical-continuation-char) 1))
1259 (forward-char 6))
1260 (delete-horizontal-space)
b8cbdf43
RS
1261 ;; Put line number in columns 0-4
1262 ;; or put continuation character in column 5.
3dd63760
JB
1263 (cond ((eobp))
1264 ((looking-at (regexp-quote fortran-continuation-string))
23029d77 1265 (if indent-tabs-mode
3dd63760 1266 (progn
23029d77
JB
1267 (indent-to
1268 (if indent-tabs-mode
1269 fortran-minimum-statement-indent-tab
1270 fortran-minimum-statement-indent-fixed))
3dd63760
JB
1271 (delete-char 1)
1272 (insert-char (fortran-numerical-continuation-char) 1))
b8cbdf43
RS
1273 (indent-to 5)
1274 (forward-char 1)))
3dd63760
JB
1275 ((looking-at "[0-9]+")
1276 (let ((extra-space (- 5 (- (match-end 0) (point)))))
1277 (if (< extra-space 0)
1278 (message "Warning: line number exceeds 5-digit limit.")
1279 (indent-to (min fortran-line-number-indent extra-space))))
1280 (skip-chars-forward "0-9")))))
1281 ;; Point is now after any continuation character or line number.
1282 ;; Put body of statement where specified.
1283 (delete-horizontal-space)
1284 (indent-to col)
1285 ;; Indent any comment following code on the same line.
1286 (if (and comment-start-skip
23029d77 1287 (fortran-find-comment-start-skip))
3dd63760
JB
1288 (progn (goto-char (match-beginning 0))
1289 (if (not (= (current-column) (fortran-comment-hook)))
1290 (progn (delete-horizontal-space)
1291 (indent-to (fortran-comment-hook)))))))))
1292
1293(defun fortran-line-number-indented-correctly-p ()
1294 "Return t if current line's line number is correctly indented.
1295Do not call if there is no line number."
1296 (save-excursion
1297 (beginning-of-line)
1298 (skip-chars-forward " \t")
1299 (and (<= (current-column) fortran-line-number-indent)
1300 (or (= (current-column) fortran-line-number-indent)
1301 (progn (skip-chars-forward "0-9")
1302 (= (current-column) 5))))))
1303
1304(defun fortran-check-for-matching-do ()
b8cbdf43 1305 "When called from a numbered statement, returns t if matching DO is found.
3dd63760
JB
1306Otherwise return a nil."
1307 (let (charnum
1308 (case-fold-search t))
1309 (save-excursion
1310 (beginning-of-line)
1311 (if (looking-at "[ \t]*[0-9]+")
1312 (progn
1313 (skip-chars-forward " \t")
1314 (skip-chars-forward "0") ;skip past leading zeros
1315 (setq charnum (buffer-substring (point)
1316 (progn (skip-chars-forward "0-9")
1317 (point))))
1318 (beginning-of-line)
1319 (and (re-search-backward
f022dd89
SM
1320 (concat "\\(^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]\\)\\|"
1321 "\\(^[ \t0-9]*do[ \t]*0*" charnum "\\b\\)\\|"
1322 "\\(^[ \t]*0*" charnum "\\b\\)")
3dd63760
JB
1323 nil t)
1324 (looking-at (concat "^[ \t0-9]*do[ \t]*0*" charnum))))))))
1325
23029d77 1326(defun fortran-find-comment-start-skip ()
b8cbdf43
RS
1327 "Move to past `comment-start-skip' found on current line.
1328Return t if `comment-start-skip' found, nil if not."
1329;;; In order to move point only if comment-start-skip is found,
1330;;; this one uses a lot of save-excursions. Note that re-search-forward
1331;;; moves point even if comment-start-skip is inside a string-constant.
1332;;; Some code expects certain values for match-beginning and end
1333 (interactive)
f022dd89
SM
1334 (if (save-excursion
1335 (re-search-forward comment-start-skip
1336 (save-excursion (end-of-line) (point)) t))
1337 (let ((save-match-beginning (match-beginning 0))
1338 (save-match-end (match-end 0)))
1339 (if (fortran-is-in-string-p (match-beginning 0))
1340 (save-excursion
1341 (goto-char save-match-end)
1342 (fortran-find-comment-start-skip)) ; recurse for rest of line
1343 (goto-char save-match-beginning)
b8cbdf43 1344 (re-search-forward comment-start-skip
f022dd89
SM
1345 (save-excursion (end-of-line) (point)) t)
1346 (goto-char (match-end 0))
1347 t))
1348 nil))
1349
1350;;;From: simon@gnu (Simon Marshall)
1351;;; Find the next ! not in a string.
1352(defun fortran-match-!-comment (limit)
1353 (let (found)
1354 (while (and (setq found (search-forward "!" limit t))
1355 (fortran-is-in-string-p (point))))
1356 (if (not found)
1357 nil
1358 ;; Cheaper than `looking-at' "!.*".
1359 (store-match-data
1360 (list (1- (point)) (progn (end-of-line) (min (point) limit))))
1361 t)))
1362
1363;; The above function is about 10% faster than the below...
1364;;(defun fortran-match-!-comment (limit)
1365;; (let (found)
1366;; (while (and (setq found (re-search-forward "!.*" limit t))
1367;; (fortran-is-in-string-p (match-beginning 0))))
1368;; found))
b8cbdf43 1369
b56eb7c9
RS
1370;;;From: ralf@up3aud1.gwdg.de (Ralf Fassel)
1371;;; Test if TAB format continuation lines work.
1372(defun fortran-is-in-string-p (where)
1373 "Return non-nil if POS (a buffer position) is inside a Fortran string,
1374nil else."
1375 (save-excursion
1376 (goto-char where)
1377 (cond
1378 ((bolp) nil) ; bol is never inside a string
1379 ((save-excursion ; comment lines too
1380 (beginning-of-line)(looking-at comment-line-start-skip)) nil)
1381 (t (let (;; ok, serious now. Init some local vars:
1382 (parse-state '(0 nil nil nil nil nil 0))
1383 (quoted-comment-start (if comment-start
1384 (regexp-quote comment-start)))
1385 (not-done t)
1386 parse-limit
1387 end-of-line
1388 )
1389 ;; move to start of current statement
1390 (fortran-next-statement)
1391 (fortran-previous-statement)
1392 ;; now parse up to WHERE
1393 (while not-done
1394 (if (or ;; skip to next line if:
1395 ;; - comment line?
1396 (looking-at comment-line-start-skip)
1397 ;; - at end of line?
1398 (eolp)
1399 ;; - not in a string and after comment-start?
1400 (and (not (nth 3 parse-state))
1401 comment-start
1402 (equal comment-start
1403 (char-to-string (preceding-char)))))
1404 ;; get around a bug in forward-line in versions <= 18.57
1405 (if (or (> (forward-line 1) 0) (eobp))
1406 (setq not-done nil))
1407 ;; else:
1408 ;; if we are at beginning of code line, skip any
1409 ;; whitespace, labels and tab continuation markers.
1410 (if (bolp) (skip-chars-forward " \t0-9"))
1411 ;; if we are in column <= 5 now, check for continuation char
1412 (cond ((= 5 (current-column)) (forward-char 1))
1413 ((and (< (current-column) 5)
1414 (equal fortran-continuation-string
1415 (char-to-string (following-char)))
1416 (forward-char 1))))
1417 ;; find out parse-limit from here
1418 (setq end-of-line (save-excursion (end-of-line)(point)))
1419 (setq parse-limit (min where end-of-line))
1420 ;; parse max up to comment-start, if non-nil and in current line
1421 (if comment-start
1422 (save-excursion
1423 (if (re-search-forward quoted-comment-start end-of-line t)
1424 (setq parse-limit (min (point) parse-limit)))))
1425 ;; now parse if still in limits
1426 (if (< (point) where)
1427 (setq parse-state (parse-partial-sexp
1428 (point) parse-limit nil nil parse-state))
1429 (setq not-done nil))
1430 ))
1431 ;; result is
1432 (nth 3 parse-state))))))
b8cbdf43
RS
1433
1434(defun fortran-auto-fill-mode (arg)
1435 "Toggle fortran-auto-fill mode.
1436With ARG, turn `fortran-auto-fill' mode on iff ARG is positive.
1437In `fortran-auto-fill' mode, inserting a space at a column beyond `fill-column'
1438automatically breaks the line at a previous space."
1439 (interactive "P")
23029d77 1440 (prog1 (setq auto-fill-function
b8cbdf43 1441 (if (if (null arg)
23029d77 1442 (not auto-fill-function)
b8cbdf43 1443 (> (prefix-numeric-value arg) 0))
4254fe58 1444 'fortran-do-auto-fill
b8cbdf43 1445 nil))
a716ac73 1446 (force-mode-line-update)))
b8cbdf43
RS
1447
1448(defun fortran-do-auto-fill ()
4254fe58
RS
1449 (if (> (current-column) fill-column)
1450 (fortran-indent-line)))
1451
1452(defun fortran-fill ()
b8cbdf43
RS
1453 (interactive)
1454 (let* ((opoint (point))
1455 (bol (save-excursion (beginning-of-line) (point)))
1456 (eol (save-excursion (end-of-line) (point)))
1457 (bos (min eol (+ bol (fortran-current-line-indentation))))
1458 (quote
1459 (save-excursion
1460 (goto-char bol)
1461 (if (looking-at comment-line-start-skip)
1462 nil ; OK to break quotes on comment lines.
1463 (move-to-column fill-column)
23029d77 1464 (cond ((fortran-is-in-string-p (point))
b8cbdf43
RS
1465 (save-excursion (re-search-backward "[^']'[^']" bol t)
1466 (if fortran-break-before-delimiters
1467 (point)
1468 (1+ (point)))))
1469 (t nil)))))
1470 ;;
1471 ;; decide where to split the line. If a position for a quoted
1472 ;; string was found above then use that, else break the line
1473 ;; before the last delimiter.
eb8c3be9 1474 ;; Delimiters are whitespace, commas, and operators.
b8cbdf43
RS
1475 ;; Will break before a pair of *'s.
1476 ;;
1477 (fill-point
1478 (or quote
1479 (save-excursion
1480 (move-to-column (1+ fill-column))
1481 (skip-chars-backward "^ \t\n,'+-/*=)"
1482;;; (if fortran-break-before-delimiters
1483;;; "^ \t\n,'+-/*=" "^ \t\n,'+-/*=)")
1484 )
1485 (if (<= (point) (1+ bos))
1486 (progn
1487 (move-to-column (1+ fill-column))
b56eb7c9 1488;;;what is this doing???
b8cbdf43
RS
1489 (if (not (re-search-forward "[\t\n,'+-/*)=]" eol t))
1490 (goto-char bol))))
1491 (if (bolp)
1492 (re-search-forward "[ \t]" opoint t)
1493 (forward-char -1)
1494 (if (looking-at "'")
1495 (forward-char 1)
1496 (skip-chars-backward " \t\*")))
1497 (if fortran-break-before-delimiters
1498 (point)
1499 (1+ (point))))))
1500 )
1501 ;; if we are in an in-line comment, don't break unless the
1502 ;; line of code is longer than it should be. Otherwise
1503 ;; break the line at the column computed above.
1504 ;;
23029d77 1505 ;; Need to use fortran-find-comment-start-skip to make sure that quoted !'s
b8cbdf43
RS
1506 ;; don't prevent a break.
1507 (if (not (or (save-excursion
1508 (if (and (re-search-backward comment-start-skip bol t)
23029d77 1509 (not (fortran-is-in-string-p (point))))
b8cbdf43
RS
1510 (progn
1511 (skip-chars-backward " \t")
1512 (< (current-column) (1+ fill-column)))))
1513 (save-excursion
1514 (goto-char fill-point)
1515 (bolp))))
1516 (if (> (save-excursion
1517 (goto-char fill-point) (current-column))
1518 (1+ fill-column))
1519 (progn (goto-char fill-point)
1520 (fortran-break-line))
1521 (save-excursion
1522 (if (> (save-excursion
1523 (goto-char fill-point)
1524 (current-column))
1525 (+ (calculate-fortran-indent) fortran-continuation-indent))
1526 (progn
1527 (goto-char fill-point)
1528 (fortran-break-line))))))
1529 ))
1530(defun fortran-break-line ()
1531 (let ((opoint (point))
1532 (bol (save-excursion (beginning-of-line) (point)))
1533 (eol (save-excursion (end-of-line) (point)))
1534 (comment-string nil))
1535
1536 (save-excursion
23029d77 1537 (if (and comment-start-skip (fortran-find-comment-start-skip))
b8cbdf43
RS
1538 (progn
1539 (re-search-backward comment-start-skip bol t)
1540 (setq comment-string (buffer-substring (point) eol))
1541 (delete-region (point) eol))))
1542;;; Forward line 1 really needs to go to next non white line
1543 (if (save-excursion (forward-line 1)
1544 (or (looking-at " [^ 0\n]")
1545 (looking-at "\t[1-9]")))
1546 (progn
b8313955
RS
1547 (end-of-line)
1548 (delete-region (point) (match-end 0))
b8cbdf43 1549 (delete-horizontal-space)
4254fe58 1550 (fortran-fill))
b8cbdf43
RS
1551 (fortran-split-line))
1552 (if comment-string
1553 (save-excursion
1554 (goto-char bol)
1555 (end-of-line)
1556 (delete-horizontal-space)
1557 (indent-to (fortran-comment-hook))
1558 (insert comment-string)))))
1559
23029d77 1560(defun fortran-analyze-file-format ()
5a8d870b 1561 "Returns nil if fixed format is used, t if TAB formatting is used.
23029d77
JB
1562Use `fortran-tab-mode-default' if no non-comment statements are found in the
1563file before the end or the first `fortran-analyze-depth' lines."
1564 (let ((i 0))
1565 (save-excursion
1566 (goto-char (point-min))
1567 (setq i 0)
1568 (while (not (or
1569 (eobp)
1570 (looking-at "\t")
1571 (looking-at " ")
1572 (> i fortran-analyze-depth)))
1573 (forward-line)
1574 (setq i (1+ i)))
1575 (cond
1576 ((looking-at "\t") t)
1577 ((looking-at " ") nil)
1578 (fortran-tab-mode-default t)
1579 (t nil)))))
1580
1581(or (assq 'fortran-tab-mode-string minor-mode-alist)
1582 (setq minor-mode-alist (cons
1583 '(fortran-tab-mode-string
1584 (indent-tabs-mode fortran-tab-mode-string))
1585 minor-mode-alist)))
1586
49116ac0
JB
1587(provide 'fortran)
1588
1a06eabd 1589;;; fortran.el ends here