Develop and Download Open Source Software

Browse CVS Repository

Annotation of /gikonavigoeson/gikonavi/ExternalThreadItem.pas

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.8 - (hide annotations) (download) (as text)
Mon Dec 1 14:32:40 2003 UTC (20 years, 4 months ago) by h677
Branch: MAIN
Changes since 1.7: +2 -1 lines
File MIME type: text/x-pascal
極力レスポップできるようにしたけど、差し戻しになるかも。
掲示板の方でリンク張られている以外のレスアンカーにURLを付加しました。

1 yoffy 1.1 unit ExternalThreadItem;
2    
3     interface
4    
5     uses
6     Windows, Classes, SysUtils,
7     IdComponent,
8     ExternalBoardPlugInMain;
9    
10     type
11     // TThreadItem ???????????h┃絎?鐚??緇? ID
12     TThreadItemProperty = (
13     tipContext, // : DWORD // ???宴??┃絎???????????/span>
14     tipNo, // : Integer // ???/span>
15     tipFileName, // : string // ?鴻?????????<?ゃ????
16     tipTitle, // : string // ?鴻???????帥?ゃ????/span>
17     tipRoundDate, // : TDateTime // ?鴻??????????緇??????ユ??鐚?綏≦???ユ??鐚?
18     tipLastModified, // : TDateTime // ?鴻?????????贋?違???????????ユ??鐚??泣?若???贋?ユ??鐚?
19     tipCount, // : Integer // ?鴻???????????潟??鐚????若?????
20     tipAllResCount, // : Integer // ?鴻???????????潟??鐚??泣?若??鐚?
21     tipNewResCount, // : Integer // ?鴻???????亥????/span>
22     tipSize, // : Integer // ?鴻???????泣?ゃ??/span>
23     tipRound, // : Boolean // 綏≦????????/span>
24     tipRoundName, // : string // 綏≦????
25     tipIsLogFile, // : Boolean // ???医?????????/span>
26     tipKokomade, // : Integer // ?潟?潟?障?ц????????/span>
27     tipNewReceive, // : Integer // ?潟?潟?????域???篆?/span>
28     tipNewArrival, // : Boolean // ?亥??
29     tipUnRead, // : Boolean // ?????????/span>
30     tipScrollTop, // : Integer // ?鴻?????若???臀?/span>
31     tipDownloadHost, // : string // 篁??????鴻?????????翫???????鴻??
32     tipAgeSage, // : TThreadAgeSage // ?≪?ゃ?????????筝???
33     tipURL, // : string // ?鴻???????????????吟?ц;腓冴??????? URL
34     tipFilePath // : string // ?????鴻????篆?絖???????????????/span>
35     );
36    
37     // *************************************************************************
38     // TThreadItem ????????????
39     // *************************************************************************
40     TThreadItemCreate = procedure(
41     inInstance : DWORD
42     ); stdcall;
43    
44     // *************************************************************************
45     // TThreadItem ???贋???????
46     // *************************************************************************
47     TThreadItemDispose = procedure(
48     inInstance : DWORD
49     ); stdcall;
50    
51     // *************************************************************************
52     // ?????潟???若??????腓?/span>
53     // *************************************************************************
54     TThreadItemOnDownload = function(
55     inInstance : DWORD // ?ゃ?潟?鴻?帥?潟??/span>
56     ) : TDownloadState; stdcall; // ?????潟???若????????????????????
57    
58     // *************************************************************************
59 yoffy 1.2 // ?吾??莨若?帥????腓?/span>
60     // *************************************************************************
61     TThreadItemOnWrite = function(
62     inInstance : DWORD; // ThreadItem ???ゃ?潟?鴻?帥?潟??/span>
63     inName : PChar; // ????(??潟????
64     inMail : PChar; // ?<?若???≪??????/span>
65     inMessage : PChar // ????
66     ) : TDownloadState; stdcall; // ?吾??莨若?帥??????????????????
67    
68     // *************************************************************************
69 yoffy 1.1 // ???合?? n ??????? html ??荀?羆?
70     // *************************************************************************
71     TThreadItemOnGetRes = function(
72     inInstance : DWORD; // ?ゃ?潟?鴻?帥?潟??/span>
73     inNo : DWORD // 茵?ず???????合???/span>
74     ) : PChar; stdcall; // 茵?ず???? HTML
75    
76     // *************************************************************************
77     // ?鴻?????????????? html ??荀?羆?
78     // *************************************************************************
79     TThreadItemOnGetHeader = function(
80     inInstance : DWORD; // ThreadItem ???ゃ?潟?鴻?帥?潟??/span>
81     inOptionalHeader : PChar // 菴遵??????????
82     ) : PChar; stdcall; // ?翫就?????? HTML
83    
84     // *************************************************************************
85     // ?鴻????????????? html ??荀?羆?
86     // *************************************************************************
87     TThreadItemOnGetFooter = function(
88     inInstance : DWORD; // ThreadItem ???ゃ?潟?鴻?帥?潟??/span>
89     inOptionalFooter : PChar // 菴遵??????????/span>
90     ) : PChar; stdcall; // ?翫就?????? HTML
91    
92 yoffy 1.2 // *************************************************************************
93     // ??? ThreadItem ??絮??????帥? URL ??荀?羆?
94     // *************************************************************************
95     TThreadItemOnGetBoardURL = function(
96     inInstance : DWORD // ThreadItem ???ゃ?潟?鴻?帥?潟??/span>
97     ) : PChar; stdcall; // ?帥? URL
98 yoffy 1.1
99     function ThreadItemDat2HTML(
100     inInstance : DWORD; // ThreadItem ???ゃ?潟?鴻?帥?潟??/span>
101     inDatRes : PChar; // ????<>?<?若??lt;>?ヤ?ID<>????<> ?ф??????????????鴻??
102     inResNo : DWORD; // ???合???/span>
103     inIsNew : Boolean // ?亥?????鴻???? True
104     ) : PChar; stdcall; // ?翫就?????? HTML
105    
106     implementation
107    
108     uses ExternalBoardManager, GikoSystem, BoardGroup;
109    
110     // *************************************************************************
111     // TThreadItem ?????鴻???????????c????緇?????
112     // *************************************************************************
113     function ThreadItemGetLong(
114     instance : DWORD;
115     propertyID : TThreadItemProperty
116     ) : DWORD; stdcall;
117     var
118     threadItem : TThreadItem;
119     begin
120    
121     threadItem := TThreadItem( instance );
122     case propertyID of
123     tipContext: // : DWORD // ???宴??┃絎???????????/span>
124     Result := threadItem.Context;
125     tipNo: // : Integer // ???/span>
126     Result := threadItem.No;
127     tipFileName: // : string // ?鴻?????????<?ゃ????
128     Result := DWORD( CreateResultString( threadItem.FileName ) );
129     tipTitle: // : string // ?鴻???????帥?ゃ????/span>
130     Result := DWORD( CreateResultString( threadItem.Title ) );
131     tipCount: // : Integer // ?鴻???????????潟??鐚????若?????
132     Result := threadItem.Count;
133     tipAllResCount: // : Integer // ?鴻???????????潟??鐚??泣?若??鐚?
134     Result := threadItem.AllResCount;
135     tipNewResCount: // : Integer // ?鴻???????亥????/span>
136     Result := threadItem.NewResCount;
137     tipSize: // : Integer // ?鴻???????泣?ゃ??/span>
138     Result := threadItem.Size;
139     tipRound: // : Boolean // 綏≦????????/span>
140     Result := DWORD( threadItem.Round );
141     tipRoundName: // : string // 綏≦????
142     Result := DWORD( CreateResultString( threadItem.RoundName ) );
143     tipIsLogFile: // : Boolean // ???医?????????/span>
144     Result := DWORD( threadItem.IsLogFile );
145     tipKokomade: // : Integer // ?潟?潟?障?ц????????/span>
146     Result := threadItem.Kokomade;
147     tipNewReceive: // : Integer // ?潟?潟?????域???篆?/span>
148     Result := threadItem.NewReceive;
149     tipNewArrival: // : Boolean // ?亥??
150     Result := DWORD( threadItem.NewArrival );
151     tipUnRead: // : Boolean // ?????????/span>
152     Result := DWORD( threadItem.UnRead );
153     tipScrollTop: // : Integer // ?鴻?????若???臀?/span>
154     Result := threadItem.ScrollTop;
155     tipDownloadHost: // : string // 篁??????鴻?????????翫???????鴻??
156     Result := DWORD( CreateResultString( threadItem.DownloadHost ) );
157     tipAgeSage: // : TThreadAgeSage // ?≪?ゃ?????????筝???
158     Result := DWORD( threadItem.AgeSage );
159     tipURL: // : string // ?鴻???????????????吟?ц;腓冴??????? URL
160     Result := DWORD( CreateResultString( threadItem.URL ) );
161     tipFilePath: // ?????鴻????篆?絖???????????????/span>
162     Result := DWORD( CreateResultString( threadItem.FilePath ) );
163     else
164     Result := 0;
165     end;
166     end;
167    
168     // *************************************************************************
169     // TThreadItem ?????鴻???????????c??荐??????
170     // *************************************************************************
171     procedure ThreadItemSetLong(
172     instance : DWORD;
173     propertyID : TThreadItemProperty;
174     param : DWORD
175     ); stdcall;
176     var
177     threadItem : TThreadItem;
178     begin
179    
180     threadItem := TThreadItem( instance );
181     case propertyID of
182     tipContext: // : DWORD // ???宴??┃絎???????????/span>
183     threadItem.Context := param;
184     tipNo: // : Integer // ???/span>
185     threadItem.No := param;
186     tipFileName: // : string // ?鴻?????????<?ゃ????
187     threadItem.FileName := string( PChar( param ) );
188     tipTitle: // : string // ?鴻???????帥?ゃ????/span>
189     threadItem.Title := string( PChar( param ) );
190     tipCount: // : Integer // ?鴻???????????潟??鐚????若?????
191     threadItem.Count := param;
192     tipAllResCount: // : Integer // ?鴻???????????潟??鐚??泣?若??鐚?
193     threadItem.AllResCount := param;
194     tipNewResCount: // : Integer // ?鴻???????亥????/span>
195     threadItem.NewResCount := param;
196     tipSize: // : Integer // ?鴻???????泣?ゃ??/span>
197     threadItem.Size := param;
198     tipRound: // : Boolean // 綏≦????????/span>
199     threadItem.Round := Boolean( param );
200     tipRoundName: // : string // 綏≦????
201     threadItem.RoundName := string( PChar( param ) );
202     tipIsLogFile: // : Boolean // ???医?????????/span>
203     threadItem.IsLogFile := Boolean( param );
204     tipKokomade: // : Integer // ?潟?潟?障?ц????????/span>
205     threadItem.Kokomade := param;
206     tipNewReceive: // : Integer // ?潟?潟?????域???篆?/span>
207     threadItem.NewReceive := param;
208     tipNewArrival: // : Boolean // ?亥??
209     threadItem.NewArrival := Boolean( param );
210     tipUnRead: // : Boolean // ?????????/span>
211     threadItem.UnRead := Boolean( param );
212     tipScrollTop: // : Integer // ?鴻?????若???臀?/span>
213     threadItem.ScrollTop := param;
214     tipDownloadHost: // : string // 篁??????鴻?????????翫???????鴻??
215     threadItem.DownloadHost := string( PChar( param ) );
216     tipAgeSage: // : TThreadAgeSage // ?≪?ゃ?????????筝???
217     threadItem.AgeSage := TGikoAgeSage( param );
218     tipURL: // : string // ?鴻???????????????吟?ц;腓冴??????? URL
219     threadItem.URL := string( PChar( param ) );
220     tipFilePath: // : string // ?????鴻????篆?絖???????????????/span>
221     threadItem.FilePath := string( PChar( param ) );
222     end;
223    
224     end;
225    
226     // *************************************************************************
227     // TThreadItem ?????鴻???????????c????緇?????
228     // *************************************************************************
229     function ThreadItemGetDouble(
230     instance : DWORD;
231     propertyID : TThreadItemProperty
232     ) : Double; stdcall;
233     var
234     threadItem : TThreadItem;
235     begin
236    
237     threadItem := TThreadItem( instance );
238     case propertyID of
239     tipRoundDate: // : TDateTime // ?鴻??????????緇??????ユ??鐚?綏≦???ユ??鐚?
240     Result := threadItem.RoundDate;
241     tipLastModified: // : TDateTime // ?鴻?????????贋?違???????????ユ??鐚??泣?若???贋?ユ??鐚?
242     Result := threadItem.LastModified;
243     else
244     Result := 0;
245     end;
246    
247     end;
248    
249     // *************************************************************************
250     // TThreadItem ?????鴻???????????c??荐??????
251     // *************************************************************************
252     procedure ThreadItemSetDouble(
253     instance : DWORD;
254     propertyID : TThreadItemProperty;
255     param : Double
256     ); stdcall;
257     var
258     threadItem : TThreadItem;
259     begin
260    
261     threadItem := TThreadItem( instance );
262     case propertyID of
263     tipRoundDate: // : TDateTime // ?鴻??????????緇??????ユ??鐚?綏≦???ユ??鐚?
264     threadItem.RoundDate := param;
265     tipLastModified: // : TDateTime // ?鴻?????????贋?違???????????ユ??鐚??泣?若???贋?ユ??鐚?
266     threadItem.LastModified := param;
267     end;
268    
269     end;
270    
271     // *************************************************************************
272     // TThreadItem ?????鴻????????<????????? dat 綵√? 1 茵??? HTML ?????????
273     // *************************************************************************
274     function ThreadItemDat2HTML(
275     inInstance : DWORD; // ThreadItem ???ゃ?潟?鴻?帥?潟??/span>
276     inDatRes : PChar; // ????<>?<?若??lt;>?ヤ?ID<>????<> ?ф??????????????鴻??
277     inResNo : DWORD; // ???合???/span>
278     inIsNew : Boolean // ?亥?????鴻???? True
279     ) : PChar; stdcall; // ?翫就?????? HTML
280     var
281     threadItem : TThreadItem;
282     res : TResRec;
283     no : string;
284     begin
285    
286     threadItem := TThreadItem( inInstance );
287     // 綣??違????茹?/span>
288     res := GikoSys.DivideStrLine( string( inDatRes ) );
289 h677 1.6 if AnsiCompareStr( string( inDatRes ) , '' ) <> 0 then begin
290     res.FBody := GikoSys.AddAnchorTag( res.FBody );
291 h677 1.8 res.FBody := GikoSys.ConvRes( res.FBody, threadItem.ParentBoard.BBSID, ChangeFileExt( threadItem.FileName, '' ), 'bbs', 'key', 'st', 'to', 'nofirst', 'true',threadItem.URL );
292    
293 h677 1.6 no := IntToStr( inResNo );
294 yoffy 1.1
295 h677 1.6 try
296     if GikoSys.Setting.UseSkin then begin
297     // ?鴻????/span>
298     if inIsNew then
299     Result := CreateResultString( GikoSys.SkinedRes(
300     GikoSys.LoadFromSkin(
301     GikoSys.Setting.GetSkinNewResFileName, threadItem, threadItem.SizeByte
302     ), res, no
303     ) )
304     else
305     Result := CreateResultString( GikoSys.SkinedRes(
306     GikoSys.LoadFromSkin(
307     GikoSys.Setting.GetSkinResFileName, threadItem, threadItem.SizeByte
308     ), res, no
309     ) );
310     end else if GikoSys.Setting.UseCSS then begin
311     // CSS
312     if res.FName = '' then
313     res.FName := '&nbsp;';
314     if res.FMailTo = '' then
315     Result := CreateResultString( '<a name="' + no + '"></a>'
316     + '<div class="header"><span class="no"><a href="menu:' + No + '">' + no + '</a></span> '
317     + '<span class="name_label">????鐚?</span> '
318     + '<span class="name"><b>' + res.FName + '</b></span> '
319     + '<span class="date_label">??腮炊?ワ?</span> '
320     + '<span class="date">' + res.FDateTime+ '</span></div>'
321     + '<div class="mes">' + res.FBody + ' </div>' )
322     else if GikoSys.Setting.ShowMail then
323     Result := CreateResultString( '<a name="' + no + '"></a>'
324     + '<div class="header"><span class="no"><a href="menu:' + no + '">' + no + '</a></span>'
325     + '<span class="name_label"> ????鐚? </span>'
326     + '<a class="name_mail" href="mailto:' + res.FMailTo + '">'
327     + '<b>' + res.FName + '</b></a><span class="mail"> [' + res.FMailTo + ']</span>'
328     + '<span class="date_label"> ??腮炊?ワ?</span>'
329     + '<span class="date"> ' + res.FDateTime+ '</span></div>'
330     + '<div class="mes">' + res.FBody + ' </div>' )
331     else
332     Result := CreateResultString( '<a name="' + no + '"></a>'
333     + '<div class="header"><span class="no"><a href="menu:' + no + '">' + no + '</a></span>'
334     + '<span class="name_label"> ????鐚? </span>'
335     + '<a class="name_mail" href="mailto:' + res.FMailTo + '">'
336     + '<b>' + res.FName + '</b></a>'
337     + '<span class="date_label"> ??腮炊?ワ?</span>'
338     + '<span class="date"> ' + res.FDateTime+ '</span></div>'
339     + '<div class="mes">' + res.FBody + ' </div>' );
340     end else begin
341     // ??????????
342     if res.FMailTo = '' then
343     Result := CreateResultString( '<a name="' + no + '"></a><dt><a href="menu:' + no + '">' + no + '</a> ????鐚?<font color="forestgreen"><b> ' + res.FName + ' </b></font> ??腮炊?ワ? ' + res.FDateTime+ '<br><dd>' + res.Fbody + ' <br><br><br>' )
344     else if GikoSys.Setting.ShowMail then
345     Result := CreateResultString( '<a name="' + no + '"></a><dt><a href="menu:' + no + '">' + no + '</a> ????鐚?<a href="mailto:' + res.FMailTo + '"><b> ' + res.FName + ' </B></a> [' + res.FMailTo + '] ??腮炊?ワ? ' + res.FDateTime+ '<br><dd>' + res.Fbody + ' <br><br><br>' )
346     else
347     Result := CreateResultString( '<a name="' + no + '"></a><dt><a href="menu:' + no + '">' + no + '</a> ????鐚?<a href="mailto:' + res.FMailTo + '"><b> ' + res.FName + ' </B></a> ??腮炊?ワ? ' + res.FDateTime+ '<br><dd>' + res.Fbody + ' <br><br><br>' );
348     end;
349     except
350     Result := nil;
351     end;
352     end else begin
353     Result := nil;
354     end;
355 yoffy 1.1
356     end;
357    
358     // *************************************************************************
359     // TThreadItem ?????鴻???????鴻??????????????????緇?????
360     // *************************************************************************
361     function ThreadItemGetHeader(
362     inInstance : DWORD; // ThreadItem ???ゃ?潟?鴻?帥?潟??/span>
363     inOptionalHeader : PChar // 菴遵??????????
364     ) : PChar; stdcall; // ?翫就?????? HTML
365     var
366     threadItem : TThreadItem;
367     skinHeader : string;
368     optionalHeader : string;
369     begin
370    
371     {$IFDEF DEBUG}
372     Writeln('ExternalBoardManager.ThreadItemGetHeader');
373     {$ENDIF}
374     threadItem := TThreadItem( inInstance );
375     optionalHeader := string( inOptionalHeader );
376    
377     try
378     if GikoSys.Setting.UseSkin then begin
379     // ?鴻????/span>
380     skinHeader := GikoSys.LoadFromSkin( GikoSys.Setting.GetSkinHeaderFileName, threadItem, threadItem.SizeByte );
381     if Length( optionalHeader ) > 0 then
382     skinHeader :=
383 yoffy 1.3 StringReplace( skinHeader, '</head>', optionalHeader + '</head><a name="top"></a>', [] );
384 yoffy 1.1 end else if GikoSys.Setting.UseCSS then begin
385     // CSS
386     skinHeader :=
387     '<html><head>' +
388     '<title>' + threadItem.Title + '</title>' +
389     '<link rel="stylesheet" href="'+ GikoSys.Setting.GetStyleSheetDir + GikoSys.Setting.CSSFileName +'" type="text/css">' +
390     optionalHeader +
391     '</head>' +
392     '<body>' +
393 yoffy 1.3 '<a name="top"></a>' +
394 yoffy 1.1 '<div class="title">' + threadItem.Title + '</div>';
395     end else begin
396     // ??????????
397     skinHeader :=
398     '<html><head>' +
399     '<title>' + threadItem.Title + '</title>' +
400     optionalHeader +
401     '</head>' +
402 yoffy 1.3 '<body TEXT="#000000" BGCOLOR="#EFEFEF" link="#0000FF" alink="#FF0000" vlink="#660099">' +
403     '<a name="top"></a>' +
404     '<font size=+1 color="#FF0000">' + threadItem.Title + '</font>' +
405     '<dl>';
406 yoffy 1.1 end;
407     except
408     end;
409    
410     Result := CreateResultString( skinHeader );
411    
412     end;
413    
414     // *************************************************************************
415     // TThreadItem ?????鴻???????鴻?????????????帥????緇?????
416     // *************************************************************************
417     function ThreadItemGetFooter(
418     inInstance : DWORD; // ThreadItem ???ゃ?潟?鴻?帥?潟??/span>
419     inOptionalFooter : PChar // 菴遵??????????/span>
420     ) : PChar; stdcall; // ?翫就?????? HTML
421     var
422     threadItem : TThreadItem;
423     skinFooter : string;
424     optionalFooter : string;
425     begin
426    
427     {$IFDEF DEBUG}
428     Writeln('ExternalBoardManager.ThreadItemGetFooter');
429     {$ENDIF}
430     threadItem := TThreadItem( inInstance );
431     optionalFooter := string( inOptionalFooter );
432    
433     try
434     if GikoSys.Setting.UseSkin then begin
435 yoffy 1.3 // ?鴻????/span>
436 yoffy 1.1 skinFooter := GikoSys.LoadFromSkin( GikoSys.Setting.GetSkinFooterFileName, threadItem, threadItem.SizeByte );
437     if Length( optionalFooter ) > 0 then
438     skinFooter :=
439     StringReplace( skinFooter, '</body>', optionalFooter + '</body>', [] );
440 yoffy 1.3 end else if GikoSys.Setting.UseCSS then begin
441     // CSS
442     skinFooter :=
443     optionalFooter +
444     '</body></html>' +
445     '<a name="last"></a>' +
446     '</body></html>';
447 yoffy 1.1 end else begin
448 yoffy 1.3 // ??????????
449     skinFooter :=
450     '</dl>' +
451     optionalFooter +
452     '</body></html>' +
453     '<a name="last"></a>' +
454     '</body></html>';
455 yoffy 1.1 end;
456     except
457     end;
458    
459     Result := CreateResultString( skinFooter );
460    
461     end;
462    
463     // *************************************************************************
464     // ?鴻?????????????潟???若?????画?????
465     // *************************************************************************
466     procedure ThreadItemWork(
467     inInstance : DWORD; // ThreadItem ???ゃ?潟?鴻?帥?潟??/span>
468     inWorkCount : Integer // ?上?????我??倶?(?????潟??)
469     ); stdcall;
470     begin
471    
472     if Assigned( OnWork ) then
473     OnWork( TObject( inInstance ), wmRead, inWorkCount );
474    
475     end;
476    
477     // *************************************************************************
478     // ?鴻?????????????潟???若????紮??障?c??
479     // *************************************************************************
480     procedure ThreadItemWorkBegin(
481     inInstance : DWORD; // ThreadItem ???ゃ?潟?鴻?帥?潟??/span>
482     inWorkCountMax : Integer // ??篆<????????腓冴???????潟??
483     ); stdcall;
484     begin
485    
486     if Assigned( OnWorkBegin ) then
487     OnWorkBegin( TObject( inInstance ), wmRead, inWorkCountMax );
488    
489     end;
490    
491     // *************************************************************************
492     // ?鴻?????????????潟???若????腟???c??
493     // *************************************************************************
494     procedure ThreadItemWorkEnd(
495     inInstance : DWORD // ThreadItem ???ゃ?潟?鴻?帥?潟??/span>
496     ); stdcall;
497     begin
498    
499     if Assigned( OnWorkEnd ) then
500     OnWorkEnd( TObject( inInstance ), wmRead );
501    
502     end;
503    
504     exports
505     ThreadItemGetLong,
506     ThreadItemSetLong,
507     ThreadItemGetDouble,
508     ThreadItemSetDouble,
509     ThreadItemDat2HTML,
510     ThreadItemGetHeader,
511     ThreadItemGetFooter,
512     ThreadItemWork,
513     ThreadItemWorkBegin,
514     ThreadItemWorkEnd;
515    
516     end.
517    

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26