/* ** 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 --- February 2000 */ /* * */ #include "stdafx.h" #if qGTK # include #endif #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_STRINGS_H #include #endif #include #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 const 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 & m_entries; NAMESPACE(std) vector m_ignlist; TViewFill(UCvsFiles *listCtrl, CSortList & 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(); }