/* Title:   !Attacher      */

#include "wimp.h"
#include "wimpt.h"
#include "win.h"
#include "event.h"
#include "baricon.h"
#include "res.h"
#include "resspr.h"
#include "menu.h"
#include "template.h"
#include "dbox.h"
#include "dboxquery.h"
#include "werr.h"
#include "visdelay.h"
#include "SWItable.h"
#include "msgs.h"
#include "help.h"

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <kernel.h>

/******************************** GLOBAL DATA *****************************/

static BOOL my_win_open = FALSE;
static BOOL unsafe_data = FALSE;
static BOOL ok_not_grey = FALSE;
static BOOL already_been_open = FALSE;
static BOOL split_file = FALSE;
static BOOL keep_ext = FALSE;
static BOOL uu_add_ext = FALSE;
static BOOL base64_add_ext = FALSE;
static BOOL splitting_file = FALSE;
static BOOL already_found_a_file = FALSE;
static BOOL processing_uucode = FALSE;
static BOOL processing_base64 = FALSE;
static BOOL processing_binhex = FALSE;
static BOOL found_end = FALSE;
static BOOL prequit = FALSE;
static BOOL start_open = TRUE;
static BOOL iconbar_icon = TRUE;
static BOOL no_ibar_icon = FALSE;

static _kernel_oserror *pos_error;
static int part_number, split_length, old_split_length, drag_filetype;
static int file_length, chars_read, max_chars, no_parts, total_read;
static int Slen, Mchar, help_icon;
static menu my_menu;
static dbox info_box_handle, split_box_handle, links_box_handle;
static wimp_w action_win_handle, split_win_handle;
static wimp_i my_ibar_icon;
static wimp_caretstr caret_pos;
static wimp_icon result;
static wimp_wstate state;
static char file_sprite[10], file_uua[255], file_uub[255];
static char my_line[255], my_line2[255], my_line3[255], base64_default[100];
static char split_prefix[255], split_suffix[50], default_file[100];
static char *st_result, version_num[10], source_name[55];
static char scrap_dir[256], file_to_code[214];
static FILE *input_file, *output_file;
static fpos_t *file_index, file_position;
static wimp_msgstr open, msg;
static _kernel_swi_regs r;

enum TOKENTYPE { NONE, BLANKS, PUNCT, TAG, NAME, CONTENT };
struct TOKEN {
                char *text;
                int  length;
                int  index;
                enum TOKENTYPE type;
             };

#define icon_help 0
#define icon_decode 1
#define icon_uuencode 2
#define icon_64encode 3
#define icon_info 4
#define icon_savefile 5
#define icon_savebutton 6
#define icon_filename 7
#define icon_cancel 8
#define icon_discard 10
 
/********************** GENERAL EVENT HANDLERS ****************************/

static void text_in_icon(wimp_w this_window,wimp_i this_icon,char *this_text)
{
  wimp_get_icon_info(this_window,this_icon,&result);
  strcpy(result.data.indirecttext.buffer,this_text);
  wimp_set_icon_state(this_window,this_icon,0,0);
}

static void reset_main_window()
{
  text_in_icon(action_win_handle,icon_filename,"");
  wimp_set_icon_state(action_win_handle,icon_filename,0x400000,0x400000);
  wimp_set_icon_state(action_win_handle,icon_savebutton,0x400000,0x400000);
  text_in_icon(action_win_handle,icon_info,"Drag a file to one of the code or decode icons");
  text_in_icon(action_win_handle,icon_help, "");
  wimp_get_icon_info(action_win_handle,icon_savefile,&result);
  strcpy(result.data.indirecttext.validstring,"s!attacher");  
  wimp_set_icon_state(action_win_handle,icon_savefile,0x1700011b,0xffffffff);
  wimp_set_icon_state(action_win_handle,icon_decode,0x2700013f,0xffffffff);
  wimp_set_icon_state(action_win_handle,icon_uuencode,0x2700013f,0xffffffff);
  wimp_set_icon_state(action_win_handle,icon_64encode,0x2700013f,0xffffffff);
  ok_not_grey = FALSE;
}

static void open_main_window()
{
  if(!my_win_open)
    {
      reset_main_window();
      wimp_get_wind_state(action_win_handle,&state);
      state.o.behind=-1;
      if (!already_been_open)
      {
        state.o.box.x0 = 158;
        state.o.box.y0 = 288;
        state.o.box.x1 = 1000;
        state.o.box.y1 = 788;
      }  
      wimp_open_wind(&state.o);
      my_win_open = TRUE;
      already_been_open = TRUE;
    }
}

static void my_iconclick(wimp_i icon)
{
  icon=icon;
  
  if(my_win_open)
  {
    wimp_get_wind_state(action_win_handle,&state);
    state.o.behind=-1;
    wimp_open_wind(&state.o);    
  }
  else open_main_window();
}

static void return_to_wimp()
{
  wimp_eventstr dummy_event;
  
  visdelay_end();
  wimp_poll(0,&dummy_event);
  visdelay_begin();
}

static void exit_function()
{
  if (prequit)
  {
    r.r[0] = 27;
    r.r[1] = (int) "<Wimp$ScrapDir>.Attacher";
    r.r[3] = 1;
    _kernel_swi(OS_FSControl, &r, &r);
  }
}

static void process_help_message(wimp_eventstr *e)
{
  if(e->data.msg.data.helprequest.m.i == my_ibar_icon && e->data.msg.data.helprequest.m.w == -2) 
  {
    help_reply(msgs_lookup("Ibar:This is UUcoder"));
    return;
  }
  if(e->data.msg.data.helprequest.m.w == action_win_handle)
  {
    switch(e->data.msg.data.helprequest.m.i)
    {
      case 1:
        help_reply(msgs_lookup("Action1"));
        break;
      case 2:
        help_reply(msgs_lookup("Action2"));
        break;
      case 3:
        help_reply(msgs_lookup("Action3"));
        break;
      case 6:
        help_reply(msgs_lookup("Action6"));
        break;
      case 7:
        help_reply(msgs_lookup("Action7"));
        break;
      case 8:
        help_reply(msgs_lookup("Action8"));
        break;
      case 9:
        help_reply(msgs_lookup("Action9"));
        break;
      case 10:
        help_reply(msgs_lookup("Actiona"));
        break;
      case 5:
        if (ok_not_grey) help_reply(msgs_lookup("Action5"));
        else help_reply(msgs_lookup("Action"));
        break;
      default:
        help_reply(msgs_lookup("Action"));
    }
  }      
}
  
static void split_fname()
{
  part_number = part_number + 1;
  sprintf(my_line, "%s%02d%s", split_prefix, part_number, split_suffix);
  text_in_icon(action_win_handle ,icon_filename, my_line);
  if(part_number != 1)
  {
    caret_pos.w = action_win_handle;
    caret_pos.i = icon_filename;
    caret_pos.index = strlen (my_line);
    caret_pos.height = -1;
    wimp_set_caret_pos(&caret_pos);
  }
}
 
static BOOL save_split_file(char *filename)
{
  div_t div_result;
  
  output_file = fopen(filename, "wb");
  if (output_file == NULL)
  {
    werr(FALSE,msgs_lookup("error7:Cannot save file here"));
    text_in_icon(action_win_handle,icon_info,"Section coded and ready to save");
    return FALSE;
  }
  input_file = fopen(file_uub,"rb");
  if(part_number != 1) 
  {
    fsetpos(input_file, file_index);
    fprintf(output_file,"%s part %d/%d  [uuencoded by RISC OS Attacher v%s]\n\n-------- CUT -------- CUT -------- CUT -------- CUT ---------\n", source_name,part_number,no_parts,version_num);
  }
  else
  {
    max_chars = (split_length * 1000) - 500;
    div_result = div(max_chars, 62);
    max_chars = div_result.quot * 62;
    total_read = 0;
    div_result = div(file_length, max_chars);
    if (div_result.rem == 0) no_parts = div_result.quot;
    else no_parts = div_result.quot + 1;
  }  
  chars_read = 0;
  if(((file_length-total_read-max_chars) > 0) && ((file_length-total_read-max_chars) < 500)) max_chars = max_chars - 500;
  while((chars_read < max_chars) && splitting_file)
  {
    st_result = fgets(my_line, 255, input_file);
    if (st_result != NULL)
    {
      fputs(my_line, output_file);
      chars_read = chars_read + strlen(my_line);
    }
    else splitting_file = FALSE;
  } 
  total_read = total_read + chars_read; 
  if (splitting_file) 
  {
    fgetpos(input_file, file_index);
    fprintf(output_file,"-------- CUT -------- CUT -------- CUT -------- CUT ---------\n\n%s part %d/%d  [uuencoded by RISC OS Attacher v%s]\n", source_name,part_number,no_parts,version_num);
  }
  fclose(input_file);
  fclose(output_file);
  r.r[0] = 18;
  r.r[1] = (int) filename;
  r.r[2] = 0xfff;
  _kernel_swi(OS_File, &r, &r);
  if (splitting_file)
  {
    split_fname();
    text_in_icon(action_win_handle,icon_info,"Next section of uuencoded file ready to save");
  }
  else 
  {
    remove (file_uub);
    caret_pos.w = action_win_handle;
    caret_pos.i = -1;
    wimp_set_caret_pos(&caret_pos);
    wimp_get_wind_state(action_win_handle, &state);
    wimp_close_wind(action_win_handle);
    reset_main_window();
    wimp_open_wind(&state.o);
    unsafe_data = FALSE;
  }
  return TRUE;
}  

