Now we can start talking. I downloaded the gcvs 1.01 version from sourceforge
and tried to compile. It failed in different places than where yours did.
TclGlue compiled correctly and I have below the compile line which is the
same as yours:
g++ -DHAVE_CONFIG_H -I. -I. -I.. -I../gcvs -I../gcvs/src -I/. -I../cvstree
-I../rf -Wall -I/usr/include/gtk-1.2 -I/usr/include/glib-1.2
-I/usr/lib/glib/include -I/usr/X11R6/include -DqUnix -DqGTK
-I/usr/X11R6/include -DqCvsDebug=0 -g -O2 -I/usr/local/include/.
-DUSE_TCL="1" -c TclGlue.cpp
What did fail were UCvsFiles.cpp and UcvsFolders.cpp. These both suffer from
the same problem of typecasting on an overloaded function called ResetView. I
have attached both amended sources so you can compare. It also appears that
the version you have is also suffering from typecasting problems.
Keep Cool
On Saturday 09 October 2004 00:20, Gregory Smirnov wrote:
> Hello,
>
> The point was that you cannot build completely all available packages on
> the fly in gentoo, like someone told here.
>
> I work in KDE environment too, but I guess you have gtk libraries
> installed. If you don't want to try, then there no point to continue
> discussion. I live fine without this gui wrapper.
>
> Regarding subversion, do not forget to update it every week to patch new
> bugs.
>
> Cheers,
> Gregory
>
> --- FYI ---
> g++ -DHAVE_CONFIG_H -I. -I. -I.. -I../gcvs -I../gcvs/src -I/. -I../cvstree
> -I../rf -Wall -I/usr/include/gtk-1.2 -I/usr/include/glib-1.2
> -I/usr/lib/glib/include -I/usr/X11R6/include -DqUnix -DqGTK
> -I/usr/X11R6/include -DqCvsDebug=0 -O2 -march=athlon-xp
> -fomit-frame-pointer -I/usr/include -DUSE_TCL="1" -c TclGlue.cpp
> TclGlue.cpp: In function `int tclCvsBrowserProc(void*, Tcl_Interp*, int,
> char**)':
> TclGlue.cpp:444: error: invalid conversion from `const char*' to `char*'
> TclGlue.cpp:449: error: invalid conversion from `const char*' to `char*'
> TclGlue.cpp:453: error: invalid conversion from `const char*' to `char*'
> TclGlue.cpp:458: error: invalid conversion from `const char*' to `char*'
> TclGlue.cpp:463: error: invalid conversion from `const char*' to `char*'
> TclGlue.cpp:468: error: invalid conversion from `const char*' to `char*'
> TclGlue.cpp:473: error: invalid conversion from `const char*' to `char*'
> TclGlue.cpp:478: error: invalid conversion from `const char*' to `char*'
> TclGlue.cpp:483: error: invalid conversion from `const char*' to `char*'
> TclGlue.cpp:488: error: invalid conversion from `const char*' to `char*'
> TclGlue.cpp:495: error: invalid conversion from `const char*' to `char*'
> TclGlue.cpp:500: error: invalid conversion from `const char*' to `char*'
> TclGlue.cpp:505: error: invalid conversion from `const char*' to `char*'
> TclGlue.cpp:510: error: invalid conversion from `const char*' to `char*'
> TclGlue.cpp:515: error: invalid conversion from `const char*' to `char*'
> TclGlue.cpp: In function `int tclCvsEntriesProc(void*, Tcl_Interp*, int,
> char**)':
> TclGlue.cpp:647: error: invalid conversion from `int (*)(void*,
> Tcl_Interp*, int, char**)' to `int (*)(void*, Tcl_Interp*, int, const
> char**)' TclGlue.cpp: In constructor `CTcl_Interp::CTcl_Interp()':
> TclGlue.cpp:968: error: invalid conversion from `int (*)(void*,
> Tcl_Interp*, int, char**)' to `int (*)(void*, Tcl_Interp*, int, const
> char**)' TclGlue.cpp:971: error: invalid conversion from `int (*)(void*,
> Tcl_Interp*, int, char**)' to `int (*)(void*, Tcl_Interp*, int, const
> char**)' TclGlue.cpp:973: error: invalid conversion from `int (*)(void*,
> Tcl_Interp*, int, char**)' to `int (*)(void*, Tcl_Interp*, int, const
> char**)' TclGlue.cpp:975: error: invalid conversion from `int (*)(void*,
> Tcl_Interp*, int, char**)' to `int (*)(void*, Tcl_Interp*, int, const
> char**)' TclGlue.cpp:977: error: invalid conversion from `int (*)(void*,
> Tcl_Interp*, int, char**)' to `int (*)(void*, Tcl_Interp*, int, const
> char**)' TclGlue.cpp:979: error: invalid conversion from `int (*)(void*,
> Tcl_Interp*, int, char**)' to `int (*)(void*, Tcl_Interp*, int, const
> char**)' TclGlue.cpp:987: error: invalid conversion from `int (*)(void*,
> Tcl_Interp*, int, char**)' to `int (*)(void*, Tcl_Interp*, int, const
> char**)' TclGlue.cpp:990: error: invalid conversion from `int (*)(void*,
> Tcl_Interp*, int, char**)' to `int (*)(void*, Tcl_Interp*, int, const
> char**)' TclGlue.cpp:993: error: invalid conversion from `int (*)(void*,
> Tcl_Interp*, int, char**)' to `int (*)(void*, Tcl_Interp*, int, const
> char**)' TclGlue.cpp:1234:2: warning: no newline at end of file
> make[2]: *** [TclGlue.o] Error 1
> make[2]: *** Waiting for unfinished jobs....
>
> ---
>
> On Friday 08 October 2004 07:40, Andrew Cilia wrote:
> > That won't help much. Besides, I'm set up over KDE only. Just try the
> > compilation at your end and post the screen messages to the group.
> >
> > BTW, you might want to take a look at subversion if you're into version
> > control.
> >
> > On Friday 08 October 2004 01:28, Gregory Smirnov wrote:
> > > Yes. I meant gcvs. Just try to build it. If you manage to build without
> > > errors then we will go in details. Errors I think was with gnome
> > > libraries. Last time I tried to build it about 3 month ago. If I don't
> > > forget, then will try tomorrow. I use Gentoo at work and debian on my
> > > lap.
> > >
> > > Cheers,
> > > Gregory
> > >
> > > On Thursday 07 October 2004 23:04, Andrew Cilia wrote:
> > > > OK, now assuming that you meant gcvs, what errors are you getting?
> > > >
> > > > On Wednesday 06 October 2004 19:11, Gregory Smirnov wrote:
> > > > > give me a hint what viagra my Gentoo lacks to build gsvs?
> > > > >
> > > > > :-) Gregory
> > > > >
> > > > > _______________________________________________
> > > > > MLUG-list mailing list
> > > > > [email protected]
> > > > > http://mailserv.megabyte.net/mailman/listinfo/mlug-list
> > >
> > > _______________________________________________
> > > MLUG-list mailing list
> > > [email protected]
> > > http://mailserv.megabyte.net/mailman/listinfo/mlug-list
>
> _______________________________________________
> MLUG-list mailing list
> [email protected]
> http://mailserv.megabyte.net/mailman/listinfo/mlug-list
--
Andrew Cilia B.Sc. MCSE ICSE RHCT
Software Engineer
___________________________________
Philip Toledo Limited
Computer & Communications Solutions
Notabile Road, Mriehel BKR01, Malta
Telephone:+356 21445566
Mobile: +356 99430588
Fax: +356 21484316
Email: [EMAIL PROTECTED]
Web Site: http://www.ptl.com.mt
/*
** 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 1, 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.
*/
/*
* Author : Alexandre Parenteau <[EMAIL PROTECTED]> --- February 2000
*/
/*
*
*/
#include "stdafx.h"
#if qGTK
# include <gtk/gtk.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "UCvsFolders.h"
#include "UCvsDialogs.h"
#include "UCvsApp.h"
#include "UCvsFiles.h"
#include "UCvsCommands.h"
#include "UCvsFrame.h"
#include "MultiString.h"
#include "FileTraversal.h"
#include "CvsEntries.h"
#include "CvsPrefs.h"
#include "AppConsole.h"
#include "CvsCommands.h"
#include "TclGlue.h"
#include "MacrosSetup.h"
#include "CvsArgs.h"
#ifdef WIN32
static PCPStr gOldLoc("P_BrowserLoc", "C:\\");
#endif
#ifdef qUnix
static PCPStr gOldLoc("P_BrowserLoc");
#endif
static const char *gDummyFile = "@@@dummy file@@@";
static CMString gHistoryLocs(100, "P_BrowserLocs");
static void *sFolderIcon;
static void *sFolderUnknownIcon;
static void *sFolderIgnoredIcon;
static void *sFolderMissingIcon;
enum
{
kIconFolderClosed,
kIconFolderOpened,
kIconFolderCVSClosed,
kIconFolderCVSOpened,
kIconFolderIgnoreClosed,
kIconFolderIgnoreOpened,
kIconFolderIgnoreLost
};
UIMPLEMENT_DYNAMIC(UCvsFolders, UWidget)
UBEGIN_MESSAGE_MAP(UCvsFolders, UWidget)
ON_UUPDATECMD(cmdUPDATE, UCvsFolders::OnCmdUIUpdate)
ON_UUPDATECMD(cmdCOMMIT, UCvsFolders::OnCmdUIUpdate)
ON_UUPDATECMD(cmdDIFF, UCvsFolders::OnCmdUIUpdate)
ON_UUPDATECMD(cmdEDIT, UCvsFolders::OnCmdUIUpdate)
ON_UUPDATECMD(cmdEDITORS, UCvsFolders::OnCmdUIUpdate)
ON_UUPDATECMD(cmdLOCKF, UCvsFolders::OnCmdUIUpdate)
ON_UUPDATECMD(cmdLOG, UCvsFolders::OnCmdUIUpdate)
ON_UUPDATECMD(cmdRELEASE, UCvsFolders::OnCmdUIUpdate)
ON_UUPDATECMD(cmdSTATUS, UCvsFolders::OnCmdUIUpdate)
ON_UUPDATECMD(cmdUNEDIT, UCvsFolders::OnCmdUIUpdate)
ON_UUPDATECMD(cmdUPDATE, UCvsFolders::OnCmdUIUpdate)
ON_UUPDATECMD(cmdQUERYUPDATE, UCvsFolders::OnCmdUIUpdate)
ON_UUPDATECMD(cmdUNLOCKF, UCvsFolders::OnCmdUIUpdate)
ON_UUPDATECMD(cmdWATCHERS, UCvsFolders::OnCmdUIUpdate)
ON_UUPDATECMD(cmdWATCHON, UCvsFolders::OnCmdUIUpdate)
ON_UUPDATECMD(cmdWATCHOFF, UCvsFolders::OnCmdUIUpdate)
ON_UUPDATECMD(cmdTAGNEW, UCvsFolders::OnCmdUIUpdate)
ON_UUPDATECMD(cmdTAGDELETE, UCvsFolders::OnCmdUIUpdate)
ON_UUPDATECMD(cmdTAGBRANCH, UCvsFolders::OnCmdUIUpdate)
ON_UUPDATECMD(cmdADD, UCvsFolders::OnCmdUIAdd)
ON_UUPDATECMD(cmdEXPLORE, UCvsFolders::OnCmdUIExplore)
ON_UUPDATECMD(cmdRELOAD, UCvsFolders::OnCmdUIReload)
ON_UUPDATECMD(cmdIGNORE, UCvsFolders::OnCmdUIIgnore)
ON_UUPDATECMD(cmdCHECKOUT, UCvsFolders::OnCmdUICheckout)
ON_UUPDATECMD(cmdIMPORT, UCvsFolders::OnCmdUIImport)
ON_UUPDATECMD_RANGE(cmdSELMACRO, cmdSELMACROEND, UCvsFolders::OnCmdUIMacrosSel)
ON_UDESTROY(UCvsFolders)
ON_UCREATE(UCvsFolders)
ON_TREE_EXPANDING(kUMainWidget, UCvsFolders::OnTreeExpanding)
ON_TREE_SELECTING(kUMainWidget, UCvsFolders::OnTreeSelecting)
ON_UCOMMAND(cmdUPDATE, UCvsFolders::OnCmdUpdate)
ON_UCOMMAND(cmdADD, UCvsFolders::OnCmdAdd)
ON_UCOMMAND(cmdCOMMIT, UCvsFolders::OnCmdCommit)
ON_UCOMMAND(cmdQUERYUPDATE, UCvsFolders::OnCmdQueryUpdate)
ON_UCOMMAND(cmdDIFF, UCvsFolders::OnCmdDiff)
ON_UCOMMAND(cmdLOG, UCvsFolders::OnCmdLog)
ON_UCOMMAND(cmdSTATUS, UCvsFolders::OnCmdStatus)
ON_UCOMMAND(cmdLOCKF, UCvsFolders::OnCmdLock)
ON_UCOMMAND(cmdUNLOCKF, UCvsFolders::OnCmdUnlock)
ON_UCOMMAND(cmdWATCHON, UCvsFolders::OnCmdWatchOn)
ON_UCOMMAND(cmdWATCHOFF, UCvsFolders::OnCmdWatchOff)
ON_UCOMMAND(cmdEDIT, UCvsFolders::OnCmdEdit)
ON_UCOMMAND(cmdUNEDIT, UCvsFolders::OnCmdUnedit)
ON_UCOMMAND(cmdWATCHERS, UCvsFolders::OnCmdWatchers)
ON_UCOMMAND(cmdEDITORS, UCvsFolders::OnCmdEditors)
ON_UCOMMAND(cmdRELEASE, UCvsFolders::OnCmdRelease)
ON_UCOMMAND(cmdTAGNEW, UCvsFolders::OnCmdTagNew)
ON_UCOMMAND(cmdTAGDELETE, UCvsFolders::OnCmdTagDelete)
ON_UCOMMAND(cmdTAGBRANCH, UCvsFolders::OnCmdTagBranch)
ON_UCOMMAND(cmdEXPLORE, UCvsFolders::OnCmdExplore)
ON_UCOMMAND(cmdRELOAD, UCvsFolders::OnCmdReload)
ON_UCOMMAND(cmdIGNORE, UCvsFolders::OnCmdIgnore)
ON_UCOMMAND(cmdCHECKOUT, UCvsFolders::OnCmdCheckout)
ON_UCOMMAND(cmdIMPORT, UCvsFolders::OnCmdImport)
ON_UCOMMAND_RANGE(cmdSELMACRO, cmdSELMACROEND, UCvsFolders::OnCmdMacrosSel)
UEND_MESSAGE_MAP()
#if 0
ON_WM_RBUTTONDOWN() // TODO
#endif
static bool sTemporaryTurnOffNotify = false;
class CTempToggleBool
{
public:
CTempToggleBool(bool & value) : m_value(value), m_didSetIt(false)
{
if(!m_value)
{
m_didSetIt = true;
m_value = true;
}
}
~CTempToggleBool()
{
if(m_didSetIt)
m_value = false;
}
protected:
bool & m_value;
bool m_didSetIt;
};
static void *GetIcon(UCvsFolders *treeCrtl, UTREEITEM item, bool hasCvsInfos, bool expand, EntnodeData *data)
{
int newImage;
void *result = 0L;
if(data == 0L)
{
if(expand)
newImage = hasCvsInfos ? kIconFolderCVSOpened : kIconFolderOpened;
else
newImage = hasCvsInfos ? kIconFolderCVSClosed : kIconFolderClosed;
}
else
{
if(expand)
{
if(data->IsIgnored())
newImage = kIconFolderIgnoreOpened;
else if(data->IsUnknown())
newImage = kIconFolderOpened;
else if(data->IsMissing())
newImage = kIconFolderIgnoreLost;
else
newImage = kIconFolderCVSOpened;
}
else
{
if(data->IsIgnored())
newImage = kIconFolderIgnoreClosed;
else if(data->IsUnknown())
newImage = kIconFolderClosed;
else if(data->IsMissing())
newImage = kIconFolderIgnoreLost;
else
newImage = kIconFolderCVSClosed;
}
}
#if qGTK
void *pixmap = 0L;
switch(newImage)
{
case kIconFolderClosed:
case kIconFolderOpened:
pixmap = sFolderUnknownIcon;
break;
case kIconFolderCVSClosed:
case kIconFolderCVSOpened:
pixmap = sFolderIcon;
break;
case kIconFolderIgnoreClosed:
case kIconFolderIgnoreOpened:
pixmap = sFolderIgnoredIcon;
break;
case kIconFolderIgnoreLost:
pixmap = sFolderMissingIcon;
break;
}
if(pixmap != 0L)
{
result = gtk_pixmap_new (GTK_PIXMAP(pixmap)->pixmap, GTK_PIXMAP(pixmap)->mask);
}
#endif
return result;
}
// regarding a path and a root item, create an
// item with a dummy item inside if and only if
// the folder is not empty.
class TBrowserFillDummy : public TraversalReport
{
public:
UTREEITEM m_root;
UTREEITEM m_item;
UCvsFolders *m_treeCtrl;
bool m_empty;
bool m_hascvs;
EntnodeData *m_data;
UStr m_dirname;
TBrowserFillDummy(UCvsFolders *treeCtrl, UTREEITEM root, UTREEITEM item, EntnodeData *data) :
m_root(root), m_item(item), m_treeCtrl(treeCtrl), m_empty(true),
m_hascvs(false), m_data(data) {}
virtual ~TBrowserFillDummy() {}
virtual kTraversal EnterDirectory(const char *fullpath, const char *dirname, const FSSpec * macspec)
{
m_dirname = dirname;
#if qUnix
if(m_dirname.empty())
m_dirname = fullpath; // '/'
#endif
return kContinueTraversal;
}
virtual kTraversal ExitDirectory(const char *fullpath)
{
if(m_item == 0L)
{
UTREE_INSERT insert;
insert.parent = m_root;
insert.icon = GetIcon(m_treeCtrl, m_item, m_hascvs, false, m_data);
insert.title = m_dirname;
insert.data = 0L;
UEventSendMessage(m_treeCtrl->GetWidID(), EV_TREE_INSERT, kUMainWidget, &insert);
m_item = insert.result;
}
// assign the entries to this item
UTREE_INFO query;
query.item = m_item;
if(m_data != 0L)
{
UEventSendMessage(m_treeCtrl->GetWidID(), EV_TREE_GETINFO, kUMainWidget, &query);
EntnodeData *data = (EntnodeData *)query.data;
if(m_data != 0L)
m_data->Ref();
query.data = m_data;
UEventSendMessage(m_treeCtrl->GetWidID(), EV_TREE_SETDATA, kUMainWidget, &query);
if(data != 0L)
data->UnRef();
}
else
{
UEventSendMessage(m_treeCtrl->GetWidID(), EV_TREE_GETINFO, kUMainWidget, &query);
m_data = (EntnodeData *)query.data;
}
if(m_empty)
return kContinueTraversal;
// add a dummy item to simulate the folder
// is not empty. This dummy item will be
// replaced by a complete listing when the
// node is expanding...
UTREE_INSERT insert;
insert.parent = m_item;
insert.icon = 0L;
insert.title = gDummyFile;
insert.data = 0L;
UEventSendMessage(m_treeCtrl->GetWidID(), EV_TREE_INSERT, kUMainWidget, &insert);
return kContinueTraversal;
}
virtual kTraversal OnError(const char *err, int errcode)
{
cvs_err(err);
cvs_err("\n");
cvs_err(strerror(errcode));
cvs_err("\n");
return kTraversalError;
}
virtual kTraversal OnIdle(const char *fullpath)
{
return kContinueTraversal;
}
virtual kTraversal OnDirectory(const char *fullpath,
const char *fullname,
const char *name,
const struct stat & dir, const FSSpec * macspec)
{
#if qUnix
if(strcmp(name, "CVS") == 0)
#else
if(stricmp(name, "cvs") == 0)
#endif
m_hascvs = true;
else
m_empty = false;
return kSkipFile;
}
};
// regarding a path and a root item, create an
// item with all the subdirectories inside.
class TBrowserFill : public TraversalReport
{
public:
UTREEITEM m_root;
UTREEITEM m_item;
UCvsFolders *m_treeCtrl;
CSortList<ENTNODE> & m_entries;
std::vector<UStr> m_ignlist;
TBrowserFill(UCvsFolders *treeCtrl, UTREEITEM root, UTREEITEM item, CSortList<ENTNODE> & entries) :
m_root(root), m_item(item), m_treeCtrl(treeCtrl),
m_entries(entries) {}
virtual ~TBrowserFill() {}
virtual kTraversal EnterDirectory(const char *fullpath, const char *dirname, const FSSpec * macspec)
{
ASSERT(m_item != 0L);
// assign the entries to this item
Entries_Open (m_entries, fullpath);
BuildIgnoredList(m_ignlist, fullpath);
return kContinueTraversal;
}
virtual kTraversal ExitDirectory(const char *fullpath)
{
m_ignlist.erase(m_ignlist.begin(), m_ignlist.end());
UTREE_INFO query;
query.item = m_item;
UEventSendMessage(m_treeCtrl->GetWidID(), EV_TREE_GETINFO, kUMainWidget, &query);
query.icon = GetIcon(m_treeCtrl, m_item, true /*ignored*/, true, (EntnodeData *)query.data);
UEventSendMessage(m_treeCtrl->GetWidID(), EV_TREE_SETICON, kUMainWidget, &query);
return kContinueTraversal;
}
virtual kTraversal OnError(const char *err, int errcode)
{
return kTraversalError;
}
virtual kTraversal OnIdle(const char *fullpath)
{
return kContinueTraversal;
}
virtual kTraversal OnDirectory(const char *fullpath,
const char *fullname,
const char *name,
const struct stat & dir, const FSSpec * macspec)
{
#if qUnix
if(strcmp(name, "CVS") == 0)
#else
if(stricmp(name, "cvs") == 0)
#endif
return kSkipFile;
// is the sub-directory ignored ?
EntnodeData *data = Entries_SetVisited(fullpath, m_entries, name, dir, true, &m_ignlist);
if(!(bool)gFileViewIgnore && data->IsIgnored())
return kSkipFile;
// create the item for the sub-directory
TBrowserFillDummy traverse(m_treeCtrl, m_item, 0L, data);
/*kTraversal res = */FileTraverse(fullname, traverse);
// assign the icon regarding our Entries info
if(traverse.m_item != 0L)
{
UTREE_INFO query;
query.item = traverse.m_item;
query.icon = GetIcon(m_treeCtrl, m_item, true /*ignored*/, false, data);
UEventSendMessage(m_treeCtrl->GetWidID(), EV_TREE_SETICON, kUMainWidget, &query);
}
return kSkipFile;
}
};
UCvsFolders::UCvsFolders() : UWidget(kUCvsFoldersID)
{
}
UCvsFolders::~UCvsFolders()
{
}
void UCvsFolders::OnDestroy(void)
{
delete this;
}
void UCvsFolders::OnCreate(void)
{
if(sFolderIcon == 0L)
{
sFolderIcon = UCreate_pixmap(this, "folder.xpm");
sFolderUnknownIcon = UCreate_pixmap(this, "foldunk.xpm");
sFolderIgnoredIcon = UCreate_pixmap(this, "foldign.xpm");
sFolderMissingIcon = UCreate_pixmap(this, "foldmiss.xpm");
}
UStr newpath;
newpath = (const char *)gOldLoc;
if(newpath.empty())
newpath = gCvsPrefs.Home();
// set the initial root
ResetBrowser(newpath, true);
}
void UCvsFolders::ResetBrowser(const char *path, bool notifyView)
{
UWaitCursor wait;
DeleteAllItems();
bool isReload = path != 0L && !m_root.empty() && stricmp(m_root, path) == 0;
m_root = path;
if(path == 0L)
return;
if(!isReload)
{
if(HasPersistentSettings(m_root))
LoadPersistentSettings(m_root);
else
{
// check if the path has a CVS folder. If not,
// we don't want the user to be prompted (like when
// WinCvs is starting for the first time).
UStr cvsFolder(m_root);
if(!cvsFolder.endsWith(kPathDelimiter))
cvsFolder << kPathDelimiter;
cvsFolder << "CVS";
struct stat sb;
if (stat(cvsFolder, &sb) != -1 && S_ISDIR(sb.st_mode))
AskCreatePersistentSettings(m_root);
}
}
if(stricmp(gOldLoc, m_root) != 0)
gOldLoc = m_root;
// update the history combo
gHistoryLocs.Insert(m_root);
UEventSendMessage(kUCvsFrameID, EV_COMBO_RESETALL, UCvsFrame::kDirCombo, 0L);
const std::vector<UStr> & list = gHistoryLocs.GetList();
std::vector<UStr>::const_iterator i;
int pos = 0;
for(i = list.begin(); i != list.end(); ++i, pos++)
{
UEventSendMessage(kUCvsFrameID, EV_COMBO_APPEND,
UCvsFrame::kDirCombo, (void *)(const char *)*i);
}
UEventSendMessage(kUCvsFrameID, EV_COMBO_SETSEL, UMAKEINT(UCvsFrame::kDirCombo, 0), 0L);
// fill the browser
TBrowserFillDummy traverse(this, 0L, 0L, 0L);
/*kTraversal res = */FileTraverse(m_root, traverse);
if(traverse.m_item != 0L)
{
UEventSendMessage(GetWidID(), EV_TREE_EXPAND, UMAKEINT(kUMainWidget, 0), traverse.m_item);
if(notifyView && UCvsApp::gApp->GetFilesView())
UCvsApp::gApp->GetFilesView()->ResetView(path);
}
}
void UCvsFolders::ResetView(bool forceReload, bool notifyView)
{
UWaitCursor doWait;
std::vector<UStr> allExpanded;
StoreExpanded(allExpanded);
bool contentChanged = false;
UStr selPath;
UTREEITEM selItem;
UEventSendMessage(GetWidID(), EV_TREE_GETSEL, kUMainWidget, &selItem);
if(selItem != 0L)
RetrievePath(selItem, selPath);
if(forceReload)
{
ResetBrowser(m_root);
contentChanged = true;
}
if(contentChanged)
{
// restore the expanded paths and the selected item
std::vector<UStr>::const_iterator i;
for(i = allExpanded.begin(); i != allExpanded.end(); ++i)
{
StepToLocation(*i);
}
if(!selPath.empty())
{
selItem = GetItemByLocation(selPath);
if(selItem != 0L)
UEventSendMessage(GetWidID(), EV_TREE_SELECT, UMAKEINT(kUMainWidget, 0), selItem);
}
}
// we don't need to notify the file view if we force the reload
// because that's already done
if(notifyView)
{
UCvsApp::gApp->GetFilesView()->ResetView(forceReload);
}
UEventSendMessage(GetWidID(), EV_CHGFOCUS, kUMainWidget, 0L);
}
void UCvsFolders::StoreExpanded(std::vector<UStr> & allExpanded, UTREEITEM root)
{
UTREE_INFO query;
query.item = root;
UEventSendMessage(GetWidID(), EV_TREE_GETINFO, kUMainWidget, &query);
UTREEITEM item = query.item;
if(item == 0L)
return;
if(query.expanded)
{
UStr path;
RetrievePath(item, path);
allExpanded.push_back(path);
}
UTREEITEM childItem = query.child;
while(childItem != 0L)
{
StoreExpanded(allExpanded, childItem);
query.item = childItem;
UEventSendMessage(GetWidID(), EV_TREE_GETINFO, kUMainWidget, &query);
childItem = query.next;
}
}
void UCvsFolders::StepToLocation(const char *path, bool notifyView)
{
UStr root(m_root);
if(!root.endsWith(kPathDelimiter))
root << kPathDelimiter;
UStr subpath(path);
if(!subpath.endsWith(kPathDelimiter))
subpath << kPathDelimiter;
// check if it is a sub-path
if(strncmp(root, subpath, root.length()) != 0)
return;
UTREE_INFO query;
query.item = 0L;
UEventSendMessage(GetWidID(), EV_TREE_GETINFO, kUMainWidget, &query);
UTREEITEM item = query.item;
UTREEITEM lastitem = 0L;
if(item == 0L)
return;
// step inside synchronized
const char *tmp = (const char *)subpath + root.length() - 1;
while((tmp = strchr(tmp, kPathDelimiter)) != 0L)
{
const char *name = ++tmp;
if(name[0] == '\0')
break;
UStr subname;
const char *tmp2 = strchr(name, kPathDelimiter);
if(tmp2 == 0L)
subname = name;
else
subname.set(name, tmp2 - name);
query.item = item;
UEventSendMessage(GetWidID(), EV_TREE_GETINFO, kUMainWidget, &query);
UTREEITEM childItem = query.child;
// find the subitem which matches this name
while(childItem != 0L)
{
query.item = childItem;
UEventSendMessage(GetWidID(), EV_TREE_GETINFO, kUMainWidget, &query);
EntnodeData *data = (EntnodeData *)query.data;
if(data != 0L)
{
#ifdef qUnix
if(strcmp((*data)[EntnodeData::kName], subname) == 0)
#else
if(_stricmp((*data)[EntnodeData::kName], subname) == 0)
#endif
{
// found it !
lastitem = item = childItem;
UEventSendMessage(GetWidID(), EV_TREE_EXPAND, UMAKEINT(kUMainWidget, 0), item);
break;
}
}
childItem = query.next;
}
}
// in case this is called by the view, turn off notifying
// when the item gets selected
if(lastitem != 0L)
{
if(!notifyView)
{
CTempToggleBool toggler(sTemporaryTurnOffNotify);
UEventSendMessage(GetWidID(), EV_TREE_SELECT, UMAKEINT(kUMainWidget, 0), lastitem);
}
else
{
UEventSendMessage(GetWidID(), EV_TREE_SELECT, UMAKEINT(kUMainWidget, 0), lastitem);
}
}
}
UTREEITEM UCvsFolders::GetItemByLocation(const char *path)
{
UStr root(m_root);
if(!root.endsWith(kPathDelimiter))
root << kPathDelimiter;
UStr subpath(path);
if(!subpath.endsWith(kPathDelimiter))
subpath << kPathDelimiter;
// check if it is a sub-path
if(strncmp(root, subpath, root.length()) != 0)
return 0L;
UTREE_INFO query;
query.item = 0L;
UEventSendMessage(GetWidID(), EV_TREE_GETINFO, kUMainWidget, &query);
UTREEITEM item = query.item;
if(item == 0L)
return 0L;
// step inside synchronized
const char *tmp = (const char *)subpath + root.length() - 1;
while((tmp = strchr(tmp, kPathDelimiter)) != 0L)
{
const char *name = ++tmp;
if(name[0] == '\0')
break;
CStr subname;
const char *tmp2 = strchr(name, kPathDelimiter);
if(tmp2 == 0L)
subname = name;
else
subname.set(name, tmp2 - name);
UTREEITEM childItem = query.child;
// find the subitem which matches this name
while(childItem != 0L)
{
query.item = childItem;
UEventSendMessage(GetWidID(), EV_TREE_GETINFO, kUMainWidget, &query);
EntnodeData *data = (EntnodeData *)query.data;
if(data != 0L)
{
#if qUnix
if(strcmp((*data)[EntnodeData::kName], subname) == 0)
#else
if(_stricmp((*data)[EntnodeData::kName], subname) == 0)
#endif
{
item = childItem;
break;
}
}
childItem = query.next;
}
if(childItem == 0L)
return 0L;
}
return item;
}
void UCvsFolders::OnTreeExpanding(int collapse, UTREEITEM item)
{
// many situations make that we enter here twice. Fortunately enough
// we only dare the first signal.
static bool sSemaphore = false;
USemaphore policeman(sSemaphore);
if(policeman.IsEnteredTwice())
return;
UWaitCursor wait;
UTREE_INFO query;
query.item = item;
UEventSendMessage(GetWidID(), EV_TREE_GETINFO, kUMainWidget, &query);
EntnodeData *data = (EntnodeData *)query.data;
// we refuse to expand in this case cause the folder is not really here
if(data != 0L && data->IsMissing())
{
UEventSendMessage(GetWidID(), EV_TREE_EXPAND, UMAKEINT(kUMainWidget, 1), item);
return;
}
// erase all the childs
DeleteAllItems(item);
UStr path;
RetrievePath(item, path);
if(collapse)
{
TBrowserFillDummy traverse(this, 0L, item, 0L);
/*kTraversal res = */FileTraverse(path, traverse);
}
else
{
CSortList<ENTNODE> entries(200, ENTNODE::Compare);
TBrowserFill traverse(this, 0L, item, entries);
/*kTraversal res = */FileTraverse(path, traverse);
#if qGTK
// gtk is closing the tree when we removed everything in it
UEventSendMessage(GetWidID(), EV_TREE_EXPAND, UMAKEINT(kUMainWidget, 0), item);
#endif
// add the missing folders
Entries_SetMissing(entries);
int numEntries = entries.NumOfElements();
for(int i = 0; i < numEntries; i++)
{
const ENTNODE & theNode = entries.Get(i);
EntnodeData *data = ((ENTNODE *)&theNode)->Data();
if(!data->IsMissing() || data->GetType() != ENT_SUBDIR)
continue;
UTREE_INSERT insert;
insert.parent = item;
insert.icon = GetIcon(this, item, false, false, data->Ref());
insert.title = (*data)[EntnodeData::kName];
insert.data = data;
UEventSendMessage(GetWidID(), EV_TREE_INSERT, kUMainWidget, &insert);
}
}
}
void UCvsFolders::OnTreeSelecting(int deselect, UTREEITEM item)
{
if(deselect)
return;
UTREE_INFO query;
query.item = item;
UEventSendMessage(GetWidID(), EV_TREE_GETINFO, kUMainWidget, &query);
EntnodeData *data = (EntnodeData *)query.data;
if(data != 0L && data->IsMissing())
return;
if(!sTemporaryTurnOffNotify)
{
UStr path;
RetrievePath(item, path);
UCvsFiles *fileView = (UCvsFiles *)UEventQueryWidget(kUCvsFilesID);
if(fileView != 0L)
{
ASSERT(fileView->IsKindOf(URUNTIME_CLASS(UCvsFiles)));
fileView->ResetView((const char *)path);
}
}
}
void UCvsFolders::SetDefaultRoot(const char *root)
{
struct stat sb;
if (stat(root, &sb) == -1 || !S_ISDIR(sb.st_mode))
{
cvs_err("Cannot access directory '%s' (error %d)\n", root, errno);
return;
}
gOldLoc = root;
}
void UCvsFolders::RetrievePath(UTREEITEM item, UStr & path)
{
UStr tmp, newPath;
path = "";
do
{
UTREE_INFO query;
query.item = item;
UEventSendMessage(GetWidID(), EV_TREE_GETINFO, kUMainWidget, &query);
item = query.parent;
tmp = path;
newPath = item == 0L ? (const char *)m_root : query.title;
if(!newPath.endsWith(kPathDelimiter))
newPath << kPathDelimiter;
newPath << path;
path = newPath;
} while(item != 0L);
}
void UCvsFolders::DeleteAllItems(void)
{
DeleteAllItems(NULL);
}
void UCvsFolders::DeleteAllItems(UTREEITEM root)
{
// we don't want the file view to be notified when things get deleted
CTempToggleBool toggler(sTemporaryTurnOffNotify);
UTREE_INFO query;
bool eraseRoot = false;
query.item = root;
UEventSendMessage(GetWidID(), EV_TREE_GETINFO, kUMainWidget, &query);
if(root == 0L)
{
root = query.item;
eraseRoot = true;
}
if(root == 0L)
return;
UTREEITEM childItem = query.child;
// erase all the childs
while(childItem != 0L)
{
UTREE_INFO queryChild;
queryChild.item = childItem;
UEventSendMessage(GetWidID(), EV_TREE_GETINFO, kUMainWidget, &queryChild);
EntnodeData *data = (EntnodeData *)queryChild.data;
if(data != 0L)
{
queryChild.data = 0L; // So that subsequent references after UnRef() won't SEGV
UEventSendMessage(GetWidID(), EV_TREE_SETDATA, kUMainWidget, &queryChild);
data->UnRef(); // Or move this one after DeleteAllItems? so we don't loose one system call. For now, safe way
}
DeleteAllItems(childItem);
UEventSendMessage(GetWidID(), EV_TREE_DELETE, kUMainWidget, childItem);
childItem = queryChild.next;
}
// erase the root only if initially root was 0L
if(eraseRoot)
{
EntnodeData *data = (EntnodeData *)query.data;
ASSERT(data == 0L);
UEventSendMessage(GetWidID(), EV_TREE_DELETE, kUMainWidget, root);
}
}
bool UCvsFolders::DisableGeneric()
{
UCvsApp *app = UCvsApp::gApp;
return app->IsCvsRunning() || gCvsPrefs.empty() || !HasFocus();
}
void UCvsFolders::OnUpdateGeneric(UCmdUI* pCmdUI, bool needCvsInfos)
{
if(DisableGeneric())
{
pCmdUI->Enable(false);
return;
}
UTREEITEM *item;
UEventSendMessage(GetWidID(), EV_TREE_GETSEL, kUMainWidget, &item);
if(item == 0L)
{
pCmdUI->Enable(false);
return;
}
UStr path;
RetrievePath(item, path);
if(!path.endsWith(kPathDelimiter))
path << kPathDelimiter;
path << "CVS";
struct stat sb;
if (stat(path, &sb) == -1 || !S_ISDIR(sb.st_mode))
pCmdUI->Enable(!needCvsInfos);
else
pCmdUI->Enable(needCvsInfos);
}
int UCvsFolders::OnCmdUpdate(void)
{
UTREEITEM *item;
UEventSendMessage(GetWidID(), EV_TREE_GETSEL, kUMainWidget, &item);
ASSERT(item != 0L);
UStr path;
RetrievePath(item, path);
CvsCmdUpdateFolder(path);
return 0;
}
void UCvsFolders::OnCmdUIUpdate(UCmdUI *pCmdUI)
{
OnUpdateGeneric(pCmdUI, true);
}
int UCvsFolders::OnCmdAdd(void)
{
UTREEITEM *item;
UEventSendMessage(GetWidID(), EV_TREE_GETSEL, kUMainWidget, &item);
ASSERT(item != 0L);
UStr path;
RetrievePath(item, path);
CvsCmdAddFolder(path);
return 0;
}
int UCvsFolders::OnCmdCommit(void)
{
UTREEITEM *item;
UEventSendMessage(GetWidID(), EV_TREE_GETSEL, kUMainWidget, &item);
ASSERT(item != 0L);
UStr path;
RetrievePath(item, path);
CvsCmdCommitFolder(path);
return 0;
}
int UCvsFolders::OnCmdQueryUpdate(void)
{
UTREEITEM *item;
UEventSendMessage(GetWidID(), EV_TREE_GETSEL, kUMainWidget, &item);
ASSERT(item != 0L);
UStr path;
RetrievePath(item, path);
CvsCmdUpdateFolder(path, true);
return 0;
}
int UCvsFolders::OnCmdDiff(void)
{
UTREEITEM *item;
UEventSendMessage(GetWidID(), EV_TREE_GETSEL, kUMainWidget, &item);
ASSERT(item != 0L);
UStr path;
RetrievePath(item, path);
CvsCmdDiffFolder(path);
return 0;
}
int UCvsFolders::OnCmdLog(void)
{
UTREEITEM *item;
UEventSendMessage(GetWidID(), EV_TREE_GETSEL, kUMainWidget, &item);
ASSERT(item != 0L);
UStr path;
RetrievePath(item, path);
CvsCmdLogFolder(path);
return 0;
}
int UCvsFolders::OnCmdStatus(void)
{
UTREEITEM *item;
UEventSendMessage(GetWidID(), EV_TREE_GETSEL, kUMainWidget, &item);
ASSERT(item != 0L);
UStr path;
RetrievePath(item, path);
CvsCmdStatusFolder(path);
return 0;
}
int UCvsFolders::OnCmdLock(void)
{
UTREEITEM *item;
UEventSendMessage(GetWidID(), EV_TREE_GETSEL, kUMainWidget, &item);
ASSERT(item != 0L);
UStr path;
RetrievePath(item, path);
CvsCmdLockFolder(path);
return 0;
}
int UCvsFolders::OnCmdUnlock(void)
{
UTREEITEM *item;
UEventSendMessage(GetWidID(), EV_TREE_GETSEL, kUMainWidget, &item);
ASSERT(item != 0L);
UStr path;
RetrievePath(item, path);
CvsCmdUnlockFolder(path);
return 0;
}
int UCvsFolders::OnCmdWatchOn(void)
{
UTREEITEM *item;
UEventSendMessage(GetWidID(), EV_TREE_GETSEL, kUMainWidget, &item);
ASSERT(item != 0L);
UStr path;
RetrievePath(item, path);
CvsCmdWatchOnFolder(path);
return 0;
}
int UCvsFolders::OnCmdWatchOff(void)
{
UTREEITEM *item;
UEventSendMessage(GetWidID(), EV_TREE_GETSEL, kUMainWidget, &item);
ASSERT(item != 0L);
UStr path;
RetrievePath(item, path);
CvsCmdWatchOffFolder(path);
return 0;
}
int UCvsFolders::OnCmdEdit(void)
{
UTREEITEM *item;
UEventSendMessage(GetWidID(), EV_TREE_GETSEL, kUMainWidget, &item);
ASSERT(item != 0L);
UStr path;
RetrievePath(item, path);
CvsCmdEditFolder(path);
return 0;
}
int UCvsFolders::OnCmdUnedit(void)
{
UTREEITEM *item;
UEventSendMessage(GetWidID(), EV_TREE_GETSEL, kUMainWidget, &item);
ASSERT(item != 0L);
UStr path;
RetrievePath(item, path);
CvsCmdUneditFolder(path);
return 0;
}
int UCvsFolders::OnCmdWatchers(void)
{
UTREEITEM *item;
UEventSendMessage(GetWidID(), EV_TREE_GETSEL, kUMainWidget, &item);
ASSERT(item != 0L);
UStr path;
RetrievePath(item, path);
CvsCmdWatchersFolder(path);
return 0;
}
int UCvsFolders::OnCmdEditors(void)
{
UTREEITEM *item;
UEventSendMessage(GetWidID(), EV_TREE_GETSEL, kUMainWidget, &item);
ASSERT(item != 0L);
UStr path;
RetrievePath(item, path);
CvsCmdEditorsFolder(path);
return 0;
}
int UCvsFolders::OnCmdRelease(void)
{
UTREEITEM *item;
UEventSendMessage(GetWidID(), EV_TREE_GETSEL, kUMainWidget, &item);
ASSERT(item != 0L);
UStr path;
RetrievePath(item, path);
CvsCmdReleaseFolder(path);
return 0;
}
int UCvsFolders::OnCmdTagNew(void)
{
UTREEITEM *item;
UEventSendMessage(GetWidID(), EV_TREE_GETSEL, kUMainWidget, &item);
ASSERT(item != 0L);
UStr path;
RetrievePath(item, path);
CvsCmdTagCreateFolder(path);
return 0;
}
int UCvsFolders::OnCmdTagDelete(void)
{
UTREEITEM *item;
UEventSendMessage(GetWidID(), EV_TREE_GETSEL, kUMainWidget, &item);
ASSERT(item != 0L);
UStr path;
RetrievePath(item, path);
CvsCmdTagDeleteFolder(path);
return 0;
}
int UCvsFolders::OnCmdTagBranch(void)
{
UTREEITEM *item;
UEventSendMessage(GetWidID(), EV_TREE_GETSEL, kUMainWidget, &item);
ASSERT(item != 0L);
UStr path;
RetrievePath(item, path);
CvsCmdTagBranchFolder(path);
return 0;
}
int UCvsFolders::OnCmdExplore(void)
{
UTREEITEM *item;
UEventSendMessage(GetWidID(), EV_TREE_GETSEL, kUMainWidget, &item);
ASSERT(item != 0L);
UStr path;
RetrievePath(item, path);
#ifdef WIN32
HINSTANCE hInst = ShellExecute(*AfxGetMainWnd(), "explore", path,
0L, 0L, SW_SHOWDEFAULT);
if((long)hInst < 32)
{
cvs_err("Unable to explore '%s' (error %d)\n", (const char *)path, GetLastError());
}
#endif
#ifdef qUnix
CvsArgs args(false);
args.add(gCvsPrefs.Browser());
args.add(path);
UCvsApp::gApp->Execute(args.Argc(), args.Argv());
#endif
return 0;
}
int UCvsFolders::OnCmdReload(void)
{
ResetView(true);
return 0;
}
int UCvsFolders::OnCmdIgnore(void)
{
gFileViewIgnore = !(bool)gFileViewIgnore;
ResetView(true, true);
return 0;
}
int UCvsFolders::OnCmdCheckout(void)
{
CvsCmdCheckoutModule();
return 0;
}
int UCvsFolders::OnCmdImport(void)
{
CvsCmdImportModule();
return 0;
}
void UCvsFolders::OnCmdUIAdd(UCmdUI *pCmdUI)
{
OnUpdateGeneric(pCmdUI, false);
}
void UCvsFolders::OnCmdUIExplore(UCmdUI *pCmdUI)
{
if(DisableGeneric())
{
pCmdUI->Enable(false);
return;
}
UTREEITEM selItem;
UEventSendMessage(GetWidID(), EV_TREE_GETSEL, kUMainWidget, &selItem);
pCmdUI->Enable(selItem != 0L);
}
void UCvsFolders::OnCmdUIReload(UCmdUI *pCmdUI)
{
UCvsApp *app = UCvsApp::gApp;
pCmdUI->Enable(!app->IsCvsRunning());
}
void UCvsFolders::OnCmdUIIgnore(UCmdUI *pCmdUI)
{
pCmdUI->Enable(!DisableGeneric());
pCmdUI->Check(gFileViewIgnore);
}
void UCvsFolders::OnCmdUICheckout(UCmdUI *pCmdUI)
{
UCvsApp *app = UCvsApp::gApp;
pCmdUI->Enable(!app->IsCvsRunning() && !gCvsPrefs.empty());
}
void UCvsFolders::OnCmdUIImport(UCmdUI *pCmdUI)
{
UCvsApp *app = UCvsApp::gApp;
pCmdUI->Enable(!app->IsCvsRunning() && !gCvsPrefs.empty());
}
void UCvsFolders::OnCmdUIMacrosSel(int cmd, UCmdUI *pCmdUI)
{
if(DisableGeneric())
{
pCmdUI->Enable(false);
return;
}
UTREEITEM selItem;
UEventSendMessage(GetWidID(), EV_TREE_GETSEL, kUMainWidget, &selItem);
pCmdUI->Enable(selItem != 0L && CTcl_Interp::IsAvail());
}
int UCvsFolders::OnCmdMacrosSel(int cmd)
{
CTcl_Interp interp;
CMacroEntry & entry = gMacrosSel.entries[cmd - cmdSELMACRO];
CStr path = entry.path;
CTcl_Interp::Unixfy(path);
UTREEITEM selItem;
UEventSendMessage(GetWidID(), EV_TREE_GETSEL, kUMainWidget, &selItem);
CStr selPath;
RetrievePath(selItem, selPath);
CStr uppath, folder;
SplitPath(selPath, uppath, folder);
UTREE_INFO query;
query.item = selItem;
UEventSendMessage(GetWidID(), EV_TREE_GETINFO, kUMainWidget, &query);
bool deleteData = false;
EntnodeData *data = (EntnodeData *)query.data;
if(data == 0L)
{
deleteData = true;
EntnodePath *apath = new EntnodePath(uppath);
data = new EntnodeFolder(folder, apath);
apath->UnRef();
}
TclBrowserReset();
TclBrowserAppend(uppath, data);
interp.DoScriptVar("source \"%s\"", (const char *)path);
if(deleteData)
data->UnRef();
return 0;
}
/*
** 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 1, 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.
*/
/*
* Author : Alexandre Parenteau <[EMAIL PROTECTED]> --- February 2000
*/
/*
*
*/
#include "stdafx.h"
#if qGTK
# include <gtk/gtk.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
#include <string>
#include "UCvsFiles.h"
#include "UCvsDialogs.h"
#include "UCvsFolders.h"
#include "UCvsCommands.h"
#include "UCvsFrame.h"
#include "UCvsApp.h"
#include "CvsPrefs.h"
#include "FileTraversal.h"
#include "MultiFiles.h"
#include "CvsCommands.h"
#include "CvsArgs.h"
#include "TclGlue.h"
#include "AppConsole.h"
#include "MoveToTrash.h"
#include "MacrosSetup.h"
#ifndef NAMESPACE
# if defined(_MSC_VER) || defined(__MWERKS__) || (__GNUC__ > 2)
# define NAMESPACE(w) w::
# else
# define NAMESPACE(w) ::
# endif
#endif
UIMPLEMENT_DYNAMIC(UCvsFiles, UWidget)
UBEGIN_MESSAGE_MAP(UCvsFiles, UWidget)
ON_UUPDATECMD(cmdUPDATE, UCvsFiles::OnCmdUIUpdate)
ON_UUPDATECMD(cmdCOMMIT, UCvsFiles::OnCmdUIUpdate)
ON_UUPDATECMD(cmdDIFF, UCvsFiles::OnCmdUIUpdate)
ON_UUPDATECMD(cmdEDIT, UCvsFiles::OnCmdUIUpdate)
ON_UUPDATECMD(cmdEDITORS, UCvsFiles::OnCmdUIUpdate)
ON_UUPDATECMD(cmdLOCKF, UCvsFiles::OnCmdUIUpdate)
ON_UUPDATECMD(cmdLOG, UCvsFiles::OnCmdUIUpdate)
ON_UUPDATECMD(cmdTAGNEW, UCvsFiles::OnCmdUIUpdate)
ON_UUPDATECMD(cmdTAGDELETE, UCvsFiles::OnCmdUIUpdate)
ON_UUPDATECMD(cmdTAGBRANCH, UCvsFiles::OnCmdUIUpdate)
ON_UUPDATECMD(cmdSTATUS, UCvsFiles::OnCmdUIUpdate)
ON_UUPDATECMD(cmdUNEDIT, UCvsFiles::OnCmdUIUpdate)
ON_UUPDATECMD(cmdQUERYUPDATE, UCvsFiles::OnCmdUIUpdate)
ON_UUPDATECMD(cmdUNLOCKF, UCvsFiles::OnCmdUIUpdate)
ON_UUPDATECMD(cmdWATCHERS, UCvsFiles::OnCmdUIUpdate)
ON_UUPDATECMD(cmdWATCHON, UCvsFiles::OnCmdUIUpdate)
ON_UUPDATECMD(cmdWATCHOFF, UCvsFiles::OnCmdUIUpdate)
ON_UUPDATECMD(cmdADD, UCvsFiles::OnCmdUIAdd)
ON_UUPDATECMD(cmdADDB, UCvsFiles::OnCmdUIAddB)
ON_UUPDATECMD(cmdRELEASE, UCvsFiles::OnCmdUIRelease)
ON_UUPDATECMD(cmdRMV, UCvsFiles::OnCmdUIRmv)
ON_UUPDATECMD(cmdGRAPH, UCvsFiles::OnCmdUIGraph)
ON_UUPDATECMD(cmdEDITSELDEF, UCvsFiles::OnCmdUIEditseldef)
ON_UUPDATECMD(cmdRELOAD, UCvsFiles::OnCmdUIReload)
ON_UUPDATECMD(cmdUPFOLDER, UCvsFiles::OnCmdUIUpone)
ON_UUPDATECMD(cmdTRASH, UCvsFiles::OnCmdUITrash)
ON_UUPDATECMD(cmdEXPLORE, UCvsFiles::OnCmdUIExplore)
ON_UUPDATECMD(cmdIGNORE, UCvsFiles::OnCmdUIIgnore)
ON_UUPDATECMD(cmdEDITSEL, UCvsFiles::OnCmdUITrash)
ON_UUPDATECMD_RANGE(cmdSELMACRO, cmdSELMACROEND, UCvsFiles::OnCmdUIMacroSel)
ON_UCOMMAND(cmdUPDATE, UCvsFiles::OnCmdUpdate)
ON_UCOMMAND(cmdADD, UCvsFiles::OnCmdAdd)
ON_UCOMMAND(cmdADDB, UCvsFiles::OnCmdAddb)
ON_UCOMMAND(cmdCOMMIT, UCvsFiles::OnCmdCommit)
ON_UCOMMAND(cmdRMV, UCvsFiles::OnCmdRmv)
ON_UCOMMAND(cmdQUERYUPDATE, UCvsFiles::OnCmdQueryUpdate)
ON_UCOMMAND(cmdRELOAD, UCvsFiles::OnCmdReload)
ON_UCOMMAND(cmdUPFOLDER, UCvsFiles::OnCmdUpone)
ON_UCOMMAND(cmdTRASH, UCvsFiles::OnCmdTrash)
ON_UCOMMAND(cmdDIFF, UCvsFiles::OnCmdDiff)
ON_UCOMMAND(cmdLOG, UCvsFiles::OnCmdLog)
ON_UCOMMAND(cmdGRAPH, UCvsFiles::OnCmdGraph)
ON_UCOMMAND(cmdSTATUS, UCvsFiles::OnCmdStatus)
ON_UCOMMAND(cmdLOCKF, UCvsFiles::OnCmdLock)
ON_UCOMMAND(cmdUNLOCKF, UCvsFiles::OnCmdUnlock)
ON_UCOMMAND(cmdWATCHON, UCvsFiles::OnCmdWatchOn)
ON_UCOMMAND(cmdWATCHOFF, UCvsFiles::OnCmdWatchOff)
ON_UCOMMAND(cmdEDIT, UCvsFiles::OnCmdEdit)
ON_UCOMMAND(cmdUNEDIT, UCvsFiles::OnCmdUnedit)
ON_UCOMMAND(cmdWATCHERS, UCvsFiles::OnCmdWatchers)
ON_UCOMMAND(cmdEDITORS, UCvsFiles::OnCmdEditors)
ON_UCOMMAND(cmdRELEASE, UCvsFiles::OnCmdRelease)
ON_UCOMMAND(cmdTAGNEW, UCvsFiles::OnCmdTagNew)
ON_UCOMMAND(cmdTAGDELETE, UCvsFiles::OnCmdTagDelete)
ON_UCOMMAND(cmdTAGBRANCH, UCvsFiles::OnCmdTagBranch)
ON_UCOMMAND(cmdEXPLORE, UCvsFiles::OnCmdExplore)
ON_UCOMMAND(cmdIGNORE, UCvsFiles::OnCmdIgnore)
ON_UCOMMAND(cmdEDITSEL, UCvsFiles::OnCmdEditsel)
ON_UCOMMAND(cmdEDITSELDEF, UCvsFiles::OnCmdEditseldef)
ON_UCOMMAND_RANGE(cmdSELMACRO, cmdSELMACROEND, UCvsFiles::OnMacroSel)
ON_LIST_DBLCLICK(kUMainWidget, UCvsFiles::OnDblClick)
ON_LIST_SELCOLUMN(kUMainWidget, UCvsFiles::OnSelColumn)
ON_UDESTROY(UCvsFiles)
ON_UCREATE(UCvsFiles)
UEND_MESSAGE_MAP()
#if 0
ON_UUPDATECMD(cmdSMALLICONS, OnCmdUISmallIcons)
ON_UUPDATECMD(cmdFULLLIST, OnCmdUIList)
ON_UUPDATECMD(cmdROWDETAILS, OnCmdUIFullRowDetails)
ON_COMMAND(ID_VIEW_SMALLICONS, OnViewSmallIcons)
ON_COMMAND(ID_VIEW_FULLLIST, OnViewList)
ON_COMMAND(ID_VIEW_ROWDETAILS, OnViewFullRowDetails)
ON_WM_LBUTTONDOWN()
ON_WM_RBUTTONDOWN()
ON_NOTIFY_REFLECT(LVN_COLUMNCLICK, OnColumnclick)
ON_NOTIFY_REFLECT(LVN_KEYDOWN, OnKeydown)
ON_WM_TIMER()
//}}AFX_MSG_MAP
ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
#endif
static void *sFileIconTextIcon;
static void *sFileIconBinaryIcon;
static void *sFileIconUnknownIcon;
static void *sFileIconAddedIcon;
static void *sFileIconConflictIcon;
static void *sFileIconMissIcon;
static void *sFolderIconIcon;
static void *sFolderIconUnknownIcon;
static void *sFolderIconMissIcon;
static void *sFileIconTextModIcon;
static void *sFileIconBinaryModIcon;
static void *sFileIconIgnoredIcon;
static void *sFolderIconIgnoredIcon;
static void *sFileIconRemovedIcon;
/*
kFileIconText,cvsfile
kFileIconBinary,binfile
kFileIconUnknown,unkfile
kFileIconAdded,addfile
kFileIconConflict,conflict
kFileIconMiss,missfile
kFolderIcon,folder
kFolderIconUnknown,foldunk
kFolderIconMiss,foldmiss
kFileIconTextMod,modfile
kFileIconBinaryMod,modbin
kFileIconIgnored,ignfile
kFolderIconIgnored,foldign
kFileIconRemoved,delfile
*/
enum
{
kFileIconText = 0,
kFileIconBinary,
kFileIconUnknown,
kFileIconAdded,
kFileIconConflict,
kFileIconMiss,
kFolderIcon,
kFolderIconUnknown,
kFolderIconMiss,
kFileIconTextMod,
kFileIconBinaryMod,
kFileIconIgnored,
kFolderIconIgnored,
kFileIconRemoved
};
#define NUM_COLUMNS 7
static char *_gszColumnLabel[NUM_COLUMNS] =
{
"Name", "Rev.", "Option", "Status", "Tag", "Date", "Conflict"
};
static int _gnColumnWidth[NUM_COLUMNS] =
{
150, 50, 50, 100, 150, 150, 150
};
static const char * month_names[12] =
{
"Jan", "Feb", "Mar", "Apr",
"May", "Jun", "Jul", "Aug",
"Sep", "Oct", "Nov", "Dec"
};
CPersistentBool gFileViewIgnore("P_FileViewIgnore", true);
CPersistentInt gFileViewSort("P_FileViewSort", EntnodeData::kName);
CPersistentBool gFileViewSortAsc("P_FileViewSortAsc", true);
class TViewFill : public TraversalReport
{
public:
UCvsFiles *m_listCtrl;
CSortList<ENTNODE> & m_entries;
NAMESPACE(std) vector<CStr> m_ignlist;
TViewFill(UCvsFiles *listCtrl, CSortList<ENTNODE> & entries) :
m_listCtrl(listCtrl), m_entries(entries) {}
virtual ~TViewFill() {}
virtual kTraversal EnterDirectory(const char *fullpath, const char *dirname, const FSSpec * macspec)
{
Entries_Open (m_entries, fullpath);
BuildIgnoredList(m_ignlist, fullpath);
return kContinueTraversal;
}
virtual kTraversal ExitDirectory(const char *fullpath)
{
m_ignlist.erase(m_ignlist.begin(), m_ignlist.end());
return kContinueTraversal;
}
virtual kTraversal OnError(const char *err, int errcode)
{
return kTraversalError;
}
virtual kTraversal OnIdle(const char *fullpath)
{
return kContinueTraversal;
}
virtual kTraversal OnDirectory(const char *fullpath,
const char *fullname,
const char *name,
const struct stat & dir, const FSSpec * macspec)
{
#if qUnix
if(strcmp(name, "CVS") == 0)
#else
if(stricmp(name, "CVS") == 0)
#endif
return kSkipFile;
EntnodeData *data = Entries_SetVisited(fullpath, m_entries, name, dir, true, &m_ignlist);
if(!(bool)gFileViewIgnore && data->IsIgnored())
return kSkipFile;
// get the tag
CStr subCVS;
CStr tagName;
subCVS = fullname;
if(!subCVS.endsWith(kPathDelimiter))
subCVS << kPathDelimiter;
subCVS << "CVS";
if(chdir(subCVS) == 0)
Tag_Open(tagName, subCVS);
if(chdir(fullpath) != 0)
return kTraversalError;
int rownum;
UEventSendMessage(m_listCtrl->GetWidID(), EV_LIST_NEWROW, kUMainWidget, &rownum);
UEventSendMessage(m_listCtrl->GetWidID(), EV_LIST_ROWSETDATA, UMAKEINT(kUMainWidget, rownum), data);
ULIST_INSERT entry;
entry.row = rownum;
entry.col = 0;
entry.title = name;
entry.icon = UCvsFiles::GetImageForEntry(data);
UEventSendMessage(m_listCtrl->GetWidID(), EV_LIST_INSERT, kUMainWidget, &entry);
entry.icon = 0L;
// set item text for additional columns
for(int j = 1; j < NUM_COLUMNS; j++)
{
const char *info = (*data)[j];
if(info != 0L)
{
entry.col = j;
entry.title = info;
UEventSendMessage(m_listCtrl->GetWidID(), EV_LIST_INSERT, kUMainWidget, &entry);
}
}
entry.col = EntnodeData::kStatus;
entry.title = data->GetDesc();
UEventSendMessage(m_listCtrl->GetWidID(), EV_LIST_INSERT, kUMainWidget, &entry);
entry.col = EntnodeFile::kTag;
entry.title = tagName.empty() ? "" : (const char *)tagName;
UEventSendMessage(m_listCtrl->GetWidID(), EV_LIST_INSERT, kUMainWidget, &entry);
return kSkipFile;
}
virtual kTraversal OnAlias(const char *fullpath,
const char *fullname,
const char *name,
const struct stat & dir, const FSSpec * macspec)
{
return OnFile(fullpath, fullname, name, dir, macspec);
}
virtual kTraversal OnFile(const char *fullpath,
const char *fullname,
const char *name,
const struct stat & dir, const FSSpec * macspec)
{
EntnodeData *data = Entries_SetVisited(fullpath, m_entries, name, dir, false, &m_ignlist);
if(!(bool)gFileViewIgnore && data->IsIgnored())
return kContinueTraversal;
int rownum;
UEventSendMessage(m_listCtrl->GetWidID(), EV_LIST_NEWROW, kUMainWidget, &rownum);
UEventSendMessage(m_listCtrl->GetWidID(), EV_LIST_ROWSETDATA, UMAKEINT(kUMainWidget, rownum), data);
ULIST_INSERT entry;
entry.row = rownum;
entry.col = 0;
entry.title = name;
entry.icon = UCvsFiles::GetImageForEntry(data);
UEventSendMessage(m_listCtrl->GetWidID(), EV_LIST_INSERT, kUMainWidget, &entry);
entry.icon = 0L;
#if 0 /* TODO */
lvi.state = data->IsLocked() ?
INDEXTOSTATEIMAGEMASK(2) : INDEXTOSTATEIMAGEMASK(1);
#endif
// set item text for additional columns
for(int j = 1; j < NUM_COLUMNS; j++)
{
const char *info = (*data)[j];
if(info != 0L)
{
entry.col = j;
entry.title = info;
UEventSendMessage(m_listCtrl->GetWidID(), EV_LIST_INSERT, kUMainWidget, &entry);
}
}
entry.col = EntnodeData::kStatus;
entry.title = data->GetDesc();
UEventSendMessage(m_listCtrl->GetWidID(), EV_LIST_INSERT, kUMainWidget, &entry);
return kContinueTraversal;
}
};
UCvsFiles::UCvsFiles() : UWidget(kUCvsFilesID), m_entries(200, ENTNODE::Compare), m_entriesMod(0), m_entriesLogMod(0)
{
m_sort = (int)gFileViewSort;
m_ascendant = (bool)gFileViewSortAsc;
}
UCvsFiles::~UCvsFiles()
{
gFileViewSort = m_sort;
gFileViewSortAsc = m_ascendant;
}
void UCvsFiles::OnDestroy(void)
{
delete this;
}
void UCvsFiles::OnCreate(void)
{
if(sFileIconTextIcon == 0L)
{
sFileIconTextIcon = UCreate_pixmap(this, "cvsfile.xpm");
sFileIconBinaryIcon = UCreate_pixmap(this, "binfile.xpm");
sFileIconUnknownIcon = UCreate_pixmap(this, "unkfile.xpm");
sFileIconAddedIcon = UCreate_pixmap(this, "addfile.xpm");
sFileIconConflictIcon = UCreate_pixmap(this, "conflict.xpm");
sFileIconMissIcon = UCreate_pixmap(this, "missfile.xpm");
sFolderIconIcon = UCreate_pixmap(this, "folder.xpm");
sFolderIconUnknownIcon = UCreate_pixmap(this, "foldunk.xpm");
sFolderIconMissIcon = UCreate_pixmap(this, "foldmiss.xpm");
sFileIconTextModIcon = UCreate_pixmap(this, "modfile.xpm");
sFileIconBinaryModIcon = UCreate_pixmap(this, "modbin.xpm");
sFileIconIgnoredIcon = UCreate_pixmap(this, "ignfile.xpm");
sFolderIconIgnoredIcon = UCreate_pixmap(this, "foldign.xpm");
sFileIconRemovedIcon = UCreate_pixmap(this, "delfile.xpm");
}
UEventSendMessage(GetWidID(), EV_LIST_SETFEEDBACK, UMAKEINT(kUMainWidget, 0), 0L);
UEventSendMessage(GetWidID(), EV_LIST_ADDCOLUMNS, UMAKEINT(kUMainWidget, NUM_COLUMNS), 0L);
for(int i = 0; i < NUM_COLUMNS; i++)
{
UEventSendMessage(GetWidID(), EV_LIST_SETCOLTITLE, UMAKEINT(kUMainWidget, i), _gszColumnLabel[i]);
UEventSendMessage(GetWidID(), EV_LIST_SETCOLWIDTH, UMAKEINT(kUMainWidget, i), (void *)_gnColumnWidth[i]);
}
UEventSendMessage(GetWidID(), EV_LIST_SETFEEDBACK, UMAKEINT(kUMainWidget, 1), 0L);
}
void UCvsFiles::ResetView(const char *path, bool notifyBrowser)
{
m_path = path;
ResetView(true);
UStr title(UCvsApp::gApp->GetAppName());
title << ": ";
title << m_path;
UEventSendMessage(kUCvsFrameID, EV_SETTEXT, kUMainWidget, (void *)(const char *)title);
if(notifyBrowser)
{
// notify the tree
UCvsApp::gApp->GetBrowserView()->StepToLocation(path);
}
}
void UCvsFiles::GetEntriesModTime(time_t & newEntriesMod, time_t & newEntriesLogMod)
{
newEntriesMod = 0;
newEntriesLogMod = 0;
if(chdir(m_path) != 0)
return;
if(chdir("CVS") != 0)
return;
struct stat sb;
if (stat("Entries", &sb) != -1)
newEntriesMod = sb.st_mtime;
if (stat("Entries.log", &sb) != -1)
newEntriesLogMod = sb.st_mtime;
chdir(m_path);
}
int UCvsFiles::Search(const char *title)
{
int row = -1;
while((row = UEventSendMessage(GetWidID(), EV_LIST_GETNEXT,
UMAKEINT(kUMainWidget, row), 0L)) != -1)
{
ULIST_INFO info;
info.col = 0;
info.row = row;
UEventSendMessage(GetWidID(), EV_LIST_GETINFO, kUMainWidget, &info);
if(info.title == 0L)
continue;
#if qUnix
if(strcmp(title, info.title) == 0)
#else
if(stricmp(title, info.title) == 0)
#endif
return row;
}
return -1;
}
void UCvsFiles::ResetView(bool forceReload, bool notifyBrowser)
{
UWaitCursor wait;
static bool sSemaphore = false;
USemaphore policeman(sSemaphore);
if(policeman.IsEnteredTwice())
return;
// - check if we really need to reload (forceReload == false)
// - wait a bit for the watcher in order to let him tell us
// if something was modified.
time_t newEntriesMod;
time_t newEntriesLogMod;
GetEntriesModTime(newEntriesMod, newEntriesLogMod);
if(!forceReload)
{
if(m_entriesMod == newEntriesMod && m_entriesLogMod == newEntriesLogMod)
return;
}
// reset all the watchers
m_entriesMod = newEntriesMod;
m_entriesLogMod = newEntriesLogMod;
// get the selection to later try to restore it
CvsArgs selection(false);
int nItem = -1;
while((nItem = UEventSendMessage(GetWidID(), EV_LIST_GETNEXTSEL,
UMAKEINT(kUMainWidget, nItem), 0L)) != -1)
{
EntnodeData *data;
UEventSendMessage(GetWidID(), EV_LIST_ROWGETDATA, UMAKEINT(kUMainWidget, nItem), &data);
selection.add((*data)[EntnodeData::kName]);
}
UEventSendMessage(GetWidID(), EV_LIST_RESETALL, kUMainWidget, 0L);
// refetch all items
TViewFill traverse(this, m_entries);
/*kTraversal res = */FileTraverse(m_path, traverse);
// add the missing files
Entries_SetMissing(m_entries);
int numEntries = m_entries.NumOfElements();
for(int i = 0; i < numEntries; i++)
{
const ENTNODE & theNode = m_entries.Get(i);
EntnodeData *data = ((ENTNODE *)&theNode)->Data();
if(!data->IsMissing())
continue;
int rownum;
UEventSendMessage(GetWidID(), EV_LIST_NEWROW, kUMainWidget, &rownum);
UEventSendMessage(GetWidID(), EV_LIST_ROWSETDATA, UMAKEINT(kUMainWidget, rownum), data);
ULIST_INSERT entry;
entry.row = rownum;
entry.col = 0;
entry.title = (*data)[EntnodeData::kName];
entry.icon = UCvsFiles::GetImageForEntry(data);
UEventSendMessage(GetWidID(), EV_LIST_INSERT, kUMainWidget, &entry);
entry.icon = 0L;
// set item text for additional columns
for(int j = 1; j < NUM_COLUMNS; j++)
{
const char *info = (*data)[j];
if(info != 0L)
{
entry.col = j;
entry.title = info;
UEventSendMessage(GetWidID(), EV_LIST_INSERT, kUMainWidget, &entry);
}
}
entry.col = EntnodeData::kStatus;
entry.title = data->GetDesc();
UEventSendMessage(GetWidID(), EV_LIST_INSERT, kUMainWidget, &entry);
}
Resort();
// now restore the selection
int argc = selection.Argc(), c;
char * const *argv = selection.Argv();
for(c = 0; c < argc; c++)
{
int row = Search(argv[c]);
if(row != -1)
UEventSendMessage(GetWidID(), EV_LIST_ADDSEL, UMAKEINT(kUMainWidget, row), 0L);
}
if(notifyBrowser)
{
// notify the tree
UCvsApp::gApp->GetBrowserView()->ResetView(forceReload);
}
}
void *UCvsFiles::GetImageForEntry(EntnodeData *data)
{
int result;
void *resIcon = 0L;
if(data->GetType() == ENT_FILE)
{
const char *info = 0L;
if(data->IsIgnored())
{
result = kFileIconIgnored;
}
else if(data->IsUnknown())
{
result = kFileIconUnknown;
}
else if(data->IsMissing())
{
result = data->IsRemoved() ? kFileIconRemoved : kFileIconMiss;
}
else if((*data)[EntnodeFile::kConflict] != 0L)
{
result = kFileIconConflict;
}
else if(data->IsRemoved())
{
result = kFileIconRemoved;
}
else if((info = (*data)[EntnodeFile::kOption]) != 0L && strcmp(info, "-kb") == 0)
{
result = data->IsUnmodified() ? kFileIconBinary : kFileIconBinaryMod;
}
else
{
result = data->IsUnmodified() ? kFileIconText : kFileIconTextMod;
}
}
else
{
if(data->IsIgnored())
{
result = kFolderIconIgnored;
}
else if(data->IsUnknown())
{
result = kFolderIconUnknown;
}
else if(data->IsMissing())
{
result = kFolderIconMiss;
}
else
{
result = kFolderIcon;
}
}
#if qGTK
void *pixmap = 0L;
switch(result)
{
case kFileIconText:
pixmap = sFileIconTextIcon;
break;
case kFileIconBinary:
pixmap = sFileIconBinaryIcon;
break;
case kFileIconUnknown:
pixmap = sFileIconUnknownIcon;
break;
case kFileIconAdded:
pixmap = sFileIconAddedIcon;
break;
case kFileIconConflict:
pixmap = sFileIconConflictIcon;
break;
case kFileIconMiss:
pixmap = sFileIconMissIcon;
break;
case kFolderIcon:
pixmap = sFolderIconIcon;
break;
case kFolderIconUnknown:
pixmap = sFolderIconUnknownIcon;
break;
case kFolderIconMiss:
pixmap = sFolderIconMissIcon;
break;
case kFileIconTextMod:
pixmap = sFileIconTextModIcon;
break;
case kFileIconBinaryMod:
pixmap = sFileIconBinaryModIcon;
break;
case kFileIconIgnored:
pixmap = sFileIconIgnoredIcon;
break;
case kFolderIconIgnored:
pixmap = sFolderIconIgnoredIcon;
break;
case kFileIconRemoved:
pixmap = sFileIconRemovedIcon;
break;
}
if(pixmap != 0L)
{
resIcon = gtk_pixmap_new (GTK_PIXMAP(pixmap)->pixmap, GTK_PIXMAP(pixmap)->mask);
}
#endif
return resIcon;
}
int UCvsFiles::OnCmdUpdate(void)
{
int nItem = -1;
MultiFiles mf;
mf.newdir(m_path);
// first add the folders
while((nItem = UEventSendMessage(GetWidID(), EV_LIST_GETNEXTSEL, UMAKEINT(kUMainWidget, nItem), 0L)) != -1)
{
EntnodeData *data;
UEventSendMessage(GetWidID(), EV_LIST_ROWGETDATA, UMAKEINT(kUMainWidget, nItem), &data);
if(data->GetType() == ENT_SUBDIR)
{
CStr fullpath;
fullpath = m_path;
if(!fullpath.endsWith(kPathDelimiter))
fullpath << kPathDelimiter;
fullpath << (*data)[EntnodeData::kName];
CvsCmdUpdateFolder(fullpath);
}
else
{
mf.newfile((*data)[EntnodeData::kName], 0, (*data)[EntnodeFile::kVN]);
}
}
if(mf.NumFiles() != 0)
{
CvsCmdUpdateFiles(&mf);
}
return 0;
}
bool UCvsFiles::DisableGeneric()
{
return UEventSendMessage(GetWidID(), EV_LIST_GETNEXTSEL, UMAKEINT(kUMainWidget, -1), 0L) == -1 ||
UCvsApp::gApp->IsCvsRunning() || gCvsPrefs.empty() || !HasFocus();
}
void UCvsFiles::OnCmdUIUpdate(UCmdUI *pCmdUI)
{
if(DisableGeneric())
{
pCmdUI->Enable(false);
return;
}
int nItem = -1;
bool res = true;
int numFiles = 0;
int numFolders = 0;
while((nItem = UEventSendMessage(GetWidID(), EV_LIST_GETNEXTSEL, UMAKEINT(kUMainWidget, nItem), 0L)) != -1)
{
EntnodeData *data;
UEventSendMessage(GetWidID(), EV_LIST_ROWGETDATA, UMAKEINT(kUMainWidget, nItem), &data);
if(data->IsUnknown())
{
res = false;
break;
}
if(data->GetType() == ENT_FILE)
numFiles++;
else
numFolders++;
if((numFiles != 0) && (numFolders != 0))
{
res = false;
break;
}
}
pCmdUI->Enable(res);
}
void UCvsFiles::OnCmdUIAdd(UCmdUI *pCmdUI)
{
if(DisableGeneric())
{
pCmdUI->Enable(false);
return;
}
int nItem = -1;
bool res = true;
int numFiles = 0;
int numFolders = 0;
while((nItem = UEventSendMessage(GetWidID(), EV_LIST_GETNEXTSEL, UMAKEINT(kUMainWidget, nItem), 0L)) != -1)
{
EntnodeData *data;
UEventSendMessage(GetWidID(), EV_LIST_ROWGETDATA, UMAKEINT(kUMainWidget, nItem), &data);
if(!(data->IsUnknown() || (data->IsRemoved() && data->IsMissing())))
{
res = false;
break;
}
if(data->GetType() == ENT_FILE)
{
numFiles++;
}
else
numFolders++;
if((numFiles != 0) && (numFolders != 0))
{
res = false;
break;
}
}
pCmdUI->Enable(res);
}
void UCvsFiles::OnCmdUIAddB(UCmdUI *pCmdUI)
{
if(DisableGeneric())
{
pCmdUI->Enable(false);
return;
}
int nItem = -1;
bool res = true;
while((nItem = UEventSendMessage(GetWidID(), EV_LIST_GETNEXTSEL, UMAKEINT(kUMainWidget, nItem), 0L)) != -1)
{
EntnodeData *data;
UEventSendMessage(GetWidID(), EV_LIST_ROWGETDATA, UMAKEINT(kUMainWidget, nItem), &data);
if(data->GetType() != ENT_FILE)
{
res = false;
break;
}
if(!(data->IsUnknown() || (data->IsRemoved() && data->IsMissing())))
{
res = false;
break;
}
}
pCmdUI->Enable(res);
}
void UCvsFiles::OnCmdUIRelease(UCmdUI *pCmdUI)
{
if(DisableGeneric())
{
pCmdUI->Enable(false);
return;
}
int nItem = -1;
bool res = true;
int numFolders = 0;
while((nItem = UEventSendMessage(GetWidID(), EV_LIST_GETNEXTSEL, UMAKEINT(kUMainWidget, nItem), 0L)) != -1)
{
EntnodeData *data;
UEventSendMessage(GetWidID(), EV_LIST_ROWGETDATA, UMAKEINT(kUMainWidget, nItem), &data);
if(data->IsUnknown() || data->GetType() != ENT_SUBDIR)
{
res = false;
break;
}
numFolders++;
if(numFolders > 1)
{
res = false;
break;
}
}
pCmdUI->Enable(res);
}
void UCvsFiles::OnCmdUIRmv(UCmdUI *pCmdUI)
{
if(DisableGeneric())
{
pCmdUI->Enable(false);
return;
}
int nItem = -1;
bool res = true;
while((nItem = UEventSendMessage(GetWidID(), EV_LIST_GETNEXTSEL, UMAKEINT(kUMainWidget, nItem), 0L)) != -1)
{
EntnodeData *data;
UEventSendMessage(GetWidID(), EV_LIST_ROWGETDATA, UMAKEINT(kUMainWidget, nItem), &data);
if(data->IsUnknown() || data->IsRemoved() || data->GetType() == ENT_SUBDIR)
{
res = false;
break;
}
}
pCmdUI->Enable(res);
}
void UCvsFiles::OnCmdUIGraph(UCmdUI *pCmdUI)
{
if(DisableGeneric())
{
pCmdUI->Enable(false);
return;
}
int nItem = -1;
bool res = true;
while((nItem = UEventSendMessage(GetWidID(), EV_LIST_GETNEXTSEL, UMAKEINT(kUMainWidget, nItem), 0L)) != -1)
{
EntnodeData *data;
UEventSendMessage(GetWidID(), EV_LIST_ROWGETDATA, UMAKEINT(kUMainWidget, nItem), &data);
if(data->IsUnknown() || data->GetType() == ENT_SUBDIR)
{
res = false;
break;
}
}
pCmdUI->Enable(res);
}
void UCvsFiles::OnCmdUIEditseldef(UCmdUI *pCmdUI)
{
if(DisableGeneric())
{
pCmdUI->Enable(false);
return;
}
int nItem = -1;
bool res = true;
while((nItem = UEventSendMessage(GetWidID(), EV_LIST_GETNEXTSEL, UMAKEINT(kUMainWidget, nItem), 0L)) != -1)
{
EntnodeData *data;
UEventSendMessage(GetWidID(), EV_LIST_ROWGETDATA, UMAKEINT(kUMainWidget, nItem), &data);
if(data->GetType() == ENT_SUBDIR || data->IsMissing())
{
res = false;
break;
}
}
pCmdUI->Enable(res);
if(gCvsPrefs.Viewer() != 0L)
{
CStr title("Edit with ");
title << gCvsPrefs.Viewer();
pCmdUI->SetText(title);
}
}
void UCvsFiles::OnCmdUIReload(UCmdUI *pCmdUI)
{
pCmdUI->Enable(!DisableGeneric());
}
void UCvsFiles::OnCmdUIUpone(UCmdUI *pCmdUI)
{
pCmdUI->Enable(!DisableGeneric());
}
void UCvsFiles::OnCmdUITrash(UCmdUI *pCmdUI)
{
if(DisableGeneric())
{
pCmdUI->Enable(false);
return;
}
int nItem = -1;
bool res = true;
while((nItem = UEventSendMessage(GetWidID(), EV_LIST_GETNEXTSEL, UMAKEINT(kUMainWidget, nItem), 0L)) != -1)
{
EntnodeData *data;
UEventSendMessage(GetWidID(), EV_LIST_ROWGETDATA, UMAKEINT(kUMainWidget, nItem), &data);
if(data->GetType() == ENT_SUBDIR || data->IsMissing())
{
res = false;
break;
}
}
pCmdUI->Enable(res);
}
void UCvsFiles::OnCmdUIExplore(UCmdUI *pCmdUI)
{
if(DisableGeneric())
{
pCmdUI->Enable(false);
return;
}
int nItem = -1;
bool res = true;
int numItem = 0;
while((nItem = UEventSendMessage(GetWidID(), EV_LIST_GETNEXTSEL, UMAKEINT(kUMainWidget, nItem), 0L)) != -1)
{
EntnodeData *data;
UEventSendMessage(GetWidID(), EV_LIST_ROWGETDATA, UMAKEINT(kUMainWidget, nItem), &data);
if(data->IsMissing() || ++numItem > 1)
{
res = false;
break;
}
}
pCmdUI->Enable(res);
}
void UCvsFiles::OnCmdUIIgnore(UCmdUI *pCmdUI)
{
pCmdUI->Enable(!DisableGeneric());
pCmdUI->Check(gFileViewIgnore);
}
void UCvsFiles::OnCmdUIMacroSel(int cmd, UCmdUI *pCmdUI)
{
if(DisableGeneric())
{
pCmdUI->Enable(false);
return;
}
int nItem = UEventSendMessage(GetWidID(), EV_LIST_GETNEXTSEL, UMAKEINT(kUMainWidget, -1), 0L);
pCmdUI->Enable(nItem != -1 && CTcl_Interp::IsAvail());
}
int UCvsFiles::OnCmdAdd(void)
{
int nItem = -1;
MultiFiles mf;
mf.newdir(m_path);
// first add the folders
while((nItem = UEventSendMessage(GetWidID(), EV_LIST_GETNEXTSEL, UMAKEINT(kUMainWidget, nItem), 0L)) != -1)
{
EntnodeData *data;
UEventSendMessage(GetWidID(), EV_LIST_ROWGETDATA, UMAKEINT(kUMainWidget, nItem), &data);
if(data->GetType() == ENT_SUBDIR)
{
CStr fullpath;
fullpath = m_path;
if(!fullpath.endsWith(kPathDelimiter))
fullpath << kPathDelimiter;
fullpath << (*data)[EntnodeData::kName];
CvsCmdAddFolder(fullpath);
}
else
{
mf.newfile((*data)[EntnodeData::kName], 0, (*data)[EntnodeFile::kVN]);
}
}
if(mf.NumFiles() != 0)
{
CvsCmdAddFiles(&mf);
}
return 0;
}
int UCvsFiles::OnCmdAddb(void)
{
int nItem = -1;
MultiFiles mf;
mf.newdir(m_path);
// first add the folders
while((nItem = UEventSendMessage(GetWidID(), EV_LIST_GETNEXTSEL, UMAKEINT(kUMainWidget, nItem), 0L)) != -1)
{
EntnodeData *data;
UEventSendMessage(GetWidID(), EV_LIST_ROWGETDATA, UMAKEINT(kUMainWidget, nItem), &data);
if(data->GetType() == ENT_SUBDIR)
{
CStr fullpath;
fullpath = m_path;
if(!fullpath.endsWith(kPathDelimiter))
fullpath << kPathDelimiter;
fullpath << (*data)[EntnodeData::kName];
CvsCmdAddFolder(fullpath);
}
else
{
mf.newfile((*data)[EntnodeData::kName], 0, (*data)[EntnodeFile::kVN]);
}
}
if(mf.NumFiles() != 0)
{
CvsCmdAddBinaryFiles(&mf);
}
return 0;
}
int UCvsFiles::OnCmdCommit(void)
{
int nItem = -1;
MultiFiles mf;
mf.newdir(m_path);
// first add the folders
while((nItem = UEventSendMessage(GetWidID(), EV_LIST_GETNEXTSEL, UMAKEINT(kUMainWidget, nItem), 0L)) != -1)
{
EntnodeData *data;
UEventSendMessage(GetWidID(), EV_LIST_ROWGETDATA, UMAKEINT(kUMainWidget, nItem), &data);
if(data->GetType() == ENT_SUBDIR)
{
CStr fullpath;
fullpath = m_path;
if(!fullpath.endsWith(kPathDelimiter))
fullpath << kPathDelimiter;
fullpath << (*data)[EntnodeData::kName];
CvsCmdCommitFolder(fullpath);
}
else
{
mf.newfile((*data)[EntnodeData::kName], 0, (*data)[EntnodeFile::kVN]);
}
}
if(mf.NumFiles() != 0)
{
CvsCmdCommitFiles(&mf);
}
return 0;
}
int UCvsFiles::OnCmdRmv(void)
{
int nItem = -1;
MultiFiles mf;
mf.newdir(m_path);
// first add the folders
while((nItem = UEventSendMessage(GetWidID(), EV_LIST_GETNEXTSEL, UMAKEINT(kUMainWidget, nItem), 0L)) != -1)
{
EntnodeData *data;
UEventSendMessage(GetWidID(), EV_LIST_ROWGETDATA, UMAKEINT(kUMainWidget, nItem), &data);
if(data->GetType() != ENT_FILE)
continue;
mf.newfile((*data)[EntnodeData::kName], 0, (*data)[EntnodeFile::kVN]);
}
if(mf.NumFiles() != 0)
{
CvsCmdRemoveFiles(&mf);
}
return 0;
}
int UCvsFiles::OnCmdQueryUpdate(void)
{
int nItem = -1;
MultiFiles mf;
mf.newdir(m_path);
// first add the folders
while((nItem = UEventSendMessage(GetWidID(), EV_LIST_GETNEXTSEL, UMAKEINT(kUMainWidget, nItem), 0L)) != -1)
{
EntnodeData *data;
UEventSendMessage(GetWidID(), EV_LIST_ROWGETDATA, UMAKEINT(kUMainWidget, nItem), &data);
if(data->GetType() == ENT_SUBDIR)
{
CStr fullpath;
fullpath = m_path;
if(!fullpath.endsWith(kPathDelimiter))
fullpath << kPathDelimiter;
fullpath << (*data)[EntnodeData::kName];
CvsCmdUpdateFolder(fullpath, true);
}
else
{
mf.newfile((*data)[EntnodeData::kName], 0, (*data)[EntnodeFile::kVN]);
}
}
if(mf.NumFiles() != 0)
{
CvsCmdUpdateFiles(&mf, true);
}
return 0;
}
int UCvsFiles::OnCmdReload(void)
{
ResetView(true, true);
return 0;
}
int UCvsFiles::OnCmdUpone(void)
{
UStr uppath, filename;
SplitPath(m_path, uppath, filename);
ResetView((const char *)uppath, true);
return 0;
}
int UCvsFiles::OnCmdTrash(void)
{
int nItem = -1;
MultiFiles mf;
mf.newdir(m_path);
// first add the folders
while((nItem = UEventSendMessage(GetWidID(), EV_LIST_GETNEXTSEL, UMAKEINT(kUMainWidget, nItem), 0L)) != -1)
{
EntnodeData *data;
UEventSendMessage(GetWidID(), EV_LIST_ROWGETDATA, UMAKEINT(kUMainWidget, nItem), &data);
if(data->GetType() != ENT_FILE)
continue;
mf.newfile((*data)[EntnodeData::kName], 0, (*data)[EntnodeFile::kVN]);
}
if(mf.NumFiles() != 0)
{
CvsArgs args(false);
mf.next();
const char *dir = mf.add(args);
char * const *argv = args.Argv();
int argc = args.Argc();
for(int i = 0; i < argc; i++)
{
CStr fullpath(dir);
if(!fullpath.empty() && !fullpath.endsWith(kPathDelimiter))
{
fullpath << kPathDelimiter;
}
fullpath << argv[i];
if(chmod(fullpath, 0666) != 0)
{
cvs_err("Unable to change permission on '%s' (error %d)\n", (const char *)fullpath, errno);
continue;
}
if(!CompatMoveToTrash(argv[i], dir))
cvs_err("Unable to remove '%s' (error %d)\n", (const char *)fullpath, errno);
else
#ifdef WIN32
cvs_out("'%s' has been moved successfully to the recycle bin...\n", (const char *)fullpath);
#else
cvs_out("'%s' has been deleted successfully...\n", (const char *)fullpath);
#endif
}
ResetView(true);
}
return 0;
}
int UCvsFiles::OnCmdDiff(void)
{
int nItem = -1;
MultiFiles mf;
mf.newdir(m_path);
// first add the folders
while((nItem = UEventSendMessage(GetWidID(), EV_LIST_GETNEXTSEL, UMAKEINT(kUMainWidget, nItem), 0L)) != -1)
{
EntnodeData *data;
UEventSendMessage(GetWidID(), EV_LIST_ROWGETDATA, UMAKEINT(kUMainWidget, nItem), &data);
if(data->GetType() == ENT_SUBDIR)
{
CStr fullpath;
fullpath = m_path;
if(!fullpath.endsWith(kPathDelimiter))
fullpath << kPathDelimiter;
fullpath << (*data)[EntnodeData::kName];
CvsCmdDiffFolder(fullpath);
}
else
{
mf.newfile((*data)[EntnodeData::kName], 0, (*data)[EntnodeFile::kVN]);
}
}
if(mf.NumFiles() != 0)
{
CvsCmdDiffFiles(&mf);
}
return 0;
}
int UCvsFiles::OnCmdLog(void)
{
int nItem = -1;
MultiFiles mf;
mf.newdir(m_path);
// first add the folders
while((nItem = UEventSendMessage(GetWidID(), EV_LIST_GETNEXTSEL, UMAKEINT(kUMainWidget, nItem), 0L)) != -1)
{
EntnodeData *data;
UEventSendMessage(GetWidID(), EV_LIST_ROWGETDATA, UMAKEINT(kUMainWidget, nItem), &data);
if(data->GetType() == ENT_SUBDIR)
{
CStr fullpath;
fullpath = m_path;
if(!fullpath.endsWith(kPathDelimiter))
fullpath << kPathDelimiter;
fullpath << (*data)[EntnodeData::kName];
CvsCmdLogFolder(fullpath);
}
else
{
mf.newfile((*data)[EntnodeData::kName], 0, (*data)[EntnodeFile::kVN]);
}
}
if(mf.NumFiles() != 0)
{
CvsCmdLogFiles(&mf);
}
return 0;
}
int UCvsFiles::OnCmdGraph(void)
{
int nItem = -1;
MultiFiles mf;
mf.newdir(m_path);
// first add the folders
while((nItem = UEventSendMessage(GetWidID(), EV_LIST_GETNEXTSEL, UMAKEINT(kUMainWidget, nItem), 0L)) != -1)
{
EntnodeData *data;
UEventSendMessage(GetWidID(), EV_LIST_ROWGETDATA, UMAKEINT(kUMainWidget, nItem), &data);
if(data->GetType() != ENT_FILE)
continue;
mf.newfile((*data)[EntnodeData::kName], 0, (*data)[EntnodeFile::kVN]);
}
if(mf.NumFiles() != 0)
{
CvsCmdLogFiles(&mf, true);
}
return 0;
}
int UCvsFiles::OnCmdStatus(void)
{
int nItem = -1;
MultiFiles mf;
mf.newdir(m_path);
// first add the folders
while((nItem = UEventSendMessage(GetWidID(), EV_LIST_GETNEXTSEL, UMAKEINT(kUMainWidget, nItem), 0L)) != -1)
{
EntnodeData *data;
UEventSendMessage(GetWidID(), EV_LIST_ROWGETDATA, UMAKEINT(kUMainWidget, nItem), &data);
if(data->GetType() == ENT_SUBDIR)
{
CStr fullpath;
fullpath = m_path;
if(!fullpath.endsWith(kPathDelimiter))
fullpath << kPathDelimiter;
fullpath << (*data)[EntnodeData::kName];
CvsCmdStatusFolder(fullpath);
}
else
{
mf.newfile((*data)[EntnodeData::kName], 0, (*data)[EntnodeFile::kVN]);
}
}
if(mf.NumFiles() != 0)
{
CvsCmdStatusFiles(&mf);
}
return 0;
}
int UCvsFiles::OnCmdLock(void)
{
int nItem = -1;
MultiFiles mf;
mf.newdir(m_path);
// first add the folders
while((nItem = UEventSendMessage(GetWidID(), EV_LIST_GETNEXTSEL, UMAKEINT(kUMainWidget, nItem), 0L)) != -1)
{
EntnodeData *data;
UEventSendMessage(GetWidID(), EV_LIST_ROWGETDATA, UMAKEINT(kUMainWidget, nItem), &data);
if(data->GetType() == ENT_SUBDIR)
{
CStr fullpath;
fullpath = m_path;
if(!fullpath.endsWith(kPathDelimiter))
fullpath << kPathDelimiter;
fullpath << (*data)[EntnodeData::kName];
CvsCmdLockFolder(fullpath);
}
else
{
mf.newfile((*data)[EntnodeData::kName], 0, (*data)[EntnodeFile::kVN]);
}
}
if(mf.NumFiles() != 0)
{
CvsCmdLockFiles(&mf);
}
return 0;
}
int UCvsFiles::OnCmdUnlock(void)
{
int nItem = -1;
MultiFiles mf;
mf.newdir(m_path);
// first add the folders
while((nItem = UEventSendMessage(GetWidID(), EV_LIST_GETNEXTSEL, UMAKEINT(kUMainWidget, nItem), 0L)) != -1)
{
EntnodeData *data;
UEventSendMessage(GetWidID(), EV_LIST_ROWGETDATA, UMAKEINT(kUMainWidget, nItem), &data);
if(data->GetType() == ENT_SUBDIR)
{
CStr fullpath;
fullpath = m_path;
if(!fullpath.endsWith(kPathDelimiter))
fullpath << kPathDelimiter;
fullpath << (*data)[EntnodeData::kName];
CvsCmdUnlockFolder(fullpath);
}
else
{
mf.newfile((*data)[EntnodeData::kName], 0, (*data)[EntnodeFile::kVN]);
}
}
if(mf.NumFiles() != 0)
{
CvsCmdUnlockFiles(&mf);
}
return 0;
}
int UCvsFiles::OnCmdWatchOn(void)
{
int nItem = -1;
MultiFiles mf;
mf.newdir(m_path);
// first add the folders
while((nItem = UEventSendMessage(GetWidID(), EV_LIST_GETNEXTSEL, UMAKEINT(kUMainWidget, nItem), 0L)) != -1)
{
EntnodeData *data;
UEventSendMessage(GetWidID(), EV_LIST_ROWGETDATA, UMAKEINT(kUMainWidget, nItem), &data);
if(data->GetType() == ENT_SUBDIR)
{
CStr fullpath;
fullpath = m_path;
if(!fullpath.endsWith(kPathDelimiter))
fullpath << kPathDelimiter;
fullpath << (*data)[EntnodeData::kName];
CvsCmdWatchOnFolder(fullpath);
}
else
{
mf.newfile((*data)[EntnodeData::kName], 0, (*data)[EntnodeFile::kVN]);
}
}
if(mf.NumFiles() != 0)
{
CvsCmdWatchOnFiles(&mf);
}
return 0;
}
int UCvsFiles::OnCmdWatchOff(void)
{
int nItem = -1;
MultiFiles mf;
mf.newdir(m_path);
// first add the folders
while((nItem = UEventSendMessage(GetWidID(), EV_LIST_GETNEXTSEL, UMAKEINT(kUMainWidget, nItem), 0L)) != -1)
{
EntnodeData *data;
UEventSendMessage(GetWidID(), EV_LIST_ROWGETDATA, UMAKEINT(kUMainWidget, nItem), &data);
if(data->GetType() == ENT_SUBDIR)
{
CStr fullpath;
fullpath = m_path;
if(!fullpath.endsWith(kPathDelimiter))
fullpath << kPathDelimiter;
fullpath << (*data)[EntnodeData::kName];
CvsCmdWatchOffFolder(fullpath);
}
else
{
mf.newfile((*data)[EntnodeData::kName], 0, (*data)[EntnodeFile::kVN]);
}
}
if(mf.NumFiles() != 0)
{
CvsCmdWatchOffFiles(&mf);
}
return 0;
}
int UCvsFiles::OnCmdEdit(void)
{
int nItem = -1;
MultiFiles mf;
mf.newdir(m_path);
// first add the folders
while((nItem = UEventSendMessage(GetWidID(), EV_LIST_GETNEXTSEL, UMAKEINT(kUMainWidget, nItem), 0L)) != -1)
{
EntnodeData *data;
UEventSendMessage(GetWidID(), EV_LIST_ROWGETDATA, UMAKEINT(kUMainWidget, nItem), &data);
if(data->GetType() == ENT_SUBDIR)
{
CStr fullpath;
fullpath = m_path;
if(!fullpath.endsWith(kPathDelimiter))
fullpath << kPathDelimiter;
fullpath << (*data)[EntnodeData::kName];
CvsCmdEditFolder(fullpath);
}
else
{
mf.newfile((*data)[EntnodeData::kName], 0, (*data)[EntnodeFile::kVN]);
}
}
if(mf.NumFiles() != 0)
{
CvsCmdEditFiles(&mf);
}
return 0;
}
int UCvsFiles::OnCmdUnedit(void)
{
int nItem = -1;
MultiFiles mf;
mf.newdir(m_path);
// first add the folders
while((nItem = UEventSendMessage(GetWidID(), EV_LIST_GETNEXTSEL, UMAKEINT(kUMainWidget, nItem), 0L)) != -1)
{
EntnodeData *data;
UEventSendMessage(GetWidID(), EV_LIST_ROWGETDATA, UMAKEINT(kUMainWidget, nItem), &data);
if(data->GetType() == ENT_SUBDIR)
{
CStr fullpath;
fullpath = m_path;
if(!fullpath.endsWith(kPathDelimiter))
fullpath << kPathDelimiter;
fullpath << (*data)[EntnodeData::kName];
CvsCmdUneditFolder(fullpath);
}
else
{
mf.newfile((*data)[EntnodeData::kName], 0, (*data)[EntnodeFile::kVN]);
}
}
if(mf.NumFiles() != 0)
{
CvsCmdUneditFiles(&mf);
}
return 0;
}
int UCvsFiles::OnCmdWatchers(void)
{
int nItem = -1;
MultiFiles mf;
mf.newdir(m_path);
// first add the folders
while((nItem = UEventSendMessage(GetWidID(), EV_LIST_GETNEXTSEL, UMAKEINT(kUMainWidget, nItem), 0L)) != -1)
{
EntnodeData *data;
UEventSendMessage(GetWidID(), EV_LIST_ROWGETDATA, UMAKEINT(kUMainWidget, nItem), &data);
if(data->GetType() == ENT_SUBDIR)
{
CStr fullpath;
fullpath = m_path;
if(!fullpath.endsWith(kPathDelimiter))
fullpath << kPathDelimiter;
fullpath << (*data)[EntnodeData::kName];
CvsCmdWatchersFolder(fullpath);
}
else
{
mf.newfile((*data)[EntnodeData::kName], 0, (*data)[EntnodeFile::kVN]);
}
}
if(mf.NumFiles() != 0)
{
CvsCmdWatchersFiles(&mf);
}
return 0;
}
int UCvsFiles::OnCmdEditors(void)
{
int nItem = -1;
MultiFiles mf;
mf.newdir(m_path);
// first add the folders
while((nItem = UEventSendMessage(GetWidID(), EV_LIST_GETNEXTSEL, UMAKEINT(kUMainWidget, nItem), 0L)) != -1)
{
EntnodeData *data;
UEventSendMessage(GetWidID(), EV_LIST_ROWGETDATA, UMAKEINT(kUMainWidget, nItem), &data);
if(data->GetType() == ENT_SUBDIR)
{
CStr fullpath;
fullpath = m_path;
if(!fullpath.endsWith(kPathDelimiter))
fullpath << kPathDelimiter;
fullpath << (*data)[EntnodeData::kName];
CvsCmdEditorsFolder(fullpath);
}
else
{
mf.newfile((*data)[EntnodeData::kName], 0, (*data)[EntnodeFile::kVN]);
}
}
if(mf.NumFiles() != 0)
{
CvsCmdEditorsFiles(&mf);
}
return 0;
}
int UCvsFiles::OnCmdRelease(void)
{
int nItem = -1;
// first add the folders
while((nItem = UEventSendMessage(GetWidID(), EV_LIST_GETNEXTSEL, UMAKEINT(kUMainWidget, nItem), 0L)) != -1)
{
EntnodeData *data;
UEventSendMessage(GetWidID(), EV_LIST_ROWGETDATA, UMAKEINT(kUMainWidget, nItem), &data);
if(data->GetType() == ENT_SUBDIR)
{
CStr fullpath;
fullpath = m_path;
if(!fullpath.endsWith(kPathDelimiter))
fullpath << kPathDelimiter;
fullpath << (*data)[EntnodeData::kName];
CvsCmdReleaseFolder(fullpath);
}
}
return 0;
}
int UCvsFiles::OnCmdTagNew(void)
{
int nItem = -1;
MultiFiles mf;
mf.newdir(m_path);
// first add the folders
while((nItem = UEventSendMessage(GetWidID(), EV_LIST_GETNEXTSEL, UMAKEINT(kUMainWidget, nItem), 0L)) != -1)
{
EntnodeData *data;
UEventSendMessage(GetWidID(), EV_LIST_ROWGETDATA, UMAKEINT(kUMainWidget, nItem), &data);
if(data->GetType() == ENT_SUBDIR)
{
CStr fullpath;
fullpath = m_path;
if(!fullpath.endsWith(kPathDelimiter))
fullpath << kPathDelimiter;
fullpath << (*data)[EntnodeData::kName];
CvsCmdTagCreateFolder(fullpath);
}
else
{
mf.newfile((*data)[EntnodeData::kName], 0, (*data)[EntnodeFile::kVN]);
}
}
if(mf.NumFiles() != 0)
{
CvsCmdTagCreateFiles(&mf);
}
return 0;
}
int UCvsFiles::OnCmdTagDelete(void)
{
int nItem = -1;
MultiFiles mf;
mf.newdir(m_path);
// first add the folders
while((nItem = UEventSendMessage(GetWidID(), EV_LIST_GETNEXTSEL, UMAKEINT(kUMainWidget, nItem), 0L)) != -1)
{
EntnodeData *data;
UEventSendMessage(GetWidID(), EV_LIST_ROWGETDATA, UMAKEINT(kUMainWidget, nItem), &data);
if(data->GetType() == ENT_SUBDIR)
{
CStr fullpath;
fullpath = m_path;
if(!fullpath.endsWith(kPathDelimiter))
fullpath << kPathDelimiter;
fullpath << (*data)[EntnodeData::kName];
CvsCmdTagDeleteFolder(fullpath);
}
else
{
mf.newfile((*data)[EntnodeData::kName], 0, (*data)[EntnodeFile::kVN]);
}
}
if(mf.NumFiles() != 0)
{
CvsCmdTagDeleteFiles(&mf);
}
return 0;
}
int UCvsFiles::OnCmdTagBranch(void)
{
int nItem = -1;
MultiFiles mf;
mf.newdir(m_path);
// first add the folders
while((nItem = UEventSendMessage(GetWidID(), EV_LIST_GETNEXTSEL, UMAKEINT(kUMainWidget, nItem), 0L)) != -1)
{
EntnodeData *data;
UEventSendMessage(GetWidID(), EV_LIST_ROWGETDATA, UMAKEINT(kUMainWidget, nItem), &data);
if(data->GetType() == ENT_SUBDIR)
{
CStr fullpath;
fullpath = m_path;
if(!fullpath.endsWith(kPathDelimiter))
fullpath << kPathDelimiter;
fullpath << (*data)[EntnodeData::kName];
CvsCmdTagBranchFolder(fullpath);
}
else
{
mf.newfile((*data)[EntnodeData::kName], 0, (*data)[EntnodeFile::kVN]);
}
}
if(mf.NumFiles() != 0)
{
CvsCmdTagBranchFiles(&mf);
}
return 0;
}
int UCvsFiles::OnCmdExplore(void)
{
int nItem = -1;
// first add the folders
if((nItem = UEventSendMessage(GetWidID(), EV_LIST_GETNEXTSEL, UMAKEINT(kUMainWidget, nItem), 0L)) != -1)
{
EntnodeData *data;
UEventSendMessage(GetWidID(), EV_LIST_ROWGETDATA, UMAKEINT(kUMainWidget, nItem), &data);
CStr fullpath;
fullpath = m_path;
if(!fullpath.endsWith(kPathDelimiter))
fullpath << kPathDelimiter;
fullpath << (*data)[EntnodeData::kName];
#ifdef WIN32
HINSTANCE hInst = ShellExecute(*AfxGetMainWnd(), "explore", fullpath,
0L, 0L, SW_SHOWDEFAULT);
if((long)hInst < 32)
{
cvs_err("Unable to explore '%s' (error %d)\n", (char *)m_path, GetLastError());
}
#endif
#ifdef qUnix
CvsArgs args(false);
args.add(gCvsPrefs.Browser());
args.add(fullpath);
UCvsApp::gApp->Execute(args.Argc(), args.Argv());
#endif
}
return 0;
}
int UCvsFiles::OnCmdIgnore(void)
{
gFileViewIgnore = !(bool)gFileViewIgnore;
ResetView(true, true);
return 0;
}
int UCvsFiles::OnCmdEditsel(void)
{
int nItem = -1;
while((nItem = UEventSendMessage(GetWidID(), EV_LIST_GETNEXTSEL, UMAKEINT(kUMainWidget, nItem), 0L)) != -1)
{
EntnodeData *data;
UEventSendMessage(GetWidID(), EV_LIST_ROWGETDATA, UMAKEINT(kUMainWidget, nItem), &data);
EditSel(data);
}
return 0;
}
int UCvsFiles::OnCmdEditseldef(void)
{
int nItem = -1;
while((nItem = UEventSendMessage(GetWidID(), EV_LIST_GETNEXTSEL, UMAKEINT(kUMainWidget, nItem), 0L)) != -1)
{
EntnodeData *data;
UEventSendMessage(GetWidID(), EV_LIST_ROWGETDATA, UMAKEINT(kUMainWidget, nItem), &data);
EditSel(data, true);
}
return 0;
}
int UCvsFiles::OnMacroSel(int cmd)
{
CTcl_Interp interp;
CMacroEntry & entry = gMacrosSel.entries[cmd - cmdSELMACRO];
CStr path = entry.path;
CTcl_Interp::Unixfy(path);
TclBrowserReset();
int nItem = -1;
while((nItem = UEventSendMessage(GetWidID(), EV_LIST_GETNEXTSEL, UMAKEINT(kUMainWidget, nItem), 0L)) != -1)
{
EntnodeData *data;
UEventSendMessage(GetWidID(), EV_LIST_ROWGETDATA, UMAKEINT(kUMainWidget, nItem), &data);
TclBrowserAppend(m_path, data);
}
interp.DoScriptVar("source \"%s\"", (const char *)path);
return 0;
}
void UCvsFiles::EditSel(EntnodeData *data, bool useDefault)
{
CStr fullpath;
fullpath = m_path;
if(!fullpath.endsWith(kPathDelimiter))
fullpath << kPathDelimiter;
fullpath << (*data)[EntnodeData::kName];
if(data->GetType() == ENT_SUBDIR)
{
ResetView((const char *)fullpath, true);
}
else
{
#ifdef WIN32
char viewer[_MAX_PATH];
HINSTANCE hInst = FindExecutable((*data)[EntnodeData::kName],
m_path, viewer);
bool done = false;
if(!useDefault && (UINT)hInst >= 32)
{
HINSTANCE hInst = ShellExecute(*AfxGetMainWnd(), "open", (*data)[EntnodeData::kName],
NULL, m_path, SW_SHOWDEFAULT);
if((long)hInst < 32)
{
cvs_err("Unable to open '%s' (error %d), using default viewer instead\n", (char *)fullpath, GetLastError());
}
else
done = true;
}
if(!done)
{
const char * argv[3] = {0L, 0L, 0L};
CStr program, file;
if(strchr(gCvsPrefs.Viewer(), ' ') != 0L)
{
program << '\"';
program << gCvsPrefs.Viewer();
program << '\"';
}
else
program = gCvsPrefs.Viewer();
if(strchr(fullpath, ' ') != 0L)
{
file << '\"';
file << fullpath;
file << '\"';
}
else
file = fullpath;
argv[0] = program;
argv[1] = file;
int process = _spawnvp(_P_NOWAIT, gCvsPrefs.Viewer(), argv);
}
#endif
#ifdef qUnix
CStr fullpath;
fullpath = m_path;
if(!fullpath.endsWith(kPathDelimiter))
fullpath << kPathDelimiter;
fullpath << (*data)[EntnodeData::kName];
CvsArgs args(false);
args.add(gCvsPrefs.Viewer());
args.add(fullpath);
UCvsApp::gApp->Execute(args.Argc(), args.Argv());
#endif
}
}
void UCvsFiles::OnDblClick(void)
{
int nItem = -1;
while((nItem = UEventSendMessage(GetWidID(), EV_LIST_GETNEXTSEL, UMAKEINT(kUMainWidget, nItem), 0L)) != -1)
{
EntnodeData *data;
UEventSendMessage(GetWidID(), EV_LIST_ROWGETDATA, UMAKEINT(kUMainWidget, nItem), &data);
EditSel(data);
}
}
static int compareName(UWidget *wid, void *data1, void *data2)
{
UCvsFiles *w = (UCvsFiles *)wid;
EntnodeData *d1 = (EntnodeData *)data1;
EntnodeData *d2 = (EntnodeData *)data2;
int res = stricmp((*d1)[EntnodeData::kName], (*d2)[EntnodeData::kName]);
return w->IsSortAscendant() ? res : -res;
}
static int compareStatus(UWidget *wid, void *data1, void *data2)
{
UCvsFiles *w = (UCvsFiles *)wid;
EntnodeData *d1 = (EntnodeData *)data1;
EntnodeData *d2 = (EntnodeData *)data2;
int res = stricmp((*d1)[EntnodeData::kStatus], (*d2)[EntnodeData::kStatus]);
if(res == 0)
res = stricmp((*d1)[EntnodeData::kName], (*d2)[EntnodeData::kName]);
return w->IsSortAscendant() ? res : -res;
}
static int compareOption(UWidget *wid, void *data1, void *data2)
{
UCvsFiles *w = (UCvsFiles *)wid;
EntnodeData *d1 = (EntnodeData *)data1;
EntnodeData *d2 = (EntnodeData *)data2;
const char *s1 = (*d1)[EntnodeFile::kOption];
const char *s2 = (*d2)[EntnodeFile::kOption];
int res;
if(s1 != 0L && s2 != 0L)
res = strcmp(s1, s2);
else
res = (long)s1 < (long)s2 ? -1 : ((long)s1 > (long)s2 ? 1 : 0);
if(res == 0)
res = stricmp((*d1)[EntnodeData::kName], (*d2)[EntnodeData::kName]);
return w->IsSortAscendant() ? res : -res;
}
static int revcmp(const char *rev1, const char *rev2)
{
if(rev1 == 0L && rev2 == 0L)
return 0;
else if(rev1 == 0L || rev2 == 0L)
return rev1 == 0L ? -1 : 1;
CStr r1(rev1), r2(rev2);
CStr q1, q2;
char *tmp;
int v1, v2;
if((tmp = strchr(r1, '.')) != 0L)
{
tmp[0] = '\0';
q1 = tmp + 1;
}
v1 = atoi(r1);
if((tmp = strchr(r2, '.')) != 0L)
{
tmp[0] = '\0';
q2 = tmp + 1;
}
v2 = atoi(r2);
if(v1 == v2)
return revcmp(q1.empty() ? (char *)0L : (const char *)q1, q2.empty() ? (char *)0L : (const char *)q2);
return v1 < v2 ? -1 : 1;
}
static int compareRevs(UWidget *wid, void * data1, void * data2)
{
UCvsFiles *w = (UCvsFiles *)wid;
EntnodeData *d1 = (EntnodeData *)data1;
EntnodeData *d2 = (EntnodeData *)data2;
const char *s1 = (*d1)[EntnodeFile::kVN];
const char *s2 = (*d2)[EntnodeFile::kVN];
int res;
if(s1 != 0L && s2 != 0L)
res = revcmp(s1, s2);
else
res = (long)s1 < (long)s2 ? -1 : ((long)s1 > (long)s2 ? 1 : 0);
if(res == 0)
res = stricmp((*d1)[EntnodeData::kName], (*d2)[EntnodeData::kName]);
return w->IsSortAscendant() ? res : -res;
}
static int compareTag(UWidget *wid, void * data1, void * data2)
{
UCvsFiles *w = (UCvsFiles *)wid;
EntnodeData *d1 = (EntnodeData *)data1;
EntnodeData *d2 = (EntnodeData *)data2;
const char *s1 = (*d1)[EntnodeFile::kTag];
const char *s2 = (*d2)[EntnodeFile::kTag];
int res;
if(s1 != 0L && s2 != 0L)
res = strcmp(s1, s2);
else
res = (long)s1 < (long)s2 ? -1 : ((long)s1 > (long)s2 ? 1 : 0);
if(res == 0)
res = stricmp((*d1)[EntnodeData::kName], (*d2)[EntnodeData::kName]);
return w->IsSortAscendant() ? res : -res;
}
static int compareConflict(UWidget *wid, void * data1, void * data2)
{
UCvsFiles *w = (UCvsFiles *)wid;
EntnodeData *d1 = (EntnodeData *)data1;
EntnodeData *d2 = (EntnodeData *)data2;
const char *s1 = (*d1)[EntnodeFile::kConflict];
const char *s2 = (*d2)[EntnodeFile::kConflict];
int res;
if(s1 != 0L && s2 != 0L)
res = strcmp(s1, s2);
else
res = (long)s1 < (long)s2 ? -1 : ((long)s1 > (long)s2 ? 1 : 0);
if(res == 0)
res = stricmp((*d1)[EntnodeData::kName], (*d2)[EntnodeData::kName]);
return w->IsSortAscendant() ? res : -res;
}
static int compareTimestamp(UWidget *wid, void *data1, void *data2)
{
UCvsFiles *w = (UCvsFiles *)wid;
EntnodeData *d1 = (EntnodeData *)data1;
EntnodeData *d2 = (EntnodeData *)data2;
const char *s1 = (*d1)[EntnodeFile::kTS];
const char *s2 = (*d2)[EntnodeFile::kTS];
int res;
if(s1 != 0L && s2 != 0L ) {
UStr str[2] = {s1, s2};
UStr t[2];
for(int i=0; i < 2; i++) {
// put the year in front of the date string
t[i] = str[i].substr(str[i].rfind(" ")+1, 4);
t[i] += " ";
// convert month name to month number
for(int j=0; j < 12; j++) {
if( !(strcmp(str[i].substr(4,3), month_names[j]) ) ) {
if(j<9)
t[i] += "0";
t[i] += j+1;
break;
}
}
t[i] += " ";
// paste day and time to time string
t[i] += str[i].substr(8, str[i].rfind(" ")-4);
}
res = t[0].compare(t[1]);
#ifdef DEBUG
fprintf(stderr, "%s %c %s\n", t[0].c_str(), (res==1?'<':'>') , t[1].c_str());
#endif
} else {
res = s1 < s2 ? -1 : (s1 > s2 ? 1 : 0);
}
if(res == 0)
res = stricmp((*d1)[EntnodeData::kName], (*d2)[EntnodeData::kName]);
return w->IsSortAscendant() ? res : -res;
}
void UCvsFiles::Resort(void)
{
UListSorter fsort = 0L;
switch(m_sort)
{
case EntnodeData::kName:
fsort = compareName;
break;
case EntnodeFile::kVN:
fsort = compareRevs;
break;
case EntnodeData::kStatus:
fsort = compareStatus;
break;
case EntnodeFile::kOption:
fsort = compareOption;
break;
case EntnodeFile::kTag:
fsort = compareTag;
break;
case EntnodeFile::kConflict:
fsort = compareConflict;
break;
case EntnodeFile::kTS:
fsort = compareTimestamp;
break;
}
if(fsort != 0L)
UEventSendMessage(GetWidID(), EV_LIST_RESORT, UMAKEINT(kUMainWidget, m_sort), (void *)fsort);
}
void UCvsFiles::OnSelColumn(int column)
{
if(column == m_sort)
m_ascendant = !m_ascendant;
else
{
m_ascendant = true;
switch(column)
{
case EntnodeData::kName:
case EntnodeData::kStatus:
case EntnodeFile::kOption:
case EntnodeFile::kTag:
case EntnodeFile::kConflict:
case EntnodeFile::kTS:
case EntnodeFile::kVN:
m_sort = column;
break;
}
}
Resort();
}