/****************************************************************************** * Copyright (C) 2005 by la9527 * * * * 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.* ******************************************************************************/ #include "mcd.h" #include "cmdshell.h" using namespace MLSUTIL; using namespace MLS; Mcd::Mcd(const string& sDir) { _pRoot = NULL; _nSRow = 0; _nSCol = 0; _sCode = "LINM0.7"; _nCounter = 0; _pReader = NULL; _bMcdSort = true; _bHidden = false; if (sDir == "") _pRoot = new Dir("/", NULL); else _pRoot = new Dir(sDir, NULL); _pOrder.clear(); SetOrder(); SetCur("/"); } Mcd::~Mcd() { if (_pRoot) { for (pDirIterator p = _pOrder.begin(); p!=_pOrder.end(); ++p) delete *p; _pRoot = NULL; } } bool Mcd::Load(const char* sFile) { FILE *pFile; char sCheckVersion[10]; bool bLinked; bool bDirNotNull; int nPreDepth = 0, nRow = 0; Dir *preNode = NULL, *pNode = NULL; memset(&sCheckVersion, 0, sizeof(sCheckVersion)); if ( sFile ) pFile = fopen(sFile, "rb"); if (!pFile) return false; fread(sCheckVersion, _sCode.size(), 1, pFile); if (_sCode != sCheckVersion) return false; File tFile; while( !feof( pFile ) ) { int nDepth = fgetc(pFile); int nCheck = fgetc(pFile); int nLink = fgetc(pFile); int nSize =fgetc(pFile)*256; nSize += fgetc(pFile); if (feof(pFile)) break; char sFullName[nSize+1]; fread(sFullName, nSize, 1, pFile); sFullName[nSize] = 0; // depth에 따른 노드 조정 if ( nDepth > nPreDepth ) { pNode = preNode; } else { while( nDepth < nPreDepth ) { pNode = pNode->pParentDir; nPreDepth--; } if ( pNode ) nRow++; } preNode = new Dir(sFullName, pNode, nCheck == 1 ? true : false); preNode->tFile.bLink = nLink == 1 ? true : false; preNode->nDepth = nDepth; preNode->nRow = nRow; if ( pNode ) pNode->vNode.push_back(preNode); else pNode = preNode; nPreDepth = nDepth; } fclose(pFile); if ( pNode ) { while(pNode->pParentDir) pNode = pNode->pParentDir; _pRoot = pNode; } else { return false; } SetOrder(); return true; } bool Mcd::Save(const char* sFile) { FILE *pFile = NULL; if ( sFile ) pFile = fopen(sFile, "wb"); if (!pFile) return false; fwrite(_sCode.c_str(), _sCode.size(), 1, pFile); for (pDirIterator i = _pOrder.begin(); i!= _pOrder.end(); i++) { fputc ((*i)->nDepth, pFile); fputc( (*i)->bCheck == true ? 1 : 0, pFile); fputc( (*i)->tFile.bLink == true ? 1 : 0, pFile); fputc ((*i)->tFile.sFullName.size() / 256, pFile); fputc ((*i)->tFile.sFullName.size() % 256, pFile); fputs ((*i)->tFile.sFullName.c_str(), pFile); } fclose(pFile); return true; } /// \brief tree 이하의 노드를 모두 지운다. /// \param tree 지우고자 하는 자식 노드 /// \param bOrdering 정렬 여부 void Mcd::Destroy(Dir *pTree, bool bOrdering) {// 비재귀 if (pTree == NULL) return; if (_pOrder.empty()) return; int nDepth = pTree->nDepth; g_Log.Write("_pOrder size [%d] [%d]", _pOrder.size(), nDepth); for (pDirIterator i= _pOrder.begin()+pTree->nIndex+1; i!=_pOrder.end(); i++) { g_Log.Write("depth [%d] ndepth [%d] 1", (*i)->nDepth, nDepth); if (nDepth >= (*i)->nDepth) break; g_Log.Write("depth [%d] ndepth [%d] 2", (*i)->nDepth, nDepth); delete *i; } g_Log.Write("_pOrder size [%d] [%d] end", _pOrder.size(), nDepth); pTree->vNode.clear(); pTree->bCheck = false; if (bOrdering) { SetOrder(); } } /// \brief str이 가르키는 directory로 현재 위치를 이동시킨다. /// \param str 현재 directory로 위치시키고자하는 directory명 void Mcd::SetCur(const string &sPath) { // 01234567890123456789 // m_pRoot->name = "/sdfsd/sdfsdsf/" // "/sdfsd/sdfsdsf/p/3/" // str이 "" 일 경우 처음 위치로 if (sPath.empty()) { _pCur = _pOrder.begin(); return; } if ( sPath == _pRoot->tFile.sFullName // 루트일때 || sPath.size() < _pRoot->tFile.sFullName.size()) // 루트사이즈보다 작을때 { _pCur = _pOrder.begin(); return; } // / // 012345678901234 // /home/ioklo/ppp string sTmpPath = sPath; string sTmpPath2 = _pRoot->tFile.sFullName; if (sTmpPath.substr(0, 1) != "/") sTmpPath = "/" + sTmpPath; if (sTmpPath2.substr(0, 1) != "/") sTmpPath2 = "/" + sTmpPath2; //g_Log.Write("MCD::SetCur [%s] [%s]", sPath.c_str(), sTmpPath.substr(sTmpPath2.size()).c_str()); StringToken tStrToken(sTmpPath.substr(sTmpPath2.size()), "/"); pDirIterator i; Dir *pNode = _pRoot; while (tStrToken.Next()) { const string &t = tStrToken.Get(); // 자식들 중에 있는거 찾아낸다. for (i = pNode->vNode.begin(); i != pNode->vNode.end() ;i++) { if ((*i)->tFile.sName == t) break; } if (i == pNode->vNode.end()) {_pCur = _pOrder.begin(); return;} pNode = (*i); } _pCur = _pOrder.begin() + (*i)->nIndex; } /// \brief mcd상에서 위 directory로 이동한다. void Mcd::Key_Up() { pDirIterator i; if ((*_pCur)->pParentDir) { if ((*_pCur)->nDepth != (*(_pCur-1))->nDepth ) { pDirIterator t; for (t = _pCur-1 ; t != _pOrder.begin() - 1; t--) if ((*t)->nDepth == (*_pCur)->nDepth) break; if (t != _pOrder.begin()-1) _pCur = t; else Key_Left(); } else _pCur--; } else Key_Left(); } /// \brief mcd상에서 아래 directory로 이동한다. void Mcd::Key_Down() { // 아래부분에 뭔가 있을 경우 if ((*_pCur)->pParentDir) { if (_pCur+1 == _pOrder.end() || (*_pCur)->nDepth != (*(_pCur+1))->nDepth ) { pDirIterator t; for (t = _pCur+1 ; t != _pOrder.end(); t++) if ((*t)->nDepth == (*_pCur)->nDepth) break; if (t != _pOrder.end()) _pCur = t; else Key_Right(); } else _pCur++; } } /// \brief mcd상에서 왼쪽(상위 directory)로 이동한다. void Mcd::Key_Left() { if ((*_pCur)->pParentDir) _pCur= _pOrder.begin() + (*_pCur)->pParentDir->nIndex; } /// \brief mcd상에서 오른쪽(하위 directory)로 이동한다. void Mcd::Key_Right() { if (!(*_pCur)->vNode.empty()) { _pCur= _pOrder.begin() + (*_pCur)->vNode.front()->nIndex; g_Log.Write("Key_Right vNode empty [%s]", (*_pCur)->Path().c_str()); } else { string p = (*_pCur)->Path(); g_Log.Write("Key_Right [%s]", p.c_str()); Scan(*_pCur, 1); SetCur(p); if ((*_pCur)->vNode.empty()) if (_pCur+1 != _pOrder.end()) _pCur++; else if (!(*_pCur)->vNode.empty() && (*_pCur)->nDepth - _nSCol == 5) _nSCol = _nSCol + 1; } } void Mcd::Key_Home() { SetCur("/"); } void Mcd::Key_End() { while((!(*_pCur)->vNode.empty())) { _pCur= _pOrder.begin() + (*_pCur)->vNode.front()->nIndex; g_Log.Write("Key_Right vNode empty [%s]", (*_pCur)->Path().c_str()); } } /// \brief mcd 정렬을 한다. void Mcd::SetOrder() { vector