/*
    Tucnak - VHF contest log
    Copyright (C) 2012-2020 Ladislav Vaiz <ok1zia@nagano.cz>

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    version 2 as published by the Free Software Foundation.

*/

#include "header.h"

#include "zosk.h"

#ifdef Z_HAVE_SDL

#include "kbd.h"
#include "main.h"
#include "qsodb.h"
#include "terminal.h"
#include "tsdl.h"

#define sdlkey(key) case key: strcat(s, #key); break

#define ZOSK_KEYY (zosk->font_h + 10 + 10)
#define ZOSK_LEFT ((SDL_Keycode)-10)
#define ZOSK_RIGHT ((SDL_Keycode)-11)
#define ZOSK_TP_CENTER 0
#define ZOSK_TP_LEFT 1
#define ZOSK_TP_RIGHT 2

char *zosk_sym2text(struct zosk *zosk, struct zosk_key *key, SDL_Keycode sym){
	static char txt[5];
	
    switch ((int)sym){
	    case SDLK_LSHIFT:    key->isshift = 1; zosk->shift = key; return "SH";
        case SDLK_LCTRL:     key->isshift = 1; zosk->ctrl = key;  return "Ctrl";
		case SDLK_LALT:      key->isshift = 1; zosk->alt = key;   return "Alt";
        case SDLK_MODE:      key->isshift = 1; zosk->fn = key;    return "\x0f";
        case SDLK_BACKSPACE: return "BSP";								  
        case SDLK_ESCAPE:    zosk->esc = key; return "Esc";
        case SDLK_TAB:       return "TAB";
        case SDLK_RETURN:    return "ENT";
        case SDLK_SPACE:     return "___";
        case SDLK_0:         return "0"; 
		case SDLK_F10:		 return "F10";
		case ZOSK_LEFT:      return "\x1b";
		case ZOSK_RIGHT:     return "\x1a";
        default:
            if (sym > 32 && sym < 256){
                g_snprintf(txt, 3, "%c", sym);
				return txt;
            }
            if (sym >= SDLK_F1 && sym <= SDLK_F9){
                g_snprintf(txt, 4, "F%d", sym - SDLK_F1 + 1);
				return txt;
            }
			return "";
    }

}

struct zosk_key *zosk_key_add(struct zosk *zosk, int w2, SDL_Keycode sym, SDL_Keycode symFn, SDL_Keycode symShift){
    struct zosk_key *key = g_new0(struct zosk_key, 1);

    key->x = zosk->x0 + (zosk->x2 * zosk->bw2 * 2) / 2;
    key->w = zosk->bw2 * w2 - 4;
    key->y = zosk->y0 + zosk->y * zosk->bh + ZOSK_KEYY;
    key->h = zosk->bh - 4;
    key->cx = key->x + key->w / 2;
    key->cy = key->y + key->h / 2;
    key->sym = sym;
    key->symFn = symFn;
	key->symShift = symShift;

	strcpy(key->text, zosk_sym2text(zosk, key, key->sym));
	strcpy(key->textFn, zosk_sym2text(zosk, key, key->symFn));
	strcpy(key->textShift, zosk_sym2text(zosk, key, key->symShift));


    g_ptr_array_add(zosk->keys, key);
    zosk->x2 += w2;
    return key;
}

static void zosk_move(struct zosk *zosk){
	switch (cfg->touchpos){
		case ZOSK_TP_LEFT:
			zosk->parent_x = 0;
			break;
		case ZOSK_TP_RIGHT:
			zosk->parent_x = zosk->screen_w - zosk->surface->w;
			break;
		case ZOSK_TP_CENTER:
			zosk->parent_x = (zosk->screen_w - zosk->surface->w) / 2;
		default:
			break;
	}

}

struct zosk *zosk_init(SDL_Surface *screen, int flags, const char *text){
    struct zosk *zosk;
	int w = screen->w;
	int h = screen->h;
    int spypeers = 0;

    //dbg("zosk_init(%d, '%s')\n", flags, text);
	zosk = g_new0(struct zosk, 1);

