Logo Search packages:      
Sourcecode: tucnak2 version File versions  Download package

sdl.c

/*
    Tucnak - VHF contest log
    Copyright (C) 2002-2006  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"

#ifdef HAVE_SDL

void (*fast_putpixel)(SDL_Surface *surface, int x, int y, int color);
int (*fast_getpixel)(SDL_Surface *surface, int x, int y);
      
struct sdl *sdl;
SDL_Color pal[256];
static int dashcnt=0;

extern const unsigned char icon_tucnak[2036];

struct sdl *init_sdl(){
    int w,h;
    SDL_Rect r;
    char str[256];
      char errbuf[1024];
    
    if (opt_g && opt_t) {
        opt_t=opt_g=0;   /* user is crazy */
    }

    if (!opt_g && !opt_t){
        if (getenv("DISPLAY")!=NULL) opt_g=1;
    }else{
        if (opt_t) opt_g=0;
    }
    
    if (!opt_g) return NULL;

    
    
    sdl=g_new0(struct sdl, 1);
    
    sdl->iconv=iconv_open("ISO8859-2","UCS-2LE");
    if (sdl->iconv==(iconv_t)(-1)){
        int err=errno;
        dbg("Can't init iconv %s\n", strerror_r(err, errbuf, sizeof(errbuf)));
        free_sdl();
        return NULL;
    }
    
    
    setenv("SDL_VIDEO_X11_WMCLASS", "Tucnak", 1);
    if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE)){
 /*       log_addf(VTEXT(T_CANT_SET_GR_S), "SDL_Init"); not initialised here */
        log_addf("Can't set graphics mode (SDL_Init)");
        free_sdl();
        return NULL;
    };  
    SDL_EnableKeyRepeat(200, 20);
    SDL_EnableUNICODE(1);

    sdl->icon = do_png_create(icon_tucnak, sizeof(icon_tucnak));
    if (!sdl->icon) internal("Can't create icon_tucnak, currupted executable?");
    SDL_WM_SetIcon(sdl->icon, NULL);
    
    w=cfg->gfx_x;
    h=cfg->gfx_y;
    if (sdl_setvideomode(w, h, 1)){
        log_addf("Can't set graphics mode (SetVideoMode)");
        free_sdl(); 
        return NULL;
    }
    sdl->bpp = sdl->screen->format->BitsPerPixel;
    sdl->eventpipestate_mutex=g_mutex_new();
    
    strcpy(str, "Vydrj, pijajr...");
    fontout(sdl->screen, (w-strlen(str)*FONT_W)/2, h/2-FONT_H-4, makecol(255, 255, 255), 0, str);
    r.x=(w-32)/2;
    r.y=h/2+4;
    r.w=24;
    r.h=24;
    SDL_BlitSurface(sdl->icon, NULL, sdl->screen, &r);
    SDL_UpdateRect(sdl->screen, 0, 0, w, h);

        
    return sdl;
}

void sdl_stop_event_thread(){
    if (!sdl) return;
    if (!sdl->event_thread) return;
    sdl->event_thread_break=1;
    SDL_WaitThread(sdl->event_thread, NULL);
    sdl->event_thread=0;
}

void free_sdl(){
    if (!sdl) return;
    sdl_stop_event_thread();
    if (sdl->icon) SDL_FreeSurface(sdl->icon);
    if (sdl->screen) SDL_FreeSurface(sdl->screen);
    if (sdl->eventpipestate_mutex) g_mutex_free(sdl->eventpipestate_mutex);
    CONDGFREE(sdl->title);

    SDL_Quit();

    if (sdl->iconv) iconv_close(sdl->iconv);
    
    g_free(sdl);
    sdl=NULL;
}


void sdl_info(){
    SDL_Rect **modes;
    int i;
    const SDL_VideoInfo *vi;
    char str[256];
    int oldw, oldh;

    printf("\n  sdl_info:\n");
    if (SDL_Init(SDL_INIT_VIDEO)<0){
        printf("SDL_Init failed\n");
        return;
    };
    
    SDL_VideoDriverName(str, sizeof(str)-1);
    str[sizeof(str)-1]='\0';
    if (*str) printf("Driver: %s\n", str);
    
    vi=SDL_GetVideoInfo();
    if (!vi){
        printf("No \"best mode\" exists\n");
        return;
    }else{
        /*printf("\"Best mode\" is %d x %d, %dbpp ", vi->current_w, vi->current_h, vi->BitsPerPixel);*/
        printf("\"Best mode\" is %dbpp ", vi->vfmt->BitsPerPixel);
        if (vi->vfmt->palette){
            printf("using palette ");
        }else{
            printf("R=%08x G=%08x B=%08x A=%08x  ", vi->vfmt->Rmask, vi->vfmt->Gmask, vi->vfmt->Bmask, vi->vfmt->Amask);
        }
        printf("colorkey=%04x alpha=%d\n", vi->vfmt->colorkey, vi->vfmt->alpha);
    }
    
    
    modes=SDL_ListModes(NULL, SDL_FULLSCREEN);
    if (!modes) {
        printf("No video modes available (SDL_ListModes)\n");
    }else{
        if (modes==(SDL_Rect**)-1){
            printf("All resolutinons available\n");
            return;
        }
        
        oldw=oldh=-1;
        for (i=0;modes[i];i++){
            if (modes[i]->w==oldw && modes[i]->h==oldh) continue;
            printf(" %d x %d  %d bpp\n", modes[i]->w, modes[i]->h, vi->vfmt->BitsPerPixel);
            oldw=modes[i]->w;
            oldh=modes[i]->h;
        }
    }

    
}

