/*
 *  MS-dependent world code
 */


#include <InterViews\itable.h>
#include <InterViews\bitmap.h>
#include <InterViews\canvas.h>
#include <InterViews\color.h>
#include <InterViews\font.h>
#include <InterViews\painter.h>
#include <InterViews\interact.h>
#include <InterViews\shape.h>
#include <InterViews\world.h>
#include <InterViews\X11\worldrep.h>
#include <InterViews\X11\eventrep.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

extern void InitSensors(), InitColors(), InitCursors (Color*, Color*);
extern HANDLE hInstance_, hPrevInstance_;

WorldRep* _world;
InteractorTable* _itable;

int saved_argc;
char** saved_argv;

void World::Init () {
    rep = new WorldRep;
    rep->_hinstance = hInstance_;
    rep->_hprevinstance = hPrevInstance_;
    rep->_root = GetDesktopWindow();
    rep->_cmap = nil;
    rep->_max_palette_entry = 0;
    SetCurrent();
    rep->_itable = new InteractorTable(2048);
    rep->_itable->Insert((void*)rep->root(), this);

    canvas = new Canvas((void*)rep->root());
    canvas->width  = GetDeviceCaps(rep->_hDC, HORZRES);
    canvas->height = GetDeviceCaps(rep->_hDC, VERTRES);
    canvas->status = CanvasMapped;

    xmax = canvas->width - 1;
    ymax = canvas->height - 1;

    double pixmm =
	(double(canvas->width)/(double(GetDeviceCaps(rep->_hDC, HORZSIZE))));
    cm     = round(10*pixmm);
    inch   = round(25.4*pixmm);
    inches = inch;
    point  = inch/72.27;
    points = point;

    InitColors();

    stdfont = new Font("SYSTEM_FONT");
    stdfont->Reference();

    stdpaint = new Painter();
    stdpaint->Reference();
#ifdef _3D
    stdpaint3D=new Painter3D(stdpaint);
    stdpaint3D->Reference();
#endif
}

void World::FinishInit () {
    SetCurrent();
    RootConfig();
    InitSensors();
    InitCursors(output->GetFgColor(), output->GetBgColor());
}

World::~World () {
    delete rep->_itable;
    delete rep;
}

void World::SaveCommandLine (int argc, char* argv[]) {
    saved_argc = argc;
    saved_argv = new char*[argc + 1];

    for (int i = 0 ; i < argc ; i++) {
	saved_argv[i] = argv[i];
    }
    saved_argv[i] = nil;
}

const char* World::UserDefaults () {
    return nil;
}

void World::FinishInsert (Interactor*) {
    /* nothing else to do */
}

void World::DoChange (Interactor* i) {
    Canvas* c = i->canvas;
    if (c != nil && c->status == CanvasMapped) {
	Shape* s = i->GetShape();
	if (c->width != s->width || c->height != s->height) {
	    Coord x, y;
	    i->GetOrigin(x, y);
	    if ((i->GetInteractorType() == ApplicationInteractor) ||
		(i->GetInteractorType() == ToplevelInteractor)) {
		MoveWindow(
		    (HWND)c->id,
		    x,
		    y - _world->YBorder -_world->YCaption,
		    s->width + _world->XBorder*2,
		    s->height + _world->YBorder*2 + _world->YCaption,
		    TRUE
		);
	    } else {
		MoveWindow((HWND)c->id, x, y, s->width, s->height, true);
	    }
	} else {
	    i->Resize();
	}
    }
}

void World::DoRemove (Interactor*) {
}

int World::Fileno () {
    return 0;
}

void World::SetCurrent () {
    _world = rep;
}

void World::SetRoot (void* r) {
    rep->_root = (HWND)r;
}

void World::SetScreen (int n) {
}

int World::NPlanes () {
    return GetDeviceCaps(rep->_hDC, PLANES);
}

int World::NButtons () {
    return 3;
}

int World::PixelSize () {
    return NPlanes();
}

const char* World::GetDefault (const char* name) {
    return GetAttribute(name);
}

const char* World::GetGlobalDefault (const char* name) {
    return GetAttribute(name);
}

unsigned World::ParseGeometry (
    const char* spec, Coord& x, Coord& y, unsigned int& w, unsigned int &h
) {
    char str[20];
    char *substr;
    char sign_x, sign_y;
    int  len;
    unsigned int values = GeomNoValue;

    if (spec[0] != '=') {
	return values;
    }
    strcpy(str, spec);

			/* Vorzeichen */
    if ((substr = strpbrk(str, "+-")) != NULL) {
	sign_x = *substr;
	if ((substr = strpbrk(++substr, "+-")) != NULL) {
	    sign_y = *substr;
	} else {
	    return values;
	}
    }

			/* Width */

    if ((substr = strtok(&str[1], "x+-"))  == NULL) {
	return values;
    } else {
	if ((w = atoi(substr)) != 0) {
	    values |= GeomWidthValue;
	}
    }

			/* Height */

    if ((substr = strtok(NULL, "x+-")) == NULL) {
	values = GeomNoValue;
	return values;
    } else {
	if ((h = atoi(substr)) != 0) {
	    values |= GeomHeightValue;
	}
    }

			/* x */

    if ((substr = strtok(NULL, "x+-")) == NULL) {
	return values;
    } else {
	if ((len = strspn(substr, "0123456789")) != 0) {
	    x = atoi(substr);
	    values |= GeomXValue;
	} else {
	    values |= GeomNoValue;
	    return values;
	}
	switch (sign_x) {
	    case '+':   break;
	    case '-': { values |= GeomXNegative;
			x = -x;
			break; }
	    default:  { values |= GeomNoValue;
			return values; }
	}
    }
			     /* y */

    if ((substr = strtok(NULL, "x+-")) == NULL) {
	values |= GeomNoValue;
	return values;
    } else {
	if ((len = strspn(substr, "0123456789")) != 0) {
	    y = atoi(substr);
	    values |= GeomYValue;
	} else {
	    values |= GeomNoValue;
	    return values;
	}
	switch (sign_y) {
	    case '+':   break;
	    case '-': { values |= GeomYNegative;
			y = -y;
			break; }
	    default:  { values |= GeomNoValue;
			return values; }
	}
    }
    return values;
}

void World::SetHint (const char* hint) {
}

void World::RingBell (int v) {
}

void World::SetKeyClick (int v) {
}

void World::SetAutoRepeat (boolean b) {
}

void World::SetFeedback (int t, int s) {
}

#ifdef _3D
void SetColorMap(unsigned long, class Canvas*) {
};
#endif