static void handle_link()
{
  dbox_field field_number;
  wimp_eventstr e;
  
  strcpy(msg.data.chars, "");
  dbox_show(links_box_handle);
  field_number = dbox_fillin(links_box_handle);
  switch (field_number)
  {
    case 0:
      strcpy(msg.data.chars, "http://www.bramber.demon.co.uk/software/attach.zip");
      break;
        
    case 3:
      strcpy(msg.data.chars, "http://www.bramber.demon.co.uk/john/atin.html");
      break;
        
    case 4:
      strcpy(msg.data.chars, "http://www.bramber.demon.co.uk/john/athis.html");
      break;
        
    case 5:
      strcpy(msg.data.chars, "http://www.bramber.demon.co.uk/john/soft.html");
      break;
          
    case 6:
      strcpy(msg.data.chars, "mailto:john@bramber.demon.co.uk");
      break;
  }
  dbox_hide(links_box_handle);
  if (strlen(msg.data.chars) == 0) return;
  msg.hdr.size = 256;
  msg.hdr.your_ref = 0;
  msg.hdr.action = 0x4af80; 
  wimp_sendmessage(18, &msg, 0);
  wimp_poll( 0x1973, &e);
  if((e.e == wimp_ESENDWANTACK) && (e.data.msg.hdr.action ==  wimp_MDATAOPEN)) wimp_poll( 0x1973, &e);
  if (field_number == 6) 
  {
    os_read_var_val("Alias$URLOpen_mailto", my_line, 255);
    if (strlen(my_line) != 0)
    {
      if (strstr(my_line, "Messenger") != NULL)
      {
        strcpy(my_line, "URLOpen_mailto ");
        strcat(my_line, msg.data.chars);
        wimp_starttask(my_line);
      }
    }
  }
  else 
  {
    os_read_var_val("Alias$URLOpen_HTTP", my_line, 255);
    if (strlen(my_line) != 0)
    {
      if (strstr(my_line, "ArcWeb") != NULL)
      {
        strcpy(my_line, "URLOpen_HTTP ");
        strcat(my_line, msg.data.chars);
        wimp_starttask(my_line);
      }
    }
  }  
}

static void convert_sprite_details()
{
  sprintf(file_sprite, "file_%03x\0", drag_filetype);
  if(wimp_spriteop(40,file_sprite) != 0) strcpy(file_sprite,"file_xxx");
}
 
static void start_the_drag()
{
  int wind_limit, wind_factor;
  wimp_dragstr drag;
  
  drag.window = action_win_handle;
  drag.type = 5;
  drag.parent.x0 = -20;
  drag.parent.y0 = -20;
  r.r[0] = -1;
  r.r[1] = 11;
  _kernel_swi(OS_ReadModeVariable, &r, &r);
  wind_limit = r.r[2];
  r.r[0] = -1;
  r.r[1] = 4;
  _kernel_swi(OS_ReadModeVariable, &r, &r);
  wind_factor = r.r[2];
  drag.parent.x1 = (wind_limit <<wind_factor) + 20;
  r.r[0] = -1;
  r.r[1] = 12;
  _kernel_swi(OS_ReadModeVariable, &r, &r);
  wind_limit = r.r[2];
  r.r[0] = -1;
  r.r[1] = 5;
  _kernel_swi(OS_ReadModeVariable, &r, &r);
  wind_factor = r.r[2];
  drag.parent.y1 = (wind_limit << wind_factor) + 20;  
  wimp_get_icon_info(action_win_handle, icon_savefile, &result);
  wimp_get_wind_state(action_win_handle, &state);
  drag.box.x0 = result.box.x0 + state.o.box.x0 + 40;
  drag.box.x1 = result.box.x1 + state.o.box.x0 - 40;
  drag.box.y0 = result.box.y0 + state.o.box.y1 + 38;
  drag.box.y1 = result.box.y1 + state.o.box.y1 - 40;
  r.r[0] = 161;
  r.r[1] =28;
  _kernel_swi(OS_Byte, &r, &r);
  if((r.r[2] & 2) == 2) 
  {
    convert_sprite_details();
    r.r[0] = 197;
    r.r[1] = 1;
    r.r[2] = (int) &file_sprite;
    r.r[3] = (int) &drag.box;
    r.r[4] = (int) &drag.parent;
    _kernel_swi(DragASprite_Start, &r, &r);
  }
  else wimp_drag_box(&drag);
}

static void reply_with_scrap(wimp_eventstr *e)
{
  e->data.msg.hdr.your_ref = e->data.msg.hdr.my_ref;
  e->data.msg.hdr.action = wimp_MDATASAVEOK;
  e->data.msg.hdr.size = 256;
  e->data.msg.data.datasaveok.estsize = -1;
  sprintf(e->data.msg.data.datasaveok.name,"<Wimp$ScrapDir>.Attacher.!!Scrap!!");
  wimpt_noerr(wimp_sendmessage(wimp_ESENDWANTACK,&e->data.msg,e->data.msg.hdr.task));
}

static void acknowledge_receipt(wimp_eventstr *e)
{
  e->data.msg.hdr.your_ref = e->data.msg.hdr.my_ref;
  e->data.msg.hdr.action = wimp_MDATALOADOK;
  wimpt_noerr(wimp_sendmessage(wimp_ESEND,&e->data.msg,e->data.msg.hdr.task));
}

static void load_choices_vals()
{
  dbox_getfield(split_box_handle, 8, split_prefix, 255);
  dbox_getfield(split_box_handle, 10, split_suffix, 50);
  dbox_getfield(split_box_handle, 14, default_file,255);
  dbox_getfield(split_box_handle, 26, base64_default,255);
  split_length = dbox_getnumeric(split_box_handle, 4);
  if (split_length < 2) split_length = 2;
  dbox_setnumeric(split_box_handle, 4, split_length);
  wimp_get_icon_info(split_win_handle, 1, &result);
  if((result.flags & wimp_ISELECTED) == 0) split_file = FALSE;
  else split_file =TRUE;
  wimp_get_icon_info(split_win_handle, 24, &result);
  if((result.flags & wimp_ISELECTED) == 0) keep_ext = FALSE;
  else keep_ext = TRUE;
  wimp_get_icon_info(split_win_handle, 28, &result);
  if((result.flags & wimp_ISELECTED) == 0) uu_add_ext = FALSE;
  else uu_add_ext = TRUE;
  wimp_get_icon_info(split_win_handle, 29, &result);
  if((result.flags & wimp_ISELECTED) == 0) base64_add_ext = FALSE;
  else base64_add_ext = TRUE;
  wimp_get_icon_info(split_win_handle, 31, &result);
  if((result.flags & wimp_ISELECTED) == 0) start_open = FALSE;
  else start_open = TRUE;
  wimp_get_icon_info(split_win_handle, 32, &result);
  if((result.flags & wimp_ISELECTED) == 0) iconbar_icon = FALSE;
  else iconbar_icon = TRUE;
}