    w -= 10;
    //h -= 10;
	if (ctest && !ctest->oldcontest) spypeers = ctest->spypeers->len;
    //h = zsdl->font_h * (term->y - cfg->loglines - spypeers - DISP_QSOS - 2);
	h = (sdl->screen->h / FONT_H) * FONT_H + zsdl->font_h * ( - cfg->loglines - spypeers - DISP_QSOS - 1);
    //log_addf("window_h=%d  FONT_H=%d  font_h=%d  h=%d\n", sdl->screen->h, FONT_H, zsdl->font_h, h);
    zosk->KX2 = 21;
    zosk->KY = 5;
	zosk->font_h = 48;//zsdl_max_font_h(zosk->bw2 * 2 - 2, zosk->bh / 2, "M");//32;
	zosk->font_w = zsdl_h2w(zosk->font_h);
	zosk->bw2 = Z_MIN((w * 2) / zosk->KX2, (h - 4 - ZOSK_KEYY) / zosk->KY) / 2;
    //log_addf("MIN(%d, %d) = %d",(w * 2) / zosk->KX2, (h - 20 - ZOSK_KEYY) / zosk->KY, zosk->bw2); 
    zosk->bh = zosk->bw2 * 2;
    zosk->x0 = 10;//(w - 1 - zosk->bw4 * zosk->KX4) / 2;
    zosk->y0 = 0;//h - 1 - zosk->bh * zosk->KY;
    zosk->keys = g_ptr_array_new();
	zosk->bbg = z_makecol(128, 128, 128);
	zosk->bg = z_makecol(48, 48, 48);
	zosk->flags = flags;

	zosk->surface = SDL_CreateRGBSurface(SDL_SWSURFACE, zosk->bw2 * zosk->KX2 + 20, zosk->bh * zosk->KY + 4 + ZOSK_KEYY, screen->format->BitsPerPixel, 
                    screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, 0);

	zosk->screen_w = screen->w;
	zosk_move(zosk);
	zosk->parent_y = 0;//(screen->h - zosk->surface->h) / 2;
	
	

	zosk->gs = g_string_new(text);
	zosk->maxlen_c = (zosk->surface->w - 32 - zosk->font_h * 2) / zosk->font_w;

    zosk->x2 = 0;
    zosk->y = 0;
	zosk_key_add(zosk, 1, ZOSK_LEFT, SDLK_UNKNOWN, SDLK_UNKNOWN);
	zosk_key_add(zosk, 2, SDLK_1, SDLK_F1, SDLK_EXCLAIM);
    zosk_key_add(zosk, 2, SDLK_2, SDLK_F2, SDLK_AT);
	zosk_key_add(zosk, 2, SDLK_3, SDLK_F3, SDLK_HASH);
    zosk_key_add(zosk, 2, SDLK_4, SDLK_F4, SDLK_DOLLAR);
	zosk_key_add(zosk, 2, SDLK_5, SDLK_F5, (SDL_Keycode)'%');
    zosk_key_add(zosk, 2, SDLK_6, SDLK_F6, SDLK_CARET);
    zosk_key_add(zosk, 2, SDLK_7, SDLK_F7, SDLK_AMPERSAND);
    zosk_key_add(zosk, 2, SDLK_8, SDLK_F8, SDLK_ASTERISK);			   
	zosk_key_add(zosk, 2, SDLK_9, SDLK_F9, SDLK_LEFTPAREN);
    zosk_key_add(zosk, 2, SDLK_0, SDLK_F10, SDLK_RIGHTPAREN);

    zosk->x2 = 0;
	zosk->y++;
	zosk_key_add(zosk, 2, SDLK_q, (SDL_Keycode)'~', SDLK_UNKNOWN);
    zosk_key_add(zosk, 2, SDLK_w, SDLK_EXCLAIM, SDLK_UNKNOWN);
    zosk_key_add(zosk, 2, SDLK_e, SDLK_AT, SDLK_UNKNOWN);
    zosk_key_add(zosk, 2, SDLK_r, SDLK_HASH, SDLK_UNKNOWN);
	zosk_key_add(zosk, 2, SDLK_t, SDLK_DOLLAR, SDLK_UNKNOWN);
	zosk_key_add(zosk, 2, SDLK_y, (SDL_Keycode)'%', SDLK_UNKNOWN);
	zosk_key_add(zosk, 2, SDLK_u, (SDL_Keycode)SDLK_CARET, SDLK_UNKNOWN);
	zosk_key_add(zosk, 2, SDLK_i, SDLK_AMPERSAND, SDLK_UNKNOWN);
	zosk_key_add(zosk, 2, SDLK_o, SDLK_ASTERISK, SDLK_UNKNOWN);
	zosk_key_add(zosk, 2, SDLK_p, SDLK_UNKNOWN, SDLK_UNKNOWN);
	zosk_key_add(zosk, 1, ZOSK_RIGHT, SDLK_UNKNOWN, SDLK_UNKNOWN);

