Subversion Repositories shark

Rev

Blame | Last modification | View Log | RSS feed

/*
 *
 *
 */


#include <stdio.h>
#include <stdlib.h>


/* per sleep() */
#include <unistd.h>


#if defined(USE_NCURSES)
#include <curses.h>
#elif defined(USE_CONIO)
#include <conio.o>
#else
#error USE_NCURSES or USE_CONIO must be defined
#endif

#include "hconf.h"

/*
 *
 * CONIO
 *
 */


#ifdef USE_CONIO

#define DEFAULT_BG BLUE

#define NORMAL_FG WHITE
#define NORMAL_BG BLUE

#define INVERSE_FG BLACK
#define INVERSE_BG RED

/* -- */

struct text_info info;

void _initscreen(void)
{
  textbackground(DEFAULT_BG);
  clrscr();
  gettextinfo(&info);
}

void _endscreen(void)
{
  clrscr();
}

static __inline__ int _cols(void)
{
  return info.screenwidth;
}

static __inline__ int _rows(void)
{
  return info.screenheight;
}

int _gotorc(int r, int c)
{
  /* zero based */
  gotoxy(c,r);
}

#define _printw(fmt,args...) cprintf(fmt,##args)
#define _refresh()

void _normal(void)
{
  textbackground(NORMAL_BG);
  textcolor(NORMAL_FG);
}

#endif

/*
 *
 * NCURSES
 *
 */


#ifdef USE_NCURSES

// with bold
#define DEFAULT_FG COLOR_CYAN
#define DEFAULT_BG COLOR_BLUE

#define NORMAL_FG COLOR_BLACK
#define NORMAL_BG COLOR_WHITE

// with bold
#define INVERSE_FG COLOR_WHITE
#define INVERSE_BG COLOR_BLUE

//with bold
#define BOX_BORDERFGU COLOR_WHITE
#define BOX_BORDERBGU COLOR_WHITE

#define BOX_BORDERFGD COLOR_BLACK
#define BOX_BORDERBGD COLOR_WHITE

#define BOX_FG COLOR_BLACK
#define BOX_BG COLOR_WHITE

#define SHADOW_FG COLOR_BLACK
#define SHADOW_BG COLOR_BLACK

#define TITLE_FG COLOR_YELLOW
#define TITLE_BG COLOR_WHITE

#define _KEY_OK     0x1b
#define _KEY_DOWN   KEY_DOWN
#define _KEY_UP     KEY_UP
#define _KEY_TOGGLE 0x0a

/* -- */

#define _BACKGROUND 1
#define _NORMAL     2
#define _INVERSE    3
#define _BORDERBOXU 4
#define _BORDERBOXD 5
#define _BOX        6
#define _SHADOW     7
#define _TITLE      8
#define _DEFAULT    9

#define STDWIN stdscr

/* (U-upper,L-lower) (L-left,R-right) */
#define _UL ACS_BSSB
#define _LL ACS_SSBB        
#define _UR ACS_BBSS
#define _LR ACS_SBBS
#define _HH ACS_BSBS
#define _VV ACS_SBSB

void _defaultcolor(WINDOW *w)
{
  wattrset(w,COLOR_PAIR(_DEFAULT)|A_BOLD);
  wbkgdset(w,COLOR_PAIR(_DEFAULT)|A_BOLD);
}

void _normal(WINDOW *w)
{
  wattrset(w,COLOR_PAIR(_NORMAL));
  wbkgdset(w,COLOR_PAIR(_NORMAL));
}

void _inverse(WINDOW *w)
{
  wattrset(w,COLOR_PAIR(_INVERSE)|A_BOLD);
  wbkgdset(w,COLOR_PAIR(_INVERSE)|A_BOLD);
}

void _shadow(WINDOW *w)
{
  wattrset(w,COLOR_PAIR(_SHADOW));
  wbkgdset(w,COLOR_PAIR(_SHADOW));
}

void _boxcolor(WINDOW *w)
{
  wattrset(w,COLOR_PAIR(_BOX));
  wbkgdset(w,COLOR_PAIR(_BOX));
}

