Turbo Vision 2.0 - モダンな移植版
(github.com/magiblot)- 古典的なテキストUIフレームワークをLinuxとWindowsで再活用できるよう移植し、UTF-8と拡張色を含む共通の開発基盤を提供する
- 既存のTurbo Visionアプリのソースコードレベル互換性を最大限維持しつつ、
charベースのAPIを継続利用して、プラットフォームごとのターミナル差異をライブラリ内部で吸収する - Unicode入力と表示をフレームワーク全体に統合し、2セル幅文字、結合文字、マルチバイトのショートカットキー、UTF-8ベースの編集と描画をあわせて処理できる
- 重なり合うウィンドウ、メニュー、ダイアログ、入力欄、スクロールバーといった基本ウィジェットを備え、イベントループ、タイマー、クリップボード、マウスホイール、リサイズ、大容量ファイル編集といった現代的な動作もサポートする
- 16色中心の過去APIを超えて24ビットカラー、xterm-256パレット、システムクリップボード、複数のコンソール環境対応までをまとめ、古いTUIコードと現代のターミナル環境をつなぐ基盤になる
プロジェクトの性格と中核方針
- Turbo Vision 2.0のモダンな移植版であり、古典的なテキストUIフレームワークをLinuxとWindowsで再活用できるようにしつつ、UTF-8と拡張色まで取り込んでいる
- 当初はLinux対応の追加と既存DOS/Windows動作の維持、古いTurbo Visionアプリのソースコードレベル互換性の保持に重点を置いていた
- この互換性のため、一部のBorland C++ RTL関数も直接実装している
- 2020年7〜8月の間に既存構造の中へ完全なUnicode対応を統合し、その過程で Turbo テキストエディタも作成した
- アプリケーションがターミナル機能差や直接的なターミナルI/O処理を迂回しないようラップし、プラットフォーム差異をライブラリ側で吸収する
- LinuxとWindowsで同じコードによりテキストUIを書くことに焦点を当て、
wchar_tやTCHARではなく引き続きcharベースのAPIを維持している
なぜ有用か
- ウィジェットクラスを多数提供し、サイズ変更可能な重なり合うウィンドウ、プルダウンメニュー、ダイアログ、ボタン、スクロールバー、入力欄、チェックボックス、ラジオボタンなどをすぐに使える
- 独自ウィジェットを作る場合でも、イベントディスパッチや全角Unicode文字表示といった共通処理を書き直す負担を減らせる
- 各環境でできる限り同じ結果が出るように処理する
- Linuxコンソールで明るい背景色がblink属性に依存する場合も、ライブラリが代わりに処理してくれる
- Microsoft RTLの
setlocaleUTF-8対応を活用し、Windowsでもstd::ifstream f("コンピュータ.txt");のようなコードが意図どおり動作できる- WindowsではRTLがファイル名をシステムエンコーディングへ即座に変換する
Unicode設計とテキスト処理
- UTF-8を入力と表示の基本エンコーディングとして採用している
- 既存の
char *データ型と互換性があり、ターミナルI/Oエンコーディングと同じなので不要な変換を減らせる - UTF-8 Everywhere Manifesto の方向性とも一致する
- 既存の
- Borland C++でビルドする場合はUnicodeをサポートしないが、API拡張はエンコーディング非依存コードを書けるよう設計されている
KeyDownEventには既存のcharScan.charCodeに加えてtext[4]とtextLengthが追加され、UTF-8入力バイト列を直接渡すcharScan.charCodeには下位互換性のため今もCP437基準の文字が入るgetText()でstring viewを受け取って使う方式が推奨される
- 入力例はUnicodeと旧来コードがともに動作する仕組みをそのまま示している
ñを入力するとcharCode=164 ('ñ'),text={'\xC3','\xB1'},textLength=2になる€を入力するとCP437にないためkeyCode=0x0,charCode=0,text={'\xE2','\x82','\xAC'},textLength=3になる- ショートカットキー入力時は
textLength=0で空になる
- TScreenCellはUTF-8コードポイントと太字、下線、斜体といった拡張属性を保持できる
- ASCII制御文字はコードページ文字のように扱われる
- 有効なUTF-8はそのまま表示され、無効なUTF-8はコードページ文字として扱われる
- 拡張ASCIIとUTF-8を混在できるため下位互換性には有利だが、予期しない結果が生じることもある
- 2セル幅文字と結合文字も個別に処理する
- 結合文字は前の文字の上に重ねて表示される
ZERO WIDTH JOINERU+200Dは常に省略される- ターミナルが
wcwidth基準の文字幅を尊重すれば、目立つ描画崩れはほとんどない - Wide character display で例を確認できる
Unicode APIと標準ビューのサポート
-
Unicode対応の描画API
TDrawBuffer::moveChar,putCharはchar cを コードページ文字として扱うmoveStr,moveCStrはTStringViewを受け取り、Unicodeの規則で文字列を処理するmaxStrWidthはバイト数ではなく カラム数 基準strIndentもバイトではなく カラム数 基準なので横スクロールに使える- 戻り値はコピーされたテキストの 表示幅
moveBufはTStringView導入前に null-terminated ではない文字列を処理していた関数のため維持されているcstrlen(TStringView s)は~を除いた表示長を、strwidth(TStringView s)は~を含む表示長を返す
-
draw() の単純化とバグ削減
- 従来の
TFileViewer::draw()は部分文字列を一時バッファにコピーしてからmoveStrを呼び出していたが、この方式には buffer overrun の危険とマルチバイト境界の問題があった - 修正後は
b.moveStr(0, p, c, size.x, delta.x);の1行で処理し、中間コピーをなくしたdelta.xをカラム基準でそのまま適用できる- 最大
size.xカラム分だけコピーするため、バイト数と境界条件を直接計算する必要が減る
- 従来の
-
Unicode表示をサポートする標準ビュー
TStaticText,TFrame,TStatusLine,THistoryViewer,THelpViewer,8c7dac2a,20f331e3,TListViewer,TMenuBox,TTerminal,TOutlineViewer,tvdemoのTFileViewer,tvdirのTFilePaneが Unicode表示をサポートする- 一部のビューは 横スクロール と ワードラップ まで併せて処理する
-
Unicode入力まで処理するビュー
TInputLine,cb489d42,TEditor,TMenuViewのショートカットキー では Unicodeユーザー入力 まで処理するTEditorインスタンスはデフォルトで UTF-8モード であり、Ctrl+Pで single-byte モードに切り替え可能- この切り替えはドキュメント内容を変えず、表示方式 と 入力エンコーディング だけを変更する
TStatusLine,TButtonなどの 強調されたキーボードショートカット には対応していない
-
メニューとステータスラインの多言語文字列
~Ñ~ello,階~毎~料入報最...,五劫~の~擦り切れ,העברית ~א~ינטרנט,~Alt-Ç~ Exitのような文字列をメニューとステータスラインでそのまま使える- 結果画面は Unicode Hello で確認できる
プラットフォーム別の動作モデル
-
Unix
- Ncurses ベースのターミナル対応を使用
- X10、SGR マウスエンコーディング、xterm の modifyOtherKeys、Paul Evans の fixterms、Kitty の keyboard protocol、WSL Conpty の
win32-input-mode、far2l、Linux コンソールのTIOCLINUX修飾子と GPM マウスに対応 - プログラムが異常終了する前にターミナル状態を復元する カスタムシグナルハンドラー を備える
stderrが tty の場合、画面破損を防ぐためバッファに保存し、終了時または一時停止時に出力- バッファサイズに制限があるため、いっぱいになると
stderrへの書き込みが失敗する場合がある - すべて保持するには
2>リダイレクトを推奨
- バッファサイズに制限があるため、いっぱいになると
TERM、COLORTERM、ESCDELAY、TVISION_USE_STDIO環境変数を読み取るCOLORTERM=truecolorまたは24bitであれば 24 ビットカラーを前提とするESCDELAYのデフォルト値は10msTVISION_USE_STDIOが空でなければ/dev/ttyの代わりにstdinとstdoutで I/O を行う
-
Windows
- Win32 Console API のみに対応
- これをサポートしないターミナルエミュレーターでは、別個のコンソールウィンドウを自動で開く
- アプリケーションのレイアウトはコンソールバッファではなく コンソールウィンドウサイズ を基準とし、終了時または一時停止時にコンソールバッファを復元する
- Borland C++ でない場合は、起動時にコンソールコードページを UTF-8 に変更し、終了時に復元する
- Microsoft C ランタイムも UTF-8 モードに切り替え、開発者が
wchar_t系を直接使う必要を減らす - レガシーモードとビットマップフォントの組み合わせでは Unicode 表示が崩れることがあり、これを検出すると
ConsolasまたはLucida Consoleへのフォント変更を試みる- 例は photo で確認できる
-
共通の動作改善
- 24 ビットカラー、
stdin/stdout/stderrリダイレクトとの共存、32 ビット help ファイル互換性を提供 TVISION_MAX_FPS環境変数で最大更新レートを制御- デフォルト値は
60 0は制限を無効化-1はTHardwareInfo::screenWrite呼び出しごとに即時描画させる
- デフォルト値は
- 中ボタン、マウスホイール、最大 32767 行/列 の画面サイズ、リサイズイベントに対応
- ウィンドウは左下隅からもサイズ変更でき、中ボタンで空白領域をつかんでドラッグできる
- メニューは親項目を再クリックして閉じられ、スクロールバーはドラッグ中のページスクロールとホイール入力に反応する
TInputLineはフォーカス移動時に不要なテキストスクロールを行わないTFileViewerとTEditorは LF 改行 をサポートし、TEditorは保存時に既存の改行コードを維持し、新規ファイルではデフォルトで CRLF を使うTEditorには右クリックメニュー、中ボタンドラッグスクロール、単語単位削除キー、Home キー改善、64 KiB 超のファイル対応まで含まれるtvdemoにはイベントビューアアプレットと背景パターン変更オプションが含まれる
- 24 ビットカラー、
イベントループと API の変更
- 画面書き込みのバッファリング を使用し、通常はアクティブなイベントループ 1 回ごとに 1 回ターミナルへ送信する
- ビジーループで即時更新が必要な場合は
TScreen::flushScreen()を呼び出せる TEventQueue::waitForEvents(int timeoutMs)は入力イベントを待機し、待機中もTScreen::flushScreen()によって画面更新を行うTProgram::getEvent()はデフォルト値20のeventTimeoutMsでこれを呼び出し、100% CPU のビジーループ を避けるTEventQueue::wakeUp()は別スレッドからイベントループを起こす thread-safe なメソッドTView::getEvent(TEvent &, int timeoutMs)により、ビュー単位のタイムアウト待機を設定できるsetTimer、killTimerが追加され、タイマー満了時にevBroadcastとcmTimerExpiredを発生させるperiodMsが負数ならワンショットタイマーとして自動的にクリーンアップされる- タイマーイベントは
TProgram::idle()で生成され、キーボードまたはマウスイベントがないときにのみ処理される
TDrawBufferはもはや固定長配列ではなく、範囲外アクセスを防ぐTRectのmove、grow、intersect、UnionはTRect&を返し、チェーン呼び出し が可能TApplicationはdosShell()、cascade()、tile()を標準提供し、cmDosShell、cmCascade、cmTileをデフォルト処理するTStringView、TSpan<T>、TDrawSurface、TSurfaceView、TClipboardなどの型が追加されたTHardwareInfo、TScreen、TEventQueueはmainより前ではなく、最初のTApplication生成時に初期化される- 入力拡張も含まれる
evMouseWheel、mwUp、mwDown、mwLeft、mwRightmbMiddleButton、meTripleClickevMouseUp.buttonsに解放されたボタン情報を保持hotKeyStr、getAltCharStr、getCtrlCharStrにより マルチバイトショートカット を実装可能TKeyによりShift+Alt+Upのような新しいキー組み合わせを定義可能TInputLineはilMaxBytes、ilMaxWidth、ilMaxCharsの limitMode をサポート
クリップボード連携
-
システムクリップボード統合
- 従来は
TEditor::clipboard静的メンバーによる 内部クリップボード のみが存在し、これを利用できるのはTEditorだけだった - 新しい
TClipboardクラスで システムクリップボード にアクセスし、アクセスできない場合は内部クリップボードにフォールバックする
- 従来は
-
対応環境
-
API と貼り付け処理
<tvision/tv.h>をインクルードする前にUses_TClipboardを定義するとTClipboardを利用できるsetText(TStringView text)はシステムクリップボードの内容を設定し、アクセスできない場合は内部クリップボードを使うrequestText()はシステムクリップボードの内容を 非同期で要求 し、その後通常のevKeyDownイベント形式で受け取る- 貼り付けテキストは
keyDown.controlKeyStateのkbPasteフラグ で通常のキー入力と区別できる - 長い貼り付けが数千回のキー入力のように処理される非効率を減らすため、
TView::textEvent(...)が追加された- 連続する
evKeyDownテキストをユーザーバッファにまとめて読み取る - もはやテキストでなくなった場合は
putEvent()で次のループに渡す
- 連続する
-
標準コマンド連携
TEditorとTInputLineはcmCut、cmCopy、cmPasteコマンドに反応する- アプリケーションはステータスバーなどで
kbCtrlX、kbCtrlC、kbCtrlVを各コマンドに接続する必要がある - フォーカスと選択状態に応じて、関連コマンドを自動的に有効化または無効化する
拡張カラーモデルと互換性
- Turbo Vision API は従来の 16 色を超える 拡張カラー をサポートする
- 4 ビット BIOS color attributes
- 24 ビット RGB
- 8 ビット xterm-256color palette index
- terminal default color
- ターミナルが特定の色形式をサポートしていない場合、Turbo Vision が 量子化 して表示する
- モダンなプラットフォームでは
ucharの代わりに TColorAttr、ushortの代わりに TAttrPair を導入TPaletteもTColorAttr配列を使用するTView::mapColorはvirtualとなり、階層型パレットシステムを迂回した色指定が可能になった
TColorBIOS、TColorRGB、TColorXTerm、TColorDesiredにより色表現の階層を分けるTColorAttrはforeground、background、styleビットマスクを持つ- スタイルには
slBold、slItalic、slUnderline、slBlink、slReverse、slStrikeを含む slReverseは信頼性が低いため、reverseAttribute(TColorAttr attr)の使用が推奨される
TViewで拡張カラーを使う方法は 3 つあるmapColorをオーバーライドしてインデックスごとに ハードコード するdraw()でTDrawBufferに 直接TColorAttrを渡す- アプリケーション パレット自体を変更 する
TScreen::screenModeでディスプレイ能力を公開するsmMonoは monocolorsmBW80は grayscalesmCO80は少なくとも 16 色smColor256は少なくとも 256 色smColorHighはそれ以上の色、たとえば 24 ビットカラーを意味する
- 下位互換性は
#ifdefのない共通 API の維持に合わせて設計されている- Borland C++ では
TColorAttr、TAttrPairはそれぞれuchar、ushortの typedef になる - モダンなプラットフォームでは従来の
uchar、ushortの位置を置き換えられる - レガシーコードはそのままコンパイルできるが、non-BIOS 色属性 は
ucharやushortに暗黙変換された時点で失われる可能性がある
- Borland C++ では
drawメソッドでushortをパレットインデックス対と色属性対の両方に使っていたコードはそのまま動作するが、拡張カラーを活かすには変数宣言をushortから TAttrPair に変えればよいTColorDialogは再設計されていないため、ランタイムの 拡張カラー選択器 としては利用できない
ビルド、配布、統合
-
Linux と Unix 系
- CMake と GCC/Clang により、静的ライブラリ
libtvision.aをビルド可能 hello、tvdemo、tvedit、tvdir、mmenu、palette、tvhcHelp Compiler もあわせて生成される- 要件は C++14 対応コンパイラ、
libncursesw、任意のlibgpm - ランタイムのクリップボード連携には
xsel、xclip、wl-clipboardが使われる - 一部の環境では
-ltinfowが必要な場合があり、そうでないと実行時に segmentation fault が発生することがある- 関連 issue: #11
- CMake と GCC/Clang により、静的ライブラリ
-
Windows とその他のツールチェーン
- MSVC ビルドでは、対象アーキテクチャごとに個別のビルドディレクトリを使い、成果物は
tvision.libとサンプルアプリとして生成される TV_USE_STATIC_RTLオプションで Microsoft ランタイムの静的リンクが可能/MTと/MD、デバッグ版と非デバッグ版のバイナリは相互に混在リンクできない<tvision/tv.h>を使うには/permissive-、/Zc:__cplusplusフラグが必要で、CMake のサブモジュール方式なら自動で有効化される- 適切な MSVC バージョンと設定であれば Windows XP も可能とされている
- MinGW は Linux と同様に CMake でビルドし、コンパイラが対応していれば Windows XP 以降で実行可能
- Borland C++ でも DOS または Windows 向けライブラリのビルドは可能だが、Unicode はサポートしない
- Borland C++ 環境では winevdm の使用が代替案として示されている
- MSVC ビルドでは、対象アーキテクチャごとに個別のビルドディレクトリを使い、成果物は
-
プロジェクト統合方法と配布状況
- CMake では
find_package(tvision CONFIG)またはadd_subdirectory(tvision)の 2 方式を提供 - どちらの方式でも include パスと Ncurses、GPM など必要なリンクを自動処理する
- vcpkg に
tvisionポートがある - 現時点では stable release はなく、最新コミット基準でアップグレード中に見つかった問題の報告が推奨されている
- Unix 系ではデモアプリを自分でビルドする必要がある
- Windows バイナリは Actions で提供される
examples-dos32.zip: Borland C++ ビルドの 32 ビット実行ファイル、Unicode 非対応examples-x86.zip: MSVC ビルドの 32 ビット実行ファイル、Windows Vista 以降が必要examples-x64.zip: MSVC ビルドの 64 ビット実行ファイル、x64 Windows Vista 以降が必要
- CMake では
サンプル、ドキュメント、活用事例
- 入門用として Turbo Vision For C++ User's Guide が推奨されている
- 基礎を身につけた後は、Turbo Vision 2.0 Programming Guide も参考にできる
- サンプルとして
hello、tvdemo、tvedit、paletteなどを提供 - スクリーンショット集は here で見られる
- 活用中のアプリケーションとして、以下が挙げられている
1件のコメント
Hacker Newsのコメント
このリポジトリがフロントページに載っているのを見て本当にうれしくなったし、今はこのリポジトリ向けのwrapperを自分で作っている
.Net上でmacOS向けにTurbo Visionを動かしているのだが、かなり魔法のような感覚がある
より高水準のAPIを提供し、かなり古めかしいpalette APIもラップまたは改善し、layoutも追加しているところだ
まだ非公開リポジトリで鋭意作業中で、今日はコントロールが置かれたsurface基準でpaletteを決め、明日は別の部分を整えるという感じで継続的に手を入れている
layoutの整理や、今の基準で不足している基本コントロールの追加など、やることはまだ残っている
以前Terminal.Guiも使ってみたが、v2への移行中だからか、バグなしで扱うのはかなり難しかったし、Claudeも実際のターミナルを考慮せずにTUIライブラリを作ると何をしてはいけないかをよく示していた
だから現代版Turbo Visionがあればいいのにと思っていたところでこのリポジトリを見つけ、Unicode対応まで入っているのを見て本当にありがたかった
https://www.remobjects.com/elements/oxygene/
https://www.remobjects.com/elements/
私も.NET wrapperを作っていて、たぶん進捗はそこまでではないが、Windows Forms APIをできるだけ近く再現しつつ、drag-and-dropのTUIデザイナーまで入れたいと思っている
例はこちら: https://github.com/brianluft/terminalforms/tree/main/src/TerminalFormsDemo
C++側の厄介な統合作業の大半はこちらで処理した: https://github.com/brianluft/terminalforms/tree/main/src/tfcore
P/Invokeで呼べるようにシンプルなC関数をexportしておき、C#側は主にクラス構造化に集中できるようにした
最初はC++で可能なことはすべてC#でも可能であるべきだと押し通したが、あまりに複雑になり、placement newでC++オブジェクトをC#バッファ内に置いて、実質的にC#側でC++クラスを継承するようなレベルまで行ったところで設計が破綻した
結局、より直接的で柔軟性は低いがはるかに単純なアプローチに切り替え、柔軟性はC#側に持たせることにした
あなたのP/Invokeシステムがどう構成されているのか気になる
おかげでGEOS向けアプリを作るとか、1人Hurdチームに入るとかいう無駄な試みをせずに済んでいる気がする
Terminal.Guiも使ってみたが、TVのほうが魅力的でwrapperを考えていたので、公開されたらぜひ見てみたい
私のプログラミング歴は文字どおり90年代にゴミ箱から始まった
誰かが捨てたTurbo Visionの本を拾い、誰でも作れた青みがかったTUIにすぐ夢中になった
元のバージョンはTurbo Pascal 6に含まれていて、C++ポートは後から出た
だからこれはポートの現代的ポートと見ていい
Borlandは他のフレームワークでも似たようなことをしていて、OWLももともとはTurbo Pascal for Windows 1.5のほうが先だったし、C++ Builderのツールのかなりの部分も実際にはDelphiで書かれていた
Turbo Pascal 5.5のObject Pascal、そして6のTurbo Visionが私のOOP入門だったが、その道に入れたのは幸運だったと思う
MS-DOSのような環境でも、OOPとTurbo Visionがもたらすフレームワークの利点をしっかり学べた
BorlandがTurbo Pascal、Turbo C++、TurboVisionを出してきたとき、可能性の宇宙が一気に広がったように感じた
コンパイラ性能も素晴らしく、マニュアルは芸術品のようで、あの本を今でも持っていられたらと思う
これは単なる文化的宝物だ
90年代初頭にC/C++をほぼTurbo C++付属のBorland本の山だけ読んで独学したが、今では参考書だけ読んでそうやって学ぶ場面を想像することすら難しい
新しいTUIフレームワークはいつも何かが足りない感じがしていたし、今これをまた使ってみて、それが単なるノスタルジーだったのか確かめようと思っている
次のツールに組み込む予定で、作った人たちには大きな拍手を送りたい
GW-BASICとMS-DOSを除けば、Turbo BASIC、Turbo Pascal、Turbo C++ for MS-DOS and Windows 3.x、Turbo Vision、OWLまで全部Borlandだった
VC++は5あたりから使ったが、MFCはBorland製品に比べるといつもあまりに味気なく感じられた
今でもC++ BuilderのRAD能力に本当に追いつけているものは少なく、.NETもDelphiのような低レベルコーディングとAOTのストーリーを整理するのにかなり長い時間がかかった
Go、C++、Rustの開発者にはMS-DOS向けTurbo Pascal 7と最新のDelphiを何部かずつ渡すべきだと思う
Turbo Vision 2.0は今でもかなり実用的で、1年前にプロトタイプ作業で実際に使ってみた
LLDBデバッガ向けのTurbo Visionフロントエンドを作り、BorlandのTurbo Debuggerのように動かそうとしたが、大半は思いどおりにいった
199x年で止まった場所をそのまま引き継いだようで驚かされたし、1993年のコードも大きな問題なくコンパイルして実行できた
内蔵エディタにもScintillaベースのより良い版があって、syntax highlightingのような機能も入っているが、私が改造しようとしていた部分はうまくいかず、たぶん作者に助けを求める必要がありそうだ
ただ、現代的な共有知としての意味でのドキュメントは不足していて、Stack OverflowやAIに尋ねるのは難しく、サンプルコードを見て学び、Turbo Visionの本を何冊も読み返す昔ながらのやり方で進めるしかなかった
手動layoutはかなり面倒なので、Qtのような自動layoutがあるといいし、splitterも少し恋しいが、実装自体は難しくなさそうだ
もうひとつ驚いたのは、TVが実際にはかなり小さくコンパクトだという点だ。90年代にはものすごく巨大に感じていた
全体として現代化の作業は本当によくできていて、私はこれをとても気に入っている
Turbo Visionはもともと高品質な文書を非常に多く提供していた
むしろそうした文書が不足しているのは今の時代のほうだと思う
https://archive.org/details/bitsavers_borlandTurrogrammingGuide1992_25707423
cmakeディレクティブが山ほどあるのを見ると、つい昔に戻りたくなる
Turbo CやPascalではF9を押せばすぐ動いたのに
一方で、これは私たちのツールチェーンの無能さも示していると感じる
今の時代ならオンラインコンパイラをひとつ示してすぐ実行するか、ダウンロードしてフォルダをひとつ開いて実行する程度で済むべきなのに、ツールというより儀式の手順になってしまっている
./configure && make && make installこそ、今でもgold standardであるべきだ
これはTurbo Visionポート/クローンのひとつにすぎない
C++側にはこれもある: https://github.com/kloczek/tvision
FreePascal/Lazarusに入っている版はPascalで書かれていて、Rust版もひとつあるが、少しvibe-codedっぽく見える: https://github.com/aovestdipaperino/turbo-vision-4-rust
ターミナルでこれを動かすと、本来のテキストモード画面のマウスが持っていた肝心の感覚が少し失われる
本物のテキストモード画面では、マウスポインタではなく、マウスで動く黄色いブロックのように見えた
高解像度LinuxテキストモードでGPMを使って動かしてみた人がいるのか気になる
下のセルの色を反転して表示する方式で、画面の大半を埋めるメインウィンドウが濃い青だったため、結果として明るい黄色のブロックのように見えることが多かった
最近のWookash podcastでChuck Jazdzewskiを扱った回を勧めたい
もともとTurbo Visionを作ったチームの一員で、そのエコシステム全体の話もたくさん出てくる
私はいまだにC++版より本物のTurbo Vision、つまりPascal版のほうを求めている
C++版は結局、Pascal版を移したものに近く感じられる
たとえばPascalでは
usesがキーワードなのに、#defineでモジュールをincludeする方式はどうしてもハックっぽく感じるまあ今となっては大きな違いではないかもしれないが
テキストモードIDEもFree Visionを使っている
https://wiki.lazarus.freepascal.org/images/1/19/Userscreen.png
ただし大きな違いは、Free VisionとTurbo VisionがDelphiの
classではなく、Turbo Pascal 5.5時代のobject型を使っている点だclassならRTTIのおかげで自動シリアライズのようなものを実装しやすいが、objectにはそれがないので、異なる型を実行時に区別するには、オブジェクトポインタの固定オフセットにあるVMTポインタを登録するような形で手動シリアライズを行う必要があるFree Pascalは
objectにprivate/protected/publicやpropertyのような便利機能を少し追加しているが、Free Visionは元のTurbo Vision APIを実装するため、そうした拡張は使っていない