/**********************************************************************
 *
 * locate.cpp
 * Copyright (C) 1996
 * 
 * A component of the fnord webserver written by bmorin@wpi.edu.
 *
 * Altered for use with the Greenstone digital library software by the
 * New Zealand Digital Library Project at the University of Waikato,
 * New Zealand.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *********************************************************************/

#include "text_t.h"
#include <windows.h>
#include <stdio.h>
#include "locate.h"
#include "settings.h"

/* The following values are inserted or used by FNORD.CPP */
HWND GSDL_Window;
int line_spacing;
RECT text_rect;


static FILE *log_file=NULL;

static int location_found=0;
text_t data_location;

void set_location(text_t possible)
{
  if (location_found != 0) return;
  if (!possible.empty()) {
    data_location = possible;
    if (*(data_location.end()-1) != '\\') {
      data_location.push_back('\\');
    }
    location_found = 1;
  }
}

void find_location(void)
{
  if (location_found != 0) return;
  
  char here[MAX_FILENAME_SIZE];
  char *send;

  if (GetModuleFileName(NULL,here,MAX_FILENAME_SIZE) <= 0) {
    // failed
    data_location.clear();
  } else {
    send = strrchr(here,'\\');
    if (send != NULL) {
      ++send;
    } else {
      send = strchr(here,':');
      if (send != NULL) {
        ++send;
      } else {
        send = here;
      }
    }
  }
  *send = 0;
  data_location.setcstr(here);
  location_found = 1;
}

void open_log_file()
{
  if (log_file != NULL) fclose(log_file);
  log_file = fopen(gsdl_log_name, "a");
  if (log_file != NULL) {
	  fprintf (log_file, "\n\n-----------\n");
	  fprintf (log_file, "log started\n");
	  fprintf (log_file, "-----------\n\n");
  }
}

void close_log_file()
{
  if (log_file != NULL) {
    fclose(log_file);
    log_file = NULL;
  }
}

#define CONSOLE_BUFFER_SIZE 2048
char console_buffer[CONSOLE_BUFFER_SIZE];
char *next_console, *last_console;
int console_top, console_y;

void activate_console(void)
{
  gsdl_show_console = 1;
  next_console = console_buffer;
  *next_console = 0;
  last_console = next_console;
  console_y = console_top = text_rect.top +
    (text_rect.bottom - text_rect.top + 1) % line_spacing / 2;
  InvalidateRect(GSDL_Window,NULL,TRUE);
}

void deactivate_console(void)
{
  gsdl_show_console = 0;
  InvalidateRect(GSDL_Window,NULL,TRUE);
}

void refresh_console(HDC dc)
{
  int loc;  char *b, *e;
  loc = console_top;
  for (e = console_buffer;;) {
    b = e;
    while (*e >= ' ') ++e;
    TextOut(dc,0,loc,b,e-b);
    loc += line_spacing;
    if (*e == 0) break;
    ++e;
    if (*e == 0) break;
    }
}

void scroll(HDC dc, int nbits)
{
  RECT scroll, clip, update;

  scroll.left = clip.left = text_rect.left;
  scroll.right = clip.right = text_rect.right;
  clip.top = console_top;
  clip.bottom = text_rect.bottom;
  scroll.top = clip.top + nbits;
  scroll.bottom = text_rect.bottom;
  ScrollDC(dc,0,-nbits,&scroll,&clip,NULL,&update);
  FillRect(dc,&update, (HBRUSH)GetStockObject(WHITE_BRUSH));
}

int remove_line()
{
  char *bin, *bout;
  bin = bout = console_buffer;
  while (*bin >= ' ') ++bin;
  if (*bin != 0) {
    ++bin;
    if (*bin != 0) {
      while (*bin != 0) *bout++ = *bin++;
      *bout = *bin;
      last_console -= (bin - bout);
      next_console = bout;
      return line_spacing;
      }
    }
  next_console = console_buffer;
  *next_console = 0;
  last_console = next_console;
  return 0;
}

void display_line(HDC dc, char *line, int nch)
{
  int scroll_needed = 0;
  while (next_console + nch + 1 
         > console_buffer + CONSOLE_BUFFER_SIZE)
    scroll_needed += remove_line();
  console_y -= scroll_needed;
  if (*last_console == '\n') {
    console_y += line_spacing;
    if (console_y + line_spacing > text_rect.bottom) {
      scroll_needed += remove_line();
      console_y -= line_spacing;
      }
    last_console = next_console;
    }
  if (scroll_needed != 0) scroll(dc, scroll_needed);
  while (nch-- > 0) *next_console++ = *line++;
  TextOut(dc,0,console_y,last_console,next_console-last_console);
  *next_console = *line;
  if (*next_console != 0) {
    last_console = next_console;
    ++next_console;
    *next_console = 0;
    }
}

void display_text(HDC dc, char *buffer)
{
  char *bl, *bp;
  for (bl = buffer;;) {
    for (bp = bl;;) {
      if (*bp == '\t') *bp = ' ';
      if (*bp < ' ') break;
      ++bp;
      }
    if (*bp != 0) *bp = '\n';
    display_line(dc, bl, bp-bl);
    if (*bp == 0) break;
    bl = bp+1;
    if (*bl == 0) break;
    }
}

void log_message(char *msg)
{
  if (log_file != NULL) {
    fprintf(log_file,"%s",msg);
    fflush(log_file);
  }
  if (gsdl_show_console) {
    char buffer[1024];  HDC dc;
    sprintf(buffer,"%s",msg);
    dc = GetDC(GSDL_Window);
    display_text(dc,buffer);
    ReleaseDC(GSDL_Window,dc);
  }
}

void log_message_N(char*msg, int n)
{
  if (log_file != NULL) {
    int len = 0;
    while (len < n) {
      fputc (msg[len], log_file);
      ++len;
    }
    fflush(log_file);
  }
  
  // these messages are not send to the console
  if (gsdl_show_console) {
    HDC dc;
    dc = GetDC(GSDL_Window);
    display_text(dc,"message only written to log file\n");
    ReleaseDC(GSDL_Window,dc);
  }
}

void LogCriticalError(char *cderr, char *Msg)
{
  char MsgBoxStr[200];
  
  strcpy(MsgBoxStr, "Critical Error Number ");
  strcat(MsgBoxStr, cderr);
  strcat(MsgBoxStr, "\n");
  strcat(MsgBoxStr, Msg);
  strcat(MsgBoxStr, "\nGreenstone Digital Library software\nshutting down");
  MessageBox(GSDL_Window, MsgBoxStr, "Greenstone Digital Library Software",
	     MB_OK | MB_ICONERROR);
  PostMessage(GSDL_Window, WM_DESTROY, 0, 0);
}


/* returns second-first taking into account wrap around */
DWORD DiffTickCounts (DWORD first, DWORD second) 
{
  if (second >= first) return (second-first);
  return (MAXDWORD-first+1+second);
}