    zosk->x2 = 0;
    zosk->y++;
    zosk_key_add(zosk, 3, SDLK_TAB, SDLK_UNKNOWN, SDLK_UNKNOWN);
	zosk_key_add(zosk, 2, SDLK_a, SDLK_UNDERSCORE, SDLK_UNKNOWN);
	zosk_key_add(zosk, 2, SDLK_s, SDLK_MINUS, SDLK_UNKNOWN);
    zosk_key_add(zosk, 2, SDLK_d, SDLK_PLUS, SDLK_UNKNOWN);
    zosk_key_add(zosk, 2, SDLK_f, SDLK_EQUALS, SDLK_UNKNOWN);
    zosk_key_add(zosk, 2, SDLK_g, SDLK_COLON, SDLK_UNKNOWN);
	zosk_key_add(zosk, 2, SDLK_h, SDLK_SEMICOLON, SDLK_UNKNOWN);
	zosk_key_add(zosk, 2, SDLK_j, SDLK_QUOTE, SDLK_UNKNOWN);
	zosk_key_add(zosk, 2, SDLK_k, SDLK_QUOTEDBL, SDLK_UNKNOWN);
    zosk_key_add(zosk, 2, SDLK_l, SDLK_UNKNOWN, SDLK_UNKNOWN);
    
    zosk->x2 = 0;
    zosk->y++;
    zosk_key_add(zosk, 2, SDLK_ESCAPE, SDLK_UNKNOWN, SDLK_UNKNOWN);
	zosk_key_add(zosk, 2, SDLK_LSHIFT, SDLK_UNKNOWN, SDLK_UNKNOWN);
	zosk_key_add(zosk, 2, SDLK_z, SDLK_LEFTPAREN, SDLK_UNKNOWN);
	zosk_key_add(zosk, 2, SDLK_x, SDLK_RIGHTPAREN, SDLK_UNKNOWN);
    zosk_key_add(zosk, 2, SDLK_c, SDLK_LESS, SDLK_UNKNOWN);
    zosk_key_add(zosk, 2, SDLK_v, SDLK_GREATER, SDLK_UNKNOWN);
	zosk_key_add(zosk, 2, SDLK_b, SDLK_LEFTBRACKET, SDLK_UNKNOWN);
	zosk_key_add(zosk, 2, SDLK_n, SDLK_RIGHTBRACKET, SDLK_UNKNOWN);
	zosk_key_add(zosk, 2, SDLK_m, SDLK_COMMA, SDLK_UNKNOWN);
    zosk_key_add(zosk, 3, SDLK_BACKSPACE, SDLK_UNKNOWN, SDLK_UNKNOWN);
	                    
    zosk->x2 = 0;
    zosk->y++;
	zosk_key_add(zosk, 2, SDLK_LCTRL, SDLK_UNKNOWN, SDLK_UNKNOWN);
	zosk_key_add(zosk, 2, SDLK_MODE, SDLK_UNKNOWN, SDLK_UNKNOWN);
    zosk_key_add(zosk, 2, SDLK_LALT, SDLK_UNKNOWN, SDLK_UNKNOWN);
    zosk_key_add(zosk, 6, SDLK_SPACE, SDLK_UNKNOWN, SDLK_UNKNOWN);
	zosk_key_add(zosk, 2, SDLK_QUESTION, SDLK_UNKNOWN, SDLK_UNKNOWN);
	zosk_key_add(zosk, 2, SDLK_PERIOD, (SDL_Keycode)'|', SDLK_UNKNOWN);
	zosk_key_add(zosk, 2, SDLK_SLASH, SDLK_BACKSLASH, SDLK_UNKNOWN);
    zosk_key_add(zosk, 3, SDLK_RETURN, SDLK_UNKNOWN, SDLK_UNKNOWN);
    return zosk;
}


