# Plan: Port MapWindow from Delphi/VCL to Lazarus/LCL

## Status

**COMPLETE — 2026-03-11.** MapWindow builds and runs under Lazarus/FPC. The project files `MapWindow.lpr`, `MapWindow.lpi`, and `mainform.lfm` are in place; the Delphi project files (`MapWindow.dpr`, `MapWindow.dproj`, `mainform.dfm`) are retained in the repo for reference. All verification criteria below were met.

---

## Context

MapWindow is a Delphi 13 / VCL DLL exporting a real-time globe map view into the HC game engine. Seven other ExportDLL projects in this repo already use Lazarus/FPC (lazGUI, lazHCEffects, lazTurncoat, ActUnitReport, AutoSaves, GroupIdManager, TestGroupIds). Porting MapWindow to Lazarus removes the Delphi 13 commercial compiler dependency, aligns the build toolchain with the rest of the project, and takes advantage of the already-ported Lazarus TGlobe4 LCL package. The DLL name, exported API signatures, and all HC callbacks remain unchanged.

---

## TGlobe4 Lazarus Package

- **Package name:** `TG4_Lazarus`
- **Package file:** `C:\Prog\Projects\Stratsims\Delphi\Components\TGlobe4\Source\TG4_Lazarus.lpk`
- **Unit names are identical** to the Delphi version (Globe4, TGClasses, TGSysUtils, GlobeUtils, TGPresenters, TGObjects) — no uses clause changes needed for TGlobe4 units.
- **Conditional define used inside TGlobe4 source:** `{$IFDEF TG_LAZARUS}` (not needed in MapWindow code, just awareness).
- **New property relevant to the port:** `ImageTransparent: Boolean` on `TPointPresenter` — added in v4.10. The Lazarus version renders presenter icons with transparency by default (default = True). This means the BMP sprite sheet icons will render with correct transparency without extra code.
- **lazbuild command** (for automated/CI builds):
  ```
  "C:/Prog/lazarus/32/lazarus/lazbuild.exe" --build-all Source/TG4_Lazarus.lpk
  ```
  Use the same lazbuild.exe for building MapWindow itself once the `.lpi` exists.

## Critical Prerequisites (before coding begins)

1. **Obtain `uCICG4Presenters.pas` source** from the user and place it in the project root alongside `mainform.pas`. This file is the custom TGlobe4 presenter for HC military symbols and is currently missing (only `.dcu` files exist).

---

## Files to Create

| File | Replaces |
|---|---|
| `MapWindow.lpr` | `MapWindow.dpr` |
| `MapWindow.lpi` | `MapWindow.dproj` |
| `mainform.lfm` | `mainform.dfm` |

## Files to Modify

| File | Changes |
|---|---|
| `mainform.pas` | VCL → LCL uses clause, TAdvSplitter → TSplitter, unit prefix cleanup |
| `uCICG4Presenters.pas` | Same VCL → LCL uses clause treatment; verify TGlobe4 LCL API compatibility |
| `CLAUDE.md` | Add reference to plan file |

## Files to Keep Unchanged

- All files in `../../shared/pascal/` — already have `{$ifdef FPC}` guards and compile under both Delphi and FPC.
- `MapWindow.res` — resource file, compatible.
- `MapWindow/TGWorld.lyr`, `Graphics/GR_ICONS.BMP` — runtime assets, unchanged.

## Delphi Project Files (retire after successful build)

`MapWindow.dpr` and `MapWindow.dproj` should be archived or deleted once the Lazarus build is verified.

---

## Step-by-Step Implementation

### Step 1 — Create `MapWindow.lpr`

Model on `lazGUI\lazGUI.lpr`. Key changes from `MapWindow.dpr`:

- Add `{$mode delphi}{$H+}` at top (same as lazGUI.lpr)
- Remove `System.` and `Winapi.` prefixes from all unit names
- Add `Interfaces` to the uses clause (required by LCL)
- Replace `Winapi.Windows` → `Windows`, `System.SysUtils` → `SysUtils`, etc.
- `GetModuleName(hInstance)` → `GetModuleFileName(hInstance, buf, SizeOf(buf))` — FPC's `hInstance` is in the `System` unit
- Keep `Application.Initialize` only — **no** `Application.Run` (it freezes HC; confirmed in lazGUI.lpr)
- `frmMain.ParentWindow := hwndHC` — works identically in LCL (confirmed in lazGUI.lpr)
- Keep all exported function signatures exactly — same names, same types, same `cdecl` convention

### Step 2 — Create `MapWindow.lpi`

Model on `lazGUI\lazGUI.lpi`. Key settings:

```xml
<RequiredPackages>
  <Item1><PackageName Value="LCL"/></Item1>
  <Item2><PackageName Value="TG4_Lazarus"/></Item2>
</RequiredPackages>
<SearchPaths>
  <OtherUnitFiles Value="..\..\shared\pascal"/>
  <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
```

- Target output: `C:\Games\HC\ExportDLLs\GE`
- Debug host app: `C:\Games\HC\Winharp32.exe`, working dir `C:\Games\HC`
- `RelocatableUnit: True` (required for DLL)
- Platform: Win32 initially (Win64 is a stretch goal)