int sdl_setvideomode(int w, int h, int init){
    int i;
    
    if (!init) sdl_stop_event_thread();
    
    /*dbg("w=%d h=%d  ", w, h);
    w=((int)(w/FONT_W))*FONT_W;
    h=((int)(h/FONT_H))*FONT_H;
    dbg("w=%d h=%d  \n", w, h); */

    if ((sdl->screen = SDL_SetVideoMode(w, h, 0, SDL_SWSURFACE|SDL_RESIZABLE|SDL_HWPALETTE))==NULL){
        dbg("SDL_SetVideoMode(%d,%d) failed\n", w, h);
        return 1;    
    }

    if (SDL_MUSTLOCK(sdl->screen)) internal("surface must be locked");
    
    sdl->termarea.x = 0;
    sdl->termarea.y = 0;
    sdl->termarea.w = w;
    sdl->termarea.h = h;
/*    if (sdl->title) free_rect(sdl->title);
    if (sdl->map) free_rect(sdl->map);
    if (sdl->info) free_rect(sdl->info);
    sdl->title = new_rect(4,4, w-8, T_H);
    sdl->map   = new_rect(4, T_H+8,w-I_W-12, h-12-T_H);
    sdl->info  = new_rect(w-I_W-4, T_H+8, I_W, h-12-T_H);
  */  
   /* sdl->m_x=sdl->map->x + sdl->map->w/2;
    sdl->m_y=sdl->map->y + sdl->map->h/2;*/
    
    if (sdl->screen->format->palette){
        int i;
        SDL_PixelFormat *fmt;
        
        for (i=0; i<256; i++){
            sdl->colors[i].r=(i&0xe0)+31; 
            sdl->colors[i].g=((i<<3)&0xe0)+31;
            sdl->colors[i].b=((i<<6)&0xc0)+63;
        }
        SDL_SetColors(sdl->screen, sdl->colors, 0, 256);

        fmt=sdl->screen->format;
        fmt->Rmask=0xe0;
        fmt->Gmask=0x1c;
        fmt->Bmask=0x03;
        fmt->Rshift=5;
        fmt->Gshift=2;
        fmt->Bshift=0;
        fmt->Rloss=5;
        fmt->Gloss=5;
        fmt->Bloss=6;
        
        
    }
    switch(sdl->screen->format->BytesPerPixel){
        case 1:
            fast_putpixel = fast_putpixel8;
                  fast_getpixel = fast_getpixel8;
            break;
        case 2:
            fast_putpixel = fast_putpixel16;
                  fast_getpixel = fast_getpixel16;
            break;
        case 3:
            fast_putpixel = fast_putpixel24;
                  fast_getpixel = fast_getpixel24;
            break;
        case 4:
            fast_putpixel = fast_putpixel32;
                  fast_getpixel = fast_getpixel32;
            break;
    }
    pal[0].r = pal[0].g = pal[0].b = 0;
    sdl->gr[0] = makecol(0, 0, 0);
    for (i=1; i<16; i++){
        pal[i].r = pal[i].g = pal[i].b = i*4+3;
        sdl->gr[i] = makecol(i*16+15, i*16+15, i*16+15);
    }
    for (i=0; i<16; i++){
        int r,g,b;
        if (i&0x08){
            r=255*(i&0x01);
            g=255*((i&0x02)>>1);
            b=255*((i&0x04)>>2);
        }else if (i==0x07){
            r=192;
            g=192;
            b=192;
        }else{
            r=128*(i&0x01);
            g=128*((i&0x02)>>1);
            b=128*((i&0x04)>>2);
        }

        sdl->termcol[i]=makecol(r,g,b);
        /*dbg("color[%d]=%d,%d,%d\n", i, r,g,b);*/
    }
    sdl->cursor=makecol(128,128,0);
    sdl->yellow=makecol(255,255,0);
    sdl->green=makecol(0,255,0);
    sdl->red=makecol(255,0,0);
#if 0
    if (gses){ /* first call is without session */
        for (i=0;i<gses->subwins->len;i++){
            sw=(struct subwin *)g_ptr_array_index(gses->subwins, i);
            if (sw->type!=SWT_MAP) break;
            map_update_layout(sw);
        }
    }
#endif    
    
  /*  invalidate_bkg(NULL);
    invalidate_cache(aband);*/
    
    if (!init){
        sdl->event_thread_break=0;
        sdl->event_thread=SDL_CreateThread(sdl_event_thread, (void*)(vint)sdl->pipefd);
        if (!sdl->event_thread) {
            error("ERROR: can't create event thread");
            return -1;
        }
    }
    return 0;
}

