source: tags/1.2.0/LocalPlayer/Help.pas

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