/*
TMPMIX.CPP

Temporary panel miscellaneous utility functions

*/

#include "TmpPanel.hpp"
#include <string>
#include <utils.h>

const TCHAR *GetMsg(int MsgId)
{
  return(Info.GetMsg(Info.ModuleNumber,MsgId));
}

void InitDialogItems(const MyInitDialogItem *Init,struct FarDialogItem *Item,
                    int ItemsNumber)
{
  int i;
  struct FarDialogItem *PItem=Item;
  const MyInitDialogItem *PInit=Init;
  for (i=0;i<ItemsNumber;i++,PItem++,PInit++)
  {
    PItem->Type=PInit->Type;
    PItem->X1=PInit->X1;
    PItem->Y1=PInit->Y1;
    PItem->X2=PInit->X2;
    PItem->Y2=PInit->Y2;
    PItem->Flags=PInit->Flags;
    PItem->Focus=0;
    PItem->History=0;
    PItem->DefaultButton=0;
#ifdef UNICODE
    PItem->MaxLen=0;
#endif
#ifndef UNICODE
    lstrcpy(PItem->Data,PInit->Data!=-1 ? GetMsg(PInit->Data) : "");
#else
    PItem->PtrData = PInit->Data!=-1 ? GetMsg(PInit->Data) : L"";
#endif
  }
}

void FreePanelItems(PluginPanelItem *Items, DWORD Total)
{
  if(Items){
    for (DWORD I=0;I<Total;I++) {
      if (Items[I].Owner)
        free ((void*)Items[I].Owner);
#ifdef UNICODE
      if (Items[I].FindData.lpwszFileName)
        free((void*)Items[I].FindData.lpwszFileName);
#endif
    }
    free (Items);
  }
}

TCHAR *ParseParam(TCHAR *& str)
{
  TCHAR* p=str;
  TCHAR* parm=NULL;
  if(*p==_T('|')){
    parm=++p;
    p=_tcschr(p,_T('|'));
    if(p){
      *p=_T('\0');
      str=p+1;
      FSF.LTrim(str);
      return parm;
    }
  }
  return NULL;
}

void GoToFile(const TCHAR *Target, BOOL AnotherPanel)
{
#ifndef UNICODE
  int FCTL_SetPanelDir = AnotherPanel?FCTL_SETANOTHERPANELDIR:FCTL_SETPANELDIR;
  int FCTL_GetPanelInfo = AnotherPanel?FCTL_GETANOTHERPANELINFO:FCTL_GETPANELINFO;
  int FCTL_RedrawPanel = AnotherPanel?FCTL_REDRAWANOTHERPANEL:FCTL_REDRAWPANEL;
#define _PANEL_HANDLE  INVALID_HANDLE_VALUE
#else
#define FCTL_SetPanelDir  FCTL_SETPANELDIR
#define FCTL_GetPanelInfo FCTL_GETPANELINFO
#define FCTL_RedrawPanel  FCTL_REDRAWPANEL
  HANDLE  _PANEL_HANDLE = AnotherPanel?PANEL_PASSIVE:PANEL_ACTIVE;
#endif

  PanelRedrawInfo PRI;
  PanelInfo PInfo;
  int pathlen;

  const TCHAR *p = FSF.PointToName(const_cast<TCHAR*>(Target));
  StrBuf Name(lstrlen(p)+1);
  lstrcpy(Name,p);
  pathlen=(int)(p-Target);
  StrBuf Dir(pathlen+1);
  if (pathlen)
    memcpy(Dir.Ptr(),Target,pathlen*sizeof(TCHAR));
  Dir[pathlen]=_T('\0');

  FSF.Trim(Name);
  FSF.Trim(Dir);
  FSF.Unquote(Name);
  FSF.Unquote(Dir);

  if (*Dir.Ptr())
  {
#ifndef UNICODE
    Info.Control(_PANEL_HANDLE,FCTL_SetPanelDir,Dir.Ptr());
#else
    Info.Control(_PANEL_HANDLE,FCTL_SetPanelDir,0,(LONG_PTR)Dir.Ptr());
#endif
  }

#ifndef UNICODE
  Info.Control(_PANEL_HANDLE,FCTL_GetPanelInfo,&PInfo);
#else
  Info.Control(_PANEL_HANDLE,FCTL_GetPanelInfo,0,(LONG_PTR)&PInfo);
#endif

  PRI.CurrentItem=PInfo.CurrentItem;
  PRI.TopPanelItem=PInfo.TopPanelItem;

  for(int J=0; J < PInfo.ItemsNumber; J++)
  {

#ifndef UNICODE
#define FileName PInfo.PanelItems[J].FindData.cFileName
#else
#define FileName (PPI?PPI->FindData.lpwszFileName:NULL)
    PluginPanelItem* PPI=(PluginPanelItem*)malloc(Info.Control(_PANEL_HANDLE,FCTL_GETPANELITEM,J,0));
    if(PPI)
    {
      Info.Control(_PANEL_HANDLE,FCTL_GETPANELITEM,J,(LONG_PTR)PPI);
    }
#endif

    if(!FSF.LStricmp(Name,FSF.PointToName(FileName)))
#undef FileName
    {
      PRI.CurrentItem=J;
      PRI.TopPanelItem=J;
#ifdef UNICODE
      free(PPI);
#endif
      break;
    }
#ifdef UNICODE
    free(PPI);
#endif
  }
#ifndef UNICODE
  Info.Control(_PANEL_HANDLE,FCTL_RedrawPanel,&PRI);
#else
  Info.Control(_PANEL_HANDLE,FCTL_RedrawPanel,0,(LONG_PTR)&PRI);
#endif
#undef _PANEL_HANDLE
#undef FCTL_SetPanelDir
#undef FCTL_GetPanelInfo
#undef FCTL_RedrawPanel
}

