
/*  Mailboxes: manage other (optional) mailboxes 
 *
 *  This file is part of Aileron, a WINGs email client. 
 *
 *  Copyright (c) 1999 - 2001 Nwanua Elumeze
 *
 *  This program is wfree software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include "Aileron.h"

struct  {
  WMWindow  *window;
  WMBrowser *browser;
  WMButton  *openb, *autob;
  WMButton  *linkb, *unlinkb;
  WMButton  *subb,  *unsubb;
  WMTextField *namet;
  unsigned short withinNetwork:1;
  unsigned short RESERVED:15;
} MailboxesPanel;


#ifndef PATH_MAX
#define PATH_MAX 1024
#endif

static void fillColumn(WMBrowserDelegate *self, WMBrowser *bPtr, 
  int col, WMList *list);
static void imapFillColumn(WMBrowserDelegate *self, WMBrowser *bPtr, 
  int col, WMList *list);


static void openCB(WMWidget *w, void *client);
static void createNetWorkMailBox(char *name, int create);
static char * getFullNewtorkName(char *toCol);

static WMBrowserDelegate browserDelegate = {
  NULL, /* data */
  fillColumn, /* createRowsForColumn */
  NULL, /* titleOfColumn */
  NULL, /* didScroll */
  NULL  /* willScroll */
};

static WMBrowserDelegate imapBrowserDelegate = {
  NULL, /* data */
  imapFillColumn, /* createRowsForColumn */
  NULL, /* titleOfColumn */
  NULL, /* didScroll */
  NULL  /* willScroll */
};

typedef struct { 
  WMWindow *win;
  WMTabViewItem *tab;
  WMPopUpButton *methodp;
  WMTextField *locationt, *usernamet;
  WMLabel *namel;
  char *name;
  unsigned short create:1;
  unsigned short RESERVED:15;
} NMPanel;

static void
affectNM(NMPanel *panel, int create);

static void 
closePanel(WMWidget *self, void *client)
{
  WMUnmapWidget(MailboxesPanel.window);
}

static void
handleKeyReleases(XEvent *event, void *client)
{ 
  KeySym ksym;
  
  XLookupString(&event->xkey, NULL, 0, &ksym, NULL);
  if(ksym == XK_Shift_R || ksym == XK_Shift_L) {
    Aileron.shiftHeld = False;
  }
}


static void
handleKeyPresses(XEvent *event, void *client)
{
  KeySym ksym;
  NMPanel *panel = (NMPanel *)client;
  
  XLookupString(&event->xkey, NULL, 0, &ksym, NULL);
  if(ksym == XK_Shift_R || ksym == XK_Shift_L) {
    Aileron.shiftHeld = True;
    return;

  } else if(panel && ksym == XK_Return) { 
    affectNM(panel, panel->create);
    return;
  }

 if(event->xkey.state & XK_Alt_L &  8) {
  
   switch (ksym) {
  
      case XK_c :  EnterSelection(); break;
      case XK_f :  RunFindPanel(); break;
      case XK_g :  FindNext(); break;
      case XK_G:   FindPrevious(); break;
     
      case XK_h:   WMHideApplication(Aileron.appContext); break;
      case XK_H:   WMHideOthers(Aileron.appContext); break;
      case XK_n :  ComposeMessage(CMCompose); break; 
      case XK_r :  ComposeMessage(CMReply); break;
      case XK_R :  ComposeMessage(CMReplyAll); break;
      case XK_W :  ComposeMessage(CMForward); break;
#if 0
      case XK_B :  ComposeMessage(CMBounce); break;
#endif
      case XK_p :  printf("RunPrintPanel\n"); break;
      case XK_q :  QuitAileron(); 
      case XK_s :  break;
      case XK_w : closePanel(NULL, NULL);  break;
    }
  }
}

char *getNameFromPath(const char *cpath)
{
  int size = strlen(cpath);
  char path[size];
  char *mark;
  
  /* for network mailboxes. ie: /Network/host/"Mail/sorted/nwanua" */
  if((mark = strchr(cpath, '"'))) { 
    char *end = strchr(mark+1, '"');

    if(end && (int)(end-mark) > 0) { 
      int len = (int)(end-mark);
      char *tmp = wmalloc(len);
      memcpy(tmp, mark+1, len-1);
      *(tmp+len-1) = 0; 
      return tmp;
    }
  }

  memcpy(path, cpath, size);
 
  /* remove trailing / */
  while (size > 0 && path[size-1]=='/')
    size--;
    
  path[size] = 0;
    
  /* directory was root */
  if (size == 0)
    return wstrdup("/");
    
  while (size > 0 && path[size-1] != '/')
    size--;
    
  if (strstr(&path[size], "/"))
    return strdup(" ");
  else
    return wstrdup(&(path[size]));
}     
    


static void 
changeMailBoxesPath(WMWidget *w, void *client)
{
  WMOpenPanel *panel;
  char *path, *nmboxes = NULL;
  struct stat stat_buf;

  if (WMGetUDStringForKey(Aileron.defaultsDB, "MailDir")) {
    path = wstrdup(WMGetUDStringForKey(Aileron.defaultsDB, "MailDir"));
  } else {
    path = wstrdup(wgethomedir());
  }

_changeMailboxesAgain:
  panel = WMGetOpenPanel(Aileron.screen);
  WMSetFilePanelAutoCompletion(panel, True);
  if (WMRunModalFilePanelForDirectory(panel, NULL, path, NULL, NULL)) {  

  nmboxes = WMGetFilePanelFileName(panel);

  if (nmboxes && strlen(nmboxes) > 1) {
    if (stat(nmboxes, &stat_buf) == 0) { 

      if (S_ISDIR(stat_buf.st_mode)) {  
        WMSetUDStringForKey(Aileron.defaultsDB, nmboxes, "MailDir");
        ResetMailboxesPanel();

      } else if (RunAlertPanel("Change Mailboxes folder", 
          "The chosen entity is not a folder",
          "Try again", "Don't change folder", NULL) == 0) {
          goto _changeMailboxesAgain;
      }

    } else if (RunAlertPanel("Change Mailboxes folder",
      "The chosen folder does not exist.",
      "Try again", "Don't change folder", NULL) == 0) { 
      goto _changeMailboxesAgain;
    }
  }
  }

  wfree(path);
}
 


