OSDN Git Service

・スレタイにタブ文字があるスレッドをHTML化して保存できない問題を修正
authorzako <zako@users.sourceforge.jp>
Thu, 13 Nov 2014 16:04:03 +0000 (01:04 +0900)
committerzako <zako@users.sourceforge.jp>
Thu, 13 Nov 2014 16:04:03 +0000 (01:04 +0900)
・NGワードで正規表現を使用できるよう変更
・NGワード編集画面を追加
・オプションでNGワード編集に従来どおりテキストエディタを使用する設定を追加

14 files changed:
AbonInfo.pas [new file with mode: 0644]
AbonInfoSet.dfm [new file with mode: 0644]
AbonInfoSet.pas [new file with mode: 0644]
AbonUnit.pas
GikoDataModule.pas
MojuUtils.pas
NgEditor.dfm [new file with mode: 0644]
NgEditor.pas [new file with mode: 0644]
Option.dfm
Option.pas
RegExpTester.dfm [new file with mode: 0644]
RegExpTester.pas [new file with mode: 0644]
Setting.pas
gikoNavi.dpr

diff --git a/AbonInfo.pas b/AbonInfo.pas
new file mode 100644 (file)
index 0000000..4a0d53c
--- /dev/null
@@ -0,0 +1,72 @@
+unit AbonInfo;
+
+interface
+
+type
+  TAbonType = (atStandard, stTransparent);
+  TCompType = (ctStandard, ctRegexp);
+  TTargetType = (ttAll, ttThread, ttBoard);
+
+  TLineInfo = class(TObject)
+  public
+    AbonType:   TAbonType;
+    CompType:   TCompType;
+    TargetType: TTargetType;
+    TargetBoard: String;
+    TargetThread: String;
+       constructor Create;
+    function ToString: String;
+    procedure Clear;
+    procedure Copy(const Src: TLineInfo);
+  end;
+
+implementation
+
+constructor TLineInfo.Create;
+begin
+    AbonType := atStandard;
+    CompType := ctStandard;
+    TargetType := ttAll;
+end;
+
+function TLineInfo.ToString: String;
+var
+    dst: String;
+begin
+    case AbonType of
+        atStandard:    dst := '\92Ê\8fí\82 \82Ú\81[\82ñ\81E';
+        stTransparent: dst := '\93§\96¾\82 \82Ú\81[\82ñ\81E';
+        else           dst := '\81E';
+    end;
+    case CompType of
+        ctStandard:    dst := dst + '\92Ê\8fí\94ä\8ar\81E';
+        ctRegexp:      dst := dst + '\90³\8bK\95\\8c»\81E';
+        else           dst := dst + '\81E';
+    end;
+    case TargetType of
+        ttAll:         dst := dst + '\91S\83X\83\8c\91Î\8fÛ';
+        ttThread:      dst := dst + '\83X\83\8c\8ew\92è';
+        ttBoard:       dst := dst + '\94Â\8ew\92è';
+    end;
+    Result := dst;
+end;
+
+procedure TLineInfo.Clear;
+begin
+    AbonType     := atStandard;
+    CompType     := ctStandard;
+    TargetType   := ttAll;
+    TargetBoard  := '';
+    TargetThread := '';
+end;
+
+procedure TLineInfo.Copy(const Src: TLineInfo);
+begin
+    AbonType     := Src.AbonType;
+    CompType     := Src.CompType;
+    TargetType   := Src.TargetType;
+    TargetBoard  := Src.TargetBoard;
+    TargetThread := Src.TargetThread;
+end;
+
+end.
diff --git a/AbonInfoSet.dfm b/AbonInfoSet.dfm
new file mode 100644 (file)
index 0000000..fbd5be8
--- /dev/null
@@ -0,0 +1,133 @@
+object AbonInfoEdit: TAbonInfoEdit
+  Left = 192
+  Top = 133
+  BorderIcons = [biSystemMenu]
+  BorderStyle = bsDialog
+  Caption = 'NG'#12527#12540#12489#35373#23450
+  ClientHeight = 349
+  ClientWidth = 439
+  Color = clBtnFace
+  Font.Charset = SHIFTJIS_CHARSET
+  Font.Color = clWindowText
+  Font.Height = -12
+  Font.Name = #65325#65331' '#65328#12468#12471#12483#12463
+  Font.Style = []
+  OldCreateOrder = False
+  OnCreate = FormCreate
+  OnDestroy = FormDestroy
+  OnShow = FormShow
+  PixelsPerInch = 96
+  TextHeight = 12
+  object AbonTypeRadio: TRadioGroup
+    Left = 16
+    Top = 8
+    Width = 313
+    Height = 49
+    Caption = #12354#12412#12540#12435#31278#21029
+    Columns = 2
+    Items.Strings = (
+      #36890#24120#12354#12412#12540#12435
+      #36879#26126#12354#12412#12540#12435)
+    TabOrder = 0
+  end
+  object CompTypeRadio: TRadioGroup
+    Left = 16
+    Top = 64
+    Width = 313
+    Height = 49
+    Caption = #27604#36611#31278#21029
+    Columns = 2
+    Items.Strings = (
+      #36890#24120#27604#36611
+      #27491#35215#34920#29694)
+    TabOrder = 1
+  end
+  object GroupBox1: TGroupBox
+    Left = 16
+    Top = 120
+    Width = 409
+    Height = 177
+    Caption = #12354#12412#12540#12435#23550#35937
+    TabOrder = 2
+    object AllRadio: TRadioButton
+      Left = 9
+      Top = 20
+      Width = 113
+      Height = 17
+      Caption = #20840#12473#12524#23550#35937
+      TabOrder = 0
+      OnClick = TargetRadioClick
+    end
+    object ThreadRadio: TRadioButton
+      Left = 9
+      Top = 42
+      Width = 113
+      Height = 17
+      Caption = #12473#12524#25351#23450
+      Enabled = False
+      TabOrder = 1
+      OnClick = TargetRadioClick
+    end
+    object BoardRadio: TRadioButton
+      Left = 9
+      Top = 106
+      Width = 113
+      Height = 17
+      Caption = #26495#25351#23450
+      Enabled = False
+      TabOrder = 2
+      OnClick = TargetRadioClick
+    end
+    object ThrNameEdit: TEdit
+      Left = 32
+      Top = 60
+      Width = 361
+      Height = 20
+      Color = clBtnFace
+      TabOrder = 3
+    end
+    object ThrInfoEdit: TEdit
+      Left = 32
+      Top = 80
+      Width = 361
+      Height = 20
+      Color = clBtnFace
+      TabOrder = 4
+    end
+    object BrdNameEdit: TEdit
+      Left = 32
+      Top = 124
+      Width = 361
+      Height = 20
+      Color = clBtnFace
+      TabOrder = 5
+    end
+    object BrdInfoEdit: TEdit
+      Left = 32
+      Top = 144
+      Width = 361
+      Height = 20
+      Color = clBtnFace
+      TabOrder = 6
+    end
+  end
+  object OkButton: TButton
+    Left = 128
+    Top = 312
+    Width = 75
+    Height = 25
+    Caption = 'OK'
+    TabOrder = 3
+    OnClick = OkButtonClick
+  end
+  object CancelButton: TButton
+    Left = 240
+    Top = 312
+    Width = 75
+    Height = 25
+    Cancel = True
+    Caption = #12461#12515#12531#12475#12523
+    ModalResult = 2
+    TabOrder = 4
+  end
+end
diff --git a/AbonInfoSet.pas b/AbonInfoSet.pas
new file mode 100644 (file)
index 0000000..4a86e47
--- /dev/null
@@ -0,0 +1,146 @@
+unit AbonInfoSet;
+
+interface
+
+uses
+  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
+  Dialogs, AbonInfo, StdCtrls, ExtCtrls;
+
+type
+  TAbonInfoEdit = class(TForm)
+    AbonTypeRadio: TRadioGroup;
+    CompTypeRadio: TRadioGroup;
+    GroupBox1: TGroupBox;
+    AllRadio: TRadioButton;
+    ThreadRadio: TRadioButton;
+    BoardRadio: TRadioButton;
+    ThrNameEdit: TEdit;
+    ThrInfoEdit: TEdit;
+    BrdNameEdit: TEdit;
+    BrdInfoEdit: TEdit;
+    OkButton: TButton;
+    CancelButton: TButton;
+    procedure FormShow(Sender: TObject);
+    procedure TargetRadioClick(Sender: TObject);
+    procedure OkButtonClick(Sender: TObject);
+    procedure FormCreate(Sender: TObject);
+    procedure FormDestroy(Sender: TObject);
+  private
+    { Private \90é\8c¾ }
+    FInf: TLineInfo;
+  public
+    { Public \90é\8c¾ }
+
+    procedure SetInfo(const src: TLineInfo);
+    procedure GetInfo(var dst: TLineInfo);
+  end;
+
+var
+  AbonInfoEdit: TAbonInfoEdit;
+
+implementation
+
+{$R *.dfm}
+
+
+procedure TAbonInfoEdit.FormCreate(Sender: TObject);
+var
+    CenterForm: TCustomForm;
+begin
+    CenterForm := TCustomForm(Owner);
+    if Assigned(CenterForm) then begin
+        Left := ((CenterForm.Width - Width) div 2) + CenterForm.Left;
+        Top := ((CenterForm.Height - Height) div 2) + CenterForm.Top;
+    end else begin
+        Left := (Screen.Width - Width) div 2;
+        Top := (Screen.Height - Height) div 2;
+    end;
+
+    FInf := TLineInfo.Create;
+end;
+
+procedure TAbonInfoEdit.FormDestroy(Sender: TObject);
+begin
+    FInf.Free;
+end;
+
+procedure TAbonInfoEdit.SetInfo(const src: TLineInfo);
+begin
+    FInf.Copy(src);
+end;
+
+procedure TAbonInfoEdit.GetInfo(var dst: TLineInfo);
+begin
+    dst.Copy(FInf);
+end;
+
+procedure TAbonInfoEdit.FormShow(Sender: TObject);
+begin
+    case FInf.AbonType of
+        atStandard:    AbonTypeRadio.ItemIndex := 0;
+        stTransparent: AbonTypeRadio.ItemIndex := 1;
+    end;
+
+    case FInf.CompType of
+        ctStandard: CompTypeRadio.ItemIndex := 0;
+        ctRegexp:   CompTypeRadio.ItemIndex := 1;
+    end;
+
+    case FInf.TargetType of
+        ttAll:    AllRadio.Checked    := True;
+        ttThread: ThreadRadio.Checked := True;
+        ttBoard:  BoardRadio.Checked  := True;
+    end;
+
+    ThrInfoEdit.Text := FInf.TargetThread;
+    BrdInfoEdit.Text := FInf.TargetBoard;
+
+    TargetRadioClick(AllRadio);
+end;
+
+procedure TAbonInfoEdit.TargetRadioClick(Sender: TObject);
+begin
+    if (ThreadRadio.Checked = True) then begin
+        ThrNameEdit.Enabled := True;
+        ThrInfoEdit.Enabled := True;
+        BrdNameEdit.Enabled := False;
+        BrdInfoEdit.Enabled := False;
+    end else if (BoardRadio.Checked = True) then begin
+        ThrNameEdit.Enabled := False;
+        ThrInfoEdit.Enabled := False;
+        BrdNameEdit.Enabled := True;
+        BrdInfoEdit.Enabled := True;
+    end else begin
+        ThrNameEdit.Enabled := False;
+        ThrInfoEdit.Enabled := False;
+        BrdNameEdit.Enabled := False;
+        BrdInfoEdit.Enabled := False;
+    end;
+end;
+
+procedure TAbonInfoEdit.OkButtonClick(Sender: TObject);
+begin
+    if (AbonTypeRadio.ItemIndex = 1) then
+        FInf.AbonType := stTransparent
+    else
+        FInf.AbonType := atStandard;
+
+    if (CompTypeRadio.ItemIndex = 1) then
+        FInf.CompType := ctRegexp
+    else
+        FInf.CompType := ctStandard;
+
+    if (ThreadRadio.Checked = True) then
+        FInf.TargetType := ttThread
+    else if (BoardRadio.Checked = True) then
+        FInf.TargetType := ttBoard
+    else
+        FInf.TargetType := ttAll;
+
+    FInf.TargetThread := ThrInfoEdit.Text;
+    FInf.TargetBoard  := BrdInfoEdit.Text;
+
+    ModalResult := mrOk;
+end;
+
+end.
index 7ed4958..a6a92f6 100644 (file)
@@ -7,7 +7,8 @@ unit AbonUnit;
 
 interface
 uses
-    Windows,Messages, ShellAPI, SysUtils, Classes,StdCtrls,StrUtils;
+    Windows,Messages, ShellAPI, SysUtils, Classes,StdCtrls,StrUtils,
+    Forms, Controls;
 
 type
        TIndiviAbon = class( TObject )
@@ -106,7 +107,7 @@ type
        procedure AddIndividualAbon( ResNum : Integer ; option : Integer; SetResNumFile : String);
        function CheckIndividualAbonList(ResNum : Integer) : Boolean;
 
-       procedure EditNGwords();  //NGword.txt\82ð\8aJ\82­\81B
+       function EditNGwords(Owner: TForm): Boolean;  //NGword.txt\82ð\8aJ\82­\81B
        function ShowAllTokens() : String;  //\83f\83o\83b\83O\97p
        //--
        procedure GoHome();//List\82Ì\82P\8ds\96Ú\82ð\93Ç\82Þ
@@ -121,10 +122,13 @@ var
        Abon1 :TAbon;
 const
        NGwordListFileName : String = 'NGwords.list';
+    DEF_REGEXP:  String = '{{REGEXP}}';
 
 implementation
 
-uses MojuUtils, GikoSystem, GikoBayesian, Setting;
+uses MojuUtils, GikoSystem, GikoBayesian, Setting,
+  NgEditor,
+  bmRegExp;
 
 function InvidiAbonListSort( item1, item2 : Pointer ) : Integer;
 begin
@@ -375,8 +379,10 @@ var
        i : Integer;
        pos : Integer;
        buftoken : String;
+    RegExp: Boolean;
 begin
        bufstl := TStringList.Create;
+    RegExp := False;
        try
                if Length(argline) > 0 then begin
                        pos := AnsiPos(#9,argline);
@@ -384,6 +390,9 @@ begin
                                buftoken := Copy(argline,1,pos-1);
                                Delete(argline,1,pos);
                                if Length(buftoken) > 0 then begin
+                    if (buftoken = DEF_REGEXP) then begin
+                        RegExp := True;
+                    end else
                     // >> \82Å\8en\82Ü\82é\83g\81[\83N\83\93\82Í\83R\83\81\83\93\83g\88µ\82¢\82Å\96³\8e\8b\82·\82é
                     if AnsiPos('>>', buftoken) <> 1 then begin
                                        bufstl.Append(buftoken);
@@ -400,12 +409,30 @@ begin
                 end;
                        end;
                        ret := bufstl.Count;
+            if (RegExp = True) then
+                ret := ret + 1;
                        SetLength(Ftokens[index],ret);
-                       for i := 0 to bufstl.Count - 1  do begin
-                               if IgnoreKana then
-                                       Ftokens[index][i] := ZenToHan(bufstl.Strings[i])
-                               else
-                    Ftokens[index][i] := bufstl.Strings[i];
+                       for i := 0 to ret - 1  do begin
+                if (RegExp = True) then begin
+                    if (i = 0) then begin
+                        if (bufstl.Strings[0] = '') then
+                            Ftokens[index][0] := ''
+                        else
+                            Ftokens[index][0] := DEF_REGEXP;
+                    end else if (i = 1) then begin
+                        if (bufstl.Strings[0] = '') then
+                            Ftokens[index][1] := DEF_REGEXP
+                        else
+                            Ftokens[index][1] := bufstl.Strings[0];
+                    end else begin
+                        Ftokens[index][i] := bufstl.Strings[i - 1];
+                    end;
+                end else begin
+                    if IgnoreKana then
+                        Ftokens[index][i] := ZenToHan(bufstl.Strings[i])
+                    else
+                        Ftokens[index][i] := bufstl.Strings[i];
+                end;
                        end;
                end;
        finally
@@ -443,6 +470,10 @@ var
        pos : PChar;
        pts, pte : PChar;
        trgLen : Integer;
+    RegExp: Boolean;
+    AWKStr: TAWKStr;
+       RStart: Integer;
+       RLength: Integer;
 begin
        hit := false;
        if AnsiStrPosEx(PChar(line), PChar(line)+Length(line), FpAbons, FpAbone) = nil then begin
@@ -453,6 +484,8 @@ begin
                        target := line;
 
                trgLen := Length(target);
+        RegExp := False;
+        AWKStr := nil;
 
                for lines := 0 to High(Ftokens) do begin
             if Length(Ftokens[lines]) = 0 then begin
@@ -465,29 +498,58 @@ begin
 
                        if Ftokens[lines][0] <> ''  then begin
                                Invisible := false;
-                               start := 0;
+                if (Ftokens[lines][0] = DEF_REGEXP) then begin
+                    RegExp := True;
+                               start := 1;
+                end else begin
+                               start := 0;
+                end;
                        end else begin
                                Invisible := true;
-                               start := 1;
+                if (High(Ftokens) > 0) and (Ftokens[lines][1] = DEF_REGEXP) then begin
+                    RegExp := True;
+                               start := 2;
+                end else begin
+                               start := 1;
+                end;
                        end;
 
+            if (RegExp = True) and (AWKStr = nil) then begin
+               AWKStr := TAWKStr.Create(nil);
+            end;
+
                        for cells := start to High(Ftokens[lines]) do begin
-                               pos := AnsiStrPosEx(pts, pte,
-                                               PChar(Ftokens[lines][cells]), PChar(Ftokens[lines][cells]) + Length(Ftokens[lines][cells]));
-                               if pos = nil then begin
-                                       hit := false;
-                                       break;
-                               end else begin
-                                       Delete(bufline, pos - pte + 1, Length(Ftokens[lines][cells]));
-                                       pts := PChar(bufline);
-                                       pte := pts + Length(bufline);
-                               end;
+                if (RegExp = False) then begin
+                    pos := AnsiStrPosEx(pts, pte,
+                            PChar(Ftokens[lines][cells]), PChar(Ftokens[lines][cells]) + Length(Ftokens[lines][cells]));
+                    if pos = nil then begin
+                        hit := false;
+                        break;
+                    end else begin
+                        Delete(bufline, pos - pte + 1, Length(Ftokens[lines][cells]));
+                        pts := PChar(bufline);
+                        pte := pts + Length(bufline);
+                    end;
+                end else begin
+                    try
+                        AWKStr.RegExp := Ftokens[lines][cells];
+                        if (AWKStr.Match(AWKStr.ProcessEscSeq(target), RStart, RLength) < 1) then
+                            hit := False;   // \83}\83b\83`\82µ\82È\82¢
+                       except
+                        hit := False;
+                    end;
+                    if (hit = False) then
+                        Break;      // 1\82Â\82Å\82à\83}\83b\83`\82µ\82È\82¢\8fê\8d\87\82Í\82 \82Ú\81[\82ñ\82µ\82È\82¢
+                end;
                        end;
                        if hit = true then begin
                                NGwordsLineNum := lines + 1;
                                break;
                        end;
                end;
+
+        if (AWKStr <> nil) then
+           FreeAndNil(AWKStr);
        end;
        Result := hit;
 end;
@@ -572,9 +634,28 @@ end;
 
 //****************************************************************************//
 //\8c»\8dÝ\83Z\83b\83g\82³\82ê\82Ä\82¢\82éNGword.txt\82ð\8aJ\82­
-procedure TAbon.EditNGwords();
+function TAbon.EditNGwords(Owner: TForm): Boolean;
+var
+    Dlg: TNgEdit;
+    ReLoad: Boolean;
 begin
-       ShellExecute(0 ,nil,PChar(FNGwordpath),nil,nil,SW_SHOW);
+    ReLoad := False;
+
+    if (GikoSys.Setting.NGTextEditor = False) then begin
+        Dlg := TNgEdit.Create(Owner);
+
+        Dlg.SetFilePath(FNGwordpath);
+        if (Dlg.ShowModal = mrOk) then begin
+            if (Dlg.GetReload = True) then
+                ReLoad := True;
+        end;
+
+        Dlg.Free;
+    end else begin
+           ShellExecute(0 ,nil,PChar(FNGwordpath),nil,nil,SW_SHOW);
+    end;
+
+    Result := ReLoad;
 end;
 //\83|\83b\83v\83A\83b\83v\97p\94»\92è\8aÖ\90\94
 function TAbon.CheckAbonPopupRes(line : String) :Boolean;
index 464417e..a39a11f 100644 (file)
@@ -573,7 +573,8 @@ end;
 procedure TGikoDM.EditNGActionExecute(Sender: TObject);
 begin
        //\83e\83L\83X\83g\82É\8aÖ\98A\95t\82¯\82ç\82ê\82½\83A\83v\83\8a\82ÅNG\83\8f\81[\83h\83t\83@\83C\83\8b\82ð\83I\81[\83v\83\93
-       GikoSys.FAbon.EditNGwords;
+       if (GikoSys.FAbon.EditNGwords(GikoForm) = True) then
+        ReloadAction.Execute;
 end;
 // *************************************************************************
 //! NG\83\8f\81[\83h\93Ç\82Ý\8d\9e\82Ý\81i\8dÄ\93Ç\82Ý\8d\9e\82Ý\81j
index 4c87fb0..1bf4a86 100644 (file)
@@ -287,6 +287,7 @@ begin
        Result := CustomStringReplace(Result, '>', '\81\84');
        Result := CustomStringReplace(Result, '<', '\81\83');
        Result := CustomStringReplace(Result, '|', '\81b');
+       Result := CustomStringReplace(Result, #9,  '');
 end;
 (*************************************************************************
  * \96³\8cø\82ÈID\82©\82Ì\83`\83F\83b\83N\81i\96³\8cø\97á\81FID:??? , ID:???X)
diff --git a/NgEditor.dfm b/NgEditor.dfm
new file mode 100644 (file)
index 0000000..b3270b9
--- /dev/null
@@ -0,0 +1,245 @@
+object NgEdit: TNgEdit
+  Left = 192
+  Top = 133
+  Width = 845
+  Height = 478
+  BorderIcons = [biSystemMenu, biMaximize]
+  Caption = 'NG'#12527#12540#12489#32232#38598
+  Color = clBtnFace
+  Constraints.MinHeight = 300
+  Constraints.MinWidth = 845
+  Font.Charset = SHIFTJIS_CHARSET
+  Font.Color = clWindowText
+  Font.Height = -12
+  Font.Name = #65325#65331' '#65328#12468#12471#12483#12463
+  Font.Style = []
+  OldCreateOrder = False
+  OnCreate = FormCreate
+  OnDestroy = FormDestroy
+  OnShow = FormShow
+  PixelsPerInch = 96
+  TextHeight = 12
+  object PanelTop: TPanel
+    Left = 0
+    Top = 0
+    Width = 829
+    Height = 41
+    Align = alTop
+    BevelOuter = bvNone
+    TabOrder = 1
+    object SetInfButton: TButton
+      Left = 8
+      Top = 8
+      Width = 81
+      Height = 25
+      Action = SetInfAction
+      TabOrder = 0
+    end
+    object InsRowButton: TButton
+      Left = 96
+      Top = 8
+      Width = 113
+      Height = 25
+      Action = InsRowAction
+      TabOrder = 1
+    end
+    object AddRowButton: TButton
+      Left = 216
+      Top = 8
+      Width = 105
+      Height = 25
+      Action = AddRowAction
+      TabOrder = 2
+    end
+    object DelRowButton: TButton
+      Left = 328
+      Top = 8
+      Width = 129
+      Height = 25
+      Action = DelRowAction
+      TabOrder = 3
+    end
+    object AddColButton: TButton
+      Left = 464
+      Top = 8
+      Width = 105
+      Height = 25
+      Action = AddColAction
+      TabOrder = 4
+    end
+    object DelColButton: TButton
+      Left = 576
+      Top = 8
+      Width = 129
+      Height = 25
+      Action = DelColAction
+      TabOrder = 5
+    end
+    object RegExpButton: TButton
+      Left = 720
+      Top = 8
+      Width = 97
+      Height = 25
+      Action = RegExpAction
+      TabOrder = 6
+    end
+  end
+  object PanelBottom: TPanel
+    Left = 0
+    Top = 399
+    Width = 829
+    Height = 41
+    Align = alBottom
+    BevelOuter = bvNone
+    TabOrder = 2
+    object ButtonOk: TButton
+      Left = 256
+      Top = 8
+      Width = 75
+      Height = 25
+      Caption = 'OK'
+      TabOrder = 0
+      OnClick = ButtonOkClick
+    end
+    object ButtonReload: TButton
+      Left = 352
+      Top = 8
+      Width = 113
+      Height = 25
+      Caption = 'OK('#20877#35501#12415#36796#12415')'
+      TabOrder = 1
+      OnClick = ButtonReloadClick
+    end
+    object ButtonCancel: TButton
+      Left = 488
+      Top = 8
+      Width = 75
+      Height = 25
+      Caption = #12461#12515#12531#12475#12523
+      ModalResult = 2
+      TabOrder = 2
+    end
+  end
+  object NgWordGrid: TStringGrid
+    Left = 0
+    Top = 41
+    Width = 829
+    Height = 358
+    Align = alClient
+    ColCount = 4
+    Ctl3D = True
+    DefaultColWidth = 200
+    DefaultRowHeight = 19
+    FixedCols = 2
+    RowCount = 10
+    Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goDrawFocusSelected, goColSizing, goEditing]
+    ParentCtl3D = False
+    TabOrder = 0
+    OnMouseUp = NgWordGridMouseUp
+  end
+  object GridMenu: TPopupMenu
+    Left = 88
+    Top = 288
+    object MnStdAbn: TMenuItem
+      Caption = #27161#28310#12354#12412#12540#12435
+      OnClick = MnStdAbnClick
+    end
+    object MnTrnAbn: TMenuItem
+      Caption = #36879#26126#12354#12412#12540#12435
+      OnClick = MnTrnAbnClick
+    end
+    object N1: TMenuItem
+      Caption = '-'
+    end
+    object MnStdCmp: TMenuItem
+      Caption = #36890#24120#27604#36611
+      OnClick = MnStdCmpClick
+    end
+    object MnRegexp: TMenuItem
+      Caption = #27491#35215#34920#29694
+      OnClick = MnRegexpClick
+    end
+    object N2: TMenuItem
+      Caption = '-'
+    end
+    object MnAllThr: TMenuItem
+      Caption = #20840#12473#12524#23550#35937
+      Checked = True
+      Enabled = False
+    end
+    object MnSpcThr: TMenuItem
+      Caption = #12473#12524#25351#23450'...'
+      Enabled = False
+    end
+    object MnSpcBrd: TMenuItem
+      Caption = #26495#25351#23450'...'
+      Enabled = False
+    end
+    object N3: TMenuItem
+      Caption = '-'
+    end
+    object MnInsRow: TMenuItem
+      Action = InsRowAction
+    end
+    object MnAddRow: TMenuItem
+      Action = AddRowAction
+    end
+    object MnDelRow: TMenuItem
+      Action = DelRowAction
+    end
+    object N4: TMenuItem
+      Caption = '-'
+    end
+    object MnAddCol: TMenuItem
+      Action = AddColAction
+    end
+    object MnDelCol: TMenuItem
+      Action = DelColAction
+    end
+    object N5: TMenuItem
+      Caption = '-'
+    end
+    object MnRegExpTest: TMenuItem
+      Action = RegExpAction
+    end
+  end
+  object ActionList: TActionList
+    Left = 144
+    Top = 296
+    object AddRowAction: TAction
+      Category = #12464#12522#12483#12489
+      Caption = #19968#30058#19979#12395#34892#36861#21152
+      OnExecute = AddRowActionExecute
+    end
+    object AddColAction: TAction
+      Category = #12464#12522#12483#12489
+      Caption = #19968#30058#21491#12395#21015#36861#21152
+      OnExecute = AddColActionExecute
+    end
+    object InsRowAction: TAction
+      Category = #12464#12522#12483#12489
+      Caption = #36984#25246#20301#32622#12395#34892#25407#20837
+      OnExecute = InsRowActionExecute
+    end
+    object DelColAction: TAction
+      Category = #12464#12522#12483#12489
+      Caption = #36984#25246#21015#65288#32294#26041#21521#65289#21066#38500
+      OnExecute = DelColActionExecute
+    end
+    object DelRowAction: TAction
+      Category = #12464#12522#12483#12489
+      Caption = #36984#25246#34892#65288#27178#26041#21521#65289#21066#38500
+      OnExecute = DelRowActionExecute
+    end
+    object RegExpAction: TAction
+      Category = #35373#23450
+      Caption = #27491#35215#34920#29694#12486#12473#12488
+      OnExecute = RegExpActionExecute
+    end
+    object SetInfAction: TAction
+      Category = #35373#23450
+      Caption = #36984#25246#34892#35373#23450
+      OnExecute = SetInfActionExecute
+    end
+  end
+end
diff --git a/NgEditor.pas b/NgEditor.pas
new file mode 100644 (file)
index 0000000..bb9b6db
--- /dev/null
@@ -0,0 +1,677 @@
+unit NgEditor;
+
+interface
+
+uses
+  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
+  Dialogs, Grids, ExtCtrls, StdCtrls, Menus, ActnList, AbonInfo;
+
+type
+  TNgEdit = class(TForm)
+    PanelTop: TPanel;
+    PanelBottom: TPanel;
+    NgWordGrid: TStringGrid;
+    ButtonOk: TButton;
+    ButtonReload: TButton;
+    ButtonCancel: TButton;
+    GridMenu: TPopupMenu;
+    MnStdAbn: TMenuItem;
+    MnTrnAbn: TMenuItem;
+    N1: TMenuItem;
+    MnStdCmp: TMenuItem;
+    MnRegexp: TMenuItem;
+    N2: TMenuItem;
+    MnAllThr: TMenuItem;
+    MnSpcThr: TMenuItem;
+    MnSpcBrd: TMenuItem;
+    N3: TMenuItem;
+    MnInsRow: TMenuItem;
+    MnAddRow: TMenuItem;
+    MnDelRow: TMenuItem;
+    SetInfButton: TButton;
+    InsRowButton: TButton;
+    AddRowButton: TButton;
+    DelRowButton: TButton;
+    AddColButton: TButton;
+    DelColButton: TButton;
+    RegExpButton: TButton;
+    ActionList: TActionList;
+    AddRowAction: TAction;
+    AddColAction: TAction;
+    InsRowAction: TAction;
+    DelColAction: TAction;
+    DelRowAction: TAction;
+    RegExpAction: TAction;
+    SetInfAction: TAction;
+    N4: TMenuItem;
+    MnAddCol: TMenuItem;
+    MnDelCol: TMenuItem;
+    N5: TMenuItem;
+    MnRegExpTest: TMenuItem;
+    procedure FormCreate(Sender: TObject);
+    procedure NgWordGridMouseUp(Sender: TObject; Button: TMouseButton;
+      Shift: TShiftState; X, Y: Integer);
+    procedure FormDestroy(Sender: TObject);
+    procedure ButtonOkClick(Sender: TObject);
+    procedure ButtonReloadClick(Sender: TObject);
+    procedure FormShow(Sender: TObject);
+    procedure AddRowActionExecute(Sender: TObject);
+    procedure AddColActionExecute(Sender: TObject);
+    procedure InsRowActionExecute(Sender: TObject);
+    procedure DelColActionExecute(Sender: TObject);
+    procedure DelRowActionExecute(Sender: TObject);
+    procedure RegExpActionExecute(Sender: TObject);
+    procedure SetInfActionExecute(Sender: TObject);
+    procedure MnStdAbnClick(Sender: TObject);
+    procedure MnTrnAbnClick(Sender: TObject);
+    procedure MnStdCmpClick(Sender: TObject);
+    procedure MnRegexpClick(Sender: TObject);
+  private
+    { Private \90é\8c¾ }
+    FInfoList: TList;
+    FFilePath: String;
+    FReload: Boolean;
+
+    procedure Load;
+    procedure Save;
+    procedure ClearInfo;
+    procedure DeleteInfo(Index: Integer);
+    function ParseLine(const Line: String; var NgList: TStringList): TLineInfo;
+    procedure DspLineNo(Row: Integer);
+  public
+    { Public \90é\8c¾ }
+    procedure SetFilePath(FilePath: String);
+    function GetReload: Boolean;
+  end;
+
+var
+  NgEdit: TNgEdit;
+const
+    DEF_COMMENT: String = '>>';
+    DEF_REGEXP:  String = '{{REGEXP}}';
+    DEF_THREAD:  String = '{{THREAD:';
+    DEF_BOARD:   String = '{{BOARD:';
+    DEF_END:     String = '}}';
+
+implementation
+
+uses RegExpTester, AbonInfoSet, GikoSystem, MojuUtils;
+
+{$R *.dfm}
+
+
+procedure TNgEdit.FormCreate(Sender: TObject);
+begin
+    FInfoList := TList.Create;
+    FReload := False;
+
+    Left   := GikoSys.Setting.NGWindowLeft;
+    Top    := GikoSys.Setting.NGWindowTop;
+    Width  := GikoSys.Setting.NGWindowWidth;
+    Height := GikoSys.Setting.NGWindowHeight;
+    if (GikoSys.Setting.NGWindowMax = False) then
+        WindowState := wsNormal
+    else
+        WindowState := wsMaximized;
+end;
+
+procedure TNgEdit.FormDestroy(Sender: TObject);
+begin
+    ClearInfo;
+    FInfoList.Free;
+
+    GikoSys.Setting.NGWindowLeft   := Left;
+    GikoSys.Setting.NGWindowTop    := Top;
+    GikoSys.Setting.NGWindowWidth  := Width;
+    GikoSys.Setting.NGWindowHeight := Height;
+    if (WindowState = wsMaximized) then
+        GikoSys.Setting.NGWindowMax := True
+    else
+        GikoSys.Setting.NGWindowMax := False;
+end;
+
+procedure TNgEdit.SetFilePath(FilePath: String);
+begin
+    FFilePath := FilePath;
+end;
+
+procedure TNgEdit.FormShow(Sender: TObject);
+var
+    inf: TLineInfo;
+    Col: Integer;
+begin
+    FReload := False;
+
+    NgWordGrid.RowCount := 2;
+    NgWordGrid.ColCount := 3;
+    NgWordGrid.ColWidths[0] := 27;
+    NgWordGrid.ColWidths[1] := 200;
+    NgWordGrid.Cells[0, 0] := 'No.';
+    NgWordGrid.Cells[1, 0] := '\90Ý\92è';
+    NgWordGrid.Cells[0, 1] := '   1';
+    NgWordGrid.Cells[1, 1] := '';
+    NgWordGrid.Cells[2, 1] := '';
+
+    Load;
+
+    for Col := 2 to NgWordGrid.ColCount - 1 do
+        NgWordGrid.Cells[Col, 0] := 'NG\83\8f\81[\83h' + IntToStr(Col - 1);
+
+    if (FInfoList.Count = 0) then begin
+        inf := TLineInfo.Create;
+        FInfoList.Add(inf);
+        NgWordGrid.Cells[1, 1] := inf.ToString;
+    end;
+end;
+
+function TNgEdit.GetReload: Boolean;
+begin
+    Result := FReload;
+end;
+
+procedure TNgEdit.Load;
+var
+    text: TStringList;
+    line: TStringList;
+    msg: String;
+    idx: Integer;
+    max_line: Integer;
+    inf: TLineInfo;
+    Row: Integer;
+    Col: Integer;
+    ColCnt: Integer;
+begin
+    if (FFilePath = '') or (FileExists(FFilePath) = False) then
+        Exit;
+
+    text := TStringList.Create;
+    line := TStringList.Create;
+
+    ClearInfo;
+
+    try
+        text.LoadFromFile(FFilePath);
+
+        max_line := text.Count - 1;
+        Row := 1;
+
+        for idx := 0 to max_line do begin
+            inf := ParseLine(text.Strings[idx], line);
+            if (inf <> nil) then begin
+                FInfoList.Add(inf);
+
+                ColCnt := line.Count + 2;
+                if (NgWordGrid.ColCount < ColCnt) then
+                    NgWordGrid.ColCount := ColCnt;
+
+                if (NgWordGrid.RowCount <= Row) then
+                    NgWordGrid.RowCount := Row + 1;
+
+                DspLineNo(Row);
+                NgWordGrid.Cells[1, Row] := inf.ToString;
+                for Col := 2 to (ColCnt - 1) do begin
+                    NgWordGrid.Cells[Col, Row] := line.Strings[Col - 2];
+                end;
+
+                Row := Row + 1;
+            end;
+        end;
+
+    except
+        on e: Exception do begin
+            msg := 'NG\83\8f\81[\83h\83t\83@\83C\83\8b\82Ì\93Ç\82Ý\8d\9e\82Ý\82Å\83G\83\89\81[\82ª\94­\90\82µ\82Ü\82µ\82½\81B' + #10 + e.Message;
+            Application.MessageBox(PChar(msg), 'NG\83\8f\81[\83h\95Ò\8fW', MB_OK or MB_ICONERROR);
+        end;
+    end;
+
+    text.Free;
+    line.Free;
+end;
+
+procedure TNgEdit.DspLineNo(Row: Integer);
+var
+    CellStr: String;
+begin
+    CellStr := '   ' + IntToStr(Row);
+    NgWordGrid.Cells[0, Row] := Copy(CellStr, Length(CellStr) - 3, 4);
+end;
+
+procedure TNgEdit.Save;
+var
+    Row: Integer;
+    Col: Integer;
+    RowMax: Integer;
+    ColMax: Integer;
+    Line: String;
+    text: TStringList;
+    inf: TLineInfo;
+    msg: String;
+begin
+    if (FFilePath = '') then
+        Exit;
+
+    text := TStringList.Create;
+    RowMax := NgWordGrid.RowCount - 1;
+    ColMax := NgWordGrid.ColCount - 1;
+
+    for Row := 1 to RowMax do begin
+        Line := '';
+        for Col := 2 to ColMax do begin
+            if (NgWordGrid.Cells[Col, Row] <> '') then begin
+                if (Line <> '') then
+                    Line := Line + #9;
+                Line := Line + CustomStringReplace(NgWordGrid.Cells[Col, Row], #13#10, '');
+            end;
+        end;
+        if (Line <> '') then begin
+            if (FInfoList.Count >= Row) then begin
+                inf := TLineInfo(FInfoList.Items[Row - 1]);
+
+                if (inf.CompType = ctRegexp) then
+                    Line := DEF_REGEXP + #9 + Line;
+
+                case inf.TargetType of
+                    ttThread: Line := DEF_THREAD + inf.TargetThread + DEF_END + #9 + Line;
+                    ttBoard:  Line := DEF_BOARD  + inf.TargetBoard  + DEF_END + #9 + Line;
+                end;
+
+                if (inf.AbonType = stTransparent) then
+                    Line := #9 + Line;
+            end;
+
+            text.Add(Line);
+        end;
+    end;
+
+    try
+        text.SaveToFile(FFilePath);
+    except
+        on e: Exception do begin
+            msg := 'NG\83\8f\81[\83h\83t\83@\83C\83\8b\82Ö\82Ì\95Û\91\82Å\83G\83\89\81[\82ª\94­\90\82µ\82Ü\82µ\82½\81B' + #10 + e.Message;
+            Application.MessageBox(PChar(msg), 'NG\83\8f\81[\83h\95Ò\8fW', MB_OK or MB_ICONERROR);
+        end;
+    end;
+
+    text.Free;
+end;
+
+function TNgEdit.ParseLine(const Line: String; var NgList: TStringList): TLineInfo;
+var
+    src: String;
+    inf: TLineInfo;
+    idx: Integer;
+    len: Integer;
+    NgWd: String;
+begin
+    NgList.Clear;
+
+    src := Line;
+    if (src = '') then begin
+        Result := nil;
+        Exit;
+    end;
+
+    inf := TLineInfo.Create;
+
+    if (src[1] = #9) then begin
+        inf.AbonType := stTransparent;
+        Delete(src, 1, 1);
+    end;
+
+    while (src <> '') do begin
+        idx := Pos(#9, src);
+        if (idx > 0) then begin
+            NgWd := Copy(src, 1, idx - 1);
+            Delete(src, 1, idx);
+        end else begin
+            NgWd := src;
+            src := '';
+        end;
+
+        if (NgWd = DEF_REGEXP) then begin
+            inf.CompType := ctRegexp;
+        end else if (Pos(DEF_THREAD, NgWd) = 1) then begin
+            idx := Pos(DEF_END, NgWd);
+            if (idx > 1) then begin
+                len := idx - Length(DEF_THREAD) - 1;
+                inf.TargetThread := Copy(NgWd, Length(DEF_THREAD) + 1, len);
+            end else begin
+                NgList.Add(NgWd);
+            end;
+        end else if (Pos(DEF_BOARD, NgWd) = 1) then begin
+            idx := Pos(DEF_END, NgWd);
+            if (idx > 1) then begin
+                len := idx - Length(DEF_BOARD) - 1;
+                inf.TargetBoard := Copy(NgWd, Length(DEF_BOARD) + 1, len);
+            end else begin
+                NgList.Add(NgWd);
+            end;
+        end else if (NgWd <> '') then begin
+            NgList.Add(NgWd);
+        end;
+    end;
+
+    Result := inf;
+end;
+
+procedure TNgEdit.ClearInfo;
+begin
+    while (FInfoList.Count > 0) do begin
+        TLineInfo(FInfoList.Items[0]).Free;
+        FInfoList.Delete(0);
+    end;
+end;
+
+procedure TNgEdit.DeleteInfo(Index: Integer);
+begin
+    if (Index >= 0) and (Index < FInfoList.Count) then begin
+        TLineInfo(FInfoList.Items[Index]).Free;
+        FInfoList.Delete(Index);
+    end;
+end;
+
+procedure TNgEdit.ButtonOkClick(Sender: TObject);
+begin
+    FReload := False;
+    Save;
+    ModalResult := mrOk;
+end;
+
+procedure TNgEdit.ButtonReloadClick(Sender: TObject);
+begin
+    FReload := True;
+    Save;
+    ModalResult := mrOk;
+end;
+
+procedure TNgEdit.AddRowActionExecute(Sender: TObject);
+var
+    Row: Integer;
+    Col: Integer;
+    inf: TLineInfo;
+begin
+    Row := NgWordGrid.RowCount;
+    NgWordGrid.RowCount := NgWordGrid.RowCount + 1;
+
+    DspLineNo(Row);
+
+    inf := TLineInfo.Create;
+    FInfoList.Add(inf);
+    NgWordGrid.Cells[1, Row] := inf.ToString;
+
+    for Col := 2 to NgWordGrid.ColCount - 1 do begin
+        NgWordGrid.Cells[Col, Row] := '';
+    end;
+
+    NgWordGrid.Row := Row;
+end;
+
+procedure TNgEdit.AddColActionExecute(Sender: TObject);
+var
+    Row: Integer;
+    Col: Integer;
+begin
+    Col := NgWordGrid.ColCount;
+    NgWordGrid.ColCount := NgWordGrid.ColCount + 1;
+
+    NgWordGrid.Cells[Col, 0] := 'NG\83\8f\81[\83h' + IntToStr(Col - 1);
+    for Row := 1 to NgWordGrid.RowCount - 1 do begin
+        NgWordGrid.Cells[Col, Row] := '';
+    end;
+
+    NgWordGrid.Col := Col;
+end;
+
+procedure TNgEdit.InsRowActionExecute(Sender: TObject);
+var
+    RowMax: Integer;
+    RowMin: Integer;
+    RowIns: Integer;
+    Row: Integer;
+    Col: Integer;
+    inf: TLineInfo;
+begin
+    if (NgWordGrid.Row <= 0) or (NgWordGrid.Row >= NgWordGrid.RowCount) then
+        Exit;
+
+    RowIns := NgWordGrid.Row;
+    RowMin := NgWordGrid.Row + 1;
+    RowMax := NgWordGrid.RowCount;
+    NgWordGrid.RowCount := NgWordGrid.RowCount + 1;
+    DspLineNo(NgWordGrid.RowCount - 1);
+
+    for Row := RowMax downto RowMin do begin
+        for Col := 1 to NgWordGrid.ColCount - 1 do begin
+            NgWordGrid.Cells[Col, Row] := NgWordGrid.Cells[Col, (Row - 1)];
+        end;
+    end;
+
+    inf := TLineInfo.Create;
+    FInfoList.Insert(RowIns - 1, inf);
+    NgWordGrid.Cells[1, RowIns] := inf.ToString;
+
+    for Col := 2 to NgWordGrid.ColCount - 1 do begin
+        NgWordGrid.Cells[Col, RowIns] := '';
+    end;
+
+end;
+
+procedure TNgEdit.DelColActionExecute(Sender: TObject);
+var
+    ColDel: Integer;
+    ColMax: Integer;
+    ColMin: Integer;
+    Row: Integer;
+    Col: Integer;
+begin
+    if (NgWordGrid.ColCount <= 3) then
+        Exit;
+    if (NgWordGrid.Col <= 1) or (NgWordGrid.Col >= NgWordGrid.ColCount) then
+        Exit;
+
+    ColDel := NgWordGrid.Col;
+    for Row := 1 to NgWordGrid.RowCount - 1 do begin
+        if (NgWordGrid.Cells[ColDel, Row] <> '') then begin
+            if (Application.MessageBox('\91I\91ð\82³\82ê\82½\97ñ\82É\82ÍNG\83\8f\81[\83h\82ª\90Ý\92è\82³\82ê\82Ä\82¢\82Ü\82·\82ª\8dí\8f\9c\82µ\82Ä\82à\82æ\82ë\82µ\82¢\82Å\82·\82©\81H',
+                                        '\91I\91ð\97ñ\8dí\8f\9c', MB_YESNO or MB_ICONQUESTION) = IDYES) then
+                Break
+            else
+                Exit;
+        end;
+    end;
+
+    ColMin := ColDel;
+    ColMax := NgWordGrid.ColCount - 2;
+
+    for Row := 1 to NgWordGrid.RowCount - 1 do begin
+        for Col := ColMin to ColMax do begin
+            NgWordGrid.Cells[Col, Row] := NgWordGrid.Cells[Col + 1, Row];
+        end;
+    end;
+
+    NgWordGrid.ColCount := NgWordGrid.ColCount - 1;
+
+end;
+
+procedure TNgEdit.DelRowActionExecute(Sender: TObject);
+var
+    RowDel: Integer;
+    RowMin: Integer;
+    RowMax: Integer;
+    Row: Integer;
+    Col: Integer;
+    inf: TLineInfo;
+begin
+    if (NgWordGrid.Row <= 0) or (NgWordGrid.Row >= NgWordGrid.RowCount) then
+        Exit;
+
+    RowDel := NgWordGrid.Row;
+
+    for Col := 2 to NgWordGrid.ColCount - 1 do begin
+        if (NgWordGrid.Cells[Col, RowDel] <> '') then begin
+            if (Application.MessageBox('\91I\91ð\82³\82ê\82½\8ds\82É\82ÍNG\83\8f\81[\83h\82ª\90Ý\92è\82³\82ê\82Ä\82¢\82Ü\82·\82ª\8dí\8f\9c\82µ\82Ä\82à\82æ\82ë\82µ\82¢\82Å\82·\82©\81H',
+                                        '\91I\91ð\8ds\8dí\8f\9c', MB_YESNO or MB_ICONQUESTION) = IDYES) then
+                Break
+            else
+                Exit;
+        end;
+    end;
+
+    if (FInfoList.Count = 1) then begin
+        for Col := 1 to NgWordGrid.ColCount - 1 do begin
+            NgWordGrid.Cells[Col, 1] := '';
+        end;
+        DeleteInfo(RowDel - 1);
+        inf := TLineInfo.Create;
+        FInfoList.Add(inf);
+        NgWordGrid.Cells[1, 1] := inf.ToString;
+    end else begin
+        RowMin := RowDel;
+        RowMax := NgWordGrid.RowCount - 2;
+
+        for Row := RowMin to RowMax do begin
+            for Col := 1 to NgWordGrid.ColCount - 1 do begin
+                NgWordGrid.Cells[Col, Row] := NgWordGrid.Cells[Col, Row + 1];
+            end;
+        end;
+
+        NgWordGrid.RowCount := NgWordGrid.RowCount - 1;
+        DeleteInfo(RowDel - 1);
+    end;
+end;
+
+procedure TNgEdit.RegExpActionExecute(Sender: TObject);
+var
+    Dlg: TRegExpTest;
+    inf: TLineInfo;
+begin
+    Dlg := TRegExpTest.Create(Self);
+
+    if (NgWordGrid.Row > 0) and (NgWordGrid.Row < NgWordGrid.RowCount) and
+       (NgWordGrid.Col > 1) and (NgWordGrid.Col < NgWordGrid.ColCount) then begin
+        if (NgWordGrid.Cells[NgWordGrid.Col, NgWordGrid.Row] <> '') then begin
+            inf := TLineInfo(FInfoList.Items[NgWordGrid.Row - 1]);
+            if (inf.CompType = ctRegexp) then
+                Dlg.SetRegExp(NgWordGrid.Cells[NgWordGrid.Col, NgWordGrid.Row]);
+        end;
+    end;
+
+    Dlg.ShowModal;
+
+    Dlg.Free;
+end;
+
+procedure TNgEdit.SetInfActionExecute(Sender: TObject);
+var
+    inf: TLineInfo;
+    Dlg: TAbonInfoEdit;
+begin
+    if (NgWordGrid.Row <= 0) or (NgWordGrid.Row >= NgWordGrid.RowCount) then
+        Exit;
+
+    inf := TLineInfo(FInfoList.Items[NgWordGrid.Row - 1]);
+
+    Dlg := TAbonInfoEdit.Create(Self);
+    Dlg.SetInfo(inf);
+
+    if (Dlg.ShowModal = mrOk) then begin
+        Dlg.GetInfo(inf);
+        NgWordGrid.Cells[1, NgWordGrid.Row] := inf.ToString;
+    end;
+
+    Dlg.Free;
+end;
+
+procedure TNgEdit.NgWordGridMouseUp(Sender: TObject; Button: TMouseButton;
+  Shift: TShiftState; X, Y: Integer);
+var
+    Col: Integer;
+    Row: Integer;
+    MousePos: TPoint;
+    MenuPos: TPoint;
+    inf: TLineInfo;
+begin
+    if (Button = mbRight) then begin
+        NgWordGrid.MouseToCell(X, Y, Col, Row);
+        if (Col >= 0) and (Row > 0) then begin
+            inf := TLineInfo(FInfoList.Items[Row - 1]);
+            if (inf.AbonType = stTransparent) then begin
+                MnStdAbn.Checked := False;
+                MnTrnAbn.Checked := True;
+            end else begin
+                MnStdAbn.Checked := True;
+                MnTrnAbn.Checked := False;
+            end;
+            if (inf.CompType = ctRegexp) then begin
+                MnStdCmp.Checked := False;
+                MnRegexp.Checked := True;
+                if (Col > 1) then
+                    MnRegExpTest.Enabled := True
+                else
+                    MnRegExpTest.Enabled := False;
+            end else begin
+                MnStdCmp.Checked := True;
+                MnRegexp.Checked := False;
+                MnRegExpTest.Enabled := False;
+            end;
+            if (Col > 1) then
+                MnDelCol.Enabled := True
+            else
+                MnDelCol.Enabled := False;
+
+            NgWordGrid.Row := Row;
+            if (Col > 1) then
+                NgWordGrid.Col := Col;
+            MousePos.X := X + NgWordGrid.Left;
+            MousePos.Y := Y + NgWordGrid.Top;
+            MenuPos := Self.ClientToScreen(MousePos);
+            GridMenu.Popup(MenuPos.X, MenuPos.Y);
+        end;
+    end;
+end;
+
+procedure TNgEdit.MnStdAbnClick(Sender: TObject);
+var
+    inf: TLineInfo;
+begin
+    if (NgWordGrid.Row > 0) and (NgWordGrid.Row < NgWordGrid.RowCount) then begin
+        inf := TLineInfo(FInfoList.Items[NgWordGrid.Row - 1]);
+        inf.AbonType := atStandard;
+        NgWordGrid.Cells[1, NgWordGrid.Row] := inf.ToString;
+    end;
+end;
+
+procedure TNgEdit.MnTrnAbnClick(Sender: TObject);
+var
+    inf: TLineInfo;
+begin
+    if (NgWordGrid.Row > 0) and (NgWordGrid.Row < NgWordGrid.RowCount) then begin
+        inf := TLineInfo(FInfoList.Items[NgWordGrid.Row - 1]);
+        inf.AbonType := stTransparent;
+        NgWordGrid.Cells[1, NgWordGrid.Row] := inf.ToString;
+    end;
+end;
+
+procedure TNgEdit.MnStdCmpClick(Sender: TObject);
+var
+    inf: TLineInfo;
+begin
+    if (NgWordGrid.Row > 0) and (NgWordGrid.Row < NgWordGrid.RowCount) then begin
+        inf := TLineInfo(FInfoList.Items[NgWordGrid.Row - 1]);
+        inf.CompType := ctStandard;
+        NgWordGrid.Cells[1, NgWordGrid.Row] := inf.ToString;
+    end;
+end;
+
+procedure TNgEdit.MnRegexpClick(Sender: TObject);
+var
+    inf: TLineInfo;
+begin
+    if (NgWordGrid.Row > 0) and (NgWordGrid.Row < NgWordGrid.RowCount) then begin
+        inf := TLineInfo(FInfoList.Items[NgWordGrid.Row - 1]);
+        inf.CompType := ctRegexp;
+        NgWordGrid.Cells[1, NgWordGrid.Row] := inf.ToString;
+    end;
+end;
+
+end.
index 92a1609..e739d5b 100644 (file)
@@ -60,7 +60,7 @@ object OptionDialog: TOptionDialog
     Top = 4
     Width = 509
     Height = 389
-    ActivePage = TabSheet2
+    ActivePage = NGwordSheet
     MultiLine = True
     TabOrder = 3
     OnChange = OptionTabChange
@@ -1574,11 +1574,11 @@ object OptionDialog: TOptionDialog
       end
       object SpamFilterGroupBox: TGroupBox
         Left = 12
-        Top = 216
+        Top = 264
         Width = 477
         Height = 57
         Caption = #12473#12497#12512#12501#12451#12523#12479
-        TabOrder = 1
+        TabOrder = 2
         Visible = False
         object SpamFilterAlgorithmComboBox: TComboBox
           Left = 12
@@ -1595,6 +1595,22 @@ object OptionDialog: TOptionDialog
             #20351#29992#12377#12427)
         end
       end
+      object GroupBox28: TGroupBox
+        Left = 12
+        Top = 208
+        Width = 477
+        Height = 49
+        Caption = 'NG'#12527#12540#12489#32232#38598
+        TabOrder = 1
+        object NGTextEditCheckBox: TCheckBox
+          Left = 12
+          Top = 20
+          Width = 349
+          Height = 17
+          Caption = #12513#12514#24115#12394#12393#12398#12486#12461#12473#12488#12456#12487#12451#12479#12434#20351#29992#12377#12427'(&T)'
+          TabOrder = 0
+        end
+      end
     end
     object UserIDSheet: TTabSheet
       Caption = #65298#12385#12419#12435#12397#12427
index dd70f62..f1b0d88 100644 (file)
@@ -231,6 +231,8 @@ type
     DispImageCheckBox: TCheckBox;
     GroupBox27: TGroupBox;
     ThreadTitleTrimCheckBox: TCheckBox;
+    GroupBox28: TGroupBox;
+    NGTextEditCheckBox: TCheckBox;
                procedure FormCreate(Sender: TObject);
                procedure FormDestroy(Sender: TObject);
                procedure ApplyButtonClick(Sender: TObject);
@@ -884,6 +886,8 @@ begin
        AddResAnchorCheckBox.Checked := GikoSys.Setting.AddResAnchor;
        DeleteSyriaCheckBox.Checked := GikoSys.Setting.DeleteSyria;
        IgnoreKanaCheckBox.Checked := GikoSys.Setting.IgnoreKana;
+    //NG\83\8f\81[\83h\95Ò\8fW
+    NGTextEditCheckBox.Checked := GikoSys.Setting.NGTextEditor;
 {$IFDEF SPAM_FILTER_ENABLED}
        // \83X\83p\83\80\83t\83B\83\8b\83^\82Ì\90Ý\92è\82ð\95\\8e¦\82·\82é
        SpamFilterGroupBox.Visible := True;
@@ -1202,6 +1206,8 @@ begin
        GikoSys.Setting.DeleteSyria := DeleteSyriaCheckBox.Checked;
        GikoSys.Setting.IgnoreKana := IgnoreKanaCheckBox.Checked;
        GikoSys.FAbon.IgnoreKana := GikoSys.Setting.IgnoreKana;
+    //NG\83\8f\81[\83h\95Ò\8fW
+    GikoSys.Setting.NGTextEditor := NGTextEditCheckBox.Checked;
        // \8eg\97p\82·\82é\83X\83p\83\80\83t\83B\83\8b\83^
        if GikoSys.Setting.SpamFilterAlgorithm <> TGikoSpamFilterAlgorithm(
                SpamFilterAlgorithmComboBox.ItemIndex ) then begin
diff --git a/RegExpTester.dfm b/RegExpTester.dfm
new file mode 100644 (file)
index 0000000..872b47a
--- /dev/null
@@ -0,0 +1,66 @@
+object RegExpTest: TRegExpTest
+  Left = 192
+  Top = 133
+  BorderIcons = [biSystemMenu]
+  BorderStyle = bsDialog
+  Caption = #27491#35215#34920#29694#12486#12473#12488
+  ClientHeight = 112
+  ClientWidth = 666
+  Color = clBtnFace
+  Font.Charset = SHIFTJIS_CHARSET
+  Font.Color = clWindowText
+  Font.Height = -12
+  Font.Name = #65325#65331' '#65328#12468#12471#12483#12463
+  Font.Style = []
+  OldCreateOrder = False
+  OnCreate = FormCreate
+  OnShow = FormShow
+  PixelsPerInch = 96
+  TextHeight = 12
+  object Label1: TLabel
+    Left = 16
+    Top = 20
+    Width = 60
+    Height = 12
+    Caption = #23550#35937#25991#23383#21015
+  end
+  object Label2: TLabel
+    Left = 16
+    Top = 44
+    Width = 48
+    Height = 12
+    Caption = #27491#35215#34920#29694
+  end
+  object TargetEdit: TEdit
+    Left = 88
+    Top = 16
+    Width = 561
+    Height = 20
+    TabOrder = 0
+  end
+  object RegExpEdit: TEdit
+    Left = 88
+    Top = 40
+    Width = 561
+    Height = 20
+    TabOrder = 1
+  end
+  object TestButton: TButton
+    Left = 288
+    Top = 72
+    Width = 75
+    Height = 25
+    Caption = #12486#12473#12488
+    TabOrder = 2
+    OnClick = TestButtonClick
+  end
+  object CloseButton: TButton
+    Left = 576
+    Top = 72
+    Width = 75
+    Height = 25
+    Caption = #38281#12376#12427
+    ModalResult = 2
+    TabOrder = 3
+  end
+end
diff --git a/RegExpTester.pas b/RegExpTester.pas
new file mode 100644 (file)
index 0000000..70c6dc0
--- /dev/null
@@ -0,0 +1,91 @@
+unit RegExpTester;
+
+interface
+
+uses
+  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
+  Dialogs, StdCtrls;
+
+type
+  TRegExpTest = class(TForm)
+    Label1: TLabel;
+    TargetEdit: TEdit;
+    Label2: TLabel;
+    RegExpEdit: TEdit;
+    TestButton: TButton;
+    CloseButton: TButton;
+    procedure TestButtonClick(Sender: TObject);
+    procedure FormShow(Sender: TObject);
+    procedure FormCreate(Sender: TObject);
+  private
+    { Private \90é\8c¾ }
+    FRegExp: String;
+  public
+    { Public \90é\8c¾ }
+    procedure SetRegExp(const src: String);
+  end;
+
+var
+  RegExpTest: TRegExpTest;
+
+implementation
+
+uses bmRegExp;
+
+{$R *.dfm}
+
+
+procedure TRegExpTest.FormCreate(Sender: TObject);
+var
+    CenterForm: TCustomForm;
+begin
+    CenterForm := TCustomForm(Owner);
+    if Assigned(CenterForm) then begin
+        Left := ((CenterForm.Width - Width) div 2) + CenterForm.Left;
+        Top := ((CenterForm.Height - Height) div 2) + CenterForm.Top;
+    end else begin
+        Left := (Screen.Width - Width) div 2;
+        Top := (Screen.Height - Height) div 2;
+    end;
+end;
+
+procedure TRegExpTest.SetRegExp(const src: String);
+begin
+    FRegExp := src;
+end;
+
+procedure TRegExpTest.FormShow(Sender: TObject);
+begin
+    RegExpEdit.Text := FRegExp;
+end;
+
+procedure TRegExpTest.TestButtonClick(Sender: TObject);
+var
+    AWKStr: TAWKStr;
+       RStart: Integer;
+       RLength: Integer;
+begin
+    if (TargetEdit.Text = '') then begin
+        Application.MessageBox('\91Î\8fÛ\95\8e\9a\97ñ\82ð\8ew\92è\82µ\82Ä\82­\82¾\82³\82¢\81B', PChar(Caption), MB_OK or MB_ICONERROR);
+        Exit;
+    end;
+    if (RegExpEdit.Text = '') then begin
+        Application.MessageBox('\90³\8bK\95\\8c»\82ð\8ew\92è\82µ\82Ä\82­\82¾\82³\82¢\81B', PChar(Caption), MB_OK or MB_ICONERROR);
+        Exit;
+    end;
+
+       AWKStr := TAWKStr.Create(nil);
+       try
+        AWKStr.RegExp := RegExpEdit.Text;
+        if (AWKStr.Match(AWKStr.ProcessEscSeq(TargetEdit.Text), RStart, RLength) > 0) then
+            Application.MessageBox('\83}\83b\83`\82µ\82Ü\82µ\82½\81B', PChar(Caption), MB_OK or MB_ICONINFORMATION)
+        else
+            Application.MessageBox('\83}\83b\83`\82µ\82Ü\82¹\82ñ\82Å\82µ\82½\81B', PChar(Caption), MB_OK or MB_ICONWARNING);
+       except
+               on E: Exception do
+            ShowMessage(E.Message);
+    end;
+       FreeAndNil(AWKStr);
+end;
+
+end.
index 6c549d5..ecec20f 100644 (file)
@@ -355,6 +355,14 @@ type
                FDeleteSyria : Boolean; //\83V\83\8a\83A\8cê\83u\83\89\83N\83\89\91Î\8dô
                FIgnoreKana     : Boolean;      //\91S\94¼\8ap\82Ð\82ç\83J\83i\82Ì\88á\82¢\82ð\96³\8e\8b\82·\82é\82©
 
+        //NG\83\8f\81[\83h\95Ò\8fW
+        FNGTextEditor: Boolean; //\95Ò\8fW\82É\83e\83L\83X\83g\83G\83f\83B\83^\82ð\8eg\97p\82·\82é\82©
+               FNGWindowTop: Integer;
+               FNGWindowLeft: Integer;
+               FNGWindowHeight: Integer;
+               FNGWindowWidth: Integer;
+               FNGWindowMax: Boolean;
+
                // \83X\83\8c\83b\83h\8di\8d\9e\83t\83B\81[\83\8b\83h\82Ì\95\9d
                FSelectComboBoxWidth : Integer;
 
@@ -777,6 +785,15 @@ type
                property AddResAnchor : Boolean read FAddResAnchor write FAddResAnchor;
                property DeleteSyria : Boolean read FDeleteSyria write FDeleteSyria;
                property IgnoreKana : Boolean read FIgnoreKana write FIgnoreKana;
+
+        //NG\83\8f\81[\83h\95Ò\8fW
+        property NGTextEditor: Boolean read FNGTextEditor write FNGTextEditor;
+               property NGWindowTop: Integer read FNGWindowTop write FNGWindowTop;
+               property NGWindowLeft: Integer read FNGWindowLeft write FNGWindowLeft;
+               property NGWindowHeight: Integer read FNGWindowHeight write FNGWindowHeight;
+               property NGWindowWidth: Integer read FNGWindowWidth write FNGWindowWidth;
+               property NGWindowMax: Boolean read FNGWindowMax write FNGWindowMax;
+
                // \83X\83\8c\83b\83h\8di\8d\9e\83t\83B\81[\83\8b\83h\82Ì\95\9d
                property SelectComboBoxWidth : Integer read FSelectComboBoxWidth write FSelectComboBoxWidth;
 
@@ -1335,6 +1352,14 @@ begin
                FDeleteSyria :=  ini.ReadBool('Abon','DeleteSyria',false);
                FIgnoreKana  :=  ini.ReadBool('Abon','IgnoreKana',false);
 
+        //NG\83\8f\81[\83h\95Ò\8fW
+        FNGTextEditor   := ini.ReadBool('NGWordEditor', 'NGTextEditor', False);
+               FNGWindowTop    := ini.ReadInteger('NGWordEditor', 'NGWindowTop', 100);
+               FNGWindowLeft   := ini.ReadInteger('NGWordEditor', 'NGWindowLeft', 100);
+               FNGWindowHeight := ini.ReadInteger('NGWordEditor', 'NGWindowHeight', 478);
+               FNGWindowWidth  := ini.ReadInteger('NGWordEditor', 'NGWindowWidth', 845);
+               FNGWindowMax    := ini.ReadBool('NGWordEditor', 'NGWindowMax', False);
+
                // \83G\83f\83B\83^
                FSpaceToNBSP    := ini.ReadBool( 'Editor', 'SpaceToNBSP', False );
                FAmpToCharRef   := ini.ReadBool( 'Editor', 'AmpToCharRef', False );
@@ -1789,6 +1814,14 @@ begin
                ini.WriteBool('Abon','DeleteSyria',FDeleteSyria);
                ini.WriteBool('Abon','IgnoreKana', FIgnoreKana);
 
+        //NG\83\8f\81[\83h\95Ò\8fW
+        ini.WriteBool('NGWordEditor', 'NGTextEditor', FNGTextEditor);
+               ini.WriteInteger('NGWordEditor', 'NGWindowTop', FNGWindowTop);
+               ini.WriteInteger('NGWordEditor', 'NGWindowLeft', FNGWindowLeft);
+               ini.WriteInteger('NGWordEditor', 'NGWindowHeight', FNGWindowHeight);
+               ini.WriteInteger('NGWordEditor', 'NGWindowWidth', FNGWindowWidth);
+               ini.WriteBool('NGWordEditor', 'NGWindowMax', FNGWindowMax);
+
                // \83G\83f\83B\83^
                ini.WriteBool( 'Editor', 'SpaceToNBSP', FSpaceToNBSP );
                ini.WriteBool( 'Editor', 'AmpToCharRef', FAmpToCharRef );
index bfd5fa4..5da962d 100644 (file)
@@ -88,7 +88,11 @@ uses
   WideMemo in 'WideMemo.pas',
   ThreadSearch in 'ThreadSearch.pas' {ThreadSrch},
   uLkJSON in 'lkJSON\uLkJSON.pas',
-  ThreadNGEdt in 'ThreadNGEdt.pas' {ThreadNGEdit};
+  ThreadNGEdt in 'ThreadNGEdt.pas' {ThreadNGEdit},
+  AbonInfo in 'AbonInfo.pas',
+  AbonInfoSet in 'AbonInfoSet.pas' {AbonInfoEdit},
+  NgEditor in 'NgEditor.pas' {NgEdit},
+  RegExpTester in 'RegExpTester.pas' {RegExpTest};
 
 {$R *.RES}
 {$R gikoResource.res}