#ifndef __pinboard_h
#define __pinboard_h

#define ICONBAR_HEIGHT 132
#define BD_DEFAULT_COLOUR 0x55555500
#define FG_DEFAULT_COLOUR 0xffffff00
#define ICON_SPRITE_SIZE 82
#define iconbar_height (ICONBAR_HEIGHT+(1<<bbc_modevar(-1,bbc_YEigFactor)))

#define GRID_WIDTH_NORMAL 192
#define GRID_HEIGHT_NORMAL 128
#define GRID_WIDTH_DOUBLE (GRID_WIDTH_NORMAL*5/4)
#define GRID_HEIGHT_DOUBLE (GRID_HEIGHT_NORMAL*6/4)
#define GRID_WIDTH_SMALL (GRID_WIDTH_NORMAL+64)
#define GRID_HEIGHT_SMALL (ICON_TEXT_HEIGHT+8)

#define IGNORE(a) do { (a) = (a);} while(0)

#include "tboxlibs/toolbox.h"
#include "tboxlibs/wimp.h"

#define PINBOARD_DEFAULT_FILENAME "<Choices$Write>.Boot.Tasks.Pinboard"

#define ICON_TEXT_HEIGHT 44
#define MAX_ICON_WIDTH 192

/* definition for a pin */
#define pin_type_empty     0 // due for removal
#define pin_type_localfile 1 // ie saved on the pinboard
#define pin_type_window    2
#define pin_type_tinydir   4
#define pin_type_fsfile    8 // ie saved elsewhere, normal file pin
#define pin_type_sticky   16 // post-it note
#define pin_type_recheck  32 // added as X pin and not found: need to recheck if clicked on
#define pin_has_marker    64
#define pin_locked       128 // pin locked in place on pinboard
#define pin_nosnap       (1<<30) // don't snap to grid on creation

/* tests */
#define pin_is_localfile(a)   (((a)->icontype &pin_type_localfile)!=0)
#define pin_is_window(a)      (((a)->icontype &0xff)==pin_type_window)
#define pin_is_tinywin(a)     (((a)->icontype &0xff)==(pin_type_window|pin_type_tinydir))
#define pin_is_anywin(a)      (((a)->icontype & pin_type_window)!=0)
#define pin_is_tiny(a)        (((a)->icontype & pin_type_tinydir)!=0)
#define pin_is_fsfile(a)      (((a)->icontype & pin_type_fsfile)!=0)
#define pin_is_anyfile(a)     (((a)->icontype & (pin_type_localfile | pin_type_fsfile))!=0)
#define pin_is_sticky(a)      (((a)->icontype & pin_type_sticky)!=0)
#define pin_needs_recheck(a)  (((a)->icontype & pin_type_recheck)!=0)
#define pin_not_marked(a)     (((a)->icontype & pin_has_marker)==0)
#define pin_is_locked(a)      (((a)->icontype & pin_locked)!=0)

/* get/set filetype from pin */
#define pin_filetype(a)  (((a)->icontype>>16) &0xffff)
#define pin_set_filetype(a,b) ((a)->icontype=((a)->icontype & 0x0000ffff) | (b<<16))

/* marker */
#define pin_set_marked(a)    ((a)->icontype |= pin_has_marker)
#define pin_clear_marked(a)  ((a)->icontype &= ~pin_has_marker)

/* sticky edited */
#define sticky_flag_edited     (1<<22)
#define sticky_edited(a)       (((a)->icondata.flags & sticky_flag_edited)!=0)
#define sticky_set_edited(a)   ((a)->icondata.flags |= sticky_flag_edited)
#define sticky_clear_edited(a) ((a)->icondata.flags &= ~sticky_flag_edited)

typedef struct {
  unsigned int icontype;
  struct {
    BBox bbox;
    int buffer; // text to plot
    int sprite; // sprite to plot
    int flags;
  } icondata;
  
  ObjectId obj;          // tinydirs need an objectid and an iconbar icon handle
  int iconbar_icon;
  int sprite_x,sprite_y; // sprite x and y sizes (w,h)
  union {
    struct {
      int filename_offset; // full filename for the pin
      int alias; // indirected
    } pin;
    struct {
      int task_handle;
      int handle;   // or the window handle for the iconised window
      BBox visible_area; // where the window came from
    } window;
    struct {
      ComponentId textarea;
      int textarea_handle; // stickies have the text stored elsewhere by Toolbox
      int font_x,font_y;   // you can't currently access the font settings from a TextArea
      int font_name; // indirected
      int title; // indirected
    } sticky;
  } data;
} pin;