static void
listDirectoryOnColumn(int col, char *path)
{
  WMBrowser *bPtr = MailboxesPanel.browser;
  struct dirent *dentry;
  DIR *dir;
  struct stat stat_buf;
  char pbuf[PATH_MAX+16];
  char *tmpname;
  
  if (col < 0 || !path)
    return;

  if (col == 0) {
    WMInsertBrowserItem(bPtr, 0, 1, "Network", True);

  } else if (col == 1) {
    tmpname = getNameFromPath(path);
    if (tmpname) { 
      if (!strcmp(tmpname, "Network")) { 
        WMPropList *dic, *keys, *key;
        char *name;
        int i, nelem;

        dic = WMGetUDObjectForKey(Aileron.defaultsDB, "NetworkMailBoxes");
        if (!dic) 
          goto _noNM;
        keys = WMGetPLDictionaryKeys(dic);
        if (!keys)  
          goto _noNM;
             
        nelem = WMGetPropListItemCount(keys);

        for(i=0; i<nelem; i++) {
          if (!(key = WMGetFromPLArray(keys, i))) 
            continue; 

          if (!(name = WMGetFromPLString(key)))
            continue; 

           WMInsertBrowserItem(bPtr, col, -1, name, 1);
        }
_noNM:
      wfree(tmpname);
      return;
      } 
      wfree(tmpname);
/* is not in "Network dir */
    }

  } else if (MailboxesPanel.withinNetwork) { 
    WMPropList *dic, *keys, *nmbox, *props, *val;
    char *string, *path, *toCol;
    int i, nelem, foundnmbox = False;

    WMInsertBrowserItem(MailboxesPanel.browser, col, -1, "Inbox", 0);

    dic = WMGetUDObjectForKey(Aileron.defaultsDB, "NetworkMailBoxes");
    if (!dic) 
      return;

    if(!(keys = WMGetPLDictionaryKeys(dic))) 
      return;
             
    if (!(path = WMGetBrowserPathToColumn(MailboxesPanel.browser, 1)))
      return; 
      
    if(!(toCol = getNameFromPath(path))) {
      wfree(toCol);
      return;
    }
    wfree(path);
      
    nelem = WMGetPropListItemCount(keys);

    for(i=0; i<nelem; i++) {
      if (!(nmbox = WMGetFromPLArray(keys, i))) 
        continue; 

      if (!(string = WMGetFromPLString(nmbox)))
        continue; 

      if (!strcmp(string, *toCol=='/'?toCol+1:toCol)) {
        foundnmbox = True;
        break;
      } 
    } 

    if (foundnmbox) { 

      props = WMGetFromPLDictionary(dic, nmbox);
      nelem = WMGetPropListItemCount(props);
      if (nelem < 3)  { 
        wfree(toCol);
        return; 
      }
   
      for(i=3; i<nelem; i++) {
        val = WMGetFromPLArray(props, i); 
        WMInsertBrowserItem(MailboxesPanel.browser, col, -1, 
          WMGetFromPLString(val), 0);
      }
    }

    return;
  }
   

  dir = opendir(path);
  if (!dir) 
    return;
  
  while ((dentry = readdir(dir))) { 
    if (!strcmp(dentry->d_name, ".") ||
        !strcmp(dentry->d_name, "..")||
        !strcmp(dentry->d_name, "Network")) 
      continue;
    
    strcpy(pbuf, path);
    if (strcmp(path, "/")!=0)
      strcat(pbuf, "/");

    strcat(pbuf, dentry->d_name);
  
    if (stat(pbuf, &stat_buf)!=0) {
      FSErrorhandler("Open Mailbox Folder", pbuf, errno);
      continue;
    } else {
      int isDirectory;
    
      isDirectory = S_ISDIR(stat_buf.st_mode);
    
      WMInsertBrowserItem(bPtr, col, -1, dentry->d_name, isDirectory);
    }   
  }   

  /* WMSortBrowserColumn(bPtr, col); */
  closedir(dir);
}   

void
ResetMailboxesPanel(void)
{
  WMList *list;
  char *path;

  if (!Aileron.mboxesCreated) 
    return;
  
  path = wstrdup(WMGetUDStringForKey(Aileron.defaultsDB, "MailDir"));
  WMSetBrowserPath(MailboxesPanel.browser, path);

  if ((list = WMGetBrowserListInColumn(MailboxesPanel.browser, 0))) { 
    WMClearList(list);
    listDirectoryOnColumn(0, path);
  }

  if ((list = WMGetBrowserListInColumn(MailboxesPanel.browser, 1))) { 
    WMClearList(list);
  }

  wfree(path);
}

static void
autoOpen(WMWidget *w, void *client)
{
  WMBrowser *bPtr = MailboxesPanel.browser;
  int add, i, num, col = WMGetBrowserSelectedColumn(bPtr);
  WMListItem *item;
  char *mbox, *string;
  WMPropList *array, *check = NULL, *pmbox;

  item = WMGetBrowserSelectedItemInColumn(bPtr, col);
  if (!item) 
    return;
  if(item->isBranch) 
    return;

  /* can only come from Mailboxes, but check just in case... */
  if (!WMGetUDStringForKey(Aileron.defaultsDB, "MailDir")) 
    return;

  add = (Bool) (WMGetButtonSelected(MailboxesPanel.autob));
  if (MailboxesPanel.withinNetwork) { 
    char *npath, *path;

    if (!(path = WMGetBrowserPathToColumn(bPtr, 1)))
      return;

    npath = getNameFromPath(path);
    if(!(mbox = getFullNewtorkName(npath))) {
      wfree(path);
      return;
    }

    wfree(npath);
    wfree(path);
    mbox = wstrappend(mbox, item->text);
    
  } else {
    int len;

    mbox = wstrdup(WMGetUDStringForKey(Aileron.defaultsDB, "MailDir"));
    len = strlen(mbox)-1;
    if(mbox[len] == '/')
      mbox[len] = 0;
    mbox = wstrappend(mbox, WMGetBrowserPathToColumn(bPtr, col));
  }

  array = WMGetUDObjectForKey(Aileron.defaultsDB, "DefaultMailBoxes");

  if (!array) {
    if(!add)
      return;

    pmbox = WMCreatePLString(mbox);
    array = WMCreatePLArray(pmbox, NULL);
    WMSetUDObjectForKey(Aileron.defaultsDB, array, "DefaultMailBoxes");

  } else {
    num = WMGetPropListItemCount(array);

    for (i=0; i<num; i++) {
      if(!(check = WMGetFromPLArray(array, i)))
        continue;
      if (!(string = WMGetFromPLString(check)))
        continue;

      if (!strcmp(string, mbox)) {
        if(add)
          goto _autoOpenFailed;
        else 
          WMDeleteFromPLArray(array, i);
      }
    }

    if(add) {
      pmbox = WMCreatePLString(mbox);
      WMAddToPLArray(array, pmbox);
/* misbehaves if released... why? */
#if 0
      WMReleasePropList(pmbox);
#endif
    }
 } 

_autoOpenFailed:
/* misbehaves if released... why? */
#if 0
  WMReleasePropList(array);
  if(check) 
    WMReleasePropList(check);
#endif
  wfree(mbox);


}


static char *
getFullNewtorkName(char *toCol)
{
  WMPropList *dic, *keys, *nmbox, *props, *val;
  char *string;
  int i, nelem, foundnmbox = False;

  dic = WMGetUDObjectForKey(Aileron.defaultsDB, "NetworkMailBoxes");
  if (!dic) 
    return NULL;

  if(!(keys = WMGetPLDictionaryKeys(dic))) 
    return NULL;
             
  nelem = WMGetPropListItemCount(keys);

  for(i=0; i<nelem; i++) {
    if (!(nmbox = WMGetFromPLArray(keys, i))) 
      continue; 

    if (!(string = WMGetFromPLString(nmbox)))
      continue; 

    if (!strcmp(string, *toCol=='/'?toCol+1:toCol)) {
      foundnmbox = True;
      break;
    } 
  }

  if (foundnmbox) { 
    char *netaddr;

    props = WMGetFromPLDictionary(dic, nmbox);
    nelem = WMGetPropListItemCount(props);
    if (nelem < 3) 
      return NULL; 
   
	netaddr = wstrdup("{"); 
    val = WMGetFromPLArray(props, 0); 
    netaddr = wstrappend(netaddr, WMGetFromPLString(val)); 
    netaddr = wstrappend(netaddr, "/"); 
    val = WMGetFromPLArray(props, 2); 
    netaddr = wstrappend(netaddr, WMGetFromPLString(val));
    netaddr = wstrappend(netaddr, "/user=\""); 
    val = WMGetFromPLArray(props, 1);
    netaddr = wstrappend(netaddr, WMGetFromPLString(val)); 
    return wstrappend(netaddr, "\"}");
  }

  return NULL;
}