static void handle_uu_choices()
{
  BOOL keep_loop = TRUE;
  wimp_iconflags old_flags, old_flags1, old_flags2, old_flags3, old_flags4;
  wimp_iconflags old_flags5;
  BOOL old_uu_add_ext, old_base64_add_ext, old_keep_ext, old_split_file;
  BOOL old_iconbar_icon, old_start_open;
     
  dbox_show(split_box_handle);
  old_split_file = split_file;
  old_keep_ext = keep_ext;
  old_uu_add_ext = uu_add_ext;
  old_base64_add_ext = base64_add_ext;
  old_iconbar_icon = iconbar_icon;
  old_start_open = start_open;
  wimp_get_icon_info(split_win_handle, 1, &result);
  old_flags = result.flags;
  wimp_get_icon_info(split_win_handle, 24, &result);
  old_flags1 = result.flags;
  wimp_get_icon_info(split_win_handle, 28, &result);
  old_flags2 = result.flags;
  wimp_get_icon_info(split_win_handle, 29, &result);
  old_flags3 = result.flags;
  wimp_get_icon_info(split_win_handle, 31, &result);
  old_flags4 = result.flags;
  wimp_get_icon_info(split_win_handle, 32, &result);
  old_flags5 = result.flags;
  old_split_length = dbox_getnumeric(split_box_handle, 4);
  if(((old_flags4 & wimp_ISELECTED) == 0) && ((old_flags5 & wimp_ISELECTED) == 0))
  {
    wimp_set_icon_state(split_win_handle, 32, wimp_ISELECTED, wimp_ISELECTED);
    old_flags5 = old_flags5 + wimp_ISELECTED;
  }

  while (keep_loop)
  {
    switch(dbox_fillin(split_box_handle))
    {
      case 5:
        dbox_hide(split_box_handle);
        load_choices_vals();
        keep_loop = FALSE;
        break;
            
      case 6:
        split_length = dbox_getnumeric(split_box_handle, 4);
        split_length = split_length - 1;
        if (split_length < 2) split_length = 2;
        dbox_setnumeric(split_box_handle, 4, split_length);
        break;
          
      case 7:
        split_length = dbox_getnumeric(split_box_handle, 4);
        split_length = split_length + 1;
        dbox_setnumeric(split_box_handle, 4, split_length);
        break;
      
      case 11:
        dbox_hide(split_box_handle);
        load_choices_vals();
        keep_loop = FALSE;
        output_file = fopen("<Attacher$Dir>.Choices","wb");
        if (output_file == NULL)
        {
          werr(FALSE, msgs_lookup("error4:Cannot create Choices file"));
          break;
        }
        if (split_file) fputs("0\n", output_file);
        else fputs("1\n", output_file);
        split_length = dbox_getnumeric(split_box_handle, 4);
        if (split_length < 2) split_length = 2;
        dbox_setnumeric(split_box_handle, 4, split_length);
        fprintf(output_file,"%u\n",split_length);
        fprintf(output_file,"%s\n",split_prefix);
        fprintf(output_file,"%s\n",split_suffix);
        fprintf(output_file,"%s\n",default_file);
        fprintf(output_file,"%s\n",base64_default);
        if (keep_ext) fputs("0\n", output_file);
        else fputs("1\n", output_file);
        if (uu_add_ext) fputs("0\n", output_file);
        else fputs("1\n", output_file);
        if (base64_add_ext) fputs("0\n", output_file);
        else fputs("1\n", output_file);
        if (start_open) fputs("1\n", output_file);
        else fputs("0\n", output_file);
        if (iconbar_icon || !start_open) fputs("1\n", output_file);
        else fputs("0\n", output_file);
        fclose(output_file);
        break;      

      case 9:
      default:
        dbox_hide(split_box_handle);
        split_file = old_split_file;
        keep_ext = old_keep_ext;
        uu_add_ext = old_uu_add_ext;
        base64_add_ext = old_base64_add_ext;
        wimp_set_icon_state(split_win_handle, 1, old_flags, 0xffffffff);
        wimp_set_icon_state(split_win_handle, 24, old_flags1, 0xffffffff);
        wimp_set_icon_state(split_win_handle, 28, old_flags2, 0xffffffff);
        wimp_set_icon_state(split_win_handle, 29, old_flags3, 0xffffffff);
        wimp_set_icon_state(split_win_handle, 31, old_flags4, 0xffffffff);
        wimp_set_icon_state(split_win_handle, 32, old_flags5, 0xffffffff);
        dbox_setnumeric(split_box_handle, 4, old_split_length);
        split_length = dbox_getnumeric(split_box_handle, 4);
        dbox_setfield(split_box_handle, 8, split_prefix);
        dbox_setfield(split_box_handle, 10, split_suffix);
        dbox_setfield(split_box_handle, 14, default_file);
        dbox_setfield(split_box_handle, 26, base64_default);
        keep_loop = FALSE;
        break;
    }
  }
}

static void check_scrap_exists()
{
  FILE *file_1;
  
  file_1 = fopen("<Wimp$ScrapDir>.Attacher", "w");
  if(file_1 != NULL)
  {
    fclose(file_1);
    remove("<Wimp$ScrapDir>.Attacher");  
    strcpy(scrap_dir, "<Wimp$ScrapDir>.Attacher");
    r.r[0] = 8;
    r.r[1] = (int) scrap_dir;
    _kernel_swi(OS_File, &r, &r);
    sprintf(file_uua, "%s.!!uua!!\0", scrap_dir);
    sprintf(file_uub, "%s.!!uub!!\0", scrap_dir);
  }
}  

static void test_for_full_scrap()
{
  FILE *file_1, *file_2, *file_3;
  char file_full[256], file_fuller[256];
  
  if (unsafe_data) return;
  check_scrap_exists();
  
  file_1 = fopen(file_uub, "w");
  sprintf(file_full, "%s.!ghfddgopq\0", scrap_dir);
  file_2 = fopen(file_full, "w");
  sprintf(file_fuller, "%s.!ghfdskdwq\0", scrap_dir);
  file_3 = fopen(file_fuller, "w");
  if (file_3 == NULL)
  {
    fclose(file_1);
    fclose(file_2);
    remove(file_uub);
    remove(file_fuller);
    strcat(scrap_dir, ".~zq");
    r.r[0] = 8;
    r.r[1] = (int) scrap_dir;
    _kernel_swi(OS_File, &r, &r);
    sprintf(file_uua, "%s.!!uua!!\0", scrap_dir);
    sprintf(file_uub, "%s.!!uub!!\0", scrap_dir);
    return;
  }
  fclose(file_1);
  fclose(file_2);
  fclose(file_3);
  remove(file_uub);
  remove(file_full);
  remove(file_fuller);
}

/******************************** saving files ***************************/

static void setup_to_save(char *fname, int ftype, int indicator)
{
  int i, len;
  char invalid_chars[20], *inv_point, *invalid_char;
  
  wimp_set_icon_state(action_win_handle,icon_decode,0x400000,0x400000);
  wimp_set_icon_state(action_win_handle,icon_uuencode,0x400000,0x400000);
  wimp_set_icon_state(action_win_handle,icon_64encode,0x400000,0x400000);
  len = strlen(fname) + 1;
  for(i=0; i<=len; i++) if((int) fname[i] < 32) fname[i] = 0;
  strcpy(invalid_chars, " &@%*#^$:,|\x5c\x22");
  for (i=0; i<strlen(invalid_chars); i++)
  {
    inv_point = invalid_chars + 1;
    invalid_char = fname - 1;
    while (invalid_char != NULL)
    {
      invalid_char = strchr(invalid_char+1, invalid_chars[i]);
      if((invalid_char != NULL)  && (*invalid_char == 44)) *invalid_char = 0;
      else if (invalid_char != NULL) *invalid_char = 95;
    }
  }
  if((indicator == 1) && split_file)
  {
    r.r[0] = 17;
    r.r[1] = (int) file_uub;
    _kernel_swi(OS_File, &r, &r);
    file_length = r.r[4];
    if (file_length > (split_length * 1000))
    {
      part_number = 0;
      split_fname();
      splitting_file = TRUE;
    }
  }
  if (!splitting_file) 
  {
    text_in_icon(action_win_handle, icon_filename, fname);
    text_in_icon(action_win_handle, icon_info, "File ready to save, double click, or drag the file icon, or click on 'Save'");
  }
  else text_in_icon(action_win_handle, icon_info, "First part of file ready to save, double click, or drag, or click on 'Save'");
  sprintf(my_line, "R2;sfile_%03x\0", ftype);
  wimp_get_icon_info(action_win_handle,icon_savefile,&result);
  strcpy(result.data.indirecttext.validstring,my_line);  
  wimp_set_icon_state(action_win_handle,icon_savefile,0x813f,0xffff);
  wimp_set_icon_state(action_win_handle,icon_filename,0x400000,0);
  wimp_set_icon_state(action_win_handle,icon_savebutton,0x400000,0);
  r.r[0] = 18;
  r.r[1] = (int) file_uub;
  r.r[2] = ftype;
  _kernel_swi(OS_File, &r, &r);
  caret_pos.w = action_win_handle;
  caret_pos.i = icon_filename;
  caret_pos.height = -1;
  wimp_get_icon_info(action_win_handle,icon_filename,&result);
  caret_pos.index = strlen(result.data.indirecttext.buffer);
  wimp_set_caret_pos(&caret_pos);
  ok_not_grey = TRUE;
  drag_filetype = ftype;
}


