tinycobol/cobroutines/screen.c

799 lines
19 KiB
C
Raw Permalink Blame History

/*
* Copyright (C) 2003 Ferran Pegueroles, Hudson Reis.
*.
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1,
* or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; see the file COPYING.LIB. If
* not, write to the Free Software Foundation, Inc., 59 Temple Place,
* Suite 330, Boston, MA 02111-1307 USA
*/
/* Screen routines */
#include <stdio.h>
#include <string.h>
#if defined(__MINGW32__)
# include <curses.h>
# include "mwindows.h"
#else
# include <termios.h>
# include <ncurses.h>
#endif
#include "globals.h"
#include <unistd.h> // for read()
struct screenArea {
char initLine;
char initColumn;
char endLine;
char endColumn;
} *screenArea;
struct screenposition {
short line;
short column;
} *screenposition;
char *windows[99];
struct windpos {
unsigned char id, fu, ls, ce, nl, tl, atr;
char dados[4000];
} *windpos;
struct windmenu {
unsigned char id, fu, ls, ce, nl, tl, atr, nlm, tlm, rtm;
char dados[4000];
} *windmenu;
int lastWindow = -1;
bool initColor = 0;
/* Prototypes */
/* Functions */
//cbl_t cbl_clear_scr(void) {
// clear();
// return 0;
//}
//void cbl_get_csr_pos(int *x, int *y, int *retorno) {
// getsyx((int)*y,(int)*x);
// printf("Y: %d\n", *y);
// printf("X: %d\n", *x);
// *retorno = 0;
//}
//cbl_t cbl_get_kbd_status(void) {
// nodelay(stdscr,TRUE);
// timeout(10);
// return(getch());
//}
//cbl_t cbl_read_kbd_char(void) {
// return (getch());
//}
/*----------------------------------------------------------------------------------------
Routine: cbl_save_screen
Purpose: Saves all screen contents on a user program buffer.
----------------------------------------------------------------------------------------*/
void cbl_save_screen( chtype *buffer ) {
int l = 0;
int c = 0;
int i = 0;
for ( l = 0 ; l < 24 ; l++ )
for ( c = 0 ; c < 80 ; c++ )
buffer[i++] = mvinch(l,c);
}
/*----------------------------------------------------------------------------------------
Routine: cbl_restore_screen
Purpose: Restores all screen contents from a user program buffer.
----------------------------------------------------------------------------------------*/
void cbl_restore_screen( chtype *buffer ) {
int l = 0;
int c = 0;
int i = 0;
chtype k;
for ( l = 0 ; l < 24 ; l++ )
for ( c = 0 ; c < 80 ; c++ ) {
k = buffer[i++];
attron( (k & A_ATTRIBUTES) | (k & A_COLOR) );
mvaddch(l, c, (k & A_CHARTEXT));
}
}
/*----------------------------------------------------------------------------------------
Routine: cbl_save_partial_screen
Purpose: Saves a screen portion's contents on a user program buffer.
----------------------------------------------------------------------------------------*/
void cbl_save_partial_screen( struct screenArea *screenArea , chtype *buffer ) {
int l = 0;
int c = 0;
int i = 0;
int initLine = (int)screenArea->initLine;
int initCol = (int)screenArea->initColumn;
int endLine = (int)screenArea->endLine;
int endCol = (int)screenArea->endColumn;
// mvprintw(23,0,"OnSave: %d %d %d %d",initLine,initCol,endLine,endCol);
// getch();
// refresh();
for ( l = initLine-1 ; l < endLine ; l++ )
for ( c = initCol-1 ; c < endCol ; c++ )
buffer[i++] = mvinch(l,c);
}
/*----------------------------------------------------------------------------------------
Routine: cbl_restore_partial_screen
Purpose: Restores a screen portion's contents from a user program buffer.
----------------------------------------------------------------------------------------*/
void cbl_restore_partial_screen( struct screenArea *screenArea , chtype *buffer ) {
int l = 0;
int c = 0;
int i = 0;
chtype k;
int initLine = (int)screenArea->initLine;
int initCol = (int)screenArea->initColumn;
int endLine = (int)screenArea->endLine;
int endCol = (int)screenArea->endColumn;
// mvprintw(23,0,"OnRestore: %d %d %d %d",initLine,initCol,endLine,endCol);
// getch();
// refresh();
for ( l = initLine-1 ; l < endLine ; l++ )
for ( c = initCol-1 ; c < endCol ; c++ ) {
k = buffer[i++];
attron( (k & A_ATTRIBUTES) | (k & A_COLOR) );
mvaddch(l, c, (k & A_CHARTEXT));
}
}
/*
void cbl_read_scr_chars (struct posicaotela *posicao,
char *buffer_caracteres,
short *buffer_tamanho,
int *retorno)
{
printf("Reading scr chars...\n");
int y, x, i, t;
*retorno = 0;
posicaotela = posicao;
x = posicao->coluna;
y = posicao->linha;
t = *buffer_tamanho - x;
memset(buffer_caracteres,' ',t);
for (i=(x-1);i<=t;i++) {
buffer_caracteres[i] = mvinch(y,i) & A_CHARTEXT;
}
}
void cbl_read_scr_attrs (struct posicaotela *posicao,
char *buffer_atributos,
short *buffer_tamanho,
int *retorno)
{
int y, x, i, t;
*retorno = 0;
posicaotela = posicao;
x = posicao->coluna;
y = posicao->linha;
t = *buffer_tamanho - x;
memset(buffer_atributos,' ',t);
for (i=(x-1);i<=t;i++) {
buffer_atributos[i] = mvinch(y,i) & A_ATTRIBUTES;
}
}
void cbl_read_scr_chattrs (struct posicaotela *posicao,
char *buffer_caracteres,
char *buffer_atributos,
short *buffer_tamanho,
int *retorno)
{
chtype k;
int y, x, i, t, c;
*retorno = 0;
posicaotela = posicao;
x = posicao->coluna;
y = posicao->linha;
memset(buffer_atributos, ' ',*buffer_tamanho * 2);
memset(buffer_caracteres,' ',*buffer_tamanho);
i = 0, t = 0, c = 0;
while(i++ < *buffer_tamanho) {
k = mvinch(y, x);
buffer_caracteres[c++] = (k & A_CHARTEXT);
buffer_atributos[t++] = (k & A_ATTRIBUTES)/65536;
//buffer_atributos[t++] = k & A_COLOR;
buffer_atributos[t++] = (k & A_COLOR)/256;
//printf("color on read:%d\n",(char)((k & A_COLOR)/256));
mvprintw(1,1,"col:%d lin:%d char:%c color:%d",x,y,(k & A_CHARTEXT),(k & A_COLOR)/256); refresh(); getch(); refresh();
x++;
}
}
*/
/*----------------------------------------------------------------------------------------------
cbl_set_csr_pos
Sets the cursor position
----------------------------------------------------------------------------------------------*/
//void cbl_set_csr_pos(int *x, int *y, int *retorno) {
// *retorno = 0;
// setsyx((int)*y,(int)*x);
// move((int)*y,(int)*x);
// refresh();
//}
/*
void cbl_write_scr_attrs (struct posicaotela *posicao,
char *buffer_atributos,
short *buffer_tamanho,
int *retorno)
{
printf("Writing scr attributes...\n");
int y, x, i, t;
*retorno = 0;
posicaotela = posicao;
x = posicao->coluna;
y = posicao->linha;
t = *buffer_tamanho + x;
initscr();
for (i=(x-1);i<=t;i++) {
mvaddch(y, x, *buffer_atributos);
x++;
*buffer_atributos++;
}
// refresh();
endwin();
}
void cbl_write_scr_chars (struct posicaotela *posicao,
char *buffer_caracteres,
short *buffer_tamanho,
int *retorno)
{
printf("Writing scr chars...\n");
int y, x, i, t;
*retorno = 0;
posicaotela = posicao;
x = posicao->coluna;
y = posicao->linha;
t = *buffer_tamanho + x;
initscr();
for (i=(x-1);i<=t;i++) {
mvaddch(y, x, *buffer_caracteres);
x++;
*buffer_caracteres++;
}
// refresh();
endwin();
}
cbl_t cbl_write_scr_chars_attr(void) {
return 0;
}
void cbl_write_scr_chattrs (struct posicaotela *posicao,
char *buffer_caracteres,
char *buffer_atributos,
short *buffer_tamanho,
int *retorno)
{
chtype k;
int y, x, i, k1, c, att, cor;
//addstr("to em cbl_write_scr_chattrs"); refresh(); getch(); refresh();
*retorno = 0;
posicaotela = posicao;
x = posicao->coluna;
y = posicao->linha;
mvprintw(1,1,"col:%d lin:%d",x,y); refresh(); getch(); refresh();
i = 0, c = 0;
while(i < *buffer_tamanho) {
att = ((int) *(buffer_atributos + (c++))) * 65536;
cor = ((int) *(buffer_atributos + (c++))) * 256;
cor = buffer_atributos[c++];
k1 = *(buffer_caracteres + i);
k1 += (k1<0?256:0);
k = k1 | att | cor;
mvaddch(y, x++, k);
i++;
}
refresh();
}
cbl_t cbl_write_scr_n_attr(void) {
return 0;
}
cbl_t cbl_write_scr_n_char(void) {
return 0;
}
cbl_t cbl_write_scr_n_chattr(void) {
return 0;
}
cbl_t cbl_write_scr_tty(void) {
return 0;
}
cbl_t cbl_get_scr_type(void) {
return 0;
}
*/
// ----------------------------------------------------------------------
// Implemented by Walter Garrote
// garrote@dm.com.br
// Brazil
// Go<47><6F>nia-Goi<6F>s
// ----------------------------------------------------------------------
// Obs: As subrotinas que manipulam acesso a video devem ser executadas
// depois de ser chamado no programa cobol uma instru<72><75>o que fa<66>a a inicializa<7A><61>o
// da biblioteca ncurses. Se isso n<>o ocorrer, teremos problema.
// inicia par de cores
void cbl_windms_inicia_cor() {
int i;
if(initColor) // ja passamos por aqui;
return;
if(has_colors()) { // temos suporte a cores
start_color();
for(i = 0; i < COLOR_PAIRS; i++)
init_pair(i, i % COLORS, i / COLORS);
}
initColor++;
// na lib do tiny na parte de inicializacao de cores, n<>o est<73> definido os pares
// foi criada o par com fg e bg = 0
}
// retorna cor de fundo e de frente usando o codigo de cor
void cbl_windms_color_pair(short cor, short *fg, short *bg) {
if(cor == 0) // cor padrao 7 (frente branca, fundo preto)
cor = 7;
*fg = cor % 8; // cor de frente
*bg = cor / 8; // cor de fundo
}
// retorna o codigo de cor usando cor de frente e de fundo
short cbl_windms_monta_cor(short fg, short bg) {
return ((bg * 8) + fg);
}
// escreve na janela
// para se pensar, podemos colocar um byte a mais como sendo o tipo do caracter (highlight, blink etc)
void cbl_windms_escreve(struct windpos *lk) {
int y, x;
short fg, bg, atr;
char *dados = NULL;
switch(lk->fu) { // qual a funcao
case 1:
case 2: dados = windows[lk->id]; // posiciona na memoria alocada pelo subrotina
break;
case 10: dados = lk->dados; // estamos recebendo a tela via cobol
atr = lk->atr;
cbl_windms_color_pair(atr, &bg, &fg);
attron(COLOR_PAIR(atr));
break;
}
move(lk->ls, lk->ce);
refresh(); // apenas para garantir, caso haja um display antes
for(y = lk->ls; y < (lk->ls + lk->nl); y++) { // escreve as linhas
for(x = lk->ce; x < (lk->ce + lk->tl); x++) { // escreve as colunas
if(*dados == '~') { // mudanca de atributo
dados++; // proxima posicao
fg = (int) *(dados++) - 48; // cor de frente
bg = (int) *(dados++) - 48; // cor de fundo
atr = cbl_windms_monta_cor(fg, bg); // qual o par ?
attron(COLOR_PAIR(atr)); // set atributo
}
mvaddch(y, x, *dados++);
}
}
refresh();
}
// muda moldura da janela
void cbl_windms_moldura(struct windpos *lk) {
int i;
short fg, bg, atr;
atr = lk->atr;
cbl_windms_color_pair(lk->atr, &fg, &bg);
attron(COLOR_PAIR(atr));
mvaddch (lk->ls, lk->ce , ACS_ULCORNER); // canto esquerdo superior
mvaddch (lk->ls, lk->ce + lk->tl - 1, ACS_URCORNER); // canto direito superior
mvaddch (lk->ls + lk->nl - 1, lk->ce , ACS_LLCORNER); // canto esquerdo inferior
mvaddch (lk->ls + lk->nl - 1, lk->ce + lk->tl - 1, ACS_LRCORNER); // canto direito inferior
for(i = lk->ls + 1; i < lk->ls + lk->nl - 1; i++) {
mvaddch(i, lk->ce , ACS_VLINE); // linha esquerda
mvaddch(i, lk->ce + lk->tl - 1, ACS_VLINE); // linha direita
}
for(i = lk->ce + 1; i < lk->ce + lk->tl - 1; i++) {
mvaddch(lk->ls, i , ACS_HLINE); // linha superior
mvaddch(lk->ls + lk->nl - 1, i , ACS_HLINE); // linha inferior
}
refresh();
return;
}
// muda cor da janela
void cbl_windms_mudacor(struct windpos *lk) {
short fg, bg;
cbl_windms_color_pair(lk->atr, &fg, &bg);
attron(COLOR_PAIR(lk->atr));
}
// guarda porcao da janela na memoria
int cbl_windms_guarda(struct windpos *lk) {
int y, x, tamanho;
short fg, bg, atr, oldatr; // variaveis auxiliares
char *dados;
if(lastWindow == 99) // limite de janelas
return -1;
tamanho = 4;
for(y = lk->ls; y < lk->ls + lk->nl + 1; y++) // quantos bytes serao necessarios ?
for(x = lk->ce; x < lk->ce + lk->tl + 1; x++) {
atr = (mvinch(y, x) & A_ATTRIBUTES) / 256;
if(atr != oldatr) {
tamanho += 3;
oldatr = atr;
}
tamanho++;
}
lastWindow++; // janela a ser utilizada
windows[lastWindow] = (char *) malloc(sizeof(char) * tamanho); //(lk->nl * lk->tl * 3)); // ponteiro para memoria de video
dados = windows[lastWindow];
oldatr = 0;
for(y = lk->ls; y < lk->ls + lk->nl; y++) { // guarda janela
for(x = lk->ce; x < lk->ce + lk->tl; x++) {
atr = (mvinch(y, x) & A_ATTRIBUTES) / 256;
if(atr != oldatr) {
cbl_windms_color_pair(atr, &bg, &fg);
*dados++ = '~';
*dados++ = (char) ( ( atr % 8 ) + 48 );
*dados++ = (char) ( ( atr / 8 ) + 48 );
oldatr = atr;
}
*dados++ = mvinch(y, x) & A_CHARTEXT;
}
}
return lastWindow;
}
// remove janela
int cbl_windms_remove(struct windpos *lk) {
while(lastWindow >= lk->id)
if(windows[lastWindow]) {
if(lk->fu == 2) // restaura janela antes
cbl_windms_escreve(lk);
free(windows[lastWindow--]);
}
return lastWindow;
}
// auxilio na montagem do menu
void cbl_windms_display_menu(struct windpos *lk, char *dados, int linha) {
}
char * cbl_windms_pos(int nlm, int tlm, int l, int c, char *dad) {
// int tc, l1, c1;
// char *dat;
return NULL;
}
// menu pop
int cbl_windms_menu(struct windpos *lk) {
//int t, y,
int tecla = 0, nlm, tlm, rtm;
char *dad; //, *dat;
struct windpos *lkm;
lkm = calloc(sizeof(struct windpos),0);
// parametros
lkm->id = lk->id;
lkm->ls = lk->ls;
lkm->ce = lk->ce;
lkm->nl = lk->nl;
lkm->tl = lk->tl;
dad = lk->dados;
nlm = (int) *dad++;
tlm = (int) *dad++;
rtm = (int) *dad++;
//t =
//while(t>0) {
// lkm->dados[y++]=*dad++;
// t--;
//}
//lkm->dados = *dad;
lkm->fu = 11;
cbl_windms_moldura(lkm); // moldura
lkm->fu = 10;
cbl_windms_escreve(lkm);
cbl_windms_display_menu(lk, dad, rtm);
noecho();
tecla = getch();
do {
// switch(tecla) {
// case 27: printf("27\n");
// tecla = getch();
// switch(tecla) {
// case 79: tecla = getch();
// break;
// case 91: tecla = getch();
// switch(tecla) {
// case 49:
// case 50:
// case 51:
// case 52:
// case 53:
// case 54: do {
// tecla = getch();
// } while(tecla != 126);
// break;
// }
// break;
// default: break;
// }
// break;
// default: printf("oia %i,%c\n",tecla,tecla);
// break;
// }
move(5, 1); addch(32); refresh();
switch(tecla) {
case KEY_UP: printf("UP %i\t%c ",tecla,tecla);
break;
case KEY_DOWN: printf("Down %i\t%c ",tecla,tecla);
break;
case KEY_LEFT: printf("Left %i\t%c ",tecla,tecla);
break;
case KEY_RIGHT: printf("Right %i\t%c ",tecla,tecla);
break;
case KEY_HOME: printf("Home %i\t%c ",tecla,tecla);
break;
case KEY_END: printf("End %i\t%c ",tecla,tecla);
break;
case KEY_NPAGE: printf("Npage %i\t%c ",tecla,tecla);
break;
case KEY_PPAGE: printf("Ppage %i\t%c ",tecla,tecla);
break;
default:
break;
}
move(5, 1); addch(32); refresh();
tecla = getch();
} while(tecla != KEY_EXIT);
echo();
return 1;
}
// funcao principal
int windms(struct windpos *lk) {
struct windpos *lkaux;
// ajusta valores
lkaux = (struct windpos *) malloc(sizeof(struct windpos));
*lkaux = *lk;
lkaux->ls--;
lkaux->ce--;
cbl_windms_inicia_cor();
if( //(lkaux->ls < 0 || lkaux->ls > 24) || (lkaux->ce < 0 || lkaux->ce > 79) ||
(lkaux->nl < 1 || lkaux->nl > 24) ||
(lkaux->tl < 1 || lkaux->tl > 79)) // parametros errados
return 0;
switch(lk->fu) {
case 0: lk->id = cbl_windms_guarda(lkaux); // guarda janela
break;
case 2: // restaura janela
case 3: lk->id = cbl_windms_remove(lkaux); // elimina janela sem restaurar
break;
case 1: // restaura janela
case 10: cbl_windms_escreve(lkaux); // escreve janela
break;
case 11: cbl_windms_moldura(lkaux); // moldura a janela
break;
case 12: cbl_windms_mudacor(lkaux); // muda cor da janela
break;
case 13: cbl_windms_menu(lkaux); // menu
getch();
break;
}
return 1;
}
// Function to allocate dinamyc memory
// receive: pointer = pointer to memory allocated
// size = size of memory to allocate
// flags = only for compatibility
// return: 0 = ok, memory allocated
// 1 = error
int cbl_alloc_mem(char **pointer, unsigned int size, unsigned int flagsmem ) {
if((*pointer = (char *) malloc(sizeof(char) * size)))
// memset(*pointer, 32, size); for compatibility, microfocus doesn<73>t initialize the memory allocated
return 0;
return 1;
}
// free the memory previous allocated
// receive: pointer
// return: none
void cbl_free_mem(char **pointer) {
free(*pointer);
}
// clear the window with character and attribute
// receive: character = that will paint the screen
// attribute = pair of attribute
// return: none
void cbl_clear_scr(short character, short atr) {
int normal = A_NORMAL | character;
cbl_windms_inicia_cor();
if(has_colors())
normal |= COLOR_PAIR(atr);
bkgdset(normal);
erase();
return;
}
// return the position of cursor
// receive: structure with line and column
// return: position of cursor
void cbl_get_csr_pos(struct screenposition *scr) {
getsyx(scr->line, scr->column);
scr->line++; // adjust the line
scr->column++; // adjust the column
return;
}
// return the state of keyboard
// receive: none
// return: state of keyboard : 0 none, 1 has key
// modified from scr_curses
void cbl_get_kbd_status(short *state) {
int c;
nodelay(stdscr,TRUE);
c=getch();
nodelay(stdscr,FALSE);
if(c > 0) {
ungetch(c);
*state = 1;
} else
*state = 0;
return;
}
// return the size of screen
// receive: none
// return: depth and width
void cbl_get_scr_size(short *depth, short *width) {
getmaxyx(stdscr, *depth, *width);
return;
}
// return the character in keyboard buffer
// receive: none
// return: character
//void cbl_read_kbd_char2(char *character) {
// *character = (char) getch();
// return;
//}
void clr_clear_kbd_buffer() {
nodelay(stdscr, TRUE);
while( getch() != ERR );
nodelay(stdscr,FALSE);
}
//static struct termios initial_settings, new_settings;
static int peek_character = -1;
void init_keyboard()
{
// tcgetattr(0,&initial_settings);
// new_settings = initial_settings;
// new_settings.c_lflag &= ~ICANON;
// new_settings.c_lflag &= ~ECHO;
// new_settings.c_lflag &= ~ISIG;
// new_settings.c_cc[VMIN] = 1;
// new_settings.c_cc[VTIME] = 0;
// tcsetattr(0, TCSANOW, &new_settings);
}
void close_keyboard()
{
// tcsetattr(0, TCSANOW, &initial_settings);
}
int readch()
{
char ch;
if(peek_character != -1)
{
ch = peek_character;
peek_character = -1;
return ch;
}
read(0,&ch,1);
return ch;
}