static void 
openCB(WMWidget *w, void *client)
{
  WMBrowser *bPtr = MailboxesPanel.browser;
  int col = WMGetBrowserSelectedColumn(bPtr);
  Bool isBranch;

  if (col<0)
    return;


  isBranch = ((WMListItem *) 
    WMGetBrowserSelectedItemInColumn(bPtr, col))->isBranch;

  if (MailboxesPanel.withinNetwork) { 
    char *path, *name, *netaddr;

    if(col == 0 && isBranch) {
      return;
    }

    if (!(path = WMGetBrowserPathToColumn(bPtr, 1)))
      return;

    if(!(name = getNameFromPath(path))) {
      wfree(path);
      return;
    }
      
    wfree(path);


    if(col == 1) { 
      createNetWorkMailBox(name, 0);
      wfree(name);
      return;
    }

    if(!(netaddr = getFullNewtorkName(name))) { 
      wfree(name);
      return;
    }
  
    if(col > 1) {
      char *mboxpath, *mboxname;

      if (!(mboxpath = WMGetBrowserPathToColumn(bPtr, col))) { 
        wfree(name);
        return;
      }

      if(!(mboxname = getNameFromPath(mboxpath))) {
        wfree(name);
        wfree(mboxpath);
        return;
      }
      
      wfree(mboxpath);
      netaddr = wstrappend(netaddr, mboxname);
      wfree(mboxname);
    }

    OpenMailBox(netaddr);

#if 0
{
    void *mbox = NULL;
    MAILSTREAM *stream;

    if((mbox = GetMailBoxForName(netaddr))) { 
stream = GetMailBoxStream(mbox);
printf("returned %lu \n", mail_subscribe(stream, "mySubscription"));
imap_lsub(stream,NIL,netaddr);
    } else printf("not opened!\n");

  /*    puts ("Known mailboxes:");
mail_lsub (stream,NIL,netaddr);
    mail_list (stream, NIL, netaddr);
*/

}
#endif

    wfree(netaddr);
    wfree(name);
  
  } else if (WMGetUDStringForKey(Aileron.defaultsDB, "MailDir") && !isBranch) { 
    char *toCol, *path;
    int len;

    if (!(toCol = WMGetBrowserPathToColumn(bPtr, col)))
      return;

    path = wstrdup(WMGetUDStringForKey(Aileron.defaultsDB, "MailDir"));
    len = strlen(path)-1;
    if(path[len] == '/')
      path[len] = 0;
    path = wstrappend(path, toCol);

    wfree(toCol);
    OpenMailBox(path);
    wfree(path);
  }

}

