<< Back
// FVSDKLogList.cpp : implementation file
//
// Copyright © 1997-2008 - Rhino Software, Inc.
// FTP Voyager® is a registered trademark of Rhino Software, Inc.
// http://www.RhinoSoft.com/
//
// Author:  Mark P. Peterson
// Date:    August 19, 2005
//
// You are free to use/modify this code but leave this header intact.
// This code is public domain so you are free to use it any of your
// applications (Freeware, Trialware, Commercial, etc.).  FTP Voyager,
// the FTP Voyager Software Development Kit, and FtpTree ActiveX Control
// are not public domain.  Any registration IDs or non-public domain software
// from Rhino Software, Inc. remains copyrighted.  For more information
// refer to the license agreement distributed with the FTP Voyager SDK.
//
// If you decide to use the FTP Voyager Software Development Kit, or FtpTree
// ActiveX control, you must first purchase a license.  For more information
// visit http://www.RhinoSoft.com/
//------------------------------------------------------------------------------
//
// NOTE: This FTP Voyager SDK sample is more complex than the C Sample found in
// C:\Program Files\RhinoSoft.com\FVSDK\SampleC
// The intent of this sample is to cover all of the FTP Voyager SDK's functionality
//
//------------------------------------------------------------------------------

#include "stdafx.h"
#include "SampleCPP.h"
#include "FVSDKLogList.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

/////////////////////////////////////////////////////////////////////////////
// CFVSDKLogList dialog

CFVSDKLogList::CFVSDKLogList()
{
    // init vars
    m_nMaxPromptLen     = 0;
    m_bSetParaFormat    = FALSE;
    m_nLogLines         = 0;

    // set the colors to use in the rich edit control log
    m_clrCommand    = RGB(0, 0x7f, 0x00);       // green
    m_clrResponse   = RGB(0, 0, 0);             // black
    m_clrError      = RGB(0x7f, 0, 0);          // red
    m_clrStatus     = RGB(0, 0, 0xff);          // light blue
} // CFVSDKLogList


CFVSDKLogList::~CFVSDKLogList()
{
} // ~CFVSDKLogList

/////////////////////////////////////////////////////////////////////////////
// CFVSDKLogList log operations

void CALLBACK CFVSDKLogList::LogTextCallback(FVSDK_CALLBACK_DATA pvLogTextData, UINT nType, LPCTSTR pszText)
{
    // if we have a pointer to the control, do the actual callback
    if (pvLogTextData) {

        // log the text to the rich edit control
        ((CFVSDKLogList *) pvLogTextData)->LogText(nType, pszText);
    } // if
} // LogTextCallback


char *detab_str(char* buf, char* str)
{
    int i = -1, ii = 0;

    while (buf[++i]) {
        if (buf[i] == '\t') {
            do  {
                str[ii] = ' ';
                ++ii;
            } while (! ((ii % 8) == NULL));
            --ii;
        } /* if */
        else
            str[ii] = buf[i];
        ++ii;
    } /* while */

    if (ii >= 1)
        str[ii] = '\0';
    return (str);
} /* detab_str */


void CFVSDKLogList::LogText(UINT nType, LPCTSTR pszText)
{
    char        szBuf[4096];
    CString     sStr, sOutput;
    int         anStrs[] = {IDS_COMMAND_PROMPT, 0, 0, IDS_STATUS_PROMPT, IDS_ERROR_PROMPT};

    // is there a prompt associated with the item
    if ((nType < (sizeof(anStrs) / sizeof(anStrs[0]))) && (anStrs[nType])) {

        // load the string from our resources
        sOutput.LoadString(anStrs[nType]);

        // get rid of trailing space
        sOutput.TrimRight();
    } // if

    // get the line of text
    if (*pszText)
        sStr = detab_str((char *) pszText, szBuf);

    // append the rest
    sOutput += ("\t" + sStr);

    // new line
    if (m_nLogLines > 0)
        AppendText("\r\n");

    // new line
    ++m_nLogLines;

    // write it out
    OutputLine(nType, sOutput);
} // LogText

/////////////////////////////////////////////////////////////////////////////
// CFVSDKLogList rich edit control operations

void CFVSDKLogList::SetupCallback(FVSDK_Session* pSession)
{
    // setup the callback function
    pSession->pfnLogText = LogTextCallback;
    pSession->pvLogTextData = this;

    // initialize the rich edit control
    Init();
} // SetupCallback