### Step 3 — Port `mainform.pas`

**Uses clause changes** (interface section):

| Remove | Replace with |
|---|---|
| `Winapi.Windows` | `Windows` |
| `Winapi.Messages` | `Messages` |
| `System.SysUtils` | `SysUtils` |
| `System.Variants` | *(remove — not needed)* |
| `System.Classes` | `Classes` |
| `System.ImageList` | *(remove — covered by ImgList)* |
| `Vcl.Graphics` | `Graphics` |
| `Vcl.Controls` | `Controls` |
| `Vcl.Forms` | `Forms` |
| `Vcl.Dialogs` | `Dialogs` |
| `Vcl.ExtCtrls` | `ExtCtrls` |
| `Vcl.StdCtrls` | `StdCtrls` |
| `Vcl.ComCtrls` | `ComCtrls` |
| `Vcl.ImgList` | `ImgList` |
| `AdvSplitter` | *(remove — handled in form)* |

**Component changes:**

- `TAdvSplitter` → `TSplitter` (in `ExtCtrls`). TSplitter is simpler but covers the use case.
- TGlobe4 units (Globe4, TGClasses, TGSysUtils, GlobeUtils, TGPresenters, TGObjects) — keep as-is; unit names are identical in the LCL package.

**Other changes:**

- Add `{$mode objfpc}{H+}` at top of file (consistent with lazGUI's mainform.pas)
- `Application.ExeName` returns the host EXE path in both VCL and LCL — the existing `ExtractFilePath(Application.ExeName) + 'Graphics\GR_ICONS.BMP'` call works as-is.
- `GetModuleFileName(hInstance, ...)` for DLL-relative asset path (TGWorld.lyr) — keep this approach; it is more correct than Application.ExeName for DLL-relative assets.
- `SetBkMode`, `SetTextAlign` — Windows GDI calls, available in both via the `Windows` unit. No change needed.

### Step 4 — Create `mainform.lfm`

Use the Lazarus IDE's built-in DFM→LFM converter (**Tools → Convert DFM File to LFM**) on `mainform.dfm`. Then manually:

- Replace the `TAdvSplitter` component block with a `TSplitter` block
- Confirm the TGlobe4 component entry uses the correct class name from the LCL package
- Remove any VCL-only properties that the LFM parser rejects (Lazarus will warn on load)

### Step 5 — Port `uCICG4Presenters.pas`

*(Requires source from user first)*

Apply the same uses clause treatment as Step 3. Key notes:
- `TPointPresenter` in the Lazarus TGlobe4 now has `ImageTransparent: Boolean` (default True). The custom `TCICG4PointPresenter` likely inherits from `TPointPresenter` — verify the property is set appropriately for sprite sheet icons (transparency should work automatically with the default True setting).
- TGlobe4 unit names are unchanged between Delphi and Lazarus versions, so presenter registration calls should not change.
- Verify against `TGPresenters.pas` and `TGClasses.pas` in `C:\Prog\Projects\Stratsims\Delphi\Components\TGlobe4\Source\` if any API methods differ.

### Step 6 — Automated build via lazbuild

Once the `.lpi` is working in the IDE, the project can be built from the command line:

```
"C:/Prog/lazarus/32/lazarus/lazbuild.exe" --build-all MapWindow.lpi
```

For Win64 (stretch goal):
```
"C:/Prog/lazarus/32/lazarus/lazbuild.exe" --os=win64 --cpu=x86_64 --build-all MapWindow.lpi
```

---

## Reference Files (read only)

- `C:\Prog\Projects\StratsimsOSS\HC\ExportDLLs\lazGUI\lazGUI.lpr` — DLL entry point pattern
- `C:\Prog\Projects\StratsimsOSS\HC\ExportDLLs\lazGUI\lazGUI.lpi` — project config pattern
- `C:\Prog\Projects\StratsimsOSS\HC\ExportDLLs\MapWindow\mainform.pas` — source to port
- `C:\Prog\Projects\StratsimsOSS\HC\ExportDLLs\MapWindow\mainform.dfm` — form to convert
- `C:\Prog\Projects\StratsimsOSS\HC\ExportDLLs\MapWindow\MapWindow.dpr` — entry point to port
- `C:\Prog\Projects\Stratsims\Delphi\Components\TGlobe4\Source\TGPresenters.pas` — Lazarus TGlobe4 presenter API reference
- `C:\Prog\Projects\Stratsims\Delphi\Components\TGlobe4\Source\TG4_Lazarus.lpk` — Lazarus package file

---

## Verification

1. Project compiles in Lazarus IDE with zero errors (warnings acceptable for first pass)
2. `MapWindow.dll` loads in HC without crashing on startup
3. Globe map window opens embedded inside the HC parent window
4. Groups are rendered on the map during an active scenario
5. Player/God mode radio button correctly filters visible groups
6. Mouse wheel zooms the globe in and out
7. Heading arrows appear and are colored by side for moving groups
8. `TGWorld.lyr` loads correctly (world outline visible)