/****************************** Decoding files ******************************/

static void base64_decode_and_save()
{
  wimp_get_icon_info(split_win_handle, 24, &result);
  if((result.flags & wimp_ISELECTED) == 0) r.r[0] = 2;
  else r.r[0] = 3;
  r.r[1] = (int) file_uua;
  r.r[2] = (int) file_uub;
  pos_error = _kernel_swi(TypeTrans_FromBase64, &r, &r);
  remove(file_uua);
  if (pos_error != NULL)
  {
    wimp_reporterror((os_error *) pos_error, 0, "Attacher");
    wimp_get_wind_state(action_win_handle, &state);
    wimp_close_wind(action_win_handle);
    reset_main_window();
    wimp_open_wind(&state.o);
    processing_base64 = FALSE;
    unsafe_data = FALSE;
    return;
  }
  setup_to_save((char*) r.r[4], r.r[3], 0);
  visdelay_end();
}

static void check_extra(char *the_line)
{
  char a_buffer[256];
  
  fgetpos(input_file, &file_position);
  st_result = fgets(a_buffer, 255, input_file);
  if (st_result == NULL)
  {
    fsetpos(input_file, &file_position);
    return;
  }
  if ((strncmp(a_buffer, "x-", 2) == 0) || (strncmp(a_buffer, "X-", 2) == 0)) st_result = fgets(a_buffer, 255, input_file);
  if ((strncmp(a_buffer, "x-", 2) == 0) || (strncmp(a_buffer, "X-", 2) == 0)) st_result = fgets(a_buffer, 255, input_file);
  if ((strncmp(a_buffer, "x-", 2) == 0) || (strncmp(a_buffer, "X-", 2) == 0)) st_result = fgets(a_buffer, 255, input_file);
  if ((strncmp(a_buffer, "x-", 2) == 0) || (strncmp(a_buffer, "X-", 2) == 0)) st_result = fgets(a_buffer, 255, input_file);
  if ((strncmp(a_buffer, " ", 1) == 0) || (strncmp(a_buffer, "\t", 1) == 0)|| (strncmp(a_buffer, "name", 4) == 0)) 
  {
    the_line[strlen(the_line) -1] = 0;
    strcat(the_line, a_buffer);
  }
  else fsetpos(input_file, &file_position);
  return;
}

static void decode64(wimp_eventstr *e)
{
  BOOL first_line = FALSE;
  BOOL second_line = FALSE;
  BOOL disposition = FALSE;
  BOOL boundary = FALSE;
  int i;
  char buf[36];
  
  return_to_wimp();
  strcpy(file_to_code, e->data.msg.data.dataload.name);
  input_file = fopen(e->data.msg.data.dataload.name, "rb");
  while (!feof(input_file) && !first_line)
  {
    st_result = fgets(my_line, 255, input_file);
    if(st_result == NULL) break;
    for( i=0;i<15;i++) buf[i] = my_line[i] | 0x20;
    if(strncmp(buf, "content-type: ", 14) == 0) 
    { 
      check_extra(my_line);
      first_line = TRUE;
    }  
  }
  if (!first_line)
  {
    werr(FALSE, msgs_lookup("errore:No base64"));
    reset_main_window();
    unsafe_data = FALSE;
    processing_base64 = FALSE;
    remove("<Wimp$ScrapDir>.Attacher.!!Scrap!!"); 
    fclose(input_file);
    return;
  }
  while (!feof(input_file) && !second_line)
  {
    st_result = fgets(my_line2, 255, input_file);
    if(st_result == NULL) break;
    for( i=0;i<34;i++) buf[i] = my_line2[i] | 0x20;
    if(strncmp(buf, "content-type: ", 14) == 0)
    {
      for (i=0;i<255;i++) my_line[i] = my_line2[i];
      check_extra(my_line);
      disposition = FALSE;
    }
    if(strncmp(buf, "content-disposition: ", 21) == 0)
    {
      for (i=0;i<255;i++) my_line3[i] = my_line2[i];
      check_extra(my_line3);
      disposition = TRUE;
    }
    if(strncmp(buf, "content-transfer-encoding: base64", 33) == 0) second_line = TRUE;
  }
  if (!second_line)
  {
    werr(FALSE, msgs_lookup("errore:No base64"));
    reset_main_window();
    unsafe_data = FALSE;
    processing_base64 = FALSE;
    remove("<Wimp$ScrapDir>.Attacher.!!Scrap!!"); 
    fclose(input_file);
    return;
  }
  text_in_icon(action_win_handle, icon_info, "Processing base64 coded file");
  return_to_wimp();
  fgetpos(input_file, &file_position);
  if (!disposition)
  {
    fgets(my_line3, 100, input_file);
    for( i=0;i<21;i++) buf[i] = my_line3[i] | 0x20;
    if(strncmp(buf, "content-disposition: ", 21) == 0) 
    {
      check_extra(my_line3);
      disposition = TRUE;
    }
  }
  output_file = fopen(file_uua, "wb");
  fputs(my_line, output_file);
  if (disposition) fputs(my_line3, output_file);
  fputs(my_line2, output_file);
  fgets(my_line, 255, input_file);
  fputs("\n", output_file);
  fsetpos(input_file, &file_position);
  fgets(my_line, 255, input_file);
  while (strlen(my_line) > 2) fgets(my_line, 255, input_file);
  fgets(my_line, 255, input_file);
  boundary = FALSE;
  while ((strlen(my_line) > 2) && !feof(input_file) && !boundary)
  {
    fputs(my_line, output_file);
    fgets(my_line, 255, input_file);
    if(strncmp(my_line, "-", 1) == 0) boundary = TRUE;
  }
  fputs("\n", output_file);
  fclose(output_file);
  fgetpos(input_file, &file_position);
  fclose(input_file);
  return_to_wimp();
  base64_decode_and_save();
  return;
}