void zosk_free(struct zosk *zosk){
	int i;
	for (i = 0; i < zosk->keys->len; i++){
        struct zosk_key *key = (struct zosk_key *)g_ptr_array_index(zosk->keys, i);  
		g_free(key);
	}
	g_ptr_array_free(zosk->keys, TRUE);
	SDL_FreeSurface(zosk->surface);
	g_string_free(zosk->gs, TRUE);
	g_free(zosk);
}

void zosk_draw_key_text(struct zosk *zosk, struct zosk_key *key){
	SDL_Rect r;
	char *c = key->text;
	int color, fh;

	
	if (zosk->fn->pressed && key->symFn != SDLK_UNKNOWN) c = key->textFn; 
	if (zosk->shift->pressed && key->symShift != SDLK_UNKNOWN) c = key->textShift; 
	fh = zsdl_max_font_h(key->w - 2, key->h - 2, c);
	color = z_makecol(255, 255, 255);

	switch ((int)key->sym){
		case SDLK_LSHIFT:
			r.x = key->cx - (int)(0.2 * fh);
			r.w = 0.4 * fh + 1;
			r.y = key->cy + (int)(0.1 * fh);
			r.h = 0.1 * fh + 1;
			SDL_FillRect(zosk->surface, &r, color);
			r.x = key->cx - (int)(0.2 * fh);
			r.w = 0.4 * fh + 1;
			r.y = key->cy + (int)(0.3 * fh);
			r.h = 0.1 * fh + 1;
			SDL_FillRect(zosk->surface, &r, color);

			z_triangle(zosk->surface, 
				key->cx - (int)(0.4 * fh), key->cy + (int)(0.1 * fh),
				key->cx + (int)(0.4 * fh), key->cy + (int)(0.1 * fh),
				key->cx, key->cy - (int)(0.3 * fh), color);
			break;
		case SDLK_BACKSPACE: 
			r.x = key->cx - (int)(0.4 * fh);
			r.w = (int)(1.2 * fh);
			r.y = key->cy - (int)(0.4 * fh);
			r.h = (int)(0.8 * fh) + 1;
			SDL_FillRect(zosk->surface, &r, color);
			z_triangle(zosk->surface,
				key->cx - (int)(0.4 * fh), key->cy - (int)(0.4 * fh),
				key->cx - (int)(0.4 * fh), key->cy + (int)(0.4 * fh),
				key->cx - (int)(0.8 * fh), key->cy, color);
			zsdl_printf(zosk->surface, key->cx + (int)(0.1 * fh), key->cy - 1, zosk->bbg, 0, 
				ZFONT_CENTERX | ZFONT_CENTERY | ZFONT_TRANSP | ZFONT_USERH(fh),
				"x");
			break;
		case SDLK_TAB:    
			z_line(zosk->surface, key->cx - (int)(0.5 * fh), key->cy-1, key->cx + (int)(0.2 * fh), key->cy-1, color);
			z_line(zosk->surface, key->cx - (int)(0.5 * fh), key->cy, key->cx + (int)(0.2 * fh), key->cy, color);
			z_line(zosk->surface, key->cx - (int)(0.5 * fh), key->cy+1, key->cx + (int)(0.2 * fh), key->cy+1, color);
			z_triangle(zosk->surface,
				key->cx + (int)(0.2 * fh), key->cy - (int)(0.4 * fh),
				key->cx + (int)(0.2 * fh), key->cy + (int)(0.4 * fh),
				key->cx + 3* (int)(0.2 * fh), key->cy, color);
			/*z_putpixel(zosk->surface,key->cx + (int)(0.2 * fh), key->cy - (int)(0.4 * fh), sdl->red);
			z_putpixel(zosk->surface,key->cx + (int)(0.2 * fh), key->cy + (int)(0.4 * fh), sdl->red);
			z_putpixel(zosk->surface,key->cx + 3* (int)(0.2 * fh), key->cy, sdl->red);*/
			r.x = key->cx + 3* (int)(0.2 * fh) + 1;
			r.w = 2;
			r.y = key->cy - (int)(0.5 * fh);
			r.h = (int)(1 * fh);
			SDL_FillRect(zosk->surface, &r, color);
			break;
		case SDLK_RETURN:						

			z_triangle(zosk->surface,
				key->cx - (int)(0.4 * fh), key->cy - (int)(0.4 * fh),
				key->cx - (int)(0.4 * fh), key->cy + (int)(0.4 * fh),
				key->cx - (int)(0.8 * fh), key->cy, color);

			
			r.x = key->cx - (int)(0.4 * fh);
			r.w = 0.8 * fh;
			r.y = key->cy -1;
			r.h = 3;
			SDL_FillRect(zosk->surface, &r, color);
			r.x = key->cx + (int)(0.4 * fh);
			r.w = 3;
			r.y = key->cy - (int)(0.5 * fh);
			r.h = 0.5 * fh + 2;
			SDL_FillRect(zosk->surface, &r, color);
			break;
		case SDLK_SPACE:
			r.x = key->cx - (int)(0.6 * fh);
			r.w = 1.2 * fh;
			r.y = key->cy + (int)(0.4 * fh);
			r.h = 3;
			SDL_FillRect(zosk->surface, &r, color);
			r.x = key->cx - (int)(0.6 * fh) - 3;
			r.w = 3;
			r.y = key->cy + (int)(0.4 * fh) - 5;
			r.h = 8;
			SDL_FillRect(zosk->surface, &r, color);
			r.x = key->cx + (int)(0.6 * fh);
			r.w = 3;
			r.y = key->cy + (int)(0.4 * fh) - 5;
			r.h = 8;
			SDL_FillRect(zosk->surface, &r, color);
			break;

        default:
			if (strlen(c) == 1 && (zosk->shift->pressed || zosk->flags & ZOSK_UPCONVERT)) {
				char cc[2];
				cc[0] = toupper(c[0]);
				cc[1] = '\0';
				zsdl_printf(zosk->surface, key->cx, key->cy, z_makecol(255, 255, 255), 0, 
					ZFONT_CENTERX | ZFONT_CENTERY | ZFONT_TRANSP | ZFONT_USERH(fh),
					"%s", cc);
			}else{
				zsdl_printf(zosk->surface, key->cx, key->cy, z_makecol(255, 255, 255), 0, 
					ZFONT_CENTERX | ZFONT_CENTERY | ZFONT_TRANSP | ZFONT_USERH(fh),
					"%s", c);
			}
			break;
	}

}