void sdl_redraw_screen(void){
    int x,y,p,fg,bg,d,i,j, col;
    int minx,maxx,miny,maxy;
    unsigned char c;
    SDL_Rect dstrect;
      int update_dstrect=0;
    int iconx=0, icony=0;
    int draw_icon=0;

    minx=term->x;
    miny=term->y;
    maxx=-1;
    maxy=-1;

    if (term->last_screen!=DUMMY && (term->cx!=term->lcx || term->cy!=term->lcy)){
        term->last_screen[term->cx+term->cy*term->x]=0;
        term->last_screen[term->lcx+term->lcy*term->x]=0;
        term->lcx=term->cx;
        term->lcy=term->cy;
    }
      
      if (gses && gses->ontop && gses->ontop->screen && !show_qs()){
            
            
            dstrect.x=gses->ontop->x*FONT_W;
            dstrect.y=gses->ontop->y*FONT_H;
            dstrect.w=gses->ontop->w*FONT_W;
            dstrect.h=gses->ontop->h*FONT_H;
            SDL_BlitSurface(gses->ontop->screen, 0, sdl->screen,&dstrect);
            /*dbg("sdl_redraw_screen, blit \n");*/
      fill_lastarea(gses->ontop->x, gses->ontop->y, gses->ontop->w, gses->ontop->h, 0);
            update_dstrect=1;
      }

    if (gses && gses->icon != gses->oldicon){
        gses->oldicon=gses->icon;
        iconx=1;
        icony=term->y-cfg->loglines-DISP_QSOS-1;
        if (ctest) icony-=aband->spypeers->len;
        fill_lastarea(iconx, icony, 48/FONT_W+1, 48/FONT_H+1, 0);
        draw_icon=1;
    }
    if (gses && gses->icon == ssbd->recicon){
        x=term->x-1;
        for (y=0;y<6;y++) {
            term->last_screen[x+term->x*y]=0;
            term->screen[x+term->x*y]=' ';
        }
    }
    d=0;
    for (p=0,y=0;y<term->y;y++){
        for (x=0;x<term->x;x++,p++){
            if (term->screen[p] == term->last_screen[p]) continue;
                  if (!term->screen[p]) continue;
            d=1;
            if (x<minx) minx=x;
            if (y<miny) miny=y;
            if (x>maxx) maxx=x;
            if (y>maxy) maxy=y;
                    
            fg=(term->screen[p]&0x0700)>>8;
            if (term->screen[p]&0x4000) fg|=0x08;
            if (term->screen[p]&ATTR_FRAME){
                c=term->screen[p]-48;                
                if (c==170) c=134;
                else if (c==169) c=133;
            }else{
                c=term->screen[p];
            }
            
            bg=sdl->termcol[(term->screen[p]&0x3800)>>11];
            if (x+y>0 && x==term->cx && y==term->cy) bg=sdl->cursor;
            
                SDL_SetClipRect(sdl->screen, &sdl->termarea);
            fontoutc(sdl->screen, x*FONT_W, y*FONT_H, 
                    sdl->termcol[fg], 
                    bg, 
                    0, 
                    c);
        }
    }
    if (gses && gses->icon == ssbd->recicon){
        x=(term->x-1)*FONT_W;
        y=6*FONT_H-1;
        for (i=0;i<96;i++) {
            if (i<ssbd->loglevel) col=makecol(0, 255,0);
            else col=makecol(0, 100, 0);
            for (j=1;j<FONT_W-1;j++) fast_putpixel(sdl->screen, x+j, y-i, col);
        }
    }
    if (draw_icon) {
        SDL_Rect r;
        
        r.x=iconx*FONT_W;
        r.y=icony*FONT_H;
        r.w=48;
        r.h=48;
        SDL_BlitSurface(gses->icon, NULL, sdl->screen, &r); 
            SDL_UpdateRect(sdl->screen, r.x, r.y, r.w, r.h);
    }
    if (d) {
        minx=minx*FONT_W;
        miny=miny*FONT_H;
        maxx=(maxx+1)*FONT_W;
        maxy=(maxy+1)*FONT_H;
        /*rect(sdl->screen, minx, miny, maxx, maxy, 0x80);*/
        SDL_UpdateRect(sdl->screen, minx, miny, maxx-minx, maxy-miny);
        memcpy(term->last_screen, term->screen, term->x * term->y * sizeof(int));
    }
      if (update_dstrect){
/*          rect2(sdl->screen, &dstrect, 0x800000);          */
            SDL_UpdateRect(sdl->screen, dstrect.x, dstrect.y, dstrect.w, dstrect.h);
      }

}

SDL_Rect *new_rect(int x, int y, int w, int h){
    SDL_Rect *rect;

    rect = g_new0(SDL_Rect, 1);
    rect->x = x;
    rect->y = y;
      /* TODO */
    rect->w = w;
    rect->h = h;
    return rect;
}

void free_rect(SDL_Rect *rect){
    g_free(rect);
}



int sdl_get_terminal_size(int fd, int *x, int *y){
    *x=sdl->screen->w/FONT_W;
    *y=sdl->screen->h/FONT_H;
    return 0;
}

int handle_unicode(const SDL_Event *sev, struct event *ev){
    char iso[10];
    char uni[2];
    char *isoptr;
    char *uniptr;
    size_t in,out;
    int err,ret;

    if (!sev->key.keysym.unicode) return 0;
    
    in=2;
    out=10;
    uni[0]=sev->key.keysym.unicode;
    uni[1]=sev->key.keysym.unicode>>8;
    isoptr=iso;
    uniptr=uni;
    
    /*dbg("uniptr=%p isoptr=%p in=%d out=%d\n", uniptr, isoptr, in, out);*/
    ret=iconv(sdl->iconv, &uniptr, &in, &isoptr, &out);
    err=errno;
    /*dbg("uniptr=%p isoptr=%p in=%d out=%d\n", uniptr, isoptr, in, out);*/
    
    if (debug_keyboard){
        fprintf(stderr, "Keyboard: unicode=0x%04x  iso:0x%02x '%c'\n", sev->key.keysym.unicode, (unsigned char)iso[0],isprint(iso[0])?(unsigned char)iso[0]:'.');
    }
    if (ret || !iso[0]){
        log_addf("Can't handle keystroke unicode=0x%04x  ret=%d  iso=0x%02x\n", sev->key.keysym.unicode, ret, (unsigned char)iso[0]);
        return 0;
    }

    ev->x=(unsigned char)iso[0];
    if (ev->x<' '){    /* Ctrl+letter */
        ev->x+='@';
    }

    /*if (sev->key.keysym.mod & KMOD_SHIFT)           ev->y|=KBD_SHIFT;*/
    if (sev->key.keysym.mod & (KMOD_ALT|KMOD_META)) ev->y|=KBD_ALT;
    if (sev->key.keysym.mod & KMOD_CTRL)            ev->y|=KBD_CTRL;

    return 1;
}