// older versions didn't have filename_offset inside a struct...
#define filename_offset pin.filename_offset

typedef struct {
  unsigned int count;
  pin info[];
} pins;

void pins_init(void);

int pin_add(pin *newpin); // returns index of new pin

/* if indirected data moves, we need to update offsets.  Anything after the offset needs to move by adjustment */
void pin_update_offsets(int offset,int adjustment);

extern int filer_base_column,filer_base_row;

#define BD_IMAGE_MASK     0x0f
#define BD_IMAGE_TYPE(a)  ((a) & BD_IMAGE_MASK)
#define BD_IMAGE_PLAIN  1
#define BD_IMAGE_SPRITE 2
#define BD_IMAGE_JPEG   3
#define BD_IS_PLAIN(a)  (BD_IMAGE_TYPE(a)==BD_IMAGE_PLAIN)
#define BD_IS_SPRITE(a) (BD_IMAGE_TYPE(a)==BD_IMAGE_SPRITE)
#define BD_IS_JPEG(a)   (BD_IMAGE_TYPE(a)==BD_IMAGE_JPEG)

#define BD_PAINT_MASK   0xf0
#define BD_PAINT(a)    ((a) & BD_PAINT_MASK)
#define BD_SCALED       0x10
#define BD_CENTRED      0x20
#define BD_TILED        0x30
#define BD_FULLSCREEN   0x40

#define BD_TEXT_STYLE_MASK 0xf00
#define BD_TEXT_STYLE(a) ((a) & BD_TEXT_STYLE_MASK)
#define BD_TEXT_THEME  0x100
#define BD_TEXT_BLEND   0x200
#define BD_TEXT_OUTLINE 0x300

#define BD_IMAGE_CACHE  0x1000
#define BD_IMAGE_CACHE_MASK 0x1000
#define BD_CAROUSEL_CACHE 0x2000


typedef enum {
  ICONIZE_TO_BUTTON,
  ICONIZE_TO_ICONBAR,
  ICONIZE_TO_TOPLEFT,
  ICONIZE_TO_BOTTOMLEFT,
  ICONIZE_TO_TOPRIGHT,
  ICONIZE_TO_BOTTOMRIGHT
} IconizeSetting;

typedef enum {
  ICONIZE_HORIZONTAL,
  ICONIZE_VERTICAL
} IconizeStack;

typedef enum {
  SOURCE_PINBOARD_SELDRAG,
  SOURCE_PINBOARD_ADJDRAG,
  SOURCE_TINYDIR_SELDRAG,
  SOURCE_TINYDIR_ADJDRAG
} source;

typedef enum {
  ICONSIZE_NORMAL,
  ICONSIZE_DOUBLE,
  ICONSIZE_SMALL,
  ICONSIZE_UNSPEC /* nothing was specfied in the command, so don't change */
} _iconsize;

typedef enum {
  /* no autosave */
  AUTOSAVE_NONE,
  /* autosave with confirmation */
  AUTOSAVE_CONFIRM,
  /* autosave, no prompt */
  AUTOSAVE_AUTO,
  /* nothing was specfied in the command, so don't change */
  AUTOSAVE_UNSPEC,
} autosave_type;

typedef enum {
  OVERWRITE_ALWAYS,
  OVERWRITE_CONFIRM,
  OVERWRITE_RENAME,
  OVERWRITE_UNSPEC /* nothing was specfied in the command, so don't change */
} overwrite_type;

typedef enum {
  WATERMARK_TOPLEFT,
  WATERMARK_TOPCENTRE,
  WATERMARK_TOPRIGHT,
  WATERMARK_LEFT,
  WATERMARK_CENTRE,
  WATERMARK_RIGHT,
  WATERMARK_BOTTOMLEFT,
  WATERMARK_BOTTOMCENTRE,
  WATERMARK_BOTTOMRIGHT
} watermark_type;