static void check_for_next_base64()
{
  BOOL first_line = FALSE;
  BOOL second_line = FALSE;
  BOOL disposition = FALSE;
  int i;
  char buf[36];
  
  return_to_wimp();
  input_file = fopen(file_to_code, "rb");
  fsetpos(input_file, &file_position);
  while (!feof(input_file) && !first_line)
  {
    st_result = fgets(my_line, 255, input_file);
    if(st_result == NULL) break;
    for( i=0;i<15;i++) buf[i] = my_line[i] | 0x20;
    if(strncmp(buf, "content-type: ", 14) == 0) first_line = TRUE;   
  }
  if (!first_line)
  {
    reset_main_window();
    processing_base64 = FALSE;
    fclose(input_file);
    remove("<Wimp$ScrapDir>.Attacher.!!Scrap!!"); 
    visdelay_end();
    return;
  }
  while (!feof(input_file) && !second_line)
  {
    st_result = fgets(my_line2, 255, input_file);
    if(st_result == NULL) break;
    for( i=0;i<34;i++) buf[i] = my_line2[i] | 0x20;
    if(strncmp(buf, "content-type: ", 14) == 0)
    {
      for (i=0;i<255;i++) my_line[i] = my_line2[i];
      disposition = FALSE;
    }
    if(strncmp(buf, "content-disposition: ", 21) == 0)
    {
      for (i=0;i<255;i++) my_line3[i] = my_line2[i];
      disposition = TRUE;
    }
    if(strncmp(buf, "content-transfer-encoding: base64", 33) == 0) second_line = TRUE;
  }
  if (!second_line)
  {
    reset_main_window();
    processing_base64 = FALSE;
    fclose(input_file);
    remove("<Wimp$ScrapDir>.Attacher.!!Scrap!!"); 
    visdelay_end();
    return;
  }
  unsafe_data = TRUE;
  text_in_icon(action_win_handle, icon_info, "Processing base64 coded file");
  if (!disposition)
  {
    fgetpos(input_file, &file_position);
    fgets(my_line3, 100, input_file);
    for( i=0;i<21;i++) buf[i] = my_line3[i] | 0x20;
    if(strncmp(buf, "content-disposition: ", 21) == 0) disposition = TRUE;
  }
  return_to_wimp();
  output_file = fopen(file_uua, "wb");
  fputs(my_line, output_file);
  if (disposition) fputs(my_line3, output_file);
  fputs(my_line2, output_file);
  fputs("\n", output_file);
  fsetpos(input_file, &file_position);
  fgets(my_line, 255, input_file);
  while (strlen(my_line) > 2) fgets(my_line, 255, input_file);
  fgets(my_line, 255, input_file);
  while ((strlen(my_line) > 2) && !feof(input_file))
  {
    fputs(my_line, output_file);
    fgets(my_line, 255, input_file);
  }
  fputs("\n", output_file);
  fclose(output_file);
  fgetpos(input_file, &file_position);
  fclose(input_file);
  return_to_wimp();
  base64_decode_and_save();
  return;
}

static void decode_and_save()
{
  wimp_get_icon_info(split_win_handle, 24, &result);
  if((result.flags & wimp_ISELECTED) == 0) r.r[0] = 2;
  else r.r[0] = 3;
  r.r[1] = (int) file_uua;
  r.r[2] = (int) file_uub;
  pos_error = _kernel_swi(TypeTrans_FromUUcode, &r, &r);
  remove(file_uua);
  if (pos_error != NULL)
  {
    wimp_reporterror((os_error *) pos_error, 0, "Attacher");
    wimp_get_wind_state(action_win_handle, &state);
    wimp_close_wind(action_win_handle);
    reset_main_window();
    wimp_open_wind(&state.o);
    processing_uucode = FALSE;
    unsafe_data = FALSE;
    return;
  }
  strcpy(my_line, (char*)r.r[4]);
  setup_to_save(my_line, r.r[3], 0);
  visdelay_end();
}

static BOOL transfer_body()
{
  found_end = FALSE;
  while (TRUE)
  {
    fputs(my_line,output_file);
    st_result = fgets(my_line, 255, input_file);
    if (st_result == NULL) break;
    if ((my_line[0] != Mchar) || (strlen(my_line) != Slen)) break;
  }
  if (st_result != NULL)
  {
    st_result = fgets(my_line2, 255, input_file);
    if (st_result != NULL)
    {
      if (strncmp(my_line2, "end", 3) == 0)
      {
        fputs(my_line, output_file);
        if ((strncmp(my_line, "`", 1) != 0) && (Slen > 60)) fputs("`\n", output_file);
        fputs(my_line2, output_file);
        found_end = TRUE;
      }
      else
      {
        st_result = fgets(my_line3, 255, input_file);
        if (st_result != NULL)
        {
          if (strncmp(my_line3, "end", 3) == 0)
          {
            fputs(my_line, output_file);
            fputs(my_line2, output_file);
            fputs(my_line3, output_file);
            found_end = TRUE;
          }
        }
      }
    }
  }
  fgetpos(input_file, &file_position);
  if (found_end)
  {
    st_result = fgets(my_line, 255, input_file);
    if (st_result != NULL) fputs(my_line, output_file);
    text_in_icon(action_win_handle, icon_info, "Decoding complete uuencoded file");
    return_to_wimp();
  }
  fclose(output_file);
  fclose(input_file);
  if (found_end) return(TRUE);
  text_in_icon(action_win_handle, icon_info, "Waiting for next section of uuencoded file ...");
  visdelay_end();
  return(FALSE);
}

static void check_for_next()
{
  wimp_wstate state;
  
  visdelay_begin();
  input_file = fopen(file_to_code, "rb");
  if (input_file == NULL)
  {
    werr(FALSE, msgs_lookup("error8: can't open source file"));
    reset_main_window();
    return;
  }
  fsetpos(input_file, &file_position);
  while (!feof(input_file))
  {
    fgets(my_line, 255, input_file);
    if(strncmp(my_line, "begin ", 6) == 0) break;
  }
  if (!feof(input_file))
  {
    text_in_icon(action_win_handle, icon_info, "Processing a further uucoded file");
    return_to_wimp();
    output_file = fopen(file_uua, "wb");
    fputs(my_line, output_file);
    st_result = fgets(my_line, 255, input_file);
    if (st_result == NULL)
    {
      werr(FALSE, msgs_lookup("error9:Faulty file"));
      fclose(input_file);
      fclose(output_file);
      reset_main_window();
      remove(file_uua);
      return;
    }
    Mchar = (int) my_line[0];
    Slen = strlen(my_line);
    unsafe_data = TRUE;
    if (transfer_body()) decode_and_save();
    return;
  } 
  fclose(input_file); 
  remove("<Wimp$ScrapDir>.Attacher.!!Scrap!!"); 
  wimp_get_wind_state(action_win_handle, &state);
  wimp_close_wind(action_win_handle);
  reset_main_window();
  wimp_open_wind(&state.o);
  processing_uucode = FALSE;
  visdelay_end();
}

static void examine_file(wimp_eventstr *e)
{
  int j;
  
  text_in_icon(action_win_handle, icon_info, "Processing file");
  visdelay_begin();
  return_to_wimp();
  input_file = fopen(e->data.msg.data.dataload.name, "rb");
  strcpy(file_to_code, e->data.msg.data.dataload.name);
  if (input_file == NULL)
  {
    werr(FALSE, msgs_lookup("error8: can't open source file"));
    reset_main_window();
    return;
  }
  while (!feof(input_file) && !processing_uucode && !processing_base64 && !processing_binhex)
  {
    fgets(my_line, 255, input_file);
    for(j=0;j<34;j++) my_line2[j] = my_line[j] | 0x20;
    if(strncmp(my_line, "begin ", 6) == 0) processing_uucode = TRUE;
    if(strncmp(my_line2, "content-transfer-encoding: base64", 33) == 0) processing_base64 = TRUE;
    if(strncmp(my_line, "(This file must be converted with BinHex 4.0)", 45) == 0) processing_binhex = TRUE;
  }
  if (processing_uucode)
  {
    text_in_icon(action_win_handle, icon_info, "Processing uucoded file");
    wimp_set_icon_state(action_win_handle,icon_uuencode,0x400000,0);
    wimp_set_icon_state(action_win_handle,icon_64encode,0x400000,0);
    return_to_wimp();
    output_file = fopen(file_uua, "wb");
    fputs(my_line, output_file);
    st_result = fgets(my_line, 255, input_file);
    if (st_result == NULL)
    {
      werr(FALSE, msgs_lookup("error9:Faulty file"));
      fclose(input_file);
      fclose(output_file);
      reset_main_window();
      remove(file_uua);
      return;
    }
    Mchar = (int) my_line[0];
    Slen = strlen(my_line);
    unsafe_data = TRUE;
    if (transfer_body()) decode_and_save();
    return;
  }  
  if (processing_base64)
  {
    fclose(input_file);
    unsafe_data = TRUE;
    decode64(e);
    return;
  } 
  if (processing_binhex)
  {
    fclose(input_file);
    werr(FALSE, msgs_lookup("errorf:No Binhex decoder"));
    visdelay_end();
    wimp_get_wind_state(action_win_handle, &state);
    wimp_close_wind(action_win_handle);
    reset_main_window();
    wimp_open_wind(&state.o);
    processing_binhex = FALSE;
    return;    
  }
  fclose(input_file);  
  visdelay_end();
  werr(FALSE, msgs_lookup("error2:No coded data"));
  wimp_get_wind_state(action_win_handle, &state);
  wimp_close_wind(action_win_handle);
  reset_main_window();
  wimp_open_wind(&state.o);
  return;
}