void _titlecolor(WINDOW *w)
{
  wattrset(w,COLOR_PAIR(_TITLE)|A_BOLD);
  wbkgdset(w,COLOR_PAIR(_TITLE)|A_BOLD);
}

void _borderboxucolor(WINDOW *w)
{
  wattrset(w,COLOR_PAIR(_BORDERBOXU)|A_BOLD);
  wbkgdset(w,COLOR_PAIR(_BORDERBOXU)|A_BOLD);
}

void _borderboxdcolor(WINDOW *w)
{
  wattrset(w,COLOR_PAIR(_BORDERBOXD));
  wbkgdset(w,COLOR_PAIR(_BORDERBOXD));
}

void _initscreen(void)
{
  initscr();
  start_color();
  init_pair(_BACKGROUND,DEFAULT_BG,DEFAULT_BG);
  init_pair(_DEFAULT,DEFAULT_FG,DEFAULT_BG);
  init_pair(_NORMAL,NORMAL_FG,NORMAL_BG);
  init_pair(_INVERSE,INVERSE_FG,INVERSE_BG);
  init_pair(_BORDERBOXU,BOX_BORDERFGU,BOX_BORDERBGU);
  init_pair(_BORDERBOXD,BOX_BORDERFGD,BOX_BORDERBGD);
  init_pair(_BOX,BOX_FG,BOX_BG);
  init_pair(_SHADOW,SHADOW_FG,SHADOW_BG);
  init_pair(_TITLE,TITLE_FG,TITLE_BG);
  bkgdset(COLOR_PAIR(_BACKGROUND));
  clear();
  cbreak(); /* input one char at time (don't wait for \n) */
  noecho();
  keypad(stdscr,TRUE);
  _normal(stdscr);
  refresh();
}

void _endscreen(void)
{
  endwin();
}

static __inline__ int _cols(void)
{
  return COLS;
}

static __inline__ int _rows(void)
{
  return LINES;
}

static __inline__ void _gotorc(WINDOW *w,int r, int c)
{
  /* zero based */
  wmove(w,r,c);
}

#define _printw(w,fmt,args...) wprintw(w,fmt,##args)

void _refresh(WINDOW *w)
{
  wrefresh(w);
}

WINDOW *_createwin(int str, int stc, int lines, int cols)
{
  WINDOW *wnd;
  wnd=newwin(lines,cols,str,stc);
  if (wnd!=NULL) {
    //wbkgdset(wnd,COLOR_PAIR(_BACKGROUND));
    //wclear(wnd);
    //_normal(wnd);
  }
  return wnd;
}

#define _deletewin(w) delwin(w)

#define _putch(w,c) waddch(w,c)
#define _getch() getch()
#define _clreol(w) wclrtoeol(w)
#define _clrscr(w) wclear(w)

#define _bell() addch('\07');

#endif

/*
 *
 *
 *
 */


static void whichcolor(WINDOW *wnd, int up, int inv)
{
  if (((inv==1)&&(up==1))||((inv==0)&&(up==0))) _borderboxdcolor(wnd);
  else _borderboxucolor(wnd);
}

void _settitle(WINDOW *wnd,
               int sy, int sx,
               int lines, int cols,
               int bordy, int bordx,
               char *title,
               int shad, int inv)
{
  int x;

  sx-=bordx+1;
  sy-=bordy+1;
  cols+=2*(bordx+1);
  lines+=2*(bordy+1);

  whichcolor(wnd,1,inv);
  _gotorc(wnd,sy,sx+1);
  for (x=0;x<cols-2;x++) _putch(wnd,_HH);

  if (title!=NULL) {
    _titlecolor(wnd);
    _gotorc(wnd,sy,sx+(cols-strlen(title)-2)/2);
    _printw(wnd," %s ",title);

    _normal(wnd);
    _gotorc(wnd,sy+2,sx+2);
    _printw(wnd,"use <ESC> to exit, <ENTER> to enter/toggle,");
    _gotorc(wnd,sy+3,sx+2);
    _printw(wnd,"arrows keys to move");
  }


  _refresh(wnd);
}

