|
|
@@ -1091,6 +1091,84 @@ BEGIN
|
|
|
IF data^.cx > data^.len[data^.cy] THEN data^.cx := data^.len[data^.cy] END
|
|
|
END EdEnsure;
|
|
|
|
|
|
+PROCEDURE Eq (a, b : ARRAY OF CHAR) : BOOLEAN;
|
|
|
+ VAR i : INTEGER;
|
|
|
+BEGIN
|
|
|
+ i := 0;
|
|
|
+ WHILE (i <= VAL(INTEGER, HIGH(a))) AND (i <= VAL(INTEGER, HIGH(b))) AND
|
|
|
+ (a[i] # 0C) AND (b[i] # 0C) AND (a[i] = b[i]) DO
|
|
|
+ i := i + 1
|
|
|
+ END;
|
|
|
+ RETURN a[i] = b[i]
|
|
|
+END Eq;
|
|
|
+
|
|
|
+PROCEDURE IsIdentChar (c : CHAR) : BOOLEAN;
|
|
|
+BEGIN
|
|
|
+ RETURN ((c >= 'A') AND (c <= 'Z')) OR ((c >= 'a') AND (c <= 'z')) OR
|
|
|
+ ((c >= '0') AND (c <= '9')) OR (c = '_')
|
|
|
+END IsIdentChar;
|
|
|
+
|
|
|
+PROCEDURE UpcaseCopy (VAR dest : ARRAY OF CHAR; s : ARRAY OF CHAR);
|
|
|
+ VAR i : INTEGER; c : CHAR;
|
|
|
+BEGIN
|
|
|
+ i := 0;
|
|
|
+ WHILE (i <= VAL(INTEGER, HIGH(s))) AND (i < VAL(INTEGER, HIGH(dest))) AND (s[i] # 0C) DO
|
|
|
+ c := s[i];
|
|
|
+ IF (c >= 'a') AND (c <= 'z') THEN c := CHR(ORD(c) - 32) END;
|
|
|
+ dest[i] := c;
|
|
|
+ i := i + 1
|
|
|
+ END;
|
|
|
+ dest[i] := 0C
|
|
|
+END UpcaseCopy;
|
|
|
+
|
|
|
+PROCEDURE IsKeywordM2 (w : ARRAY OF CHAR) : BOOLEAN;
|
|
|
+BEGIN
|
|
|
+ RETURN Eq(w,"AND") OR Eq(w,"ARRAY") OR Eq(w,"BEGIN") OR Eq(w,"BY") OR
|
|
|
+ Eq(w,"CASE") OR Eq(w,"CONST") OR Eq(w,"DEFINITION") OR Eq(w,"DIV") OR
|
|
|
+ Eq(w,"DO") OR Eq(w,"ELSE") OR Eq(w,"ELSIF") OR Eq(w,"END") OR
|
|
|
+ Eq(w,"EXIT") OR Eq(w,"EXPORT") OR Eq(w,"FOR") OR Eq(w,"FROM") OR
|
|
|
+ Eq(w,"IF") OR Eq(w,"IMPLEMENTATION") OR Eq(w,"IMPORT") OR Eq(w,"IN") OR
|
|
|
+ Eq(w,"LOOP") OR Eq(w,"MOD") OR Eq(w,"MODULE") OR Eq(w,"NOT") OR
|
|
|
+ Eq(w,"OF") OR Eq(w,"OR") OR Eq(w,"POINTER") OR Eq(w,"PROCEDURE") OR
|
|
|
+ Eq(w,"QUALIFIED") OR Eq(w,"RECORD") OR Eq(w,"REPEAT") OR Eq(w,"RETURN") OR
|
|
|
+ Eq(w,"SET") OR Eq(w,"THEN") OR Eq(w,"TO") OR Eq(w,"TYPE") OR
|
|
|
+ Eq(w,"UNTIL") OR Eq(w,"VAR") OR Eq(w,"WHILE") OR Eq(w,"WITH")
|
|
|
+END IsKeywordM2;
|
|
|
+
|
|
|
+PROCEDURE IsKeywordOberon (w : ARRAY OF CHAR) : BOOLEAN;
|
|
|
+BEGIN
|
|
|
+ RETURN Eq(w,"ARRAY") OR Eq(w,"BEGIN") OR Eq(w,"BY") OR Eq(w,"CASE") OR
|
|
|
+ Eq(w,"CONST") OR Eq(w,"DIV") OR Eq(w,"DO") OR Eq(w,"ELSE") OR
|
|
|
+ Eq(w,"ELSIF") OR Eq(w,"END") OR Eq(w,"FALSE") OR Eq(w,"FOR") OR
|
|
|
+ Eq(w,"IF") OR Eq(w,"IMPORT") OR Eq(w,"IN") OR Eq(w,"IS") OR
|
|
|
+ Eq(w,"MOD") OR Eq(w,"MODULE") OR Eq(w,"NIL") OR Eq(w,"OF") OR
|
|
|
+ Eq(w,"OR") OR Eq(w,"POINTER") OR Eq(w,"PROCEDURE") OR Eq(w,"RECORD") OR
|
|
|
+ Eq(w,"REPEAT") OR Eq(w,"RETURN") OR Eq(w,"THEN") OR Eq(w,"TO") OR
|
|
|
+ Eq(w,"TRUE") OR Eq(w,"TYPE") OR Eq(w,"UNTIL") OR Eq(w,"VAR") OR
|
|
|
+ Eq(w,"WHILE") OR Eq(w,"WITH")
|
|
|
+END IsKeywordOberon;
|
|
|
+
|
|
|
+PROCEDURE IsKeywordPascal (w : ARRAY OF CHAR) : BOOLEAN;
|
|
|
+BEGIN
|
|
|
+ RETURN Eq(w,"AND") OR Eq(w,"ARRAY") OR Eq(w,"BEGIN") OR Eq(w,"CASE") OR
|
|
|
+ Eq(w,"CONST") OR Eq(w,"DIV") OR Eq(w,"DO") OR Eq(w,"DOWNTO") OR
|
|
|
+ Eq(w,"ELSE") OR Eq(w,"END") OR Eq(w,"FILE") OR Eq(w,"FOR") OR
|
|
|
+ Eq(w,"FUNCTION") OR Eq(w,"GOTO") OR Eq(w,"IF") OR Eq(w,"IN") OR
|
|
|
+ Eq(w,"LABEL") OR Eq(w,"MOD") OR Eq(w,"NIL") OR Eq(w,"NOT") OR
|
|
|
+ Eq(w,"OF") OR Eq(w,"OR") OR Eq(w,"PACKED") OR Eq(w,"PROCEDURE") OR
|
|
|
+ Eq(w,"PROGRAM") OR Eq(w,"RECORD") OR Eq(w,"REPEAT") OR Eq(w,"SET") OR
|
|
|
+ Eq(w,"THEN") OR Eq(w,"TO") OR Eq(w,"TYPE") OR Eq(w,"UNTIL") OR
|
|
|
+ Eq(w,"VAR") OR Eq(w,"WHILE") OR Eq(w,"WITH")
|
|
|
+END IsKeywordPascal;
|
|
|
+
|
|
|
+PROCEDURE IsKeywordLang (lang : INTEGER; w : ARRAY OF CHAR) : BOOLEAN;
|
|
|
+BEGIN
|
|
|
+ IF lang = langModula2 THEN RETURN IsKeywordM2(w) END;
|
|
|
+ IF lang = langOberon THEN RETURN IsKeywordOberon(w) END;
|
|
|
+ IF lang = langPascal THEN RETURN IsKeywordPascal(w) END;
|
|
|
+ RETURN FALSE
|
|
|
+END IsKeywordLang;
|
|
|
+
|
|
|
PROCEDURE EdInsertChar (data : EditorDataPtr; cp : CARDINAL);
|
|
|
VAR ln, i : INTEGER;
|
|
|
BEGIN
|
|
|
@@ -1113,8 +1191,69 @@ BEGIN
|
|
|
data^.dirty := TRUE
|
|
|
END EdInsertChar;
|
|
|
|
|
|
+PROCEDURE IsOpenKw (w : ARRAY OF CHAR) : BOOLEAN;
|
|
|
+BEGIN
|
|
|
+ RETURN Eq(w,"BEGIN") OR Eq(w,"THEN") OR Eq(w,"ELSE") OR Eq(w,"ELSIF") OR
|
|
|
+ Eq(w,"DO") OR Eq(w,"LOOP") OR Eq(w,"REPEAT") OR Eq(w,"RECORD") OR
|
|
|
+ Eq(w,"CASE") OR Eq(w,"OF")
|
|
|
+END IsOpenKw;
|
|
|
+
|
|
|
+PROCEDURE IsCloseKw (w : ARRAY OF CHAR) : BOOLEAN;
|
|
|
+BEGIN
|
|
|
+ RETURN Eq(w,"END") OR Eq(w,"UNTIL") OR Eq(w,"ELSE") OR Eq(w,"ELSIF")
|
|
|
+END IsCloseKw;
|
|
|
+
|
|
|
+PROCEDURE EdIndentSpaces (data : EditorDataPtr; ln : INTEGER) : INTEGER;
|
|
|
+ VAR i : INTEGER;
|
|
|
+BEGIN
|
|
|
+ i := 0;
|
|
|
+ WHILE (i < data^.len[ln]) AND (data^.line[ln][i] = ' ') DO i := i + 1 END;
|
|
|
+ RETURN i
|
|
|
+END EdIndentSpaces;
|
|
|
+
|
|
|
+PROCEDURE EdRtrim (data : EditorDataPtr; ln, upto : INTEGER) : INTEGER;
|
|
|
+BEGIN
|
|
|
+ WHILE (upto > 0) AND (data^.line[ln][upto - 1] = ' ') DO upto := upto - 1 END;
|
|
|
+ RETURN upto
|
|
|
+END EdRtrim;
|
|
|
+
|
|
|
+PROCEDURE EdLastWordOpen (data : EditorDataPtr; ln : INTEGER) : BOOLEAN;
|
|
|
+ VAR n, i : INTEGER; w : ARRAY [0..63] OF CHAR;
|
|
|
+BEGIN
|
|
|
+ IF data^.lang = langNone THEN RETURN FALSE END;
|
|
|
+ n := EdRtrim(data, ln, data^.len[ln]);
|
|
|
+ IF n = 0 THEN RETURN FALSE END;
|
|
|
+ i := n;
|
|
|
+ WHILE (i > 0) AND IsIdentChar(data^.line[ln][i - 1]) DO i := i - 1 END;
|
|
|
+ n := 0;
|
|
|
+ WHILE (i < data^.len[ln]) AND IsIdentChar(data^.line[ln][i]) AND (n < 63) DO
|
|
|
+ w[n] := data^.line[ln][i]; n := n + 1; i := i + 1
|
|
|
+ END;
|
|
|
+ w[n] := 0C;
|
|
|
+ UpcaseCopy(w, w);
|
|
|
+ RETURN IsOpenKw(w)
|
|
|
+END EdLastWordOpen;
|
|
|
+
|
|
|
+PROCEDURE EdDedent (data : EditorDataPtr);
|
|
|
+ VAR lead, n, i : INTEGER;
|
|
|
+BEGIN
|
|
|
+ IF (data = NIL) OR (data^.lang = langNone) OR (data^.indent <= 0) THEN RETURN END;
|
|
|
+ lead := EdIndentSpaces(data, data^.cy);
|
|
|
+ IF lead = 0 THEN RETURN END;
|
|
|
+ n := data^.indent;
|
|
|
+ IF n > lead THEN n := lead END;
|
|
|
+ FOR i := 0 TO data^.len[data^.cy] - n - 1 DO
|
|
|
+ data^.line[data^.cy][i] := data^.line[data^.cy][i + n]
|
|
|
+ END;
|
|
|
+ data^.len[data^.cy] := data^.len[data^.cy] - n;
|
|
|
+ data^.line[data^.cy][data^.len[data^.cy]] := 0C;
|
|
|
+ data^.cx := data^.cx - n;
|
|
|
+ IF data^.cx < 0 THEN data^.cx := 0 END;
|
|
|
+ data^.dirty := TRUE
|
|
|
+END EdDedent;
|
|
|
+
|
|
|
PROCEDURE EdNewLine (data : EditorDataPtr);
|
|
|
- VAR ln, i, k, tail : INTEGER;
|
|
|
+ VAR ln, i, k, tail, ind : INTEGER;
|
|
|
BEGIN
|
|
|
EdEnsure(data);
|
|
|
IF data^.count >= EDMAXLINES THEN RETURN END;
|
|
|
@@ -1131,9 +1270,22 @@ BEGIN
|
|
|
data^.len[ln + 1] := tail;
|
|
|
FOR k := data^.cx TO EDMAXCOL - 1 DO data^.line[ln][k] := 0C END;
|
|
|
data^.len[ln] := data^.cx;
|
|
|
+ (* auto-indent: copy the leading spaces, plus one level after an open
|
|
|
+ keyword (BEGIN/THEN/DO/... ) *)
|
|
|
+ ind := EdIndentSpaces(data, ln);
|
|
|
+ IF EdLastWordOpen(data, ln) AND (data^.indent > 0) THEN
|
|
|
+ ind := ind + data^.indent
|
|
|
+ END;
|
|
|
+ IF (ind > 0) AND (data^.len[ln + 1] + ind < EDMAXCOL - 1) THEN
|
|
|
+ FOR k := data^.len[ln + 1] - 1 TO 0 BY -1 DO
|
|
|
+ data^.line[ln + 1][k + ind] := data^.line[ln + 1][k]
|
|
|
+ END;
|
|
|
+ FOR k := 0 TO ind - 1 DO data^.line[ln + 1][k] := ' ' END;
|
|
|
+ data^.len[ln + 1] := data^.len[ln + 1] + ind
|
|
|
+ END;
|
|
|
data^.count := data^.count + 1;
|
|
|
data^.cy := data^.cy + 1;
|
|
|
- data^.cx := 0;
|
|
|
+ data^.cx := ind;
|
|
|
data^.dirty := TRUE
|
|
|
END EdNewLine;
|
|
|
|
|
|
@@ -1241,83 +1393,7 @@ END EdMove;
|
|
|
|
|
|
(* --- syntax highlighting + keyword upcasing ---------------------------- *)
|
|
|
|
|
|
-PROCEDURE Eq (a, b : ARRAY OF CHAR) : BOOLEAN;
|
|
|
- VAR i : INTEGER;
|
|
|
-BEGIN
|
|
|
- i := 0;
|
|
|
- WHILE (i <= VAL(INTEGER, HIGH(a))) AND (i <= VAL(INTEGER, HIGH(b))) AND
|
|
|
- (a[i] # 0C) AND (b[i] # 0C) AND (a[i] = b[i]) DO
|
|
|
- i := i + 1
|
|
|
- END;
|
|
|
- RETURN a[i] = b[i]
|
|
|
-END Eq;
|
|
|
|
|
|
-PROCEDURE IsIdentChar (c : CHAR) : BOOLEAN;
|
|
|
-BEGIN
|
|
|
- RETURN ((c >= 'A') AND (c <= 'Z')) OR ((c >= 'a') AND (c <= 'z')) OR
|
|
|
- ((c >= '0') AND (c <= '9')) OR (c = '_')
|
|
|
-END IsIdentChar;
|
|
|
-
|
|
|
-PROCEDURE UpcaseCopy (VAR dest : ARRAY OF CHAR; s : ARRAY OF CHAR);
|
|
|
- VAR i : INTEGER; c : CHAR;
|
|
|
-BEGIN
|
|
|
- i := 0;
|
|
|
- WHILE (i <= VAL(INTEGER, HIGH(s))) AND (i < VAL(INTEGER, HIGH(dest))) AND (s[i] # 0C) DO
|
|
|
- c := s[i];
|
|
|
- IF (c >= 'a') AND (c <= 'z') THEN c := CHR(ORD(c) - 32) END;
|
|
|
- dest[i] := c;
|
|
|
- i := i + 1
|
|
|
- END;
|
|
|
- dest[i] := 0C
|
|
|
-END UpcaseCopy;
|
|
|
-
|
|
|
-PROCEDURE IsKeywordM2 (w : ARRAY OF CHAR) : BOOLEAN;
|
|
|
-BEGIN
|
|
|
- RETURN Eq(w,"AND") OR Eq(w,"ARRAY") OR Eq(w,"BEGIN") OR Eq(w,"BY") OR
|
|
|
- Eq(w,"CASE") OR Eq(w,"CONST") OR Eq(w,"DEFINITION") OR Eq(w,"DIV") OR
|
|
|
- Eq(w,"DO") OR Eq(w,"ELSE") OR Eq(w,"ELSIF") OR Eq(w,"END") OR
|
|
|
- Eq(w,"EXIT") OR Eq(w,"EXPORT") OR Eq(w,"FOR") OR Eq(w,"FROM") OR
|
|
|
- Eq(w,"IF") OR Eq(w,"IMPLEMENTATION") OR Eq(w,"IMPORT") OR Eq(w,"IN") OR
|
|
|
- Eq(w,"LOOP") OR Eq(w,"MOD") OR Eq(w,"MODULE") OR Eq(w,"NOT") OR
|
|
|
- Eq(w,"OF") OR Eq(w,"OR") OR Eq(w,"POINTER") OR Eq(w,"PROCEDURE") OR
|
|
|
- Eq(w,"QUALIFIED") OR Eq(w,"RECORD") OR Eq(w,"REPEAT") OR Eq(w,"RETURN") OR
|
|
|
- Eq(w,"SET") OR Eq(w,"THEN") OR Eq(w,"TO") OR Eq(w,"TYPE") OR
|
|
|
- Eq(w,"UNTIL") OR Eq(w,"VAR") OR Eq(w,"WHILE") OR Eq(w,"WITH")
|
|
|
-END IsKeywordM2;
|
|
|
-
|
|
|
-PROCEDURE IsKeywordOberon (w : ARRAY OF CHAR) : BOOLEAN;
|
|
|
-BEGIN
|
|
|
- RETURN Eq(w,"ARRAY") OR Eq(w,"BEGIN") OR Eq(w,"BY") OR Eq(w,"CASE") OR
|
|
|
- Eq(w,"CONST") OR Eq(w,"DIV") OR Eq(w,"DO") OR Eq(w,"ELSE") OR
|
|
|
- Eq(w,"ELSIF") OR Eq(w,"END") OR Eq(w,"FALSE") OR Eq(w,"FOR") OR
|
|
|
- Eq(w,"IF") OR Eq(w,"IMPORT") OR Eq(w,"IN") OR Eq(w,"IS") OR
|
|
|
- Eq(w,"MOD") OR Eq(w,"MODULE") OR Eq(w,"NIL") OR Eq(w,"OF") OR
|
|
|
- Eq(w,"OR") OR Eq(w,"POINTER") OR Eq(w,"PROCEDURE") OR Eq(w,"RECORD") OR
|
|
|
- Eq(w,"REPEAT") OR Eq(w,"RETURN") OR Eq(w,"THEN") OR Eq(w,"TO") OR
|
|
|
- Eq(w,"TRUE") OR Eq(w,"TYPE") OR Eq(w,"UNTIL") OR Eq(w,"VAR") OR
|
|
|
- Eq(w,"WHILE") OR Eq(w,"WITH")
|
|
|
-END IsKeywordOberon;
|
|
|
-
|
|
|
-PROCEDURE IsKeywordPascal (w : ARRAY OF CHAR) : BOOLEAN;
|
|
|
-BEGIN
|
|
|
- RETURN Eq(w,"AND") OR Eq(w,"ARRAY") OR Eq(w,"BEGIN") OR Eq(w,"CASE") OR
|
|
|
- Eq(w,"CONST") OR Eq(w,"DIV") OR Eq(w,"DO") OR Eq(w,"DOWNTO") OR
|
|
|
- Eq(w,"ELSE") OR Eq(w,"END") OR Eq(w,"FILE") OR Eq(w,"FOR") OR
|
|
|
- Eq(w,"FUNCTION") OR Eq(w,"GOTO") OR Eq(w,"IF") OR Eq(w,"IN") OR
|
|
|
- Eq(w,"LABEL") OR Eq(w,"MOD") OR Eq(w,"NIL") OR Eq(w,"NOT") OR
|
|
|
- Eq(w,"OF") OR Eq(w,"OR") OR Eq(w,"PACKED") OR Eq(w,"PROCEDURE") OR
|
|
|
- Eq(w,"PROGRAM") OR Eq(w,"RECORD") OR Eq(w,"REPEAT") OR Eq(w,"SET") OR
|
|
|
- Eq(w,"THEN") OR Eq(w,"TO") OR Eq(w,"TYPE") OR Eq(w,"UNTIL") OR
|
|
|
- Eq(w,"VAR") OR Eq(w,"WHILE") OR Eq(w,"WITH")
|
|
|
-END IsKeywordPascal;
|
|
|
-
|
|
|
-PROCEDURE IsKeywordLang (lang : INTEGER; w : ARRAY OF CHAR) : BOOLEAN;
|
|
|
-BEGIN
|
|
|
- IF lang = langModula2 THEN RETURN IsKeywordM2(w) END;
|
|
|
- IF lang = langOberon THEN RETURN IsKeywordOberon(w) END;
|
|
|
- IF lang = langPascal THEN RETURN IsKeywordPascal(w) END;
|
|
|
- RETURN FALSE
|
|
|
-END IsKeywordLang;
|
|
|
|
|
|
PROCEDURE HiPut (v : ViewPtr; c : INTEGER; ch : CHAR; attr : Attr;
|
|
|
x0, y0, w : INTEGER; draw : BOOLEAN);
|
|
|
@@ -1435,6 +1511,10 @@ BEGIN
|
|
|
IF IsKeywordLang(data^.lang, up) AND (NOT Eq(w, up)) THEN
|
|
|
FOR k := 0 TO n - 1 DO data^.line[ln][i + k] := up[k] END;
|
|
|
data^.dirty := TRUE
|
|
|
+ END;
|
|
|
+ (* smart dedent: a close keyword at the start of the line moves it left *)
|
|
|
+ IF IsCloseKw(up) AND (i = EdIndentSpaces(data, ln)) THEN
|
|
|
+ EdDedent(data)
|
|
|
END
|
|
|
END EdUpcaseWord;
|
|
|
|
|
|
@@ -1505,7 +1585,8 @@ BEGIN
|
|
|
EdClrLine(data^.line[0]);
|
|
|
data^.len[0] := 0;
|
|
|
data^.cx := 0; data^.cy := 0; data^.top := 0; data^.left := 0;
|
|
|
- data^.ins := TRUE; data^.dirty := FALSE; data^.lang := langNone
|
|
|
+ data^.ins := TRUE; data^.dirty := FALSE; data^.lang := langNone;
|
|
|
+ data^.indent := 2
|
|
|
END
|
|
|
END EditorInit;
|
|
|
|
|
|
@@ -1559,6 +1640,7 @@ BEGIN
|
|
|
END;
|
|
|
data^.cx := 0; data^.cy := 0; data^.top := 0; data^.left := 0;
|
|
|
data^.dirty := FALSE;
|
|
|
+ IF data^.indent <= 0 THEN data^.indent := 2 END;
|
|
|
RETURN TRUE
|
|
|
END EditorLoad;
|
|
|
|
|
|
@@ -1588,6 +1670,11 @@ BEGIN
|
|
|
IF data # NIL THEN data^.lang := lang END
|
|
|
END EditorSetLanguage;
|
|
|
|
|
|
+PROCEDURE EditorSetIndent (data : EditorDataPtr; n : INTEGER);
|
|
|
+BEGIN
|
|
|
+ IF data # NIL THEN data^.indent := n END
|
|
|
+END EditorSetIndent;
|
|
|
+
|
|
|
PROCEDURE DrawView(v : ViewPtr);
|
|
|
VAR c : ViewPtr;
|
|
|
BEGIN
|