typedef struct {
  ObjectId obj;
  int bd_flags;
  unsigned int bd_colour; // backdrop colour
  unsigned int bg_colour; // text background colour when plotting outlines
  unsigned int fg_colour;
  char *bd_filename;  // so we can reload if need be
  char *bd_image;
  int image_length;
  int image_width,image_height; // size of original image
  int window_width,window_height; // size of current screen
  int pixel_x,pixel_y; // pixel size x/y (1<<eig)
  int *colourtrans;

  // icon size info
  _iconsize iconsize;

  // settings for icon deposition for iconizing
  IconizeSetting setting_iconize;
  IconizeStack   setting_iconize_stack;

  // settings for tidying
  IconizeSetting setting_tidy;
  IconizeStack   setting_tidy_stack;

  // grid setting
  int snap_to_grid;

  // prevent adjust removing icons
  int disable_adjust;

  // autosave configuration
  autosave_type autosave;

  // confirm overwriting of files?
  overwrite_type overwrite;

  // doubleclick-hold to open apps?
  int doubleclick_hold;
  
  // drag bits
  char *predrag_state; // array of selection state before drag started
  int drag_x,drag_y;   // coords for the start point for the drag
  source drag_origin;

  // outline text plotting
  int cached_pin; // id of last pin
  int *text_sprite; // sprite area for text rendering
  int *text_savearea; // save area for VDU vars, or NULL
  int text_sprite_w,text_sprite_h;

  // default sticky font
  char *stickyfont;

  // watermark
  watermark_type watermark_location;
  int wm_x_offset,wm_y_offset;
  int *watermark_data;
  int watermark_length;
  BBox watermark_plot_area;
  int watermark_x_xform,watermark_y_xform;
  int watermark_x_scale,watermark_y_scale;

  // toggle state
  int toggle_position;
} _backdrop_state;

extern _backdrop_state backdrop_state;

typedef enum {
  PIN_ADD_CENTRED,
  PIN_ADD_BOTTOM_LEFT
} pin_add_coord_type;

void pin_delete(_backdrop_state *state,int i);
int pin_remove(_backdrop_state *state,int p);
void pin_redraw(_backdrop_state *state,int icon);
void pin_remove_empties(_backdrop_state *state);
void pin_remove_all_task(_backdrop_state *state,int task_handle);
void pin_remove_window(_backdrop_state *state,int window);
void pin_restore_all_windows(_backdrop_state *state);
void pin_find_gap(_backdrop_state *state,IconizeSetting corner,IconizeStack stack_direction,BBox *gap);
int pin_find_object(ObjectId id);
void pinboard_move_selected_icons(_backdrop_state *state,int dx,int dy);
void pinboard_move_icons_from_tinydir(_backdrop_state *state,int drop_x,int drop_y);
void backdrop_redraw_iconarea(_backdrop_state *state,BBox *area);

_backdrop_state *backdrop_init(void);
int backdrop_load_image(_backdrop_state *state,int orientation,char *pathname,int store_filename,int cache_jpeg);
int backdrop_add_pin(_backdrop_state *state,int pin_type,int x,int y,pin_add_coord_type add_type,int filetype,char **leafname,char **text,char **path,int window,int task);
void backdrop_add_pin_command(_backdrop_state *state,char *path,int x,int y,int locked);
void backdrop_add_xpin_command(_backdrop_state *state,char *path,int x,int y,int locked);

int truncate(char **,char **);
void pin_set_spritesize(pin *p,char *sprite);
int pin_find_filename(char *path,int tiny);
void backdrop_redraw_all(_backdrop_state *state);
int message_fontchanged(WimpMessage *message,void *handle);
int message_help(WimpMessage *message,void *handle);
int pin_locate_upcall(_backdrop_state *state,char *fs,char *path,int create_if_missing);
int pin_info_updated(_backdrop_state *state,int p);
int pin_new_localfile(_backdrop_state *state,char **path);
void pin_update_filetypeicons(_backdrop_state *state);
int pin_recheck(_backdrop_state *state,int p);
int pin_iterate_selection(int index,int mask,int skip_locked,int no_tiny);
#define pin_get_selected(mask) pin_iterate_selection(-1,mask,0,0)
#define pin_get_selected_unlocked(mask) pin_iterate_selection(-1,mask,1,1)
#define pin_get_selected_nodir(mask) pin_iterate_selection(-1,mask,0,1)
int pin_count_nodir(int selected,int max,int mask);
void pin_remove_stickies(_backdrop_state *state,int min,int max,int delete_all);
void grid_size(_backdrop_state *state,int *grid_width,int *grid_height);

int upcall_make_filename(char *fs,char *path,char **output);

extern pins *pinlist;


typedef enum {
  BD_SELECT_CLEAR_ALL, // select this one and clear other icons
  BD_SELECT_TOGGLE     // toggle state of this one
} bd_icon_action;

void backdrop_select_icon(_backdrop_state *state,int icon,bd_icon_action action);

void pinboard_save(_backdrop_state *state,char *path);
int pin_update_iconsize(_backdrop_state *state,_iconsize size);

extern MessagesFD msgtrans;
extern ObjectId menu_mainmenu,saveas_win;

// determine if it's a slow-release double click to open a directory
int mouse_dbl_drag(_backdrop_state *);

void filer_opendir(int index);

#endif