void _box(WINDOW *wnd,
          int sy, int sx,
          int lines, int cols,
          int bordy, int bordx,
          char *title,
          int shad, int inv)
{
  int x,y;

  sx-=bordx+1;
  sy-=bordy+1;
  cols+=2*(bordx+1);
  lines+=2*(bordy+1);

  {
    char blanks[180];
    memset(blanks,' ',sizeof(blanks));
    blanks[cols]='\0';
    _boxcolor(wnd);
    for (y=0;y<lines;y++) {
      _gotorc(wnd,sy+y,sx);
      _printw(wnd,"%s",blanks);
    }
  }

  whichcolor(wnd,1,inv);
  _gotorc(wnd,sy,sx);
  _putch(wnd,_UL);
  for (x=0;x<cols-2;x++) _putch(wnd,_HH);
  whichcolor(wnd,0,inv);
  _putch(wnd,_UR);

  for (y=1;y<lines-1;y++) {
    whichcolor(wnd,1,inv);
    _gotorc(wnd,sy+y,sx);
    _putch(wnd,_VV);
    whichcolor(wnd,0,inv);
    _gotorc(wnd,sy+y,sx+cols-1);
    _putch(wnd,_VV);
    if (shad) {
      _shadow(wnd);
      _putch(wnd,' ');
      _putch(wnd,' ');
    }
  }

  whichcolor(wnd,1,inv);
  _gotorc(wnd,sy+lines-1,sx);
  _putch(wnd,_LL);
  whichcolor(wnd,0,inv);
  for (x=0;x<cols-2;x++) _putch(wnd,_HH);
  _putch(wnd,_LR);
  if (shad) {
    _shadow(wnd);
    _putch(wnd,' ');
    _putch(wnd,' ');
  }

  if (shad) {
    _shadow(wnd);
    _gotorc(wnd,sy+lines,sx+1);
    for (x=0;x<cols+1;x++) _putch(wnd,' ');
  }

  sx+=bordx+1;
  sy+=bordy+1;
  cols-=2*(bordx+1);
  lines-=2*(bordy+1);

  _settitle(wnd,sy,sx,lines,cols,bordy,bordx,title,shad,inv);

  /* refresh made by _settitle() */
}

void showtitle(char *s);

/* -- */


void showbol(WINDOW *wnd, struct menuentry *ptr)
{
  struct variable *var;
  char ch;
  var=ptr->x.bool.var;  
  if (!strcmp(var->value,"y")) ch='*';
  else ch=' ';
  _printw(wnd,"[%c] %s",ch,ptr->x.bool.text);
  _normal(wnd);
  _clreol(wnd);
}

void showtristate(WINDOW *wnd, struct menuentry *ptr)
{
  struct variable *var;
  char ch;
  var=ptr->x.bool.var;  
  if (!strcmp(var->value,"y")) ch='*';
  else if (!strcmp(var->value,"n")) ch=' ';
  else ch='M';
  _printw(wnd,"<%c> %s",ch,ptr->x.bool.text);
  _normal(wnd);
  _clreol(wnd);
}

void showchoice(WINDOW *wnd, struct menuentry *ptr)
{
  _printw(wnd,"   %s (%s)",ptr->x.choice.text,ptr->x.choice.act->text);
  _normal(wnd);
  _clreol(wnd);
}

void showsubmenu(WINDOW *wnd, struct menuentry *ptr)
{
  _printw(wnd,"    %s --->",ptr->x.submenu.text);
  _normal(wnd);
  _clreol(wnd);
}

/* -- */

int nmax; // numero linee massimo

void showmenuentries(WINDOW *wnd,struct menuentry *ptr, int r, int c, int rcur)
{
  int i;

  i=0;
  while (ptr!=NULL) {
    _gotorc(wnd,r,c);
    if (r==rcur) _inverse(wnd);
    else _normal(wnd);
    r++;
    switch(ptr->type) {
    case BOOLENTRY:
      showbol(wnd,ptr);
      break;
    case TRISTATEENTRY:
      showtristate(wnd,ptr);
      break;
    case CHOICEENTRY:
      showchoice(wnd,ptr);
      break;
    case SUBMENUENTRY:
      showsubmenu(wnd,ptr);
      break;
    default:
      _printw(wnd,"@@@");
      break;
    }
    ptr=ptr->n;
    i++;
    if (i==nmax) return;
  }
}

