Emulación de conio de Borland® para Dev-C++

¿Por qué emular conio?

Aunque se trate de una biblioteca no estándar, conio se ha convertido para muchos programadores educados o acostumbrados a compiladores de Borland® en una herramienta imprescindible para crear programas de consola.

Adicionalmente, cuando se crean aplicaciones de consola usando compiladores para Windows, como Dev-C++, a menudo necesitamos compilar programas escritos originalmente para compiladores Borland®. O sencillamente, queremos dotar a nuestros programas de consola de una apariencia más amigable y agradable.

Por supuesto, podemos recurrir a las funciones de consola del API de Windows, pero a menudo la conversión entre funciones de conio y sus equivalentes en el API no son tan sencillas, y en cualquier caso requiere cierto tiempo.

Este documento incluye una emulación de conio para el compilador Mingw, usado por el entorno de programación Dev-C++.

Es cierto que Dev-C++ incluye una emulación de conio, pero a nuestro juicio no es lo bastante fiel en cuanto a comportamiento a la original de Borland®. Sobre todo en funciones de ventanas, lecturas sin eco en pantalla, y en funciones como "kbhit", que o bien no se emulan, o se hace de forma incompleta.

Por supuesto, no todas las funciones y macros se han emulado, hay algunas con las que no es posible hacerlo, concretamente las que relacionadas con entrada y salida de puertos: "inp", "inport", "inportb", "inpw", "outp", "outport", "outportb" y "outpw"; ya que estas macros colisionan con el control del hardware de Windows.

Además de estas macros, la única función que no se emula es "cscanf", debido a las dificultades que entraña su implementación. En futuras versiones intentaremos incluirla. En su lugar se usa "scanf" directamente.

Trabajar con la emulación de conio

Al contrario que sucede con los compiladores de Borland®, en el que la biblioteca está incluída en el compilador, cuando se trabaja con otros compiladores es necesario incluir el código objeto en la fase de enlazado o bien el fichero fuente conio.c como parte del proyecto. También se puede crear una biblioteca estática (ver creación de bibliotecas estáticas), que es lo que haremos en este artículo.

Esto es algo más engorroso que cuando se usa desde un compilador de Borland®, pero no debemos olvidar que no se trata de una biblioteca estándar, cosa que a menudo se olvida o pasa desapercibida para los que están acostumbrados a usarla.

En la sección de bibliotecas de Borland® se incluye una referencia de las funciones, macros y estructuras definidas en conio.

Como recordatorio, he incluido el texto de ayuda de Borland® para cada una de las funciones emuladas dentro del propio fichero fuente.

Ficheros incluidos

Se suministran tres proyectos "dev", cada uno orientado a una forma diferente de usar la biblioteca.

El primer proyecto se llama "conio-lib", y sirve para crear un fichero de biblioteca estática, "conio.a".

Aconsejo compilar primero ese proyecto, el resultado será el fichero "libconio.a". Una vez hecho esto habría que copiar el fichero "libconio.a" al directorio "C:\Dev-Cpp\lib", suponiendo que tengas instalado Dev-C++ en el disco "C:". Después, habría que copiar los ficheros "conio.h" y, opcionalmente, "conio.c" en el directorio "C:\Dev-Cpp\include".

Ahora podemos compilar cualquiera de los otros proyectos.

El proyecto "conio-eje-a" es un ejemplo para el uso de la biblioteca estática, en él se añade el fichero "libconio.a" a la lista de bibliotecas a incluir en la fase de enlazado.

El proyecto "conio-eje-c" es un ejemplo para el uso del fichero "conio.c" como parte de un proyecto con varios ficheros fuente.

En el fichero zip que se puede descargar al final de esta página, se incluyen diez ficheros:

  • conio.h: el fichero de cabecera, con las declaraciones de funciones y tipos.
  • conio.c: el fichero fuente de la emulación.
  • libconio.a: el fichero de biblioteca.
  • text.c: un fichero de ejemplo del uso de "conio".
  • conio-lib.dev: proyecto para la generación del fichero de biblioteca.
  • conio-eje-a.dev: proyecto para ilustar un ejemplo usando el fichero de biblioteca.
  • conio-eje-c.dev: proyecto para ilustrar un ejemplo usando el fichero fuente como parte de un proyecto multifuente.
  • 6-Console_conio.template, ConsoleConio_c.txt y ConsoleConio_cpp.txt: deben copiarse al directorio "c:\dev-cpp\Templates", y sirven para crear un nuevo tipo de proyecto Dev-C++, que facilita la creación aplicaciones para consola usando "conio".

Programa de ejemplo

Se trata de un programa muy sencillo que hace uso de las funciones más frecuentes de conio: "clrscr", "gotoxy", "cputs", "putch", "getch", "getche", "kbhit", etc.

Errores e implementaciones incorrectas

Por supuesto, es posible que algunas de las funciones tengan errores, o que su comportamiento no sea exactamente el esperado. En cualquier caso, si detectas un error o algún comportamiento extraño, notifícanoslo a colabora@conclase.net e intentaremos corregirlo en futuras versiones.

Del mismo modo, si tu mismo decides modificar, mejorar o corregir alguna función, con gusto incluiremos tus modificaciones en futuras versiones, por supuesto, indicando tu autoría dentro del propio fichero fuente tanto como en este documento.

Historia de versiones

La versión 1.1, se debe a la colaboración de un compañero, que ha corregido los errores que cometí al usar características C++ en el fichero conio.c.

La versión 1.2 contiene una correción sobre la función _setcursortype, que no funcionaba correctamente con la opción _NOCURSOR. Gracias a Antonio Vallejo Zea por indicarnos el error.

La versión 1.3 está corregida para generar el fichero de biblioteca con el nombre "libconio.a", de modo que es más fácil de usar, ya que basta con especificar la opción de enlazado "-lconio".

También se incluye un nuevo tipo de proyecto para Dev-C++: "consola + conio", que facilita la creación de proyectos para consola que usen esta biblioteca.

Mejoras (características a añadir)

Aún quedan cosas por mejorar, y estamos trabajando en ellas. Por ejemplo, la respuesta a teclas especiales: las de función y las del cursor. Para ello hay que cambiar la implementación de las funciones de lectura: getch, getche... de modo que usen la función del API ReadConsoleInput.

Ficheros

Ir a página de descargas: descargas