void zosk_draw_key(struct zosk *zosk, struct zosk_key *key, int bbg){
    SDL_Rect r;
	int x, y;
	int bg2 = z_makecol((z_r(zosk->surface, bbg) * 3) / 4, (z_g(zosk->surface, bbg) * 3) / 4, (z_b(zosk->surface, bbg) * 3) / 4);
	

	r.x = key->x;
	r.y = key->y;
	r.w = key->w;
	r.h = key->h;
	SDL_FillRect(zosk->surface, &r, bbg);
	x = r.x;
	y = r.y;
	z_putpixel(zosk->surface, x, y, zosk->bg);
	z_putpixel(zosk->surface, x+1, y, zosk->bg);
	z_putpixel(zosk->surface, x+2, y, bg2);
	z_putpixel(zosk->surface, x, y+1, zosk->bg);
	z_putpixel(zosk->surface, x, y+2, bg2);
	x = r.x + r.w - 1;
	y = r.y;
	z_putpixel(zosk->surface, x, y, zosk->bg);
	z_putpixel(zosk->surface, x-1, y, zosk->bg);
	z_putpixel(zosk->surface, x-2, y, bg2);
	z_putpixel(zosk->surface, x, y+1, zosk->bg);
	z_putpixel(zosk->surface, x, y+2, bg2);
	x = r.x;
	y = r.y + r.h - 1;
	z_putpixel(zosk->surface, x, y, zosk->bg);
	z_putpixel(zosk->surface, x+1, y, zosk->bg);
	z_putpixel(zosk->surface, x+2, y, bg2);
	z_putpixel(zosk->surface, x, y-1, zosk->bg);
	z_putpixel(zosk->surface, x, y-2, bg2);
	x = r.x + r.w - 1;
	y = r.y + r.h - 1;
	z_putpixel(zosk->surface, x, y, zosk->bg);
	z_putpixel(zosk->surface, x-1, y, zosk->bg);
	z_putpixel(zosk->surface, x-2, y, bg2);
	z_putpixel(zosk->surface, x, y-1, zosk->bg);
	z_putpixel(zosk->surface, x, y-2, bg2);

	zosk_draw_key_text(zosk, key); 
}

