// kate: space-indent on; indent-width 4; replace-tabs on; remove-trailing-spaces all;
// kate: syntax pascal; indent-mode pascal;

// these variables are understood by the pascal indenter ...
// kate: cfgIndentCase false;          // indent elements in a case statement
// kate: cfgIndentBegin 2;            // indent 'begin' this many spaces
// kate: debugMode false;              // show how indent is determined
// kate: cfgAutoInsertStar true;      // auto insert '*' in (* ... *)-comments
// kate: cfgSnapParen true;           // snap '* )' to '*)' in comments


unit unit1;

interface
type t = real;

implementation

FUNCTION f(
            alf : real;
            fred : integer;  // should line up with alf
            bill : boolean;
            joe: char;
          );
VAR s : string;
BEGIN s := do; WriteLn(s) END;


procedure getbyte;   // CHECK: cr after this line is **not** indented

var  // CHECK: cr after this line **is** indented
    ch : char;

begin

   // need to consider:
   // if c then begin s1; s2 end; // strip these lines
   // begin   // normal case
   // end     // normal case
   // end else if begin // should be OK since /end/ tested last
   // need to consider ...
   //                  if c1 then begin s1; s2 end
   //                  else s3;
                                        // <-- align this line

                                        { checking multi line statements }


    while aaaaaaaaaaaaaaaaaaaaaaa
            and bbbbbbbbbbb  do
        if c1 then begin
            s1;
            for i := 1
                  to 10 do
                s3
        end;
    s4;
    s5; // the ';' here links to the ';' after the 'case' below

    if c1 then
        case e01 of
        111111111:    s1;
        23:
            writeln(x,
                    'fred',
                    notCaseValue:4,
                    x);

        2:
            case e05 of
            1: s1;   // CHECK: cr here should go to new case value!
            88:
                s3;

            2:  begin
                  s2;
                  s3;
                end;

            3:
                case e09 of
                1: s1;   // CHECK: cr here should go to new case value!
                88:
                    s3;

                2:
                    begin
                      s2;
                      s3;
                    end;

                3: s3;
                4,5,6..9: s6;

                otherwise
                    writeln('lots');
                    writeln(' and lots');
                end; {case}

            4,5,6..9: s6;

            otherwise
                writeln('lots');
                writeln(' and lots');
            end; {case}

        4: if e then
              begin   // CHECK: should be indented after case value
                s1;
                s2
              end
            else if ee
                    and ee1
            then begin
                s1;
                s2;
            end;

        99: a:= 13;
        100: if e then s1;

        333333: if c then
              begin // CKECK: should indent one level from case value
                s3; // CHECK: should be indented another level
                s4
              end;

        30:
            if c then begin // cr here is OK
                s3;
                s4
            end;
        4: writeln('fred',
                   notCaseValue:4,
                   x
                  );
        s4;             // incorrect code, indenter should expect a case value here
        88:
            if c1 then
              begin
                s6;
                s7
            else
                s8
              end;     // stress test: else/end crossed over !!
        end; {case}
    s6;

    a := 1;
    a := 2;
    a := 3;
    if c1
            and c2 then begin // can be aligned manually
        a := 12;             // should be indented one level from if statement
        f(x)
    end;
    if c1
            and c2  // can be aligned manually
    then
      begin
        a := 12;             // should be indented one level from if statement
        f(x)
      end;
    if c then
        if c then
            if c then
                repeat s1 until c
            else
                a[    i,
                      j,
                      zzzzzzzzzz[ a,
                                  b
                                ],
                      vvvvv   // CHECK: indent lines with zzzzzzzzz
                 ] := x
                      + 10;
    if a then
        if b then
            if c then begin
                s1;
                s2;
            end; {if}
    while z do s1;


    while not (  ((currchar.value = '*') and (nextchar.value = ')'))
                 or (currchar.value = '}') // args should line up inside parens
                 or (nextchar.name = endofline)
                 or ( sym^.length >= maxsymbolsize-2 )
                 or (nextchar.name = filemark)) do
        storenextchar(sym^.length,sym^.value);  // should be indented from while

    while not (currchar.value = '*') and (nextchar.value = ')')
          or (currchar.value = '}')           // possible to realign first line manually
          or (nextchar.name = endofline)      // CHECK: other lines should follow first line  // CHECK:: indents line up
          or ( sym^.length >= maxsymbolsize-2 )
          or (nextchar.name = filemark) do
        storenextchar(sym^.length,sym^.value);  // should be indented from while

    while not (currchar.value = '*') and (nextchar.value = ')')
          or (currchar.value = '}')           // possible to realign first line manually
          or (nextchar.name = endofline)      // CHECK: other lines should follow first line  // CHECK:: indents line up
          or ( sym^.length >= maxsymbolsize-2 )
          or (nextchar.name = filemark)
    do
        storenextchar(sym^.length,sym^.value);  // should be indented from while

    dblchar[becomes] := ':=';
    dblchar[opencomment] := '(*';  // not start of comment!
    sglchar[semicolon] := ';';
    sglchar[colon]     := ':';
    sglchar[equals]    := '=';
    sglchar[openparen] := '(';
    sglchar[closeparen] := ')';
    sglchar[period]    := '.';
    sglchar[opencomment] := '{';
    sglchar[closecomment] := '}';

    with nextchar do
        if eof(infile) then
          begin
            name := filemark;
            if ch in ['0'..'9'] then
                name := digit
            else if ch = '''' then begin
                name := quote
            end else if (ch = blank) or (ch = chr(tab)) then
                name := space
            else name := otherchar
                value := blank
          end
        else if eoln(infile) then
          begin
            name := endofline;
            value := blank;
            if c1 then begin s1; s2 end
            else s7;
            inlines := inlines + 1;
            readln(infile)
          end
        else
          begin
            read(infile,ch);
            value := ch;
            if ch in ['a'..'z','A'..'Z','_'] then
                name := letter
            else
                if ch in ['0'..'9'] then
                    name := digit
                else if ch = '''' then while c do
                  begin
                    s1;
                    name := quote
                  end;
                else if (ch = blank) or (ch = chr(tab)) then
                    name := space
                else name := otherchar
          end;

          { CHECK:
                    # pp lines go to start of line, unless they are in a comment
          }

#if
#endif
    cccccc; // CHECK: this aligns with code
# // CHECK: preprocessor lines go to start of line

    if c1 then
        if c2 then while c do
            s
        else
            s2;
    s3;
    s4;

end; { getbyte }
