// 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 }