#if 0
static Bool
checkIfNetWorkConfigIsOpen(char *name)
{
#endif

static void 
closeNM(WMWidget *w, void *client)
{
  NMPanel *panel = (NMPanel *)client;
  
  WMCloseWindow(panel->win);
  WMDestroyWidget(panel->win);
  wfree(panel);
}


static void
affectNM(NMPanel *panel, int create)
{
  char *loc, *username, *mname;
  WMPropList *dic, *nmbox, *props, *tmp;
  Bool first = False;

  loc = WMGetTextFieldText(panel->locationt);
  if (strlen(loc) < 2) { 
    if(create) { 
      RunAlertPanel("Create Network mailbox",
         "Unless you provide a machine name or IP address,\n"
         "this network mailbox will not be be created.",
         "I understand", NULL, NULL);
    } else {
      RunAlertPanel("Change Network mailbox",
         "Unless you provide a machine name or IP address,\n"
         "this network mailbox will not be be changed",
         "I understand", NULL, NULL);
    }
    wfree(loc);
    return;
  }

  username = WMGetTextFieldText(panel->usernamet);
  if (strlen(username) < 2) { 
    if(create) { 
      RunAlertPanel("Create Network mailbox",
        "Unless you provide a username\n, this network mailbox "
        "will not be be created.",
        "I understand", NULL, NULL);
     } else {
      RunAlertPanel("Change Network mailbox",
        "Unless you provide a username\n, this network mailbox "
        "will not be be changed",
        "I understand", NULL, NULL);
    }
    wfree(username);
    return;
  }

  mname = WMGetLabelText(panel->namel);
  fprintf(stderr,"createing mbox %s\n",mname);
 
  nmbox = WMCreatePLString(mname);
  props = WMCreatePLArray(NULL);
  WMAddToPLArray(props, (tmp = WMCreatePLString(loc)));
  WMReleasePropList(tmp);
  WMAddToPLArray(props, (tmp = WMCreatePLString(username)));
  WMReleasePropList(tmp);
  WMAddToPLArray(props, (tmp = WMCreatePLString(
    WMGetPopUpButtonSelectedItem(panel->methodp)?"pop":"imap")));
  WMReleasePropList(tmp);

  dic = WMGetUDObjectForKey(Aileron.defaultsDB, "NetworkMailBoxes");
  if (!dic) {
    dic = WMCreatePLDictionary(nmbox, props, NULL);
    first = True;

  } else {
    WMPropList *keys, *check;
    char *string;
    int i, nelem;

    keys = WMGetPLDictionaryKeys(dic);
    if (keys) {
      nelem = WMGetPropListItemCount(keys);
      for(i=0; i<nelem; i++) {
        if (!(check = WMGetFromPLArray(keys, i))) 
          continue; 

        if (!(string = WMGetFromPLString(check)))
          continue; 

        if (!strcmp(string, mname) && create)  
          goto _createNMret;
      } 
    }
    fprintf(stderr,"Inserting \n");
    WMPutInPLDictionary(dic, nmbox, props);
    fprintf(stderr,"done \n");

  }

  if (first)
    WMSetUDObjectForKey(Aileron.defaultsDB, dic, "NetworkMailBoxes");

printf("remove comments\n");
#if 0
  if(create)
    WMInsertBrowserItem(MailboxesPanel.browser, 1, -1, name, 1);
#endif

_createNMret:
  WMReleasePropList(dic);
  WMReleasePropList(nmbox);
  WMReleasePropList(props);
  wfree(loc);
  //  wfree(mname);
  wfree(username);
  closeNM(NULL, panel);


}


static void 
changeNM(WMWidget *w, void *client)
{
  NMPanel *panel = (NMPanel *)client;
  affectNM(panel, 0);
}

static void 
createNM(WMWidget *w, void *client)
{
  NMPanel *panel = (NMPanel *)client;
  affectNM(panel, 1);
}

static void
createNetWorkMailBox(char *name, int create)
{
  WMLabel *l;
  WMButton *b;
  NMPanel *panel;
  unsigned w=290, h=155;

  panel = (NMPanel *) wmalloc(sizeof(NMPanel));
  if (!panel)
    return;
  
  panel->win = WMCreateWindowWithStyle(Aileron.screen, 
    "Aileron Network Mailbox", WMTitledWindowMask);
  WMSetWindowTitle(panel->win, create?
    "Aileron: Create Network Mailbox":"Aileron: Change Network Mailbox");
  WMSetWindowMinSize(panel->win, w, h);
  WMSetWindowMaxSize(panel->win, w, h);
  WMResizeWidget(panel->win, w, h);      
  WMCreateEventHandler(WMWidgetView(panel->win),
    KeyPressMask, handleKeyPresses, panel);
  WMCreateEventHandler(WMWidgetView(panel->win),
    KeyReleaseMask, handleKeyReleases, NULL);

  l = NewLabel(panel->win, "Name:", 10, 10, 80, 20);
printf("remove comments %s\n",name);
#if 1
  panel->namel = NewLabel(panel->win, name, 92, 10, 180, 20);
  WMSetLabelRelief(panel->namel, WRSunken);
#endif

  l = NewLabel(panel->win, "Location:", 10, 35, 80, 20);
  panel->locationt = NewTextField(panel->win, name, 92, 35, 180, 20);
  WMSetBalloonTextForView("You can also put IP numbers here.",
    WMWidgetView(panel->locationt));

  l = NewLabel(panel->win, "Username:", 10, 60, 80, 20);
  panel->usernamet = NewTextField(panel->win, 
    create?myusername():NULL, 92, 60, 180, 20);

  l = NewLabel(panel->win, "Method:", 10, 85, 80, 20);
  panel->methodp = WMCreatePopUpButton(panel->win);
  WMResizeWidget(panel->methodp, 87, 20);
  WMMoveWidget(panel->methodp, 92, 85);
  WMSetPopUpButtonText(panel->methodp, "imap");
  WMAddPopUpButtonItem(panel->methodp, "imap");
  WMAddPopUpButtonItem(panel->methodp, "pop");
  WMSetPopUpButtonSelectedItem(panel->methodp, 0);


  b = WMCreateCommandButton(panel->win);
  WMSetButtonText(b, "Cancel");
  WMResizeWidget(b, 75, 25);
  WMMoveWidget(b, 120, 120);
  WMSetButtonAction(b, closeNM, panel);

  b = WMCreateCommandButton(panel->win);
  WMSetButtonText(b, create?"Create":"Change");
  WMResizeWidget(b, 75, 25);
  WMMoveWidget(b, 205, 120);
  WMSetButtonImageDefault(b);
  WMSetButtonImagePosition(b, WIPRight);
  WMSetButtonAction(b, create?createNM:changeNM, panel);

  panel->create = create;

  if(!create) { 
    char *netaddr = getFullNewtorkName(name); 
  
    if(netaddr) { 
      char *start=netaddr+1, *mark = NULL;
      char text[128], *end;

      mark = strchr(start, '/');
      snprintf(text, 1+(int)(mark-start), start);
      WMSetTextFieldText(panel->locationt, text);
      start = mark+1; 
      mark = strchr(start, '/');
      snprintf(text, 1+(int)(mark-start), start);
      WMSetPopUpButtonSelectedItem(panel->methodp, !strcmp(text, "pop"));
      start = mark+1; 
      mark = strchr(start, '"');
      end = strrchr(start, '"');
      snprintf(text, (int)(end-mark), mark+1);
      WMSetTextFieldText(panel->usernamet, text);
    }

    wfree(netaddr);
  }

/* add it?
  WMHashInsert(Aileron.windowCount, "_NETWORK_MAILBOX_PANEL_", 
    &MailboxesPanel);
*/
  
  WMRealizeWidget(panel->win);
  WMMapSubwidgets(panel->win);
  WMAppAddWindow(Aileron.appContext, WMWidgetXID(panel->win));
  WMMapWidget(panel->win);

}

static void 
newCB(WMWidget *w, void *client)
{
  char *name = WMGetTextFieldText(MailboxesPanel.namet);
  char *path; 
  int col;
  WMBrowser *bPtr = MailboxesPanel.browser;
  WMListItem *item;
  Bool is_dir = 0;
  mode_t  mode = umask(0);
  
  if (strlen(name)<1 || *name == '.') {
    wfree(name);
    return;
  }

  if ((col = WMGetBrowserSelectedColumn(bPtr)) < 0) {
    wfree(name);
    return;
  }

  if (col == 0 
    &&(!strcmp(name, "Drafts") || !strcmp(name, "Drafts/")
    || !strcmp(name, "Network")|| !strcmp(name, "Network/")
    || !strcmp(name, "Outgoing")|| !strcmp(name, "Outgoing/"))) {

    wfree(name);
    return;
  }


  if (MailboxesPanel.withinNetwork) { 
    if(col == 0) {
      createNetWorkMailBox(name, !Aileron.shiftHeld);
    } else { 
      Bool isBranch = (*(name+strlen(name)-1) == '/');
      RunAlertPanel((isBranch?"New Folder":"New Mailbox"),
        "Currently, new folders or mailboxes cannot be created"
        "on remote hosts...", "I understand", NULL, NULL);
      wfree(name);
    }
    return;
  }


  if (!WMGetUDStringForKey(Aileron.defaultsDB, "MailDir")) {
    RunAlertPanel(
      ((*(name+strlen(name)-1) == '/')?"New Folder":"New Mailbox"),
        "The main folder for mailboxes was not found.\n"
        "An \"Open Panel\" will be shown so you can choose one.",
        "I understand", NULL, NULL);
    changeMailBoxesPath(NULL, NULL);
    if (!WMGetUDStringForKey(Aileron.defaultsDB, "MailDir")) {
      wfree(name);
      return;
    }
  }

  path = wstrdup(WMGetUDStringForKey(Aileron.defaultsDB, "MailDir"));

  if (col<0) {
    col = 0;
    is_dir = 0;

  } else {
    char *toCol;

    item = WMGetBrowserSelectedItemInColumn(bPtr, col);
    if (item->isBranch) {
      is_dir = 1;
      toCol = WMGetBrowserPathToColumn(bPtr, col);
      path = wstrappend(path, toCol);
    } else {
      toCol = WMGetBrowserPathToColumn(bPtr, col-1);
      path = wstrappend(path, toCol);
    }
    wfree(toCol);
  }

  path = wstrappend(path, "/");
  path = wstrappend(path, name);

  if (FileExists(path)) {
    RunAlertPanel((item->isBranch?"New Folder":"New Mailbox"),
    "A file with the same name already exists,\n"
    "so this can't be created.", "I understand", NULL, NULL);
    wfree(path);
    return;
  }

  umask(mode);
  mode = 0777777^mode;

  if (*(path+strlen(path)-1) == '/') {
 
    if (mkdir(path,mode & 0700) != 0) {
      FSErrorhandler("Create Mailbox Folder", path, errno);
    } else {
      char dirname[strlen(name)];
      snprintf(dirname, strlen(name), name);
      WMInsertBrowserItem(bPtr, col, -1, dirname, True);
    }
  } else {
    if ( open(path, O_WRONLY|O_CREAT|O_EXCL, mode & 0600) == -1) {
      FSErrorhandler("Create Mailbox", path, errno);
    } else {
      WMInsertBrowserItem(bPtr, col+is_dir, -1, name, False);
    }
  }
    
  WMSetTextFieldText(MailboxesPanel.namet, NULL);
  wfree(name);
  wfree(path);
}


static void 
deleteCB(WMWidget *w, void *client)
{
  WMBrowser *bPtr = MailboxesPanel.browser;
  int col = WMGetBrowserSelectedColumn(bPtr);
  char *name, string[201];
  Bool result, isFolder;
  
  if (col < 0)
    return;

  if (!(WMGetBrowserSelectedItemInColumn(bPtr, col)->text))
    return;

  name = wstrdup(WMGetBrowserSelectedItemInColumn(bPtr, col)->text);
  if (strlen(name)<1 || !strcmp(name, "Network")) {
    wfree(name);
    return;
  }
    
  isFolder = ((WMListItem *) 
    WMGetBrowserSelectedItemInColumn(bPtr, col))->isBranch;

  if (isFolder) {
    snprintf(string, 200, "%s\nThis folder of mailboxes is about to be "
      "deleted.\nAre you sure this is what you want to do?", name);
     result = RunAlertPanel("Delete Mailbox Folder", string,
      "No", "Yes, delete it", NULL);
  } else {
    snprintf(string, 200, "%s\nThis mailbox is about to be deleted.\n"
      " Are you sure this is what you want to do?", name);
     result = RunAlertPanel("Delete Mailbox", string,
      "No", "Yes, delete it", NULL);
  }

  if (result && MailboxesPanel.withinNetwork) { 
    WMPropList *dic, *keys, *nmbox, *props;
    int i, nelem, foundnmbox = False;
    char *str;

    dic = WMGetUDObjectForKey(Aileron.defaultsDB, "NetworkMailBoxes");
    if (!dic) {
      wfree(name);
      return ;
    }

    if(!(keys = WMGetPLDictionaryKeys(dic))) {
      wfree(name);
      return;
    }
             
    nelem = WMGetPropListItemCount(keys);

    for(i=0; i<nelem; i++) {
      if (!(nmbox = WMGetFromPLArray(keys, i))) 
        continue; 

      if (!(str = WMGetFromPLString(nmbox)))
        continue; 

      if (!strcmp(str, name)) { 
        foundnmbox = True;
         break;
      } 
    }

    if (foundnmbox) { 
      props = WMGetFromPLDictionary(dic, nmbox);
      WMRemoveFromPLDictionary(dic, props);
    }

    WMRemoveBrowserItem(bPtr, col, 
      WMGetBrowserSelectedRowInColumn(bPtr, col));
    return;
  }



  if (result) {
    if (*name == '{') {
      printf("remove network mbox\n");
      CloseMailBox("network:name");

    } else {
      char *path;
      char *toCol;
      struct stat filestat;
    
      CloseMailBox(name);

      if (!WMGetUDStringForKey(Aileron.defaultsDB, "MailDir")) {
        RunAlertPanel(isFolder?"Delete Mailbox Folder":"Mailbox Folder",
         "Cannot continue this operation, since it cannot be found.",
         "I understand", NULL, NULL);
       return;
      }

      toCol = WMGetBrowserPathToColumn(bPtr, col);
      if (!toCol)
        return;

      path = wstrdup(WMGetUDStringForKey(Aileron.defaultsDB, "MailDir"));
      path = wstrappend(path, toCol);
      wfree(toCol);

      if (stat(path,&filestat)) {
        FSErrorhandler("Delete Mailbox", path, errno);

      } else { 
        
        int row = WMGetBrowserSelectedRowInColumn(bPtr, col);

        if (S_ISDIR(filestat.st_mode)) {
          if (rmdir(path) != 0) {
            FSErrorhandler("Delete Mailbox Folder", path, errno);
          } else {
            WMRemoveBrowserItem(bPtr, col, row);
          }
        } else {
          if (remove(path) != 0) {
            FSErrorhandler("Delete Mailbox", path, errno);
          } else {
            WMRemoveBrowserItem(bPtr, col, row);
          }
        }
      }

      wfree(path);
    }
  }
  wfree(name);
}

static void
restoreTitleAfterTransfer(void *data)
{
  RestoreMailBoxWindowTitle(data);
}

static void 
transferCB(WMWidget *w, void *client)
{
  WMBrowser *bPtr = MailboxesPanel.browser;
  long col = WMGetBrowserSelectedColumn(bPtr);
  char *mailbox, string[PATH_MAX+1], sequence[10], *toCol;
  unsigned long msgno, nmsgs;
  MAILSTREAM *stream;
  MESSAGECACHE *msgcache;
  WMArray *items;
  WMListItem *item;
  int i;
  char *option, *from;
  FILE *file;
  time_t date;
  ENVELOPE *env;
  void *mbox;

  
  if (!Aileron.mbox || col < 0)
    return;

  mbox = Aileron.mbox;

  if ( ((WMListItem *)
    WMGetBrowserSelectedItemInColumn(bPtr, col))->isBranch) {
    RunAlertPanel("Transfer Messages",
    "Messages cannot be transferred to folders\n, only other mailboxes.",
    "I understand", NULL, NULL);
    return;
  }

  option = WMGetUDStringForKey(Aileron.defaultsDB, "MailDir");
  if(!option)
    return;

  mailbox = wstrdup(option);
  toCol = WMGetBrowserPathToColumn(bPtr, col);
  mailbox = wstrappend(mailbox, toCol);
  wfree(toCol);
  if (!mailbox || strlen(mailbox)<1)
    return;
    
  if (!strcmp(mailbox, getNameFromPath(GetMailBoxName(mbox)))) {
    wfree(mailbox);
    return;
  }

  items = GetMailBoxSelectedMessages(mbox);
  if (!items)
    return;
  nmsgs = WMGetArrayItemCount(items);
  if (nmsgs < 1)
    return;

  snprintf(string, PATH_MAX, "Aileron: Moving %lu message%sto %s",
    nmsgs, (nmsgs==1)?" ":"s ", getNameFromPath(mailbox));

  if(MailBoxIsNetwork(mbox)) {
    file = fopen(mailbox, "a");
    if(!file) { 
      RunAlertPanel("Transfer Messages", 
        "Could not open the mailbox to transfer to.",
          "I understand", NULL, NULL);
      return;
    }
  }

  stream = GetMailBoxStream(mbox);
  SetMailBoxWindowTitle(mbox, string);

  for(i=0; i<nmsgs; i++) {
    item = WMGetFromArray(items, i);
    if (item) { 
      msgno = *(long *)(item->text);
      msgcache = mail_elt(stream, msgno);

      if(MailBoxIsNetwork(mbox)) {

        date = mail_longdate(msgcache);
        env = mail_fetchenvelope (stream, msgno);
        from = GetCharFromAddress(env->from);

        if (!from || strlen(from) < 1) {
          from = wstrdup(myusername());
          from = wstrappend(from, "@");
          from = wstrappend(from, mylocalhost());
        }

        fprintf(file, "\nFrom %s %s", from, ctime(&date));
        wfree(from);
        fprintf(file, "%s", 
          mail_fetch_header (stream,msgno,NIL,NIL,NIL,FT_PEEK | FT_INTERNAL));
        fprintf(file, "%s\n", 
          mail_fetch_text(stream, msgno, NIL, NIL, FT_PEEK | FT_INTERNAL));

      } else {
        snprintf(sequence, 8, "%lu", msgno);
        if(!mail_copy(stream, sequence, mailbox)) { 
          char *err = wstrdup("A problem occurred while transfering:\n");

          err = wstrappend(err, Aileron.errorMsg?Aileron.errorMsg:
                "no reason given");
          RunAlertPanel("Transfer Messages", err,
            "I understand", NULL, NULL);
          wfree(err);
          RestoreMailBoxWindowTitle(mbox);
          return;
        }
      }
      
    }

  }

  
  MarkMessagesAsDeleted(mbox, True);
  if(MailBoxIsNetwork(mbox))
    fclose(file);

  WMAddTimerHandler(1000, restoreTitleAfterTransfer, mbox);

  wfree(mailbox);
}



static void 
initLinkCB(WMWidget *w, void *client)
{
  WMBrowser *bPtr = MailboxesPanel.browser;
  int col = WMGetBrowserSelectedColumn(bPtr);
  char *path, *link, *tmp, *name=NULL;
  WMOpenPanel *panel;

  if (MailboxesPanel.withinNetwork 
    || !WMGetUDStringForKey(Aileron.defaultsDB, "MailDir"))
    return;

  if (col > 0) { 
    if (!(name = WMGetBrowserPathToColumn(bPtr, col-1)))
      return;

    path = wstrdup(WMGetUDStringForKey(Aileron.defaultsDB, "MailDir"));
    path = wstrappend(path, name);

  } else { 
    path = wstrdup(WMGetUDStringForKey(Aileron.defaultsDB, "MailDir"));
    col = 0;
  }

  panel = WMGetOpenPanel(Aileron.screen);
  WMSetFilePanelAutoCompletion(panel, True);

  if (WMRunModalFilePanelForDirectory(panel, NULL, path, NULL, NULL)) {

    if (!(link = WMGetFilePanelFileName(panel))) {
      wfree(path);
      return;
    }


    if (!FileExists(link)) {
      RunAlertPanel("Link Mailbox Path",
        "I won't create a link to a file that does not exist!",
        "I understand", NULL, NULL);
      wfree(link);
      wfree(path);
      return;
    }

    path = wstrappend(path, "/"); { 
      int len = strlen(link)-1;
      if (link[len] == '/') 
        link[len] = 0;
    }
    tmp = getNameFromPath(link);
    path = wstrappend(path, tmp);
    wfree(tmp);

    if (FileExists(path)) {
      RunAlertPanel("Link Mailbox Path",
       "I won't create a link with the same name as an existing mailbox!",
       "I understand", NULL, NULL);
      wfree(link);
      wfree(path);
      return;
    }

    if (symlink(link, path) != 0) { 
      FSErrorhandler("Link Mailbox Path", link, errno);
      wfree(link);
      wfree(path);
      return;
    } else {
      struct stat stat_buf;

      if (stat(link, &stat_buf)==0) {
        WMInsertBrowserItem(bPtr, col, -1, getNameFromPath(link), 
        S_ISDIR(stat_buf.st_mode));
      }
    }
  
    wfree(link);
  }

  wfree(path);
}

static void 
unlinkCB(WMWidget *w, void *client)
{
  WMBrowser *bPtr = MailboxesPanel.browser;
  int col = WMGetBrowserSelectedColumn(bPtr);
  char *name = NULL, *toCol;
  char buf[1];
  int is_dir = 0;
  WMListItem *item;

  if (col < 0 || !WMGetUDStringForKey(Aileron.defaultsDB, "MailDir"))
    return;

  item = WMGetBrowserSelectedItemInColumn(bPtr, col);
  is_dir = item->isBranch;
  
  if (!(toCol = WMGetBrowserPathToColumn(bPtr, col)))
    return;
  name = wstrdup(WMGetUDStringForKey(Aileron.defaultsDB, "MailDir"));
  name = wstrappend(name, toCol);
  wfree(toCol);
  
  if (readlink(name, buf, 1) == -1) {
    FSErrorhandler(is_dir?"Unlink attached folder."
      : "Unlink attached mailbox.", name, errno); {
     wfree(name);
     return;
    }

  } else if (unlink(name) == 0) { 
    WMList *list = WMGetBrowserListInColumn(MailboxesPanel.browser, col);
    if (list) {
      char *path = WMGetUDStringForKey(Aileron.defaultsDB, "MailDir");
      WMClearList(list);
      listDirectoryOnColumn(col, path);
      wfree(path);
    }
  }

  wfree(name);
}


void CloseMailboxesPanel(void)
{
  if (!Aileron.mboxesCreated) 
    return;

  WMUnmapWidget(MailboxesPanel.window);
}


static void
browserClick(WMBrowser *bPtr, void *client)
{
  int i, num, col = WMGetBrowserSelectedColumn(bPtr);
  WMListItem *item;
  char *toCol, *mbox, *string;
  WMPropList *array, *check = NULL;

  if (col < 0) {
    WMSetButtonSelected(MailboxesPanel.autob, 0);
    return;
  }

  if (!(item = WMGetBrowserSelectedItemInColumn(bPtr, col))) {
    WMSetButtonSelected(MailboxesPanel.autob, 0);
    return;
  }
  
  if(item->isBranch) {
    WMSetButtonSelected(MailboxesPanel.autob, 0);
    WMSetButtonEnabled(MailboxesPanel.autob, 0);
  } else { 
    WMSetButtonEnabled(MailboxesPanel.autob, 1);
  }

  WMSetButtonSelected(MailboxesPanel.autob, 0);
    WMSetTextFieldText(MailboxesPanel.namet, NULL);
  
  WMSetTextFieldText(MailboxesPanel.namet, 
    (item->isBranch?item->text:NULL));

  if (!(toCol = WMGetBrowserPathToColumn(bPtr, col))) {
    WMSetButtonSelected(MailboxesPanel.autob, 0);
    return;
  }

  MailboxesPanel.withinNetwork = !strncmp(toCol, "/Network", 8);
  if(MailboxesPanel.withinNetwork) { 
    WMUnmapWidget(MailboxesPanel.linkb);
    WMUnmapWidget(MailboxesPanel.unlinkb);
    WMMapWidget(MailboxesPanel.subb);
    WMMapWidget(MailboxesPanel.unsubb);

    if(col >= 1 ) {
      WMSetButtonEnabled(MailboxesPanel.subb, True);
      WMSetButtonEnabled(MailboxesPanel.unsubb, True);
    } else {
      WMSetButtonEnabled(MailboxesPanel.subb, False);
      WMSetButtonEnabled(MailboxesPanel.unsubb, False);
    }

    if(col == 1 ) {
      WMSetButtonText(MailboxesPanel.openb, "Change");
    } else {
      WMSetButtonText(MailboxesPanel.openb, "Open");
    }

  } else {
    WMUnmapWidget(MailboxesPanel.subb);
    WMUnmapWidget(MailboxesPanel.unsubb);
    WMMapWidget(MailboxesPanel.linkb);
    WMMapWidget(MailboxesPanel.unlinkb);
    WMSetButtonText(MailboxesPanel.openb, "Open");
  }

  wfree(toCol);

  if (item->isBranch) {
    WMSetButtonSelected(MailboxesPanel.autob, 0);
    return;
  }


  /* can only come from Mailboxes, but check just in case... */
  if (!WMGetUDStringForKey(Aileron.defaultsDB, "MailDir")) {
    WMSetButtonSelected(MailboxesPanel.autob, 0);
    return;
  }

  if (MailboxesPanel.withinNetwork) {
    char *npath, *path;

    if (!(path = WMGetBrowserPathToColumn(bPtr, 1)))
      return;

    npath = getNameFromPath(path);
    if(!(mbox = getFullNewtorkName(npath))) {
      wfree(path);
      return;
    }

    wfree(npath);
    wfree(path);
    mbox = wstrappend(mbox, item->text);
  } else {
    int len;
    mbox = wstrdup(WMGetUDStringForKey(Aileron.defaultsDB, "MailDir"));
    len = strlen(mbox)-1;
    if(mbox[len] == '/')
      mbox[len] = 0;
    mbox = wstrappend(mbox, WMGetBrowserPathToColumn(bPtr, col));
  }
  
  array = WMGetUDObjectForKey(Aileron.defaultsDB, "DefaultMailBoxes");
  
  if (!array)
    return;
    
  num = WMGetPropListItemCount(array);
  for (i=0; i<num; i++) {
    if(!(check = WMGetFromPLArray(array, i)))
      continue;
    if (!(string = WMGetFromPLString(check)))
      continue;
      
    if (!strcmp(string, mbox)) {
      wfree(mbox);
      WMSetButtonSelected(MailboxesPanel.autob, 1);
      return;
    }
  } 

/* misbehaves if released... why? */
#if 0
  WMReleasePropList(array);
  if(check) 
    WMReleasePropList(check);
#endif
  WMSetButtonSelected(MailboxesPanel.autob, 0);
  wfree(mbox);

}

static void
browserDClick(WMBrowser *bPtr, WMButton *null)
{

#if 1
  openCB(MailboxesPanel.openb, NULL);
#else
  int col = WMGetBrowserSelectedColumn(bPtr);
  WMListItem *item = WMGetBrowserSelectedItemInColumn(bPtr, col);
/* why is this dying all of a sudden, bPtr (button) 
and MailboxesPanel.openb point to diff. why? */
  if (!item->isBranch) 
    WMPerformButtonClick(MailboxesPanel.openb);
#endif
}



static void 
sizeChanged(void *self, WMNotification *notif)
{
  void *object = WMGetNotificationObject(notif);
    
  if (WMGetNotificationName(notif) == WMViewSizeDidChangeNotification) {
    if (object == WMWidgetView(MailboxesPanel.window)) {

    unsigned short w = WMWidgetWidth(MailboxesPanel.window);
    unsigned short h =  WMWidgetHeight(MailboxesPanel.window);
      WMResizeWidget(MailboxesPanel.browser,  w-20, h-110);

      if(w>190)
        WMSetBrowserMaxVisibleColumns(MailboxesPanel.browser, 2);
      else
        WMSetBrowserMaxVisibleColumns(MailboxesPanel.browser, 1);
    }
  }
}
    


static void
fillColumn(WMBrowserDelegate *self, WMBrowser *bPtr, int col, WMList *list)
{
  char *path; 
  char *toCol;
  
  path = wstrdup(WMGetUDStringForKey(Aileron.defaultsDB, "MailDir"));

  if (col > 0 && (toCol = WMGetBrowserPathToColumn(bPtr, col))) { 
    path = wstrappend(path, toCol);
    wfree(toCol);
  }
  
  listDirectoryOnColumn(col, path);
  wfree(path);
}

static void 
closeImapPanel(WMWidget *self, void *client)
{
  WMDestroyWidget(self);
}

static void
imapFillColumn(WMBrowserDelegate *self, WMBrowser *bPtr, int col, WMList *list)
{
  printf("imaplistDirectoryOnColumn(col, path);\n");
#if 0
  char *path; 
  char *toCol;
  
  path = wstrdup(WMGetUDStringForKey(Aileron.defaultsDB, "MailDir"));

  if (col > 0 && (toCol = WMGetBrowserPathToColumn(bPtr, col))) { 
    path = wstrappend(path, toCol);
    wfree(toCol);
  }
  
  wfree(path);
#endif
}


static void 
unsubCB(WMWidget *w, void *client)
{
}

static void 
subCB(WMWidget *widget, void *client)
{
  unsigned w=380, h=270;
  WMLabel *l;
  WMButton *b;
  WMWindow *window;
  WMBrowser *browser;
  char *path;
  WMTextField *filtert;


  window = WMCreateWindowWithStyle(Aileron.screen, 
    "Aileron IMAP Folders", 
    WMTitledWindowMask | WMClosableWindowMask | WMResizableWindowMask);
  WMSetWindowTitle(window, "Aileron: IMAP Folders");
  WMSetWindowMinSize(window, w, h);
  WMSetWindowMaxSize(window, w, h);
  WMResizeWidget(window, w, h);      
  WMSetViewNotifySizeChanges(WMWidgetView(window), True);
  WMCreateEventHandler(WMWidgetView(window),
    KeyPressMask, handleKeyPresses, NULL);
  WMCreateEventHandler(WMWidgetView(window),
    KeyReleaseMask, handleKeyReleases, NULL);

  
  browser = WMCreateBrowser(window);
  WMSetBrowserAllowMultipleSelection(browser, True);
  WMSetBrowserDelegate(browser, &imapBrowserDelegate);
  path = wstrdup(WMGetUDStringForKey(Aileron.defaultsDB, "MailDir"));
  WMSetBrowserPath(browser, path);
  wfree(path);
  WMSetBrowserPathSeparator(browser, "/");
  WMSetBrowserAction(browser, 
    (WMAction *)browserClick, NULL);
  WMSetBrowserDoubleAction(browser, 
    (WMAction *)browserDClick, NULL);
  WMSetViewNotifySizeChanges(WMWidgetView(browser), True);
  WMSetBalloonTextForView("This browser allows multiple selections.\n"
    "Select all the mailboxes you wish, then \"Subscribe\" them.", 
    WMWidgetView(browser));
  WMSetBrowserMaxVisibleColumns(browser, 2);
  WMSetBrowserTitled(browser, False);
  WMMoveWidget(browser, 10, 10);
  WMResizeWidget(browser, w-20, h-80);

  l = NewLabel(window, "Show only items that contain:", 10, h-60, 170, 20);
  filtert = NewTextField(window, NULL, 192, h-60, 176, 20);
  WMSetBalloonTextForView("You can use regular expressions in this textfield",
    WMWidgetView(filtert));

/* handletext press will sort, on list (can */

  b = WMCreateCommandButton(window);
  WMSetButtonText(b, "Subscribe");
  WMMoveWidget(b, 192, h-30);
  WMResizeWidget(b, 83, 24);
  WMSetButtonAction(b, deleteCB, NULL);

  b = WMCreateCommandButton(window);
  WMSetButtonText(b, "Cancel");
  WMMoveWidget(b, 285, h-30);
  WMResizeWidget(b, 83, 24);
  WMSetButtonAction(b, newCB, NULL);


  WMSetWindowCloseAction(window, closeImapPanel, NULL);
  
  WMRealizeWidget(window);
  WMMapSubwidgets(window);

  WMAppAddWindow(Aileron.appContext, WMWidgetXID(window));

  
  WMMapWidget(window);

  WMLoadBrowserColumnZero(browser);
#if 0
  WMAddNotificationObserver(sizeChanged, &
    WMViewSizeDidChangeNotification, WMWidgetView(window));
#endif

}



void RunMailboxesPanel(void)
{
  unsigned w=190, h=300;
  WMLabel *l;
  WMButton *b;
  char *path;

printf("\n\ndelet NM does not... add severl nm's at once breaks:
 WMGetPLDictionaryKeys (pl=0x40ae5fe0) at getting.c:354
354     getting.c: No such file or directory.\n\n\n");

  if (!WMGetUDStringForKey(Aileron.defaultsDB, "MailDir")) {
    RunAlertPanel("Open Mailboxes Panel",
        "The main folder for mailboxes was not found.\n"
        "An \"Open Panel\" will be shown so you can choose one.",
        "I understand", NULL, NULL);
    changeMailBoxesPath(NULL, NULL);
    if (!WMGetUDStringForKey(Aileron.defaultsDB, "MailDir")) {
      return;
    }
  }

  if (Aileron.mboxesCreated) { 
    XRaiseWindow(Aileron.display, 
    WMWidgetXID(MailboxesPanel.window));
    WMMapWidget(MailboxesPanel.window);
    return;
  }   

  MailboxesPanel.window = WMCreateWindowWithStyle(Aileron.screen, 
    "Aileron Mailboxes", 
    WMTitledWindowMask | WMClosableWindowMask | WMResizableWindowMask);
  WMSetWindowTitle(MailboxesPanel.window, "Aileron: Mailboxes");
  WMSetWindowMinSize(MailboxesPanel.window, w, h);
  WMSetWindowMaxSize(MailboxesPanel.window, w*2, h);
  WMResizeWidget(MailboxesPanel.window, w, h);      
  WMSetWindowResizeIncrements(MailboxesPanel.window, 190, 20);
  WMSetViewNotifySizeChanges(WMWidgetView(MailboxesPanel.window), True);
  WMCreateEventHandler(WMWidgetView(MailboxesPanel.window),
    KeyPressMask, handleKeyPresses, NULL);
  WMCreateEventHandler(WMWidgetView(MailboxesPanel.window),
    KeyReleaseMask, handleKeyReleases, NULL);

  
  MailboxesPanel.browser = WMCreateBrowser(MailboxesPanel.window);
  WMSetBrowserDelegate(MailboxesPanel.browser, &browserDelegate);
  path = wstrdup(WMGetUDStringForKey(Aileron.defaultsDB, "MailDir"));
  WMSetBrowserPath(MailboxesPanel.browser, path);
  wfree(path);
  WMSetBrowserPathSeparator(MailboxesPanel.browser, "/");
  WMSetBrowserAction(MailboxesPanel.browser, 
    (WMAction *)browserClick, NULL);
  WMSetBrowserDoubleAction(MailboxesPanel.browser, 
    (WMAction *)browserDClick, NULL);
  WMSetViewNotifySizeChanges(WMWidgetView(MailboxesPanel.browser), True);
  WMSetBalloonTextForView("If you want to open an existing mailbox "
   "that is not listed in the\nMailboxes Panel, drag the panel to twice "
   "its width to reveal\n a \"Link\" button. Use that button to create a "
   "link to that mailbox.", WMWidgetView(MailboxesPanel.browser));
  

  WMSetBrowserMaxVisibleColumns(MailboxesPanel.browser, 1);
  WMSetBrowserTitled(MailboxesPanel.browser, False);
  WMMoveWidget(MailboxesPanel.browser, 10, 10);
  WMResizeWidget(MailboxesPanel.browser, w-20, h-110);

  l = NewLabel(MailboxesPanel.window, "Name:", 10, h-90, 42, 20);
  MailboxesPanel.namet = 
    NewTextField(MailboxesPanel.window, NULL, w-139, h-90, 130, 20);
/*
  WMCreateEventHandler(WMWidgetView(MailboxesPanel.namet), KeyPressMask,
    checkIfExists, mailboxes);
*/

  MailboxesPanel.withinNetwork = False;
 
  b = WMCreateCommandButton(MailboxesPanel.window);
  WMSetButtonText(b, "Delete");
  WMMoveWidget(b, 10, h-60);
  WMResizeWidget(b, 80, 24);
  WMSetButtonAction(b, deleteCB, NULL);

  b = WMCreateCommandButton(MailboxesPanel.window);
  WMSetButtonText(b, "New");
  WMMoveWidget(b, w-90, h-60);
  WMResizeWidget(b, 80, 24);
  WMSetButtonAction(b, newCB, NULL);


  MailboxesPanel.openb = b = WMCreateCommandButton(MailboxesPanel.window);
  WMSetButtonText(b, "Open");
  WMMoveWidget(b, 10, h-30);
  WMResizeWidget(b, 80, 24);
  WMSetButtonAction(b, openCB, NULL);

  b = WMCreateCommandButton(MailboxesPanel.window);
  WMSetButtonText(b, "Transfer");
  WMMoveWidget(b, w-90, h-30);
  WMResizeWidget(b, 80, 24);
  WMSetButtonImageDefault(b);
  WMSetButtonImagePosition(b, WIPRight);
  WMSetButtonAction(b, transferCB, NULL);
  WMSetBalloonTextForView("After removing messages out of a mailbox window,\n"
    "remember to compact the mailbox.", WMWidgetView(b));

  MailboxesPanel.autob = b = WMCreateSwitchButton(MailboxesPanel.window);
  WMSetButtonTextAlignment(b, WALeft);
  WMSetButtonText(b, "Automatically Open");
  WMSetButtonAction(b, autoOpen, NULL);
  WMMoveWidget(b, w+5, h-90);
  WMResizeWidget(b, 174, 24);
  WMSetBalloonTextForView("If you want Aileron to open a mailbox "
   "when it searches for\n new mail, select it from the list and then click "
   "this button.", WMWidgetView(b));
  WMSetButtonEnabled(MailboxesPanel.autob, 0);


  MailboxesPanel.linkb = b = WMCreateCommandButton(MailboxesPanel.window);
  WMSetButtonText(b, "Link...");
  WMSetButtonAction(b, initLinkCB, NULL);
  WMMoveWidget(b, w+5, h-60);
  WMResizeWidget(b, 80, 24);
  WMSetBalloonTextForView("Click to attach entirely different folders\n"
  "and mailboxes by linking them into the current folder.", WMWidgetView(b));

  MailboxesPanel.unlinkb = b = WMCreateCommandButton(MailboxesPanel.window);
  WMSetButtonText(b, "Unlink");
  WMSetButtonAction(b, unlinkCB, NULL);
  WMMoveWidget(b, w+100, h-60);
  WMResizeWidget(b, 80, 24);
  WMSetBalloonTextForView("Click to detach selected linked folders and "
  "mailboxes.", WMWidgetView(b));

  MailboxesPanel.subb = b = WMCreateCommandButton(MailboxesPanel.window);
  WMSetButtonText(b, "Subscribe...");
  WMSetButtonAction(b, subCB, NULL);
  WMMoveWidget(b, w+5, h-60);
  WMResizeWidget(b, 80, 24);
  WMSetBalloonTextForView("Click to subscribe to remote mailboxes "
    "on this host.", WMWidgetView(b));
    
  MailboxesPanel.unsubb = b = WMCreateCommandButton(MailboxesPanel.window);
  WMSetButtonText(b, "Unsubscribe");
  WMSetButtonAction(b, unsubCB, NULL);
  WMMoveWidget(b, w+100, h-60); 
  WMResizeWidget(b, 80, 24);
  WMSetBalloonTextForView("Click to unsubscribe from remote mailboxes "
    "on this host.", WMWidgetView(b));
  
  b = WMCreateCommandButton(MailboxesPanel.window);
  WMSetButtonTextAlignment(b, WALeft);
  WMSetButtonText(b, "Change Mailboxes folder...");
  WMSetButtonAction(b, changeMailBoxesPath, NULL);
  WMMoveWidget(b, w+5, h-30);
  WMResizeWidget(b, 174, 24);


  WMSetWindowCloseAction(MailboxesPanel.window, closePanel, NULL);
  
  WMRealizeWidget(MailboxesPanel.window);
  WMMapSubwidgets(MailboxesPanel.window);
  WMUnmapWidget(MailboxesPanel.subb);
  WMUnmapWidget(MailboxesPanel.unsubb);

  WMAppAddWindow(Aileron.appContext, WMWidgetXID(MailboxesPanel.window));

  WMHashInsert(Aileron.windowTable, "_MAILBOXES_PANEL_", 
    &MailboxesPanel);
  
  WMMapWidget(MailboxesPanel.window);

  WMLoadBrowserColumnZero(MailboxesPanel.browser);
  WMAddNotificationObserver(sizeChanged, &MailboxesPanel,
    WMViewSizeDidChangeNotification, WMWidgetView(MailboxesPanel.window));

  Aileron.mboxesCreated = True;
}



void mm_lsub(MAILSTREAM *stream, int delimiter, char *mailbox, long attributes)
{
  printf ("mm_lsub: %s\n", mailbox);
}


