/* Font loading and misc. column/row oriented text printing routines */

#include <stdio.h>
#include <alloc.h>
#include <dos.h>
#include <string.h>
#include <io.h>
#include <fcntl.h>
#include <vbe.h>
#include "vbetext.h"

int     txt_curx = 1;
int     txt_cury = 1;
int     txt_curvis = 0;

unsigned long txt_fgcol = 0xAAAAAAL;
unsigned long txt_bgcol = 0x000000L;

unsigned long far *thin_cursor;
unsigned long far *thin_cursorbg;
unsigned long far *fat_cursor;
unsigned long far *fat_cursorbg;
unsigned long far *cursor[2];
unsigned long far *cursorbg[2];

int cur_type = THIN_CURSOR;
int cur_height[2] = {2, 16};

unsigned char far *font;
unsigned int fontseg;


int vbeLoadFont(char *fontname)
{
       union REGS regs;
       struct SREGS segregs;
       int f;

       if((f = _open(fontname, O_BINARY | O_RDONLY)) == -1)
               return 0;

       allocmem(4096/16, &fontseg);
       font = (unsigned char far*)MK_FP(fontseg, 0);

       regs.h.ah = 0x3F;
       regs.x.bx = f;
       regs.x.cx = 4096;
       regs.x.dx = FP_OFF(font);
       segregs.ds = FP_SEG(font);
       intdosx(&regs, &regs, &segregs);

       _close(f);
       return 1;
}


void vbeTxtColor(unsigned long fg, unsigned long bg)
{
       int i;

       txt_fgcol = fg;
       txt_bgcol = bg;

       for(i = 0; i < (8 * cur_height[cur_type]); i++)
               cursor[cur_type][i] = txt_fgcol;
}


void do_cursor()
{
       if(txt_curvis) {
               vbeGetImage((txt_curx - 1) * 8,
               ((txt_cury - 1) * 16) + (16 - cur_height[cur_type]),
               8, cur_height[cur_type], cursorbg[cur_type]);
               vbePutSprite((txt_curx - 1) * 8,
               ((txt_cury - 1) * 16) + (16 - cur_height[cur_type]),
               8, cur_height[cur_type], cursor[cur_type]);
       }
}


void vbePosCur(int x, int y)
{
       txt_curx = x;
       txt_cury = y;
}


void vbeHideCur()
{
       vbePutImage((txt_curx - 1) * 8,
       ((txt_cury - 1) * 16) + (16 - cur_height[cur_type]),
       8, cur_height[cur_type], cursorbg[cur_type]);
       txt_curvis = 0;
}


void vbeShowCur()
{
       vbeGetImage((txt_curx - 1) * 8,
       ((txt_cury - 1) * 16) + (16 - cur_height[cur_type]),
       8, cur_height[cur_type], cursorbg[cur_type]);
       vbePutSprite((txt_curx - 1) * 8,
       ((txt_cury - 1) * 16) + (16 - cur_height[cur_type]),
       8, cur_height[cur_type], cursor[cur_type]);
       txt_curvis = 1;
}


void vbeSetCurType(int type)
{
       cur_type = type;
}


void vbePutch(int c)
{
       switch(c){
               case 8:         /* Backspace */
                       if(txt_curx > 1) {
                               vbePutImage((txt_curx - 1) * 8,
                               ((txt_cury - 1) * 16) + (16 - cur_height[cur_type]),
                               8, cur_height[cur_type], cursorbg[cur_type]);
                               txt_curx--;
                       }
                       break;
               default:
                       vbeWriteCharOpaque((txt_curx - 1) * 8,
                               (txt_cury - 1) * 16, txt_fgcol, txt_bgcol, c);
                       txt_curx++;
       }

       if(txt_curx > 80) {
               txt_curx = 1;
               txt_cury ++;
       }

       do_cursor();
}


void vbePrintf(char *s)
{
       int cr = 0, len = strlen(s);

       if(! len)
               return;

       if(s[len - 1] == '\n') {
               s[len - 1] = 0;
               cr = 1;
       }

       vbeWriteStringOpaque((txt_curx - 1) * 8,
               (txt_cury - 1) * 16, txt_fgcol, txt_bgcol, (char far*)s);

       if(cr) {
               txt_cury++;
               txt_curx = 1;
               s[len - 1] = '\n';
       } else
               txt_curx += len;

       do_cursor();
}