void WFD2FFD(WIN32_FIND_DATA &wfd, FAR_FIND_DATA &ffd)
{
  ffd.dwFileAttributes=wfd.dwFileAttributes;
  ffd.dwUnixMode=wfd.dwUnixMode;
  ffd.ftCreationTime=wfd.ftCreationTime;
  ffd.ftLastAccessTime=wfd.ftLastAccessTime;
  ffd.ftLastWriteTime=wfd.ftLastWriteTime;
  ffd.nFileSize=wfd.nFileSize;
  ffd.nPhysicalSize=wfd.nPhysicalSize;
#ifndef UNICODE
  strncpy(ffd.cFileName,wfd.cFileName, ARRAYSIZE(ffd.cFileName));
#else
  ffd.lpwszFileName = wcsdup(wfd.cFileName);
#endif
}

#ifdef UNICODE
wchar_t* FormNtPath(const wchar_t* path, StrBuf& buf) {
  int l = lstrlen(path);
  buf.Grow(l + 1);
  lstrcpy(buf, path);
  return buf;
}
#endif

TCHAR* ExpandEnvStrs(const TCHAR* input, StrBuf& output) {
#ifdef UNICODE
  std::string s;
  Wide2MB(input, s);
  Environment::ExpandString(s, false);
  std::wstring w;
  StrMB2Wide(s, w);
  output.Grow(w.size() + 1);
  lstrcpy(output, w.c_str());

#else
  output.Grow(MAX_PATH);
  FSF.ExpandEnvironmentStr(input, output, output.Size());
#endif
  return output;
}

static DWORD LookAtPath(const TCHAR *dir, const TCHAR *name, TCHAR *buffer = NULL, DWORD buf_size = 0)
{
	std::wstring path(dir);
	if (path.empty())
		return 0;

	if (path[path.size()-1]!=GOOD_SLASH)
		path+= GOOD_SLASH;

	path+= name;
	if (GetFileAttributes(path.c_str())==INVALID_FILE_ATTRIBUTES)
		return 0;

	if (buf_size >= (path.size() + 1))
		wcscpy(buffer, path.c_str());

	return path.size() + 1;
}


bool FindListFile(const TCHAR *FileName, StrBuf &output)
{
  StrBuf Path;
  DWORD dwSize;

#ifdef UNICODE
  StrBuf FullPath;
  GetFullPath(FileName, FullPath);
  StrBuf NtPath;
  FormNtPath(FullPath, NtPath);
#else
  const char* FullPath = FileName;
  const char* NtPath = FileName;
#endif

  const TCHAR *final=NULL;
  if (GetFileAttributes(NtPath) != INVALID_FILE_ATTRIBUTES)
  {
#ifdef UNICODE
    output.Grow(FullPath.Size());
#else
    output.Grow(lstrlen(FullPath)+1);
#endif
    lstrcpy(output, FullPath);
    return true;
  }
  {
    const TCHAR *tmp = FSF.PointToName(Info.ModuleName);
    Path.Grow((int)(tmp-Info.ModuleName+1));
    lstrcpyn(Path,Info.ModuleName,(int)(tmp-Info.ModuleName+1));
    dwSize = LookAtPath(Path, FileName);
    if (dwSize)
    {
      final = Path;
      goto success;
    }
  }
  ExpandEnvStrs(_T("$FARHOME:$PATH"),Path);
  for (TCHAR *str=Path, *p=_tcschr(Path,_T(':')); *str; p=_tcschr(str,_T(':')))
  {
    if (p)
      *p = 0;

    FSF.Unquote(str);
    FSF.Trim(str);

    if (*str)
    {
      dwSize = LookAtPath(str, FileName);
      if (dwSize)
      {
        final = str;
        goto success;
      }
    }

    if (p)
      str = p+1;
    else
      break;
  }

  return false;

success:

  output.Grow(dwSize);
  if (LookAtPath(final, FileName, output, dwSize)!=dwSize)
	  fprintf(stderr, "LookAtPath: unexpected size\n");

  return true;
}

#ifdef UNICODE
wchar_t* GetFullPath(const wchar_t* input, StrBuf& output)
{
  output.Grow(MAX_PATH);
  int size = FSF.ConvertPath(CPM_FULL, input, output, output.Size());
  if (size > output.Size())
  {
    output.Grow(size);
    FSF.ConvertPath(CPM_FULL, input, output, output.Size());
  }
  return output;
}
#endif