int sdl_event_thread(void *handle){
    int fd=(int)(long int)handle;
    SDL_Event sev,sev2;
    struct event ev;
    int shift,k,sk,ret;
      char errbuf[1024];
    
    /* wait for empty pipe */
   /* dbg("event thread activated %d\n", sdl->eventpipestate);*/
    
    while(!sdl->event_thread_break){
#if 0        
        SDL_KeyboardEvent *kev;
#endif                
        ev.ev = ev.x = ev.y = ev.y = ev.b = 0;
        k=sk=0;
      
            SDL_PumpEvents();
            switch(SDL_PeepEvents(&sev, 1, SDL_GETEVENT, SDL_ALLEVENTS)) {
                case -1: 
                return -1;
                break;
                case 0: 
                SDL_Delay(50);
                continue;
                case 1: 
                break;
            }
        /*dbg("event %d\n", sev.type);*/
        
        switch(sev.type){
            case SDL_KEYDOWN:
#if 0
                dbg("KEYDOWN: ");
                for (k=0;k<sizeof(sev);k++) {
                    char *c;
                    c=(char *)&sev;
                    dbg ("%02x ", (unsigned char) (c[k]));
                }
                dbg("\n");
#endif
#if 0
                kev=&sev;
    
                dbg("type=%d state=%d scan=%d sym=%d mod=%d unicode=%d\n", 
                        kev->type, kev->state, kev->keysym.scancode, kev->keysym.sym, kev->keysym.mod, kev->keysym.unicode);
#endif                

                
                ev.ev=EV_KBD;
        /*dbg("event: %d %x %d '%c'\n", sev.type, sev.key.keysym.mod, sev.key.keysym.sym, sev.key.keysym.sym);*/
                switch(sev.key.keysym.sym){
                    case SDLK_BACKSPACE:    k=sk=KBD_BS;         goto handle;                                            
                    case SDLK_TAB:          k=sk=KBD_TAB;        goto handle;
                    case SDLK_RETURN:                
                    case SDLK_KP_ENTER:     k=sk=KBD_ENTER;      goto handle;
                              case SDLK_PAUSE:        fprintf(stderr, "PAUSE\n");      goto handle;
                    case SDLK_ESCAPE:       k=sk=KBD_ESC;        goto handle;

                    case SDLK_UP:             k=sk=KBD_UP;         goto handle;
                    case SDLK_DOWN:           k=sk=KBD_DOWN;       goto handle;
                    case SDLK_RIGHT:          k=sk=KBD_RIGHT;      goto handle;
                    case SDLK_LEFT:           k=sk=KBD_LEFT;       goto handle;
                    case SDLK_INSERT:         k=sk=KBD_INS;        goto handle;
                    case SDLK_DELETE:       k=sk=KBD_DEL;        goto handle;
                    case SDLK_HOME:           k=sk=KBD_HOME;       goto handle;
                    case SDLK_END:            k=sk=KBD_END;        goto handle;
                    case SDLK_PAGEUP:         k=sk=KBD_PGUP;       goto handle;
                    case SDLK_PAGEDOWN:     k=sk=KBD_PGDN;       goto handle;
                    case SDLK_F1:             k=sk=KBD_F1;         goto handle;
                    case SDLK_F2:             k=sk=KBD_F2;         goto handle;
                    case SDLK_F3:             k=sk=KBD_F3;         goto handle;
                    case SDLK_F4:             k=sk=KBD_F4;         goto handle;
                    case SDLK_F5:             k=sk=KBD_F5;         goto handle;
                    case SDLK_F6:             k=sk=KBD_F6;         goto handle;
                    case SDLK_F7:             k=sk=KBD_F7;         goto handle;
                    case SDLK_F8:             k=sk=KBD_F8;         goto handle;
                    case SDLK_F9:             k=sk=KBD_F9;         goto handle;
                    case SDLK_F10:            k=sk=KBD_F10;        goto handle;
                    case SDLK_F11:            k=sk=KBD_F11;        goto handle;
                    case SDLK_F12:            k=sk=KBD_F12;        goto handle;
                    case SDLK_KP0:          k=KBD_INS;   sk='0'; goto handle;
                    case SDLK_KP1:          k=KBD_END;   sk='1'; goto handle;
                    case SDLK_KP2:          k=KBD_DOWN;  sk='2'; goto handle;
                    case SDLK_KP3:          k=KBD_PGDN;  sk='3'; goto handle;
                    case SDLK_KP4:          k=KBD_LEFT;  sk='4'; goto handle;
                    case SDLK_KP5:          k=KBD_DOWN;  sk='5'; goto handle;
                    case SDLK_KP6:          k=KBD_RIGHT; sk='6'; goto handle;
                    case SDLK_KP7:          k=KBD_HOME;  sk='7'; goto handle;
                    case SDLK_KP8:          k=KBD_UP;    sk='8'; goto handle;
                    case SDLK_KP9:          k=KBD_PGUP;  sk='9'; goto handle;
                    case SDLK_KP_PERIOD:    k=KBD_DEL;   sk='.'; goto handle;
                    case SDLK_KP_DIVIDE:    k=sk='/';            goto handle;
                    case SDLK_KP_MULTIPLY:      k=sk='*';            goto handle;
                    case SDLK_KP_MINUS:   k=sk='-';            goto handle;
                    case SDLK_KP_PLUS:        k=sk='+';            goto handle;
                    default: break;
                }

                if (sev.key.keysym.unicode){
                    if (handle_unicode(&sev, &ev)) goto send;
                    dbg("to je divny, unicode 0x%04x nebyla zpracovana\n", sev.key.keysym.unicode);
                }

                switch(sev.key.keysym.sym){
                    case SDLK_QUOTE:        k='\'';  sk='"';     break;
                    case SDLK_COMMA:        k=',';   sk='<';     break;
                    case SDLK_MINUS:        k='-';   sk='_';     break;
                    case SDLK_PERIOD:       k='.';   sk='>';     break;
                    case SDLK_SLASH:        k='/';   sk='?';     break;
                    case SDLK_0:            k='0';   sk=')';     break;                                            
                    case SDLK_1:            k='1';   sk='!';     break;                                            
                    case SDLK_2:            k='2';   sk='@';     break;                                            
                    case SDLK_3:            k='3';   sk='#';     break;                                            
                    case SDLK_4:            k='4';   sk='$';     break;                                            
                    case SDLK_5:            k='5';   sk='%';     break;                                            
                    case SDLK_6:            k='6';   sk='^';     break;                                            
                    case SDLK_7:            k='7';   sk='&';     break;                                            
                    case SDLK_8:            k='8';   sk='*';     break;                                            
                    case SDLK_9:            k='9';   sk='(';     break;                                            
                    case SDLK_SEMICOLON:    k=';';   sk=':';     break;
                    case SDLK_LESS:         k='<';   sk='>';     break;
                    case SDLK_EQUALS:       k='=';   sk='+';     break;
                    case SDLK_LEFTBRACKET:  k='[';   sk='{';     break;
                    case SDLK_BACKSLASH:    k='\\';  sk='|';     break;
                    case SDLK_RIGHTBRACKET: k=']';   sk='}';     break;
                    case SDLK_BACKQUOTE:    k='`';   sk='~';     break;
                                                          
                    default: 
                        if (sev.key.keysym.sym<0x100){
                            k=sk=sev.key.keysym.sym;
                            if (k>='a' && k<='z'){
                                sk-='a'-'A';
                            }
                        }else{
                            k=sk=0;
                        }
                        break;
                }
handle:;                
                shift=(sev.key.keysym.mod & KMOD_SHIFT)!=0;
                /*dbg("\nshift=%d caps=%d %d\n", shift,sev.key.keysym.mod & KMOD_CAPS,(sev.key.keysym.mod & KMOD_CAPS)!=0 );*/
                if (k>='a' && k<='z') shift^=(sev.key.keysym.mod & KMOD_CAPS)!=0;
                if (sev.key.keysym.sym>=SDLK_KP0 && sev.key.keysym.sym<=SDLK_KP_PERIOD) shift^=(sev.key.keysym.mod & KMOD_NUM)!=0;
                
                if (shift){
                    ev.x=sk; 
                    if (sk>=256) ev.y|=KBD_SHIFT;
                }else{
                    ev.x=k;
                }

                if (sev.key.keysym.mod & (KMOD_ALT|KMOD_META)){
                    ev.y|=KBD_ALT;
                }
                    
                if (sev.key.keysym.mod & KMOD_CTRL){
                    ev.y|=KBD_CTRL;
                }
                    
                
                if (ev.x) goto send;
                break;

            case SDL_MOUSEBUTTONDOWN:
                ev.ev=EV_MOUSE;
                ev.x=sev.button.x/FONT_W;
                ev.y=sev.button.y/FONT_H;
                ev.mx=sev.button.x;
                ev.my=sev.button.y;
                switch(sev.button.button){
                    case SDL_BUTTON_LEFT:      
                        sdl->mouse_drag=1;
                        sdl->drag_buttons=ev.b=B_LEFT;    
                        goto send;
                    case SDL_BUTTON_MIDDLE:    
                        sdl->mouse_drag=1;
                        sdl->drag_buttons=ev.b=B_MIDDLE;  
                        goto send;
                    case SDL_BUTTON_RIGHT:     
                        sdl->mouse_drag=1;
                        sdl->drag_buttons=ev.b=B_RIGHT;   
                        goto send;
                    case SDL_BUTTON_WHEELUP:   ev.b=B_WHUP;    goto send;
                    case SDL_BUTTON_WHEELDOWN: ev.b=B_WHDOWN;  goto send;
                }
                                                                   
                break;

            case SDL_MOUSEBUTTONUP:
                sdl->mouse_drag=0;
                ev.ev=EV_MOUSE;
                ev.x=sev.button.x/FONT_W;
                ev.y=sev.button.y/FONT_H;
                ev.mx=sev.button.x;
                ev.my=sev.button.y;
                switch(sev.button.button){
                    case SDL_BUTTON_LEFT:      ev.b=B_LEFT|B_UP;    goto send;
                    case SDL_BUTTON_MIDDLE:    ev.b=B_MIDDLE|B_UP;  goto send;
                    case SDL_BUTTON_RIGHT:     ev.b=B_RIGHT|B_UP;   goto send;
                }
                                                                   
                break;
            case SDL_MOUSEMOTION:
                ev.ev=EV_MOUSE;
                ev.x=sev.button.x/FONT_W;
                ev.y=sev.button.y/FONT_H;
                if (sdl->mouse_drag) 
                    ev.b=sdl->drag_buttons|B_DRAG;
                else
                    ev.b=B_MOVE;
                ev.mx=sev.button.x;
                ev.my=sev.button.y;
                sdl->mouse_x=sev.button.x;
                sdl->mouse_y=sev.button.y;
                while (SDL_PeepEvents(&sev2, 1, SDL_PEEKEVENT, SDL_ALLEVENTS)==1){
                    if (sev2.type!=SDL_MOUSEMOTION) break;
                        ret=SDL_PeepEvents(&sev, 1, SDL_GETEVENT, SDL_ALLEVENTS);
                    if (ret!=1) internal("Somebody stole my event");
                   /* dbg("next SDL_MOUSEMOTION\n");*/
                    ev.x=sev2.button.x/FONT_W;
                    ev.y=sev2.button.y/FONT_H;
                    ev.mx=sev2.button.x;
                    ev.my=sev2.button.y;
                    sdl->mouse_x=sev2.button.x;
                    sdl->mouse_y=sev2.button.y;
                }
                goto send;
                if (sdl->mouse_drag) goto send;
                continue;
                

            case SDL_VIDEORESIZE:
                ev.ev=EV_SDLRESIZE;
                ev.mx=sev.resize.w;
                ev.my=sev.resize.h;
                ev.x=ev.mx/FONT_W;
                ev.y=ev.my/FONT_H;
                goto send;
/*                sdl_setvideomode(sev.resize.w, sev.resize.h);
                resize_terminal(CBA0);
                break;*/
                
                  case SDL_QUIT:
                ev.ev=EV_KBD;
                ev.x='q';
                ev.y=KBD_ALT;
                goto send;
        }
        continue;
send:;        
        /*dbg("ev=%ld x=%ld(%c) y=%ld b=%ld\n", ev.ev, ev.x, isprint(ev.x)?ev.x:0, ev.y, ev.b);*/

        while(1){
            int len;
            LOCK(sdl->eventpipestate);
            len=sdl->eventpipestate;
            UNLOCK(sdl->eventpipestate);
            if (len<sizeof(ev)*5) break;
          /*  dbg("waiting for the sun %d\n", len);*/
            usleep(100000);
        }
        ret=write(fd, &ev, sizeof(ev));
        if (ret != sizeof(ev)) {
            int err;
            err=errno;
            if (err==32 && !sdl->event_thread_break){
                internal("Sem pridej konec vlakna, vole. Nakej nouma mi zavrel pajpu");
            }
            internal("can't write to event pipe ret=%d errno=%d %s\n", ret,err, strerror_r(err, errbuf, sizeof(errbuf)));
            break;
        }   
        LOCK(sdl->eventpipestate);
        sdl->eventpipestate+=sizeof(ev);
        /*dbg("w %d\n", sdl->eventpipestate);*/
        UNLOCK(sdl->eventpipestate);
        
        
    }
    dbg("sdl_thread exited %d\n", sdl->event_thread_break);
    
    return 0;
}