void zosk_draw_top(struct zosk *zosk, struct zosk_key *key){
	char *c = key->text;
	int fh, fw;
	Uint32 Rmask, Gmask, Bmask, Amask;
	SDL_Surface *surface;
	int x, y, transp, half;
	SDL_Rect r;

	if (zosk->flags & ZOSK_IGNOREESC) return;

	if (zosk->fn->pressed && key->symFn != SDLK_UNKNOWN) c = key->textFn;
	if (zosk->shift->pressed && key->symShift != SDLK_UNKNOWN) c = key->textShift;
	fh = zsdl_max_font_h(key->w - 2, key->h - 2, c);
	fw = zsdl_h2w(fh);

	Rmask = Gmask = Bmask = Amask = 0 ; 
	if ( SDL_BYTEORDER == SDL_LIL_ENDIAN ) {
		Rmask = 0x000000FF;
		Gmask = 0x0000FF00;
		Bmask = 0x00FF0000;
		Amask = 0xFF000000;
	} else {
		Rmask = 0xFF000000;
		Gmask = 0x00FF0000;
		Bmask = 0x0000FF00;
		Amask = 0x000000FF;
	}
	surface = SDL_CreateRGBSurface(SDL_SWSURFACE, 10 + fw * strlen(c), 10 + fh, 32, Rmask, Gmask, Bmask, Amask);

	SDL_FillRect(surface, NULL, SDL_MapRGBA(surface->format, 150, 0, 0, 255)); // opaque

	// blit text/glyph to tooltip
	r.x = key->cx - surface->w / 2;
	r.w = key->w - 2;
	r.y = key->cy - surface->h / 2;
	r.h = key->h - 2;
	SDL_BlitSurface(zosk->surface, &r , surface, NULL);
	

	transp = SDL_MapRGBA(surface->format, 150, 0, 0, 0);
	half = SDL_MapRGBA(surface->format, 150, 0, 0, 128);

	
	x = 0;
	y = 0;
	z_putpixel32(surface, x, y, transp);
	z_putpixel32(surface, x+1, y, transp);
	z_putpixel32(surface, x+2, y, half);
	z_putpixel32(surface, x, y+1, transp);
	z_putpixel32(surface, x, y+2, half);
	x = surface->w - 1;
	y = 0;
	z_putpixel32(surface, x, y, transp);
	z_putpixel32(surface, x-1, y, transp);
	z_putpixel32(surface, x-2, y, half);
	z_putpixel32(surface, x, y+1, transp);
	z_putpixel32(surface, x, y+2, half);
	x = 0;
	y = surface->h - 1;
	z_putpixel32(surface, x, y, transp);
	z_putpixel32(surface, x+1, y, transp);
	z_putpixel32(surface, x+2, y, half);
	z_putpixel32(surface, x, y-1, transp);
	z_putpixel32(surface, x, y-2, half);
	x = surface->w - 1;
	y = surface->h - 1;
	z_putpixel32(surface, x, y, transp);
	z_putpixel32(surface, x-1, y, transp);
	z_putpixel32(surface, x-2, y, half);
	z_putpixel32(surface, x, y-1, transp);
	z_putpixel32(surface, x, y-2, half);
	
	//zosk_draw_key_text(zosk, key); TODO ruzne bitove konfigurace

	// blit prepared tooltip to keyboard
	r.x = (key->w - surface->w) / 2 + key->x;
	r.w = surface->w;
	r.y = key->y - surface->h - 3;
	r.h = surface->h;
	SDL_BlitSurface(surface, NULL, zosk->surface, &r);



	SDL_FreeSurface(surface);
}