static void next_uucode_bit(wimp_eventstr *e)
{
  text_in_icon(action_win_handle, icon_info, "Processing file");
  visdelay_begin();
  return_to_wimp();
  input_file = fopen(e->data.msg.data.dataload.name, "rb");
  strcpy(file_to_code, e->data.msg.data.dataload.name);
  if (input_file == NULL)
  {
    werr(FALSE, msgs_lookup("error8: can't open source file"));
    reset_main_window();
    return;
  }
  while (feof(input_file) == 0)
  {
    fgets(my_line, 255, input_file);
    if ((my_line[0] == Mchar) && (strlen(my_line) == Slen)) break;
  }
  text_in_icon(action_win_handle, icon_info, "Processing uucoded file");
  return_to_wimp();
  output_file = fopen(file_uua, "ab");
  if (transfer_body()) decode_and_save();
  return;  
}

/******************************* General Handlers ***********************/

static BOOL save_to_file(char *filename)
{
  BOOL success = TRUE;
  
  pos_error = NULL;
  visdelay_begin();
  text_in_icon(action_win_handle,icon_info,"Saving file");
  if (splitting_file) success = save_split_file(filename);
  else
  {
    r.r[0] = 26;
    r.r[1] = (int) file_uub;
    r.r[2] = (int) filename;
    r.r[3] = 130;
    pos_error = _kernel_swi(XOS_FSControl, &r, &r);
  }
  if(pos_error != NULL || !success) 
  {
    wimp_reporterror((os_error *) pos_error, 17, "Attacher");
    text_in_icon(action_win_handle,icon_info,"Correct the name and save the file");
    success = TRUE;
    return TRUE;
  }
  visdelay_end();
  if (splitting_file) 
  {
    split_fname();
    return TRUE;
  }
  caret_pos.w = action_win_handle;
  caret_pos.i = -1;
  wimp_set_caret_pos(&caret_pos);
  wimp_get_wind_state(action_win_handle, &state);
  wimp_close_wind(action_win_handle);
  reset_main_window();
  if (processing_uucode || processing_base64)
  {
    wimp_set_icon_state(action_win_handle,icon_uuencode,0x400000,0);
    wimp_set_icon_state(action_win_handle,icon_64encode,0x400000,0);
  }
  wimp_open_wind(&state.o);
  unsafe_data = FALSE;
  return TRUE;
}

static void click_ok()
{
  wimp_get_icon_info(action_win_handle,icon_filename,&result);
  if (!strstr(result.data.indirecttext.buffer,"::"))
  {
    werr(FALSE,msgs_lookup("error1:To save drag the file to a directory"));
    return;
  }
  if (splitting_file) save_split_file(result.data.indirecttext.buffer);
  else save_to_file(result.data.indirecttext.buffer);
}

static BOOL launch_file(char *fname, int ftype, BOOL help)
{
  wimp_eventstr e;
  
  open.hdr.size = 256;
  open.hdr.your_ref = 0;
  open.hdr.action = wimp_MDATAOPEN;
  open.data.dataopen.w = action_win_handle;
  open.data.dataopen.i = 0;
  open.data.dataopen.x = 0;
  open.data.dataopen.y = 0;
  open.data.dataopen.size = 0;
  open.data.dataopen.type = ftype;
  strcpy(open.data.dataopen.name, fname);
  wimp_sendmessage(18, &open, 0);
  wimp_poll( 0x1973, &e);
  if((e.e == wimp_ESENDWANTACK) && (e.data.msg.hdr.action ==  wimp_MDATAOPEN)) wimp_poll( 0x1973, &e);
  if((e.e != wimp_ESEND) && (e.e != wimp_ESENDWANTACK) && (e.e != wimp_EACK)) return TRUE;
  if ((e.e != wimp_EACK) || (e.data.msg.hdr.action != 5)) 
  {
    unsafe_data = FALSE;
    return TRUE;
  }
  sprintf(my_line3, "Alias$@RunType_%03x\0", ftype);
  r.r[0] = (int) my_line3;
  r.r[2] = -1;
  _kernel_swi(OS_ReadVarVal, &r, &r);
  if (r.r[2] == 0)
  {
    werr(FALSE, msgs_lookup("error6:No run action"));
    if (help) return FALSE;
    r.r[0] = 25;
    r.r[1] = (int) fname;
    r.r[2] = (int) file_uub;
    _kernel_swi(OS_FSControl, &r, &r);
    return FALSE;
  }
  return_to_wimp();
  wimp_starttask(fname);
  unsafe_data = FALSE;
  visdelay_end();
  return TRUE;
}

static void dataload_routine (wimp_eventstr *e)
{
  check_scrap_exists();
  if(e->data.msg.data.dataload.i == 2) /* uuencode */
  {
    visdelay_begin();
    test_for_full_scrap();
    text_in_icon(action_win_handle, icon_info, "uuencoding file");
    return_to_wimp();
    if (uu_add_ext) r.r[0] = 37;
    else r.r[0] = 36;
    r.r[1] = (int) e->data.msg.data.dataload.name;
    r.r[2] = (int) file_uub;
    r.r[3] = e->data.msg.data.dataload.type;
    r.r[4] = 0;
    pos_error = _kernel_swi(TypeTrans_ToUUcode, &r, &r);
    return_to_wimp();
    if (pos_error == NULL) setup_to_save(default_file, 0xfff, 1);
    else 
    {
      werr(FALSE , msgs_lookup("errora:cannot encode file"));
      remove(file_uub);
    }
    unsafe_data = TRUE;
    remove("<Wimp$Scrap>");
    visdelay_end();
    return;
  }
  if(e->data.msg.data.dataload.i == 1) /* uudecode */
  {
    if (processing_uucode) next_uucode_bit(e);
    test_for_full_scrap();
    if (!processing_base64 && !processing_uucode) examine_file(e);
    return;
  }
  if(e->data.msg.data.dataload.i == 3) /* base64 encode */
  {
    visdelay_begin();
    test_for_full_scrap();
    text_in_icon(action_win_handle, icon_info, "MIME base64 coding file");
    return_to_wimp();
    if (base64_add_ext) r.r[0] = 3;
    else r.r[0] = 2;
    r.r[1] = (int) e->data.msg.data.dataload.name;
    r.r[2] = (int) file_uub;
    r.r[3] = e->data.msg.data.dataload.type;
    r.r[4] = 0;
    pos_error = _kernel_swi(TypeTrans_ToBase64, &r, &r);
    return_to_wimp();
    if (pos_error == NULL) setup_to_save(base64_default, 0xfff, 2);
    else 
    {
      werr(FALSE , msgs_lookup("errorc:cannot base64 code file"));
      remove(file_uub);
    }
    unsafe_data = TRUE;
    remove("<Wimp$Scrap>");
    visdelay_end();
    return;
  }
}

