9 puntos por GN⁺ 3 일 전 | 1 comentarios | Compartir por WhatsApp
  • 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 char para 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 char en lugar de wchar_t o TCHAR

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 setlocale en el RTL de Microsoft para que en Windows también funcione como se espera código como std::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
  • 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 existente charScan.charCode, se agregan text[4] y textLength para pasar directamente la secuencia de bytes de entrada UTF-8
    • En charScan.charCode se sigue guardando un carácter según CP437 por compatibilidad hacia atrás
    • Se recomienda usar getText() para obtener una string view
  • Los ejemplos de entrada muestran tal cual cómo conviven Unicode y el código heredado
    • Al ingresar ñ, queda charCode=164 ('ñ'), text={'\xC3','\xB1'}, textLength=2
    • Al ingresar , como no existe en CP437, queda keyCode=0x0, charCode=0, text={'\xE2','\x82','\xAC'}, textLength=3
    • En entradas de atajos, textLength=0 queda vacío
  • 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 JOINER U+200D siempre 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, putChar tratan char c como un carácter de página de códigos
    • moveStr, moveCStr reciben TStringView y procesan cadenas con reglas de Unicode
      • maxStrWidth se basa en la cantidad de columnas, no en la cantidad de bytes
      • strIndent tambié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
    • moveBuf se mantiene porque era la función que procesaba cadenas no terminadas en null antes de la introducción de TStringView
    • cstrlen(TStringView s) devuelve la longitud visible excluyendo ~, y strwidth(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 a moveStr, 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 intermedia
      • delta.x puede aplicarse directamente con base en columnas
      • Como solo se copian hasta size.x columnas, ya no hace tanta falta calcular manualmente la cantidad de bytes ni las condiciones de borde
  • Vistas estándar con soporte para visualización Unicode

  • Vistas que también manejan entrada Unicode

    • TInputLine, cb489d42, TEditor y los atajos de teclado de TMenuView también manejan entrada de usuario Unicode
    • Las instancias de TEditor están en modo UTF-8 de forma predeterminada y pueden cambiar al modo de un solo byte con Ctrl+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, TButton y similares
  • Cadenas multilingües en menús y barra de estado

    • Cadenas como ~Ñ~ello, 階~毎~料入報最..., 五劫~の~擦り切れ, העברית ~א~ינטרנט, ~Alt-Ç~ Exit pueden usarse tal cual en los menús y la barra de estado
    • El resultado en pantalla puede verse en Unicode Hello

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-mode de WSL Conpty, far2l, modificadores TIOCLINUX de 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 stderr es 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 stderr pueden fallar si se llena
      • Para conservar todo, se recomienda redirigir con 2>
    • Lee las variables de entorno TERM, COLORTERM, ESCDELAY, TVISION_USE_STDIO
      • Si COLORTERM=truecolor o 24bit, asume color de 24 bits
      • El valor predeterminado de ESCDELAY es 10 ms
      • Si TVISION_USE_STDIO no está vacío, hace I/O con stdin y stdout en lugar de /dev/tty
  • 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 Consolas o Lucida 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/stderr y 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
      • 0 desactiva el límite
      • -1 hace que dibuje inmediatamente en cada llamada a THardwareInfo::screenWrite
    • 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
    • TInputLine no desplaza el texto innecesariamente al mover el foco
    • TFileViewer y TEditor soportan saltos de línea LF, y TEditor conserva el salto de línea existente al guardar, mientras que los archivos nuevos usan CRLF por defecto
    • TEditor tambié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 KiB
    • tvdemo incluye un applet visor de eventos y una opción para cambiar el patrón de fondo

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 con TScreen::flushScreen() mientras espera
  • TProgram::getEvent() llama a esto con eventTimeoutMs, cuyo valor predeterminado es 20, para evitar un bucle ocupado al 100% de CPU
  • TEventQueue::wakeUp() es un método thread-safe para despertar el bucle de eventos desde otro hilo
  • TView::getEvent(TEvent &, int timeoutMs) permite establecer esperas con timeout a nivel de vista
  • Se agregaron setTimer y killTimer, que generan evBroadcast y cmTimerExpired cuando expira un temporizador
    • Si periodMs es 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
  • TDrawBuffer ya no es un arreglo de longitud fija y evita accesos fuera de rango
  • move, grow, intersect y Union de TRect devuelven TRect&, lo que permite encadenamiento
  • TApplication ofrece dosShell(), cascade() y tile() de forma predeterminada, y maneja cmDosShell, cmCascade y cmTile por defecto
  • Se agregaron tipos como TStringView, TSpan<T>, TDrawSurface, TSurfaceView y TClipboard
  • THardwareInfo, TScreen y TEventQueue ya no se inicializan antes de main, sino al crear el primer TApplication
  • También se amplió la entrada
    • evMouseWheel, mwUp, mwDown, mwLeft, mwRight
    • mbMiddleButton, meTripleClick
    • evMouseUp.buttons conserva la información del botón liberado
    • hotKeyStr, getAltCharStr, getCtrlCharStr permiten implementar atajos multibyte
    • TKey permite definir nuevas combinaciones de teclas como Shift+Alt+Up
    • TInputLine soporta limitMode de ilMaxBytes, ilMaxWidth e ilMaxChars

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 solo TEditor podía usarlo
    • La nueva clase TClipboard accede al portapapeles del sistema y, si no se puede acceder, usa el portapapeles interno como alternativa
  • 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+V o Cmd+V del emulador de terminal siempre sigue siendo posible por separado
  • API y manejo del pegado

    • Se puede usar TClipboard si se define Uses_TClipboard antes de incluir <tvision/tv.h>
    • setText(TStringView text) establece el contenido del portapapeles del sistema y, si no se puede acceder, usa el portapapeles interno
    • requestText() hace una solicitud asíncrona del contenido del portapapeles del sistema y luego se recibe en la forma normal de eventos evKeyDown
    • El texto pegado se puede distinguir de la entrada normal de teclado con la bandera kbPaste en keyDown.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 evKeyDown para leerlo
      • Cuando deja de ser texto, lo pasa al siguiente ciclo con putEvent()
  • Integración con comandos estándar

    • TEditor y TInputLine responden a los comandos cmCut, cmCopy y cmPaste
    • La aplicación debe vincular kbCtrlX, kbCtrlC y kbCtrlV a 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 uchar y TAttrPair en lugar de ushort
    • TPalette también usa un arreglo de TColorAttr
    • TView::mapColor pasó a ser virtual, lo que permite asignar colores evitando el sistema jerárquico de paletas
  • TColorBIOS, TColorRGB, TColorXTerm y TColorDesired dividen la jerarquía de representación de color
    • TColorAttr tiene máscaras de bits foreground, background y style
    • Los estilos incluyen slBold, slItalic, slUnderline, slBlink, slReverse y slStrike
    • Como slReverse es poco confiable, se recomienda usar reverseAttribute(TColorAttr attr)
  • Hay tres formas de usar colores extendidos en TView
    • sobrescribir mapColor y codificar en duro por índice
    • pasar TColorAttr directamente a TDrawBuffer dentro de draw()
    • modificar la propia paleta de la aplicación
  • TScreen::screenMode expone las capacidades de visualización
    • smMono es monocolor
    • smBW80 es escala de grises
    • smCO80 es de al menos 16 colores
    • smColor256 es de al menos 256 colores
    • smColorHigh significa 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++, TColorAttr y TAttrPair se definen con typedef como uchar y ushort, respectivamente
    • En plataformas modernas pueden reemplazar los lugares donde antes iban uchar y ushort
    • El código legado sigue compilando tal cual, pero los atributos de color no BIOS pueden perderse en cuanto se convierten implícitamente a uchar o ushort
  • El código en métodos draw que usaba ushort tanto 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 de ushort a TAttrPair
  • TColorDialog no 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.a con CMake y GCC/Clang
    • También se generan hello, tvdemo, tvedit, tvdir, mmenu, palette y el compilador de ayuda tvhc
    • Los requisitos se resumen en un compilador con soporte para C++14, libncursesw y libgpm como opcional
    • Para la integración del portapapeles en tiempo de ejecución se usan xsel, xclip y wl-clipboard
    • En algunos entornos puede hacer falta -ltinfow; de lo contrario, puede ocurrir un segmentation fault al ejecutar
      • Issue relacionado: #11
  • 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.lib y apps de ejemplo
    • La opción TV_USE_STATIC_RTL permite enlazar estáticamente el runtime de Microsoft
    • No se puede enlazar mezclando /MT y /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
  • Formas de integración del proyecto y estado de distribución

    • En CMake se ofrecen dos métodos: find_package(tvision CONFIG) o add_subdirectory(tvision)
    • Ambos métodos gestionan automáticamente las rutas de include y los enlaces necesarios como Ncurses y GPM
    • Existe un port de tvision en 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 Unicode
      • examples-x86.zip: ejecutables de 32 bits compilados con MSVC, requiere Windows Vista o superior
      • examples-x64.zip: ejecutables de 64 bits compilados con MSVC, requiere Windows Vista x64 o superior

Ejemplos, documentación y casos de uso

1 comentarios

 
GN⁺ 3 일 전
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

    • Oxygene es parte de la familia de productos Elements de RemObjects, así que además de Oxygene, que es de la línea Pascal, puedes mezclar varios lenguajes populares y llevarlos a Windows, macOS, Linux, Android, etc.
      https://www.remobjects.com/elements/oxygene/
      https://www.remobjects.com/elements/
    • Yo también he trabajado con este port de tvision, y cada vez que toco un framework TUI nuevo termino sintiendo que Turbo Vision es mejor
      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
    • Jugar con esta librería TV rasca muy bien la nostalgia y da gusto
      Gracias a eso creo que he evitado intentos inútiles como ponerme a hacer apps para GEOS o unirme al equipo unipersonal de Hurd
    • Yo también quería intentar lo mismo
      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

    • Lo curioso es que Free Vision fue, en algún momento, el resultado de que alguien tomara la versión en C++ liberada al dominio público, la tradujera manualmente y la llevara de vuelta a Object/Free Pascal
    • OWL de verdad estaba adelantado a su tiempo
  • 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

    • Esos manuales eran realmente increíbles
      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
    • Durante mucho tiempo Turbo Vision fue mi estándar de oro
      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
    • Hubo una época en la que yo era Borland al 100%
      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

  • 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

    • En el Unix moderno, compilar software ya había sido un problema resuelto en algún momento
      ./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

    • En esencia no era amarillo como tal
      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 uses es una palabra clave, mientras que incluir módulos con #define se siente más como un hack
    Bueno, quizá hoy ya no sea una diferencia tan importante

    • Free Vision, incluido en Free Pascal, básicamente cumple ese papel
      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 object de Turbo Pascal 5.5, no class de Delphi
      Con class es fácil implementar cosas como serialización automática gracias a RTTI, pero object no 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 objeto
      Free Pascal sí le añadió a object algunas comodidades como private/protected/public y property, pero Free Vision no usa esas extensiones porque implementa la API original de Turbo Vision