int sdl_attach_terminal(int in, int out, int ctl)
{
    /*struct terminal *term;*/
    /*dbg("attach_terminal\n");*/
    int fd[2];
    if (c_pipe(fd)) {
        error("ERROR: can't create pipe for internal communication");
        return -1;
    }
    /*dbg("sdl_attach terminal: pipe %d->%d\n", fd[1], fd[0]);*/
    fcntl(fd[0], F_SETFL, O_NONBLOCK);

    /*         -1  -1   -1          -1 */
    handle_trm(in, out, out, fd[1], ctl); /* before sdl_thread! */
    
/*    dbg("after handle_trm %d\n", sdl->eventpipestate);*/
    sdl->pipefd=fd[1];
    sdl->event_thread_break=0;
    sdl->event_thread=SDL_CreateThread(sdl_event_thread, (void*)(vint)sdl->pipefd);
    if (!sdl->event_thread) {
        error("ERROR: can't create event thread");
        return -1;
    }
    
    if ((term = init_term(fd[0], out, win_func))) {
        handle_basic_signals(term); /* OK, this is race condition, but it must be so; GPM installs it's own buggy TSTP handler */
        return fd[1];
    }

    close(fd[0]);
    close(fd[1]);
    return -1;
}


int makecol(int r, int g, int b){
    SDL_PixelFormat *format;

    format=sdl->screen->format;
    return (((r>>format->Rloss)<<format->Rshift)&format->Rmask) |
           (((g>>format->Gloss)<<format->Gshift)&format->Gmask) |
           (((b>>format->Bloss)<<format->Bshift)&format->Bmask);
}



