/*
 * winboard-4.2.6.0-ru
 *
 * wclipbrd.c -- Clipboard routines for WinBoard
 * $Id: wclipbrd.c,v 1.4 2000-05-03 18:12:00-07 default Exp default $
 *
 * Copyright 2000 Free Software Foundation, Inc.
 * Russian menu and dialogs Copyright 2003 A.V.Serdukov.
 *
 * ------------------------------------------------------------------------
 * 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 "config.h"

#include <windows.h>   /* required for all Windows applications */
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <io.h>
#include <sys/stat.h>

#include "common.h"
#include "winboard.h"
#include "frontend.h"
#include "backend.h"
#include "wclipbrd.h"

/* Imports from winboard.c */
extern HWND hwndMain;

/* File globals */
static char *copyTemp;
static char *pasteTemp;

VOID 
CopyFENToClipboard()
{
  char *fen = NULL;

  fen = PositionToFEN(currentMove);
  if (!fen) {
    DisplayError("Невозможно преобразовать позицию в формат FEN.", 0); //"Unable to convert position to FEN."
    return;
  }
  if (!CopyTextToClipboard(fen))
      DisplayError("Невозможно скопировать позицию (FEN) в буфер обмена", 0); //"Unable to copy FEN to clipboard."
  free(fen);
}


VOID
CopyGameToClipboard()
{
  /* A rather cheesy hack here. Write the game to a file, then read from the
   * file into the clipboard.
   */
  char *buf = NULL;
  FILE *f;
  unsigned long size;
  size_t len;
  struct stat st;

  if (!copyTemp) {
    copyTemp = tmpnam(NULL);
  }
  if (!copyTemp) {
      DisplayError("Ошибка при создании имени временного файла.",0); //"Cannot create temporary file name."
      return;
  }
  f = fopen(copyTemp, "w"); 
  if (!f) {
    DisplayError("Не могу открыть временный файл.", 0); //"Cannot open temporary file."
    return;
  }
  if (!SaveGame(f,0,"")) { 			/* call into backend */
    DisplayError("Не могу записать во временный файл.", 0); //"Cannot write to temporary file."
    goto copy_game_to_clipboard_cleanup;
  }
  f = fopen(copyTemp, "rb");
  if (!f) {
    DisplayError("Не могу открыть вновь временный файл.", 0); //"Cannot reopen temporary file."
    goto copy_game_to_clipboard_cleanup;
  }
  if (fstat(fileno(f), &st) < 0) {
    DisplayError("Не могу определить размер файла.", 0); //"Cannot determine size of file."
    goto copy_game_to_clipboard_cleanup;
  }
  size = st.st_size;
  if (size == -1) {
    DisplayError("Не могу определить размер файла.", 0); //"Cannot determine size of file."
    goto copy_game_to_clipboard_cleanup;
  }
  rewind(f);
  buf = (char*)malloc(size+1);
  if (!buf) {
    DisplayError("Нет памяти для открытия буфера обмена", 0); //"Cannot allocate clipboard buffer."
    goto copy_game_to_clipboard_cleanup;
  }
  len = fread(buf, sizeof(char), size, f);
  if (len == -1) {
    DisplayError("Не могу прочитать временный файл.", 0); //"Cannot read from temporary file."
    goto copy_game_to_clipboard_cleanup;
  }
  if ((unsigned long)size != (unsigned long)len) { /* sigh */ 
      DisplayError("Ошибка при чтении временного файла.", 0); //"Error reading from temporary file."
      goto copy_game_to_clipboard_cleanup;
  }
  buf[size] = 0;
  if (!CopyTextToClipboard(buf)) {
      DisplayError("Невозможно скопировать текст в буфер обмена.", 0); //"Cannot copy text to clipboard"
  }

copy_game_to_clipboard_cleanup:
  if (buf) free(buf);
  if (f) fclose(f);
}


int 
CopyTextToClipboard(char *text)
{
  /* some (most?) of the error checking may be overkill, 
   * but hey, this is Windows 
   */
  HGLOBAL hGlobalMem;
  LPVOID lpGlobalMem;
  BOOL locked;
  UINT lockCount;
  DWORD err;

  hGlobalMem = GlobalAlloc(GHND, (DWORD)lstrlen(text)+1);
  if (hGlobalMem == NULL) {
    DisplayError("Недостаточно памяти для буфера обмена.", 0); //"Unable to allocate memory for clipboard."
    return FALSE;
  }
  lpGlobalMem = GlobalLock(hGlobalMem);
  if (lpGlobalMem == NULL) {
    DisplayError("Невозможно заблокировать память буфера обмена.", 0); //"Unable to lock clipboard memory."
    GlobalFree(hGlobalMem);
    return FALSE;
  }
  lstrcpy(lpGlobalMem, text);
  if (appData.debugMode) {
    lockCount = GlobalFlags(hGlobalMem) & GMEM_LOCKCOUNT;
    fprintf(debugFP, "CopyTextToClipboard(): lock count %d\n", lockCount);
  }
  SetLastError(NO_ERROR);
  locked = GlobalUnlock(hGlobalMem);
  err = GetLastError();
  if (appData.debugMode) {
    lockCount = GlobalFlags(hGlobalMem) & GMEM_LOCKCOUNT;
    fprintf(debugFP, "CopyTextToClipboard(): lock count %d\n", lockCount);
  }
  if (!locked) {
    locked = !((err == NO_ERROR) || (err == ERROR_NOT_LOCKED));
    if (appData.debugMode) {
      fprintf(debugFP, 
	      "CopyTextToClipboard(): err %d locked %d\n", err, locked);
    }
  }
  if (locked) {
    DisplayError("Невозможно разблокировать память буфера обмена.", 0); //"Cannot unlock clipboard memory."
    GlobalFree(hGlobalMem);
    return FALSE;
  }
  if (!OpenClipboard(hwndMain)) {
    DisplayError("Не могу открыть буфер обмена.", 0); //"Cannot open clipboard."
    GlobalFree(hGlobalMem);
    return FALSE;
  }
  if (!EmptyClipboard()) {
    DisplayError("Невозможно освободить буфер обмена", 0); //"Cannot empty clipboard."
    return FALSE;
  }
  if (hGlobalMem != SetClipboardData(CF_TEXT, hGlobalMem)) {
    DisplayError("Невозможно скопировать текст в буфер обмена.", 0); //"Cannot copy text to clipboard."
    CloseClipboard();
    GlobalFree(hGlobalMem);
    return FALSE;
  }
  if (!CloseClipboard())
    DisplayError("Не могу закрыть буфер обмена.", 0); //"Cannot close clipboard."
  
  return TRUE;
}



