/*
 *  neercs        console-based window manager
 *  Copyright (c) 2006 Sam Hocevar <sam@zoy.org>
 *                2008 Jean-Yves Lamoureux <jylam@lnxscene.org>
 *                All Rights Reserved
 *
 *  $Id$
 *
 *  This program is free software. It comes without any warranty, to
 *  the extent permitted by applicable law. You can redistribute it
 *  and/or modify it under the terms of the Do What The Fuck You Want
 *  To Public License, Version 2, as published by Sam Hocevar. See
 *  http://sam.zoy.org/wtfpl/COPYING for more details.
 */

#include <stdint.h>
#include <caca.h>

enum wm_types
{
    WM_FULL,
    WM_CARD,
    WM_HSPLIT,
    WM_VSPLIT,

    WM_MAX,
};


struct screen
{
    /* Graphics stuff */
    int init;
    cucul_canvas_t *cv;
    uint32_t clearattr;
    uint8_t fg, bg;   /* ANSI-context fg/bg */
    uint8_t dfg, dbg; /* Default fg/bg */
    uint8_t bold, blink, italics, negative, concealed, underline;
    uint8_t faint, strike, proportional; /* unsupported */

    /* Other stuff */
    int visible;                 /* Draw canvas and border flag */
    int fd;                      /* pty fd */
    unsigned char *buf;          /* text buffer */
    long int total;              /* buffer length */
    char *title;                 /* tty title */
    int bell;                    /* bell occuring */
    unsigned int scroll, s1, s2; /* FIXME, ANSI scroll properties */
    int pid;                     /* running program pid */

    int x, y;                    /* Canvas position */
    int w, h;                    /* Canvas size */

    int orig_x, orig_y;          /* Used by recurrents */
    int orig_w, orig_h;          /* Used by recurrents */

};

struct screen_list
{
    int wm_type;                 /* Window manager type */
    int in_bell;                 /* Bell occuring in a window  */
    int dont_update_coords;      /* Used by recurrents */
    int attached;                /* Are we attached to a terminal */

    /* Lock */
    int locked;
    char lockpass[1024];
    char lockmsg[1024];

    /* Add-ons*/
    int mini;                    /* Thumbnails */
    int status;                  /* Status bar */
    int help;                    /* help */

    /* ScreenSaver stuff */
    long long unsigned int screensaver_timeout;     /* Screensaver timeout in us */
    int in_screensaver;
    void *screensaver_data;

    int pty, prevpty;            /* Current and previous window */
    int count;                   /* Window count */
    int width, height;           /* caca window size */
    struct screen **screen;      /* Windows */
};


struct recurrent
{
    int (*function)(struct screen_list*, struct recurrent* rec, void *user, long long unsigned int t);
    void *user;
    long long unsigned int  start_time;
    int kill_me;
};

struct recurrent_list
{
    int count;
    struct recurrent **recurrent;
};


void version(void);



int create_pty(char *cmd, unsigned int w, unsigned int h, int *cpid);
int create_pty_grab(pid_t pid, unsigned int w, unsigned int h);
int grab_process(pid_t pid, char *ptyname, int ptyfd);

long int import_term(struct screen_list *screen_list, struct screen *sc, void const *data, unsigned int size);
int set_tty_size(int fd, unsigned int w, unsigned int h);
int update_terms(struct screen_list* screen_list);
void refresh_screens(cucul_canvas_t *cv,
                     caca_display_t *dp,
                     struct screen_list *screen_list);
int update_screens_contents(struct screen_list* screen_list);
long long get_ms(void);

int detach(struct screen_list* screen_list, caca_display_t * dp);

/* Screens management */
struct screen* create_screen(int w, int h, char *command);
struct screen* create_screen_grab(int w, int h, int pid);
int destroy_screen(struct screen *s);
int add_screen(struct screen_list *list, struct screen *s);
int remove_screen(struct screen_list *list, int n, int please_kill);
void resize_screen(struct screen *s, int z, int h);

/* Window managers */
void update_windows_props(cucul_canvas_t *cv, struct screen_list *screen_list);
void update_windows_props_cards(cucul_canvas_t *cv, struct screen_list *screen_list);
void update_windows_props_hsplit(cucul_canvas_t *cv, struct screen_list *screen_list);
void update_windows_props_full(cucul_canvas_t *cv, struct screen_list *screen_list);
void update_windows_props_vsplit(cucul_canvas_t *cv, struct screen_list *screen_list);

/* Effects and addons */
void draw_thumbnails(cucul_canvas_t *cv, struct screen_list *screen_list);
void draw_status(cucul_canvas_t *cv, struct screen_list *screen_list);
void draw_help(cucul_canvas_t *cv, struct screen_list *screen_list);
void draw_lock(cucul_canvas_t *cv, struct screen_list *screen_list);
int validate_lock(struct screen_list *screen_list, char *user, char *pass);

int close_screen_recurrent(struct screen_list*, struct recurrent* rec, void *user, long long unsigned int t);


/* Screensavers */
void screensaver_init(cucul_canvas_t *cv,
                      caca_display_t *dp,
                      struct screen_list *screen_list);
void screensaver_kill(cucul_canvas_t *cv,
                      caca_display_t *dp,
                      struct screen_list *screen_list);

void draw_screensaver(cucul_canvas_t *cv,
                      caca_display_t *dp,
                      struct screen_list *screen_list);
void screensaver_flying_toasters(cucul_canvas_t *cv,
                                 caca_display_t *dp,
                                 struct screen_list *screen_list);

void screensaver_flying_toasters_init(cucul_canvas_t *cv,
                                 caca_display_t *dp,
                                 struct screen_list *screen_list);

void screensaver_flying_toasters_kill(cucul_canvas_t *cv,
                                 caca_display_t *dp,
                                 struct screen_list *screen_list);



/* Recurrents */
int add_recurrent(struct recurrent_list *list,
                  int (*function)(struct screen_list*, struct recurrent* rec, void *user, long long unsigned int t),
                  void *user);
int remove_recurrent(struct recurrent_list *list, int n);


#if 0
#   define debug(f, z...) fprintf(stderr, f "\n", z)
#else
#   define debug(f, z...) do {} while(0)
#endif