void vbeEdgets(char *s, int maxlen, int mk_upper)
{
       char temp[82];
       int insert = 1, done = 0, pos, len, i, j, c, zeroflag;

       vbePrintf(s);
       strcpy(temp,s);
       pos = strlen(s);
       len = strlen(s);

       while (! done) {
               zeroflag = 0;
               if ((c = getch()) == 0) {
                       zeroflag = 1;
                       c = getch();
               }

               if(mk_upper)
                       c = toupper(c);

               switch (c) {
                       case ESC :
                               if (len == 0)
                                       break;

                               for (i = pos; i < len; i++)
                                       vbePutch(' ');
                               for (i = len-1; i >= 0; i--) {
                                       vbePutch(BACKSPC);
                                       vbePutch(' ');
                                       vbePutch(BACKSPC);
                               }
                               pos = len = 0;
                               break;

                       case LEFT :
                               if (zeroflag) {
                                       if (pos == 0)
                                               break;
                                       pos--;
                                       vbePutch(BACKSPC);
                                       break;
                               }

                       case RIGHT :
                               if (zeroflag) {
                                       if (pos == len)
                                               break;
                                       if (pos != maxlen) {
                                               vbePutch(temp[pos]);
                                               pos++;
                                       }
                                       break;
                               }

                       case HOME :
                               if (zeroflag) {
                                       while (pos-- > 0)
                                               vbePutch(BACKSPC);
                                       pos = 0;
                                       break;
                               }

                       case END :
                               if (zeroflag) {
                                       while (pos < len)
                                               vbePutch(temp[pos++]);
                                       break;
                               }

                       case INSERT :
                               if (zeroflag) {
                                       insert = (!(insert));
/*                                      ShowCur(curstart[insert],7); */
                                       break;
                               }

                       case DELETE :
                               if (zeroflag) {
                                       if (pos == len)
                                                 break;
                                       for (i = pos; i < len; i++)
                                               temp[i] = temp[i + 1];
                                       len--;
                                       for (i = pos; i < len; i++)
                                               vbePutch(temp[i]);
                                       vbePutch(' ');
                                       for (i = len + 1; i > pos; i--)
                                               vbePutch(BACKSPC);
                                       break;
                               }

                       case BACKSPC :
                               if (c == BACKSPC) {
                                       if (pos == 0)
                                               break;
                                       if (pos != len) {
                                               for (i = pos - 1; i < len; i++)
                                                       temp[i] = temp[i + 1];
                                               pos--;
                                               len--;
                                               vbePutch(BACKSPC);
                                               for (i = pos; i < len; i++)
                                                       vbePutch(temp[i]);
                                               vbePutch(' ');
                                               for (i = len; i >= pos; i--)
                                                       vbePutch(BACKSPC);
                                       } else {
                                               vbePutch(BACKSPC);
                                               vbePutch(' ');
                                               vbePutch(BACKSPC);
                                               pos = --len;
                                       }
                                       break;
                               }

                       case ENTER :
                               if (c == ENTER) {
                                       done = 1;
                                       break;
                               }

                       case CTLEND :
                               if (zeroflag) {
                                       for (i = pos; i < len; ++i)
                                               vbePutch(' ');
                                       for (i = pos; i < len; ++i)
                                               vbePutch(BACKSPC);
                                       len = pos;
                                       break;
                               }

                       case CTLHOME :
                               if (zeroflag) {
                                       if (pos == 0)
                                               break;
                                       if (pos != len) {
                                               while (0 != pos) {
                                                       for (i = pos - 1; i < len; i++)
                                                               temp[i] = temp[i + 1];
                                                       pos--;
                                                       len--;
                                                       vbePutch(BACKSPC);
                                                       for (i = pos; i < len; i++)
                                                               vbePutch(temp[i]);
                                                       vbePutch(' ');
                                                       for (i = len; i >= pos; i--)
                                                               vbePutch(BACKSPC);
                                               }
                                       } else {
                                               while (0 != pos) {
                                                       vbePutch(BACKSPC);
                                                       vbePutch(' ');
                                                       vbePutch(BACKSPC);
                                                       pos = --len;
                                               }
                                       }
                                       break;
                               }

                       case CTLRT :
                               if (zeroflag) {
                                       do {
                                               if (pos == len)
                                                       break;
                                               if (pos != maxlen) {
                                                       vbePutch(temp[pos]);
                                                       pos++;
                                               }
                                       } while (isspace(temp[pos]));
                                       do {
                                               if (pos == len)
                                                       break;
                                               if (pos != maxlen) {
                                                       vbePutch(temp[pos]);
                                                       pos++;
                                               }
                                       } while (!isspace(temp[pos]));
                                       break;
                               }

                       case CTLLFT :
                               if (zeroflag) {
                                       do {
                                               if (pos == 0)
                                                       break;
                                               pos--;
                                               vbePutch(BACKSPC);
                                       } while (isspace(temp[pos]));
                                       do {
                                               if (pos == 0)
                                                       break;
                                               pos--;
                                               vbePutch(BACKSPC);
                                       } while (!isspace(temp[pos]));
                                               break;
                               }

                       default :
                               if (zeroflag)
                                       break;
                               if (c == 0 || pos == maxlen)
                                       break;
                               if ((!(insert)) || pos == len) {
                                       temp[pos++] = (char)c;
                                       if (pos > len) len++;
                                               vbePutch(c);
                               } else {
                                       if(len == maxlen)
                                               break;

                                       for (i = len++; i >= pos; i--)
                                               temp[i + 1] = temp[i];
                                       temp[pos++] = (char)c;
                                       vbePutch(c);
                                       for (i = pos; i < len; i++)
                                               vbePutch(temp[i]);
                                       for (i = len; i > pos; i--)
                                               vbePutch(BACKSPC);
                               }
               }
       }
       temp[len] = '\0';
       strcpy(s, temp);
       return len;
}