home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 1995 November
/
PCWK1195.iso
/
inne
/
podstawy
/
dos
/
format
/
2m30src.exe
/
2M-INDOC.C
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-06
|
29KB
|
862 lines
/*───────────────────────────────────────────────────────────────────\
│ │
│ Lector del fichero de documentación para 2M-INFO. │
│ │
│ El programa utiliza sólo español o inglés para los │
│ mensajes propios, pero el fichero de documentación │
│ soportaría varios idiomas más. │
│ │
│ (C) 1994-1995 Ciriaco García de Celis │
│ │
\───────────────────────────────────────────────────────────────────*/
#include <conio.h>
#include <stdio.h>
#include <alloc.h>
#include <string.h>
#include <io.h>
#include <dos.h>
#include "2m-info.h"
#define MAX_IDIOMAS 10 /* número máximo de idiomas soportado */
#define MAX_MENUS 21 /* número máximo de submenús + principal */
#define MAX_TITULO 60 /* longitud máxima de los títulos de menús */
#define MAX_PAISES 24 /* nº máximo códigos telefónicos soportados */
#define MAX_NPAIS 15 /* tamaño máximo del nombre del país */
#define OP_SALIR -1
#define OP_ALTX -2
#define OP_765DEBUG -3
#define OP_FDTR -4
#define OP_IDIOMA -5
#define CV 15 /* color para miniventanas */
#define CFV 1 /* color de fondo para miniventanas */
#define CM 15 /* color para los menús */
#define CLM 11 /* color para la línea de los menús */
#define CF9 14 /* color para F9 */
#define CFM 1 /* color de fondo para los menús */
#define CFMS 3 /* color para la sombra de los menús */
#define CC 15 /* color durante carga de datos */
#define CFC 4 /* color de fondo durante carga de datos */
#define CI 15 /* color de impresión para el texto */
#define CFI 1 /* color de fondo de impresión para el texto */
#define CG 14 /* color de impresión de gráficos y cuadros */
#define CE 14 /* color para las líneas de estado */
#define CFE 2 /* color de fondo para las líneas de estado */
typedef struct {
int numitems; /* número de líneas del menú */
char titulo[MAX_MENUS][MAX_TITULO]; /* mensaje a imprimir */
char *texto[MAX_MENUS]; /* punteros a textos en memoria */
long offseek[MAX_MENUS]; /* offset a textos en fichero */
int numlineas[MAX_MENUS]; /* nº líneas en fichero */
} Menu;
typedef struct {
char nombre[MAX_NPAIS+1]; /* nombre del idioma */
short pais[MAX_PAISES]; /* códigos telefónicos de países que lo hablan */
} Idioma;
extern int set80x30 (void);
extern int Tecla (void);
extern int EsOS2 (void);
extern int EsWinEnh (void);
extern int semilla;
extern int sp;
extern void debug765 (void);
extern void ResetVideo (void);
extern void fdtr (int, int);
extern void CursorOff (void);
extern void BrilloOn (void);
extern void ventana (int, int, int, int, int, int, int);
extern void v3dg (int, int, int, int, int, int, int, int, int);
extern void v3df (int, int, int, int, int, int, int, int);
extern void boton (int, int, int, int, int, int, char *);
extern void Estrellas (void);
extern unsigned rnd (unsigned);
FILE *AbrirFDA (char *, char *);
int MemoriaInsuficiente (void),
CrearMenus (FILE *, char *, char *, Menu *[][MAX_MENUS], Idioma *, int *),
ConstruirIDX (FILE *, char *, char *, Menu *[][MAX_MENUS], Idioma *, int *),
parseint (char **),
EligeIdioma (Idioma *, int),
PintarMenu (int, Menu *, char *, int *),
justificar (unsigned char **, unsigned char *);
void LiberarMemoria (Menu *[][MAX_MENUS], int, int),
ImprimirTexto (Menu *[][MAX_MENUS], int, int, int, int, FILE *),
Estrellas (void),
Visualizar (char *, char *),
clreof (int, int, unsigned *, int),
display (unsigned char **, unsigned *, unsigned, unsigned);
char *parsestr (char *);
char far *LineasPant = MK_FP (0x40, 0x84);
int VerFicheroDoc (char *dir, char *fich, char *fichindice, Parametros *cmd)
{
FILE *fichdoc; /* handle para el fichero de documentación */
int nm, /* número de menus en cada idioma */
ni, /* número de idiomas */
idioma, /* idioma en uso */
opcion,
subopc,
accion, subacc,
modo30;
long sm;
char *idstr;
Menu *menu[MAX_IDIOMAS][MAX_MENUS];
Idioma idiom[MAX_IDIOMAS];
if (MemoriaInsuficiente()) return (0);
if ((fichdoc=AbrirFDA(dir, fich))==NULL) return (1);
for (ni=0; ni<MAX_IDIOMAS; ni++)
for (nm=0; nm < MAX_MENUS; nm++) menu[ni][nm]=NULL; /* menús a 0 */
if (!cmd->HazIdx)
nm = CrearMenus (fichdoc, dir, fichindice, menu, idiom, &ni);
if (cmd->HazIdx || !nm)
nm = ConstruirIDX (fichdoc, dir, fichindice, menu, idiom, &ni);
idioma = EligeIdioma (idiom, ni); if (cmd->ModoI) idioma = (ni-1)-idioma;
modo30=1;
if (((EsOS2() || (EsWinEnh() && (EsWinEnh() < 0x400))) &&
(!cmd->Modo30)) || (cmd->Modo25)) modo30=0;
if (modo30)
set80x30();
else
*LineasPant=24; /* asegurar variable BIOS inicializada */
Estrellas();
opcion = subopc = 0;
do {
sp = (strstr(idiom[idioma].nombre, "ESPAÑOL")!=NULL);
idstr = idiom[idioma!=ni-1? idioma+1: 0].nombre;
accion=PintarMenu (0, menu[idioma][0], idstr, &opcion);
switch (accion) {
case OP_SALIR:
case OP_ALTX: break;
case OP_765DEBUG: ResetVideo(); debug765();
if (modo30) set80x30(); Estrellas();
break;
case OP_FDTR: ResetVideo(); fdtr (0, 0);
if (modo30) set80x30(); Estrellas();
break;
case OP_IDIOMA: idioma++; if (idioma>=ni) idioma=0; break;
default:
sm = - (menu[idioma][0]->offseek[opcion]);
if (sm > 0) do {
sp = (strstr(idiom[idioma].nombre, "ESPAÑOL")!=NULL);
idstr = idiom[idioma!=ni-1? idioma+1: 0].nombre;
subacc = PintarMenu (1, menu[idioma][sm], idstr, &subopc);
switch (subacc) {
case OP_SALIR:
case OP_ALTX: break;
case OP_765DEBUG: ResetVideo(); debug765();
if (modo30) set80x30(); Estrellas();
break;
case OP_FDTR: ResetVideo(); fdtr (0, 0);
if (modo30) set80x30(); Estrellas();
break;
case OP_IDIOMA: idioma++; if (idioma>=ni) idioma=0; break;
default: ImprimirTexto (menu, idioma, ni, sm, subopc, fichdoc);
Estrellas();
break;
}
} while ((subacc != OP_SALIR) && (subacc != OP_ALTX));
else
ImprimirTexto (menu, idioma, ni, 0, opcion, fichdoc); Estrellas();
break;
}
} while ((accion != OP_SALIR) && (accion != OP_ALTX));
fclose (fichdoc);
if (nm) LiberarMemoria (menu, ni, nm);
return (accion == OP_ALTX);
}
FILE *AbrirFDA (char *directorio, char *fichero)
{
char nfich[64];
FILE *f;
strcpy (nfich, directorio); strcat (nfich, fichero);
if ((f=fopen(nfich, "rt"))==NULL) {
ventana (ABRIR, 21, 10, 59, 16, CV, CFV);
if (sp) {
gotoxy (3,2); cputs ("Fichero "); cputs(fichero);
cputs(" no encontrado");
gotoxy (12,4); cputs("Pulse una tecla");
}
else {
gotoxy (6,2); cputs ("File "); cputs(fichero);
cputs(" not found");
gotoxy (13,4); cputs("Press any key");
}
CursorOff(); Tecla();
ventana (CERRAR, 21, 10, 59, 16, 0, 0);
}
return (f);
}
int MemoriaInsuficiente() /* Asegurar un mínimo de memoria */
{
char *bloque;
int insuficiente=1;
if ((bloque=farmalloc(5120L))==NULL) {
ventana (ABRIR, 21, 10, 59, 16, CV, CFV);
if (sp) {
gotoxy (10,2); cputs ("Memoria insuficiente");
gotoxy (12,4); cputs("Pulse una tecla");
}
else {
gotoxy (10,2); cputs ("Insufficient memory");
gotoxy (13,4); cputs("Press any key");
}
CursorOff(); Tecla();
ventana (CERRAR, 21, 10, 59, 16, 0, 0);
}
else {
insuficiente=0;
farfree (bloque);
}
return (insuficiente);
}
int CrearMenus (FILE *fdoc, char *dir, char *fichidx,
Menu *menus[][MAX_MENUS], Idioma *idiom, int *NumIdiomas)
{
char nfich[64];
int NumMenus, i, j, iniv;
long tamanio;
struct ftime ff, fechahora;
FILE *fidx;
iniv = (*LineasPant - 4) >> 1;
NumMenus=0;
ventana (ABRIR, 24, iniv, 56, iniv+4, CV, CFV);
gotoxy (12,2); if (sp) cputs("Espere..."); else cputs(" Wait...");
CursorOff();
strcpy (nfich, dir); strcat (nfich, fichidx);
if ((fidx=fopen(nfich, "r+b"))!=NULL) {
fseek (fidx, 96L, SEEK_SET);
fread (&tamanio, sizeof(long), 1, fidx);
fread (&fechahora, sizeof (fechahora), 1, fidx);
getftime (fileno(fdoc), &ff);
if ((memcmp(&ff, &fechahora, sizeof (ff))==0) &&
(tamanio==filelength(fileno(fdoc)))) {
fread (NumIdiomas, sizeof(int), 1, fidx);
fread (&NumMenus, sizeof(int), 1, fidx);
fseek (fidx, 128L, SEEK_SET);
for (i=0; i < *NumIdiomas; i++) {
for (j=0; j < NumMenus; j++) {
menus [i][j] = farmalloc (sizeof(Menu));
fread (menus[i][j], sizeof(Menu), 1, fidx);
}
fread (&idiom[i], sizeof(Idioma), 1, fidx);
}
}
fclose (fidx);
}
ventana (CERRAR, 24, iniv, 56, iniv+4, 0, 0);
return (NumMenus);
}
int ConstruirIDX (FILE *doc, char *directorio, char *fichidx,
Menu *menus[][MAX_MENUS], Idioma *idiom, int *NumIdiomas)
{
char bf[96], *p;
int i, j, idioma, lineas=0, nm, itemm, items;
long tamanio;
struct ftime fechahora;
FILE *fidx;
ventana (ABRIR, 12, 10, 67, 17, CV, CFV);
if (sp) {
gotoxy (4,2); cputs ("El fichero de índice rápido ("); cputs (fichidx); cputs(") no se");
gotoxy (4,3); cputs ("corresponde con el de documentación o no existe.");
gotoxy (4,4); cputs ("Se está creando nuevamente. Esta tarea podría");
gotoxy (4,5); cputs ("llevar varios segundos.");
}
else {
gotoxy (4,2); cputs ("Fast access index file ("); cputs (fichidx); cputs(") is not");
gotoxy (4,3); cputs ("relationed with documentation file or not exist.");
gotoxy (4,4); cputs ("It is being created again. This work may takes");
gotoxy (4,5); cputs ("some seconds.");
}
CursorOff();
for (i=0; i<MAX_IDIOMAS; i++) {
for (j=0; j<MAX_MENUS; j++) menus[i][j]=NULL;
memset (&idiom[i], 0, sizeof (Idioma));
}
idioma=0;
while (!feof (doc)) {
if (fgets (bf, 80, doc)==NULL) break;
lineas++;
if ((p=strstr(bf, "{INICIOIDIOMA"))!=NULL) {
nm = 1;
itemm = items = -1;
p+=13; i=0; while (*p == ' ') p++;
while ((*p != ':') && (i<MAX_NPAIS))
idiom [idioma].nombre[i] = *p++, i++;
idiom [idioma].nombre[i] = 0; p++; i=0;
do {
j = parseint (&p);
if (j==-2) {
fgets (bf, 80, doc); p = bf;
j = parseint (&p);
}
else
idiom [idioma].pais[i++] = j;
} while ((j>0) && (i<MAX_PAISES));
lineas=0;
}
else if ((p=strstr(bf, "{FINIDIOMA")) != NULL) {
if (items != -1) { /* cerrar submenú */
menus[idioma][nm]->numlineas[items] = lineas-1;
menus[idioma][nm]->numitems = items+1;
nm++;
items = -1;
}
if (itemm>0) menus[idioma][0]->numlineas[itemm] = lineas;
menus[idioma][0]->numitems = itemm+1;
idioma++;
}
else if ((p=strstr(bf, "{LINEAMENU")) != NULL) {
if (items != -1) { /* cerrar submenú */
menus[idioma][nm]->numlineas[items] = lineas-1;
menus[idioma][nm]->numitems = items+1;
nm++;
items = -1;
}
if (itemm>=0) menus[idioma][0]->numlineas[itemm] = lineas-1;
else {
menus[idioma][0] = farmalloc (sizeof(Menu));
memset (menus[idioma][0], 0, sizeof(Menu));
}
itemm++; lineas=0;
strncpy (menus[idioma][0]->titulo[itemm], parsestr (p+10), MAX_TITULO);
menus[idioma][0]->offseek[itemm] = ftell(doc);
menus[idioma][0]->texto[itemm] = NULL;
}
else if ((p=strstr(bf, "{LINEASUBMENU")) != NULL) {
if (items>=0) menus[idioma][nm]->numlineas[items] = lineas-1;
else {
menus[idioma][nm] = farmalloc (sizeof(Menu));
memset (menus[idioma][nm], 0, sizeof(Menu));
menus[idioma][0]->offseek[itemm] = -nm; /* menú -> submenú */
}
items++; lineas=0;
strncpy (menus[idioma][nm]->titulo[items], parsestr (p+13), MAX_TITULO);
menus[idioma][nm]->offseek[items] = ftell(doc);
menus[idioma][nm]->texto[items] = NULL;
}
}
*NumIdiomas = idioma;
strcpy (bf, directorio); strcat (bf, fichidx);
remove (bf);
if ((fidx=fopen(bf, "w+b"))!=NULL) {
for (i=0; i<96; i++) bf[i]=0;
strcpy (bf, "\r\nFichero índice para acceso rápido.\r\nFast access index file.\r\n\032");
fwrite (bf, 96, 1, fidx);
tamanio=filelength(fileno(doc));
getftime (fileno(doc), &fechahora);
fwrite (&tamanio, sizeof(long), 1, fidx);
fwrite (&fechahora, sizeof(fechahora), 1, fidx);
fwrite (NumIdiomas, sizeof(int), 1, fidx);
fwrite (&nm, sizeof(int), 1, fidx);
for (i=0; i<32; i++) bf[i]=0; fwrite (bf, 32, 1, fidx);
fseek (fidx, 128L, SEEK_SET);
for (i=0; i < *NumIdiomas; i++) {
for (j=0; j < nm; j++)
fwrite (menus[i][j], sizeof(Menu), 1, fidx);
fwrite (&idiom[i], sizeof(Idioma), 1, fidx);
}
fclose (fidx);
}
ventana (CERRAR, 12, 10, 67, 17, 0, 0);
return (nm);
}
void LiberarMemoria (Menu *menus[][MAX_MENUS], int ni, int nm)
{
int i, j, k;
for (i=0; i<ni; i++)
for (j=0; j<nm; j++) {
for (k=0; k < menus[i][j]->numitems; k++)
if (menus[i][j]->texto[k] != NULL) farfree (menus[i][j]->texto[k]);
farfree (menus[i][j]);
}
}
int parseint (char **p)
{
int num=0;
if (**p == '}') return (-1);
if (**p == '\n') return (-2);
do {
while (**p == ' ') (*p)++;
if ((**p >= '0') && (**p <= '9')) {
num *= 10;
num += **p -'0';
}
if (**p == '*') num=-3;
(*p)++;
} while ((**p != ',') && (**p != '}'));
if (**p != '}') (*p)++;
return (num);
}
char *parsestr (char *p)
{
char *pp;
while ((*p == ' ') || (*p == '[')) p++;
pp=p; while ((*p != ']') && (*p != '}')) p++; *p=0;
return (pp);
}
int EligeIdioma (Idioma *idiom, int ni)
{
union REGS r; struct SREGS s;
char info[64];
int idioma, i, j;
idioma=0;
for (i=0; i<ni; i++) if (idiom[i].pais[0] == -3) idioma=i; /* por defecto */
if (_osmajor>=3) {
r.x.ax=0x3800; s.ds=FP_SEG(info); r.x.dx=FP_OFF(info);
intdosx (&r, &r, &s);
for (i=0; i<ni; i++)
for (j=0; idiom[i].pais[j] > 0; j++)
if (idiom[i].pais[j] == r.x.bx) idioma = i;
}
return (idioma);
}
int PintarMenu (int nivel, Menu *menu, char *idinombre, int *opc)
{
int lx, ly, cx, cy, i, tecla, cod=0, salir=0;
static char *buffer[2];
ly = menu->numitems + 3;
lx = 0;
for (i=0; i < menu->numitems; i++)
if (strlen (menu->titulo[i]) > lx) lx = strlen(menu->titulo[i]);
lx += 5;
cx = (80-lx) >> 1; cy = ((*LineasPant + 1) - ly) >> 1;
if (cy+ly >= 25) cy = 24-ly; /* no usar 5 últimas líneas en 80x30 */
if ((buffer[nivel]=farmalloc (2L*(lx+3)*(ly+2)))!=NULL)
gettext (cx, cy, cx+lx+2, cy+ly+1, buffer[nivel]);
window (cx+2, cy+1, cx+lx+2, cy+ly+1); textbackground (CFMS); clrscr();
window (cx, cy, cx+lx, cy+ly); textbackground (CFM); clrscr();
textcolor (CLM); putch ('┌');
for (i=2; i<=ly; i++) {
gotoxy (1, i); putch('│');
gotoxy (lx+1, i); putch('│');
}
for (i=2; i<=lx; i++) {
gotoxy (i, 1); putch('─');
gotoxy (i, ly+1); putch('─');
}
gotoxy (lx+1, 1); putch('┐'); gotoxy (1, ly+1); putch('└');
cod=_wscroll; _wscroll=0; gotoxy (lx+1, ly+1); putch('┘'); _wscroll=cod;
window (cx+1, cy+1, cx+lx-1, cy+ly-1);
do {
textcolor (CM); textbackground (CFM);
for (i=0; i < menu->numitems; i++) {
gotoxy (2, i+2); putch(' '); cputs (menu->titulo[i]); putch(' '); }
gotoxy (lx - strlen (idinombre) - 4, i+2);
textcolor (CF9); cputs ("F9 "); cputs(idinombre);
if (peekb(0x40, 0x49) != 7) {
textcolor (CFM); textbackground (CM); }
else {
textcolor (0); textbackground (7); }
gotoxy (2, *opc+2); putch(' '); cputs (menu->titulo[*opc]); putch(' ');
CursorOff();
tecla = Tecla();
switch (tecla) {
case 0x4300: /* F9 */ cod=OP_IDIOMA; salir=1; break;
case ' ':
case '2':
case 0x5000: /* cur ab */ (*opc)++; break;
case '8':
case 0x4800: /* cur arr */ (*opc)--; break;
case '7':
case 0x4700: /* Home */
case '9':
case 0x4900: /* PgUp */ *opc=0; break;
case 27: /* ESC */ if (nivel==1) { salir=1; break; }
if (*opc == menu->numitems-1)
salir=1;
case '1':
case 0x4F00: /* End */
case '3':
case 0x5100: /* PgDn */ *opc = menu->numitems-1; break;
}
if (*opc<0) *opc = menu->numitems-1;
if (*opc >= menu->numitems) *opc=0;
} while ((tecla != 13) && (tecla != 0x2D00) && (!salir));
if (cod != OP_IDIOMA) {
cod = *opc;
if (tecla == 0x2D00) cod = OP_ALTX;
else if ((*opc == menu->numitems-1) || (salir)) cod = OP_SALIR;
else if (strstr (menu->titulo[*opc], "765DEBUG")) cod = OP_765DEBUG;
else if (strstr (menu->titulo[*opc], "FDTR")) cod = OP_FDTR;
}
if (buffer[nivel] != NULL) {
puttext (cx, cy, cx+lx+2, cy+ly+1, buffer[nivel]);
farfree (buffer[nivel]); buffer[nivel]=NULL;
}
window (1,1,80,25);
return (cod);
}
void ImprimirTexto (menu, idioma, ni, submenu, opcion, fichdoc)
Menu *menu[][MAX_MENUS];
int idioma, ni, submenu, opcion;
FILE *fichdoc;
{
long tbuffer; /* longitud total del texto */
int idi, /* idioma en curso para liberar memoria */
id, /* contador de idiomas para liberar memoria */
sb, /* submenú en curso para liberar memoria */
sl, /* opción del submenú en curso para liberar memoria */
ex, /* variable de control de huida del bucle */
cargar, /* indica si hay que traer los datos de disco */
li, iniv;
char *p, *k;
tbuffer = 81L * menu[idioma][submenu]->numlineas[opcion] + 1;
idi = idioma - 1; if (idi<0) idi = ni-1;
cargar = menu[idioma][submenu]->texto[opcion] == NULL;
iniv = (*LineasPant - 4) >> 1;
if (cargar) {
ventana (ABRIR, 34, iniv, 46, iniv+4, CC, CFC);
gotoxy (2,2); if (sp) cputs ("Espere..."); else cputs(" Wait...");
CursorOff();
}
ex=1; /* pedir memoria; si hace falta, liberando alguna opción */
while ((menu[idioma][submenu]->texto[opcion] == NULL) && ex)
if ((menu[idioma][submenu]->texto[opcion]=farmalloc (tbuffer))==NULL)
for (ex = id = 0; (id < ni) && !ex; id++, idi = (idi+ni-1) % ni)
for (sb=0; (menu[idi][sb]!=NULL) && !ex; sb++)
for (sl=0; (sl < menu[idi][sb]->numitems) && !ex; sl++)
if (menu[idi][sb]->texto[sl] != NULL) {
farfree (menu[idi][sb]->texto[sl]);
menu[idi][sb]->texto[sl] = NULL;
ex++;
}
if (menu[idioma][submenu]->texto[opcion] == NULL) {
ventana (CERRAR, 34, iniv, 46, iniv+4, 0, 0);
ventana (ABRIR, 28, iniv, 51, iniv+4, CV, CFV);
gotoxy (2,2);
cputs(sp? "Memoria Insuficiente": "Insufficient memory");
CursorOff(); delay(1500); while (kbhit()) (void) getch();
ventana (CERRAR, 28, iniv, 51, iniv+4, 0, 0);
}
else {
if (cargar) {
fseek (fichdoc, menu[idioma][submenu]->offseek[opcion], SEEK_SET);
p = menu[idioma][submenu]->texto[opcion];
for (li=0; li < menu[idioma][submenu]->numlineas[opcion]; li++) {
fgets (p, 80, fichdoc);
if (strlen(p)>1) {
k = p; p += strlen(p); *(p-1) = 10;
while ((*(p-2)==' ') && (p-k > 1)) { p--; *(p-1)=10; }
}
else
*p++=' ', *p++=10;
}
p--; *(p-1) = 0;
farrealloc (menu[idioma][submenu]->texto[opcion],
p - menu[idioma][submenu]->texto[opcion]+1);
}
if (cargar) ventana (CERRAR, 34, iniv, 46, iniv+4, 0, 0);
Visualizar (menu[idioma][submenu]->titulo[opcion],
menu[idioma][submenu]->texto[opcion]);
}
}
void Visualizar (char *titulo, char *cadena)
{
unsigned char *vram, *p, *ap, status[80];
unsigned *bram;
unsigned lineas, linea, ln, cars, atrp, atrg, atrs, off, tecla, i;
CursorOff();
lineas = *LineasPant + 1;
vram = MK_FP ((peekb(0x40, 0x49) & 0x7F) == 7 ? 0xB000:0xB800, 0);
if (peekb(0x40, 0x49) != 7) {
atrp = ((CFI << 4) | CI) << 8; atrs = ((CFE << 4) | CE) << 8;
atrg = ((CFI << 4) | CG) << 8;
}
else {
atrp = 15 << 8; atrs = 7 << 12; /* mono */
atrg = 7 << 8;
}
bram = (unsigned *) vram;
cars = 80;
while (cars--) *bram++=atrs | ' ';
bram = (unsigned *) vram + (lineas-1)*80;
cars = 80;
while (cars--) *bram++=atrs | ' ';
bram = (unsigned *) vram;
off = (80 - strlen(titulo)) >> 1;
p = titulo; while (*p) bram [off++] = atrs | *p++; /* título */
strcpy (status, sp?
" Teclas: \030 \031 RePág AvPág Inicio Fin Intro-Salir":
" Keys: \030 \031 PgUp PgDn Home End Enter-Exits");
off = (lineas-1)*80;
p = status; while (*p) bram [off++] = atrs | *p++; /* status */
p = cadena;
for (linea = 1; (linea <= lineas-2) && *p; linea++)
display (&p, &bram[linea*80], atrp, atrg);
clreof (linea, lineas, bram, atrp);
do {
tecla = Tecla();
switch (tecla) {
case ' ':
case '2':
case 0x5000: /* cur ab */
ap = p; ln = linea;
while (linea < lineas-1) {
while ((*p != 10) && *p) p++;
if (*p) p++; linea++;
}
if (*p) {
memmove (&bram[80], &bram[160], (lineas-3)*160);
display (&p, &bram[(linea-1)*80], atrp, atrg);
}
else {
p=ap; linea=ln;
}
break;
case '8':
case 0x4800: /* cur arr */
linea++;
while ((linea>0) && (p-cadena)) {
while ((*p != 10) && (p!=cadena)) p--; linea--;
if (p-cadena) p--; }
if (linea<2) {
p++; if (!linea) p++;
linea=2;
memmove (&bram[160], &bram[80], (lineas-3)*160);
display (&p, &bram[(linea-1)*80], atrp, atrg);
}
else linea=1;
break;
case '9':
case 0x4900: /* PgUp */
for (i=0; (i < lineas+linea-2) && (p-cadena); i++) {
while ((*p != 10) && (p-cadena)) p--;
p--;
}
if (p-cadena) p+=2;
for (linea = 1; (linea <= lineas-2) && *p; linea++)
display (&p, &bram[linea*80], atrp, atrg);
clreof (linea, lineas, bram, atrp);
break;
case '3':
case 0x5100: /* PgDn */
for (i=0; (i < lineas-1-linea) && (*p); i++) {
while ((*p != 10) && (*p)) p++;
p++;
}
for (linea = 1; (linea <= lineas-2) && *p; linea++)
display (&p, &bram[linea*80], atrp, atrg);
if (linea>1) {
clreof (linea, lineas, bram, atrp);
break;
}
case '1':
case 0x4F00: /* End */
while (*p++);
linea=lineas;
while ((linea>0) && (p-cadena)) {
while ((*p != 10) && (p!=cadena)) p--; linea--;
if (p-cadena) p--; }
if (p-cadena) p+=2;
for (linea = 1; (linea <= lineas-2) && *p; linea++)
display (&p, &bram[linea*80], atrp, atrg);
clreof (linea, lineas, bram, atrp);
break;
case '7':
case 0x4700: /* Home */
p = cadena;
for (linea = 1; (linea <= lineas-2) && *p; linea++)
display (&p, &bram[linea*80], atrp, atrg);
clreof (linea, lineas, bram, atrp);
break;
}
} while ((tecla != 27) && (tecla != 13) && (tecla != 0x2D00));
}
void clreof (int linea, int lineas, unsigned *bram, int fondo)
{
int i;
unsigned char *p, pp[81];
for (i=0; i<79; i++) pp[i]=' '; pp[i]=10;
for (i=linea; i<=lineas-2; i++) {
p=pp;
display (&p, &bram[i*80], fondo, fondo);
}
}
void display (unsigned char **texto, unsigned *pant, unsigned c1, unsigned c2)
{
int off=0, relleno, color;
unsigned char justificado[80], *p;
relleno = (color = justificar (texto, justificado) ? c2 : c1) | ' ';
p = justificado;
pant [off++] = relleno; while (*p) pant [off++] = *p++ | color;
while (off<80) pant [off++] = relleno; /* clreol */
(*texto)++;
}
int justificar (unsigned char **texto, unsigned char *j)
{
unsigned char *p, c0, c1;
int justif=1, i, ii, lon, izq=0, tipo, grafico=0;
char ais[6][3]={". ",
", ", /* casos preferidos para insertar espacios */
"; ",
": ",
") ",
" ("};
p = *texto; while (*p == ' ') { p++; izq++; }
while ((*p != 10) && *p && justif) {
switch (*p) {
case 218: /* '┌' */ /* ('┌' es signed y da problemas) */
case 179: /* '│' */
case 195: /* '├' */
case 192: /* '└' */
case 196: /* '─' */
case 219: /* '█' */
case 220: /* '▄' */
case 223: /* '▀' */ grafico++;
justif=0; break; /* sin justificar */
case 240: /* '≡' */ justif=0; break;
}
p++;
}
if (justif) {
p = *texto;
while ((*p != 10) && *p) p++;
if (*p && (*(p+2)==10) || (*(p+2)==0)) justif=0;
}
p = j;
while ((**texto != 10) && **texto)
if (**texto != 240) {
*p++=**texto; (*texto)++;
}
else
(*texto)++; /* saltar '≡' */
*p=0;
lon=strlen(j);
if (justif && (lon > 64) && (izq<5))
while (lon < 78) {
for (tipo=0; (tipo<6) && (lon<78); tipo++)
for (i = lon-1; (i > izq) && (lon < 78); i--)
if ((j[i] == ais[tipo][1]) && (j[i-1] == ais[tipo][0])) {
c0 = ' ';
for (ii=i; j[ii-1] ;ii++) { c1=j[ii]; j[ii]=c0; c0=c1; }
lon++;
}
for (i = lon-1; (i > izq) && (lon < 78); i--)
if ((j[i]==' ') && (j[i-1] != ' ')) {
c0 = ' ';
for (ii=i; j[ii-1] ;ii++) { c1=j[ii]; j[ii]=c0; c0=c1; }
lon++;
}
}
return (grafico);
}