source: branches/AlphaChannel/LocalPlayer/Help.pas

Last change on this file was 261, checked in by chronos, 4 years ago
  • Added: Partial support for key bindings configuration.
File size: 78.3 KB
Line 
1{$INCLUDE Switches.inc}
2unit Help;
3
4interface
5
6uses
7 Protocol, ScreenTools, BaseWin, StringTables, Math, LCLIntf, LCLType,
8 Messages, SysUtils, Classes, Graphics, Controls, Forms, ExtCtrls,
9 ButtonB, PVSB, Types, fgl;
10
11const
12 MaxHist = 16;
13
14 { link categories }
15 hkNoLink = 0;
16 hkAdv = 1;
17 hkImp = 2;
18 hkTer = 3;
19 hkFeature = 4;
20 hkInternet = 5;
21 hkModel = 6;
22 hkMisc = 7;
23 hkCrossLink = $40;
24 hkText = $80;
25
26 liInvalid = $3FFF; // link index indicates invalid link
27
28 { link indices for category hkMisc }
29 miscMain = 0;
30 miscCredits = 1;
31 miscGovList = 2;
32 miscJobList = 3;
33 miscSearchResult = 7;
34
35 fJungle = 8; // pseudo terrain
36
37type
38
39 { THyperText }
40
41 THyperText = class(TStringList)
42 public
43 procedure AddLine(s: String = ''; Format: integer = 0; Picpix: Integer = 0;
44 LinkCategory: integer = 0; LinkIndex: integer = 0);
45 procedure LineFeed;
46 procedure AppendList(Source: THyperText);
47 destructor Destroy; override;
48 end;
49
50 { THistItem }
51
52 THistItem = class
53 Kind: Integer;
54 No: Integer;
55 Pos: Integer;
56 SearchContent: string;
57 procedure Assign(Source: THistItem);
58 end;
59
60 { THistItems }
61
62 THistItems = class(TFPGObjectList<THistItem>)
63 function AddNew(Kind, No, Pos: Integer; SearchContent: string): THistItem;
64 end;
65
66 { THelpDlg }
67
68 THelpDlg = class(TFramedDlg)
69 CloseBtn: TButtonB;
70 BackBtn: TButtonB;
71 TopBtn: TButtonB;
72 SearchBtn: TButtonB;
73 procedure FormCreate(Sender: TObject);
74 procedure FormDestroy(Sender: TObject);
75 procedure FormMouseWheel(Sender: TObject; Shift: TShiftState;
76 WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
77 procedure FormPaint(Sender: TObject);
78 procedure CloseBtnClick(Sender: TObject);
79 procedure PaintBox1MouseMove(Sender: TObject; Shift: TShiftState;
80 x, y: integer);
81 procedure PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
82 Shift: TShiftState; x, y: integer);
83 procedure BackBtnClick(Sender: TObject);
84 procedure TopBtnClick(Sender: TObject);
85 procedure FormClose(Sender: TObject; var Action: TCloseAction);
86 procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
87 procedure SearchBtnClick(Sender: TObject);
88 protected
89 procedure OffscreenPaint; override;
90 private
91 Kind: Integer;
92 no: Integer;
93 Sel: Integer;
94 CaptionColor: Integer;
95 hADVHELP, hIMPHELP, hFEATUREHELP, hGOVHELP, hSPECIALMODEL, hJOBHELP: Integer;
96 SearchContent: string;
97 NewSearchContent: string;
98 CaptionFont: TFont;
99 MainText: THyperText;
100 SearchResult: THyperText;
101 HelpText: TStringTable;
102 ExtPic, TerrIcon: TBitmap;
103 ScrollBar: TPVScrollbar;
104 x0: array [-2..180] of Integer;
105 procedure PaintTerrIcon(x, y, xSrc, ySrc: Integer);
106 procedure ScrollBarUpdate(Sender: TObject);
107 procedure Line(ca: TCanvas; i: Integer; lit: Boolean);
108 procedure Prepare(sbPos: Integer = 0);
109 procedure ShowNewContentProcExecute(NewMode: Integer; HelpContext: string);
110 procedure WaterSign(x0, y0, iix: Integer);
111 procedure Search(SearchString: string);
112 procedure OnScroll(var m: TMessage); message WM_VSCROLL;
113 procedure OnMouseLeave(var Msg: TMessage); message CM_MOUSELEAVE;
114 public
115 HistItems: THistItems;
116 Difficulty: Integer;
117 procedure ClearHistory;
118 procedure ShowNewContent(NewMode, Category, Index: Integer);
119 function TextIndex(Item: string): Integer;
120 end;
121
122var
123 HelpDlg: THelpDlg;
124
125
126implementation
127
128uses
129 Directories, ClientTools, Term, Tribes, Inp, Messg, UPixelPointer, Global,
130 UKeyBindings;
131
132{$R *.lfm}
133
134type
135
136 { THelpLineInfo }
137
138 THelpLineInfo = class
139 Format: Byte;
140 Picpix: Byte;
141 Link: Word;
142 procedure Assign(Source: THelpLineInfo);
143 end;
144
145{ THelpLineInfo }
146
147procedure THelpLineInfo.Assign(Source: THelpLineInfo);
148begin
149 Format := Source.Format;
150 PicPix := Source.PicPix;
151 Link := Source.Link;
152end;
153
154{ THistItem }
155
156procedure THistItem.Assign(Source: THistItem);
157begin
158 Kind := Source.Kind;
159 No := Source.No;
160 Pos := Source.Pos;
161 SearchContent := Source.SearchContent;
162end;
163
164{ THistItems }
165
166function THistItems.AddNew(Kind, No, Pos: Integer; SearchContent: string
167 ): THistItem;
168begin
169 Result := THistItem.Create;
170 Result.Kind := Kind;
171 Result.No := No;
172 Result.Pos := Pos;
173 Result.SearchContent := SearchContent;
174 Add(Result);
175end;
176
177procedure THyperText.AddLine(s: String; Format: integer; Picpix: integer;
178 LinkCategory: integer; LinkIndex: integer);
179var
180 HelpLineInfo: THelpLineInfo;
181begin
182 HelpLineInfo := THelpLineInfo.Create;
183 if LinkIndex < 0 then
184 LinkIndex := liInvalid;
185 HelpLineInfo.Format := Format;
186 HelpLineInfo.Picpix := Picpix;
187 HelpLineInfo.Link := LinkCategory shl 8 + LinkIndex;
188 AddObject(s, TObject(HelpLineInfo));
189end;
190
191procedure THyperText.LineFeed;
192begin
193 AddLine;
194end;
195
196procedure THyperText.AppendList(Source: THyperText);
197var
198 I: Integer;
199 HelpLineInfo: THelpLineInfo;
200begin
201 for I := 0 to Source.Count - 1 do begin
202 HelpLineInfo := THelpLineInfo.Create;
203 HelpLineInfo.Assign(THelpLineInfo(Source.Objects[I]));
204 AddObject(Source.Strings[I], HelpLineInfo);
205 end;
206end;
207
208destructor THyperText.Destroy;
209begin
210 inherited Destroy;
211end;
212
213const
214 { text formats }
215 pkNormal = 0;
216 pkCaption = 1;
217 pkSmallIcon = 2;
218 pkBigIcon = 3;
219 pkAdvIcon = 4;
220 pkTer = 5;
221 pkBigTer = 6;
222 pkFeature = 7;
223 pkDot = 8;
224 pkNormal_Dot = 9;
225 pkDomain = 10;
226 pkSection = 11;
227 pkBigFeature = 12;
228 pkExp = 13;
229 pkAITStat = 14;
230 pkExternal = 15;
231 pkModel = 16;
232 pkNormal_64 = 17;
233 pkIllu = 18;
234 pkLogo = 19;
235 pkTerImp = 20;
236 pkRightIcon = 21;
237 pkAdvIcon_AsPreq = 22;
238 pkSmallIcon_AsPreq = 23;
239 pkSpecialIcon = 24;
240 pkGov = 25;
241
242 nSeeAlso = 14;
243 SeeAlso: array [0 .. nSeeAlso - 1] of record Kind, no, SeeKind,
244 SeeNo: integer end = ((Kind: hkImp; no: imWalls; SeeKind: hkFeature;
245 SeeNo: mcArtillery), (Kind: hkImp; no: imHydro; SeeKind: hkImp;
246 SeeNo: woHoover), (Kind: hkImp; no: imWalls; SeeKind: hkImp;
247 SeeNo: imGrWall), (Kind: hkImp; no: imHighways; SeeKind: hkAdv;
248 SeeNo: adWheel), (Kind: hkImp; no: imCathedral; SeeKind: hkImp;
249 SeeNo: woBach), (Kind: hkImp; no: imBank; SeeKind: hkImp; SeeNo: imStockEx),
250 (Kind: hkImp; no: imShipComp; SeeKind: hkImp; SeeNo: imSpacePort),
251 (Kind: hkImp; no: imShipPow; SeeKind: hkImp; SeeNo: imSpacePort),
252 (Kind: hkImp; no: imShipHab; SeeKind: hkImp; SeeNo: imSpacePort),
253 (Kind: hkFeature; no: mcSub; SeeKind: hkFeature; SeeNo: mcRadar),
254 (Kind: hkFeature; no: mcDefense; SeeKind: hkAdv; SeeNo: adSteel),
255 (Kind: hkFeature; no: mcSE; SeeKind: hkFeature; SeeNo: mcNP), (Kind: hkAdv;
256 no: adWheel; SeeKind: hkImp; SeeNo: imHighways), (Kind: hkAdv; no: adSteel;
257 SeeKind: hkFeature; SeeNo: mcDefense));
258
259 nTerrainHelp = 14;
260 TerrainHelp: array [0 .. nTerrainHelp - 1] of integer = (fGrass, fGrass + 12,
261 fPrairie, fForest, fJungle, fHills, fMountains, fSwamp, fTundra, fArctic,
262 fDesert, 3 * 12 { DeadLands } , fShore, fOcean);
263
264 nJobHelp = 8;
265 JobHelp: array [0 .. nJobHelp - 1] of integer = (jRoad, jRR, jCanal, jIrr,
266 jFarm, jMine, jFort, jBase);
267
268procedure THelpDlg.FormCreate(Sender: TObject);
269begin
270 inherited;
271 HistItems := THistItems.Create;
272
273 CaptionLeft := BackBtn.Left + BackBtn.Width;
274 CaptionRight := SearchBtn.Left;
275 inc(ModalFrameIndent, 29);
276 MainText := THyperText.Create;
277 MainText.OwnsObjects := True;
278 SearchResult := THyperText.Create;
279 SearchResult.OwnsObjects := True;
280 ScrollBar := TPVScrollbar.Create(Self);
281 ScrollBar.SetBorderSpacing(36, 9, 11);
282 ScrollBar.OnUpdate := ScrollBarUpdate;
283
284 HelpText := TStringTable.Create;
285 HelpText.LoadFromFile(LocalizedFilePath('Help' + DirectorySeparator + 'help.txt'));
286 hADVHELP := HelpText.Gethandle('ADVHELP');
287 hIMPHELP := HelpText.Gethandle('IMPHELP');
288 hFEATUREHELP := HelpText.Gethandle('FEATUREHELP');
289 hGOVHELP := HelpText.Gethandle('GOVHELP');
290 hSPECIALMODEL := HelpText.Gethandle('SPECIALMODEL');
291 hJOBHELP := HelpText.Gethandle('JOBHELP');
292
293 CaptionFont := Font.Create;
294 CaptionFont.Assign(UniFont[ftNormal]);
295 CaptionFont.Style := CaptionFont.Style + [fsItalic, fsBold];
296 InitButtons();
297
298 TopBtn.Hint := Phrases.Lookup('BTN_CONTENTS');
299 BackBtn.Hint := Phrases.Lookup('BTN_BACK');
300 SearchBtn.Hint := Phrases.Lookup('BTN_SEARCH');
301
302 ExtPic := TBitmap.Create;
303 TerrIcon := TBitmap.Create;
304 TerrIcon.PixelFormat := pf24bit;
305 TerrIcon.SetSize(xSizeBig, ySizeBig);
306 TerrIcon.Canvas.FillRect(0, 0, TerrIcon.Width, TerrIcon.Height);
307 SearchContent := '';
308 ShowNewContentProc := ShowNewContentProcExecute;
309end;
310
311procedure THelpDlg.ShowNewContentProcExecute(NewMode: Integer;
312 HelpContext: string);
313begin
314 HelpDlg.ShowNewContent(NewMode, hkText,
315 HelpDlg.TextIndex(HelpContext))
316end;
317
318procedure THelpDlg.FormDestroy(Sender: TObject);
319begin
320 ShowNewContentProc := nil;
321 FreeAndNil(ScrollBar);
322 FreeAndNil(MainText);
323 FreeAndNil(SearchResult);
324 FreeAndNil(ExtPic);
325 FreeAndNil(TerrIcon);
326 FreeAndNil(HelpText);
327 // FreeAndNil(CaptionFont);
328 FreeAndNil(HistItems);
329end;
330
331procedure THelpDlg.FormMouseWheel(Sender: TObject; Shift: TShiftState;
332 WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
333begin
334 if ScrollBar.ProcessMouseWheel(WheelDelta) then begin
335 PaintBox1MouseMove(nil, [], MousePos.X - Left,
336 MousePos.Y - Top);
337 end;
338end;
339
340procedure THelpDlg.CloseBtnClick(Sender: TObject);
341begin
342 Close;
343end;
344
345procedure THelpDlg.OnScroll(var m: TMessage);
346begin
347 { TODO: Handled by MouseWheel event
348 if ScrollBar.Process(m) then begin
349 Sel := -1;
350 SmartUpdateContent(true)
351 end;
352 }
353end;
354
355procedure THelpDlg.OnMouseLeave(var Msg: TMessage);
356begin
357 if Sel <> -1 then begin
358 Line(Canvas, Sel, false);
359 Sel := -1
360 end
361end;
362
363procedure THelpDlg.ClearHistory;
364begin
365 HistItems.Clear;
366end;
367
368procedure THelpDlg.FormPaint(Sender: TObject);
369begin
370 inherited;
371 Canvas.Font.Assign(UniFont[ftNormal]);
372end;
373
374procedure THelpDlg.Line(ca: TCanvas; i: Integer; lit: Boolean);
375var
376 TextColor, x, y: Integer;
377 TextSize: TSize;
378 s: string;
379begin
380 s := MainText[ScrollBar.Position + i];
381 if s = '' then
382 Exit;
383 x := x0[i];
384 y := 2 + i * 24;
385 if ca = Canvas then
386 begin
387 x := x + SideFrame;
388 y := y + WideFrame
389 end;
390 if THelpLineInfo(MainText.Objects[ScrollBar.Position + i]).Format
391 in [pkCaption, pkBigTer, pkRightIcon, pkBigFeature] then
392 begin
393 ca.Font.Assign(CaptionFont);
394 { ca.brush.color:=CaptionColor;
395 ca.FillRect(rect(x,i*24,x+24,i*24+24));
396 ca.brush.color:=$FFFFFF;
397 ca.FrameRect(rect(x+1,i*24+1,x+24-1,i*24+24-1));
398 ca.Brush.Style:=bsClear; }
399 BitBltCanvas(ca, x, y - 4, 24, 24, GrExt[HGrSystem].Data.Canvas, 1,
400 146);
401 BiColorTextOut(ca, $FFFFFF, $7F007F, x + 10 - ca.Textwidth(s[1]) div 2,
402 y - 3, s[1]);
403 BiColorTextOut(ca, CaptionColor, $7F007F, x + 24, y - 3, copy(s, 2, 255));
404 ca.Font.Assign(UniFont[ftNormal]);
405 end
406 else if THelpLineInfo(MainText.Objects[ScrollBar.Position + i]).Format = pkSection
407 then
408 begin
409 ca.Font.Assign(CaptionFont);
410 BiColorTextOut(ca, CaptionColor, $7F007F, x, y - 3, s);
411 ca.Font.Assign(UniFont[ftNormal]);
412 end
413 else
414 begin
415 if (Kind = hkMisc) and (no = miscMain) then
416 ca.Font.Assign(CaptionFont);
417 TextColor := Colors.Canvas.Pixels[clkMisc, cliPaperText];
418 if ca = Canvas then
419 begin
420 TextSize.cx := BiColorTextWidth(ca, s);
421 TextSize.cy := ca.TextHeight(s);
422 if y + TextSize.cy >= WideFrame + InnerHeight then
423 TextSize.cy := WideFrame + InnerHeight - y;
424 FillSeamless(ca, x, y, TextSize.cx, TextSize.cy, -SideFrame,
425 ScrollBar.Position * 24 - WideFrame, Paper);
426 end;
427 BiColorTextOut(ca, TextColor, $7F007F, x, y, s);
428 if lit then
429 with ca do
430 begin
431 Assert(ca = Canvas);
432 Pen.Color := TextColor;
433 MoveTo(x + 1, y + TextSize.cy - 2);
434 LineTo(x + TextSize.cx, y + TextSize.cy - 2);
435 end;
436 if (Kind = hkMisc) and (no = miscMain) then
437 ca.Font.Assign(UniFont[ftNormal]);
438 end
439end;
440
441procedure THelpDlg.WaterSign(x0, y0, iix: integer);
442const
443 nHeaven = 28;
444 MaxSum = 9 * 9 * 255 * 75 div 100;
445var
446 x, y, dx, dy, xSrc, ySrc, sum, xx: integer;
447 Heaven: array [0..nHeaven] of integer;
448 PaintPtr, CoalPtr: TPixelPointer;
449 ImpPtr: array [-1..1] of TPixelPointer;
450begin
451 // assume eiffel tower has free common heaven
452 for dy := 0 to nHeaven - 1 do
453 Heaven[dy] := BigImp.Canvas.Pixels[woEiffel mod 7 * xSizeBig,
454 (SystemIconLines + woEiffel div 7) * ySizeBig + dy];
455
456 BigImp.BeginUpdate;
457 Offscreen.BeginUpdate;
458 xSrc := iix mod 7 * xSizeBig;
459 ySrc := (iix div 7 + 1) * ySizeBig;
460 for y := 0 to ScaleToNative(ySizeBig) * 2 - 1 do
461 if ((ScaleToNative(y0) + y) >= 0) and ((ScaleToNative(y0) + y) < ScaleToNative(InnerHeight)) then begin
462 PaintPtr := PixelPointer(OffScreen, 0, ScaleToNative(y0) + y);
463 CoalPtr := PixelPointer(Templates, 0, ScaleToNative(yCoal) + y);
464 for dy := -1 to 1 do
465 if ((Max(y + ScaleToNative(dy), 0) shr 1) >= 0) and ((Max(y + ScaleToNative(dy), 0) shr 1) < ScaleToNative(ySizeBig)) then
466 ImpPtr[dy] := PixelPointer(BigImp, 0, ScaleToNative(ySrc) + (Max(y + ScaleToNative(dy), 0) shr 1));
467 for x := 0 to ScaleToNative(xSizeBig) * 2 - 1 do begin
468 sum := 0;
469 for dx := -1 to 1 do begin
470 xx := ScaleToNative(xSrc) + Max((x + ScaleToNative(dx)), 0) shr 1;
471 for dy := -1 to 1 do begin
472 ImpPtr[dy].SetX(xx);
473 if ((y + ScaleToNative(dy)) shr 1 < 0) or ((y + ScaleToNative(dy)) shr 1 >= ScaleToNative(ySizeBig)) or
474 ((x + ScaleToNative(dx)) shr 1 < 0) or ((x + ScaleToNative(dx)) shr 1 >= ScaleToNative(xSizeBig)) or
475 ((y + ScaleToNative(dy)) shr 1 < ScaleToNative(nHeaven)) and
476 (ImpPtr[dy].Pixel^.B shl 16 + ImpPtr[dy].Pixel^.G shl 8 +
477 ImpPtr[dy].Pixel^.R = Heaven[(ScaleFromNative(y) + dy) shr 1]) then
478 sum := sum + 9 * 255
479 else
480 sum := sum + ImpPtr[dy].Pixel^.B + 5 * ImpPtr[dy].Pixel^.G + 3 *
481 ImpPtr[dy].Pixel^.R;
482 end;
483 end;
484 if sum < MaxSum then begin // no saturation
485 CoalPtr.SetX(ScaleToNative(xCoal) + x);
486 sum := 1 shl 22 - (MaxSum - sum) * (256 - CoalPtr.Pixel^.B * 2);
487 PaintPtr.SetX(x0 + x);
488 PaintPtr.Pixel^.B := PaintPtr.Pixel^.B * sum shr 22;
489 PaintPtr.Pixel^.G := PaintPtr.Pixel^.G * sum shr 22;
490 PaintPtr.Pixel^.R := PaintPtr.Pixel^.R * sum shr 22;
491 end;
492 end;
493 end;
494 Offscreen.EndUpdate;
495 BigImp.EndUpdate;
496end;
497
498procedure THelpDlg.PaintTerrIcon(x, y, xSrc, ySrc: integer);
499begin
500 Frame(OffScreen.Canvas, x - 1, y - 1, x + xSizeBig, y + ySizeBig,
501 $000000, $000000);
502 if 2 * yyt < 40 then begin
503 Sprite(OffScreen, HGrTerrain, x, y, 56, 2 * yyt, xSrc, ySrc);
504 Sprite(OffScreen, HGrTerrain, x, y + 2 * yyt, 56, 40 - 2 * yyt,
505 xSrc, ySrc);
506 end else
507 Sprite(OffScreen, HGrTerrain, x, y, 56, 40, xSrc, ySrc);
508 Sprite(OffScreen, HGrTerrain, x, y, xxt, yyt, xSrc + xxt, ySrc + yyt);
509 Sprite(OffScreen, HGrTerrain, x, y + yyt, xxt, 40 - yyt, xSrc + xxt, ySrc);
510 Sprite(OffScreen, HGrTerrain, x + xxt, y, 56 - xxt, yyt, xSrc, ySrc + yyt);
511 Sprite(OffScreen, HGrTerrain, x + xxt, y + yyt, 56 - xxt, 40 - yyt,
512 xSrc, ySrc);
513end;
514
515procedure THelpDlg.OffscreenPaint;
516var
517 i, j, yl, srcno, ofs, cnt, y: Integer;
518 s: string;
519 HelpLineInfo: THelpLineInfo;
520begin
521 inherited;
522 CaptionColor := Colors.Canvas.Pixels[clkMisc, cliPaperCaption];
523 FillSeamless(OffScreen.Canvas, 0, 0, InnerWidth, InnerHeight, 0,
524 ScrollBar.Position * 24, Paper);
525 with OffScreen.Canvas do
526 begin
527 Font.Assign(UniFont[ftNormal]);
528 for i := -ScrollBar.Position to InnerHeight div 24 do
529 if ScrollBar.Position + i < MainText.Count then
530 begin
531 HelpLineInfo := THelpLineInfo(MainText.Objects[ScrollBar.Position + i]);
532 if HelpLineInfo.Format = pkExternal then
533 begin
534 yl := ExtPic.Height;
535 if 4 + i * 24 + yl > InnerHeight then
536 yl := InnerHeight - (4 + i * 24);
537 BitBltCanvas(OffScreen.Canvas, 8, 4 + i * 24, ExtPic.Width, yl, ExtPic.Canvas,
538 0, 0);
539 end;
540 end;
541 for i := -2 to InnerHeight div 24 do
542 if (ScrollBar.Position + i >= 0) and (ScrollBar.Position + i < MainText.Count) then
543 begin
544 HelpLineInfo := THelpLineInfo(MainText.Objects[ScrollBar.Position + i]);
545 if HelpLineInfo.Link <> 0 then
546 begin
547 if (Kind = hkMisc) and (no = miscSearchResult) then
548 Sprite(OffScreen, HGrSystem, 18, 9 + i * 24, 8, 8, 90, 16)
549 else if HelpLineInfo.Format in [pkSmallIcon_AsPreq, pkAdvIcon_AsPreq]
550 then
551 Sprite(OffScreen, HGrSystem, 12, i * 24 + 5, 14, 14, 65, 20)
552 else if HelpLineInfo.Link and (hkCrossLink shl 8) <> 0 then
553 Sprite(OffScreen, HGrSystem, 12, i * 24 + 5, 14, 14, 80, 1)
554 else if not((Kind = hkMisc) and (no = miscMain)) then
555 Sprite(OffScreen, HGrSystem, 10, i * 24 + 6, 14, 14, 65, 1);
556 x0[i] := 24;
557 end
558 else
559 x0[i] := 0;
560 case HelpLineInfo.Format of
561 pkLogo:
562 begin
563 Server(sGetVersion, 0, 0, j);
564 s := Format('%d.%d.%d', [j shr 16 and $FF, j shr 8 and $FF,
565 j and $FF]);
566 PaintLogo(OffScreen.Canvas, (InnerWidth - 122) div 2, i * 24 + 1,
567 GrExt[HGrSystem].Data.Canvas.Pixels[95, 1], $000000);
568 Font.Assign(UniFont[ftSmall]);
569 BiColorTextOut(OffScreen.Canvas, $000000, $7F007F,
570 (InnerWidth - Textwidth(s)) div 2, i * 24 + 26, s);
571 Font.Assign(UniFont[ftNormal]);
572 end;
573 pkSmallIcon, pkSmallIcon_AsPreq:
574 begin
575 ScreenTools.Frame(OffScreen.Canvas, 8 - 1 + x0[i], 2 - 1 + i * 24,
576 8 + xSizeSmall + x0[i], 2 + 20 + i * 24, $000000, $000000);
577 if HelpLineInfo.Picpix = imPalace then
578 BitBltCanvas(OffScreen.Canvas, 8 + x0[i], 2 + i * 24,
579 xSizeSmall, ySizeSmall, SmallImp.Canvas,
580 0 * xSizeSmall, 1 * ySizeSmall)
581 else
582 BitBltCanvas(OffScreen.Canvas, 8 + x0[i], 2 + i * 24,
583 xSizeSmall, ySizeSmall, SmallImp.Canvas,
584 HelpLineInfo.Picpix mod 7 * xSizeSmall,
585 (HelpLineInfo.Picpix + SystemIconLines * 7) div 7 *
586 ySizeSmall);
587 x0[i] := x0[i] + (8 + 8 + 36);
588 end;
589 pkBigIcon:
590 begin
591 FrameImage(OffScreen.Canvas, BigImp, x0[i] + 12, i * 24 - 7, 56,
592 40, HelpLineInfo.Picpix mod 7 * xSizeBig,
593 HelpLineInfo.Picpix div 7 * ySizeBig);
594 x0[i] := 64 + 8 + 8 + x0[i];
595 end;
596 pkSpecialIcon:
597 begin
598 case HelpLineInfo.Picpix of
599 0:
600 FrameImage(OffScreen.Canvas, GrExt[HGrSystem2].Data,
601 12 + x0[i], -7 + i * 24, 56, 40, 137, 127);
602 1:
603 begin
604 PaintTerrIcon(12 + x0[i], -7 + i * 24,
605 1 + 3 * (xxt * 2 + 1), 1 + yyt);
606 if 2 * yyt < 40 then
607 Sprite(OffScreen, HGrTerrain, 12 + x0[i], -7 + 4 + i * 24,
608 56, 2 * yyt, 1 + 3 * (xxt * 2 + 1) + xxt - 28,
609 1 + yyt + 1 * (yyt * 3 + 1))
610 else
611 Sprite(OffScreen, HGrTerrain, 12 + x0[i],
612 -7 + 4 + i * 24 - 4, 56, 40, 1 + 3 * (xxt * 2 + 1) + xxt
613 - 28, 1 + yyt + 1 * (yyt * 3 + 1) + yyt - 20);
614 end;
615 2:
616 begin
617 PaintTerrIcon(12 + x0[i], -7 + i * 24,
618 1 + 7 * (xxt * 2 + 1), 1 + yyt + 4 * (yyt * 3 + 1));
619 if 2 * yyt < 40 then
620 Sprite(OffScreen, HGrTerrain, 12 + x0[i], -7 + 4 + i * 24,
621 56, 32, 1 + 4 * (xxt * 2 + 1) + xxt - 28,
622 1 + yyt + 12 * (yyt * 3 + 1) + yyt - 16)
623 else
624 Sprite(OffScreen, HGrTerrain, 12 + x0[i], -7 + 4 + i * 24,
625 56, 32, 1 + 4 * (xxt * 2 + 1) + xxt - 28,
626 1 + yyt + 12 * (yyt * 3 + 1) + yyt - 16)
627 end;
628 end;
629 x0[i] := 64 + 8 + 8 + x0[i];
630 end;
631 pkDomain:
632 begin
633 ScreenTools.Frame(OffScreen.Canvas, 8 - 1 + x0[i], 2 - 1 + i * 24,
634 8 + 36 + x0[i], 2 + 20 + i * 24, $000000, $000000);
635 Dump(OffScreen, HGrSystem, 8 + x0[i], 2 + i * 24, 36, 20,
636 75 + HelpLineInfo.Picpix * 37, 295);
637 x0[i] := x0[i] + (8 + 8 + 36);
638 end;
639 pkAdvIcon, pkAdvIcon_AsPreq:
640 begin
641 ScreenTools.Frame(OffScreen.Canvas, 8 - 1 + x0[i], 2 - 1 + i * 24,
642 8 + xSizeSmall + x0[i], 2 + ySizeSmall + i * 24,
643 $000000, $000000);
644 if AdvIcon[HelpLineInfo.Picpix] < 84 then
645 BitBltCanvas(OffScreen.Canvas, 8 + x0[i], 2 + i * 24,
646 xSizeSmall, ySizeSmall, SmallImp.Canvas,
647 (AdvIcon[HelpLineInfo.Picpix] + SystemIconLines * 7) mod 7 *
648 xSizeSmall, (AdvIcon[HelpLineInfo.Picpix] + SystemIconLines *
649 7) div 7 * ySizeSmall)
650 else
651 Dump(OffScreen, HGrSystem, 8 + x0[i], 2 + i * 24, 36, 20,
652 1 + (AdvIcon[HelpLineInfo.Picpix] - 84) mod 8 * 37,
653 295 + (AdvIcon[HelpLineInfo.Picpix] - 84) div 8 * 21);
654 j := AdvValue[HelpLineInfo.Picpix] div 1000;
655 BitBltCanvas(OffScreen.Canvas, x0[i] + 4, 4 + i * 24, 14, 14,
656 GrExt[HGrSystem].Mask.Canvas, 127 + j * 15, 85, SRCAND);
657 Sprite(OffScreen, HGrSystem, x0[i] + 3, 3 + i * 24, 14, 14,
658 127 + j * 15, 85);
659 x0[i] := x0[i] + (8 + 8 + 36);
660 end;
661 pkRightIcon:
662 begin
663 if Imp[HelpLineInfo.Picpix].Kind <> ikWonder then
664 ImpImage(OffScreen.Canvas, InnerWidth - (40 + xSizeBig), i * 24,
665 HelpLineInfo.Picpix, gDespotism)
666 else
667 WaterSign(InnerWidth - (40 + 2 * xSizeBig), i * 24 - 8,
668 HelpLineInfo.Picpix + 7);
669 x0[i] := x0[i] + 8;
670 end;
671 pkIllu:
672 WaterSign(8, i * 24 - 8, HelpLineInfo.Picpix);
673 pkBigFeature:
674 begin
675 cnt := 0;
676 for j := nDomains - 1 downto 0 do
677 if 1 shl j and Feature[HelpLineInfo.Picpix].Domains <> 0 then
678 begin
679 inc(cnt);
680 Dump(OffScreen, HGrSystem, InnerWidth - 38 - 38 * cnt,
681 i * 24 + 1, 36, 20, 75 + j * 37, 295);
682 ScreenTools.Frame(OffScreen.Canvas, InnerWidth - 39 - 38 * cnt, i * 24,
683 InnerWidth - 2 - 38 * cnt, i * 24 + 21, $000000, $000000);
684 end;
685 DarkGradient(OffScreen.Canvas, InnerWidth - 38 - 38 * cnt,
686 i * 24 + 23, cnt * 38 - 2, 1);
687 ofs := InnerWidth - (39 + 7) - 19 * cnt;
688 with OffScreen.Canvas do
689 begin
690 Brush.color := $C0C0C0;
691 FrameRect(Rect(ofs, 1 + 23 + i * 24, ofs + 14,
692 15 + 23 + i * 24));
693 Brush.Style := bsClear;
694 Sprite(OffScreen, HGrSystem, ofs + 2, 3 + 23 + i * 24, 10, 10,
695 66 + HelpLineInfo.Picpix mod 11 * 11,
696 137 + HelpLineInfo.Picpix div 11 * 11);
697 end;
698 x0[i] := x0[i] + 8;
699 end;
700 pkTer, pkBigTer:
701 begin
702 if HelpLineInfo.Format = pkBigTer then
703 y := i * 24 - 3 + yyt
704 else
705 y := i * 24 + 13;
706 if HelpLineInfo.Picpix >= 3 * 12 then
707 srcno := 2 * 9 + 6
708 else if HelpLineInfo.Picpix mod 12 = fJungle then
709 srcno := 18 * 9
710 else if HelpLineInfo.Picpix mod 12 < fJungle then
711 srcno := HelpLineInfo.Picpix mod 12
712 else
713 srcno := 27 + (HelpLineInfo.Picpix mod 12 - 9) * 18;
714 if HelpLineInfo.Format = pkTer then
715 begin
716 ofs := x0[i] + 8;
717 x0[i] := 2 * xxt + 8 + ofs;
718 end
719 else
720 begin
721 ofs := InnerWidth - (2 * xxt + 38);
722 x0[i] := x0[i] + 8;
723 end;
724 if srcno >= fJungle then
725 begin
726 Sprite(OffScreen, HGrTerrain, ofs + 4, y - yyt + 2, xxt * 2 - 8,
727 yyt * 2 - 4, 5 + 2 * (xxt * 2 + 1),
728 3 + yyt + 2 * (yyt * 3 + 1));
729 Sprite(OffScreen, HGrTerrain, ofs, y - 2 * yyt, xxt * 2,
730 yyt * 3 - 2, 1 + srcno mod 9 * (xxt * 2 + 1),
731 1 + srcno div 9 * (yyt * 3 + 1));
732 end
733 else
734 Sprite(OffScreen, HGrTerrain, ofs + 4, y - yyt + 2, xxt * 2 - 8,
735 yyt * 2 - 4, 5 + srcno mod 9 * (xxt * 2 + 1),
736 3 + yyt + srcno div 9 * (yyt * 3 + 1));
737 if HelpLineInfo.Picpix >= 3 * 12 then { rare resource }
738 Sprite(OffScreen, HGrTerrain, ofs, y - 2 * yyt, xxt * 2,
739 yyt * 3, 1 + 8 * (xxt * 2 + 1),
740 1 + (HelpLineInfo.Picpix - 2 * 12) * (yyt * 3 + 1))
741 else if HelpLineInfo.Picpix >= 12 then { special tile }
742 begin
743 if HelpLineInfo.Picpix mod 12 = fJungle then
744 srcno := 17 * 9 + 8
745 else if HelpLineInfo.Picpix mod 12 < fJungle then
746 srcno := HelpLineInfo.Picpix mod 12
747 else
748 srcno := 18 + 8 + (HelpLineInfo.Picpix mod 12 - 9) * 18;
749 srcno := srcno + HelpLineInfo.Picpix div 12 * 9;
750 Sprite(OffScreen, HGrTerrain, ofs, y - 2 * yyt, xxt * 2,
751 yyt * 3, 1 + srcno mod 9 * (xxt * 2 + 1),
752 1 + srcno div 9 * (yyt * 3 + 1));
753 end;
754 end;
755 pkTerImp:
756 begin
757 ofs := 8;
758 if HelpLineInfo.Picpix = 5 then
759 begin // display mine on hills
760 Sprite(OffScreen, HGrTerrain, ofs + 4, i * 24 + 13 - yyt,
761 xxt * 2 - 8, yyt * 2 - 4, 5 + 2 * (xxt * 2 + 1),
762 3 + yyt + 2 * (yyt * 3 + 1));
763 srcno := 45
764 end
765 else
766 srcno := fPrairie; // display on prairie
767 Sprite(OffScreen, HGrTerrain, ofs + 4, i * 24 + 13 - yyt,
768 xxt * 2 - 8, yyt * 2 - 4, 5 + srcno mod 9 * (xxt * 2 + 1),
769 3 + yyt + srcno div 9 * (yyt * 3 + 1));
770 if HelpLineInfo.Picpix = 12 then { river }
771 Sprite(OffScreen, HGrTerrain, ofs, i * 24 + 11 - yyt, xxt * 2,
772 yyt * 2, 1 + 5 * (xxt * 2 + 1), 1 + yyt + 13 * (yyt * 3 + 1))
773 else if HelpLineInfo.Picpix >= 3 then { improvement 2 }
774 begin
775 if HelpLineInfo.Picpix = 6 then
776 Sprite(OffScreen, HGrTerrain, ofs, i * 24 + 11 - 2 * yyt,
777 xxt * 2, yyt * 3, 1 + 7 * (xxt * 2 + 1),
778 1 + 12 * (yyt * 3 + 1));
779 Sprite(OffScreen, HGrTerrain, ofs, i * 24 + 11 - 2 * yyt,
780 xxt * 2, yyt * 3, 1 + (HelpLineInfo.Picpix - 3) *
781 (xxt * 2 + 1), 1 + 12 * (yyt * 3 + 1))
782 end
783 else { improvement 1 }
784 begin
785 Sprite(OffScreen, HGrTerrain, ofs, i * 24 + 11 - 2 * yyt,
786 xxt * 2, yyt * 3, 1 + 2 * (xxt * 2 + 1),
787 1 + (9 + HelpLineInfo.Picpix) * (yyt * 3 + 1));
788 Sprite(OffScreen, HGrTerrain, ofs, i * 24 + 11 - 2 * yyt,
789 xxt * 2, yyt * 3, 1 + 5 * (xxt * 2 + 1),
790 1 + (9 + HelpLineInfo.Picpix) * (yyt * 3 + 1))
791 end;
792 x0[i] := x0[i] + 8;
793 end;
794 pkModel:
795 begin
796 FrameImage(OffScreen.Canvas, BigImp, x0[i] + 12, i * 24 - 7,
797 56, 40, 0, 0);
798 Sprite(OffScreen, HGrStdUnits, x0[i] + 8, i * 24 - 11, 64, 44,
799 1 + HelpLineInfo.Picpix mod 10 * 65,
800 1 + HelpLineInfo.Picpix div 10 * 49);
801 x0[i] := 64 + 8 + 8 + x0[i];
802 end;
803 pkFeature:
804 begin
805 DarkGradient(OffScreen.Canvas, x0[i] + 8 - 1,
806 7 + i * 24 - 3, 16, 1);
807 ScreenTools.Frame(OffScreen.Canvas, x0[i] + 8, 7 + i * 24 - 2, x0[i] + 8 + 13,
808 7 + i * 24 - 2 + 13, $C0C0C0, $C0C0C0);
809 Sprite(OffScreen, HGrSystem, x0[i] + 8 + 2, 7 + i * 24, 10, 10,
810 66 + HelpLineInfo.Picpix mod 11 * 11,
811 137 + HelpLineInfo.Picpix div 11 * 11);
812 x0[i] := x0[i] + 8 + 8 + 2 + 13;
813 end;
814 pkExp:
815 begin
816 ScreenTools.Frame(OffScreen.Canvas, 20 - 1, 8 - 4 + i * 24, 20 + 12,
817 8 + 11 + i * 24, $000000, $000000);
818 Dump(OffScreen, HGrSystem, 20, 8 - 3 + i * 24, 12, 14,
819 121 + HelpLineInfo.Picpix * 13, 28);
820 x0[i] := 20 + 8 + 11;
821 end;
822 pkAITStat:
823 begin
824 Sprite(OffScreen, HGrSystem, 20, 6 + i * 24, 14, 14,
825 1 + HelpLineInfo.Picpix * 15, 316);
826 x0[i] := 20 + 8 + 11;
827 end;
828 pkGov:
829 begin
830 ScreenTools.Frame(OffScreen.Canvas, 8 - 1 + x0[i], 2 - 1 + i * 24,
831 8 + xSizeSmall + x0[i], 2 + 20 + i * 24, $000000, $000000);
832 BitBltCanvas(OffScreen.Canvas, 8 + x0[i], 2 + i * 24, xSizeSmall,
833 ySizeSmall, SmallImp.Canvas, (HelpLineInfo.Picpix - 1) *
834 xSizeSmall, ySizeSmall);
835 x0[i] := x0[i] + (8 + 8 + 36);
836 end;
837 pkDot:
838 begin
839 Sprite(OffScreen, HGrSystem, x0[i] + 18, 9 + i * 24, 8,
840 8, 81, 16);
841 x0[i] := 20 + 8 + 4;
842 end;
843 pkNormal_Dot:
844 x0[i] := 20 + 8 + 4;
845 pkNormal_64:
846 x0[i] := 64 + 8 + 8;
847 else
848 x0[i] := x0[i] + 8;
849 end;
850 Self.Line(OffScreen.Canvas, i, False)
851 end;
852 end;
853 MarkUsedOffscreen(InnerWidth, InnerHeight + 13 + 48);
854end;
855
856procedure THelpDlg.ScrollBarUpdate(Sender: TObject);
857begin
858 Sel := -1;
859 SmartUpdateContent(true)
860end;
861
862procedure THelpDlg.Prepare(sbPos: integer = 0);
863var
864 i, j, Special, Domain, Headline, TerrType, TerrSubType: integer;
865 s: string;
866 ps: pchar;
867 List: THyperText;
868 CheckSeeAlso: Boolean;
869
870 procedure AddAdvance(i: integer);
871 begin
872 MainText.AddLine(Phrases.Lookup('ADVANCES', i), pkAdvIcon, i,
873 hkAdv + hkCrossLink, i);
874 end;
875
876 procedure AddPreqAdv(i: integer);
877 begin
878 MainText.AddLine(Phrases.Lookup('ADVANCES', i), pkAdvIcon_AsPreq, i,
879 hkAdv + hkCrossLink, i);
880 end;
881
882 procedure AddImprovement(i: integer);
883 begin
884 MainText.AddLine(Phrases.Lookup('IMPROVEMENTS', i), pkSmallIcon, i,
885 hkImp + hkCrossLink, i);
886 end;
887
888 procedure AddPreqImp(i: integer);
889 begin
890 MainText.AddLine(Phrases.Lookup('IMPROVEMENTS', i), pkSmallIcon_AsPreq, i,
891 hkImp + hkCrossLink, i);
892 end;
893
894 procedure AddTerrain(i: integer);
895 begin
896 if MainText.Count > 1 then
897 begin
898 MainText.LineFeed;
899 end;
900 MainText.AddLine(Phrases.Lookup('TERRAIN', i), pkTer, i, hkTer, i);
901 end;
902
903 procedure AddFeature(i: integer);
904 begin
905 MainText.AddLine(Phrases.Lookup('FEATURES', i), pkFeature, i,
906 hkFeature + hkCrossLink, i);
907 end;
908
909 procedure AddModel(i: integer);
910 var
911 pix: integer;
912 Name: string;
913 begin
914 if MainText.Count > 1 then
915 MainText.LineFeed;
916 FindStdModelPicture(SpecialModelPictureCode[i], pix, Name);
917 MainText.AddLine(Name, pkModel, pix, hkModel + hkCrossLink, i)
918 end;
919
920 procedure AddStandardBlock(Item: string);
921 var
922 i: integer;
923 begin
924 with MainText do
925 begin
926 if Item = 'LOGO' then
927 begin
928 AddLine('', pkLogo);
929 LineFeed;
930 end
931 else if Item = 'TECHFORMULA' then
932 begin
933 i := Difficulty;
934 if i = 0 then
935 i := 2;
936 AddLine(Format(HelpText.Lookup('TECHFORMULA'), [TechFormula_M[i],
937 TechFormula_D[i]]))
938 end
939 else if Item = 'EXPERIENCE' then
940 for i := 0 to nExp - 1 do
941 AddLine(Phrases.Lookup('EXPERIENCE', i), pkExp, i)
942 else if Item = 'MODERN' then
943 for i := 1 to 3 do
944 begin
945 LineFeed;
946 AddLine(Phrases.Lookup('TERRAIN', 3 * 12 + i), pkTer, 3 * 12 + i);
947 end
948 else if Item = 'SAVED' then
949 AddLine(DataDir + 'Saved', pkNormal)
950 else if Item = 'AITSTAT' then
951 for i := 0 to 3 do
952 AddLine(Phrases2.Lookup('AITSTAT', i), pkAITStat, i)
953 end
954 end;
955
956 procedure DecodeItem(s: string; var Category, Index: Integer);
957 var
958 i: Integer;
959 begin
960 if (Length(s) > 0) and (s[1] = ':') then begin
961 Category := hkMisc;
962 Index := 0;
963 for i := 3 to length(s) do
964 Index := Index * 10 + Ord(s[i]) - 48;
965 case s[2] of
966 'A': Category := hkAdv;
967 'B': Category := hkImp;
968 'T': Category := hkTer;
969 'F': Category := hkFeature;
970 'E': Category := hkInternet;
971 'S': Category := hkModel;
972 'C': Index := miscCredits;
973 'J': Index := miscJobList;
974 'G': Index := miscGovList;
975 end;
976 if (Category <> hkMisc) and (Index = 0) then
977 Index := 200;
978 end else begin
979 Category := hkText;
980 Index := HelpText.Gethandle(Copy(s, 1, 255));
981 end;
982 end;
983
984 procedure AddTextual(s: string);
985 var
986 i, p, l, ofs, CurrentFormat, FollowFormat, Picpix, LinkCategory, LinkIndex,
987 RightMargin: integer;
988 Name: string;
989 begin
990 RightMargin := InnerWidth - 16 - GetSystemMetrics(SM_CXVSCROLL);
991 FollowFormat := pkNormal;
992 while s <> '' do
993 begin
994 Picpix := 0;
995 LinkCategory := 0;
996 LinkIndex := 0;
997 if s[1] = '$' then
998 begin // window caption
999 p := 1;
1000 repeat
1001 inc(p)
1002 until (p > Length(s)) or (s[p] = '\');
1003 Caption := Copy(s, 2, p - 2);
1004 Delete(s, 1, p);
1005 end
1006 else if s[1] = '&' then
1007 begin // standard block
1008 p := 1;
1009 repeat
1010 inc(p)
1011 until (p > Length(s)) or (s[p] = '\');
1012 AddStandardBlock(Copy(s, 2, p - 2));
1013 Delete(s, 1, p);
1014 end
1015 else if s[1] = '@' then
1016 begin // image
1017 if (Length(s) >= 2) and (s[2] = '@') then
1018 begin // generate from icon
1019 Picpix := 0;
1020 p := 3;
1021 while (p <= Length(s)) and (s[p] <> '\') do
1022 begin
1023 Picpix := Picpix * 10 + Ord(s[p]) - 48;
1024 inc(p)
1025 end;
1026 if (Picpix < 0) or (Picpix >= nImp) then
1027 Picpix := 0;
1028 MainText.AddLine('', pkIllu, Picpix);
1029 MainText.LineFeed;
1030 MainText.LineFeed;
1031 end
1032 else
1033 begin // external image
1034 p := 1;
1035 repeat
1036 Inc(p)
1037 until (p > Length(s)) or (s[p] = '\');
1038 if LoadGraphicFile(ExtPic, LocalizedFilePath('Help' +
1039 DirectorySeparator + Copy(s, 2, p - 2)) + '.png') then
1040 begin
1041 MainText.AddLine('', pkExternal);
1042 for i := 0 to (ExtPic.Height - 12) div 24 do
1043 MainText.LineFeed;
1044 end;
1045 end;
1046 Delete(s, 1, p);
1047 end
1048 else
1049 begin
1050 case s[1] of
1051 ':', ';':
1052 begin // link
1053 p := 1;
1054 repeat
1055 inc(p)
1056 until (p > Length(s)) or (s[p] = '\') or (s[p] = ' ');
1057 DecodeItem(Copy(s, 2, p - 2), LinkCategory, LinkIndex);
1058 CurrentFormat := 0;
1059 if (LinkCategory <> hkText) and (LinkIndex < 200) then
1060 // show icon
1061 case LinkCategory of
1062 hkAdv:
1063 begin
1064 CurrentFormat := pkAdvIcon;
1065 Picpix := LinkIndex
1066 end;
1067 hkImp:
1068 begin
1069 CurrentFormat := pkSmallIcon;
1070 Picpix := LinkIndex
1071 end;
1072 hkTer:
1073 begin
1074 CurrentFormat := pkTer;
1075 Picpix := LinkIndex;
1076 end;
1077 hkFeature:
1078 begin
1079 CurrentFormat := pkFeature;
1080 Picpix := LinkIndex
1081 end;
1082 hkModel:
1083 begin
1084 CurrentFormat := pkModel;
1085 FindStdModelPicture(SpecialModelPictureCode[LinkIndex],
1086 Picpix, Name);
1087 end;
1088 end;
1089 if s[1] = ':' then
1090 LinkCategory := LinkCategory + hkCrossLink;
1091 if (p > Length(s)) or (s[p] = ' ') then
1092 Delete(s, 1, p)
1093 else
1094 Delete(s, 1, p - 1)
1095 end;
1096 '!': // highlited
1097 if (Length(s) >= 2) and (s[2] = '!') then
1098 begin
1099 if MainText.Count > 1 then
1100 MainText.LineFeed;
1101 FollowFormat := pkCaption;
1102 CurrentFormat := pkCaption;
1103 Delete(s, 1, 2);
1104 end
1105 else
1106 begin
1107 FollowFormat := pkSection;
1108 CurrentFormat := pkSection;
1109 Delete(s, 1, 1);
1110 end;
1111 '-':
1112 begin // list
1113 FollowFormat := pkNormal_Dot;
1114 CurrentFormat := pkDot;
1115 Delete(s, 1, 1);
1116 end;
1117 else
1118 CurrentFormat := FollowFormat;
1119 end;
1120 if FollowFormat = pkNormal_Dot then
1121 ofs := 20 + 4 + 8
1122 else
1123 ofs := 8;
1124 p := 0;
1125 repeat
1126 repeat
1127 Inc(p)
1128 until (p > Length(s)) or (s[p] = ' ') or (s[p] = '\');
1129 if (BiColorTextWidth(OffScreen.Canvas, Copy(s, 1, p - 1)) <=
1130 RightMargin - ofs) then
1131 l := p - 1
1132 else
1133 Break;
1134 until (p >= Length(s)) or (s[l + 1] = '\');
1135 MainText.AddLine(Copy(s, 1, l), CurrentFormat, Picpix, LinkCategory,
1136 LinkIndex);
1137 if (l < Length(s)) and (s[l + 1] = '\') then
1138 FollowFormat := pkNormal;
1139 Delete(s, 1, l + 1);
1140 end
1141 end
1142 end;
1143
1144 procedure AddItem(Item: string);
1145 begin
1146 AddTextual(HelpText.Lookup(Item));
1147 end;
1148
1149 procedure AddModelText(i: Integer);
1150 var
1151 pix: Integer;
1152 s: string;
1153 begin
1154 with MainText do begin
1155 if Count > 1 then begin
1156 LineFeed;
1157 LineFeed;
1158 end;
1159 FindStdModelPicture(SpecialModelPictureCode[i], pix, s);
1160 AddLine(s, pkSection);
1161 AddLine(Format(HelpText.Lookup('STRENGTH'), [SpecialModel[i].Attack,
1162 SpecialModel[i].Defense]), pkNormal_64);
1163 AddLine(Format(HelpText.Lookup('SPEED'),
1164 [MovementToString(SpecialModel[i].Speed)]), pkModel, pix);
1165 if Difficulty = 0 then
1166 AddLine(Format(HelpText.Lookup('BUILDCOST'), [SpecialModel[i].Cost]),
1167 pkNormal_64)
1168 else
1169 AddLine(Format(HelpText.Lookup('BUILDCOST'),
1170 [SpecialModel[i].Cost * BuildCostMod[Difficulty] div 12]),
1171 pkNormal_64);
1172 s := HelpText.LookupByHandle(hSPECIALMODEL, i);
1173 if (s <> '') and (s <> '*') then
1174 AddTextual(s);
1175 if SpecialModelPreq[i] >= 0 then
1176 AddPreqAdv(SpecialModelPreq[i])
1177 else if SpecialModelPreq[i] = preLighthouse then
1178 AddPreqImp(woLighthouse)
1179 else if SpecialModelPreq[i] = preBuilder then
1180 AddPreqImp(woPyramids)
1181 else if SpecialModelPreq[i] = preLeo then
1182 AddPreqImp(woLeo);
1183 if SpecialModelPreq[i] <> preNone then
1184 MainText[Count - 1] := Format(HelpText.Lookup('REQUIRED'),
1185 [MainText[Count - 1]]);
1186 end
1187 end;
1188
1189 procedure AddJobList;
1190 var
1191 i, JobCost: Integer;
1192 begin
1193 with MainText do begin
1194 for i := 0 to nJobHelp - 1 do begin
1195 if i > 0 then begin
1196 LineFeed;
1197 LineFeed;
1198 end;
1199 AddLine(Phrases.Lookup('JOBRESULT', JobHelp[i]), pkSection);
1200 AddLine;
1201 AddLine('', pkTerImp, i);
1202 AddLine;
1203 AddTextual(HelpText.LookupByHandle(hJOBHELP, i));
1204 JobCost := -1;
1205 case JobHelp[i] of
1206 jCanal: JobCost := CanalWork;
1207 jFort: JobCost := FortWork;
1208 jBase: JobCost := BaseWork;
1209 end;
1210 if JobCost >= 0 then
1211 AddTextual(Format(HelpText.Lookup('JOBCOST'),
1212 [MovementToString(JobCost)]))
1213 else
1214 AddTextual(HelpText.Lookup('JOBCOSTVAR'));
1215 if JobPreq[JobHelp[i]] <> preNone then begin
1216 AddPreqAdv(JobPreq[JobHelp[i]]);
1217 MainText[Count - 1] := Format(HelpText.Lookup('REQUIRED'),
1218 [MainText[Count - 1]]);
1219 end
1220 end;
1221 end
1222 end;
1223
1224 procedure AddGraphicCredits;
1225 var
1226 i: Integer;
1227 s: string;
1228 sr: TSearchRec;
1229 List, Plus: TStringList;
1230 begin
1231 List := TStringList.Create;
1232 Plus := TStringList.Create;
1233 if FindFirst(GetGraphicsDir + DirectorySeparator + '*.credits.txt', $27, sr) = 0 then
1234 repeat
1235 Plus.LoadFromFile(GetGraphicsDir + DirectorySeparator + sr.Name);
1236 List.AddStrings(Plus);
1237 until FindNext(sr) <> 0;
1238 FindClose(sr);
1239 Plus.Free;
1240
1241 List.Sort;
1242 i := 1;
1243 while i < List.Count do
1244 if List[i] = List[i - 1] then
1245 List.Delete(i)
1246 else
1247 Inc(i);
1248
1249 for i := 0 to List.Count - 1 do begin
1250 s := List[i];
1251 while BiColorTextWidth(OffScreen.Canvas, s) > InnerWidth - 16 -
1252 GetSystemMetrics(SM_CXVSCROLL) do
1253 Delete(s, length(s), 1);
1254 MainText.AddLine(s);
1255 end;
1256 List.Free;
1257 end;
1258
1259 procedure AddSoundCredits;
1260 var
1261 i: Integer;
1262 s: string;
1263 List: TStringList;
1264 begin
1265 List := TStringList.Create;
1266 List.LoadFromFile(GetSoundsDir + DirectorySeparator + 'sound.credits.txt');
1267 for i := 0 to List.Count - 1 do begin
1268 s := List[i];
1269 while BiColorTextWidth(OffScreen.Canvas, s) > InnerWidth - 16 -
1270 GetSystemMetrics(SM_CXVSCROLL) do
1271 Delete(s, length(s), 1);
1272 MainText.AddLine(s);
1273 end;
1274 List.Free;
1275 end;
1276
1277 procedure NextSection(Item: string);
1278 begin
1279 if MainText.Count > 1 then
1280 if MainText.Count = Headline + 1 then
1281 MainText.Delete(Headline)
1282 else
1283 MainText.LineFeed;
1284 MainText.AddLine(HelpText.Lookup(Item), pkSection);
1285 Headline := MainText.Count - 1;
1286 end;
1287
1288begin { Prepare }
1289 with MainText do begin
1290 OffScreen.Canvas.Font.Assign(UniFont[ftNormal]);
1291 CheckSeeAlso := False;
1292 Clear;
1293 Headline := -1;
1294 if (no >= 200) or not(Kind in [hkAdv, hkImp, hkTer, hkFeature]) then
1295 LineFeed;
1296 case Kind of
1297 hkText:
1298 AddTextual(HelpText.LookupByHandle(no));
1299 hkMisc:
1300 begin
1301 case no of
1302 miscMain:
1303 begin
1304 Caption := HelpText.Lookup('HELPTITLE_MAIN');
1305 AddLine(HelpText.Lookup('HELPTITLE_QUICKSTART'), pkSpecialIcon,
1306 0, { pkBigIcon,22, } hkText, HelpText.Gethandle('QUICK'));
1307 LineFeed;
1308 AddLine(HelpText.Lookup('HELPTITLE_CONCEPTS'), pkBigIcon, 6,
1309 hkText, HelpText.Gethandle('CONCEPTS'));
1310 LineFeed;
1311 AddLine(HelpText.Lookup('HELPTITLE_TERLIST'), pkSpecialIcon, 1,
1312 hkTer, 200);
1313 LineFeed;
1314 AddLine(HelpText.Lookup('HELPTITLE_JOBLIST'), pkSpecialIcon, 2,
1315 hkMisc, miscJobList);
1316 LineFeed;
1317 AddLine(HelpText.Lookup('HELPTITLE_TECHLIST'), pkBigIcon, 39,
1318 hkAdv, 200);
1319 LineFeed;
1320 FindStdModelPicture(SpecialModelPictureCode[6], i, s);
1321 AddLine(HelpText.Lookup('HELPTITLE_MODELLIST'), pkModel, i,
1322 hkModel, 0);
1323 LineFeed;
1324 AddLine(HelpText.Lookup('HELPTITLE_FEATURELIST'), pkBigIcon, 28,
1325 hkFeature, 200);
1326 LineFeed;
1327 AddLine(HelpText.Lookup('HELPTITLE_IMPLIST'), pkBigIcon,
1328 7 * SystemIconLines + imCourt, hkImp, 200);
1329 LineFeed;
1330 AddLine(HelpText.Lookup('HELPTITLE_UNIQUELIST'), pkBigIcon,
1331 7 * SystemIconLines + imStockEx, hkImp, 201);
1332 LineFeed;
1333 AddLine(HelpText.Lookup('HELPTITLE_WONDERLIST'), pkBigIcon,
1334 7 * SystemIconLines, hkImp, 202);
1335 LineFeed;
1336 AddLine(HelpText.Lookup('HELPTITLE_GOVLIST'), pkBigIcon,
1337 gDemocracy + 6, hkMisc, miscGovList);
1338 LineFeed;
1339 AddLine(HelpText.Lookup('HELPTITLE_KEYS'), pkBigIcon, 2, hkText,
1340 HelpText.Gethandle('HOTKEYS'));
1341 LineFeed;
1342 AddLine(HelpText.Lookup('HELPTITLE_ABOUT'), pkBigIcon, 1,
1343 hkText, HelpText.Gethandle('ABOUT'));
1344 LineFeed;
1345 AddLine(HelpText.Lookup('HELPTITLE_CREDITS'), pkBigIcon, 22,
1346 hkMisc, miscCredits);
1347 end;
1348 miscCredits:
1349 begin
1350 AddItem('CREDITS');
1351 LineFeed;
1352 AddGraphicCredits;
1353 NextSection('CRED_CAPSOUND');
1354 AddSoundCredits;
1355 NextSection('CRED_CAPAI');
1356 Server(sGetAICredits, 0, 0, ps);
1357 AddTextual(ps);
1358 NextSection('CRED_CAPLANG');
1359 AddItem('AUTHOR');
1360 end;
1361 miscJobList:
1362 begin
1363 Caption := HelpText.Lookup('HELPTITLE_JOBLIST');
1364 AddJobList;
1365 LineFeed;
1366 AddItem('TERIMPEXCLUDE');
1367 LineFeed;
1368 AddItem('TERIMPCITY');
1369 end;
1370 miscGovList:
1371 begin
1372 Caption := HelpText.Lookup('HELPTITLE_GOVLIST');
1373 for i := 1 to nGov do
1374 begin
1375 AddLine(Phrases.Lookup('GOVERNMENT', i mod nGov), pkSection);
1376 LineFeed;
1377 if i = nGov then
1378 AddLine('', pkBigIcon, 7 * SystemIconLines + imPalace)
1379 else
1380 AddLine('', pkBigIcon, i + 6);
1381 LineFeed;
1382 AddTextual(HelpText.LookupByHandle(hGOVHELP, i mod nGov));
1383 if i mod nGov >= 2 then
1384 begin
1385 AddPreqAdv(GovPreq[i mod nGov]);
1386 MainText[Count - 1] := Format(HelpText.Lookup('REQUIRED'),
1387 [MainText[Count - 1]]);
1388 end;
1389 if i < nGov then
1390 begin
1391 LineFeed;
1392 LineFeed;
1393 end
1394 end
1395 end;
1396 miscSearchResult:
1397 begin
1398 Caption := HelpText.Lookup('HELPTITLE_SEARCHRESULTS');
1399 AddTextual(Format(HelpText.Lookup('MATCHES'), [SearchContent]));
1400 MainText.AppendList(SearchResult);
1401 end;
1402 end; // case no
1403 end;
1404
1405 hkAdv:
1406 if no = 200 then
1407 begin // complete advance list
1408 Caption := HelpText.Lookup('HELPTITLE_TECHLIST');
1409 List := THyperText.Create;
1410 List.OwnsObjects := True;
1411 for j := 0 to 3 do
1412 begin
1413 if j > 0 then
1414 begin
1415 LineFeed;
1416 LineFeed;
1417 end;
1418 AddLine(HelpText.Lookup('TECHAGE', j), pkSection);
1419 if j = 1 then
1420 AddLine(Phrases.Lookup('ADVANCES', adScience) + ' ' +
1421 HelpText.Lookup('BASETECH'), pkAdvIcon, adScience, hkAdv,
1422 adScience);
1423 if j = 2 then
1424 AddLine(Phrases.Lookup('ADVANCES', adMassProduction) + ' ' +
1425 HelpText.Lookup('BASETECH'), pkAdvIcon, adMassProduction, hkAdv,
1426 adMassProduction);
1427 List.Clear;
1428 for i := 0 to nAdv - 1 do
1429 if (i <> adScience) and (i <> adMassProduction) and
1430 (AdvValue[i] div 1000 = j) then
1431 List.AddLine(Phrases.Lookup('ADVANCES', i), pkAdvIcon, i,
1432 hkAdv, i);
1433 List.Sort;
1434 AppendList(List);
1435 end;
1436 List.Free;
1437 end
1438 else // single advance
1439 begin
1440 Caption := Phrases.Lookup('ADVANCES', no);
1441 LineFeed;
1442 AddLine(Phrases.Lookup('ADVANCES', no), pkCaption);
1443 if no in FutureTech then
1444 begin
1445 AddLine(HelpText.Lookup('HELPSPEC_FUTURE'));
1446 LineFeed;
1447 if no = futResearchTechnology then
1448 AddItem('FUTURETECHHELP100')
1449 else
1450 AddItem('FUTURETECHHELP25');
1451 end
1452 else
1453 AddLine(HelpText.Lookup('HELPSPEC_ADV'));
1454 if AdvPreq[no, 2] <> preNone then
1455 NextSection('PREREQALT')
1456 else
1457 NextSection('PREREQ');
1458 for i := 0 to 2 do
1459 if AdvPreq[no, i] <> preNone then
1460 AddPreqAdv(AdvPreq[no, i]);
1461 NextSection('GOVALLOW');
1462 for i := 2 to nGov - 1 do
1463 if GovPreq[i] = no then
1464 AddLine(Phrases.Lookup('GOVERNMENT', i), pkGov, i,
1465 hkMisc + hkCrossLink, miscGovList);
1466 NextSection('BUILDALLOW');
1467 for i := 0 to 27 do
1468 if Imp[i].Preq = no then
1469 AddImprovement(i);
1470 for i := 28 to nImp - 1 do
1471 if (Imp[i].Preq = no) and (Imp[i].Kind <> ikCommon) then
1472 AddImprovement(i);
1473 for i := 28 to nImp - 1 do
1474 if (Imp[i].Preq = no) and (Imp[i].Kind = ikCommon) then
1475 AddImprovement(i);
1476 NextSection('MODELALLOW');
1477 for i := 0 to nSpecialModel - 1 do
1478 if SpecialModelPreq[i] = no then
1479 AddModel(i);
1480 NextSection('FEATALLOW');
1481 for i := 0 to nFeature - 1 do
1482 if Feature[i].Preq = no then
1483 AddFeature(i);
1484 NextSection('FOLLOWADV');
1485 for i := 0 to nAdv - 1 do
1486 if (AdvPreq[i, 0] = no) or (AdvPreq[i, 1] = no) or
1487 (AdvPreq[i, 2] = no) then
1488 AddAdvance(i);
1489 NextSection('UPGRADEALLOW');
1490 for Domain := 0 to nDomains - 1 do
1491 for i := 1 to nUpgrade - 1 do
1492 if upgrade[Domain, i].Preq = no then
1493 begin
1494 if upgrade[Domain, i].Strength > 0 then
1495 AddLine(Format(HelpText.Lookup('STRENGTHUP'),
1496 [Phrases.Lookup('DOMAIN', Domain), upgrade[Domain,
1497 i].Strength]), pkDomain, Domain);
1498 if upgrade[Domain, i].Trans > 0 then
1499 AddLine(Format(HelpText.Lookup('TRANSUP'),
1500 [Phrases.Lookup('DOMAIN', Domain), upgrade[Domain, i].Trans]
1501 ), pkDomain, Domain);
1502 if no in FutureTech then
1503 AddLine(Format(HelpText.Lookup('COSTUP'),
1504 [upgrade[Domain, i].Cost]), pkNormal_Dot)
1505 else
1506 AddLine(Format(HelpText.Lookup('COSTMIN'),
1507 [upgrade[Domain, i].Cost]), pkNormal_Dot)
1508 end;
1509 NextSection('EXPIRATION');
1510 for i := 0 to 27 do
1511 if (Imp[i].Preq <> preNA) and (Imp[i].Expiration = no) then
1512 AddImprovement(i);
1513 NextSection('ADVEFFECT');
1514 s := HelpText.LookupByHandle(hADVHELP, no);
1515 if s <> '*' then
1516 AddTextual(s);
1517 NextSection('SEEALSO');
1518 CheckSeeAlso := true
1519 end;
1520
1521 hkImp:
1522 if no = 200 then
1523 begin // complete city improvement list
1524 Caption := HelpText.Lookup('HELPTITLE_IMPLIST');
1525 // AddLine(HelpText.Lookup('HELPTITLE_IMPLIST'),pkSection);
1526 List := THyperText.Create;
1527 List.OwnsObjects := True;
1528 for i := 28 to nImp - 1 do
1529 if (i <> imTrGoods) and (Imp[i].Preq <> preNA) and
1530 (Imp[i].Kind = ikCommon) then
1531 List.AddLine(Phrases.Lookup('IMPROVEMENTS', i), pkSmallIcon,
1532 i, hkImp, i);
1533 List.Sort;
1534 AppendList(List);
1535 List.Free;
1536 end
1537 else if no = 201 then
1538 begin // complete nat. project list
1539 Caption := HelpText.Lookup('HELPTITLE_UNIQUELIST');
1540 // AddLine(HelpText.Lookup('HELPTITLE_UNIQUELIST'),pkSection);
1541 for i := 28 to nImp - 1 do
1542 if (Imp[i].Preq <> preNA) and
1543 ((Imp[i].Kind = ikNatLocal) or (Imp[i].Kind = ikNatGlobal)) then
1544 AddLine(Phrases.Lookup('IMPROVEMENTS', i), pkSmallIcon, i,
1545 hkImp, i);
1546 { LineFeed;
1547 LineFeed;
1548 AddLine(HelpText.Lookup('HELPTITLE_SHIPPARTLIST'),pkSection);
1549 for i:=28 to nImp-1 do
1550 if (Imp[i].Preq<>preNA) and (Imp[i].Kind=ikShipPart) then
1551 AddLine(Phrases.Lookup('IMPROVEMENTS',i),pkSmallIcon,i,hkImp,i); }
1552 end
1553 else if no = 202 then
1554 begin // complete wonder list
1555 Caption := HelpText.Lookup('HELPTITLE_WONDERLIST');
1556 // AddLine(HelpText.Lookup('HELPTITLE_WONDERLIST'),pkSection);
1557 for i := 0 to 27 do
1558 if Imp[i].Preq <> preNA then
1559 AddLine(Phrases.Lookup('IMPROVEMENTS', i), pkSmallIcon, i,
1560 hkImp, i);
1561 end
1562 else
1563 begin // single building
1564 Caption := Phrases.Lookup('IMPROVEMENTS', no);
1565 LineFeed;
1566 AddLine(Phrases.Lookup('IMPROVEMENTS', no), pkRightIcon, no);
1567 case Imp[no].Kind of
1568 ikWonder: AddLine(HelpText.Lookup('HELPSPEC_WONDER'));
1569 ikCommon: AddLine(HelpText.Lookup('HELPSPEC_IMP'));
1570 ikShipPart: AddLine(HelpText.Lookup('HELPSPEC_SHIPPART'));
1571 else
1572 AddLine(HelpText.Lookup('HELPSPEC_NAT'))
1573 end;
1574 if Imp[no].Kind <> ikShipPart then begin
1575 NextSection('EFFECT');
1576 AddTextual(HelpText.LookupByHandle(hIMPHELP, no));
1577 end;
1578 if no = woSun then begin
1579 AddFeature(mcFirst);
1580 AddFeature(mcWill);
1581 AddFeature(mcAcademy);
1582 end;
1583 if (no < 28) and not Phrases2FallenBackToEnglish then
1584 begin
1585 LineFeed;
1586 if Imp[no].Expiration >= 0 then
1587 AddTextual(Phrases2.Lookup('HELP_WONDERMORALE1'))
1588 else
1589 AddTextual(Phrases2.Lookup('HELP_WONDERMORALE2'));
1590 end;
1591 if Imp[no].Preq <> preNone then
1592 begin
1593 NextSection('PREREQ');
1594 AddPreqAdv(Imp[no].Preq);
1595 end;
1596 NextSection('COSTS');
1597 if Difficulty = 0 then
1598 s := Format(HelpText.Lookup('BUILDCOST'), [Imp[no].Cost])
1599 else
1600 s := Format(HelpText.Lookup('BUILDCOST'),
1601 [Imp[no].Cost * BuildCostMod[Difficulty] div 12]);
1602 AddLine(s);
1603 if Imp[no].Maint > 0 then
1604 AddLine(Format(HelpText.Lookup('MAINTCOST'), [Imp[no].Maint]));
1605 j := 0;
1606 for i := 0 to nImpReplacement - 1 do
1607 if ImpReplacement[i].NewImp = no then
1608 begin
1609 if j = 0 then
1610 begin
1611 NextSection('REPLACE');
1612 AddItem('REPLACETEXT');
1613 j := 1
1614 end;
1615 AddImprovement(ImpReplacement[i].OldImp);
1616 end;
1617 if Imp[no].Kind = ikShipPart then
1618 begin
1619 LineFeed;
1620 if no = imShipComp then
1621 i := 1
1622 else if no = imShipPow then
1623 i := 2
1624 else { if no=imShipHab then }
1625 i := 3;
1626 AddLine(Format(HelpText.Lookup('RAREREQUIRED'),
1627 [Phrases.Lookup('TERRAIN', 3 * 12 + i)]), pkTer, 3 * 12 + i);
1628 end;
1629 if (no < 28) and (Imp[no].Expiration >= 0) then
1630 begin
1631 NextSection('EXPIRATION');
1632 s := Format(HelpText.Lookup('EXPWITH'),
1633 [Phrases.Lookup('ADVANCES', Imp[no].Expiration)]);
1634 if no = woPyramids then
1635 s := s + ' ' + HelpText.Lookup('EXPSLAVE');
1636 AddTextual(s);
1637 end;
1638 NextSection('SEEALSO');
1639 if (no < 28) and (Imp[no].Expiration >= 0) then
1640 AddImprovement(woEiffel);
1641 for i := 0 to nImpReplacement - 1 do
1642 if ImpReplacement[i].OldImp = no then
1643 AddImprovement(ImpReplacement[i].NewImp);
1644 if no = imSupermarket then
1645 AddLine(HelpText.Lookup('HELPTITLE_JOBLIST'), pkNormal, 0,
1646 hkMisc + hkCrossLink, miscJobList);
1647 CheckSeeAlso := true
1648 end;
1649
1650 hkTer:
1651 if no = 200 then
1652 begin // complete terrain type list
1653 Caption := HelpText.Lookup('HELPTITLE_TERLIST');
1654 // AddLine(HelpText.Lookup('HELPTITLE_TERLIST'),pkSection);
1655 for i := 0 to nTerrainHelp - 1 do
1656 AddTerrain(TerrainHelp[i]);
1657 end
1658 else
1659 begin // sigle terrain type
1660 TerrType := no mod 12;
1661 if TerrType = fJungle then
1662 TerrType := fForest;
1663 TerrSubType := no div 12;
1664 if no = 3 * 12 then
1665 begin
1666 TerrType := fDesert;
1667 TerrSubType := 0
1668 end;
1669 with Terrain[TerrType] do
1670 begin
1671 Caption := Phrases.Lookup('TERRAIN', no);
1672 LineFeed;
1673 AddLine(Phrases.Lookup('TERRAIN', no), pkBigTer, no);
1674 AddLine(HelpText.Lookup('HELPSPEC_TER'));
1675 LineFeed;
1676 if (ProdRes[TerrSubType] > 0) or (MineEff > 0) then
1677 AddLine(Format(HelpText.Lookup('RESPROD'),
1678 [ProdRes[TerrSubType]]));
1679 if (no < 3 * 12) and (MineEff > 0) then
1680 MainText[Count - 1] := MainText[Count - 1] + ' ' +
1681 Format(HelpText.Lookup('MOREMINE'), [MineEff]);
1682 if (FoodRes[TerrSubType] > 0) or (IrrEff > 0) then
1683 AddLine(Format(HelpText.Lookup('RESFOOD'),
1684 [FoodRes[TerrSubType]]));
1685 if (no < 3 * 12) and (IrrEff > 0) then
1686 MainText[Count - 1] := MainText[Count - 1] + ' ' +
1687 Format(HelpText.Lookup('MOREIRR'), [IrrEff]);
1688 if TradeRes[TerrSubType] > 0 then
1689 AddLine(Format(HelpText.Lookup('RESTRADE'),
1690 [TradeRes[TerrSubType]]));
1691 if Defense > 4 then
1692 AddLine(Format(HelpText.Lookup('DEFBONUS'),
1693 [(Defense - 4) * 25]));
1694 if (TerrType >= fGrass) and (TerrType <> fMountains) then
1695 if MoveCost = 2 then
1696 AddLine(HelpText.Lookup('MOVEHEAVY'))
1697 else
1698 AddLine(HelpText.Lookup('MOVEPLAIN'));
1699 if no = 3 * 12 then
1700 begin
1701 LineFeed;
1702 AddTextual(HelpText.Lookup('DEADLANDS'));
1703 end;
1704 if (TerrType = fDesert) and (no <> fDesert + 12) then
1705 begin
1706 LineFeed;
1707 AddTextual(Format(HelpText.Lookup('HOSTILE'), [DesertThurst]));
1708 end;
1709 if TerrType = fArctic then
1710 begin
1711 LineFeed;
1712 AddTextual(Format(HelpText.Lookup('HOSTILE'), [ArcticThurst]));
1713 end;
1714 if (no < 3 * 12) and (TransTerrain >= 0) then
1715 begin
1716 LineFeed;
1717 i := TransTerrain;
1718 if (TerrType <> fGrass) and (i <> fGrass) then
1719 i := i + TerrSubType * 12;
1720 // trafo to same Special resource group
1721 AddLine(Format(HelpText.Lookup('TRAFO'),
1722 [Phrases.Lookup('TERRAIN', i)]), pkTer, i,
1723 hkTer + hkCrossLink, i);
1724 if no = fSwamp + 12 then
1725 begin
1726 LineFeed;
1727 AddLine(Format(HelpText.Lookup('TRAFO'),
1728 [Phrases.Lookup('TERRAIN', TransTerrain + 24)]), pkTer,
1729 TransTerrain + 24, hkTer + hkCrossLink, TransTerrain + 24);
1730 end
1731 else if i = fGrass then
1732 begin
1733 LineFeed;
1734 AddLine(Format(HelpText.Lookup('TRAFO'),
1735 [Phrases.Lookup('TERRAIN', fGrass + 12)]), pkTer, fGrass + 12,
1736 hkTer + hkCrossLink, fGrass + 12);
1737 end
1738 end;
1739 NextSection('SPECIAL');
1740 if no = 3 * 12 then
1741 begin
1742 LineFeed;
1743 for Special := 1 to 3 do
1744 begin
1745 if Special > 1 then
1746 LineFeed;
1747 AddLine(Phrases.Lookup('TERRAIN', 3 * 12 + Special), pkTer,
1748 3 * 12 + Special);
1749 end
1750 end
1751 else if (no < 12) and (no <> fGrass) and (no <> fOcean) then
1752 begin
1753 LineFeed;
1754 for Special := 1 to 2 do
1755 if (no <> fArctic) and (no <> fSwamp) or (Special < 2) then
1756 begin
1757 if Special > 1 then
1758 LineFeed;
1759 AddLine(Phrases.Lookup('TERRAIN', no + Special * 12), pkTer,
1760 no + Special * 12);
1761 i := FoodRes[Special] - FoodRes[0];
1762 if i <> 0 then
1763 MainText[Count - 1] := MainText[Count - 1] +
1764 Format(HelpText.Lookup('SPECIALFOOD'), [i]);
1765 i := ProdRes[Special] - ProdRes[0];
1766 if i <> 0 then
1767 MainText[Count - 1] := MainText[Count - 1] +
1768 Format(HelpText.Lookup('SPECIALPROD'), [i]);
1769 i := TradeRes[Special] - TradeRes[0];
1770 if i <> 0 then
1771 MainText[Count - 1] := MainText[Count - 1] +
1772 Format(HelpText.Lookup('SPECIALTRADE'), [i]);
1773 end;
1774 end;
1775 if no = 3 * 12 then
1776 begin
1777 LineFeed;
1778 AddTextual(HelpText.Lookup('RARE'));
1779 end;
1780 if (no < 3 * 12) and (TerrType in [fDesert, fArctic]) then
1781 begin
1782 NextSection('SEEALSO');
1783 AddImprovement(woGardens);
1784 CheckSeeAlso := true
1785 end
1786 end
1787 end;
1788
1789 hkFeature:
1790 if no = 200 then
1791 begin // complete feature list
1792 Caption := HelpText.Lookup('HELPTITLE_FEATURELIST');
1793 List := THyperText.Create;
1794 List.OwnsObjects := True;
1795 for Special := 0 to 2 do
1796 begin
1797 if Special > 0 then
1798 begin
1799 LineFeed;
1800 LineFeed;
1801 end;
1802 case Special of
1803 0: AddLine(HelpText.Lookup('HELPTITLE_FEATURE1LIST'), pkSection);
1804 1: AddLine(HelpText.Lookup('HELPTITLE_FEATURE2LIST'), pkSection);
1805 2: AddLine(HelpText.Lookup('HELPTITLE_FEATURE3LIST'), pkSection);
1806 end;
1807 List.Clear;
1808 for i := 0 to nFeature - 1 do
1809 if Feature[i].Preq <> preNA then
1810 begin
1811 if i < mcFirstNonCap then
1812 j := 0
1813 else if i in AutoFeature then
1814 j := 2
1815 else
1816 j := 1;
1817 if j = Special then
1818 List.AddLine(Phrases.Lookup('FEATURES', i), pkFeature, i,
1819 hkFeature, i);
1820 end;
1821 List.Sort;
1822 AppendList(List);
1823 end;
1824 List.Free;
1825 end
1826 else
1827 begin // single feature
1828 Caption := Phrases.Lookup('FEATURES', no);
1829 LineFeed;
1830 AddLine(Phrases.Lookup('FEATURES', no), pkBigFeature, no);
1831 if no < mcFirstNonCap then
1832 AddLine(HelpText.Lookup('HELPSPEC_CAP'))
1833 else if no in AutoFeature then
1834 AddLine(HelpText.Lookup('HELPSPEC_STANDARD'))
1835 else
1836 AddLine(HelpText.Lookup('HELPSPEC_FEATURE'));
1837 NextSection('EFFECT');
1838 AddTextual(HelpText.LookupByHandle(hFEATUREHELP, no));
1839 if (Feature[no].Weight <> 0) or (Feature[no].Cost <> 0) then
1840 begin
1841 NextSection('COSTS');
1842 s := IntToStr(Feature[no].Cost);
1843 if Feature[no].Cost >= 0 then
1844 s := '+' + s;
1845 AddLine(Format(HelpText.Lookup('COSTBASE'), [s]));
1846 if Feature[no].Weight > 0 then
1847 begin
1848 AddLine(Format(HelpText.Lookup('WEIGHT'),
1849 ['+' + IntToStr(Feature[no].Weight)]));
1850 if no = mcDefense then
1851 AddLine(Format(HelpText.Lookup('WEIGHT'), ['+2']),
1852 pkDomain, dGround);
1853 end
1854 end;
1855 if Feature[no].Preq <> preNone then
1856 begin
1857 LineFeed;
1858 if Feature[no].Preq = preSun then
1859 AddPreqImp(woSun) // sun tsu feature
1860 else
1861 AddPreqAdv(Feature[no].Preq);
1862 MainText[Count - 1] := Format(HelpText.Lookup('REQUIRED'),
1863 [MainText[Count - 1]]);
1864 end;
1865 NextSection('SEEALSO');
1866 CheckSeeAlso := True;
1867 end;
1868
1869 hkModel:
1870 begin
1871 Caption := HelpText.Lookup('HELPTITLE_MODELLIST');
1872 for i := 0 to nSpecialModel - 1 do
1873 if i <> 2 then
1874 AddModelText(i);
1875 LineFeed;
1876 AddItem('MODELNOTE');
1877 end;
1878
1879 end;
1880 if CheckSeeAlso then
1881 for i := 0 to nSeeAlso - 1 do
1882 if (SeeAlso[i].Kind = Kind) and (SeeAlso[i].no = no) then
1883 case SeeAlso[i].SeeKind of
1884 hkImp: AddImprovement(SeeAlso[i].SeeNo);
1885 hkAdv: AddAdvance(SeeAlso[i].SeeNo);
1886 hkFeature: AddFeature(SeeAlso[i].SeeNo);
1887 end;
1888 if (Headline >= 0) and (Count = Headline + 1) then
1889 Delete(Headline)
1890 else
1891 LineFeed;
1892
1893 //Self.Show;
1894 ScrollBar.Init(Count - 1, InnerHeight div 24);
1895 ScrollBar.SetPos(sbPos);
1896 BackBtn.Visible := HistItems.Count > 1;
1897 TopBtn.Visible := (HistItems.Count > 1) or (Kind <> hkMisc) or (no <> miscMain);
1898 Sel := -1;
1899 end; // with MainText
1900end;
1901
1902procedure THelpDlg.ShowNewContent(NewMode, Category, Index: Integer);
1903begin
1904 if (Category <> Kind) or (Index <> no) or (Category = hkMisc) and
1905 (Index = miscSearchResult) then begin
1906 if HistItems.Count = MaxHist then HistItems.Delete(0);
1907 if HistItems.Count = 0 then
1908 HistItems.AddNew(Category, Index, ScrollBar.Position, NewSearchContent)
1909 else HistItems.AddNew(Kind, No, ScrollBar.Position, SearchContent);
1910 end;
1911 Kind := Category;
1912 no := Index;
1913 SearchContent := NewSearchContent;
1914 Prepare;
1915 OffscreenPaint;
1916 inherited ShowNewContent(NewMode);
1917end;
1918
1919procedure THelpDlg.PaintBox1MouseMove(Sender: TObject; Shift: TShiftState;
1920 x, y: integer);
1921var
1922 i0, Sel0: Integer;
1923begin
1924 y := y - WideFrame;
1925 i0 := ScrollBar.Position;
1926 Sel0 := Sel;
1927 if (x >= SideFrame) and (x < SideFrame + InnerWidth) and (y >= 0) and
1928 (y < InnerHeight) and (y mod 24 >= 8) then
1929 Sel := y div 24
1930 else
1931 Sel := -1;
1932 if (Sel + i0 >= MainText.Count) or (Sel >= 0) and
1933 (THelpLineInfo(MainText.Objects[Sel + i0]).Link = 0) then
1934 Sel := -1;
1935 if Sel <> Sel0 then
1936 begin
1937 if Sel0 <> -1 then
1938 Line(Canvas, Sel0, False);
1939 if Sel <> -1 then
1940 Line(Canvas, Sel, True)
1941 end
1942end;
1943
1944procedure THelpDlg.PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
1945 Shift: TShiftState; x, y: integer);
1946begin
1947 if Sel >= 0 then
1948 with THelpLineInfo(MainText.Objects[Sel + ScrollBar.Position]) do
1949 if Link shr 8 and $3F = hkInternet then
1950 case Link and $FF of
1951 1: OpenDocument(HomeDir + AITemplateFileName);
1952 2: OpenURL(CevoHomepage);
1953 3: OpenURL(CevoContact);
1954 end
1955 else
1956 begin
1957 if (Link >= $8000) and (Link and $3FFF = liInvalid) then
1958 exit; // invalid link;
1959 if Link >= $8000 then
1960 ShowNewContent(FWindowMode, hkText, Link and $3FFF)
1961 else
1962 ShowNewContent(FWindowMode, Link shr 8 and $3F, Link and $FF);
1963 end
1964end;
1965
1966procedure THelpDlg.BackBtnClick(Sender: TObject);
1967var
1968 HistItem: THistItem;
1969begin
1970 if HistItems.Count > 1 then begin
1971 HistItem := THistItem.Create;
1972 HistItem.Assign(HistItems.Last);
1973 HistItems.Delete(HistItems.Count - 1);
1974 if (HistItem.Kind = hkMisc) and (HistItem.No = miscSearchResult) and
1975 (HistItem.SearchContent <> SearchContent) then
1976 begin
1977 SearchContent := HistItem.SearchContent;
1978 Search(SearchContent);
1979 end;
1980 Kind := HistItem.Kind;
1981 no := HistItem.No;
1982 Prepare(HistItem.Pos);
1983 OffscreenPaint;
1984 Invalidate;
1985 HistItem.Free;
1986 end;
1987end;
1988
1989procedure THelpDlg.TopBtnClick(Sender: TObject);
1990begin
1991 while HistItems.Count > 1 do HistItems.Delete(HistItems.Count - 1);
1992 Kind := hkMisc;
1993 no := miscMain;
1994 Prepare;
1995 OffscreenPaint;
1996 Invalidate;
1997end;
1998
1999procedure THelpDlg.FormClose(Sender: TObject; var Action: TCloseAction);
2000begin
2001 ExtPic.Height := 0;
2002 inherited;
2003end;
2004
2005function THelpDlg.TextIndex(Item: string): Integer;
2006begin
2007 Result := HelpText.Gethandle(Item)
2008end;
2009
2010procedure THelpDlg.FormKeyDown(Sender: TObject; var Key: Word;
2011 Shift: TShiftState);
2012begin
2013 if KeyToShortCut(Key, Shift) = BHelp.ShortCut then // my key
2014 else
2015 inherited;
2016end;
2017
2018procedure THelpDlg.SearchBtnClick(Sender: TObject);
2019begin
2020 InputDlg.Caption := Phrases.Lookup('SEARCH');
2021 InputDlg.EInput.Text := SearchContent;
2022 InputDlg.CenterToRect(BoundsRect);
2023 InputDlg.ShowModal;
2024 if (InputDlg.ModalResult = mrOK) and (Length(InputDlg.EInput.Text) >= 2) then
2025 begin
2026 Search(InputDlg.EInput.Text);
2027 case SearchResult.Count of
2028 0:
2029 SimpleMessage(Format(HelpText.Lookup('NOMATCHES'),
2030 [InputDlg.EInput.Text]));
2031 1:
2032 with THelpLineInfo(SearchResult.Objects[0]) do
2033 if Link >= $8000 then
2034 ShowNewContent(FWindowMode, hkText, Link and $3FFF)
2035 else
2036 ShowNewContent(FWindowMode, Link shr 8 and $3F, Link and $FF);
2037 else
2038 begin
2039 NewSearchContent := InputDlg.EInput.Text;
2040 ShowNewContent(FWindowMode, hkMisc, miscSearchResult);
2041 end;
2042 end;
2043 end;
2044end;
2045
2046procedure THelpDlg.Search(SearchString: string);
2047var
2048 h, i, PrevHandle, PrevIndex, p, RightMargin: Integer;
2049 s: string;
2050 mADVHELP, mIMPHELP, mFEATUREHELP: set of 0 .. 255;
2051 bGOVHELP, bSPECIALMODEL, bJOBHELP: Boolean;
2052begin
2053 SearchResult.Clear;
2054 mADVHELP := [];
2055 mIMPHELP := [];
2056 mFEATUREHELP := [];
2057 bGOVHELP := False;
2058 bSPECIALMODEL := False;
2059 bJOBHELP := False;
2060
2061 // search in generic reference
2062 SearchString := UpperCase(SearchString);
2063 for i := 0 to 35 + 4 do begin
2064 s := Phrases.Lookup('TERRAIN', i);
2065 if pos(SearchString, UpperCase(s)) > 0 then
2066 if i < 36 then
2067 SearchResult.AddLine(s + ' ' + HelpText.Lookup('HELPSPEC_TER'),
2068 pkNormal, 0, hkTer + hkCrossLink, i)
2069 else
2070 begin
2071 SearchResult.AddLine(Phrases.Lookup('TERRAIN', 36) + ' ' +
2072 HelpText.Lookup('HELPSPEC_TER'), pkNormal, 0,
2073 hkTer + hkCrossLink, 36);
2074 if i > 36 then
2075 SearchResult.AddLine(Phrases.Lookup('IMPROVEMENTS',
2076 imShipComp + i - 37) + ' ' + HelpText.Lookup('HELPSPEC_SHIPPART'),
2077 pkNormal, 0, hkImp + hkCrossLink, imShipComp + i - 37);
2078 Break;
2079 end;
2080 end;
2081 for i := 0 to nJobHelp - 1 do
2082 if pos(SearchString, UpperCase(Phrases.Lookup('JOBRESULT', JobHelp[i]))) > 0
2083 then
2084 begin
2085 SearchResult.AddLine(HelpText.Lookup('HELPTITLE_JOBLIST'), pkNormal, 0,
2086 hkMisc + hkCrossLink, miscJobList);
2087 bJOBHELP := True;
2088 Break;
2089 end;
2090 for i := 0 to nAdv - 1 do
2091 begin
2092 s := Phrases.Lookup('ADVANCES', i);
2093 if pos(SearchString, UpperCase(s)) > 0 then
2094 begin
2095 if i in FutureTech then
2096 s := s + ' ' + HelpText.Lookup('HELPSPEC_FUTURE')
2097 else
2098 s := s + ' ' + HelpText.Lookup('HELPSPEC_ADV');
2099 SearchResult.AddLine(s, pkNormal, 0, hkAdv + hkCrossLink, i);
2100 include(mADVHELP, i);
2101 end;
2102 end;
2103 for i := 0 to nSpecialModel - 1 do
2104 begin
2105 FindStdModelPicture(SpecialModelPictureCode[i], h, s);
2106 if pos(SearchString, UpperCase(s)) > 0 then
2107 begin
2108 SearchResult.AddLine(HelpText.Lookup('HELPTITLE_MODELLIST'), pkNormal, 0,
2109 hkModel + hkCrossLink, 0);
2110 bSPECIALMODEL := True;
2111 Break;
2112 end;
2113 end;
2114 for i := 0 to nFeature - 1 do
2115 begin
2116 s := Phrases.Lookup('FEATURES', i);
2117 if Pos(SearchString, UpperCase(s)) > 0 then
2118 begin
2119 if i < mcFirstNonCap then
2120 s := s + ' ' + HelpText.Lookup('HELPSPEC_CAP')
2121 else if i in AutoFeature then
2122 s := s + ' ' + HelpText.Lookup('HELPSPEC_STANDARD')
2123 else
2124 s := s + ' ' + HelpText.Lookup('HELPSPEC_FEATURE');
2125 SearchResult.AddLine(s, pkNormal, 0, hkFeature + hkCrossLink, i);
2126 Include(mFEATUREHELP, i);
2127 end;
2128 end;
2129 for i := 0 to nImp - 1 do
2130 begin
2131 s := Phrases.Lookup('IMPROVEMENTS', i);
2132 if Pos(SearchString, UpperCase(s)) > 0 then
2133 begin
2134 case Imp[i].Kind of
2135 ikWonder:
2136 s := s + ' ' + HelpText.Lookup('HELPSPEC_WONDER');
2137 ikCommon:
2138 s := s + ' ' + HelpText.Lookup('HELPSPEC_IMP');
2139 ikShipPart:
2140 s := s + ' ' + HelpText.Lookup('HELPSPEC_SHIPPART');
2141 else
2142 s := s + ' ' + HelpText.Lookup('HELPSPEC_NAT')
2143 end;
2144 SearchResult.AddLine(s, pkNormal, 0, hkImp + hkCrossLink, i);
2145 Include(mIMPHELP, i);
2146 end
2147 end;
2148 for i := 0 to nGov - 1 do
2149 if Pos(SearchString, UpperCase(Phrases.Lookup('GOVERNMENT', i))) > 0 then
2150 begin
2151 SearchResult.AddLine(HelpText.Lookup('HELPTITLE_GOVLIST'), pkNormal, 0,
2152 hkMisc + hkCrossLink, miscGovList);
2153 bGOVHELP := True;
2154 Break;
2155 end;
2156
2157 // full text search
2158 h := -1;
2159 repeat
2160 PrevHandle := h;
2161 PrevIndex := i;
2162 if not HelpText.Search(SearchString, h, i) then
2163 Break;
2164 if h = hADVHELP then
2165 begin
2166 if (i >= 0) and ((i <> PrevIndex) or (h <> PrevHandle)) and
2167 not(i in mADVHELP) then
2168 begin
2169 s := Phrases.Lookup('ADVANCES', i);
2170 if i in FutureTech then
2171 s := s + ' ' + HelpText.Lookup('HELPSPEC_FUTURE')
2172 else
2173 s := s + ' ' + HelpText.Lookup('HELPSPEC_ADV');
2174 SearchResult.AddLine(s, pkNormal, 0, hkAdv + hkCrossLink, i)
2175 end;
2176 end
2177 else if h = hIMPHELP then
2178 begin
2179 if (i >= 0) and ((i <> PrevIndex) or (h <> PrevHandle)) and
2180 not(i in mIMPHELP) then
2181 begin
2182 s := Phrases.Lookup('IMPROVEMENTS', i);
2183 case Imp[i].Kind of
2184 ikWonder:
2185 s := s + ' ' + HelpText.Lookup('HELPSPEC_WONDER');
2186 ikCommon:
2187 s := s + ' ' + HelpText.Lookup('HELPSPEC_IMP');
2188 ikShipPart:
2189 s := s + ' ' + HelpText.Lookup('HELPSPEC_SHIPPART');
2190 else
2191 s := s + ' ' + HelpText.Lookup('HELPSPEC_NAT')
2192 end;
2193 SearchResult.AddLine(s, pkNormal, 0, hkImp + hkCrossLink, i)
2194 end;
2195 end
2196 else if h = hFEATUREHELP then
2197 begin
2198 if (i >= 0) and ((i <> PrevIndex) or (h <> PrevHandle)) and
2199 not(i in mFEATUREHELP) then
2200 begin
2201 s := Phrases.Lookup('FEATURES', i);
2202 if i < mcFirstNonCap then
2203 s := s + ' ' + HelpText.Lookup('HELPSPEC_CAP')
2204 else if i in AutoFeature then
2205 s := s + ' ' + HelpText.Lookup('HELPSPEC_STANDARD')
2206 else
2207 s := s + ' ' + HelpText.Lookup('HELPSPEC_FEATURE');
2208 SearchResult.AddLine(s, pkNormal, 0, hkFeature + hkCrossLink, i);
2209 end;
2210 end
2211 else if h = hGOVHELP then
2212 begin
2213 if (i >= 0) and (h <> PrevHandle) and not bGOVHELP then
2214 SearchResult.AddLine(HelpText.Lookup('HELPTITLE_GOVLIST'), pkNormal, 0,
2215 hkMisc + hkCrossLink, miscGovList)
2216 end
2217 else if h = hSPECIALMODEL then
2218 begin
2219 if (i >= 0) and (h <> PrevHandle) and not bSPECIALMODEL then
2220 SearchResult.AddLine(HelpText.Lookup('HELPTITLE_MODELLIST'), pkNormal,
2221 0, hkModel + hkCrossLink, 0)
2222 end
2223 else if h = hJOBHELP then
2224 begin
2225 if (i >= 0) and (h <> PrevHandle) and not bJOBHELP then
2226 SearchResult.AddLine(HelpText.Lookup('HELPTITLE_JOBLIST'), pkNormal, 0,
2227 hkMisc + hkCrossLink, miscJobList)
2228 end
2229 else if { (h<>hMAIN) and } (h <> PrevHandle) then
2230 begin
2231 s := HelpText.LookupByHandle(h);
2232 p := Pos('$', s);
2233 if p > 0 then
2234 begin
2235 s := Copy(s, p + 1, maxint);
2236 p := Pos('\', s);
2237 if p > 0 then
2238 s := Copy(s, 1, p - 1);
2239 SearchResult.AddLine(s, pkNormal, 0, hkText + hkCrossLink, h);
2240 end;
2241 end;
2242 until False;
2243
2244 // cut lines to fit to window
2245 RightMargin := InnerWidth - 16 - GetSystemMetrics(SM_CXVSCROLL);
2246 OffScreen.Canvas.Font.Assign(UniFont[ftNormal]);
2247 for i := 0 to SearchResult.Count - 1 do
2248 begin
2249 while BiColorTextWidth(OffScreen.Canvas, SearchResult[i]) >
2250 RightMargin - 32 do
2251 SearchResult[i] := copy(SearchResult[i], 1, length(SearchResult[i]) - 1)
2252 end;
2253 end;
2254
2255end.
Note: See TracBrowser for help on using the repository browser.