void zosk_draw(struct zosk *zosk){
    int i;
	SDL_Rect r;
	char *c;

	SDL_FillRect(zosk->surface, NULL, zosk->bg);
	
    r.x = 32;
	r.y = 10;
	r.w = zosk->maxlen_c * zosk->font_w;
	r.h = zosk->font_h;
	SDL_FillRect(zosk->surface, &r, z_makecol(192, 192, 192));
	c = zosk->gs->str;
	if (strlen(c) >= zosk->maxlen_c) c += strlen(c) - zosk->maxlen_c + 1;
	zsdl_printf(zosk->surface, 32, 10, z_makecol(0, 0, 0), 0, ZFONT_TRANSP | ZFONT_USERH(zosk->font_h), "%s", c);
	zsdl_printf(zosk->surface, 32 + strlen(c) * zosk->font_w, 10, 0, sdl->cursor, ZFONT_USERH(zosk->font_h), " ");

	r.w = ZOSK_KEYY - 6;//(zosk->font_h * 3) / 2;
	r.h = ZOSK_KEYY - 6;//(zosk->font_h * 3) / 2;
	r.x = zosk->surface->w - r.w - 2;
	r.y = 2;
	SDL_FillRect(zosk->surface, &r, z_makecol(192, 192, 192));
	zsdl_printf(zosk->surface, r.x + r.w/2, r.y + r.h / 2, z_makecol(0, 0, 0), 0, ZFONT_CENTERX | ZFONT_CENTERY | ZFONT_TRANSP | ZFONT_USERH(zosk->font_h), "x");

	for (i = 0; i < zosk->keys->len; i++){
        struct zosk_key *key = (struct zosk_key *)g_ptr_array_index(zosk->keys, i);  
		int color = key == zosk->active || key->pressed ? z_makecol(150, 0, 0) : zosk->bbg;
		if (key->pressed == 2) color = z_makecol(0, 75, 150);
		if (zosk->flags & ZOSK_IGNOREESC) color = zosk->bbg;
		zosk_draw_key(zosk, key, color);
		if (key == zosk->active && key->pressed != 2) zosk_draw_top(zosk, key);
    }
}

int zosk_send(struct zosk *zosk){
	SDL_Event ev;
	int i;
	struct zosk_key *key = zosk->sent;

	memset(&ev, 0, sizeof(ev));
	ev.type = SDL_KEYDOWN;
	ev.key.keysym.mod = KMOD_NONE;
	if (zosk->ctrl->pressed) ev.key.keysym.mod = KMOD_LCTRL;
    if (zosk->alt->pressed) ev.key.keysym.mod = KMOD_LALT;
    if (zosk->shift->pressed) ev.key.keysym.mod = KMOD_LSHIFT;
	ev.key.keysym.scancode = 1;
	ev.key.keysym.sym = key->sym;
	if (zosk->fn->pressed && key->symFn != SDLK_UNKNOWN) ev.key.keysym.sym = key->symFn;
	if (zosk->shift->pressed && key->symShift != SDLK_UNKNOWN) ev.key.keysym.sym = key->symShift;
#ifdef Z_HAVE_SDL1
	ev.key.keysym.unicode = 0;
	ev.key.which = 0;
#endif
	ev.key.state = SDL_PRESSED;
	SDL_PushEvent(&ev);
    //dbg("push %d\n", ev.key.keysym.sym);

	if (!zosk->ctrl->pressed && !zosk->alt->pressed){
		if (ev.key.keysym.sym >= ' ' && ev.key.keysym.sym < 128){
			if (zosk->shift->pressed || (zosk->flags & ZOSK_UPCONVERT))
				g_string_append_c(zosk->gs, z_char_uc((char)ev.key.keysym.sym));
			else
				g_string_append_c(zosk->gs, (char)ev.key.keysym.sym);

		}
		if (ev.key.keysym.sym == SDLK_BACKSPACE && zosk->gs->len > 0){
			g_string_erase(zosk->gs, zosk->gs->len - 1, 1);
		}
		if (ev.key.keysym.sym == SDLK_RETURN && (zosk->flags & ZOSK_CLEARENTER)){
			g_string_truncate(zosk->gs, 0);
		}
	}

	if (!key->isshift){
		for (i = 0; i < zosk->keys->len; i++){
			struct zosk_key *key2 = (struct zosk_key *)g_ptr_array_index(zosk->keys, i);  
			if (key2 == zosk->shift && key2->pressed == 2) continue;
			if (key2 == zosk->fn && key2->pressed == 2) continue;
			key2->pressed = 0;
		}
		zosk->shifts_active = 0;
	}else{
        if (!key->pressed){
            key->pressed = 1;
            zosk->shifts_active++;
        }else{
			if ((key == zosk->shift || key == zosk->fn) && key->pressed == 1){
				key->pressed = 2;
			}else{
				key->pressed = 0;
				zosk->shifts_active--;
				zosk->active = NULL;
			}
        }
    }
	return 0;
}