VOID
PasteFENFromClipboard()
{
  char *fen = NULL;
  if (!PasteTextFromClipboard(&fen)) {
      DisplayError("Невозможно загрузить позицию (FEN) из буфера обмена.", 0); //"Unable to paste FEN from clipboard."
      return;
  }
  if (appData.debugMode) {
    fprintf(debugFP, "PasteFenFromClipboard(): fen '%s'\n", fen);
  }
  EditPositionPasteFEN(fen); /* call into backend */
  free(fen);
}


VOID
PasteGameFromClipboard()
{
  /* Write the clipboard to a temp file, then let LoadGameFromFile()
   * do all the work.  */
  char *buf;
  FILE *f;
  size_t len;
  if (!PasteTextFromClipboard(&buf)) {
    return;
  }
  if (!pasteTemp) {
    pasteTemp = tmpnam(NULL);
  }
  f = fopen(pasteTemp, "wb+");
  if (!f) {
    DisplayError("Невозможно создать временный файл.", 0); //"Unable to create temporary file."
    return;
  }
  len = fwrite(buf, sizeof(char), strlen(buf), f);
  fclose(f);
  if (len != strlen(buf)) {
    DisplayError("Ошибка записи во временный файл.", 0); //"Error writing to temporary file."
    return;
  }
  LoadGameFromFile(pasteTemp, 0, "Буфер обмена", TRUE); //"Clipboard"
}


int 
PasteTextFromClipboard(char **text)
{
  /* some (most?) of the error checking may be overkill, 
   * but hey, this is Windows 
   */
  HANDLE hClipMem;
  LPVOID lpClipMem;
  BOOL locked = FALSE;
  DWORD err;
  UINT lockCount;

  if (!OpenClipboard(hwndMain)) {
    DisplayError("Невозможно открыть буфер обмена.", 0); //"Unable to open clipboard."
    return FALSE;
  }
  hClipMem = GetClipboardData(CF_TEXT);
  if (hClipMem == NULL) {
    CloseClipboard();
    DisplayError("Нет текста в буфере обмена.", 0); //"No text in clipboard."
    return FALSE;
  }
  lpClipMem = GlobalLock(hClipMem);
  if (lpClipMem == NULL) {
    CloseClipboard();
    DisplayError("Невозможно заблокировать память буфера обмена.", 0); //"Unable to lock clipboard memory."
    return FALSE;
  }
  *text = (char *) malloc(GlobalSize(hClipMem)+1);
  if (!*text) {
    DisplayError("Нет памяти для записи строки.", 0); //"Unable to allocate memory for text string."
    CloseClipboard();
    return FALSE;
  }
  lstrcpy(*text, lpClipMem);
  if (appData.debugMode) {
    lockCount = GlobalFlags(hClipMem) & GMEM_LOCKCOUNT;
    fprintf(debugFP, "PasteTextFromClipboard(): lock count %d\n", lockCount);
  }
  SetLastError(NO_ERROR);
#if 1
  /*suggested by Wilkin Ng*/
  lockCount = GlobalFlags(hClipMem) & GMEM_LOCKCOUNT;
  if (lockCount) {
    locked = GlobalUnlock(hClipMem);
  }
#else
  locked = GlobalUnlock(hClipMem);
#endif
  err = GetLastError();
  if (appData.debugMode) {
    lockCount = GlobalFlags(hClipMem) & GMEM_LOCKCOUNT;
    fprintf(debugFP, "PasteTextFromClipboard(): lock count %d\n", lockCount);
  }
  if (!locked) {
    locked = !((err == NO_ERROR) || (err == ERROR_NOT_LOCKED));
    if (appData.debugMode) {
      fprintf(debugFP, 
	      "PasteTextFromClipboard(): err %d locked %d\n", err, locked);
    }
  }
  if (locked) 
    DisplayError("Невозможно разблокировать память буфера обмена.", 0); //"Unable to unlock clipboard memory."
  
  if (!CloseClipboard())
    DisplayError("Невозможно закрыть буфер обмена.", 0); //"Unable to close clipboard."
  
  return TRUE;
}

VOID
DeleteClipboardTempFiles()
{
  if (copyTemp) remove(copyTemp);
  if (pasteTemp) remove(pasteTemp);
}
