/* generic.c */
/* Copyright 1999 - Joseph Pranevich */

/* This is a driver to implement, when possible, "high-level"
   routines using only low level calls. This is to make it possible
   to have accelerated functions for the individual drivers...
   or to simply not bother with them. */

/* When creating new drivers, you need to assign all the functions that
   that driver supports into the driver struct. If it is a supplementary
   driver, it should make sure to perserve the old values. */

#include <stdio.h>

#include "console.h"
#include "config.h"
#include "debugtools.h"

DEFAULT_DEBUG_CHANNEL(console);

static void GENERIC_MoveLine(char row1, char row2, char col1, char col2);
static void GENERIC_ClearLine(char row, char col1, char col2, int bgcolor,
   int attribute);
void GENERIC_Start(void)
{
   /* Here, we only want to add a driver if there is not one already
      defined. */

   TRACE("GENERIC_Start\n");

   if (!driver.clearWindow)
      driver.clearWindow = GENERIC_ClearWindow;

   if (!driver.scrollUpWindow)
      driver.scrollUpWindow = GENERIC_ScrollUpWindow;

   if (!driver.scrollDownWindow)
      driver.scrollDownWindow = GENERIC_ScrollDownWindow;

   if (!driver.getCharacter)
      driver.getCharacter = GENERIC_GetCharacter;
}

void GENERIC_ClearWindow(char row1, char col1, char row2, char col2, 
   int bg_color, int attribute)
{
   char trow, tcol, x;
   int old_refresh;

   /* Abort if we have only partial functionality */
   if (!(driver.getCursorPosition && driver.moveCursor && driver.write))
      return;

   old_refresh = CONSOLE_GetRefresh();
   CONSOLE_SetRefresh(FALSE);

   CONSOLE_GetCursorPosition(&trow, &tcol);
   
   for (x = row1; x <= row2; x++)
      GENERIC_ClearLine(x, col1, col2, bg_color, attribute);

   CONSOLE_MoveCursor(trow, tcol);

   CONSOLE_SetRefresh(old_refresh);
}      

void GENERIC_ScrollUpWindow(char row1, char col1, char row2, char col2, 
   char lines, int bg_color, int attribute)
{
   /* Scroll Up Window: Characters go down */

   char trow, tcol, x;
   int old_refresh;

   TRACE("Scroll Up %d lines from %d to %d.\n", lines, row1,
      row2);

   /* Abort if we have only partial functionality */
   if (!(driver.getCursorPosition && driver.moveCursor && driver.write
      && driver.getCharacterAtCursor && driver.clearWindow))
      return;
   
   /* Save initial state... */
   old_refresh = CONSOLE_GetRefresh();
   CONSOLE_SetRefresh(FALSE);
   CONSOLE_GetCursorPosition(&trow, &tcol);

   for (x = row1 + lines; x <= row2; x++)
   {
      GENERIC_MoveLine(x, x - lines, col1, col2);
      GENERIC_ClearLine(x, col1, col2, bg_color, attribute);
   }

   /* Restore State */
   CONSOLE_MoveCursor(trow, tcol); 
   CONSOLE_SetRefresh(old_refresh);
}

void GENERIC_ScrollDownWindow(char row1, char col1, char row2, char col2, 
   char lines, int bg_color, int attribute)
{
   /* Scroll Down Window: Characters go up */

   char trow, tcol, x;
   int old_refresh;

   /* Abort if we have only partial functionality */
   if (!(driver.getCursorPosition && driver.moveCursor && driver.write
      && driver.getCharacterAtCursor && driver.clearWindow))
      return;
   
   /* Save initial state... */
   old_refresh = CONSOLE_GetRefresh();
   CONSOLE_SetRefresh(FALSE);
   CONSOLE_GetCursorPosition(&trow, &tcol);

   for (x = row2; x >= row1 + lines; x--)
   {
      GENERIC_MoveLine(x, x + lines, col1, col2);
      GENERIC_ClearLine(x, col1, col1, bg_color, attribute);
   }

   /* Restore State */
   CONSOLE_MoveCursor(trow, tcol); 
   CONSOLE_SetRefresh(old_refresh);
}

char GENERIC_GetCharacter()
{
   /* Keep getting keys until we get one with a char value */
   char ch = (char) 0, scan;
   
   while (!ch)
   {
      CONSOLE_GetKeystroke(&scan, &ch);
   }
   return ch;
}

static void GENERIC_ClearLine(char row, char col1, char col2, int bgcolor,
   int attribute)
{
   /* This function is here to simplify the logic of the scroll and clear
      functions but may be useful elsewhere. If it can be used from
      outside here, it should be made non-static */

   char x;

   TRACE("Clear Line: %d from %d to %d (unused: bgcolor %d, attrib %d).\n", row, col1, col2, bgcolor, attribute);

   for (x = col1; x <= col2; x++)
   {
      CONSOLE_MoveCursor(row, x);
      CONSOLE_Write(' ', 0, 0, 0);
   }

   /* Assume that the calling function will make sure that the cursor is
   repositioned properly. If this becomes non-static, that will need to be
   changed. */
}
   
static void GENERIC_MoveLine(char row1, char row2, char col1, char col2)
{
   /* This function is here to simplify the logic of the scroll and clear
      functions but may be useful elsewhere. If it can be used from
      outside here, it should be made non-static */

   char x;
   int bg_color, fg_color, attribute;
   char ch;

   TRACE("Move Line: Move %d to %d.\n", row1, row2);

   for (x = col1; x <= col2; x++)
   {
      CONSOLE_MoveCursor(row1, x);
      CONSOLE_GetCharacterAtCursor(&ch, &fg_color, &bg_color, &attribute);
      CONSOLE_MoveCursor(row2, x);
      CONSOLE_Write(ch, fg_color, bg_color, attribute);
   }

   /* Assume that the calling function will make sure that the cursor is
   repositioned properly. If this becomes non-static, that will need to be
   changed. */
}   
