# FEMM port roadmap ## status snapshot The four C++ solvers (`fkn`, `belasolv`, `csolv`, `hsolv`) are linked into Rust via per-engine static archives, wrapped behind C ABI under `ffi/`, surfaced through `crates/femm-sys`. Document model is mirrored in Rust across four discipline crates (`femm-doc` for magnetostatic, `femm-doc-elec`, `femm-doc-curr`, `femm-doc-heat`); parsers and writers round-trip the on-disk text formats. An iced 0.14 canvas in `crates/femm-app` opens .fem, pans, zooms, and supports Select / AddNode / AddBlockLabel as click-tools against `femm-doc::edit`. Mag editing primitives exist (`add_node`, `add_segment`, `add_arc_segment`, `add_block_label`, `delete_selected_*`, closest-entity queries) but PSLG enforcement (intersection splitting, duplicate collapse, on-line break) is not yet implemented. There is no preprocessor for the three non-mag disciplines wired into the GUI, no post-processor at all, no property editing, no problem-definition dialog, no mesh launch, and no .ans loader. ## pre-processor The original draws a planar straight-line graph (PSLG) of nodes, segments, arc segments, and block labels. Each discipline has its own doc class (`CFemmeDoc`, `CbeladrawDoc`, `CcdrawDoc`, `ChdrawDoc`) sharing identical geometry storage but differing in `MaterialProp`, `BoundaryProp`, `PointProp`, `Circuit` fields. The View class for each discipline (`CFemmeView`, `CbeladrawView`, `CcdrawView`, `ChdrawView`) is structurally identical — the discipline-specific behavior is confined to which property dialogs open from `OnOpenSelected`. ### edit modes and mouse gestures `EditAction` in the View is an `int`: `0`=Node, `1`=Segment, `2`=BlockLabel, `3`=ArcSegment, `4`=Group. Each mode rebinds the meaning of left-click, right-click, right-double-click, and TAB. Source: `FemmeView.cpp` (mag), `beladrawView.cpp` (elec), `cdrawView.cpp` (current), `hdrawView.cpp` (heat). - node mode (`EditAction==0`) — left-click places a node at the snapped mouse position; right-click toggles selection of the closest node; right-double-click pops an info message-box for that node; TAB opens the CEnterPt dialog for typed coordinates. Tier S. - segment mode (`EditAction==1`) — left-click picks the closest node as first endpoint; a second left-click picks the second endpoint and emits an `AddSegment`; right-click toggles selection of the closest segment; right-double-click reports length, BC, mesh size; ESC clears the half-built segment. Tier S. - arc segment mode (`EditAction==3`) — same two-click flow as segment, but between the two clicks a `CArcDlg` opens for arc angle, max segment length, and boundary marker. Tier M. - block-label mode (`EditAction==2`) — left-click places a label; right-click toggles selection; right-double-click reports material, circuit, mesh size, group, magnetization direction. Tier S. - group mode (`EditAction==4`) — right-click toggles every entity sharing the closest entity's group number; TAB pops a `CGroupNumber` dialog to type a group number and toggle that whole group. Tier S. - box select (`SelectWndFlag`) — drag a rectangle; on release selects all entities of the current mode (or all four kinds when in group mode) wholly inside. XOR-pixel rubber-band drawn in `OnMouseMove`. Tier M. - circle select (`SelectCircFlag`, mag only via `OnFDSelectCirc`) — drag from center to edge; selects entities inside the resulting disc. Tier M. - zoom-window (`ZoomWndFlag`) — drag a rectangle that becomes the new view extents. Tier S. - pan via arrow keys; PgUp/PgDn zoom by step; Home resets zoom; `Ctrl+Z` undoes; DEL cuts selection; SPACE opens the property dialog for current selection; F3 halves mesh density on selected blocks; F4 doubles. Tier S. - create-radius (`CreateRadiusFlag`) — next click chooses a node; a prompt asks for radius; if `CanCreateRadius` succeeds the corner is filleted in. Tier M. The XOR-pixel rubber-band approach in the original is a Win32 trick (read pixels, XOR-write, remember to restore). In iced this becomes a transient overlay shape on the canvas — simpler and tier-S to implement. ### dialogs Every dialog below corresponds to one `Xxx.h`/`Xxx.cpp` pair under `femm/`. Discipline-prefixed variants share a layout but differ in fields. The .rc resource definitions are gone, so layout is redesigned; field set, validation, and ok-button effect come from the .h and the OnInitDialog/OnOK in the .cpp. operation dialogs opened by SPACE / Edit > Properties - `COpNodeDlg` / `bd_OpNodeDlg` / `cd_OpNodeDlg` / `hd_OpNodeDlg` — `OpNodeDlg.h` and prefixed variants. Fields: nodal-property name (dropdown over `nodeproplist`), in-group. Tier S. - `COpSegDlg` / `bd_OpSegDlg` / `cd_OpSegDlg` / `hd_OpSegDlg` — `OpSegDlg.h`. Fields: boundary-property name, line mesh size (with auto-mesh toggle), hide-in-postprocessor, in-group. Tier S. - `COpArcSegDlg` / `bd_OpArcSegDlg` / `cd_OpArcSegDlg` / `hd_OpArcSegDlg` — `OpArcSegDlg.h`. Fields: boundary marker, max segment length (degrees), hide, in-group. Tier S. - `COpBlkDlg` / `bd_OpBlkDlg` / `cd_OpBlkDlg` / `hd_OpBlkDlg` — `OpBlkDlg.h`. Fields: block material, circuit (mag only), is-external (axisymmetric only), is-default, side length / area limit with auto-mesh toggle, mag direction (and a Lua "magdirfctn" textbox for functional MagDir), turns, in-group. Tier M. - `COpGrp` — `OpGrp.h`. Bulk-edit the group number across a heterogeneous selection. Tier S. property-list dialogs opened from menu Properties > Materials / Boundaries / Points / Circuits - `CPtProp` — `PtProp.h`. List with Add / Modify / Delete. Generic shell parameterized by which underlying property list it is editing. Tier S. property-editor dialogs reached from the Add/Modify buttons of `CPtProp` (one per discipline per property kind) - `CMatDlg` — `MatDlg.h`. Magnetostatic material: name, mu_x, mu_y, H_c, J_re+J_im, conductivity, lam direction, lam thickness, lam fill, hysteresis lag angles `Theta_h*`, BH-curve edit button (opens `CBHData`), wire diameter, num strands, and a nonlinearity-mode combo. Tier L. - `bdCMatDlg` — `bd_MatDlg.h`. Electrostatic material: name, eps_x, eps_y, volume charge density qv. Tier S. - `cdCMatDlg` — `cd_MatDlg.h`. Current-flow material: name, conductivity ox/oy (real+imag), and three-curve nonlinearity arrays. Tier M. - `hdCMatDlg` — `hd_MatDlg.h`. Heat material: name, Kx, Ky, Kt (volumetric heat capacity), qv, and a nonlinear KH-curve combo with edit button. Tier M. - `CBdryDlg` — `BdryDlg.h`. Magnetostatic boundary: BdryFormat combo (Prescribed-A, small-skin-depth, mixed, strategic dual, periodic, antiperiodic, periodic-air-gap, antiperiodic-air-gap), A0/A1/A2 + phi, c0/c1, mu, sigma, inner/outer angle. Tier M. - `bdCBdryDlg` — `bd_BdryDlg.h`. Electrostatic boundary: format combo, v (potential), qs (surface charge), c0/c1. Tier S. - `cdCBdryDlg` — `cd_BdryDlg.h`. Current-flow boundary: format combo, vs (complex voltage), qs (complex surface current), c0/c1. Tier S. - `hdCBdryDlg` — `hd_BdryDlg.h`. Heat boundary: format combo, Tset (fixed T), q (heat flux), beta (radiation), htc (convection), To1/To2 (ambient temps). Tier S. - `CNodeProp` — `NodeProp.h`. Mag point property: A (potential, complex), J (point current, complex). Tier S. - equivalent for elec/curr/heat (`bd_NodeProp.h`, `cd_NodeProp.h`, `hd_NodeProp.h`) — small variants. Tier S. - `CCircProp` — `CircProp.h`. Mag circuit: name, total current (complex), series/parallel radio. Tier S. - `bdCCircProp`, `cdCCircProp`, `hdCCircProp` — `bd_CircProp.h`, `cd_CircProp.h`, `hd_CircProp.h`. V/Q name plus voltage/charge or voltage/heat-source radio. Tier S. geometry-input and modal helpers (shared) - `CEnterPt` — `EnterPt.h`. TAB-coordinate entry (rectangular or polar). Tier S. - `CArcDlg` — `ArcDlg.h`. Arc creation: angle, max-side-length, boundary. Tier S. - `CGroupNumber` — `GroupNumber.h`. Single int. Tier S. - `CCopyDlg` — `CopyDlg.h`. Rotate or translate, with about-point or delta, n-copies, IsMove flag. Tier S. - `CMirrorDlg` — `MirrorDlg.h`. Two-point axis pa/pb. Tier S. - `CScaleDlg` — `ScaleDlg.h`. Base point, scale factor. Tier S. - `CGridMod` / `GRIDDLG` — `GridMod.h`, `GRIDDLG.H`. Grid size and coords (cartesian/polar). Tier S. - `CPromptBox` — typed-radius prompt used by `OnCreateRadius`. Tier S. - `CMakeABCDlg` — `MakeABCDlg.h`. Open-boundary construction: number of layers, radius, center x/y, edge-type combo. Tier M. - `CExteriorProps` — `ExteriorProps.h`. Axisymmetric exterior region: Ri, Ro, Zo. Tier S. - `CDXFImport` — `DXFImport.h`. DXF import tolerance. Tier S. problem-definition dialog (one per discipline) - `probdlg` — `probdlg.h`. Magnetostatic: problem type (planar / axisymmetric), length units, smart-mesh, frequency, precision, min-angle, depth, problem note, solver type (succ/newton), previous-solution path and prev-type. Tier M. - `bdCProbDlg` — `bd_probdlg.h`. Electrostatic. Same shape minus frequency/solver/prev. Tier S. - `cdCProbDlg` — `cd_probdlg.h`. Current flow: adds frequency. Tier S. - `hdCProbDlg` — `hd_probdlg.h`. Heat: adds dt (time step) and previous-solution path. Tier S. material-library editor - `fe_CLibDlg` — `fe_libdlg.h` and `bd_libdlg.h` / `cd_libdlg.h` / `hd_libdlg.h`. Drag-and-drop tree (library on left, model on right). Backed by `LibFolderInfo`. Tier L. The .lib file format is read-line-by-line in `fe_libdlg.cpp::ParseLine`. The drag/drop behavior depends on Win32 CTreeCtrl, so the iced version becomes two side-by-side scrollable lists with arrow buttons or drag handles. preferences - `CPref` / `bdCPref` / `cdCPref` / `hdCPref` — `Pref.h` and prefixed variants. Per-discipline-preprocessor defaults: edit action, coords (cart/polar), problem type, length units, solver, default freq, default grid size, default pixels-per-unit, depth, precision, min-angle, show-grid, snap-grid, show-origin, show-names, and a per-color picker driven by a combo. Tier M. - `CGeneralPrefs` — `GeneralPrefs.h`. App-wide: default-doc type, default-Lua-console (drop), default-XY-plot, default-output-window, default-smartmesh. Tier S. - the post-processor variant: `CViewPref`, `bvCPref`, etc. — see post-processor section. BH curve editor (mag-only material substructure) - `CBHData` — `BHData.h`. Two text columns (B, H) plus name, with linear/log plot preview. Reads BH datafiles via `BHDatafile.cpp`. Tier M. ### geometry processing - PSLG enforcement (`MOVECOPY.CPP::EnforcePSLG`, `FancyEnforcePSLG`, and per-discipline `bd_movecopy.cpp` / `cd_movecopy.cpp` / `hd_movecopy.cpp`) — the rebuild-list approach: empty the four lists, re-`AddNode` / `AddSegment` / `AddArcSegment` / `AddBlockLabel` everything, and the `Add*` functions check tolerance, split crossings, and reject overlaps. The fancy version takes an explicit tolerance for DXF import. Tier L. - intersection math — `CFemmeDoc::GetIntersection` (line-line), `GetLineArcIntersection`, `GetArcArcIntersection`, `ShortestDistanceFromArc`, `GetCircle` (recover center/radius from two endpoints + arc angle). Pure geometry; port directly. Tier M. - `CanCreateRadius` / `CreateRadius` — fillet two adjacent segments at a node with a given radius. Tier M. - mirror, rotate, translate, scale — `RotateMove`, `TranslateMove`, `ScaleMove`, `MirrorSelected`, `RotateCopy`, `TranslateCopy`. The move variants act on the selection; copy variants accept n-copies and emit fresh entities. Each ends with a call to `EnforcePSLG`. Tier M. - DXF import — `DXFImport.cpp` plus per-discipline overrides. Reads ASCII DXF r12: LINE, ARC, CIRCLE, LWPOLYLINE entities translate into segments and arcs, then `FancyEnforcePSLG(tol)` runs. Tier L. - DXF export — `WriteDXF`. Walks lists and writes LINE/ARC entities. Tier M. - mesh launch — `OnWritePoly` in `writepoly.cpp` (mag) + discipline variants. Writes a `.poly` file: nodes (with index, x, y, marker), segments (with marker referencing boundary id), holes (block labels marked ``), region attributes (each non-hole block label gets a region id and area target). Then `CreateProcess` invokes `triangle.exe -p -P -q -e -A -a -z -Q -I `. `FunnyOnWritePoly` handles periodic-BC enforcement (nodes on the periodic boundary must come in matched pairs). After Triangle returns, `LoadMesh` reads back `.node` / `.ele` / `.edge` to populate `meshnode` / `meshline` / `greymeshline`. Tier L. We exec the Triangle binary the same way the original does — only difference is `posix_spawn` instead of `CreateProcess`. ## post-processor The post-processor opens an `.ans` file (for elec `.res`, current `.res`, heat `.anh`) produced by the solver. Each discipline has its own pair of files. The view classes are again structurally identical; the differences are in plot quantities and integral kinds. ### loading - `CFemmviewDoc::OnOpenDocument` — `FemmviewDoc.cpp:226`. Reopens the matching .fem (to get nodes/lines/labels/properties), then reads the `.ans` body: solver settings header, mesh nodes (each with A, NumList), mesh elements (each with 3 node indices, lab, b1, b2, mu1, mu2), point/segment/block/arc property arrays, optional air-gap-element block. Allocates the `NumList`/`ConList` neighbor-list adjacency. Tier L. - `belaviewDoc.cpp`, `cviewDoc.cpp`/`CVIEWDOC.CPP`, `hviewDoc.cpp` — same shape, different per-element quantities (V/D, V/J, T/F respectively). Tier M each once mag is done. ### plot modes The view stores `DensityPlot` (an int code), `NumContours`, `ShowAr`, `ShowAi`, `ShowMask`, plus `LegendFlag`, `GreyContours`, `Smooth`, `PtsFlag`, `MeshFlag`, `VectorPlot`, `VectorScaleFactor`, `PlotBounds[9][2]`. `OnDraw` (FemmviewView.cpp:777) renders, in order: density fill, mesh wireframe (if MeshFlag), contour lines (if ShowAr/ShowAi), the PSLG geometry, vectors (if VectorPlot), the user-defined contour, the mask, names, mesh points, and the legend. mag density-plot options (`cvCDPlotDlg2` — yes, the mag view borrows the current-flow dialog class; see "notes and surprises") cover, depending on DC vs AC, the quantities |B|, Bx/Br, By/Bz, |H|, Hx/Hr, Hy/Hz, |J|, J_re, J_im. Sources: `FemmviewView.cpp::OnDplot`, `cv_DPlotDlg2.h`. - mesh wireframe — `OnShowMesh`. Tier S. - input geometry overlay (always on). Tier S. - equipotential / flux-line contours (mag) — uses real-A and optionally imag-A; banded by `NumContours`; `DoContours` is the line walker in elements. Tier M. - density plot (mag) — fills each element with a color-mapped shade of B/H/J magnitude or component, optionally smoothed using nodal values. `PlotFluxDensity` per-element fill. Tier L. - vector plot (mag) — `OnVplot` -> `CVPlotDlg`. Choices: none, B, H (DC) or B_re, H_re, B_im, H_im, B_re&B_im, H_re&H_im (AC). Tier M. - point-info readout — `OnRButtonDblClk` in EditAction==0 mode shows mesh node (x,y,A,B,H,mu) at the click. `DisplayPointProperties` formats. Tier S. - mesh-point markers — `PtsFlag`. Tier S. - legend overlay — `LegendFlag` plus the 20-bin colormap (`Color00..Color19`, `Grey00..Grey19`). Tier S. - mask display — show the Henrotte weighting-function mask used by the "Henrotte" force/torque integrals. Built by `MakeMask` / `bv_makemask.cpp` / `cv_makemask.cpp` / `hv_makemask.cpp`. Tier M. post-processor selection modes (`EditAction` again, but different meanings) - `0` Point — click reports values; right-double-click shows closest input node. Tier S. - `1` Contour — left-click extends a user-defined contour (`pDoc->contour`) by snapping to closest node or to the closest segment/arc; SHIFT pops `CBendContourDlg` to bend the last contour leg into an arc; DEL removes the last point; ESC clears. Tier M. - `2` Block — left-click toggles selection of the block under the cursor (uses `InTriangle` to find which mesh element, then floods to the connected region via `ConList`). Tier M. ### integrations and contour ops The line integral dialog `CLIntDlg` exposes (mag): normal flux (B.n), MMF along H.t, contour length / surface area, force-via-stress-tensor, torque-via-stress-tensor, and (B.n)^2. The block integral dialog `CBlockInt` exposes 17 entries enumerated in `FemmviewView.cpp::OnMenuIntegrate` cases 0..16: A.J (coil energy), integral of A, energy in B.H/2, hysteresis losses, total losses, area, ohmic losses, total current, integral of B, volume, Lorentz force (DC + 2X), Lorentz torque, energy density, Maxwell-stress (Henrotte) force, Maxwell-stress torque, integral of R^2, R/g (specific reluctance). Air-gap integrals (`GapIntegral`) compute force/torque/energy across an Air Gap Element boundary using harmonics. Sources: `FemmviewView.cpp:2952-3515`, `FemmviewDoc.cpp::BlockIntegral`, `FemmviewDoc.cpp::LineIntegral`, `FemmviewDoc.cpp::lua_gapintegral`. Tier XL — these are the algorithmically heaviest part of the post-processor. elec / current / heat integrals are smaller subsets (force and torque only, for `cv_BlockInt.cpp` and `cv_LIntDlg.cpp`). ### plot dialogs - `CCPlotDlg` / `CCplotDlg2` — `CPlotDlg.h`, `CplotDlg2.h`. Mag contour-plot setup: num contours, A-bounds (lower/upper), show real, show imag, show mask. Two variants because AC has imag part. Tier S. - `cvCDPlotDlg2` — `cv_DPlotDlg2.h`. Density-plot setup: which scalar to plot (combo), show-it toggle, show legend, grayscale toggle, lower/upper bound. Tier S. - `CVPlotDlg` / `bv_VPlotDlg` / `cv_VPlotDlg` / `hv_VPlotDlg` — vector-plot kind combo and scale factor. Tier S. - `CXYPlotDlg` / `bv_XYPlotDlg` / `cv_XYPlotDlg` / `hv_XYPlotDlg` — XY plot setup for the user-contour: quantity combo (potential, |B|, B.n, B.t, |H|, H.n, H.t, plus J_eddy, Js+J_eddy in AC; for materials also Mu_x/Mu_y per block), N points, to-file plus file-format combo (text / matlab / mathematica / gnuplot / csv). The plot itself renders to a metafile via `Xyplot.cpp`. Tier M. - `CGapPlotDlg` — `GapPlotDlg.h`. Air-gap plot: pick AGE, quantity, N points, file. Tier S. - `CLIntDlg`, `cv_LIntDlg`, `hv_LIntDlg` — line integral type combo. Tier S. - `CBlockInt`, `cv_BlockInt`, `hv_BlockInt` — block integral type combo. Tier S. - `bv_CircDlg`, `cv_CircDlg`, `hv_CircDlg` — circuit-results readout. Tier S. ### post-processor preferences - `CViewPref` / `bvCPref` / `cvCPref` / `hvCPref` — `viewpref.h` and prefixed variants. Edit-action default, default density-plot kind, default vector-plot kind, weighting scheme (Henrotte / uniform / extended), num contours default, grey-contours, legend, grid, show-Ar, show-Ai, show-mask, snap, smooth, shift-H, line-integral N points, plot N points, show-mesh, show-points, show-names, color overrides. Tier M. ## shared infrastructure - grid (size, snap, show, polar vs cartesian) — same code path on the canvas in both pre and post. Tier S. - screen↔world transforms — `ScreenToDwg` / `DwgToScreen`, currently implemented in `doc_canvas.rs`. Tier already done. - zoom-to-fit (`OnZoomNatural`) — bounding-box over all nodes/labels/arcs with margin. Tier S. - keyboard zoom (`CKbdZoom`) — typed window extents. Tier S. - preferences file IO — `femme.cfg`, `belasolv.cfg`, `csolv.cfg`, `hsolv.cfg` are text key/value pairs (``, ``, ``, ...). `ScanPreferences` / `WritePreferences` per view+doc pair. Tier S. - undo stack — `UpdateUndo` snapshots all four lists into `undonodelist` / `undolinelist` / `undoarclist` / `undoblocklist` before any mutation; `Undo` swaps. One level deep. Tier S. - group numbering — every entity carries an `InGroup` int; group-mode selection and modal group editing are the only consumers. Tier S. - material library on-disk — text in a custom block-keyed format; one library file per discipline, with vendor URL/name metadata. Tier M. - BH curve evaluation — `BHData` and `BHDatafile.cpp` implement cubic-spline interpolation for nonlinear materials; the result is consumed by the solver, not the GUI, so the GUI side is just edit + serialize. Tier M. ## suggested order each milestone names the smallest visible end-to-end result, not just an internal step. 1. **finish mag PSLG enforcement and segment / arc click-tools.** Port `EnforcePSLG`, `GetIntersection`, `GetLineArcIntersection`, `GetArcArcIntersection`, `CanCreateRadius`/`CreateRadius`. Add AddSegment/AddArc canvas tools that pick the first node on click 1 and finalize on click 2. Demo: draw two crossing segments and watch them get split at the intersection. 2. **selection model + DEL/move/copy.** Add per-entity selected flag, right-click toggle, box-select drag, group right-click, and the `CCopyDlg`/`CMirrorDlg`/`CScaleDlg` modals. Demo: build a quarter geometry, mirror-copy it to full. 3. **mag problem-definition dialog + property list dialogs.** Implement `probdlg` and `CPtProp` (the four-discipline shell), plus `CMatDlg`, `CBdryDlg`, `CNodeProp`, `CCircProp`. Demo: open the bundled `demo.fem`, edit a material, save, reopen, see the change. 4. **per-selection property dialogs.** `COpNodeDlg`, `COpSegDlg`, `COpArcSegDlg`, `COpBlkDlg`. Demo: click a label, hit space, change its block material from the dropdown, see the canvas redraw with the new label text. 5. **mesh launch end-to-end (mag).** Port `OnWritePoly` (skip periodic for now), call out to the existing `triangle` binary, parse `.node`/`.ele` back into a mesh layer, draw it. Demo: hit F2 (or a "Mesh" button), see triangles overlay. 6. **mag solver launch.** Wire the existing FFI to call `fkn` on the in-memory doc (or via the saved .fem/.poly path), then move on to step 7. Demo: hit "Analyze", solver runs, .ans appears on disk. 7. **mag post-processor loading + mesh display + density plot.** Port `CFemmviewDoc::OnOpenDocument`, the neighbor-list builder, `PlotFluxDensity` for |B| only, plus the colormap. Demo: open a solved .ans, see a colored flux density plot. 8. **mag post-processor contour plot + point-info readout.** `DoContours` for real-A, the equipotential drawing, plus mouse-click point query. Demo: click anywhere, get A/B/H/mu at that point. 9. **mag line integrals.** Contour edit mode (`EditAction=1` in the postprocessor), `CLIntDlg`, `LineIntegral` for cases 0 (flux), 1 (MMF), 2 (length/area). Demo: draw a contour across an airgap, read off normal flux. 10. **mag block integrals.** Block selection mode, `CBlockInt`, all 17 `BlockIntegral` cases. Demo: select coil, read coil energy and current; select rotor, read Lorentz torque. 11. **port the other three disciplines.** Reuse the now-proven shell. The doc parsers exist already; the work is dialog families and (smaller) integral sets per discipline. 12. **DXF, material library, BH editor, open-boundary builder.** Power-user features. Defer until the four disciplines work end-to-end. ## notes and surprises - mag's density-plot dialog class is named `cvCDPlotDlg2` and lives in `cv_DPlotDlg2.h` (the current-flow viewer's file). The mag viewer doesn't have its own — `FemmviewView.cpp::OnDplot` instantiates the current-flow class directly. Not a bug, just an MFC class-rename that didn't get propagated. New iced port should have one `DensityPlotDialog` parameterized by an enum of plot kinds, not four near-copies. - `EditAction` has different meanings in pre and post processor. In pre: 0=node, 1=segment, 2=label, 3=arc, 4=group. In post: 0=point, 1=contour, 2=block. The two views share the field name but not the semantics. - the post-processor opens a *separate document* (`CFemmviewDoc`) rather than augmenting the pre-processor doc. The `.ans` loader rereads the `.fem` first to grab the original geometry and property lists, then reads the solved-element block on top. In the Rust port this should be the same: one `PostDoc` that holds a `FemmDoc` plus the solved mesh and per-element fields, not a giant union. - `OnMenuAnalyze` shells out to `fkn.exe` via `CreateProcess` with the document path. In the port, the same model is fine — we already build per-engine archives, and the `analyze(path)` Rust call replaces the process spawn. Air-gap-element support (the `agelist` array) is a recent addition driving the gap-integral and gap-plot dialogs; many demo .fem files won't have any AGEs, so the GUI must handle `agelist.size==0` everywhere. - the BH-curve dialog stores B and H as multi-line text strings (`CString m_Bdata; CString m_Hdata;`) and parses them on OK via `StripBHData`. Idiomatic Rust replacement: two synchronized Vec. - `bd_nosebl.cpp` / `cd_nosebl.cpp` / `hd_nosebl.cpp` plus `NOSEBL.CPP` carry per-discipline copies of the geometry parser, even though the geometry sections are identical across disciplines. The Rust parser crates have already collapsed these into shared types where appropriate — keep doing that for any new shared code. - the original references a "Lua Console" prominently in menus and the `lnu_*` view functions, and many doc methods are split into a non-Lua and a Lua entry point (`AddNode` and `lua_addnode`). Per project rules, the Lua console is out of scope; the `lua_*` static methods can be ignored entirely. The Lua interpreter linked through the FFI is used by the solver for material formulas (functional MagDir, BH expressions) only. - the `triangle/triangle.c` mesher is left as a separate executable invocation. Don't try to inline it. - `cFemmeView::OnMakeABC` produces an open-boundary "asymptotic boundary condition" approximation by laying down N concentric circular shells, each with a calculated mu and sigma — it builds geometry and material/boundary properties together. The dialog has a combo for the edge type (Dirichlet / Neumann), defaults sourced from `MakeABCDlg.cpp`. Useful but not on the critical path. - two grid dialogs exist: `CGridMod` (`GridMod.h`) and `GRIDDLG` (`GRIDDLG.H`). They differ only in the coord-system combo wiring. Pick one for the port. - `KbdZoom`, `MyMsgBox`, `PromptBox`, `OutBox`, `MaskProgress`, `LuaEdit`, `MyTabCtrl`, `MDITabs`, `MyRecentFileList`, `MyCommandLineInfo` are MFC convenience widgets that have no analogue and no port. The native iced widgets cover their roles. - `ActiveFEMM.cpp` / `mathlink.h` are the ActiveX/Mathematica IPC shim — explicitly out of scope per the brief. - `femmplotDoc.cpp` + `femmplotView.cpp` are a tiny separate document type that pops up to display XY-plot metafiles from the post-processor. It is not a "post processor" itself, just a viewer. The Rust port can render the same plot inside the same iced window — no separate doc class needed.