/******************************WINDOW EVENTS ******************************/
static void action_event_handler(wimp_eventstr *e, void *handle)
{
  wimp_t sender;
  wimp_mousestr mouse_inf;
  char *last_pointer, *leaf_name, *point, *task_name;
  
  handle=handle;
  if(help_process(e)) return;

  switch(e->e)
  {
    case wimp_ENULL:
      wimp_get_point_info(&mouse_inf);
      if (mouse_inf.w != action_win_handle) break;
      switch (mouse_inf.i)
      {
        case icon_decode:
          if (icon_decode != help_icon)
          {
            text_in_icon(action_win_handle, icon_help, "Decode uucode/base64");
            help_icon = icon_decode;
          }
          break;
          
        case icon_uuencode:
          if (icon_uuencode != help_icon)
          {
            text_in_icon(action_win_handle, icon_help, "UUencode file");
            help_icon = icon_uuencode;
          }
          break;
          
        case icon_64encode:
          if (icon_64encode != help_icon)
          {
            text_in_icon(action_win_handle, icon_help, "base64 code file");
            help_icon = icon_64encode;
          }
          break;
          
        default:
          if (help_icon != -1)
          {
            text_in_icon(action_win_handle, icon_help, "");
            help_icon = -1;
          }
          break;
      }
      break;
      
    case wimp_EOPEN:
      wimp_open_wind(&e->data.o);
      break;
      
    case wimp_ECLOSE:
      if (unsafe_data && !(dboxquery("Closing the window will lose unsaved data, do you really want to discard this data?")==1)) break;
      wimp_close_wind(e->data.o.w);
      wimp_set_icon_state(split_win_handle,11,0,wimp_INOSELECT);
      wimp_set_icon_state(split_win_handle,5,0,wimp_INOSELECT);
      my_win_open = FALSE;
      unsafe_data = FALSE;
      splitting_file = FALSE;
      already_found_a_file = FALSE;
      processing_uucode = FALSE;
      processing_base64 = FALSE;
      remove(file_uua);
      remove(file_uub);
      if (no_ibar_icon) win_activedec();
      break; 
      
    case wimp_EPTRLEAVE:
      event_setmask(1);
      text_in_icon(action_win_handle, icon_help, "");
      help_icon = -1;
      break;
      
    case wimp_EPTRENTER:
      event_setmask(0);
      break; 

    case wimp_EKEY:
      if(e->data.key.chcode == 13 && ok_not_grey)
      {
        click_ok();
        break;
      }
      else wimp_processkey(e->data.key.chcode);
      break;
      
    case wimp_EBUT:
      if(e->data.but.m.i == icon_cancel)
      {
        wimp_get_wind_state(action_win_handle, &state);
        if (unsafe_data) wimp_close_wind(action_win_handle);
        reset_main_window();
        if (unsafe_data) wimp_open_wind(&state.o);
        caret_pos.w = action_win_handle;
        caret_pos.i = -1;
        wimp_set_caret_pos(&caret_pos);
        unsafe_data = FALSE;
        processing_uucode = FALSE;
        processing_base64 = FALSE;
        remove("<Wimp$ScrapDir>.Attacher.!!Scrap!!");
        remove(file_uua);
        remove(file_uub);
        break;
      }
      if(e->data.but.m.i == icon_discard)
      {
        if(unsafe_data == FALSE) break;
        caret_pos.w = action_win_handle;
        caret_pos.i = -1;
        wimp_set_caret_pos(&caret_pos);
        wimp_get_wind_state(action_win_handle, &state);
        wimp_close_wind(action_win_handle);
        reset_main_window();
        if (processing_uucode || processing_base64)
        {
          wimp_set_icon_state(action_win_handle,icon_uuencode,0x400000,0);
          wimp_set_icon_state(action_win_handle,icon_64encode,0x400000,0);
        }
        wimp_open_wind(&state.o);
        remove(file_uua);
        remove(file_uub);
        unsafe_data = FALSE;        
        if(processing_uucode) check_for_next();
        if(processing_base64) check_for_next_base64();
        break;
      }
      if(e->data.but.m.i == icon_savebutton)
      {
        click_ok();
        break;
      }
      if((e->data.but.m.i == icon_savefile) && (e->data.but.m.bbits == wimp_BDRAGLEFT)  && ok_not_grey)
      {
        wimp_set_icon_state(action_win_handle, icon_savefile, 0, wimp_ISELECTED);
        start_the_drag();
        break;
      }
      
      if((e->data.but.m.i == icon_savefile) && (e->data.but.m.bbits == wimp_BLEFT))
      {
        if(splitting_file) break;
        wimp_set_icon_state(action_win_handle, icon_savefile, 0, wimp_ISELECTED);
        wimp_get_icon_info(action_win_handle, icon_filename, &result);
        sprintf(my_line, ".%s\0", result.data.indirecttext.buffer);
        last_pointer = my_line;
        while (last_pointer != NULL)
        {
          leaf_name = last_pointer + 1;
          last_pointer = strchr(last_pointer + 1, 46);
        }
        sprintf(my_line2, "%s.%s\0", scrap_dir, leaf_name);
        remove(my_line2);
        rename(file_uub, my_line2);
        remove("<Wimp$Scrap>");
        if(launch_file(my_line2, drag_filetype, FALSE))
        {
          reset_main_window();
          caret_pos.w = action_win_handle;
          caret_pos.i = -1;
          wimp_set_caret_pos(&caret_pos);
          wimp_get_wind_state(action_win_handle, &state);
          wimp_close_wind(action_win_handle);
          reset_main_window();
          if (processing_uucode || processing_base64)
          {
            wimp_set_icon_state(action_win_handle,icon_uuencode,0x400000,0);
            wimp_set_icon_state(action_win_handle,icon_64encode,0x400000,0);
          }
          else unsafe_data = FALSE;
          wimp_open_wind(&state.o);
          if (processing_uucode) check_for_next();
          if (processing_base64) check_for_next_base64();
        }
        visdelay_end();
        break;
      }
      break;
      
    case wimp_EUSERDRAG:
      wimp_get_point_info(&mouse_inf);
      if(mouse_inf.w == action_win_handle) break;
      if((mouse_inf.w == -2) && (mouse_inf.i == my_ibar_icon)) break;
      msg.hdr.size = 256;
      msg.hdr.task = mouse_inf.w;
      msg.hdr.your_ref = 0;
      msg.hdr.action = wimp_MDATASAVE;
      msg.data.datasave.w = mouse_inf.w;
      msg.data.datasave.i = mouse_inf.i;
      msg.data.datasave.x = mouse_inf.x;
      msg.data.datasave.y = mouse_inf.y;
      msg.data.datasave.type = drag_filetype;
      msg.data.datasave.estsize = 0;
      {
        int i, tail;
        char name[256];
        wimp_get_icon_info(action_win_handle, icon_filename, &result);
        strncpy(name, result.data.indirecttext.buffer, 256);
        for(i = 0; i <=256; i++) if ((int) name[i] < 32) name[i] = '\0'; 
        tail = strlen(name);
        while ((tail > 0) && (name[tail-1] != '.') && (name[tail-1] != ':')) tail--;
        for (i = 0; i <= 200; i++) msg.data.datasave.leaf[i] = name[tail++];
        msg.data.datasave.leaf[200] = '\0'; 
      }
      wimpt_noerr(wimp_sendwmessage(wimp_ESEND, &msg, mouse_inf.w, mouse_inf.i));
      break;
      
    case wimp_ESEND:
    case wimp_ESENDWANTACK:
      if(e->data.msg.hdr.action == wimp_MPREQUIT)
      {
        prequit = TRUE;
        if (unsafe_data)
        {
          e->data.msg.hdr.your_ref = e->data.msg.hdr.my_ref;
          sender = e->data.msg.hdr.task;
          wimp_sendmessage(wimp_EACK, &e->data.msg, sender);
          if (!(dboxquery("Attacher has unsaved data, do you really want to quit the desktop and discard this data?")==1)) break; 
          else 
          {
            unsafe_data = FALSE;
            open.data.words[1] = 0x1fc;
            wimp_sendmessage(8, &open, sender);
          }
        }
        break;
      }
      if(e->data.msg.hdr.action == wimp_MINITTASK)
      {
        if(e->data.msg.hdr.task != wimpt_task())
        {
          task_name = e->data.msg.data.chars + 8;
          point = strstr(task_name, "Attacher");
          if ((point != NULL))
          {
            werr(FALSE, msgs_lookup("error0:Already running"));
            msg.hdr.size = 256;
            msg.hdr.your_ref = 0;
            msg.hdr.action = wimp_MCLOSEDOWN;
            wimp_sendmessage(wimp_ESEND, &msg, e->data.msg.hdr.task);
          }
        }
      }
      if(e->data.msg.hdr.action == wimp_MHELPREQUEST)
      {
        process_help_message(e);
        break;
      }
      if(e->data.msg.hdr.action == wimp_MDATASAVE)
      {
        if((e->data.msg.data.datasave.i < 1) || (e->data.msg.data.datasave.i > 3)) break;
        if(e->data.msg.data.datasave.type > 0xfff) break;
        if(e->data.msg.hdr.task == wimpt_task()) break;
        check_scrap_exists();
        reply_with_scrap(e);
        break;
      }
      if(e->data.msg.hdr.action == wimp_MDATALOAD)
      {
        if (ok_not_grey) break;
        if((e->data.msg.data.datasave.i < 1) || (e->data.msg.data.datasave.i > 3)) break;
        acknowledge_receipt(e);
        if(e->data.msg.data.dataload.type > 0xfff)
        { 
          r.r[0] = 17;
          r.r[1] = (int) e->data.msg.data.dataload.name;
          _kernel_swi(OS_Find, &r, &r);
          if(r.r[0] != 1)
          {
            werr(FALSE, msgs_lookup("error3:Cannot code or decode"));
            fclose(input_file);
            break;
          }
        }
        if (!splitting_file) dataload_routine(e);
        break;
      }  
      if(e->data.msg.hdr.action == wimp_MDATASAVEOK)
      {
        if (splitting_file) save_split_file(e->data.msg.data.datasaveok.name);
        else save_to_file(e->data.msg.data.datasaveok.name);
        e->data.msg.hdr.your_ref = e->data.msg.hdr.my_ref;
        e->data.msg.hdr.action = wimp_MDATALOAD;
        e->data.msg.data.dataload.type = drag_filetype;
        wimpt_noerr(wimp_sendmessage(wimp_ESENDWANTACK, &e->data.msg,e->data.msg.hdr.task));
        if(processing_uucode) check_for_next();
        if(processing_base64) check_for_next_base64();
        break;
      }    

    default:
      break;
  }
}