void zosk_repeat(void *arg){
	struct zosk *zosk = (struct zosk*)arg;
	//int closesize = (zosk->font_h * 3) / 2;

	zosk_send(zosk);
	zosk->repeat_timer_id = zselect_timer_new(zsel, 20*2, zosk_repeat, zosk);

}

int zosk_click(struct zosk *zosk, int x, int y, int pressed){
    int i;
	int closesize = (zosk->font_h * 3) / 2;

//    int white = z_makecol(255, 255, 255);
	struct zosk_key *oldactive = zosk->active;
	
	//int bg = z_makecol(0, 0, 0);
	//int bg2 = z_makecol(76, 76, 76);

	if (zosk->active && zosk->active->isshift == 0){
		//zosk_draw_key(zosk, zosk->active, zosk->bbg);
		zosk->active = NULL;
	}

	if (x >= zosk->surface->w - closesize && y >- 0 && y < closesize ){
		x = zosk->esc->x;
		y = zosk->esc->y;
		zosk->flags |= ZOSK_ENTERCLOSE;
		zosk->flags |= ZOSK_IGNOREESC;
	}
	
    for (i = 0; i < zosk->keys->len; i++){
        struct zosk_key *key = (struct zosk_key *)g_ptr_array_index(zosk->keys, i);  
		if (x < key->x) continue;
		if (y < key->y) continue;
		if (x >= key->x + key->w) continue;
		if (y >= key->y + key->h) continue;
		if (pressed){
			//zosk_draw_key(zosk, key, z_makecol(150, 0, 0));
			zosk->active = key;
			zosk->sent = key;
			if (zosk->repeat_timer_id) zselect_timer_kill(zsel, zosk->repeat_timer_id);
			//zosk->repeat_timer_id = zselect_timer_new(zsel, 500/*300*/, zosk_repeat, zosk);
		}else{
			if (zosk->repeat_timer_id) {
				zselect_timer_kill(zsel, zosk->repeat_timer_id);
				zosk->repeat_timer_id = 0;
			}
			if (key == oldactive){
              //  dbg("key==oldactive isshift=%d key->pressed=%d\n", key->isshift, key->pressed);

				if (key->sym == ZOSK_LEFT){
					if (cfg->touchpos == ZOSK_TP_CENTER) cfg->touchpos = ZOSK_TP_LEFT;
					if (cfg->touchpos == ZOSK_TP_RIGHT) cfg->touchpos = ZOSK_TP_CENTER;
					zosk_move(zosk);
					sdl_force_redraw();
					break;
				}
				if (key->sym == ZOSK_RIGHT){
					if (cfg->touchpos == ZOSK_TP_CENTER) cfg->touchpos = ZOSK_TP_RIGHT;
					if (cfg->touchpos == ZOSK_TP_LEFT) cfg->touchpos = ZOSK_TP_CENTER;
					zosk_move(zosk);
					sdl_force_redraw();
					break;
				}

				zosk_send(zosk);
			}
		}
		redraw_later();
		return 0;
	}
	//sdl_force_redraw();
    //dbg("ctrl:          isshift=%d key->pressed=%d\n", zosk->ctrl->isshift, zosk->ctrl->pressed);
    //dbg("shift:         isshift=%d key->pressed=%d\n", zosk->shift->isshift, zosk->shift->pressed);
    //dbg("alt:           isshift=%d key->pressed=%d\n", zosk->alt->isshift, zosk->alt->pressed);
	redraw_later();
	return 1;
}

void zosk_clear(struct zosk *zosk){
	g_string_assign(zosk->gs, "");
}

void zosk_portrait(struct zosk *zosk){
    //dbg("zosk_portrait %d %d<%d\n", cfg->portrait, sdl->screen->w, sdl->screen->h);
	if (cfg->portrait && sdl->screen->w < sdl->screen->h){
		zosk->parent_y = sdl->screen->h - zosk->surface->h;
		gses->osk->flags &= ~ZOSK_ENTERCLOSE;
        //dbg("zosk_portrait parent_y=%d  zosk->surface->h=%d\n", zosk->parent_y, zosk->surface->h);
		resize_terminal(GINT_TO_POINTER(1));
	}
}

#endif
