/* ** 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 --- August 1998 */ /* * MacrosSetup.cpp --- hook the macros files */ #include "stdafx.h" #ifndef WIN32 # include #endif /* !WIN32 */ #ifdef HAVE_STRING_H # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_ERRNO_H # include #endif #include "MacrosSetup.h" #include "AppConsole.h" #include "FileTraversal.h" #include "getline.h" #include "CvsArgs.h" #ifdef macintosh # include "MacMisc.h" # include #endif #ifdef qMacCvsPP # include "MacCvsApp.h" #endif /* qMacCvsPP */ #include "getopt.h" #ifdef WIN32 # include "wincvs.h" # ifdef _DEBUG # define new DEBUG_NEW # undef THIS_FILE static char THIS_FILE[] = __FILE__; # endif #endif /* WIN32 */ CMacroSet gMacrosAdmin; CMacroSet gMacrosSel; static void getLoc(CStr & path, const char *subFolder) { path = ""; #ifdef WIN32 CWincvsApp* pApp = (CWincvsApp *)AfxGetApp(); pApp->GetAppPath(path); CString appPath = path; // first the macro folder may be ./macro CString test = appPath; test.TrimRight('\\'); test += "\\"; test += subFolder; struct stat sb; if(stat(test, &sb) != -1 && S_ISDIR(sb.st_mode)) { path = test; return; } CStr uppath, file; while(SplitPath(appPath, uppath, file) && !uppath.empty()) { test = uppath; test.TrimRight('\\'); test += "\\"; test += subFolder; if(stat(test, &sb) != -1 && S_ISDIR(sb.st_mode)) { path = test; return; } appPath = uppath; } path = test; #elif defined(qUnix) struct stat sb; path = PACKAGE_DATA_DIR; if(stat(path, &sb) == -1 || !S_ISDIR(sb.st_mode)) { path = PACKAGE_SOURCE_DIR; CStr uppath, folder; SplitPath(path, uppath, folder); path = uppath; if(!path.endsWith(kPathDelimiter)) path << kPathDelimiter; path << subFolder; } #elif qMacCvsPP UStr appPath = CMacCvsApp::GetAppPath(); if(!appPath.endsWith(kPathDelimiter)) appPath << kPathDelimiter; UStr test = appPath; test << subFolder; struct stat sb; if(stat(test, &sb) != -1 && S_ISDIR(sb.st_mode)) { path = test; return; } UStr uppath, file; while(SplitPath(appPath, uppath, file) && !uppath.empty()) { test = uppath; if(!test.endsWith(kPathDelimiter)) test << kPathDelimiter; test << subFolder; if(stat(test, &sb) != -1 && S_ISDIR(sb.st_mode)) { path = test; return; } appPath = uppath; } path = test; #else if(!path.empty() && !path.endsWith(kPathDelimiter)) { path << kPathDelimiter; } path << subFolder; #endif } void MacrosGetLoc(CStr & path) { getLoc(path, MACROS_FOLDER); } void PythonLibGetLoc(CStr & path) { getLoc(path, PYTHONLIB_FOLDER); } static void MacrosFlushAll(void) { gMacrosAdmin.Flush(); gMacrosSel.Flush(); } class MacroTraversal : public TraversalReport { public: virtual kTraversal OnError(const char *err, int errcode) { cvs_err(err); cvs_err("\n"); return kTraversalError; } virtual kTraversal OnFile(const char *fullpath, const char *fullname, const char *name, const struct stat & dir, const UFSSpec * macspec); }; kTraversal MacroTraversal::OnFile(const char *fullpath, const char *fullname, const char *name, const struct stat & dir, const UFSSpec * macspec) { if(stricmp(name + strlen(name) - 4, ".tcl")) return kContinueTraversal; FILE *fpin = fopen(fullname, "r"); if(fpin == 0L) { cvs_err("Impossible to open '%s' (error %d)\n", fullname, errno); return kContinueTraversal; } char *oldline = 0L; int line_length; size_t line_chars_allocated = 0; CvsArgs args(false); args.add("dummy"); if((line_length = getline (&oldline, &line_chars_allocated, fpin)) > 0 && strnicmp(oldline, "#!CVSGUI1.0", strlen("#!CVSGUI1.0")) == 0) { char *line = oldline + strlen("#!CVSGUI1.0"); while(*line) { int hasQuote = 0; char *temp; // Search for the non space char while(*line && isspace(*line)) ++line; // handle the quote if((*line) == '"') { hasQuote = 1; line++; } for(temp=line;*line;++line) { if((*line) == '"') { if(hasQuote) { hasQuote = 0; /* ok doc */ break; } } if(isspace(*line) && !hasQuote) break; } if(hasQuote) /* mismatch quote */ temp = line; if(temp != line) { CStr arg; arg.set(temp, line - temp); args.add(arg); } } static struct option long_options[] = { {"admin", no_argument, 0L, 1}, {"selection", no_argument, 0L, 2}, {"name", required_argument, 0L, 3}, {0, 0, 0, 0} }; bool hasAdmin = false; bool hasSel = false; CStr dispname; optind = 0; int option_index = 0, c; while ((c = getopt_long (args.Argc(), args.Argv(), "+", long_options, &option_index)) != EOF) { switch (c) { case 1: hasAdmin = true; break; case 2: hasSel = true; break; case 3: dispname = optarg; break; default: cvs_err("Warning : unknown option in the file '%s'\n", fullname); break; } } if(dispname.empty()) { dispname = name; } if(hasAdmin) { gMacrosAdmin.Add(fullname, dispname); } else if(hasSel) { gMacrosSel.Add(fullname, dispname); } else { cvs_err("Warning : no option in the file '%s'\n", fullname); } } free (oldline); fclose(fpin); return kContinueTraversal; } void MacrosReloadAll(void) { MacrosFlushAll(); // get the macro folder CStr path; MacrosGetLoc(path); // traverse the macro folder MacroTraversal traverse; FileTraverse(path, traverse); }