• R/O
  • HTTP
  • SSH
  • HTTPS

gikonavi: Commit


Commit MetaInfo

Revisioncedacfcd8f177e9bc2bd316ed9f4ba19f8a437eb (tree)
Time2007-02-14 01:01:29
Authorcvs2git <cvs2git>
Commitercvs2git

Log Message

This commit was manufactured by cvs2svn to create tag 'v1_55_0_692'.

Change Summary

Incremental Difference

--- a/Giko.dfm
+++ b/Giko.dfm
@@ -5147,7 +5147,7 @@ object GikoForm: TGikoForm
51475147 object UrlCopyPMenu: TMenuItem
51485148 Action = GikoDM.SelectItemURLCopyAction
51495149 end
5150- object C2: TMenuItem
5150+ object NameCopyPMenu: TMenuItem
51515151 Action = GikoDM.SelectItemNameCopyAction
51525152 end
51535153 object NameUrlCopyPMenu: TMenuItem
--- a/Giko.pas
+++ b/Giko.pas
@@ -284,7 +284,7 @@ type
284284 SelectItemNameCopyAction1: TMenuItem;
285285 B6: TMenuItem;
286286 T9: TMenuItem;
287- C2: TMenuItem;
287+ NameCopyPMenu: TMenuItem;
288288 SelectComboBox: TComboBox;
289289 MainCoolBarPopupMenu: TPopupMenu;
290290 StdToolBarVisiblePMenu: TMenuItem;
@@ -3555,7 +3555,7 @@ end;
35553555
35563556 procedure TGikoForm.ListPopupMenuPopup(Sender: TObject);
35573557 var
3558- bBoard, bCategory : Boolean;
3558+ bBoard, bCategory, bBBS : Boolean;
35593559 begin
35603560 bBoard := (GetActiveList is TBoard);
35613561 bCategory := (GetActiveList is TCategory);
--- a/GikoDataModule.dfm
+++ b/GikoDataModule.dfm
@@ -1311,6 +1311,12 @@ object GikoDM: TGikoDM
13111311 Hint = #31227#36578#12375#12390#12356#12427#26495#12398'URL'#12434#26908#32034#12377#12427
13121312 OnExecute = NewBoardSearchActionExecute
13131313 end
1314+ object NGWordEditFormAction: TAction
1315+ Category = 'NGword'
1316+ Caption = 'NG'#12527#12540#12489#32232#38598#12501#12457#12540#12512
1317+ Hint = 'NG'#12527#12540#12489#32232#38598#12501#12457#12540#12512#12458#12540#12503#12531
1318+ OnExecute = NGWordEditFormActionExecute
1319+ end
13141320 end
13151321 object ToobarImageList: TImageList
13161322 Left = 44
--- a/GikoDataModule.pas
+++ b/GikoDataModule.pas
@@ -231,6 +231,7 @@ type
231231 NewImageLinkToClipBoardAction: TAction;
232232 SetForcusForAddresBarAction: TAction;
233233 NewBoardSearchAction: TAction;
234+ NGWordEditFormAction: TAction;
234235 procedure EditNGActionExecute(Sender: TObject);
235236 procedure ReloadActionExecute(Sender: TObject);
236237 procedure GoFowardActionExecute(Sender: TObject);
@@ -434,6 +435,7 @@ type
434435 procedure AllImageLinkToClipbordActionExecute(Sender: TObject);
435436 procedure SetForcusForAddresBarActionExecute(Sender: TObject);
436437 procedure NewBoardSearchActionExecute(Sender: TObject);
438+ procedure NGWordEditFormActionExecute(Sender: TObject);
437439 private
438440 { Private 宣言 }
439441 procedure ClearResFilter;
@@ -486,7 +488,7 @@ uses
486488 GikoBayesian, About, ShellAPI,
487489 RoundName, RoundData, Menus, ListViewUtils,
488490 ThreadControl, GikoMessage, InputAssist,
489- DefaultFileManager, Forms, NewBoardURL;
491+ DefaultFileManager, Forms, NewBoardURL, NGWordEdit;
490492
491493 const
492494 MSG_ERROR : string = 'エラー';
@@ -2900,7 +2902,9 @@ begin
29002902 try
29012903 GikoForm.SelectListItem(List);
29022904 for i := 0 to List.Count - 1 do begin
2903- if TObject(List[i]) is TBoard then
2905+ if TObject(List[i]) is TCategory then
2906+ s := s + TCategory(List[i]).Title + #13#10
2907+ else if TObject(List[i]) is TBoard then
29042908 s := s + TBoard(List[i]).Title + #13#10
29052909 else if TObject(List[i]) is TThreadItem then
29062910 s := s + TThreadItem(List[i]).Title + #13#10;
@@ -2916,7 +2920,8 @@ end;
29162920 // *************************************************************************
29172921 procedure TGikoDM.SelectItemNameCopyActionUpdate(Sender: TObject);
29182922 begin
2919- if ((GikoForm.GetActiveList is TBoard) or
2923+ if ((GikoForm.GetActiveList is TBBS) or
2924+ (GikoForm.GetActiveList is TBoard) or
29202925 (GikoForm.GetActiveList is TCategory))and (GikoForm.ListView.SelCount > 0) then
29212926 TAction(Sender).Enabled := True
29222927 else
@@ -4336,5 +4341,17 @@ begin
43364341 end;
43374342 end;
43384343
4344+procedure TGikoDM.NGWordEditFormActionExecute(Sender: TObject);
4345+var
4346+ form: TNGWordEditForm;
4347+begin
4348+ form := TNGWordEditForm.Create(Self);
4349+ try
4350+ form.ShowModal;
4351+ finally
4352+ form.Release;
4353+ end;
4354+end;
4355+
43394356 end.
43404357
--- a/GikoSystem.pas
+++ b/GikoSystem.pas
@@ -262,7 +262,7 @@ const
262262 ZERO_DATE: Integer = 25569;
263263 BETA_VERSION_NAME_E = 'beta';
264264 BETA_VERSION_NAME_J = 'バタ';
265- BETA_VERSION = 54;
265+ BETA_VERSION = 55;
266266 BETA_VERSION_BUILD = ''; //!< debug版など
267267 APP_NAME = 'gikoNavi';
268268 BE_PHP_URL = 'http://be.2ch.net/test/p.php?i=';
--- a/HTMLCreate.pas
+++ b/HTMLCreate.pas
@@ -68,6 +68,7 @@ type
6868 function getNumberString(const str: String;var index :Integer; var dbCharlen: Boolean;
6969 sLen :Integer): String;
7070 function isOutsideRange(item: TThreadItem; index: Integer ): Boolean;
71+ function getKeywordLink(item: TThreadItem): String;
7172 public
7273 { Public 宣言 }
7374 procedure AddAnchorTag(PRes: PResRec);
@@ -99,7 +100,7 @@ var
99100 implementation
100101
101102 uses
102- Trip;
103+ Trip, NGWordUnit;
103104
104105 const
105106 URL_CHAR: string = '0123456789'
@@ -771,16 +772,22 @@ begin
771772
772773 if (Trim(ReadList[i]) <> '') then begin
773774 DivideStrLine(ReadList[i], @Res);
774- AddAnchorTag(@Res);
775- ConvRes(@Res, @ResLink);
776- Res.FDateTime := AddBeProfileLink(Res.FDateTime, i + 1);
777-
778- if NewReceiveNo <= (i + 1) then
779- // 新着レス
780- html.Add(SkinedRes(SkinNewRes, @Res, IntToStr(i + 1)))
781- else
782- // 通常のレス
783- html.Add(SkinedRes(SkinRes, @Res, IntToStr(i + 1)));
775+ if (NGWordList.IsNG(@Res) = -1) then begin
776+ AddAnchorTag(@Res);
777+ ConvRes(@Res, @ResLink);
778+ Res.FDateTime := AddBeProfileLink(Res.FDateTime, i + 1);
779+
780+ if NewReceiveNo <= (i + 1) then
781+ // 新着レス
782+ html.Add(SkinedRes(SkinNewRes, @Res, IntToStr(i + 1)))
783+ else
784+ // 通常のレス
785+ html.Add(SkinedRes(SkinRes, @Res, IntToStr(i + 1)));
786+ end else begin
787+{$IFDEF DEBUG}
788+ html.Add('<h4>あぼ〜ん</h4>');
789+{$ENDIF}
790+ end;
784791 end;
785792
786793 if ThreadItem.Kokomade = (i + 1) then begin
@@ -791,7 +798,7 @@ begin
791798 html.Add( KOKO_TAG );
792799 end;
793800 end;
794-
801+ html.Add(getKeywordLink(ThreadItem));
795802 html.Add('<a name="bottom"></a>');
796803 // スキン(フッタ)
797804 html.Add( LoadFromSkin( GikoSys.GetSkinFooterFileName, ThreadItem, ThreadItem.Size ) );
@@ -858,23 +865,29 @@ begin
858865 if (Trim(ReadList[i]) <> '') then begin
859866 No := IntToStr(i + 1);
860867 DivideStrLine(ReadList[i], @Res);
861- AddAnchorTag(@Res);
862- ConvRes(@Res, @ResLink);
863- Res.FDateTime := AddBeProfileLink(Res.FDateTime, i + 1);
864- if Res.FMailTo = '' then
865- html.Add(Format(FORMAT_NOMAIL, [No, No, No, Res.FName, Res.FDateTime, Res.FBody]))
866- else if GikoSys.Setting.ShowMail then
867- html.Add(Format(FORMAT_SHOWMAIL, [No, No, No, Res.FMailTo, Res.FName, Res.FMailTo, Res.FDateTime, Res.FBody]))
868- else
869- html.Add(Format(FORMAT_NOSHOW, [No, No, No, Res.FMailTo, Res.FName, Res.FDateTime, Res.FBody]));
870- end;
868+ if (NGWordList.IsNG(@Res) = -1) then begin
869+ AddAnchorTag(@Res);
870+ ConvRes(@Res, @ResLink);
871+ Res.FDateTime := AddBeProfileLink(Res.FDateTime, i + 1);
872+ if Res.FMailTo = '' then
873+ html.Add(Format(FORMAT_NOMAIL, [No, No, No, Res.FName, Res.FDateTime, Res.FBody]))
874+ else if GikoSys.Setting.ShowMail then
875+ html.Add(Format(FORMAT_SHOWMAIL, [No, No, No, Res.FMailTo, Res.FName, Res.FMailTo, Res.FDateTime, Res.FBody]))
876+ else
877+ html.Add(Format(FORMAT_NOSHOW, [No, No, No, Res.FMailTo, Res.FName, Res.FDateTime, Res.FBody]));
878+ end;
879+ end else begin
880+{$IFDEF DEBUG}
881+ html.Add('<h4>あぼ〜ん</h4>');
882+{$ENDIF}
883+ end;
871884
872885 if ThreadItem.Kokomade = (i + 1) then begin
873886 html.Add('<a name="koko"></a><div class="koko">ココまで読んだ</div>');
874887 end;
875888
876889 end;
877-
890+ html.Add(getKeywordLink(ThreadItem));
878891 html.Add('<a name="bottom"></a>');
879892 html.Add('<a name="last"></a>');
880893 html.Add('</body></html>');
@@ -922,6 +935,7 @@ begin
922935 if (Trim(ReadList[i]) <> '') then begin
923936 No := IntToStr(i + 1);
924937 DivideStrLine(ReadList[i], @Res);
938+
925939 AddAnchorTag(@Res);
926940 ConvRes(@Res, @ResLink);
927941 Res.FDateTime := AddBeProfileLink(Res.FDateTime, i + 1);
@@ -931,13 +945,19 @@ begin
931945 html.Add('<a name="' + No + '"></a><dt><a href="menu:' + No + '">' + No + '</a> 名前:<a href="mailto:' + Res.FMailTo + '"><b> ' + Res.FName + ' </B></a> [' + Res.FMailTo + '] 投稿日: <span class="date">' + Res.FDateTime+ '</span><br><dd>' + Res.Fbody + ' <br><br><br>'#13#10)
932946 else
933947 html.Add('<a name="' + No + '"></a><dt><a href="menu:' + No + '">' + No + '</a> 名前:<a href="mailto:' + Res.FMailTo + '"><b> ' + Res.FName + ' </B></a> 投稿日: <span class="date">' + Res.FDateTime+ '</span><br><dd>' + Res.Fbody + ' <br><br><br>'#13#10);
934- end;
948+ end else begin
949+{$IFDEF DEBUG}
950+ html.Add('<h4>あぼ〜ん</h4>');
951+{$ENDIF}
952+ end;
953+
935954 if ThreadItem.Kokomade = (i + 1) then begin
936955 html.Add('</dl>');
937956 html.Add('<a name="koko"></a><table width="100%" bgcolor="#55AA55" cellpadding="0" cellspacing="1"><tr><td align="center" bgcolor="#77CC77" valign="middle"><font size="-1" color="#ffffff"><b>ココまで読んだ</b></font></td></tr></table>');
938957 html.Add('<dl>');
939958 end;
940959 end;
960+ html.Add(getKeywordLink(ThreadItem));
941961 html.Add('</dl>'#13#10'<a name="bottom"></a>'#13#10'</body></html>');
942962 end;
943963
@@ -976,7 +996,7 @@ begin
976996 ReadList.LoadFromFile(FileName);
977997 ReadList.EndUpdate;
978998 GikoSys.FAbon.IndividualAbon(ReadList, ChangeFileExt(FileName,'.NG'));
979- GikoSys.FAbon.Execute(ReadList); // あぼ〜んして
999+ //GikoSys.FAbon.Execute(ReadList); // あぼ〜んして
9801000 GikoSys.FSelectResFilter.Execute(ReadList); //レスのフィルタリングをする
9811001 if ThreadItem.Title = '' then begin
9821002 DivideStrLine(ReadList[0], @Res);
@@ -1666,7 +1686,17 @@ begin
16661686 end;
16671687 inherited;
16681688 end;
1669-
1689+//! 関連キーワードリンク出力
1690+function THTMLCreate.getKeywordLink(item: TThreadItem): String;
1691+const
1692+ PARA_URL = 'http://p2.2ch.io/getf.cgi?';
1693+begin
1694+ Result := '';
1695+ if (GikoSys.Setting.AddKeywordLink) and (item.ParentBoard.Is2ch) then begin
1696+ Result := '<p><span id="keyword"><a href="' + PARA_URL
1697+ + item.URL + '" target="_blank">関連キーワード</a></span></p>';
1698+ end;
1699+end;
16701700 initialization
16711701 HTMLCreater := THTMLCreate.Create;
16721702
--- a/KuroutSetting.dfm
+++ b/KuroutSetting.dfm
@@ -21,8 +21,8 @@ object KuroutOption: TKuroutOption
2121 Top = 0
2222 Width = 517
2323 Height = 393
24- ActivePage = KakikomiTabSheet
25- TabIndex = 2
24+ ActivePage = TabSheet1
25+ TabIndex = 0
2626 TabOrder = 0
2727 object TabSheet1: TTabSheet
2828 Caption = #35443#32048#35373#23450#65297
@@ -427,8 +427,8 @@ object KuroutOption: TKuroutOption
427427 end
428428 object AHandredGroupBox: TGroupBox
429429 Left = 16
430- Top = 192
431- Width = 465
430+ Top = 184
431+ Width = 473
432432 Height = 65
433433 Caption = '100'#12524#12473#34920#31034#35373#23450
434434 TabOrder = 2
@@ -458,6 +458,22 @@ object KuroutOption: TKuroutOption
458458 Wrap = False
459459 end
460460 end
461+ object HTMLGroupBox: TGroupBox
462+ Left = 16
463+ Top = 256
464+ Width = 473
465+ Height = 65
466+ Caption = #12473#12524#12483#12489#25551#30011
467+ TabOrder = 3
468+ object AddKeywordCheckBox: TCheckBox
469+ Left = 16
470+ Top = 24
471+ Width = 233
472+ Height = 17
473+ Caption = #38306#36899#12461#12540#12527#12540#12489#12398#12522#12531#12463#12434#36861#21152#12377#12427
474+ TabOrder = 0
475+ end
476+ end
461477 end
462478 end
463479 object OkBotton: TButton
--- a/KuroutSetting.pas
+++ b/KuroutSetting.pas
@@ -68,6 +68,8 @@ type
6868 AHandredGroupBox: TGroupBox;
6969 AHandredLabeledEdit: TLabeledEdit;
7070 UpDown1: TUpDown;
71+ HTMLGroupBox: TGroupBox;
72+ AddKeywordCheckBox: TCheckBox;
7173 procedure OkBottonClick(Sender: TObject);
7274 procedure FormCreate(Sender: TObject);
7375 procedure CDeleteButtonClick(Sender: TObject);
@@ -136,6 +138,8 @@ begin
136138 MoveHistoryMaxEdit.Text := IntToStr( GikoSys.Setting.MoveHistorySize );
137139 // 先頭表示レス数
138140 AHandredLabeledEdit.Text := IntToStr( GikoSys.Setting.HeadResCount );
141+ // 関連キーワード追加フラグ
142+ AddKeywordCheckBox.Checked := GikoSys.Setting.AddKeywordLink;
139143 end;
140144
141145 procedure TKuroutOption.SaveSetting;
@@ -172,6 +176,9 @@ begin
172176 StrToIntDef( AHandredLabeledEdit.Text , 1);
173177
174178 GikoSys.Setting.KuroutSettingTabIndex := PageControl1.ActivePageIndex;
179+ // 関連キーワード追加フラグ
180+ GikoSys.Setting.AddKeywordLink := AddKeywordCheckBox.Checked;
181+
175182 end;
176183
177184 procedure TKuroutOption.RecvBufferSizeExit(Sender: TObject);
--- /dev/null
+++ b/NGWordEdit.dfm
@@ -0,0 +1,211 @@
1+object NGWordEditForm: TNGWordEditForm
2+ Left = 304
3+ Top = 176
4+ Width = 490
5+ Height = 401
6+ Caption = 'NGWordEditForm'
7+ Color = clBtnFace
8+ Font.Charset = SHIFTJIS_CHARSET
9+ Font.Color = clWindowText
10+ Font.Height = -12
11+ Font.Name = #65325#65331' '#65328#12468#12471#12483#12463
12+ Font.Style = []
13+ Menu = MainMenu1
14+ OldCreateOrder = False
15+ OnCreate = FormCreate
16+ PixelsPerInch = 96
17+ TextHeight = 12
18+ object Panel1: TPanel
19+ Left = 0
20+ Top = 0
21+ Width = 482
22+ Height = 153
23+ Align = alTop
24+ BevelOuter = bvNone
25+ Caption = 'Panel1'
26+ TabOrder = 0
27+ object Panel3: TPanel
28+ Left = 359
29+ Top = 0
30+ Width = 123
31+ Height = 153
32+ Align = alRight
33+ BevelOuter = bvLowered
34+ Caption = 'Panel3'
35+ TabOrder = 0
36+ object AddButton: TButton
37+ Left = 24
38+ Top = 16
39+ Width = 75
40+ Height = 25
41+ Caption = #36861#21152
42+ TabOrder = 0
43+ OnClick = AddButtonClick
44+ end
45+ object DeleteButton: TButton
46+ Left = 24
47+ Top = 40
48+ Width = 75
49+ Height = 25
50+ Caption = #21066#38500
51+ TabOrder = 1
52+ OnClick = DeleteButtonClick
53+ end
54+ object ApplyButton: TButton
55+ Left = 24
56+ Top = 80
57+ Width = 75
58+ Height = 25
59+ Caption = #36969#29992
60+ TabOrder = 2
61+ OnClick = ApplyButtonClick
62+ end
63+ object Button4: TButton
64+ Left = 24
65+ Top = 104
66+ Width = 75
67+ Height = 25
68+ Caption = 'Button4'
69+ TabOrder = 3
70+ end
71+ end
72+ object GikoListView1: TGikoListView
73+ Left = 0
74+ Top = 0
75+ Width = 359
76+ Height = 153
77+ Align = alClient
78+ Checkboxes = True
79+ Columns = <>
80+ GridLines = True
81+ ReadOnly = True
82+ RowSelect = True
83+ TabOrder = 1
84+ ViewStyle = vsReport
85+ OnSelectItem = GikoListView1SelectItem
86+ end
87+ end
88+ object Panel2: TPanel
89+ Left = 0
90+ Top = 153
91+ Width = 482
92+ Height = 202
93+ Align = alClient
94+ BevelOuter = bvNone
95+ Caption = 'Panel2'
96+ TabOrder = 1
97+ object Panel4: TPanel
98+ Left = 0
99+ Top = 0
100+ Width = 482
101+ Height = 41
102+ Align = alTop
103+ BevelOuter = bvNone
104+ TabOrder = 0
105+ object Label1: TLabel
106+ Left = 16
107+ Top = 8
108+ Width = 48
109+ Height = 12
110+ Caption = #36969#21512#22580#25152
111+ end
112+ object Label2: TLabel
113+ Left = 237
114+ Top = 11
115+ Width = 47
116+ Height = 12
117+ Caption = 'NG'#12527#12540#12489
118+ end
119+ object ComboBox1: TComboBox
120+ Left = 80
121+ Top = 8
122+ Width = 145
123+ Height = 20
124+ ItemHeight = 12
125+ ItemIndex = 0
126+ TabOrder = 0
127+ Text = #20840#12390
128+ Items.Strings = (
129+ #20840#12390
130+ #21517#21069#27396
131+ #12513#12540#12523#27396
132+ #26085#20184#12539'ID'
133+ #26412#25991)
134+ end
135+ object NGWordEdit: TEdit
136+ Left = 296
137+ Top = 8
138+ Width = 161
139+ Height = 20
140+ TabOrder = 1
141+ Text = 'NGWordEdit'
142+ end
143+ end
144+ object Panel5: TPanel
145+ Left = 359
146+ Top = 41
147+ Width = 123
148+ Height = 161
149+ Align = alRight
150+ BevelOuter = bvLowered
151+ Caption = 'Panel5'
152+ TabOrder = 1
153+ object ModifiedNGButton: TButton
154+ Left = 24
155+ Top = 65
156+ Width = 75
157+ Height = 25
158+ Caption = #22793#26356
159+ TabOrder = 0
160+ OnClick = ModifiedNGButtonClick
161+ end
162+ object AddNGButton: TButton
163+ Left = 24
164+ Top = 16
165+ Width = 75
166+ Height = 25
167+ Caption = #36861#21152
168+ TabOrder = 1
169+ OnClick = AddNGButtonClick
170+ end
171+ object DeleteNGButton: TButton
172+ Left = 24
173+ Top = 41
174+ Width = 75
175+ Height = 25
176+ Caption = #21066#38500
177+ TabOrder = 2
178+ OnClick = DeleteNGButtonClick
179+ end
180+ end
181+ object GikoListView2: TGikoListView
182+ Left = 0
183+ Top = 41
184+ Width = 359
185+ Height = 161
186+ Align = alClient
187+ Columns = <>
188+ GridLines = True
189+ ReadOnly = True
190+ RowSelect = True
191+ TabOrder = 2
192+ ViewStyle = vsReport
193+ OnSelectItem = GikoListView2SelectItem
194+ end
195+ end
196+ object MainMenu1: TMainMenu
197+ Left = 376
198+ Top = 48
199+ object File1: TMenuItem
200+ Caption = 'File'
201+ object Load1: TMenuItem
202+ Caption = 'Load'
203+ OnClick = Load1Click
204+ end
205+ object Save1: TMenuItem
206+ Caption = 'Save'
207+ OnClick = Save1Click
208+ end
209+ end
210+ end
211+end
--- /dev/null
+++ b/NGWordEdit.pas
@@ -0,0 +1,304 @@
1+unit NGWordEdit;
2+
3+interface
4+
5+uses
6+ Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
7+ Dialogs, ExtCtrls, StdCtrls, ComCtrls, GikoListView, Menus, GikoXMLDoc,
8+ NGWordUnit;
9+
10+type
11+ TNGWordEditForm = class(TForm)
12+ Panel1: TPanel;
13+ Panel2: TPanel;
14+ Panel3: TPanel;
15+ AddButton: TButton;
16+ DeleteButton: TButton;
17+ ApplyButton: TButton;
18+ Button4: TButton;
19+ Panel4: TPanel;
20+ Panel5: TPanel;
21+ GikoListView2: TGikoListView;
22+ GikoListView1: TGikoListView;
23+ ComboBox1: TComboBox;
24+ Label1: TLabel;
25+ NGWordEdit: TEdit;
26+ Label2: TLabel;
27+ ModifiedNGButton: TButton;
28+ AddNGButton: TButton;
29+ DeleteNGButton: TButton;
30+ MainMenu1: TMainMenu;
31+ File1: TMenuItem;
32+ Load1: TMenuItem;
33+ Save1: TMenuItem;
34+ procedure Load1Click(Sender: TObject);
35+ procedure Save1Click(Sender: TObject);
36+ procedure FormCreate(Sender: TObject);
37+ procedure GikoListView1SelectItem(Sender: TObject; Item: TListItem;
38+ Selected: Boolean);
39+ procedure AddNGButtonClick(Sender: TObject);
40+ procedure DeleteNGButtonClick(Sender: TObject);
41+ procedure AddButtonClick(Sender: TObject);
42+ procedure DeleteButtonClick(Sender: TObject);
43+ procedure ApplyButtonClick(Sender: TObject);
44+ procedure ModifiedNGButtonClick(Sender: TObject);
45+ procedure GikoListView2SelectItem(Sender: TObject; Item: TListItem;
46+ Selected: Boolean);
47+ private
48+ { Private 宣言 }
49+ function AddNGWord(ngWord: TNGWords): TListItem;
50+ procedure AddWord(word: TNGWord);
51+ public
52+ { Public 宣言 }
53+ end;
54+
55+var
56+ NGWordEditForm: TNGWordEditForm;
57+
58+implementation
59+
60+uses
61+ GikoSystem;
62+{$R *.dfm}
63+
64+procedure TNGWordEditForm.Load1Click(Sender: TObject);
65+var
66+ fname : String;
67+ i: Integer;
68+begin
69+ GikoListView2.Items.BeginUpdate;
70+ GikoListView1.Items.BeginUpdate;
71+ try
72+ GikoListView2.Items.Clear;
73+ GikoListView1.Items.Clear;
74+ fname := GikoSys.GetAppDir + 'ngwords.xml';
75+ NGWordList.LoadFromFile(fname);
76+
77+ for i :=0 to NGWordList.Count - 1 do begin
78+ AddNGWord(TNGWords(NGWordList.Items[i]));
79+ end;
80+ finally
81+ GikoListView1.Items.EndUpdate;
82+ GikoListView2.Items.EndUpdate;
83+ end;
84+end;
85+function TNGWordEditForm.AddNGWord(ngWord: TNGWords): TListItem;
86+begin
87+ Result := GikoListView1.Items.Add;
88+ Result.ImageIndex := -1;
89+ Result.Caption := '';
90+ Result.SubItems.Clear;
91+ Result.SubItems.Add(ngWord.ToString);
92+ Result.Checked := ngWord.Invisible;
93+ Result.Data := ngWord;
94+end;
95+
96+procedure TNGWordEditForm.Save1Click(Sender: TObject);
97+begin
98+ if (NGWordList <> nil) then begin
99+ NGWordList.SaveToFrile(GikoSys.GetAppDir + 'ngwords2.xml');
100+ end;
101+end;
102+
103+procedure TNGWordEditForm.FormCreate(Sender: TObject);
104+var
105+ column1,column2: TListColumn;
106+ i: Integer;
107+begin
108+ GikoListView1.Columns.BeginUpdate;
109+ column1 := GikoListView1.Columns.Add;
110+ column1.ImageIndex := -1;
111+ column1.Caption := '透明';
112+ column1.DisplayName := '透明';
113+ column1.Width := 40;
114+ column1 := GikoListView1.Columns.Add;
115+ column1.ImageIndex := -1;
116+ column1.Caption := 'NGワード';
117+ column1.DisplayName := 'NGワード';
118+ column1.Width := 250;
119+ GikoListView1.Columns.EndUpdate;
120+
121+
122+ GikoListView2.Columns.BeginUpdate;
123+ column2 := GikoListView2.Columns.Add;
124+ column2.ImageIndex := -1;
125+ column2.Caption := '適応場所';
126+ column2.DisplayName := '適応場所';
127+ column2.Width := 100;
128+ column2 := GikoListView2.Columns.Add;
129+ column2.ImageIndex := -1;
130+ column2.Caption := 'ワード';
131+ column2.DisplayName := 'ワード';
132+ column2.Width := 190;
133+ GikoListView2.Columns.EndUpdate;
134+
135+ GikoListView1.Items.BeginUpdate;
136+ for i :=0 to NGWordList.Count - 1 do begin
137+ AddNGWord(TNGWords(NGWordList.Items[i]));
138+ end;
139+ GikoListView1.Items.EndUpdate;
140+end;
141+// 上部リスト選択イベント
142+procedure TNGWordEditForm.GikoListView1SelectItem(Sender: TObject;
143+ Item: TListItem; Selected: Boolean);
144+var
145+ ngWord : TNGWords;
146+ i: Integer;
147+begin
148+ if (Item <> nil) and (Item.Data <> nil) then begin
149+ ngWord := TNGWords(item.Data);
150+ GikoListView2.Items.BeginUpdate;
151+ GikoListView2.items.Clear;
152+ if ngWord.Count = 0 then begin
153+ // 何もないと見えないのでデフォルトのメッセージ
154+ AddWord(nil);
155+ end else begin
156+ // 全部の要素を追加する
157+ for i := 0 to ngWord.Count - 1 do begin
158+ AddWord( TNGWord(ngWord.Items[i]) );
159+ end;
160+
161+ end;
162+ GikoListView2.Items.EndUpdate;
163+ end;
164+end;
165+// 下部リスト追加メソッド
166+procedure TNGWordEditForm.AddWord(word: TNGWord);
167+var
168+ litem: TListItem;
169+begin
170+ litem := GikoListView2.Items.Add;
171+ litem.ImageIndex := -1;
172+ litem.SubItems.Clear;
173+ litem.Data := word;
174+ if (word = nil) then begin
175+ litem.Caption := '<未入力>'
176+ end else begin
177+ case Integer(word.NGType) of
178+ Integer(gntAll): litem.Caption := '全部';
179+ Integer(gntName): litem.Caption := '名前欄';
180+ Integer(gntMail): litem.Caption := 'メール欄';
181+ Integer(gntDateId):litem.Caption := '日付ID欄';
182+ Integer(gntBody): litem.Caption := '本文';
183+ end;
184+ litem.SubItems.Add(word.Word);
185+ end;
186+end;
187+//! NGワード追加ボタン
188+procedure TNGWordEditForm.AddNGButtonClick(Sender: TObject);
189+var
190+ litem: TListItem;
191+ word: TNGWord;
192+begin
193+ // 現在選択されている行を取得する
194+ litem := GikoListView1.Selected;
195+ if (litem <> nil) then begin
196+ if NGWordEdit.Text <> '' then begin
197+ // <未入力>を削除する
198+ if (TNGWords(litem.Data).Count = 0) then begin
199+ GikoListView2.Items.Delete(0);
200+ end;
201+ word := TNGWord.Create;
202+ word.NGType := TGikoNGType(ComboBox1.ItemIndex);
203+ word.Word := NGWordEdit.Text;
204+ TNGWords(litem.Data).Add(word);
205+ AddWord(word);
206+ litem.SubItems.Clear;
207+ litem.SubItems.Add(TNGWords(litem.Data).ToString);
208+ end else begin
209+ ShowMessage('NGワードは空欄で登録できません');
210+ end;
211+ end;
212+end;
213+//! NGワード削除ボタン
214+procedure TNGWordEditForm.DeleteNGButtonClick(Sender: TObject);
215+var
216+ litem, litem2: TListItem;
217+begin
218+ // 現在選択されている行を取得する
219+ litem := GikoListView1.Selected;
220+ if (litem <> nil) then begin
221+ litem2 := GikoListView2.Selected;
222+ if litem2 <> nil then begin
223+ TNGWords(litem.Data).Delete(TNGWord(litem2.Data));
224+ litem.Caption := TNGWords(litem.Data).ToString;
225+ end;
226+ GikoListView2.DeleteSelected;
227+ end;
228+end;
229+//!
230+procedure TNGWordEditForm.AddButtonClick(Sender: TObject);
231+var
232+ ngWords: TNGWords;
233+begin
234+ if (NGWordList <> nil) then begin
235+ ngWords := TNGWords.Create;
236+ NGWordList.Add(ngWords);
237+ GikoListView1.Selected := AddNGWord(ngWords);
238+ GikoListView1.SetFocus;
239+ end;
240+end;
241+//!
242+procedure TNGWordEditForm.DeleteButtonClick(Sender: TObject);
243+var
244+ litem: TListItem;
245+begin
246+ // 現在選択されている行を取得する
247+ litem := GikoListView1.Selected;
248+ if (litem <> nil) and (NGWordList <> nil) then begin
249+ NGWordList.Delte( TNGWords(litem.Data));
250+ GikoListView1.DeleteSelected;
251+ end;
252+end;
253+
254+//! 適応ボタン 透明チェックを設定しなおす
255+procedure TNGWordEditForm.ApplyButtonClick(Sender: TObject);
256+var
257+ i: Integer;
258+begin
259+ for i := 0 to GikoListView1.Items.Count - 1 do begin
260+ TNGWords(GikoListView1.Items[i].Data).Invisible :=
261+ GikoListView1.Items[i].Checked;
262+ end;
263+end;
264+
265+procedure TNGWordEditForm.ModifiedNGButtonClick(Sender: TObject);
266+var
267+ litem, litem2: TListItem;
268+begin
269+ // 現在選択されている行を取得する
270+ litem := GikoListView1.Selected;
271+ if (litem <> nil) then begin
272+ litem2 := GikoListView2.Selected;
273+ if litem2 <> nil then begin
274+ TNGWord(litem2.Data).NGType := TGikoNGType(ComboBox1.ItemIndex);
275+ TNGWord(litem2.Data).Word := NGWordEdit.Text;
276+ litem.SubItems.Clear;
277+ litem.SubItems.Add(TNGWords(litem.Data).ToString);
278+
279+ case Integer(TNGWord(litem2.Data).NGType) of
280+ Integer(gntAll): litem2.Caption := '全部';
281+ Integer(gntName): litem2.Caption := '名前欄';
282+ Integer(gntMail): litem2.Caption := 'メール欄';
283+ Integer(gntDateId):litem2.Caption := '日付ID欄';
284+ Integer(gntBody): litem2.Caption := '本文';
285+ end;
286+ litem2.SubItems.Clear;
287+ litem2.SubItems.Add(TNGWord(litem2.Data).Word);
288+ end;
289+ end;
290+end;
291+
292+procedure TNGWordEditForm.GikoListView2SelectItem(Sender: TObject;
293+ Item: TListItem; Selected: Boolean);
294+var
295+ word : TNGWord;
296+ i: Integer;
297+begin
298+ if (Item <> nil) and (Item.Data <> nil) then begin
299+ word := TNGWord(item.Data);
300+ ComboBox1.ItemIndex := Ord(word.NGType);
301+ NGWordEdit.Text := word.Word;
302+ end;
303+end;
304+end.
--- /dev/null
+++ b/NGWordUnit.pas
@@ -0,0 +1,337 @@
1+unit NGWordUnit;
2+
3+interface
4+uses
5+ Windows,Messages, ShellAPI, SysUtils, Classes,StdCtrls,StrUtils,
6+ GikoXMLDoc, GikoSystem, bmRegExp;
7+
8+type
9+ //リストの表示アイテム選択
10+ TGikoNGType = (gntAll, gntName, gntMail, gntDateId, gntBody);
11+
12+ {\
13+ NGワードクラス
14+ }
15+ TNGWord = class( TObject )
16+ private
17+ FRank : Integer;
18+ FNGType : TGikoNGType;
19+ FWord : String;
20+ public
21+ procedure ReadXMLElement(element :IXMLNode);
22+ function ToXMLString(): String;
23+ property Rank : Integer read FRank write FRank;
24+ property NGType : TGikoNGType read FNGType write FNGType;
25+ property Word : String read FWord write FWord;
26+ end;
27+
28+ {\
29+ NGワード集合クラス
30+ }
31+ TNGWords = class( TList )
32+ private
33+ FRank : Integer;
34+ FInvisible: Boolean;
35+ FAWKStr: TAWKStr;
36+ public
37+ constructor Create;
38+ procedure Free;
39+ property Rank : Integer read FRank write FRank;
40+ property Invisible : Boolean read FInvisible write FInvisible;
41+ function ReadXMLElement(element :IXMLNode): Boolean;
42+ function ToXMLString(): String;
43+ function ToString(): String;
44+ procedure Delete(word: TNGWord); overload;
45+ function IsNG(PRes : PResRec): Boolean;
46+ end;
47+
48+ {\
49+ NGワード管理クラス
50+ }
51+ TNGWordList = class( TList )
52+ private
53+ public
54+ procedure Free;
55+ procedure LoadFromFile(fileName: String);
56+ procedure SaveToFrile(fileName: String);
57+ procedure Delte(NGWords: TNGWords); overload;
58+ function IsNG(PRes : PResRec): Integer;
59+ end;
60+
61+ function CompareRank(Item1, Item2: Pointer): Integer;
62+var
63+ NGWordList: TNGWordList;
64+
65+implementation
66+
67+uses
68+ MojuUtils, Sort;
69+
70+function CompareRank(Item1, Item2: Pointer): Integer;
71+begin
72+ if TObject(item1) is TNGWords then begin
73+ Result := CompareInt(
74+ TNGWords(Item1).Rank, TNGWords(Item2).Rank);
75+ end else begin
76+ Result := CompareInt(
77+ TNGWord(Item1).Rank, TNGWord(Item2).Rank);
78+ end;
79+end;
80+constructor TNGWords.Create;
81+begin
82+ FRank := 0;
83+ FAWKStr := TAWKStr.Create(nil);
84+end;
85+procedure TNGWords.Free;
86+var
87+ i: Integer;
88+begin
89+ for i := 0 to Count - 1 do begin
90+ TObject(Items[i]).Free;
91+ end;
92+ FAWKStr.Free;
93+ inherited Free;
94+end;
95+function TNGWords.ReadXMLElement(element :IXMLNode): Boolean;
96+var
97+ i, bound : Integer;
98+ NGWordNode: IXMLNode;
99+ NG: TNGWord;
100+begin
101+ Result := False;
102+ if element.NodeName = 'NGWords' then begin
103+ Rank := StrToIntDef(element.Attributes['rank'],
104+ MaxInt);
105+ Invisible := StrToBoolDef(element.Attributes['invisible'],
106+ False);
107+ bound := element.ChildNodes.Count - 1;
108+ for i := 0 to bound do begin
109+ NGWordNode := element.ChildNodes[i];
110+ if NGWordNode.NodeName = 'NGWord' then begin
111+ NG := TNGWord.Create;
112+ NG.ReadXMLElement( NGWordNode );
113+ Add(NG);
114+ end;
115+ end;
116+ Sort(@CompareRank);
117+ Result := True;
118+ end;
119+end;
120+function TNGWords.ToXMLString(): String;
121+var
122+ i: Integer;
123+begin
124+ Result := '<NGWords ' +
125+ 'rank="' + IntToStr(FRank) + '" ' +
126+ 'invisible="' + BoolToStr(Invisible) + '" >'#13#10;
127+ for i := 0 to Count - 1 do begin
128+ Result := Result + TNGWord(Items[i]).ToXMLString + #13#10;
129+ end;
130+ Result := Result + '</NGWords>';
131+end;
132+function TNGWords.ToString(): String;
133+var
134+ i: Integer;
135+begin
136+ Result := '';
137+ for i := 0 to Count - 1 do begin
138+ Result := Result + TNGWord(Items[i]).Word + ' , ';
139+ end;
140+end;
141+procedure TNGWords.Delete(word: TNGWord);
142+var
143+ i: Integer;
144+begin
145+ for i := Count - 1 downto 0 do begin
146+ if ( Items[i] = word ) then begin
147+ TNGWord(Items[i]).Free;
148+ Self.Delete(i);
149+ break;
150+ end;
151+ end;
152+end;
153+function TNGWords.IsNG(PRes : PResRec): Boolean;
154+var
155+ i, oLength: Integer;
156+ RStart, RLength: Integer;
157+ word: TNGWord;
158+begin
159+ Result := True;
160+ for i := 0 to Count - 1 do begin
161+ word := TNGWord(Items[i]);
162+ FAWKStr.RegExp := word.Word;
163+ case Ord(word.FNGType) of
164+ Ord(gntAll):
165+ begin
166+ Result := FAWKStr.Match(FAWKStr.ProcessEscSeq(PRes.FTitle),
167+ RStart, RLength) <> 0;
168+ if Result then break;
169+ Result := FAWKStr.Match(FAWKStr.ProcessEscSeq(PRes.FMailTo),
170+ RStart, RLength) <> 0;
171+ if Result then break;
172+ Result := FAWKStr.Match(FAWKStr.ProcessEscSeq(PRes.FName),
173+ RStart, RLength) <> 0;
174+ if Result then break;
175+ Result := FAWKStr.Match(FAWKStr.ProcessEscSeq(PRes.FDateTime),
176+ RStart, RLength) <> 0;
177+ if Result then break;
178+ Result := FAWKStr.Match(FAWKStr.ProcessEscSeq(PRes.FBody),
179+ RStart, RLength) <> 0;
180+ end;
181+ Ord(gntName):
182+ Result := FAWKStr.Match(FAWKStr.ProcessEscSeq(PRes.FName),
183+ RStart, RLength) <> 0;
184+ Ord(gntMail):
185+ Result := FAWKStr.Match(FAWKStr.ProcessEscSeq(PRes.FMailTo),
186+ RStart, RLength) <> 0;
187+ Ord(gntDateId):
188+ Result := FAWKStr.Match(FAWKStr.ProcessEscSeq(PRes.FDateTime),
189+ RStart, RLength) <> 0;
190+ Ord(gntBody):
191+ Result := FAWKStr.Match(FAWKStr.ProcessEscSeq(PRes.FBody),
192+ RStart, RLength) <> 0;
193+ end;
194+ if not Result then Exit;
195+ end;
196+end;
197+
198+
199+procedure TNGWord.ReadXMLElement(element :IXMLNode);
200+begin
201+ FRank := StrToIntDef(element.Attributes['rank'],
202+ MaxInt);
203+ FNGType := TGikoNGType(StrToIntDef(
204+ Trim(element.Attributes['ngtype']),
205+ Integer(gntAll)));
206+
207+ FWord := Trim(element.Attributes['word']);
208+ if FWord <> '' then begin
209+ FWord := MojuUtils.UnSanitize( FWord );
210+ end;
211+end;
212+
213+function TNGWord.ToXMLString(): String;
214+begin
215+ Result := '<NGWord ' +
216+ 'rank="' + IntToStr(FRank) + '" ' +
217+ 'ngtype="' + IntToStr(Integer(FNGType)) + '" ' +
218+ 'word="' + MojuUtils.Sanitize(FWord) + '" />';
219+end;
220+
221+procedure TNGWordList.Free;
222+var
223+ i: Integer;
224+begin
225+ for i := Self.Count - 1 downto 0 do begin
226+ TNGWords(Self.Items[i]).Free;
227+ end;
228+ inherited Free;
229+end;
230+
231+procedure TNGWordList.SaveToFrile(fileName: String);
232+var
233+ xmlStrings: TStringList;
234+ i: Integer;
235+begin
236+ xmlStrings := TStringList.Create;
237+ try
238+ xmlStrings.Add('<?xml version="1.0" encoding="Shift_JIS" standalone="yes"?>');
239+ xmlStrings.Add('<root>');
240+ for i := 0 to Self.Count - 1 do begin
241+ xmlStrings.Add(
242+ TNGWords(Self.Items[i]).ToXMLString);
243+
244+ end;
245+ xmlStrings.Add('</root>');
246+ xmlStrings.SaveToFile(fileName);
247+ finally
248+ xmlStrings.Free;
249+ end;
250+end;
251+
252+procedure TNGWordList.LoadFromFile(fileName: String);
253+
254+var
255+ i, bound : Integer;
256+ XMLDoc : IXMLDocument;
257+ XMLNode: IXMLNode;
258+ NG : TNGWords;
259+{$IFDEF DEBUG}
260+ st, rt : Cardinal;
261+{$ENDIF}
262+begin
263+{$IFDEF DEBUG}
264+ st := GetTickCount;
265+{$ENDIF}
266+ if FileExists( FileName ) then begin
267+ if (Self.Count > 0) then begin
268+ Self.Free;
269+ Self.Capacity := 0;
270+ end;
271+ try
272+ XMLDoc := IXMLDocument.Create;
273+ //XMLDoc := LoadXMLDocument(FileName);
274+ LoadXMLDocument(FileName, XMLDoc);
275+ try
276+ XMLNode := XMLDoc.DocumentElement;
277+
278+ if XMLNode.NodeName = 'root' then begin
279+ bound := XMLNode.ChildNodes.Count - 1;
280+ for i := 0 to bound do begin
281+ NG := TNGWords.Create;
282+ if (NG.ReadXMLElement(XMLNode.ChildNodes[i])) then
283+ Self.Add(NG);
284+ end;
285+ end;
286+ Sort(@CompareRank);
287+ finally
288+ XMLDoc.Free;
289+ end;
290+ except
291+ end;
292+ end;
293+{$IFDEF DEBUG}
294+ rt := GetTickCount - st;
295+ Writeln('Runtime(Load NGWords) : ' + IntToStr(rt) + ' ms');
296+{$ENDIF}
297+end;
298+procedure TNGWordList.Delte(NGWords: TNGWords);
299+var
300+ i: Integer;
301+begin
302+ for i := Count - 1 downto 0 do begin
303+ if ( Items[i] = NGWords ) then begin
304+ TNGWords(Items[i]).Free;
305+ Self.Delete(i);
306+ break;
307+ end;
308+ end;
309+end;
310+//! NG判定
311+function TNGWordList.IsNG(PRes : PResRec): Integer;
312+var
313+ i: Integer;
314+ tRes : TResRec;
315+begin
316+ Result := -1;
317+ if Count > 0 then begin
318+ for i := 0 to Count - 1 do begin
319+ if (TNGWords(Items[i]).IsNG(PRes)) then begin
320+ Result := i;
321+ break;
322+ end;
323+ end;
324+ end;
325+end;
326+
327+// シングルトンのインスタンス
328+initialization
329+ NGWordList := TNGWordList.Create;
330+
331+finalization
332+ if NGWordList <> nil then begin
333+ NGWordList.Free;
334+ NGWordList := nil;
335+ end;
336+
337+end.
--- a/Setting.pas
+++ b/Setting.pas
@@ -441,6 +441,9 @@ type
441441 FLoopBrowserTabs : Boolean;
442442 //! 100レス表示の先頭表示レス数
443443 FHeadResCount : Integer;
444+ //! 関連キーワード追加フラグ
445+ FAddKeywordLink: Boolean;
446+
444447 function GetMainCoolSet(Index: Integer): TCoolSet;
445448 function GetBoardCoolSet(Index: Integer): TCoolSet;
446449 function GetBrowserCoolSet(Index: Integer): TCoolSet;
@@ -790,6 +793,8 @@ type
790793 property LoopBrowserTabs : Boolean read FLoopBrowserTabs write FLoopBrowserTabs;
791794 //! 100レス表示の先頭表示レス数
792795 property HeadResCount : Integer read FHeadResCount write FHeadResCount;
796+ //! 関連キーワード追加フラグ
797+ property AddKeywordLink: Boolean read FAddKeywordLink write FAddKeywordLink;
793798 end;
794799
795800
@@ -1262,7 +1267,7 @@ begin
12621267
12631268 FStoredTaskTray := ini.ReadBool('Function', 'StroedTaskTray', false);
12641269 FLoopBrowserTabs := ini.ReadBool('Function', 'LoopBrowserTabs', false);
1265-
1270+ FAddKeywordLink := ini.ReadBool('Thread', 'AddKeywordLink', false);
12661271 ini.UpdateFile;
12671272 finally
12681273 ini.Free;
@@ -1640,6 +1645,7 @@ begin
16401645
16411646 ini.WriteBool('Function', 'StroedTaskTray', FStoredTaskTray);
16421647 ini.WriteBool('Function', 'LoopBrowserTabs', FLoopBrowserTabs);
1648+ ini.WriteBool('Thread', 'AddKeywordLink', FAddKeywordLink);
16431649 ini.UpdateFile;
16441650 finally
16451651 ini.Free;
--- a/gikoNavi.dpr
+++ b/gikoNavi.dpr
@@ -76,7 +76,9 @@ uses
7676 MoveHistoryItem in 'MoveHistoryItem.pas',
7777 SambaTimer in 'SambaTimer.pas',
7878 HistoryList in 'HistoryList.pas',
79- NewBoardURL in 'NewBoardURL.pas' {NewBoardURLForm};
79+ NewBoardURL in 'NewBoardURL.pas' {NewBoardURLForm},
80+ NGWordUnit in 'NGWordUnit.pas',
81+ NGWordEdit in 'NGWordEdit.pas' {NGWordEditForm};
8082
8183 {$R *.RES}
8284 {$R gikoResource.res}
Binary files a/gikoNavi.res and b/gikoNavi.res differ
--- a/readme/readme.txt
+++ b/readme/readme.txt
@@ -1,4 +1,4 @@
1-■ギコナビ Version1.00 バタ54 Readme.txt
1+■ギコナビ Version1.00 バタ55 Readme.txt
22
33
44 ------------------------------
@@ -107,6 +107,10 @@ LICENSE
107107 ------------------------------
108108 履歴
109109 ------------------------------
110+2007/XX/YY
111+ Version バタ55
112+ 詳細設定に、関連キーワードのリンクを追加するオプションを追加
113+
110114 2007/01/28
111115 Version バタ54
112116  スレッド内でのリンクで移動したときの履歴を辿れる機能を追加
Show on old repository browser