/*
 * common_sh.c
 *
 * Copyright (c) 1994 Software Research Associates, Inc.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee is hereby granted, provided
 * that the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation, and that the name of Software Research Associates not be
 * used in advertising or publicity pertaining to distribution of the
 * software without specific, written prior permission.  Software Research
 * Associates makes no representations about the suitability of this software
 * for any purpose.  It is provided "as is" without express or implied
 * warranty.
 */


#include "tb.h"
#include "wndproc.h"
#include "util.h"
#include "tcl.h"
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <fcntl.h>
#include <errno.h>
#include <direct.h>

#ifndef MAXPATHLEN
#   ifdef PATH_MAX
#       define MAXPATHLEN PATH_MAX
#   else
#       define MAXPATHLEN 2048
#   endif
#endif
#define MAX_TITLE 1024

extern HWND CreateTerminal(HANDLE);
extern unsigned int Tcl_Main(int, char **, SOCKET);
extern void	compat_exit(int);

static HWND hConsoleWnd;
static int newconsole = 0;
static int iconic = 0;
static CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
static char oldTitle[MAX_TITLE];
static int _hasWindows;
static void Exit(void);

static void
CreateNewConsole() {
    FreeConsole();
    AllocConsole();
}

int
common_tclsh(int argc, char **argv, int hasWindows, int useSocket, char *consoleTitle)
{
    HANDLE hInstance = NULL, hPrevInstance = NULL;
    HWND hTerm, hwnd;
    WPARAM result;
    HINSTANCE hLib;
    HHOOK hHook;
    HANDLE hStdout;
    COORD bufSize = {80, 200};
    char tmpName[MAX_TITLE];
    char title[MAX_TITLE];
    char *s;
    int match, prefixlen, suffix;
    WORD wVersionRequested;
    WSADATA wsaData;
    int err;
    int i, j, len;
    char c, save;
    char *bp;
    char currdir[MAXPATHLEN+1];
    static char argv0_dir[MAXPATHLEN+1];
    extern void forkexec_setargv0_dir(char *);

    _hasWindows = hasWindows;
    /* Convert backslashes to slashes */
    for (bp = argv[0]; *bp != '\0'; bp++) {
	if (*bp == '\\') {
	    *bp = '/';
	}
    }
	
    /* Extract the directory from argv[0] */
    len = strlen(argv[0]);
    for (i = len; i >= 0; i--) {
	c = argv[0][i];
	if (c == '/') {
	    break;
	}
    }
    i++;
    if (i == 0) {
	if (len >= 3 && argv[0][1] == ':') {
	    i = 2;
	}
    }

    if (i > 0) {
	save = argv[0][i];
	argv[0][i] = '\0';

	if (compat_getcwd(currdir, MAXPATHLEN+1) == NULL) {
	    panic("Unable to get working directory.");
	}
	if (chdir(argv[0]) == -1) {
	    panic("Unable to cd to %s\n", argv[0]);
	}
	if (compat_getcwd(argv0_dir, MAXPATHLEN+1) == NULL) {
	    panic("Unable to get working directory.");
	}
	if (chdir(currdir) == -1) {
	    panic("Unable to cd to %s\n", currdir);
	}
	argv[0][i] = save;
	len = strlen(argv0_dir);
	argv0_dir[len] = '/';
	argv0_dir[len+1] = '\0';
    } else {
	argv0_dir[0] = '\0';
    }

    forkexec_setargv0_dir(argv0_dir);

    for (i = 0; i < argc; i++) {
	if (strcmp(argv[i], "-console") == 0) {
	    newconsole = 1;
	    for (j = i + 1; j < argc; j++) {
		argv[j-1] = argv[j];
	    }
	    argv[j-1] = NULL;
	    i--; argc--;
	} else if (strcmp(argv[i], "-iconic") == 0) {
	    iconic = 1;
	    for (j = i + 1; j < argc; j++) {
		argv[j-1] = argv[j];
	    }
	    argv[j-1] = NULL;
	    i--; argc--;
	}
    }

    if (newconsole) {
	CreateNewConsole();
    }

    if (useSocket) {
	wVersionRequested = MAKEWORD(1, 1);
	err = WSAStartup(wVersionRequested, &wsaData);
	if (err != 0) {
	    panic("Could not find a useable winsock.dll\n");
	}
    }

    set_useSocket(useSocket);

    if (hasWindows) {
	SetAppInstance(hInstance);

	if (!hPrevInstance) {
	    RegisterWidgetClass(hInstance);	
	    RegisterTopLevelClass(hInstance);
	    RegisterTerminalClass(hInstance);
	}

	hTerm = CreateTerminal(hInstance);  
	SetPostWindow(hTerm);
    }

    if (hasWindows) {
#ifdef KANJI
	hLib = LoadLibrary("kxlib.dll");
#else
	hLib = LoadLibrary("lxlib.dll");
#endif

	hHook = SetWindowsHookEx(WH_MOUSE, 
				 (HOOKPROC)GetProcAddress(hLib, (LPCSTR)"DeliverEnterLeave"), 
				 hLib, (DWORD) NULL); 
	SetHookDeliverEL(hHook);
	FreeLibrary(hLib);
    }

    if (hasWindows) {
	hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
	GetConsoleScreenBufferInfo(hStdout, &consoleInfo);
	SetConsoleScreenBufferSize(hStdout, bufSize);

	GetConsoleTitle(oldTitle, MAX_TITLE);

	/* Get a Window handle for our console */
	s = "lr&gc";
	strcpy(tmpName, s);
	prefixlen = strlen(tmpName);

	for (suffix = 0; ; suffix++) {
	    match = 0;
	    itoa(suffix, &tmpName[prefixlen], 10);

	    len = strlen(tmpName);
	    SetConsoleTitle(tmpName);
	    for (hwnd = GetWindow(hTerm, GW_HWNDFIRST); IsWindow(hwnd);
		 hwnd = GetWindow(hwnd, GW_HWNDNEXT))
	    {
		if (GetWindowText(hwnd, title, MAX_TITLE) == len) {
		    if (strcmp(title, tmpName) == 0) {
			match++;
			hConsoleWnd = hwnd;
		    }
		}
	    }

	    if (match == 1) {
		break;
	    }
	}

	SetConsoleTitle(consoleTitle);
	if (iconic) {
	    SendMessage(hConsoleWnd, WM_SYSCOMMAND, SC_MINIMIZE, 0L);
	}
    }

    atexit(Exit);
    result = Tcl_Main(argc, argv, useSocket);
    compat_exit(result);
    /* NOTREACHED */
    return 0;
}

void
Exit(void)
{
    HANDLE hStdout;

    if (_hasWindows) {
	hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
	DestroyTclTerminal();
	SetConsoleScreenBufferSize(hStdout, consoleInfo.dwSize);
	SetConsoleTitle(oldTitle);
    }

    return;
}

    
