关于高亮显示括号匹配的算法(delphi)

环境: SynEdtor控件 + delphi
匹配括号的算法:传入参数  APoint: TBufferCoord;

const
  Brackets: array[0..7] of char = ('(', ')', '[', ']', '{', '}', '<', '>');
var
  Line: string;
  i, PosX, PosY, Len: integer;
  Test, BracketInc, BracketDec: char;
  NumBrackets: integer;
  p: TBufferCoord;
begin
  Result.Char := 0;
  Result.Line := 0;
  // 获取到鼠标的位置
  PosX := APoint.Char;
  PosY := APoint.Line;
  Line := Lines[ APoint.Line -1 ];
  if Length(Line) >= PosX then
  begin
    Test := Line[PosX];
    //判断是不是数组里的括号
    for i := Low(Brackets) to High(Brackets) do
      if Test = Brackets[i] then
      begin
        // 这里可以得到当前选中的括号与数组的匹配的括号是哪个?
        BracketInc := Brackets[i];
        BracketDec := Brackets[i xor 1]; // 0 -> 1, 1 -> 0, ...
        // NumBrackets 这个计数器很关键,如果等于0。表示找到了匹配的括号
        NumBrackets := 1;
        if Odd(i) then  //判断是否奇数
        begin
          while (true) do
          begin
            //数组里为奇数的括号,一直寻址到文本开头
            while PosX > 1 do
            begin
              Dec(PosX);
              Test := Line[PosX];
              p.Char := PosX;
              p.Line := PosY;
              if (Test = BracketInc) or (Test = BracketDec) then
              begin
                if (Test = BracketInc) and (not isCommentOrString) then
                  Inc(NumBrackets)
                else if (Test = BracketDec) and (not isCommentOrString) then
                begin
                  Dec(NumBrackets);
                  if NumBrackets = 0 then
                  begin
                    //找到匹配的括号则跳出
                    Result := P;
                    exit;
                  end;
                end;
              end;
            end;
            //while(true)跳出条件
            if PosY = 1 then break;
            Dec(PosY);
            Line := Lines[PosY - 1];
            PosX := Length(Line) + 1;
          end;
        end
        else begin
          while (true) do
          begin
             //数组里为偶数的括号,一直寻址到文本开头
            Len := Length(Line);
            while PosX < Len do
            begin
              Inc(PosX);
              Test := Line[PosX];
              p.Char := PosX;
              p.Line := PosY;
              if (Test = BracketInc) or (Test = BracketDec) then
              begin
                if (Test = BracketInc) and (not isCommentOrString) then
                  Inc(NumBrackets)
                else if (Test = BracketDec)and (not isCommentOrString) then
                begin
                  Dec(NumBrackets);
                  if NumBrackets = 0 then
                  begin
                    //找到匹配的括号则跳出
                    Result := P;
                    exit;
                  end;
                end;
              end;
            end;
            //while(true)跳出条件
            if PosY = Lines.Count then
              Break;
            Inc(PosY);
            Line := Lines[PosY - 1];
            PosX := 0;
          end;
        end;
        //不在数组的其他字符不做匹配
        break;
      end;
  end;

—–画括号的背景 上面的函数将返回一个 matchBacket: TBufferCoord;

    xpos := matchBacket.char;
    yPos := matchBacket.line;
    windows.SetBkMode(self.Canvas.Handle, windows.OPAQUE);
    self.Canvas.Font.Size:= Acontrol.canvas.Font.Size;
    self.Canvas.Font.Name:= Acontrol.canvas.Font.name;
    windows.TextOut(aControl.canvas.Handle, xpos, ypos, Bracket, 1);

总结:

     1、 整个功能的实现过程中,在查找匹配括号中使用了一个计数器,同时利用括号成对的奇偶数的判断思路完成编码。

     2、不仅需要找到匹配的括号,还要对这个位置进行背景色的绘制。

 

标签