/* --- */

struct menuentry *expandcase(struct menuentry *menuent);
struct menuentry *expandmenu(struct menuentry *menuent);

struct menuentry *expandcase(struct menuentry *menuent)
{
  struct _case *list;
  list=menuent->x._case.list;
  while (list!=NULL) {
    if (!strcmp(list->value,menuent->x._case.var->value)) {      
      return expandmenu(list->list);
    }
    list=list->next;
  }
  return NULL;
}

int nument;

struct menuentry *expandmenu(struct menuentry *menuent)
{
  struct menuentry *start,*ptr,*ent,*prev,*p;
  int ne;

  ne=0;
  ptr=menuent;
  prev=NULL;
  start=NULL;
  while (ptr!=NULL) {
    switch(ptr->type) {

    case CASEENTRY:
      ent=expandcase(ptr);
      if (ent==NULL) {
        if (prev!=NULL) prev->n=ptr->next;
        ptr=ptr->next;
        break;
      }
      if (start==NULL) start=ent;

      if (prev!=NULL) prev->n=ent;
      ent->p=prev;
      p=ent;
      while (p->n!=NULL) p=p->n;
      p->n=ptr->next;

      prev=p;
      ptr=ptr->next;
      break;

    default:
      if (start==NULL) start=ptr;
      ne++;

      ptr->p=prev;
      ptr->n=ptr->next;
     
      prev=ptr;
      ptr=ptr->next;
      break;
    }
  }

  nument+=ne;
  return start;
}

/* -- */

#define MUSTREDISPLAY 0x01
#define MUSTREBUILD   0x02

int showmenu(WINDOW *wnd, struct menu *menu);
int showchoicewnd(WINDOW *wnd, struct menuentry *menu);

int enteron(WINDOW *wnd,struct menuentry *ptr)
{
  struct variable *var;

  switch(ptr->type) {

  case BOOLENTRY:
    var=ptr->x.bool.var;
    if (*var->value=='y') *var->value='n';
    else *var->value='y';
    if (var->flags&FLAG_M) return MUSTREBUILD;
    break;

  case TRISTATEENTRY:
    var=ptr->x.tristate.var;
    if (*var->value=='y') *var->value='n';
    else if (*var->value=='n') *var->value='m';
    else *var->value='y';
    if (var->flags&FLAG_M) return MUSTREBUILD;
    break;

  case CHOICEENTRY:
    return showchoicewnd(wnd,ptr)|MUSTREDISPLAY;

  case SUBMENUENTRY:
    return showmenu(wnd,ptr->x.submenu.menu)|MUSTREDISPLAY;

  default:
    _bell();
    break;
  }

  return 0;
}

/* --- */

int SC=9;
int SR=9;
int NL=36;
int NC=61;
int BR=0;
int BC=4;

/* --- */

/* sigh :-( */
static struct choice *findprev(struct choice *list, struct choice *cur)
{
  struct choice *c,*p;
  c=list;
  p=NULL;
  while (c!=NULL) {
    if (c==cur) return p;
    p=c;
    c=c->next;
  }
  return NULL;
}