void CFVSDKLogList::Init()
{
    // initialize if we're up
    if ((m_hWnd) && (::IsWindow(m_hWnd)) && (! m_bSetParaFormat)) {
        LOGFONT     LogFont;
        int         anStrs[] = {IDS_COMMAND_PROMPT, IDS_STATUS_PROMPT, IDS_ERROR_PROMPT, 0};
        int         nIndex = 0;
        CHARFORMAT  cfCharFormat;

        // get the font
        if (SystemParametersInfo(SPI_GETICONTITLELOGFONT, 0, &LogFont, 0)) {

            // done with the font
            if ((HFONT) m_Font)
                m_Font.Detach();

            // create indirect font
            m_Font.CreateFontIndirect(&LogFont);

            // set the default font
            CWnd::SetFont(&m_Font);
        } // if

        // initialize the character format
        cfCharFormat.dwMask = 0xffffffff;
        cfCharFormat.cbSize = sizeof(cfCharFormat);
        GetDefaultCharFormat(cfCharFormat);

        // setup the font
        strcpy(cfCharFormat.szFaceName, LogFont.lfFaceName);

        // no auto color
        cfCharFormat.dwEffects = 0;

        // set the default character format
        SetDefaultCharFormat(cfCharFormat);

        // select the font
        CDC* pDC = GetDC();
        CFont* pFont = pDC->SelectObject(&m_Font);

        // determine the number of pixels per inch
        int nPixPerInch = pDC->GetDeviceCaps(LOGPIXELSX);

        // initialize the tab stop to nothing
        m_pfParaFormat.rgxTabs[0] = 0;

        // determine the width
        while (anStrs[nIndex]) {
            CString sStr;

            // load the string
            sStr.LoadString(anStrs[nIndex]);

            // get the text extent for the string
            CSize Size = pDC->GetOutputTextExtent(sStr);

            // calculate the number of TWIPS for the end of the string
            Size.cx = (int) (((double) Size.cx / (double) nPixPerInch) * (double) 1440 /* twips per inch */);

            // set the max size
            m_pfParaFormat.rgxTabs[0] = max(m_pfParaFormat.rgxTabs[0], Size.cx);

            // max prompt len
            m_nMaxPromptLen = max(m_nMaxPromptLen, sStr.GetLength());

            // next
            ++nIndex;
        } // while

        // restore the font
        if (pFont)
            pDC->SelectObject(pFont);

        // release the DC
        ReleaseDC(pDC);

        // we have one tab stop
        m_pfParaFormat.dwMask = PFM_TABSTOPS;
        m_pfParaFormat.cTabCount = 1;

        // set the size of the structure
        m_pfParaFormat.cbSize = sizeof(m_pfParaFormat);

        // set the default paragraph format
        m_bSetParaFormat = SetParaFormat(m_pfParaFormat);

        // only allow read
        SetReadOnly(TRUE);
    } // if
} // Init


void CFVSDKLogList::AppendText(LPCTSTR lpszText, CHARFORMAT* pcf /*=NULL*/)
{
    long    nEnd = GetTextLength();

    // turn off redraw
    SetRedraw(FALSE);

    // reset the paragraph format
    SetParaFormat(m_pfParaFormat);

    // select the end
    SetSel(nEnd, nEnd);

    // change the selection format?
    if (pcf)
        SetSelectionCharFormat(*pcf);

    // output the text
    ReplaceSel(lpszText);

    // what is the first character of the last line?
    nEnd = LineIndex(LineFromChar(GetTextLength()));

    // move to the first character of the last line, we do this so that we don't get a lot of flutter bang ...
    // ... when lines need to scroll to the right horizontally
    SetSel(nEnd, nEnd);

    // scroll forward one line
    LineScroll(1);

    // turn redraw back on
    SetRedraw(TRUE);

    // redraw the whole window
    Invalidate();
} // AppendText


void CFVSDKLogList::OutputLine(UINT nType, LPCTSTR lpszText)
{
    CHARFORMAT  cf;

    // setup the record
    cf.cbSize = sizeof(cf);
    cf.dwEffects = 0;
    cf.dwMask = CFM_COLOR;

    // setup for the item
    switch (nType) {

        case FVSDK_COMMAND_LOG_TYPE :
            cf.crTextColor = m_clrCommand;
            break;

        case FVSDK_RESPONSE_LOG_TYPE :
        case FVSDK_UNSOLICITED_LOG_TYPE :
            cf.crTextColor = m_clrResponse;
            break;

        case FVSDK_STATUS_LOG_TYPE :
            cf.crTextColor = m_clrStatus;
            break;

        case FVSDK_ERROR_LOG_TYPE :
            cf.crTextColor = m_clrError;
            break;
    } // switch

    // output the text
    AppendText(lpszText, &cf);
} // OutputLine


void CFVSDKLogList::ClearLog()
{
    // select all
    SetSel(0, -1);

    // put in nothing
    ReplaceSel("");

    // nothing in the log
    m_nLogLines = 0;
} // ClearLog