jens-maus/yam

View on GitHub
src/mui/FolderListtree.c

Summary

Maintainability
Test Coverage
/***************************************************************************

 YAM - Yet Another Mailer
 Copyright (C) 1995-2000 Marcel Beck
 Copyright (C) 2000-2022 YAM Open Source Team

 This program is free 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

 YAM Official Support Site :  http://www.yam.ch
 YAM OpenSource project    :  http://sourceforge.net/projects/yamos/

 $Id$

 Superclass:  MUIC_NListtree
 Description: NListtree class for displaying a folder listtree

***************************************************************************/

#include "FolderListtree_cl.h"

#include <string.h>
#include <proto/dos.h>
#include <proto/muimaster.h>
#include <libraries/gadtools.h>
#include <libraries/iffparse.h>
#include <mui/NList_mcc.h>
#include <mui/NListtree_mcc.h>

#include "YAM.h"
#include "YAM_find.h"
#include "YAM_mainFolder.h"

#include "mui/ImageArea.h"

#include "Config.h"
#include "FolderList.h"
#include "Locale.h"
#include "MUIObjects.h"
#include "Themes.h"

#include "Debug.h"

/* INCLUDE
#include "Themes.h"
*/

/* CLASSDATA
struct Data
{
  Object *folderImage[FI_MAX];
  char folderStr[SIZE_DEFAULT];
  char totalStr[SIZE_SMALL];
  char unreadStr[SIZE_SMALL];
  char newStr[SIZE_SMALL];
  char sizeStr[SIZE_SMALL];
  struct MUI_NListtree_TreeNode *helpTN;
};
*/

/* Private Functions */
/// FormatFolderInfo
// puts all user defined folder information into a string
static void FormatFolderInfo(char *folderStr, const size_t maxLen,
                             const struct Folder *folder, const struct MUI_NListtree_TreeNode *treeNode)
{
  int imageIndex = -1;

  ENTER();

  // add the folder image
  if(isGroupFolder(folder))
  {
    // special handling for the archive folder group
    if(strcmp(folder->Name, tr(MSG_MA_ARCHIVE)) == 0)
      imageIndex = isFlagSet(treeNode->tn_Flags, TNF_OPEN) ? FI_ARCHIVE_UNFOLD : FI_ARCHIVE_FOLD;
    else
      imageIndex = isFlagSet(treeNode->tn_Flags, TNF_OPEN) ? FI_UNFOLD : FI_FOLD;
  }
  else
  {
    imageIndex = folder->ImageIndex >= 0 ? folder->ImageIndex : FI_FOLD;
  }

  snprintf(folderStr, maxLen, "\033o[%d]", imageIndex);

  // include the folder name/path
  if(folder->Name[0] != '\0')
    strlcat(folderStr, folder->Name, maxLen);
  else
    snprintf(folderStr, maxLen, "%s[%s]", folderStr, folder->Path);

  // append the numbers if this is an close folder group or a folder with a valid index
  if((folder->Type == FT_GROUP && isFlagClear(treeNode->tn_Flags, TNF_OPEN)) ||
     (folder->LoadedMode != LM_UNLOAD && folder->LoadedMode != LM_REBUILD))
  {
    char dst[SIZE_SMALL];

    dst[0] = '\0';

    switch(C->FolderInfoMode)
    {
      case FIM_NAME_ONLY:
      {
        // nothing
      }
      break;

      case FIM_NAME_AND_NEW_MAILS:
      {
        if(folder->New != 0)
          snprintf(dst, sizeof(dst), " (%d)", folder->New);
      }
      break;

      case FIM_NAME_AND_UNREAD_MAILS:
      {
        if(folder->Unread != 0)
          snprintf(dst, sizeof(dst), " (%d)", folder->Unread);
      }
      break;

      case FIM_NAME_AND_NEW_UNREAD_MAILS:
      {
        if(folder->New != 0 || folder->Unread != 0)
          snprintf(dst, sizeof(dst), " (%d/%d)", folder->New, folder->Unread);
      }
      break;

      case FIM_NAME_AND_UNREAD_NEW_MAILS:
      {
        if(folder->New != 0 || folder->Unread != 0)
          snprintf(dst, sizeof(dst), " (%d/%d)", folder->Unread, folder->New);
      }
      break;
    }

    if(dst[0] != '\0')
      strlcat(folderStr, dst, maxLen);
  }

  LEAVE();
}