/* returns 1 if pixel is out of rect */
int clip_pixel(SDL_Rect *clip, int x, int y){
      if (x < clip->x || 
            y < clip->y ||
            x >= clip -> x + clip->w || 
            y >= clip -> y + clip->h) return 1;
      return 0;
}

int overlapped_pixel(SDL_Rect *clip_rect, int x, int y){
    int ret;
    if (x >= clip_rect->x && 
        y >= clip_rect->y &&
        x <  clip_rect->x + clip_rect->w &&
        y <  clip_rect->y + clip_rect->h) ret=1;
    else
        ret=0;
    dbg("overlapper_pixel(%d, %d in %dx%d%+d%+d)=%d\n", 
            x, y, clip_rect->x, clip_rect->y, clip_rect->w, clip_rect->h, ret);
    return ret;
}


int overlapped_rect(SDL_Rect *a, SDL_Rect *b){
    int ret;

    if ( (a->x+a->w <= b->x) || /* a je vlevo od b */
         (b->x+b->w <= a->x) || /* b je vlevo od a */
         (a->y+a->h <= b->y) || /* a je nad b */
         (b->y+b->h <= a->y)) ret=0; /* b je nad a */
    else
        ret=1;
    
/*    dbg("overlapped_rect(%dx%d%+d%+d,%dx%d%+d%+d)=%d\n", a->x, a->y, a->w, a->h, b->x, b->y, b->w, b->h, ret);*/
    return ret;
}

/*
 *    X ->
 *  Y 0110 0010 1010
 *  | 0100 0000 1000
 *  V 0101 0001 1001
 */
 

int overlapped_line(SDL_Rect *clip_rect, int x1, int y1, int x2, int y2){
    int mask1, mask2;

    mask1=0;
    if (x1<clip_rect->x) mask1|=0x4;
    else if (x1>=clip_rect->x+clip_rect->w) mask1|=0x8;
    if (y1<clip_rect->y) mask1|=0x2;
    else if (y1>=clip_rect->y+clip_rect->h) mask1|=0x1;
    mask2=0;
    if (x2<clip_rect->x) mask2|=0x4;
    else if (x2>=clip_rect->x+clip_rect->w) mask2|=0x8;
    if (y2<clip_rect->y) mask2|=0x2;
    else if (y2>=clip_rect->y+clip_rect->h) mask2|=0x1;
    if ((mask1|mask2)==0) return 1;
    if (mask1&mask2) return 0;
    return 1;
/*    if ((mask1&mask2)==0) return 1;
    res=mask1^mask2;
    if ((res&0x3)==0) return 0;
    if ((res&0xc)==0) return 0;
    return 1;*/
}

    


void fast_putpixel8(SDL_Surface *surface, int x, int y, int color){
    Uint8 *p;

    if (clip_pixel(&surface->clip_rect, x, y)) return;
    p = (Uint8 *) surface->pixels + y*surface->pitch + x;
    *p = color;
}

void fast_putpixel16(SDL_Surface *surface, int x, int y, int color){
    Uint16 *p;

    if (clip_pixel(&surface->clip_rect, x, y)) return;
    p = (Uint16 *) surface->pixels + y*surface->pitch/2 + x;
    *p = color;
}

void fast_putpixel24(SDL_Surface *surface, int x, int y, int color){
    Uint16 *p16;
    Uint8  *p8;

    if (clip_pixel(&surface->clip_rect, x, y)) return;
    p16 = (Uint16 *) surface->pixels + y*surface->pitch/3 + x;
    p8  = (Uint8 *)  (p16+1); 
    *p16 = color;     /* TODO Big endian? */
    *p8  = color>>16; 
}

void fast_putpixel32(SDL_Surface *surface, int x, int y, int color){
    Uint32 *p;

    if (clip_pixel(&surface->clip_rect, x, y)) return;
    p = (Uint32 *) surface->pixels + y*surface->pitch/4 + x;
    *p = color;
}


int fast_getpixel8(SDL_Surface *surface, int x, int y){
    Uint8 *p;

    p = (Uint8 *) surface->pixels + y*surface->pitch + x;
    return *p;
}

int fast_getpixel16(SDL_Surface *surface, int x, int y){
    Uint16 *p;

    p = (Uint16 *) surface->pixels + y*surface->pitch/2 + x;
    return *p;
}

int fast_getpixel24(SDL_Surface *surface, int x, int y){
    Uint16 *p16;
    Uint8  *p8;

    p16 = (Uint16 *) surface->pixels + y*surface->pitch/3 + x;
    p8  = (Uint8 *)  (p16+1); 
      return (*p16) + ((*p8)<<16);
/*    *p16 = color; */    /* TODO Big endian? */
/*    *p8  = color>>16; */
}

int fast_getpixel32(SDL_Surface *surface, int x, int y){
    Uint32 *p;

    p = (Uint32 *) surface->pixels + y*surface->pitch/4 + x;
    return *p;
}