/********************************* MENU EVENTS ****************************/
static void my_menuproc(void *handle, char *hit)
{
  handle=handle;

  switch (hit[0])
  {
    case 1:
      dbox_show(info_box_handle);
      dbox_fillin(info_box_handle);
      dbox_hide(info_box_handle);
      break;
      
    case 2:
      handle_uu_choices();
      break;
      
    case 3:
      handle_link();
      break;
      
    case 4:
      os_read_var_val("Wimp$ScrapDir", my_line, 255);
      sprintf(my_line2, "Filer_OpenDir %s.Attacher", my_line);
      os_cli(my_line2);
      break;
            
    case 5:
      launch_file("<Attacher$Help>", 0xfff, TRUE);
      break;
      
    case 6:
      if (unsafe_data && !(dboxquery("Quitting will lose unsaved data, do you really want to discard this data?")==1)) break;
      prequit = TRUE;
      exit(0);
   }
}
/****************************** INITIALISATION ****************************/

static void initialise(void)
{ 
  int st_result1;
  
  wimpt_wimpversion(310);
  wimpt_init("Attacher");
  res_init("Attacher");
  resspr_init();
  template_init();
  msgs_init();
  dbox_init();
  atexit(&exit_function);
 
  my_menu = menu_new("Attacher", ">Info,>Choices,>Links,Open Dir,Help,Quit");
  
  info_box_handle=dbox_new("Info");
  dbox_setfield(info_box_handle,3," John Allen 1997-9");
  dbox_setfield(info_box_handle,4,"1.03pre4 (11-Feb-1999)");
  strcpy(version_num, "1.03");
  dbox_raw_eventhandler(info_box_handle, help_dboxrawevents, "Info");
  links_box_handle = dbox_new("Links");
  dbox_raw_eventhandler(links_box_handle, help_dboxrawevents, "Links");
  
  split_box_handle=dbox_new("Split");
  split_length = 60;
  dbox_setnumeric(split_box_handle, 4, split_length);
  strcpy(split_prefix, "Part");
  strcpy(split_suffix, "/uue");
  strcpy(default_file, "uuencoded");
  strcpy(base64_default, "base64");
  dbox_setfield(split_box_handle, 8, split_prefix);
  dbox_setfield(split_box_handle, 10, split_suffix);
  dbox_setfield(split_box_handle, 14, default_file);
  dbox_setfield(split_box_handle, 26, base64_default);
  dbox_raw_eventhandler(split_box_handle, help_dboxrawevents, "Split");
  split_win_handle = dbox_syshandle(split_box_handle);
  wimp_set_icon_state(split_win_handle, 1, 0, wimp_ISELECTED);
  wimp_set_icon_state(split_win_handle, 31, wimp_ISELECTED, wimp_ISELECTED);
  wimp_set_icon_state(split_win_handle, 32, wimp_ISELECTED, wimp_ISELECTED);
  
  input_file = fopen("<Attacher$Dir>.Choices","rb");
  if (input_file != NULL)
  {
    st_result = fgets(my_line, 2, input_file);
    if (st_result != NULL)
    {
      if (strncmp(my_line,"0",1) == 0)
      {
        split_file = TRUE;
        wimp_set_icon_state(split_win_handle, 1, wimp_ISELECTED, wimp_ISELECTED);
      }
      st_result1 = fscanf(input_file, "%d\n", &split_length);
      if (st_result1 != EOF) dbox_setnumeric(split_box_handle, 4, split_length);
      st_result = fgets(split_prefix, 255, input_file);
      if (st_result != NULL) dbox_setfield(split_box_handle, 8, split_prefix);
      st_result = fgets(split_suffix, 10, input_file);
      if (st_result != NULL) dbox_setfield(split_box_handle, 10, split_suffix);
      st_result = fgets(default_file, 255, input_file);
      if (st_result != NULL) dbox_setfield(split_box_handle, 14, default_file);
      st_result = fgets(base64_default, 255, input_file);
      if (st_result != NULL) dbox_setfield(split_box_handle, 26, base64_default);
      st_result = fgets(my_line, 255, input_file);
      if (st_result != NULL)
      {
        if (strncmp(my_line,"0",1) == 0)
        {
          keep_ext = TRUE;
          wimp_set_icon_state(split_win_handle, 24, wimp_ISELECTED, wimp_ISELECTED); 
        }
      }
      st_result = fgets(my_line, 255, input_file);
      if (st_result != NULL)
      {
        if (strncmp(my_line,"0",1) == 0)
        {
          uu_add_ext = TRUE;
          wimp_set_icon_state(split_win_handle, 28, wimp_ISELECTED, wimp_ISELECTED); 
        }
      }
      st_result = fgets(my_line, 255, input_file);
      if (st_result != NULL)
      {
        if (strncmp(my_line,"0",1) == 0)
        {
          base64_add_ext = TRUE;
          wimp_set_icon_state(split_win_handle, 29, wimp_ISELECTED, wimp_ISELECTED); 
        }
      }
      st_result = fgets(my_line, 255, input_file);
      if (st_result != NULL)
      {
        if (strncmp(my_line,"0",1) == 0)
        {
          start_open = FALSE;
          wimp_set_icon_state(split_win_handle, 31, 0, wimp_ISELECTED); 
        }
      }
      st_result = fgets(my_line, 255, input_file);
      if (st_result != NULL)
      {
        if ((strncmp(my_line,"0",1) == 0) && start_open)
        {
          iconbar_icon = FALSE;
          wimp_set_icon_state(split_win_handle, 32, 0, wimp_ISELECTED); 
        }
      }
      load_choices_vals();
    }
  }
  fclose(input_file);
  
  if (iconbar_icon)
  {
    my_ibar_icon = baricon("!attacher", (int)resspr_area(), my_iconclick);
    event_attachmenu(win_ICONBAR, my_menu, my_menuproc, 0);
  }
  else 
  {
    win_activeinc();
    no_ibar_icon = TRUE;
  }
  
  wimp_create_wind(template_syshandle ("Action"),&action_win_handle);
  win_register_event_handler(action_win_handle, action_event_handler, 0);
  event_attachmenu(action_win_handle, my_menu, my_menuproc, 0);
  win_claim_unknown_events(action_win_handle);
  win_claim_idle_events(action_win_handle);
  if (start_open) open_main_window();
  
  os_read_var_val("Wimp$ScrapDir", my_line, 255);
  if(strlen(my_line) == 0) werr(TRUE, msgs_lookup("error5:No Wimp$ScrapDir"));
  
  help_register_handler(help_simplehandler, "Menu");
  
  strcpy(scrap_dir, "<Wimp$ScrapDir>.Attacher");
  r.r[0] = 8;
  r.r[1] = (int) scrap_dir;
  _kernel_swi(OS_File, &r, &r);
  strcpy(file_uua, scrap_dir);
  strcat(file_uua, ".!!uua!!");
  strcpy(file_uub, scrap_dir);
  strcat(file_uub, ".!!uub!!");
  
  help_icon = -1;
}
/******************************* MAIN PROGRAM *****************************/

int main()
{
  initialise();
  {
    while (TRUE)
      event_process();
  }

  return 0;
}