///

/* Overloaded Methods */
/// OVERLOAD(OM_NEW)
OVERLOAD(OM_NEW)
{
  ENTER();

  if((obj = DoSuperNew(cl, obj,

    InputListFrame,
    MUIA_ContextMenu,                 0,
    MUIA_ShortHelp,                   TRUE,
    MUIA_Font,                        C->FixedFontList ? MUIV_NList_Font_Fixed : MUIV_NList_Font,
    MUIA_Dropable,                    FALSE,
    MUIA_NList_ActiveObjectOnClick,   TRUE,
    MUIA_NList_DefaultObjectOnClick,  FALSE,
    MUIA_NList_Exports,               MUIV_NList_Exports_ColWidth|MUIV_NList_Exports_ColOrder,
    MUIA_NList_Imports,               MUIV_NList_Imports_ColWidth|MUIV_NList_Imports_ColOrder,
    MUIA_NListtree_DragDropSort,      FALSE,
    MUIA_NListtree_Title,             TRUE,
    MUIA_NListtree_DoubleClick,       MUIV_NListtree_DoubleClick_All,

    TAG_MORE, inittags(msg))) != NULL)
  {
    GETDATA;
    ULONG i;

    // prepare the folder images
    data->folderImage[FI_FOLD]           = MakeImageObject("folder_fold",           G->theme.folderImages[FI_FOLD]);
    data->folderImage[FI_UNFOLD]         = MakeImageObject("folder_unfold",         G->theme.folderImages[FI_UNFOLD]);
    data->folderImage[FI_INCOMING]       = MakeImageObject("folder_incoming",       G->theme.folderImages[FI_INCOMING]);
    data->folderImage[FI_INCOMING_NEW]   = MakeImageObject("folder_incoming_new",   G->theme.folderImages[FI_INCOMING_NEW]);
    data->folderImage[FI_OUTGOING]       = MakeImageObject("folder_outgoing",       G->theme.folderImages[FI_OUTGOING]);
    data->folderImage[FI_OUTGOING_NEW]   = MakeImageObject("folder_outgoing_new",   G->theme.folderImages[FI_OUTGOING_NEW]);
    data->folderImage[FI_TRASH]          = MakeImageObject("folder_trash",          G->theme.folderImages[FI_TRASH]);
    data->folderImage[FI_TRASH_NEW]      = MakeImageObject("folder_trash_new",      G->theme.folderImages[FI_TRASH_NEW]);
    data->folderImage[FI_SENT]           = MakeImageObject("folder_sent",           G->theme.folderImages[FI_SENT]);
    data->folderImage[FI_PROTECTED]      = MakeImageObject("status_crypt",          G->theme.statusImages[SI_CRYPT]);
    data->folderImage[FI_SPAM]           = MakeImageObject("folder_spam",           G->theme.folderImages[FI_SPAM]);
    data->folderImage[FI_SPAM_NEW]       = MakeImageObject("folder_spam_new",       G->theme.folderImages[FI_SPAM_NEW]);
    data->folderImage[FI_DRAFTS]         = MakeImageObject("folder_drafts",         G->theme.folderImages[FI_DRAFTS]);
    data->folderImage[FI_DRAFTS_NEW]     = MakeImageObject("folder_drafts_new",     G->theme.folderImages[FI_DRAFTS_NEW]);
    data->folderImage[FI_ARCHIVE]        = MakeImageObject("folder_archive",        G->theme.folderImages[FI_ARCHIVE]);
    data->folderImage[FI_ARCHIVE_FOLD]   = MakeImageObject("folder_archive_fold",   G->theme.folderImages[FI_ARCHIVE_FOLD]);
    data->folderImage[FI_ARCHIVE_UNFOLD] = MakeImageObject("folder_archive_unfold", G->theme.folderImages[FI_ARCHIVE_UNFOLD]);
    for(i = 0; i < ARRAY_SIZE(data->folderImage); i++)
      DoMethod(obj, MUIM_NList_UseImage, data->folderImage[i], i, MUIF_NONE);
  }

  RETURN((IPTR)obj);
  return (IPTR)obj;
}