void line(SDL_Surface *surface, int x1, int y1, int x2, int y2, int color){
    int dx, dy, p;      
    int inc, tmp;
    
    dx=abs(x1-x2);
    dy=abs(y1-y2);
    if (dx>=dy){
      p = 2*dy-dx;
      if (x1 >= x2){   
            tmp=x1;x1=x2;x2=tmp;
            tmp=y1;y1=y2;y2=tmp;
            }
        fast_putpixel(surface, x1, y1, color);
      if (y2>=y1) inc=1;
        else inc=-1;
      
        while(x1 < x2){ 
          x1++;         
            if (p<0) 
                p += 2*dy;
            else{
                y1+=inc;
                p += 2*(dy-dx);
            }
            fast_putpixel(surface, x1, y1, color);
        }
    }else{
      p = 2*dx-dy;
        if (y1 >= y2){
            tmp=x1;x1=x2;x2=tmp;
            tmp=y1;y1=y2;y2=tmp;
        }
        fast_putpixel(surface, x1, y1, color);
      
      if (x2>=x1) inc=1;
        else inc=-1;
      
        while(y1 < y2){ 
          y1++;         
            if (p<0) 
                p += 2*dx;
            else{
                x1 += inc;
                p += 2*(dx-dy);
            }
            fast_putpixel(surface, x1,y1, color);
        }
    }
} 

void do_line(SDL_Surface *surface, int x1, int y1, int x2, int y2, int color, 
        void (*func)(SDL_Surface *surface, int x, int y, int d) ){

    int dx, dy, p;      
    int inc, tmp;
    
    dx=abs(x1-x2);
    dy=abs(y1-y2);
    if (dx>=dy){
      p = 2*dy-dx;
      if (x1 >= x2){   
            tmp=x1;x1=x2;x2=tmp;
            tmp=y1;y1=y2;y2=tmp;
            }
        func(surface, x1, y1, color);
      if (y2>=y1) inc=1;
        else inc=-1;
      
        while(x1 < x2){ 
          x1++;         
            if (p<0) 
                p += 2*dy;
            else{
                y1+=inc;
                p += 2*(dy-dx);
            }
            func(surface, x1, y1, color);
        }
    }else{
      p = 2*dx-dy;
        if (y1 >= y2){
            tmp=x1;x1=x2;x2=tmp;
            tmp=y1;y1=y2;y2=tmp;
        }
        func(surface, x1, y1, color);
      
      if (x2>=x1) inc=1;
        else inc=-1;
      
        while(y1 < y2){ 
          y1++;         
            if (p<0) 
                p += 2*dx;
            else{
                x1 += inc;
                p += 2*(dx-dy);
            }
            func(surface, x1,y1, color);
        }
    }
} 

#define SWAP(a,b){ int tmp; \
    tmp=x##a; x##a=x##b; x##b=tmp;\
    tmp=y##a; y##a=y##b; y##b=tmp;}
    
void triangle(SDL_Surface *surface, int x1, int y1, int x2, int y2, int x3, int y3, int c){
    int a1,b1,c1, a2,b2,c2, a3,b3,c3, xx1, xx2,xx3,y;
    
    
    if (y2<y1) SWAP(1,2);
    if (y3<y1) { SWAP(1,3); SWAP(2,3); }
    if (y3<y2) SWAP(2,3);

    if (y1==y2 && y2==y3){ /* singularity, horizontal line */
#ifdef USE_RECT 
        SDL_Rect r;
        r.x=x1<x2?x1:x2;
        if (x3<r.x) r.x=x3;
        r.y=y1;
        r.w=x1>x2?x1:x2;
        if (x3>r.x) r.w=x3;
        r.w-=r.x;
        r.h=1;
        SDL_SetClipRect(surface, rect);   
        SDL_FillRect(surface, &r, c);
        SDL_SetClipRect(surface, NULL);   
#else        
        /* i don't want to sort X's :-) */
        line(surface, x1, y1, x2, y2, c);
        line(surface, x1, y1, x3, y3, c);
        line(surface, x3, y3, x2, y2, c);
#endif        
        return;
    }
    
    a1=y2-y3;
    b1=x3-x2;
    c1=y3*x2-x3*y2;
    
    a2=y1-y2;
    b2=x2-x1;
    c2=y2*x1-x2*y1;
    
    a3=y1-y3;
    b3=x3-x1;
    c3=y3*x1-x3*y1;

#ifdef USE_RECT 
    SDL_SetClipRect(surface, rect);   
#endif    
    for (y=y1;y<y2;y++){
#ifdef USE_RECT        
        SDL_Rect r;
#endif        
        xx2=-(b2*y+c2)/a2; /* a2=0 not reached because y1=y2 -> no iteration */
        xx3=-(b3*y+c3)/a3; /* a3=0 not reached because y1=y2 -> y1=y2=y3 */
#ifdef USE_RECT
        r.x=xx2<xx3?xx2:xx3;
        r.w=xx2<xx3?xx3-xx2:xx2-xx3;
        r.y=y;
        r.h=1;
        SDL_FillRect(gfx->surface, &r, c);
#else        
        line(surface, xx2, y, xx3, y, c);
#endif        
    }
    
    for (y=y2;y<y3;y++){
#ifdef USE_RECT        
        SDL_Rect r;
#endif        
        xx1=-(b1*y+c1)/a1; /* a1=0 not reached because y2=y3 -> no iteration */
        xx3=-(b3*y+c3)/a3;
#ifdef USE_RECT        
        r.x=xx1<xx3?xx1:xx3;
        r.w=xx1<xx3?xx3-xx1:xx1-xx3;
        r.y=y;
        r.h=1;
        SDL_FillRect(surface, &r, c);
#else        
        line(surface, xx1, y, xx3, y, c);
#endif        
    }
#ifdef USE_RECT    
    SDL_SetClipRect(surface, NULL);   
#endif    
    fast_putpixel(surface, x3, y3, c);
    
}

