/******************************************************************************* Copyright (c) 2003, Robert Cowham and Vaccaperna Systems Ltd. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL VACCAPERNA SYSTEMS LTD. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *******************************************************************************/ /******************************************************************************* * Name: p4ClientUser.cpp * * Author: Robert Cowham <robert@vaccaperna.co.uk> * * Description: * COM bindings for the Perforce API. User interface class * for getting Perforce results into COM. * ******************************************************************************/ #include "stdafx.h" #include "p4ClientUser.h" #include "p4interface.h" #include "TraceUtils.h" #include "i18napi.h" ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// p4ClientUser::p4ClientUser() { try { STACK_TRACE("p4ClientUser::p4ClientUser") // Ensure our arrays are OK. m_InfoArray.ReDim(Dim(0)); m_WarningArray.ReDim(Dim(0)); m_ErrorArray.ReDim(Dim(0)); m_BinaryFile = NULL; m_TextFile = NULL; m_TranslateCharset = False; } catch (...) { LogException(_T("p4ClientUser::p4ClientUser")); } } void p4ClientUser::Reset() { try { STACK_TRACE("p4ClientUser::Reset") // Ensure our arrays are OK. m_InfoArray.ReDim(Dim(0)); m_WarningArray.ReDim(Dim(0)); m_ErrorArray.ReDim(Dim(0)); m_BinaryFile = NULL; m_TextFile = NULL; } catch (...) { LogException(_T("p4ClientUser::Reset")); } } p4ClientUser::~p4ClientUser() { try { STACK_TRACE("p4ClientUser::~p4ClientUser") } catch (...) { LogException(_T("p4ClientUser::~p4ClientUser")); } } void p4ClientUser::TranslateCharset(Boolean newVal) { STACK_TRACE("p4ClientUser::TranslateCharset set") m_TranslateCharset = newVal; } Boolean p4ClientUser::TranslateCharset() { STACK_TRACE("p4ClientUser::TranslateCharset get") return m_TranslateCharset; } void p4ClientUser::CloseFiles() { try { STACK_TRACE("p4ClientUser::CloseFiles") Error e; String s; if (NULL != m_BinaryFile) { m_BinaryFile->Close(&e); if (e.Test()) { FormatAndOutputError ("Failed to close binary file:", &e); } } if (NULL != m_TextFile) { m_TextFile->Close(&e); if (e.Test()) { FormatAndOutputError ("Failed to close text file:", &e); } } } catch (...) { LogException(_T("p4ClientUser::Final")); } } // Prompt user with error message void p4ClientUser::ErrorPause( char *errBuf, Error *e ) { try { STACK_TRACE("p4ClientUser::ErrorPause") OutputError( errBuf ); String msg = errBuf; MessageBox (NULL, msg, _T("p4vb"), MB_OK); } catch (...) { LogException(_T("p4ClientUser::ErrorPause")); } } // Writes specified data to the output file. void p4ClientUser::OutputData(FileSys ** OutFile, String * FileName, enum FileSysType FType, char *data, int len) { try { STACK_TRACE("p4ClientUser::OutputData") Error e; // If we haven't created a temp output file then do so now! if (NULL == *OutFile) { *OutFile = FileSys::CreateGlobalTemp(FType); (*OutFile)->ClearDeleteOnClose(); // Have had some problems with non-unique filenames. // Delete the file and ignore any errors. (*OutFile)->Unlink(&e); e.Clear(); *FileName = (*OutFile)->Name(); (*OutFile)->Open(FOM_WRITE, &e); if (e.Test()) { String msg ("Error opening temp file for write:"); msg += (*OutFile)->Name(); msg += " - "; FormatAndOutputError(msg, &e); return; } } // Now write the data (*OutFile)->Write(data, len, &e); if (e.Test()) { FormatAndOutputError ("Error writing to temp file :", &e); return; } } catch (...) { LogException(_T("p4ClientUser::OutputData")); } } // OutputData void p4ClientUser::HandleError(Error *e) { try { STACK_TRACE("p4ClientUser::HandleError") StrBuf m; e->Fmt(&m); int s = e->GetSeverity(); // // Empty and informational messages are pushed out as output as nothing // worthy of error handling has occurred. Warnings go into the warnings // list and the rest are lumped together as errors. // if (s == E_EMPTY || s == E_INFO) AddToArray(m.Text(), m.Length(), m_InfoArray); else if (s == E_WARN) AddToArray(m.Text(), m.Length(), m_WarningArray); else AddToArray(m.Text(), m.Length(), m_ErrorArray); } catch (...) { LogException(_T("p4ClientUser::HandleError")); } } // HandleError // Just store the information for later use void p4ClientUser::OutputInfo(char level, char *data) { try { STACK_TRACE("p4ClientUser::OutputInfo") AddToArray(data, strlen(data), m_InfoArray); } catch (...) { LogException(_T("p4ClientUser::OutputInfo")); } } // Just store the information for later use void p4ClientUser::OutputWarning(char *data) { try { STACK_TRACE("p4ClientUser::OutputWarning") AddToArray(data, strlen(data), m_WarningArray); } catch (...) { LogException(_T("p4ClientUser::OutputWarning")); } } // Just store the information for later use void p4ClientUser::OutputError(char *errBuf) { try { STACK_TRACE("p4ClientUser::OutputError") AddToArray(errBuf, strlen(errBuf), m_ErrorArray); } catch (...) { LogException(_T("p4ClientUser::OutputError")); } } // Write the data to a temp file void p4ClientUser::OutputText(char *data, int len) { try { STACK_TRACE("p4ClientUser::OutputText") OutputData(&m_TextFile, &m_TextFileName, FST_TEXT, data, len); } catch (...) { LogException(_T("p4ClientUser::OutputText")); } } // Write the data to a temp file void p4ClientUser::OutputBinary(char *data, int len) { try { STACK_TRACE("p4ClientUser::OutputBinary") OutputData(&m_BinaryFile, &m_BinaryFileName, FST_BINARY, data, len); } catch (...) { LogException(_T("p4ClientUser::OutputBinary")); } } // Add specified text to specified array void p4ClientUser::AddToArray(char *data, int len, ArrayString & as) { STACK_TRACE("p4ClientUser::AddToArray") // Redim the arraystring if (!as.IsSizable()) { TraceError(0, _T("ArrayString not resizeable")); return; } int ind = as.UBound(); as.ReDim(Dim(as.LBound(), ind + 1)); // Now create the element and add it to the array String s; if (m_TranslateCharset) { s.fromUTF8(data, len); } else { if (strlen(data) == (unsigned) len) { s = data; // Let conversion routines handle it } else // Do it the slow way. { while (len > 0) { s += *data; data++; len--; } } } as(ind + 1) = s; }; // AddToArray void p4ClientUser::OutputStat(StrDict *results) { try { STACK_TRACE("p4ClientUser::OutputStat") StrPtr *data = results->GetVar("data"); StrPtr *spec = results->GetVar("specdef"); if (spec && data) { Error e; m_spec = new Spec(spec->Text(), ""); m_spec->Parse(data->Text(), &m_specData, &e); if(e.Test()) { HandleError(&e); return; } } else { int i; StrBuf msg; StrRef var, val; // Dump out the variables, using the GetVar( x ) interface. // Taken from API doc. for( i = 0; results->GetVar( i, var, val ); i++ ) { if( var == "func" ) continue; // otherAction and otherOpen go at level 2, as per 99.1 + earlier msg.Clear(); msg << var << "=" << val; char level = strncmp( var.Text(), "other", 5 ) ? '1' : '2'; OutputInfo( level, msg.Text() ); } } } catch (...) { LogException(_T("p4ClientUser::OutputStat")); } } void p4ClientUser::InputData( StrBuf *strbuf, Error *e ) { try { STACK_TRACE("p4ClientUser::InputData") m_spec->Format(&m_specData, &m_specText); strbuf->Set(m_specText.Text()); } catch (...) { LogException(_T("p4ClientUser::InputData")); } } String p4ClientUser::GetVar(String var) { try { STACK_TRACE("p4ClientUser::GetVar get") String value; StrPtr *sp = m_specData.Dict()->GetVar(var); if (sp == NULL) { value.Nullify(); } else { if (m_TranslateCharset) { value.fromUTF8(sp->Text()); } else { value = sp->Text(); } } return value; } catch (...) { LogException(_T("p4ClientUser::GetVar")); return NULL; } } void p4ClientUser::SetVar(String varName, String newVal) { try { STACK_TRACE("p4ClientUser::SetVar") if (m_TranslateCharset) { newVal.toUTF8(); } m_specData.Dict()->ReplaceVar(varName, newVal); } catch (...) { LogException(_T("p4ClientUser::SetVar")); } } void p4ClientUser::SetArrayVar(String varName, ArrayString newVal) { int i; char idx[32]; char * var; String s; STACK_TRACE("p4ClientUser::SetArrayVar") var = (char *)idx; char * tag = (char *)(LPCSTR)varName; // Remove all files in the spec list and replace with new set for (i = 0; ; i++) { wsprintfA(idx, "%s%d", tag, i); if (!m_specData.Dict()->GetVar(var)) break; m_specData.Dict()->RemoveVar(var); } for (i = 0; i + newVal.LBound() <= newVal.UBound(); i++) { wsprintfA(idx, "%s%d", tag, i); s = newVal(newVal.LBound() + i); if (m_TranslateCharset) { s.toUTF8(); } m_specData.Dict()->SetVar(idx, s); } } ArrayString p4ClientUser::GetArrayVar(String varName) { ArrayString as; int i; char idx[32]; char * var; StrPtr *field; STACK_TRACE("p4ClientUser::GetArrayVar") var = (char *) idx; char *tag = (char *)(LPCSTR)varName; for ( i = 0; ; i++ ) { wsprintfA( idx, "%s%d", tag, i ); if ( field = m_specData.Dict()->GetVar( var ) ) { int ind = as.UBound(); as.ReDim(Dim(as.LBound(), ind + 1)); // Now create the element and add it to the array String s; if (m_TranslateCharset) { s.fromUTF8(field->Text()); } else { s = field->Text(); // Let conversion routines handle it } as(ind + 1) = s; } else break; } return as; }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#10 | 9835 | Robert Cowham | Added SetProtocolV | ||
#9 | 7548 | Robert Cowham | - Fix backwards compatibility problem with P4OFC - which uses setprotocol "API", "57" | ||
#8 | 7443 | Robert Cowham | Update for new API outputstat. | ||
#7 | 6050 | Robert Cowham |
- Use P4API 2007.2 - Added SetProg, SetVersion, SetProtocol and GetProtocol |
||
#6 | 5194 | Robert Cowham |
Changes (2005.1.0.0) Added Dropped() to detect dropped connections Added Input property to provide input e.g. for passwords Added FormatDateTime() as a convenience for calling C Runtime function (for VB use) Imported changes from p4ofc which made it more reliable. |
||
#5 | 4242 | Robert Cowham |
Fixed some String leaks. Fixed problem with writing to temporary files. Updated p4API to released version of 2003.2. Start of Delphi example. |
||
#4 | 4182 | Robert Cowham | Release 1.0.0.4 - put output of Diff in normal output array. | ||
#3 | 3614 | Robert Cowham | Fixed memory leak and hanging over of variables when using forms. | ||
#2 | 3612 | Robert Cowham |
Version 1.0.0.2 New interface for ServerVersion. New put property ArrayVarVar which is the same as ArrayVar but takes an Array of Variants rather than strings (for Lisp compatibility!). |
||
#1 | 3525 | Robert Cowham | Initial release |