int showchoicewnd(WINDOW *wnd, struct menuentry *ent)
{
  struct choice *first; // first menuentry of the list
  struct choice *cur;   // selected menuentry
  struct choice *fline; // menuentry to show on the first line
  struct choice *p;
  int ch;
  int rcur;
  int i,r,c;
  int ret;

  ret=MUSTREDISPLAY;

  first=fline=cur=ent->x.choice.list;
  rcur=0;

  showtitle(ent->x.choice.text);
  _clrscr(wnd);
 
  for (;;) {
 
    r=c=0;

    p=fline;
    i=0;
    while (p!=NULL) {
      _gotorc(wnd,r,c);
      if (r==rcur) _inverse(wnd);
      else _normal(wnd);
      r++;

      _printw(wnd,"(%c) %s",p==ent->x.choice.act?'X':' ',p->text);
      _clreol(wnd);
     
      p=p->next;
      i++;
      if (i==nmax) break;
    }

    _refresh(wnd);

    ch=getch();
    switch (ch) {

    case _KEY_OK:
      return ret;

    case _KEY_DOWN:
      if (cur->next==NULL) break;
      cur=cur->next;
      if (rcur<NL-1) {
        rcur++;
        break;
      }
      fline=fline->next;
      break;

    case _KEY_UP:
      p=findprev(ent->x.choice.list,cur);
      if (p==NULL) break;
      cur=p;
      if (rcur!=0) {
        rcur=rcur--;
        break;
      }
      fline=findprev(ent->x.choice.list,fline);
      break;

    case _KEY_TOGGLE:
      if ((ent->x.choice.act->var->flags&FLAG_M)||(cur->var->flags&FLAG_M))
        ret|=MUSTREBUILD;
      *(ent->x.choice.act->var->value)='n';
      ent->x.choice.act=cur;
      *(ent->x.choice.act->var->value)='y';
      break;         
    }    
  }
}

int showmenu(WINDOW *wnd, struct menu *menu)
{
  struct menuentry *first; // first menuentry of the list
  struct menuentry *cur;   // selected menuentry
  struct menuentry *fline; // menuentry to show on the first line
  int redo;
  int ch;
  int rcur;
  int ret;

  first=fline=cur=NULL;
  rcur=0;
  redo=1;
  ret=MUSTREDISPLAY;

  for (;;) {
    if (redo&MUSTREBUILD) redo|=MUSTREDISPLAY;
    ret|=redo;
    if (redo&MUSTREBUILD) {
      fline=NULL;
     
    }
    if (redo&MUSTREDISPLAY) {
      nument=0;
      first=expandmenu(menu->entries);
      if (fline==NULL) {
        fline=first;
        if (cur==NULL) {
          cur=fline;
          rcur=0;
        }
      }
      nmax=NL;
      showtitle(menu->title);
      _normal(wnd);
      _clrscr(wnd);
      redo=0;
    }
    showmenuentries(wnd,fline,0,0,rcur);
    _refresh(wnd);

    ch=getch();
    switch (ch) {

    case _KEY_OK:
      return ret;

    case _KEY_DOWN:
      if (cur->n==NULL) break;
      cur=cur->n;
      if (rcur<NL-1) {
        rcur++;
        break;
      }
      fline=fline->n;
      break;

    case _KEY_UP:
      if (cur->p==NULL) break;
      cur=cur->p;
      if (rcur!=0) {
        rcur=rcur--;
        break;
      }
      fline=fline->p;
      break;

    case _KEY_TOGGLE:
      redo=enteron(wnd,cur);      
      break;         

    default:
      /*
      _normal(STDWIN);
      _gotorc(STDWIN,0,0);
      _printw(STDWIN,"%04x",ch);
      _refresh(STDWIN);
      */

    }    
   
  }

}

void showtitle(char *s)
{
  _settitle(STDWIN,SR-6,SC-2,NL+8,NC+4,BR,BC,s,1,0);
}

/*
 *
 */


int show(void)
{
  WINDOW *wnd;
  int i;

  _initscreen();

  SC=9;
  SR=9;
  NL=_rows()-5-SR-BR*2;
  NC=_cols()-2-SC-BC*2;
  BR=0;
  BC=4;

  _defaultcolor(STDWIN);
  _gotorc(STDWIN,0,0);
  _printw(STDWIN," Hartik4 (Lego) version 4.0pre1 - Configuration");
  _gotorc(STDWIN,1,1);
  for (i=0;i<_cols()-2;i++) _putch(STDWIN,_HH);

  _box(STDWIN,SR-6,SC-2,NL+8,NC+4,BR,BC,NULL,1,0);
  _box(STDWIN,SR,SC,NL,NC,BR,BC,NULL,0,1);
  wnd=_createwin(SR,SC,NL,NC);







  //showmenu(wnd,mainmenu);





  _endscreen();

  return 0;
}