source: branches/highdpi/LocalPlayer/Help.pas@ 193

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