Turbo Vision 2.0 - un port moderno
(github.com/magiblot)- Al portar de nuevo el framework clásico de UI de texto para poder reutilizarlo en Linux y Windows, ofrece una base de desarrollo común que incluye UTF-8 y colores extendidos
- Mantiene al máximo la compatibilidad a nivel de código fuente con las apps existentes de Turbo Vision, pero sigue usando una API basada en
charpara absorber dentro de la librería las diferencias entre terminales según la plataforma - Integra la entrada y visualización Unicode en todo el framework para manejar caracteres de ancho doble, caracteres combinantes, atajos multibyte y edición y dibujo basados en UTF-8
- Incluye widgets básicos como ventanas superpuestas, menús, cuadros de diálogo, campos de entrada y barras de desplazamiento, y también soporta comportamientos modernos como bucle de eventos, temporizadores, portapapeles, rueda del mouse, cambio de tamaño y edición de archivos grandes
- Va más allá de la antigua API centrada en 16 colores al reunir color de 24 bits, la paleta xterm-256, el portapapeles del sistema y soporte para varios entornos de consola, sirviendo como puente entre código TUI antiguo y terminales modernos
Naturaleza del proyecto y dirección principal
- Como port moderno de Turbo Vision 2.0, permite volver a usar el clásico framework de UI de texto en Linux y Windows, incorporando además UTF-8 y colores extendidos
- Al principio se enfocó en añadir soporte para Linux, mantener el comportamiento existente en DOS/Windows y preservar la compatibilidad a nivel de código fuente con aplicaciones antiguas de Turbo Vision
- Para lograr esa compatibilidad, también implementa directamente algunas funciones RTL de Borland C++
- Entre julio y agosto de 2020 integró soporte Unicode completo dentro de la estructura existente y, en ese proceso, también se creó el editor de texto Turbo
- Envuelve el acceso para que las aplicaciones no tengan que esquivar diferencias de capacidades del terminal ni manejar directamente la E/S del terminal, absorbiendo del lado de la librería las diferencias entre plataformas
- Se centra en escribir UI de texto con el mismo código en Linux y Windows, manteniendo una API basada en
charen lugar dewchar_toTCHAR
Por qué es útil
- Ofrece muchas clases de widgets para usar de inmediato ventanas superpuestas redimensionables, menús desplegables, cuadros de diálogo, botones, barras de desplazamiento, campos de entrada, casillas de verificación y botones de opción
- Incluso al crear widgets propios, reduce la carga de reescribir manejo común como el despacho de eventos o la visualización de caracteres Unicode de ancho completo
- Está diseñado para producir, en la medida de lo posible, el mismo resultado en cada entorno
- Incluso cuando en la consola de Linux los colores de fondo brillantes dependen del atributo blink, la librería lo resuelve internamente
- Aprovecha el soporte UTF-8 de
setlocaleen el RTL de Microsoft para que en Windows también funcione como se espera código comostd::ifstream f("コンピュータ.txt");- En Windows, el RTL convierte inmediatamente el nombre del archivo a la codificación del sistema
Diseño Unicode y procesamiento de texto
- Adopta UTF-8 como codificación predeterminada para entrada y visualización
- Es compatible con el tipo de dato existente
char *y coincide con la codificación de E/S del terminal, reduciendo conversiones innecesarias - También está alineado con el UTF-8 Everywhere Manifesto
- Es compatible con el tipo de dato existente
- Al compilar con Borland C++, no hay soporte Unicode, pero la ampliación de la API está diseñada para permitir escribir código independiente de la codificación
- En
KeyDownEvent, además del campo existentecharScan.charCode, se agregantext[4]ytextLengthpara pasar directamente la secuencia de bytes de entrada UTF-8- En
charScan.charCodese sigue guardando un carácter según CP437 por compatibilidad hacia atrás - Se recomienda usar
getText()para obtener una string view
- En
- Los ejemplos de entrada muestran tal cual cómo conviven Unicode y el código heredado
- Al ingresar
ñ, quedacharCode=164 ('ñ'),text={'\xC3','\xB1'},textLength=2 - Al ingresar
€, como no existe en CP437, quedakeyCode=0x0,charCode=0,text={'\xE2','\x82','\xAC'},textLength=3 - En entradas de atajos,
textLength=0queda vacío
- Al ingresar
- TScreenCell puede contener code points UTF-8 y atributos extendidos como negrita, subrayado y cursiva
- Los caracteres de control ASCII se tratan como caracteres de code page
- El UTF-8 válido se muestra tal cual, y el UTF-8 inválido se trata como caracteres de code page
- Se puede mezclar ASCII extendido y UTF-8, lo que favorece la compatibilidad hacia atrás pero también puede producir resultados inesperados
- También maneja por separado caracteres de ancho doble y caracteres combinantes
- Los caracteres combinantes se superponen sobre el carácter anterior
ZERO WIDTH JOINERU+200Dsiempre se omite- Si el terminal respeta el ancho de carácter según
wcwidth, casi no habrá artefactos gráficos visibles - Puede verse un ejemplo en Wide character display
API de Unicode y soporte de vistas estándar
-
API de dibujo con reconocimiento de Unicode
TDrawBuffer::moveChar,putChartratanchar ccomo un carácter de página de códigosmoveStr,moveCStrrecibenTStringViewy procesan cadenas con reglas de UnicodemaxStrWidthse basa en la cantidad de columnas, no en la cantidad de bytesstrIndenttambién se basa en la cantidad de columnas, no en bytes, así que puede usarse para desplazamiento horizontal- El valor de retorno es el ancho de visualización del texto copiado
moveBufse mantiene porque era la función que procesaba cadenas no terminadas en null antes de la introducción deTStringViewcstrlen(TStringView s)devuelve la longitud visible excluyendo~, ystrwidth(TStringView s)devuelve la longitud visible incluyendo~
-
Simplificación de
draw()y reducción de bugs- El
TFileViewer::draw()original copiaba una subcadena a un búfer temporal y luego llamaba amoveStr, pero este método tenía riesgo de buffer overrun y problemas en los límites de caracteres multibyte - Tras la corrección, todo se resuelve con una sola línea:
b.moveStr(0, p, c, size.x, delta.x);, eliminando la copia intermediadelta.xpuede aplicarse directamente con base en columnas- Como solo se copian hasta
size.xcolumnas, ya no hace tanta falta calcular manualmente la cantidad de bytes ni las condiciones de borde
- El
-
Vistas estándar con soporte para visualización Unicode
TStaticText,TFrame,TStatusLine,THistoryViewer,THelpViewer,8c7dac2a,20f331e3,TListViewer,TMenuBox,TTerminal,TOutlineViewer,TFileViewerdetvdemoyTFilePanedetvdirsoportan visualización Unicode- Algunas vistas incluso manejan desplazamiento horizontal y ajuste de línea
-
Vistas que también manejan entrada Unicode
TInputLine,cb489d42,TEditory los atajos de teclado deTMenuViewtambién manejan entrada de usuario Unicode- Las instancias de
TEditorestán en modo UTF-8 de forma predeterminada y pueden cambiar al modo de un solo byte conCtrl+P - Este cambio no modifica el contenido del documento; solo cambia la forma de visualización y la codificación de entrada
- No se soportan las teclas de acceso resaltadas de
TStatusLine,TButtony similares
-
Cadenas multilingües en menús y barra de estado
- Cadenas como
~Ñ~ello,階~毎~料入報最...,五劫~の~擦り切れ,העברית ~א~ינטרנט,~Alt-Ç~ Exitpueden usarse tal cual en los menús y la barra de estado - El resultado en pantalla puede verse en Unicode Hello
- Cadenas como
Modelo de funcionamiento por plataforma
-
Unix
- Usa soporte de terminal basado en Ncurses
- Soporta codificación de mouse X10 y SGR, modifyOtherKeys de xterm, fixterms de Paul Evans, el keyboard protocol de Kitty,
win32-input-modede WSL Conpty, far2l, modificadoresTIOCLINUXde la consola de Linux y el mouse GPM - Incluye manejadores de señales personalizados para restaurar el estado de la terminal antes de que el programa termine de forma anormal
- Si
stderres un tty, lo guarda en un búfer para evitar corromper la pantalla y lo imprime al salir o al suspenderse- Como el búfer tiene un límite de tamaño, las escrituras a
stderrpueden fallar si se llena - Para conservar todo, se recomienda redirigir con
2>
- Como el búfer tiene un límite de tamaño, las escrituras a
- Lee las variables de entorno
TERM,COLORTERM,ESCDELAY,TVISION_USE_STDIO- Si
COLORTERM=truecoloro24bit, asume color de 24 bits - El valor predeterminado de
ESCDELAYes10ms - Si
TVISION_USE_STDIOno está vacío, hace I/O constdinystdouten lugar de/dev/tty
- Si
-
Windows
- Solo es compatible con la Win32 Console API
- En emuladores de terminal que no la soportan, abre automáticamente una ventana de consola separada
- La disposición de la aplicación se basa en el tamaño de la ventana de consola, no en el búfer de consola, y restaura el búfer de consola al salir o suspenderse
- Si no es Borland C++, cambia la página de códigos de la consola a UTF-8 al iniciar y la restaura al salir
- También cambia el runtime de Microsoft C al modo UTF-8 para reducir la necesidad de que el desarrollador use directamente variantes de
wchar_t - En combinaciones de modo heredado y fuentes bitmap, la visualización Unicode puede romperse; si lo detecta, intenta cambiar la fuente a
ConsolasoLucida Console- Se puede ver un ejemplo en esta photo
-
Mejoras de comportamiento comunes
- Ofrece color de 24 bits, convivencia con redirección de
stdin/stdout/stderry compatibilidad con archivos de ayuda de 32 bits - Controla la tasa máxima de actualización con la variable de entorno
TVISION_MAX_FPS- El valor predeterminado es
60 0desactiva el límite-1hace que dibuje inmediatamente en cada llamada aTHardwareInfo::screenWrite
- El valor predeterminado es
- Soporta botón central del mouse, rueda del mouse, tamaños de pantalla de hasta 32767 filas/columnas y eventos de cambio de tamaño
- Las ventanas también se pueden redimensionar desde la esquina inferior izquierda, y se pueden arrastrar desde áreas vacías con el botón central
- Los menús se pueden cerrar haciendo clic otra vez en el elemento padre, y las barras de desplazamiento responden al desplazamiento por página durante el arrastre y a la rueda del mouse
TInputLineno desplaza el texto innecesariamente al mover el focoTFileVieweryTEditorsoportan saltos de línea LF, yTEditorconserva el salto de línea existente al guardar, mientras que los archivos nuevos usan CRLF por defectoTEditortambién incluye menú contextual con clic derecho, desplazamiento por arrastre con botón central, tecla para borrar por palabras, mejoras en la tecla Home y soporte para archivos de más de 64 KiBtvdemoincluye un applet visor de eventos y una opción para cambiar el patrón de fondo
- Ofrece color de 24 bits, convivencia con redirección de
Bucle de eventos y cambios en la API
- Usa buffering de escritura de pantalla y normalmente envía al terminal una vez por cada iteración del bucle de eventos activo
- Si se necesita actualización inmediata en un bucle ocupado, se puede llamar a
TScreen::flushScreen() TEventQueue::waitForEvents(int timeoutMs)espera eventos de entrada y también actualiza la pantalla conTScreen::flushScreen()mientras esperaTProgram::getEvent()llama a esto coneventTimeoutMs, cuyo valor predeterminado es20, para evitar un bucle ocupado al 100% de CPUTEventQueue::wakeUp()es un método thread-safe para despertar el bucle de eventos desde otro hiloTView::getEvent(TEvent &, int timeoutMs)permite establecer esperas con timeout a nivel de vista- Se agregaron
setTimerykillTimer, que generanevBroadcastycmTimerExpiredcuando expira un temporizador- Si
periodMses negativo, el temporizador es de una sola vez y se limpia automáticamente - Los eventos de temporizador se generan en
TProgram::idle()y solo se procesan cuando no hay eventos de teclado ni de mouse
- Si
TDrawBufferya no es un arreglo de longitud fija y evita accesos fuera de rangomove,grow,intersectyUniondeTRectdevuelvenTRect&, lo que permite encadenamientoTApplicationofrecedosShell(),cascade()ytile()de forma predeterminada, y manejacmDosShell,cmCascadeycmTilepor defecto- Se agregaron tipos como
TStringView,TSpan<T>,TDrawSurface,TSurfaceViewyTClipboard THardwareInfo,TScreenyTEventQueueya no se inicializan antes demain, sino al crear el primerTApplication- También se amplió la entrada
evMouseWheel,mwUp,mwDown,mwLeft,mwRightmbMiddleButton,meTripleClickevMouseUp.buttonsconserva la información del botón liberadohotKeyStr,getAltCharStr,getCtrlCharStrpermiten implementar atajos multibyteTKeypermite definir nuevas combinaciones de teclas comoShift+Alt+UpTInputLinesoporta limitMode deilMaxBytes,ilMaxWidtheilMaxChars
Integración con el portapapeles
-
Integración con el portapapeles del sistema
- Antes solo existía un portapapeles interno mediante el miembro estático
TEditor::clipboard, y soloTEditorpodía usarlo - La nueva clase
TClipboardaccede al portapapeles del sistema y, si no se puede acceder, usa el portapapeles interno como alternativa
- Antes solo existía un portapapeles interno mediante el miembro estático
-
Entornos compatibles
- Tiene soporte nativo en Windows, WSL y macOS
- En Unix, excepto macOS, se requiere una dependencia externa
- En ejecución remota, puede funcionar con X11 forwarding de
ssh -X, far2l y putty4far2l, y en terminales con soporte para OSC 52 - Algunas otras terminales solo admiten copiar
- Pegar con
Ctrl+Shift+VoCmd+Vdel emulador de terminal siempre sigue siendo posible por separado
-
API y manejo del pegado
- Se puede usar
TClipboardsi se defineUses_TClipboardantes de incluir<tvision/tv.h> setText(TStringView text)establece el contenido del portapapeles del sistema y, si no se puede acceder, usa el portapapeles internorequestText()hace una solicitud asíncrona del contenido del portapapeles del sistema y luego se recibe en la forma normal de eventosevKeyDown- El texto pegado se puede distinguir de la entrada normal de teclado con la bandera
kbPasteenkeyDown.controlKeyState - Para reducir la ineficiencia de tratar pegados largos como miles de pulsaciones, se agregó
TView::textEvent(...)- Reúne en un búfer de usuario el texto consecutivo de
evKeyDownpara leerlo - Cuando deja de ser texto, lo pasa al siguiente ciclo con
putEvent()
- Reúne en un búfer de usuario el texto consecutivo de
- Se puede usar
-
Integración con comandos estándar
TEditoryTInputLineresponden a los comandoscmCut,cmCopyycmPaste- La aplicación debe vincular
kbCtrlX,kbCtrlCykbCtrlVa cada comando, por ejemplo en la barra de estado - Según el foco y el estado de la selección, activa o desactiva automáticamente los comandos relacionados
Modelo de color extendido y compatibilidad
- La API de Turbo Vision admite colores extendidos más allá de los 16 colores tradicionales
- atributos de color BIOS de 4 bits
- RGB de 24 bits
- índice de paleta xterm-256color de 8 bits
- color predeterminado de la terminal
- Si la terminal no admite un formato de color específico, Turbo Vision lo muestra mediante cuantización
- En plataformas modernas se introducen TColorAttr en lugar de
uchary TAttrPair en lugar deushortTPalettetambién usa un arreglo deTColorAttrTView::mapColorpasó a servirtual, lo que permite asignar colores evitando el sistema jerárquico de paletas
TColorBIOS,TColorRGB,TColorXTermyTColorDesireddividen la jerarquía de representación de colorTColorAttrtiene máscaras de bitsforeground,backgroundystyle- Los estilos incluyen
slBold,slItalic,slUnderline,slBlink,slReverseyslStrike - Como
slReversees poco confiable, se recomienda usarreverseAttribute(TColorAttr attr)
- Hay tres formas de usar colores extendidos en
TView- sobrescribir
mapColory codificar en duro por índice - pasar
TColorAttrdirectamente aTDrawBufferdentro dedraw() - modificar la propia paleta de la aplicación
- sobrescribir
TScreen::screenModeexpone las capacidades de visualizaciónsmMonoes monocolorsmBW80es escala de grisessmCO80es de al menos 16 coloressmColor256es de al menos 256 coloressmColorHighsignifica más colores que eso, por ejemplo color de 24 bits
- La compatibilidad hacia atrás está diseñada para mantener una API común sin
#ifdef- En Borland C++,
TColorAttryTAttrPairse definen contypedefcomoucharyushort, respectivamente - En plataformas modernas pueden reemplazar los lugares donde antes iban
ucharyushort - El código legado sigue compilando tal cual, pero los atributos de color no BIOS pueden perderse en cuanto se convierten implícitamente a
ucharoushort
- En Borland C++,
- El código en métodos
drawque usabaushorttanto para pares de índices de paleta como para pares de atributos de color sigue funcionando, pero para conservar los colores extendidos basta con cambiar la declaración de la variable deushorta TAttrPair TColorDialogno fue rediseñado, así que no puede usarse como selector de colores extendidos en tiempo de ejecución
Compilación, distribución e integración
-
Linux y sistemas tipo Unix
- Se puede compilar la biblioteca estática
libtvision.acon CMake y GCC/Clang - También se generan
hello,tvdemo,tvedit,tvdir,mmenu,palettey el compilador de ayudatvhc - Los requisitos se resumen en un compilador con soporte para C++14,
libncurseswylibgpmcomo opcional - Para la integración del portapapeles en tiempo de ejecución se usan
xsel,xclipywl-clipboard - En algunos entornos puede hacer falta
-ltinfow; de lo contrario, puede ocurrir un segmentation fault al ejecutar- Issue relacionado: #11
- Se puede compilar la biblioteca estática
-
Windows y otras toolchains
- La compilación con MSVC usa directorios de compilación separados por arquitectura de destino, y los artefactos resultantes se generan como
tvision.liby apps de ejemplo - La opción
TV_USE_STATIC_RTLpermite enlazar estáticamente el runtime de Microsoft - No se puede enlazar mezclando
/MTy/MD, ni binarios de depuración y no depuración - Para usar
<tvision/tv.h>se requieren las banderas/permissive-y/Zc:__cplusplus; con el método de submódulo de CMake se habilitan automáticamente - Se indica que Windows XP también es posible con la versión y configuración adecuadas de MSVC
- MinGW compila con CMake de forma similar a Linux, y si el compilador lo soporta, puede ejecutarse en Windows XP o superior
- También es posible compilar bibliotecas para DOS o Windows con Borland C++, pero no tiene soporte para Unicode
- En entornos con Borland C++, se propone usar winevdm como alternativa
- La compilación con MSVC usa directorios de compilación separados por arquitectura de destino, y los artefactos resultantes se generan como
-
Formas de integración del proyecto y estado de distribución
- En CMake se ofrecen dos métodos:
find_package(tvision CONFIG)oadd_subdirectory(tvision) - Ambos métodos gestionan automáticamente las rutas de include y los enlaces necesarios como Ncurses y GPM
- Existe un port de
tvisionen vcpkg - Actualmente no hay stable release, y se recomienda reportar problemas encontrados al actualizar basándose en el commit más reciente
- En sistemas Unix hay que compilar manualmente las apps de demostración
- Los binarios de Windows se ofrecen en Actions
examples-dos32.zip: ejecutables de 32 bits compilados con Borland C++, sin soporte para Unicodeexamples-x86.zip: ejecutables de 32 bits compilados con MSVC, requiere Windows Vista o superiorexamples-x64.zip: ejecutables de 64 bits compilados con MSVC, requiere Windows Vista x64 o superior
- En CMake se ofrecen dos métodos:
Ejemplos, documentación y casos de uso
- Como punto de partida se recomienda Turbo Vision For C++ User's Guide
- Después de aprender lo básico, se puede tomar como referencia Turbo Vision 2.0 Programming Guide
- Se ofrecen como ejemplos
hello,tvdemo,tveditypalette - Se puede ver una colección de capturas de pantalla aquí
- Como aplicaciones que lo usan, se mencionan las siguientes
1 comentarios
Opiniones de Hacker News
Me da mucho gusto ver que este repositorio llegó a la portada, y justo ahora estoy haciendo mi propio wrapper para este repositorio
Estoy ejecutando Turbo Vision sobre .Net en macOS y se siente bastante mágico
Estoy agregando una API de más alto nivel, además de envolver o mejorar la API de palette, que ya está bastante anticuada, y también estoy añadiendo layout
Todavía estoy trabajando duro en un repositorio privado, y sigo puliéndolo poco a poco, como hoy ajustando la palette según la surface donde están colocados los controles y mañana afinando otra parte
También me quedan pendientes cosas como ordenar el layout y agregar controles básicos que hoy en día se echan de menos
Antes probé Terminal.Gui, pero como estaba en plena transición a v2, fue bastante difícil usarlo sin bugs, y Claude también mostró muy bien qué no se debe hacer cuando se crea una librería TUI sin tomar en cuenta un terminal real
Así que justo estaba pensando que estaría bien tener una versión moderna de Turbo Vision, y entonces encontré este repositorio; ver que incluso incluye soporte para Unicode me hizo sentir muy agradecido
https://www.remobjects.com/elements/oxygene/
https://www.remobjects.com/elements/
Yo también estoy haciendo un wrapper para .NET, y aunque probablemente voy menos avanzado, quiero imitar lo más posible la API de Windows Forms e incluso meterle un diseñador TUI drag-and-drop
Hay un ejemplo aquí: https://github.com/brianluft/terminalforms/tree/main/src/TerminalFormsDemo
La mayor parte de la integración complicada del lado de C++ la resolví aquí: https://github.com/brianluft/terminalforms/tree/main/src/tfcore
Exporté funciones C simples para poder llamarlas con P/Invoke, y del lado de C# me concentré sobre todo en estructurar las clases
Al principio insistí en que todo lo que se pudiera hacer en C++ también se pudiera hacer en C#, pero se volvió demasiado complejo; incluso llegué al punto de meter objetos C++ dentro de buffers de C# usando placement new, prácticamente como si estuviera heredando clases de C++ desde C#, y ahí el diseño se vino abajo
Al final cambié a un enfoque más directo, menos flexible pero mucho más simple, y decidí dejar la flexibilidad del lado de C#
Me da curiosidad cómo armaste tu sistema de P/Invoke
Gracias a eso creo que he evitado intentos inútiles como ponerme a hacer apps para GEOS o unirme al equipo unipersonal de Hurd
Sí probé Terminal.Gui, pero TV me atraía más, así que también había pensado en hacer un wrapper; de verdad me gustaría verlo cuando sea público
Mi carrera de programación empezó literalmente en la basura en los 90
Encontré un libro de Turbo Vision que alguien había tirado, y me enamoré de inmediato de esa TUI azulada que cualquiera podía hacer
La versión original venía en Turbo Pascal 6, y el port a C++ salió después
Así que esto vendría siendo un port moderno de un port
Borland hacía algo parecido con otros frameworks: OWL también empezó primero del lado de Turbo Pascal for Windows 1.5, y buena parte de las herramientas de C++ Builder en realidad estaban hechas en Delphi
Object Pascal de Turbo Pascal 5.5, y luego Turbo Vision en la 6, fueron mi entrada a la POO, y siento que tuve suerte de empezar por ahí
Incluso en un entorno como MS-DOS, OOP y Turbo Vision te enseñaban muy bien las ventajas de un framework
Cuando Borland sacó Turbo Pascal, Turbo C++ y TurboVision, sentí que de pronto se abría todo un universo de posibilidades
El rendimiento de los compiladores era excelente y los manuales parecían obras de arte; ojalá todavía conservara esos libros
Esto es puro tesoro cultural
A inicios de los 90 aprendí C/C++ casi por mi cuenta leyendo nada más la pila de libros de Borland que venían con Turbo C++, y hoy cuesta hasta imaginar una escena donde alguien aprenda así solo con libros de referencia
Los frameworks TUI nuevos siempre se sentían como si les faltara algo, y ahora voy a volver a usar esto para ver si era simple nostalgia o no
Pienso meterlo en mi próxima herramienta, y de verdad quiero aplaudir mucho a quienes lo hicieron
Fuera de GW-BASIC y MS-DOS, todo era Borland: Turbo BASIC, Turbo Pascal, Turbo C++ para MS-DOS y Windows 3.x, Turbo Vision y OWL
Empecé a usar VC++ como por la versión 5, pero MFC siempre me pareció demasiado insípido comparado con los productos de Borland
Incluso hoy, pocas cosas igualan de verdad la capacidad RAD de C++ Builder, y a .NET le tomó bastante tiempo ordenar una historia comparable para el código de bajo nivel y AOT al estilo Delphi
Yo sí les pondría unas cuantas copias de Turbo Pascal 7 para MS-DOS y Delphi moderno en las manos a desarrolladores de Go, C++ y Rust
Turbo Vision 2.0 sigue siendo bastante práctico incluso hoy, tanto que yo mismo lo usé para un prototipo hace un año
Intenté hacer un frontend de Turbo Vision para el depurador LLDB, para que funcionara como el Turbo Debugger de Borland, y en su mayor parte salió como quería
Me sorprendió sentir que retomaba exactamente donde todo se había quedado en 199x, y hasta pude compilar y ejecutar código de 1993 sin mayores problemas
También hay una versión mejorada del editor interno basada en Scintilla, con funciones como syntax highlighting, pero la parte que yo quería modificar no me salió bien, así que probablemente tendré que pedir ayuda al autor
Eso sí, falta documentación en el sentido moderno de conocimiento compartido, así que no es fácil preguntarle a Stack Overflow o a una IA; me tocó aprender viendo ejemplos y releyendo varias veces algunos libros de Turbo Vision, a la vieja usanza
El layout manual es bastante tedioso, así que estaría bien tener algo como el layout automático de Qt, y también extraño un poco los splitters, aunque no parecen difíciles de implementar
Otra cosa que me sorprendió es que TV en realidad es bastante pequeño y compacto. En los 90 se sentía gigantesco
En general, el trabajo de modernización está muy bien hecho, y a mí me gusta muchísimo
Turbo Vision originalmente sí tenía muchísima documentación de gran calidad
De hecho, creo que la que anda escasa es la parte moderna
https://archive.org/details/bitsavers_borlandTurrogrammingGuide1992_25707423
Ver tantas directivas de cmake me da ganas de volver al pasado
En Turbo C o Pascal solo presionabas F9 y corría de inmediato
Por otro lado, también siento que esto muestra la incompetencia de nuestra cadena de herramientas
A estas alturas debería bastar con señalar un compilador en línea para ejecutarlo al instante, o descargarlo, abrir una carpeta y correrlo; pero se volvió más un ritual que una herramienta
./configure && make && make install debería seguir siendo el estándar de oro
Este es solo uno de los ports/clones de Turbo Vision
Del lado de C++ también está este: https://github.com/kloczek/tvision
La versión incluida en FreePascal/Lazarus está escrita en Pascal, y también hay una en Rust que se ve medio vibe-coded: https://github.com/aovestdipaperino/turbo-vision-4-rust
Si corres esto en una terminal, se pierde un poco la sensación clave que daba el mouse en una pantalla de modo texto
En una pantalla real de modo texto no se veía como un puntero de mouse, sino más bien como un bloque amarillo movido con el mouse
Me pregunto si alguien lo ha probado en modo texto real de Linux de alta resolución con GPM
Se mostraba invirtiendo el color de la celda que quedaba debajo, y como la ventana principal que llenaba casi toda la pantalla solía ser azul oscuro, muchas veces el resultado sí parecía un bloque amarillo brillante
Recomiendo un episodio reciente del podcast de Wookash sobre Chuck Jazdzewski
Fue parte del equipo que creó Turbo Vision originalmente, y también hablan bastante de todo ese ecosistema
Yo todavía prefiero el verdadero Turbo Vision, o sea la versión en Pascal, sobre la de C++
La de C++ al final se siente más como una traslación de la de Pascal
Por ejemplo, en Pascal
useses una palabra clave, mientras que incluir módulos con#definese siente más como un hackBueno, quizá hoy ya no sea una diferencia tan importante
El IDE en modo texto también usa Free Vision
https://wiki.lazarus.freepascal.org/images/1/19/Userscreen.png
Pero la diferencia clave es que Free Vision y Turbo Vision usan el tipo
objectde Turbo Pascal 5.5, noclassde DelphiCon
classes fácil implementar cosas como serialización automática gracias a RTTI, peroobjectno tiene eso, así que para distinguir tipos distintos en tiempo de ejecución hay que hacer serialización manual, por ejemplo registrando el puntero VMT que está en un offset fijo dentro del puntero al objetoFree Pascal sí le añadió a
objectalgunas comodidades como private/protected/public y property, pero Free Vision no usa esas extensiones porque implementa la API original de Turbo Vision