///
/// OVERLOAD(OM_DISPOSE)
OVERLOAD(OM_DISPOSE)
{
  IPTR result;
  GETDATA;
  ULONG i;

  ENTER();

  for(i=0; i < ARRAY_SIZE(data->folderImage); i++)
  {
    DoMethod(obj, MUIM_NList_UseImage, NULL, i, MUIF_NONE);
    if(data->folderImage[i] != NULL)
    {
      MUI_DisposeObject(data->folderImage[i]);
      data->folderImage[i] = NULL;
    }
  }

  // dispose ourself
  result = DoSuperMethodA(cl, obj, msg);

  RETURN(result);
  return result;
}

///
/// OVERLOAD(OM_GET)
// get some stuff of our instance data
OVERLOAD(OM_GET)
{
  GETDATA;
  IPTR *store = ((struct opGet *)msg)->opg_Storage;

  switch(((struct opGet *)msg)->opg_AttrID)
  {
    case ATTR(ImageArray): *store = (ULONG)data->folderImage; return TRUE;
  }

  return DoSuperMethodA(cl, obj, msg);
}

///
/// OVERLOAD(MUIM_CheckShortHelp)
// check whether the entry under the mouse pointer changed and a new bubble help is required
OVERLOAD(MUIM_CheckShortHelp)
{
  GETDATA;
  struct MUIP_CheckShortHelp *csh = (struct MUIP_CheckShortHelp *)msg;
  struct MUI_NListtree_TestPos_Result res;
  BOOL changeHelp;

  ENTER();

  DoMethod(obj, MUIM_NListtree_TestPos, csh->mx, csh->my, &res);
  changeHelp = (res.tpr_TreeNode == data->helpTN) ? TRUE : FALSE;

  RETURN(changeHelp);
  return changeHelp;
}

///
/// OVERLOAD(MUIM_CreateShortHelp)
// set up a text for the bubble help
OVERLOAD(MUIM_CreateShortHelp)
{
  GETDATA;
  struct MUIP_CreateShortHelp *csh = (struct MUIP_CreateShortHelp *)msg;
  struct MUI_NListtree_TestPos_Result res;
  char *shortHelp = NULL;

  ENTER();

  DoMethod(obj, MUIM_NListtree_TestPos, csh->mx, csh->my, &res);
  if(res.tpr_TreeNode != NULL)
  {
    struct Folder *folder = ((struct FolderNode *)res.tpr_TreeNode->tn_User)->folder;

    if(folder != NULL && !isGroupFolder(folder))
    {
      char sizestr[SIZE_DEFAULT];

      FormatSize(folder->Size, sizestr, sizeof(sizestr), SF_AUTO);

      if(asprintf(&shortHelp, tr(MSG_FOLDERINFO_SHORTHELP), folder->Name,
                                                            folder->Fullpath,
                                                            sizestr,
                                                            folder->Total,
                                                            folder->New,
                                                            folder->Unread) == -1)
      {
        shortHelp = NULL;
      }
      else
      {
        data->helpTN = res.tpr_TreeNode;
      }
    }
  }

  RETURN(shortHelp);
  return (IPTR)shortHelp;
}

///
/// OVERLOAD(MUIM_DeleteShortHelp)
// free the bubble help text
OVERLOAD(MUIM_DeleteShortHelp)
{
  struct MUIP_DeleteShortHelp *dsh = (struct MUIP_DeleteShortHelp *)msg;

  ENTER();

  free(dsh->help);

  RETURN(0);
  return 0;
}

