#ifndef MODULE_H
#define MODULE_H

struct queue_buff_struct
  {
    struct queue_buff_struct *next;
    unsigned long *data;
    int size;
    int done;
  };

typedef struct module_ibuf_t
{
  int len;
  int done;
  int window;
  int size;
  char* text;
  int cont;
} module_ibuf_t;

typedef struct module_t
{
  int fd;
  int active;
  char* name;
  long mask;
  struct queue_buff_struct* output_queue;
  module_ibuf_t ibuf;
} module_t;

extern int module_fd;
extern int npipes;
extern module_t* Module;

#define START_FLAG 0xffffffff

#define M_TOGGLE_PAGING      (1<<0)
#define M_NEW_PAGE           (1<<1)
#define M_NEW_DESK           (1<<2)
#define M_ADD_WINDOW         (1<<3)
#define M_RAISE_WINDOW       (1<<4)
#define M_LOWER_WINDOW       (1<<5)
#define M_CONFIGURE_WINDOW   (1<<6)
#define M_FOCUS_CHANGE       (1<<7)
#define M_DESTROY_WINDOW     (1<<8)
#define M_ICONIFY            (1<<9)
#define M_DEICONIFY          (1<<10)
#define M_WINDOW_NAME        (1<<11)
#define M_ICON_NAME          (1<<12)
#define M_RES_CLASS          (1<<13)
#define M_RES_NAME           (1<<14)
#define M_END_WINDOWLIST     (1<<15)
#define M_ICON_LOCATION      (1<<16)
#define M_MAP                (1<<17)
#define M_SHADE		     (1<<18)
#define M_UNSHADE	     (1<<19)
#define M_LOCKONSEND         (1<<20)
#define M_NEW_BACKGROUND     (1<<21)

#define MAX_MESSAGES          22
#define MAX_MASK             (((1<<MAX_MESSAGES)-1) & ~M_LOCKONSEND)

/* M_LOCKONSEND when set causes afterstep to wait for the module to send an
 * unlock message back, needless to say, we wouldn't want this on by default
 */

#define HEADER_SIZE         3
#define MAX_PACKET_SIZE    27
#define MAX_BODY_SIZE      (MAX_PACKET_SIZE - HEADER_SIZE)

/* from src/afterstep/module.c */
int module_setup_socket (Window w, const char* display_string);
int module_listen(const char* socket_name);
int module_accept(int socket_fd);
void module_init (int free_resources);
void module_setup (void);
int HandleModuleInput (int channel);

/* from lib/module.c */
int module_connect(const char* socket_name);
char* module_get_socket_property(Window w);

/* from lib/readpacket.c */
int ReadASPacket (int, unsigned long *, unsigned long **);

typedef struct {
    unsigned long header[3] ;
    unsigned long* body ;
}ASMessage ;

/* from lib/module.c */
/* checks if there is message from Afterstep in incoming pipe,
 * and reads it if it is . Returns NULL if there is nothing available yet 
 */
ASMessage* CheckASMessageFine (int fd, int t_sec, int t_usec);
#define CheckASMessage(fd,t_sec) CheckASMessageFine(fd,t_sec,0)
void DestroyASMessage( ASMessage* msg );

/* more usefull stuff removing duplicate code from modules */

typedef struct as_pipes {
    int fd[2];
    int fd_width ;
    int x_fd ;
} ASPipes ;

typedef struct as_atom {
    Atom atom;
    char* name;
    Atom type;
}ASAtom ;

/* sets MyName global variable from supplied argv[0] */
void SetMyName( char* argv0 );

void default_version_func(void);
void (*custom_version_func)(void);
int ProcessModuleArgs(int argc, char** argv, char**global_config_file, unsigned long *app_window, unsigned long *app_context, void (*custom_usage_func)(void));

/* returns fd of the AfterStep connection */
int ConnectAfterStep(unsigned long message_mask);

/* constructs config filename and calls supplied user function */
void LoadBaseConfig(char* global_config_file, void (*read_base_options_func)(const char*));
void LoadConfig(char* global_config_file, char* config_file_name, void (*read_options_func)(const char*));

/* only aplicable to modules with X connection : lib/Xmodule.c */
#ifdef MODULE_X_INTERFACE
/* returns fd of the X server connection */
int ConnectX(ScreenInfo* scr, char* display_name, unsigned long message_mask);
/* get's Atom ID's of the atoms names listed in array */
void InitAtoms(Display* dpy, ASAtom *atoms);
/* X enabled version of RunModule */
int My_XNextEvent(Display* dpy, int x_fd, int as_fd, void (*as_msg_handler)(unsigned long type, unsigned long* body) ,XEvent *event);
#endif

#endif /* MODULE_H */
