[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-83992":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":8,"htmlUrl":8,"language":9,"languages":8,"totalLinesOfCode":8,"stars":10,"forks":11,"watchers":12,"openIssues":13,"contributorsCount":14,"subscribersCount":14,"size":14,"stars1d":15,"stars7d":16,"stars30d":16,"stars90d":14,"forks30d":14,"starsTrendScore":17,"compositeScore":18,"rankGlobal":8,"rankLanguage":8,"license":19,"archived":20,"fork":20,"defaultBranch":21,"hasWiki":22,"hasPages":20,"topics":23,"createdAt":8,"pushedAt":8,"updatedAt":24,"readmeContent":25,"aiSummary":8,"trendingCount":14,"starSnapshotCount":14,"syncStatus":26,"lastSyncTime":27,"discoverSource":28},83992,"TinyRetroPad","PlummersSoftwareLLC\u002FTinyRetroPad","PlummersSoftwareLLC",null,"Assembly",247,16,4,3,0,12,137,161,3.69,"Apache License 2.0",false,"main",true,[],"2026-06-12 02:04:37","\u003C!-- markdownlint-disable MD041 -->\n```ascii\n  _____      _             _____          _\n |  __ \\    | |           |  __ \\        | |\n | |__) |___| |_ _ __ ___ | |__) |_ _  __| |\n |  _  \u002F\u002F _ \\ __| '__\u002F _ \\|  ___\u002F _` |\u002F _` |\n | | \\ \\  __\u002F |_| | | (_) | |  | (_| | (_| |\n |_|  \\_\\___|\\__|_|  \\___\u002F|_|   \\__,_|\\__,_|\n T I N Y  X 86   D E S K T O P   E D I T O R\n```\n\n# TinyRetroPad\n\nA working, Notepad-style Windows text editor in roughly 2.5 KB.\n\nCompiles with: MASM and Crinkler.\n\nTinyRetroPad is a fork of **Dave's Tiny Editor (DTE)** by Matt Power, which is itself an extension of `tiny.asm` [HelloAssembly](https:\u002F\u002Fgithub.com\u002FPlummersSoftwareLLC\u002FHelloAssembly) by [Dave Plummer](https:\u002F\u002Fgithub.com\u002Fdavepl). The original goal was a working windowed text editor in the sub-1KB category; TinyRetroPad keeps that minimalist, size-obsessed spirit while filling out a full Notepad-style menu set (File \u002F Edit \u002F Format \u002F View \u002F Help) on top of it. It uses [Crinkler](https:\u002F\u002Fgithub.com\u002Frunestubbe\u002FCrinkler) compression at build time.\n\nTinyRetroPad is basically a wrapper around the RICHEDIT50W control from the WinAPI. DTE versions 1.0+ used the EDIT control with Crinkler cranked and were built up from tiny.asm, then worked down to 890 bytes with Win Defender quite unhappy. Versions 2.0+ backed Crinkler off a bit and use RICHEDIT to gain cheaper access to Courier font and much larger files; 2.0+ was worked down from 995 to 981 bytes as a bare editor. TinyRetroPad then grows from that 981-byte base by adding real menus and dialogs — Open\u002FSave\u002FSave As, Print\u002FPage Setup, Find\u002FReplace\u002FGo To, Font, Word Wrap, Time\u002FDate, and a Ln\u002FCol status bar — landing near 2,476 bytes. Each addition was kept as cheap as possible; the growth log at the top of [trpad.asm](trpad.asm) records what every feature cost in bytes.\n\n**Important:** Programs using Crinkler can be flagged as a false positive by antivirus, including Windows Defender. You may need to make an antivirus exception folder to build this (especially for 1.0+), or Windows may delete the EXE as soon as the build completes. Therefore, try this out AT YOUR OWN RISK - NO WARRANTIES \u002F NO GUARANTEES. You can accomplish this with PowerShell, but I am not going to tell you how. Sorry. You're on your own when messing with antivirus.\n\n- MASM version used: Microsoft (R) Macro Assembler Version 14.44.35224.0\n\n- MASM can vary depending on version. If you experience:\n\n  ```console\n  C:\\masm32\\include\\winextra.inc(11052) : error A2026:constant expected\n  C:\\masm32\\include\\winextra.inc(11053) : error A2026:constant expected\n  ```\n\n  In masm32\\include\\winextra.inc change:\n\n  ```assembly\n      STD_ALERT struct\n          alrt_timestamp dd ?\n          alrt_eventname WCHAR  [EVLEN + 1] dup(?)\n          alrt_servicename WCHAR [SNLEN + 1] dup(?)\n      STD_ALERT ends\n  ```\n\n  to:\n\n  ```assembly\n      STD_ALERT struct\n          alrt_timestamp dd ?\n          alrt_eventname WCHAR  (EVLEN + 1) dup(?)\n          alrt_servicename WCHAR (SNLEN + 1) dup(?)\n      STD_ALERT ends\n  ```\n\n  The brackets on lines 13,14 were changed to parens.\n\n- `build.bat` contains: \u002FLIBPATH:\"C:\\Program Files (x86)\\\\Windows Kits\\\\10\\\\Lib\\\\10.0.20348.0\\\\um\\\\x86\"\n  You may need to change to fit your system: \u002FLIBPATH:\"...\\\\Windows Kits\\\\10\\\\Lib\\\\(your version)\\\\um\\\\x86\"\n\n- You need to have Crinkler installed in a directory that has been added to PATH.\n  Example: C:\\utils\\Crinkler.exe\n\n## Contents\n\n| Folder | Description |\n| - | - |\n| `1_0` | DTE Version 1.0 aggressive 890 bytes build. Needs AV exception to be usable. |\n| `2_0_BACKUPS` | DTE Version 2.0 bare editor, 981 bytes build from RICHEDIT to release. |\n\n| File | Description |\n| - | - |\n| `build.bat` | Builds TinyRetroPad from command line. |\n| `DRAG ME ONTO DTE.txt` | How to use the editor. |\n| `DTE ABOUT.txt` | Explains some design decisions. |\n| `trpad.asm` | The program. TinyRetroPad, forked from DTE 2.0.9 |\n| `LICENSE.TXT` | Usage permissions (Apache License 2.0). |\n\n## Building the menus and Notepad features\n\nEverything past the bare RICHEDIT wrapper is built up the same way: keep the control doing the heavy lifting, and let the WinAPI common dialogs and a few `SendMessage` calls supply the rest. Almost every \"feature\" is just a menu ID routed to a one- or two-instruction handler, so the byte cost stays tiny. The\ngrowth log at the top of [trpad.asm](trpad.asm) tracks what each addition cost.\n\n### The menu bar\n\nThe whole menu bar is assembled at startup in `CreateNotepadMenus`:\n\n- `CreateMenu` makes the top-level bar, then each drop-down is a\n  `CreatePopupMenu`.\n- Items are added with two thin wrappers, `AppendEnabled` and\n  `AppendDisabled`, that call `AppendMenuA`. `AppendDisabled` with a null\n  string draws the separator lines, which avoids carrying a separate separator\n  call.\n- Every menu label lives as a packed `db` string (`MFile`, `MNew`, `MOpen`, etc.) and every command is a constant ID (`IDM_FILE_OPEN`, `IDM_EDIT_FIND`, …). `SetMenu` attaches the finished bar to the main window.\n- The same IDs power the right-click context menu via `TrackPopupMenu`, so the context menu costs almost nothing extra.\n\nThe classic `Save` item is appended onto the window's **system menu** with\n`GetSystemMenu`\u002F`AppendMenuA`, which is why it arrives as a `WM_SYSCOMMAND` instead of a `WM_COMMAND`.\n\n### Routing commands\n\nIn `WndProc`, `WM_COMMAND` extracts the low word of `wParam` and runs it down a flat list of `cmp`\u002F`je` checks straight to each `Cmd…` handler. Most handlers just forward an EDIT\u002FRICHEDIT message and return:\n\n| Menu | How it works |\n| - | - |\n| **Edit → Undo \u002F Cut \u002F Copy \u002F Paste \u002F Delete \u002F Select All** | Single `SendMessageA` of the matching `WM_UNDO` \u002F `WM_CUT` \u002F `WM_COPY` \u002F `WM_PASTE` \u002F `WM_CLEAR` \u002F `EM_SETSEL` message to the control. |\n| **Edit → Time\u002FDate** | `InsertTimeDate` calls `GetLocalTime` + `GetTimeFormatA`\u002F`GetDateFormatA`, then replaces the selection with `EM_REPLACESEL`. |\n\n### File: New \u002F Open \u002F Save \u002F Save As\n\nThe file commands are driven by the common dialogs so we never hand-roll a\nfile picker:\n\n- **Open** (`PickOpenFile`) and **Save As** (`PickSaveFile`) call\n  `GetOpenFileNameA` \u002F `GetSaveFileNameA` with a single all-files filter and store the chosen path in `CmdFile`. Open then reuses the existing `LoadStartupFile` path that the drag-and-drop launch already used.\n- Loading\u002Fsaving the actual bytes goes through `CreateFileA`, `GetFileSize`, `GlobalAlloc`, `ReadFile`\u002F`WriteFile`, and `CloseHandle` — the same plumbing the original drop-file editor used, now shared by the menus.\n- A `fDirty` flag (set on `EN_CHANGE`) drives the title-bar `*` and the `MaybeSaveChanges` \"Save changes?\" prompt that New \u002F Open \u002F Exit run before discarding the buffer.\n\n### File: Page Setup and Print\n\nPrinting leans entirely on RICHEDIT's own renderer:\n\n- **Page Setup** (`PageSetup`) just shows `PageSetupDlgA`.\n- **Print** (`PrintDoc`) calls `PrintDlgA` to get a printer DC, queries it with `GetDeviceCaps`, then asks the control to lay text onto that DC with `EM_FORMATRANGE`, looping `StartPage`\u002F`EndPage` until the whole document is emitted, wrapped in `StartDocA`\u002F`EndDoc` and released with `DeleteDC`. No GDI text drawing of our own is required.\n\n### Edit: Find \u002F Find Next \u002F Replace \u002F Go To\n\n- **Find \u002F Replace** use the modeless common dialogs `FindTextA` \u002F\n  `ReplaceTextA`. Because they are modeless, the message loop calls\n  `IsDialogMessageA` for the dialog, and the actual searching happens when the registered `FINDMSGSTRING` message (`uFindMsg`, fetched via `RegisterWindowMessageA`) arrives at `OnFindReplaceMsg`. `DoFindNext`, `DoReplaceOne`, and `DoReplaceAll` then drive selection via `EM_FINDTEXTEX`\n  and `EM_REPLACESEL`.\n- **Go To** uses an in-memory dialog template (`GoToTmpl`) shown with `DialogBoxIndirectParamA`, reads the line number with `GetDlgItemInt`, and scrolls there with `EM_LINEINDEX` + `EM_SETSEL`. Building the template in memory avoids a `.rc` resource and its overhead.\n\n### Format: Word Wrap and Font\n\n- **Word Wrap** (`ToggleWrap`) flips `fWrap` and re-targets the control's wrap width with `EM_SETTARGETDEVICE`.\n- **Font** (`ChooseFontDlg`) shows `ChooseFontW` and applies the result through `EM_SETCHARFORMAT` — the same mechanism used to force Courier at startup, which is why no `gdi32` import is needed.\n\n### View: Status Bar\n\nThe status bar is a plain `STATIC` child window created with `CreateWindowExA`. `UpdateStatus` reads the caret with `EM_EXGETSEL`, converts it to a line with `EM_EXLINEFROMCHAR` and a column with `EM_LINEINDEX`, formats `Ln %d, Col %d` with `wsprintfA`, and pushes it in with `SetWindowTextA`. The **Status Bar** menu item toggles `fStatus` and calls `ShowWindow`, while `RelayoutClient` resizes the editor and bar together on `WM_SIZE`.\n\n### Help\n\n**About** is a one-line `MessageBoxA`, and **View Help** opens the project URL in the default browser via `ShellExecuteA` — both cheaper than bundling any help content.\n\n## Credits\n\n- **TinyRetroPad** — fork adding the full Notepad-style menu set and dialogs.\n- **Dave's Tiny Editor (DTE)** — Matt Power, the sub-1KB RICHEDIT editor this fork is built on.\n- **`tiny.asm` \u002F [HelloAssembly](https:\u002F\u002Fgithub.com\u002FPlummersSoftwareLLC\u002FHelloAssembly)** — [Dave Plummer](https:\u002F\u002Fgithub.com\u002Fdavepl), the original foundation.\n\n## TinyRetroPad in use\n\n![TinyRetroPad in action](images\u002Fdte-in-action.png)\n",2,"2026-06-11 04:12:01","CREATED_QUERY"]