///
/// OVERLOAD(MUIM_NListtree_Display)
OVERLOAD(MUIM_NListtree_Display)
{
  struct MUIP_NListtree_Display *ndm = (struct MUIP_NListtree_Display *)msg;

  ENTER();

  if(ndm->TreeNode != NULL)
  {
    GETDATA;
    struct FolderNode *fnode = (struct FolderNode *)ndm->TreeNode->tn_User;

    data->folderStr[0] = '\0';
    data->totalStr[0] = '\0';
    data->unreadStr[0] = '\0';
    data->newStr[0] = '\0';
    data->sizeStr[0] = '\0';

    ndm->Array[0] = data->folderStr;
    ndm->Array[1] = data->totalStr;
    ndm->Array[2] = data->unreadStr;
    ndm->Array[3] = data->newStr;
    ndm->Array[4] = data->sizeStr;

    if(fnode != NULL && fnode->folder != NULL)
    {
      struct Folder *entry = fnode->folder;

      // create folderStr
      FormatFolderInfo(data->folderStr, sizeof(data->folderStr), entry, ndm->TreeNode);

      switch(entry->Type)
      {
        case FT_GROUP:
        {
          ndm->Preparse[0] = (entry->New != 0 || entry->Unread != 0) ? C->StyleFGroupUnread : C->StyleFGroupRead;

          // show group stats for closed nodes only
          if(isFlagClear(ndm->TreeNode->tn_Flags, TNF_OPEN))
          {
            // if other folder columns are enabled lets fill the values in
            if(hasFColTotal(C->FolderCols))
              snprintf(data->totalStr, sizeof(data->totalStr), "%d", entry->Total);

            if(hasFColUnread(C->FolderCols) && entry->Unread != 0)
              snprintf(data->unreadStr, sizeof(data->unreadStr), "%d", entry->Unread);

            if(hasFColNew(C->FolderCols) && entry->New != 0)
              snprintf(data->newStr, sizeof(data->newStr), "%d", entry->New);

            if(hasFColSize(C->FolderCols) && entry->Size > 0)
              FormatSize(entry->Size, data->sizeStr, sizeof(data->sizeStr), SF_AUTO);
          }
        }
        break;

        default:
        {
          if(entry->LoadedMode != LM_UNLOAD && entry->LoadedMode != LM_REBUILD)
          {
            if(entry->New != 0)
              ndm->Preparse[0] = C->StyleFolderNew;
            else if(entry->Unread != 0)
              ndm->Preparse[0] = C->StyleFolderUnread;
            else
              ndm->Preparse[0] = C->StyleFolderRead;

            // if other folder columns are enabled lets fill the values in
            if(hasFColTotal(C->FolderCols))
              snprintf(data->totalStr, sizeof(data->totalStr), "%d", entry->Total);

            if(hasFColUnread(C->FolderCols) && entry->Unread != 0)
              snprintf(data->unreadStr, sizeof(data->unreadStr), "%d", entry->Unread);

            if(hasFColNew(C->FolderCols) && entry->New != 0)
              snprintf(data->newStr, sizeof(data->newStr), "%d", entry->New);

            if(hasFColSize(C->FolderCols) && entry->Size > 0)
              FormatSize(entry->Size, data->sizeStr, sizeof(data->sizeStr), SF_AUTO);
          }
          else
            ndm->Preparse[0] = (char *)MUIX_I;

          if(isProtectedFolder(entry))
            snprintf(data->folderStr, sizeof(data->folderStr), "%s \033o[%d]", data->folderStr, FI_PROTECTED);
        }
      }
    }
  }
  else
  {
    ndm->Array[0] = (STRPTR)tr(MSG_Folder);
    ndm->Array[1] = (STRPTR)tr(MSG_Total);
    ndm->Array[2] = (STRPTR)tr(MSG_Unread);
    ndm->Array[3] = (STRPTR)tr(MSG_New);
    ndm->Array[4] = (STRPTR)tr(MSG_Size);
  }

  RETURN(0);
  return 0;
}

///

/* Public Methods */