void circle(SDL_Surface *surface, int x, int y, int r, int c){
    int xx, yy, p;

/*    dbg("circle([%d,%d,%d,%d], %d, %d, %d, %x\n", rect->x, rect->y, rect->w, rect->h, x, y, r, c);*/
    p=1-r;
    yy=r;
    
    for (xx=0; xx<=yy; xx++){
        fast_putpixel(surface, x+yy, y+xx, c);
        fast_putpixel(surface, x+yy, y-xx, c);
        fast_putpixel(surface, x-yy, y+xx, c);
        fast_putpixel(surface, x-yy, y-xx, c);
                              
        fast_putpixel(surface, x+xx, y+yy, c);
        fast_putpixel(surface, x+xx, y-yy, c);
        fast_putpixel(surface, x-xx, y+yy, c);
        fast_putpixel(surface, x-xx, y-yy, c);

        if (p<0){
            p+=2*xx + 3;
        }else{
            p+=2*xx - 2*yy + 1;
            yy--;
        }
    }
}


void fast_dashfce(SDL_Surface *surface, int x, int y, int d) {
    if (dashcnt++%6<3) return;
    fast_putpixel(surface, x, y, d);
}
    

void rect(SDL_Surface *surface, int x1, int y1, int x2, int y2, int c){
    line(surface, x1, y1, x2, y1, c);
    line(surface, x2, y1, x2, y2, c);
    line(surface, x1, y2, x2, y2, c);
    line(surface, x1, y1, x1, y2, c);
}

void rect2(SDL_Surface *surface, SDL_Rect *r, int c){
      rect(surface, r->x, r->y, r->x+r->w-1, r->y+r->h-1, c);
}

void cross(SDL_Surface *surface, int x, int y, int color, int zoom){
    if (zoom<2500){
        line(surface, x-1, y-1, x+1, y+1, color);
        line(surface, x-1, y+1, x+1, y-1, color);
        return;
    }
    if (zoom<4000){
        line(surface, x-2, y-2, x+2, y+2, color);
        line(surface, x-2, y+2, x+2, y-2, color);
        return;
    }
    if (zoom<10000){
        line(surface, x-3, y-3, x+3, y+3, color);
        line(surface, x-2, y-3, x+3, y+2, color);
        line(surface, x-3, y-2, x+2, y+3, color);
        line(surface, x-3, y+3, x+3, y-3, color);
        line(surface, x-2, y+3, x+3, y-2, color);
        line(surface, x-3, y+2, x+2, y-3, color);
        return;
    }
    if (zoom>=10000){
        line(surface, x-4, y-4, x+4, y+4, color);
        line(surface, x-3, y-4, x+4, y+3, color);
        line(surface, x-4, y-3, x+3, y+4, color);
        line(surface, x-4, y+4, x+4, y-4, color);
        line(surface, x-3, y+4, x+4, y-3, color);
        line(surface, x-4, y+3, x+3, y-4, color);
        return;
    }
}

int sdl_set_title(gchar *title){
    
    if (!sdl) return 0;
    CONDGFREE(sdl->title);
    sdl->title=g_strdup(title);

    SDL_WM_SetCaption(sdl->title, NULL);
    return 0;
}

void sdl_screenshot(int topwindow){
    gchar *c; 
    int i;
    SDL_Surface *surface;

    if (!sdl) return;


    if (topwindow){
        struct window *win;

        win=(struct window *)&(term->windows);
        dbg("win=%p prev=%p next=%p\n", win, win->prev, win->next);
        if (win->prev==win->next || !win->next->data){
            surface=sdl->screen;
        }else{
            SDL_Rect sr,dr;
            sr.x=sr.y=dr.w=dr.h=sr.w=sr.h=0;
            i=0;
            if (win->next->handler==menu_func || win->next->handler==mainmenu_func){
                    struct menu *menu;
                    menu=(struct menu *)win->next->data;
                    dr.x=-menu->x*FONT_W;
                    dr.y=-menu->y*FONT_H;
                    sr.w=menu->xw*FONT_W;
                    sr.h=menu->yw*FONT_H;
                    i++;
            }
            if (win->next->handler==dialog_func){
                    struct dialog_data *dd;
                    dd=(struct dialog_data *)win->next->data;
                    dr.x=-dd->x*FONT_W;
                    dr.y=-dd->y*FONT_H;
                    sr.w=dd->xw*FONT_W;
                    sr.h=dd->yw*FONT_H;
                    i++;
            }
            if (win->next->handler==cwwindow_func){
                    struct cwwin_data *cww;
                    cww=(struct cwwin_data *)win->next->data;
                    dr.x=-cww->x*FONT_W;
                    dr.y=-cww->y*FONT_H;
                    sr.w=cww->w*FONT_W;
                    sr.h=cww->h*FONT_H;
                    i++;
            }
            
            if (!i){
                surface=sdl->screen;
            }else{
                surface=SDL_CreateRGBSurface(SDL_SWSURFACE, sr.w, sr.h, sdl->bpp,                               
                        sdl->screen->format->Rmask, sdl->screen->format->Gmask, sdl->screen->format->Bmask, 0);
/*                dbg("sr=[%d,%d, %d,%d]\n", sr.x, sr.y, sr.w, sr.h);
                dbg("dr=[%d,%d, %d,%d]\n", dr.x, dr.y, dr.w, dr.h);  */
                SDL_BlitSurface(sdl->screen, NULL , surface, &dr);
/*                dbg("dr=[%d,%d, %d,%d]\n", dr.x, dr.y, dr.w, dr.h);
                SDL_BlitSurface(surface, NULL, sdl->screen, NULL);
                SDL_UpdateRect(sdl->screen, 0, 0, sdl->screen->w, sdl->screen->h);
                sleep(1);*/
            }
        }

    }else{
        surface=sdl->screen;
    }
        
    for (i=0;1;i++){  
        struct stat st;

        if (ctest)
            c=g_strdup_printf("%s/snap%d.png",ctest->directory,i);
        else
            c=g_strdup_printf("%s/tucnak/snap%d.png",getenv("HOME"),i);
        if (stat(c, &st)!=0) break;
        g_free(c);
    }
    
    if (do_png_save(surface, c)){
        log_addf(VTEXT(T_CANT_WRITE_S), c);
        errbox(VTEXT(T_CANT_WRITE), errno);
    }
    g_free(c);

    if (surface!=sdl->screen) SDL_FreeSurface(surface);
}

#endif

Generated by  Doxygen 1.6.0   Back to index