 ;; ...with tunable indentation level inside of the loop-control-expressions.
 ;;
 ;; FIXME: Actually, now that I look at it, all line-continuation from inside
-;; of "syntactic" {...} strings is fubar.  It all gets overindented.
+;; of "syntactic" {...} strings is fubar.  It all gets overindented.  Even
+;; conditional expressions.
 ;;
 ;; Look at the TCL mode code & fix it.
 
 
-(defun jpw-indent-to-matching-brace (&optional offset)
+(defun jpw-tcl-indent-to-matching-brace (&optional offset)
   "Do not call this function directly.
+Evals to nil if it didn't indent.
 {jpw: 7/06}"
   (back-to-indentation)
-  (let ((old-indent-pos (point))
-        (matching-brace-col (if (jpw-back-to-matching '?{ '?})
-                                (current-column)))
-        (matching-brace-indent (progn (jpw-backward-extended-line)
-                                      (back-to-indentation)
-                                      (current-column)))
+  (let (matching-brace-col
+        matching-brace-indent
+        new-indent
+        in-a-conditional
         );; end bindings
-    (goto-char old-indent-pos)
+    (if (not offset)
+        (setq offset 0))
+
+    (save-excursion
+      (if (jpw-back-to-matching '?{ '?})
+          (progn 
+            (setq matching-brace-col (current-column))
+            (backward-word 1)
+            (setq in-a-conditional 
+                  (looking-at "\\(elseif\\|if\\|while\\)"))
+            )
+        );;end if
+      (jpw-backward-extended-line)
+      (back-to-indentation)
+      (setq matching-brace-indent (current-column))
+      );;end excursion
+
     (if matching-brace-col
-        (indent-to (+ matching-brace-indent offset))
+        (if in-a-conditional
+            (tcl-indent-command)
+          ;; else
+          (setq new-indent (+ matching-brace-indent offset))
+          (if (< new-indent (current-indentation))
+              (save-excursion 
+                (let ((indentp (progn (back-to-indentation)
+                                      (point)))
+                      (bolp (progn (beginning-of-line)
+                                   (point)))
+                      );; end vars
+                  (delete-region bolp indentp)
+                  );; end let
+                );; end excursion
+            )
+          (indent-to new-indent)
+          )
+      ;; else
+      nil
       )
     );;end let
   )
+
+
+(defsubst jpw-tcl-statement-data ()
+  ;; Return a 2-element list describing the statement at `point'.
+  (list (cond ((looking-at "catch") 'catch)
+              ((looking-at "elseif") 'elseif)
+              ((looking-at "for ") 'for)
+              ((looking-at "foreach") 'foreach)
+              ((looking-at "if") 'if)
+              ((looking-at "while") 'while)
+              (t 'other-tcl-statement))
+        (current-indentation))
+  )
+
+
+(defsubst jpw-tcl-analyze-brace-pair ()
+  ;; Return the indentation-information of the parent of a brace-pair, or nil
+  ;; if we're not currently looking at a "} {" pair.
+  ;; The "indentation-information" is a 3-element list containing (in order):
+  ;; 1. The column of the matching open-brace of this line
+  ;; 2. The indentation of the line containing the open-brace matching the
+  ;;    close-brace on this line.
+  ;; 3. A symbol indicating parent-statement.
+  ;; 4. The indentation of the parent-statement.
+  ;; 5. The location of the ?{ on the line of the parent-statement
+  (let ((fwd-bound (point))
+        matching-open-brace-line-indent
+        matching-open-brace-indent
+        last-matching-open-brace-column
+        parent-statement-info
+        );;end vars
+    (if (looking-at "} +{")
+        (progn
+          (setq matching-open-brace-line-indent (current-column)
+                matching-open-brace-indent 
+                (+ (current-column) (- (match-end 0) (match-beginning 0))))
+          (while (looking-at "} +{")
+            (if (jpw-back-to-matching '?{ '?} nil fwd-bound)
+                (setq last-matching-open-brace-column (current-column))
+              ;; else
+              ;; Move off-char in case `jpw-back-to-matching' didn't move
+              ;; point.   Otherwise, we risk an infinite loop. 
+              (forward-char -1)
+              )
+            (back-to-indentation)
+            )
+          (setq parent-statement-info (jpw-tcl-statement-data))
+          (append matching-open-brace-indent
+                  matching-open-brace-line-indent
+                  parent-statement-info ;; 2 elts.
+                  last-matching-open-brace-column)
+          );; end progn
+      ;;else
+      nil
+      );; end outermost-if
+    );; end let
+  )
+
+
+(defsubst jpw-tcl-compute-brace-pair-indent ()
+  ;; Computes the indentation to use for a "} {" pair.  Evals to nil if
+  ;; `point' isn't currently looking at /} +{/.
+  (let* ((indent-info (jpw-tcl-analyze-brace-pair))
+         (parent-type (nth 2 indent-info))
+         ) ;; end vars
+    (if parent-type
+        (cond
+         ;; for-loops get special handling.
+         ((eq parent-type 'for)
+          (if jpw-tcl-align-for-loop-braces
+              (nth 4 indent-info)
+            ;; else:
+            ;; Offset it from the "for" statement.
+            (+ jpw-tcl-for-loop-bracepair-offset (nth 3 indent-info))
+            )
+          );; end case: for
+         ;; Indent other known statements (if, foreach, while, and so on) so
+         ;; that the close-brace aligns with the first open-brace after the
+         ;; statmenet.
+         ((not (eq parent-type 'other-tcl-statement))
+          (nth 4 indent-info)
+          );; end case: other known statement.
+         ;; Default:  let normal TCL mode handle it.
+         (t
+          nil)
+         ) ;; end cond
+      ) ;; end if
+    ) ;; end let
+  )
+
+
+(defsubst jpw-tcl-compute-1starg-indent ()
+  ;; Find the indendation column of the 1st arg of a command.  Assumes that
+  ;; `point' is on the command, or on a \[ character.
+  ;; If there's only one word on the line after `point' (and before any '\\'
+  ;; and the end of the line), return 'nil'.
+  (and (re-search-forward "\\s *" (line-end-position) t)
+       (re-search-forward "\\S *" (line-end-position) t)
+       (re-search-forward "\\s *" (line-end-position) t)
+       (not (looking-at "\\\\\\s *$"))
+       (current-column)
+       )      ;;sdfqretfwe asdrewq
+  )
+
+
+(defsubst jpw-tcl-analyze-extended-line ()
+  ;; If the present line is part of a continued line, evaluates to a 5-element
+  ;; list containing: 
+  ;; 1. The type of parent statement;
+  ;; 2. The indentation of the 1st line in the statement;
+  ;; 3. The point where the 1st line in the statement starts;
+  ;; 4. The type of opening paren on the 1st line of the statement (or nil if
+  ;;    none);
+  ;; 5. The column of (4), or nil.
+  ;; If the present line isn't an extended line, evaluates to nil.
+  ;;
+  ;; This function does not change `point'.
+  (save-excursion
+    (if (jpw-backward-extended-line)
+        (let ((parent (progn (back-to-indentation)
+                             (jpw-tcl-statement-data))
+              );;end vars
+          (if (re-search-forward "[[{\(]" (line-end-position) t)
+              (append parent
+                      (current-indentation) 
+                      (line-beginning-position)
+                      (list (char-after) (current-column)))
+            ;; else
+            (append parent 
+                    (current-indentation) 
+                    (line-beginning-position)
+                    nil nil)
+            )
+          );; end let
+      ;; else 
+      nil
+      )
+    )
+  )
+
+
+(defsubst jpw-tcl-compute-extended-close-brace-indent ()
+  ;; Compute the indent for a line that starts with ?} and is part of an
+  ;; extended TCL statement.
+  ;; There are 3 cases, described below.
+  (let* ((extended-line-info (jpw-tcl-analyze-extended-line))
+         (statement-type (car extended-line-info))
+         );;end vars
+    (cond
+     ;; Case (a):
+     ;; The for-statement is the exception, of course.  If the
+     ;; previous line begins with a "} {" pair, align to the 1st
+     ;; "{" in the statement.  Otherwise, let TCL-mode handle
+     ;; things.
+     ((eq statement-type 'for)
+      (forward-line -1)
+      (back-to-indentation)
+      (if (looking-at "}\\s +{")
+          (nth 4 tmp-extended-line-info)
+        nil)
+      )
+     ;; Case (b):
+     ;; If we're looking at some non-conditional statement, then
+     ;; find the matching curly and align to it. 
+     ((eq statement-type 'other-tcl-statement)
+      (and (jpw-back-to-matching '?{ '?})
+           (current-column))
+      )
+     ;; Case (c):
+     ;; An if, while, catch, or other control statement should
+     ;; align the close to the statement.  Which is the default
+     ;; behavior - i.e. eval to nil.
+     ;;
+     ;; This also handles the case of a nil `extended-line-info' - i.e. this
+     ;; isn't part of an extended TCL statement.  We want the default TCL-mode
+     ;; behavior in this case, too.
+     (t nil)
+     ) ;; end cond
+    );;end let
+  )
+
+
+(defsubst jpw-tcl-compute-bracket-indent ()
+  ;; Find the matching "[".  Returns the column of the beginning of the second
+  ;; word after the "[".
+  ;; If the user disables this behavior, do nothing and eval to nil.
+  (if (and jpw-tcl-align-to-arg
+           (jpw-back-to-matching '?\[ '?\]))
+      (jpw-tcl-compute-1starg-indent)
+    ;; else:  Let TCL-mode handle it.
+    nil
+    )
+  )
+
+
+(defsubst jpw-tcl-compute-extended-line-indent (extended-line-info)
+  ;; Computes the indentation for an extended TCL statement.
+  ;; 
+  ;; EXTENDED-LINE-INFO must be non-nil; the behavior of this function is
+  ;; undefined otherwise.
+  (let ((old-pos (point))
+        (statement-type (car extended-line-info))
+        (statement-open-paren (nth 3 extended-line-info))
+        (statement-bolp (nth 2 extended-line-info))
+        nearest-open-grp
+        nearest-open-grp-bolp
+        open-grp-column
+        statement-starts-group
+        ) ;; end vars
+
+    (setq nearest-open-grp 
+          (re-search-backward "[[\({]" 
+                              (nth 2 extended-line-info)
+                              t))
+    (if nearest-open-grp
+        (setq open-grp-column (current-column)
+              nearest-open-grp-bolp (line-beginning-position)
+              ;; - Does the nearest paren/bracket/brace equal the one in the
+              ;;   parent? 
+              ;; - Is the start of the line the same as the start of the
+              ;;   parent line?
+              statement-starts-group (and (eq nearest-open-grp 
+                                              statement-open-paren)
+                                          (= nearest-open-grp-bolp 
+                                             statement-bolp))
+              )
+      )
+
+    ;; Some cases and their controlling conditionals.
+
+    ;; No enclosing paren/brace/bracket?  Nothing special to do.  Let the
+    ;; normal TCL mode handle things.
+    ;; Only continue if we're inside of a grouping (i.e. a
+    ;; paren/brace/bracket).
+    (if nearest-open-grp
+        ;; - Is this a for/foreach loop?
+        ;; - Does the nearest paren/bracket/brace equal the one starting the
+        ;;   loop? 
+        ;; - Is the nearest paren/bracket/brace on the line starting the loop?
+        (if (and statement-starts-group
+                 (or (eq statement-type 'for)
+                     (eq statement-type 'foreach)
+                     ))
+            ;; for/foreach loops require special handling.  Of course.
+            do-for-or-foreach-case
+
+          ;; else
+          ;; Indent by type of paren:
+          (if (eq nearest-open-grp '?\[)
+              ;; - A ?[ always has the same indent, regardless of context.
+              (jpw-tcl-compute-bracket-indent)
+
+            ;; else
+            ;; We must be inside of a (...) or {...} pair.
+            (if (re-search-forward "\\S " (line-end-position) t)
+                ;; Align to the 1st non-ws char after the paren.
+                (if (eq nearest-open-grp '?{)
+                    ;; For a curly, add an optional offset to the paren posn.
+                    (+ (current-column) jpw-tcl-some-offset)
+                  ;; else:
+                  ;; eq ?\(
+                  (current-column)
+                  );; end if search-for-1st-non-ws-char
+
+              ;; else
+              ;; Fallback:  Use the previous line's indent.
+              (goto-char old-pos)
+              (jpw-last-line-indentation)
+              );; end indent-handler-if
+            );;end if '?[
+
+          );;end if in-a-for-loop
+
+      );; end if nearest-open-grp
+    ) ;; end let
+  )
+
+
+(defsubst jpw-tcl-compute-group-internal-indent()
+      (let* ((nearest-open-grp (re-search-backward "[[\({]" 
+                                                   (nth 2 extended-line-info)
+                                                   t))
+             (statement-type (car extended-line-info))
+             (statement-open-paren (nth 3 tmp-extended-line-info))
+             );; end vars
+        );; end let
+  )
+
+
+(defun jpw-tcl-compute-enhanced-indent ()
+  "Compute a more syntactically-correct indent than the old TCL mode indent
+function does.
+{jpw: 11/06}"
+  (save-excursion
+    (back-to-indentation)
+    (let ((starting-char (char-after))
+          (eolp (line-end-position))
+          tmp-extended-line-info
+          );; end vars
+      (cond
+
+       ;; Case #1:  Are we looking at a ")"?
+       ((eq starting-char '?\))
+        ;; Find its matching "(" and align to it, always.
+        (if (jpw-back-to-matching '?\( '?\))
+            (current-indentation)
+          ;; else:  Let TCL-mode handle it.
+          nil
+          )
+        )
+
+       ;; Case #2:  Are we looking at a "]"?
+       ((eq starting-char '?\])
+        (jpw-tcl-compute-bracket-indent)
+        )
+
+       ;; Case #3 & #4: Closing curly-brace.
+       ((eq starting-char '?})
+        (if (looking-at "}\\s +{")
+            ;; Case #3:  We're starting a line off with a closing curly-brace
+            ;; followed by an open curly-brace.
+            (jpw-tcl-compute-brace-pair-indent)
+          ;; else:
+          ;; 
+          ;; We're looking at a "}" followed by something else.
+          ;; Case #4:  It's part of an extended line.
+          ;; {Note that `jpw-tcl-compute-brace-pair-indent' evals to nil if
+          ;; Case #4 isn't in effect.}
+          (jpw-tcl-compute-extended-close-brace-indent)
+          ) ;; end outer-if
+        )
+
+       ;; Case #5:  Are we looking at an extended line?
+       ((setq tmp-extended-line-info (jpw-tcl-analyze-extended-line))
+        (jpw-tcl-compute-extended-line-indent tmp-extended-line-info)
+        )
+
+       ;; Case #6:  Are we inside of the start, test, or next expressions of a
+       ;; multi-line for-loop?
+       ;;
+       ;; If so, align to the previous line's "{", plus a user-defined offset.
+       (nil
+        )
+
+       ;; Case #7:  Are we the first statement in the body of a for-loop (or
+       ;; foreach-loop) that starts itself with extended lines?
+       ;;
+       ;; If so, align to the parent "for" (or "foreach") statement plus
+       ;; tcl-indent-level plus an optional offset.
+       ;;
+       ;; Alternative:  have a control flag (e.g.
+       ;; "correct-stoopid-tcl-for-loop-indenting") and, if it's set, check for
+       ;; this case, and indent as described above but without any optional
+       ;; offset.
+       (nil
+        )
+
+      ) ;; end cond
+    ) ;; end let
+  ) ;; end excursion
+)
 
 
 (defun jpw-tcl-indent-new-comment-line (&optional soft)

  :group 'tcl)


(defcustom jpw-tcl-allow-comment-unindent t
  "When set to non-nil, allows the function `jpw-tcl-comment-indent-command'
to \"indent backward\".  By default, `jpw-tcl-comment-indent-command' ignores
comments with internal indentation deeper than the previous line.
{jpw: 7/06}"
  :group 'tcl)



  (unless comment-end-skip
    (set (make-local-variable 'comment-end-skip) 
         "[ 	]*\\(\\s>\\|\n\\)"))

  ;; Configure paragraph start/separate vars
  (make-local-variable 'paragraph-start)
  (make-local-variable 'paragraph-separate)
  (setq paragraph-start  "[ 	]*\\(#[ 	]*\\)?$\\|^\f"
        paragraph-separate paragraph-start)
  )
(remove-hook 'tcl-mode-hook 'tcl-enhance-indentation)
(add-hook 'tcl-mode-hook 'tcl-enhance-indentation)
