사용자 도구

사이트 도구


kb:rtfwriter

RTF Writer

RTF 파일 쓰기 클래스

C++ Implementation

RTF.h
#ifndef __RTF_H__
#define __RTF_H__
 
#include <string>
#include <set>
 
//////////////////////////////////////////////////////////////////////////////
/// \class RTF
/// \brief 간단한 RTF 파일 리포트 생성을 위한 클래스.
///
/// 어디까지나 간단한 레포트 출력만을 목표로 하는 클래스이기 때문에, 기능이
/// 매우 부실하고 느리다. 하지만 개선해야할 필요성을 못 느끼겠다.
///
/// <pre>
/// RTF rtf;
/// 
/// RTF::STYLES bold;
/// bold.insert(RTF::BOLD);
/// 
/// rtf.add(RTF::DARK_BLUE, bold, "제목");
/// rtf.add("\t첫번째 항목 : %s", "뭐가 좋을까?");
/// rtf.add("\t두번째 항목 : %s", "이것이 좋을까?");
/// 
/// rtf.flush("sample.rtf");
/// </pre>
//////////////////////////////////////////////////////////////////////////////
 
class RTF
{
public:
    /// 색깔 배열
    enum Color
    {
        BLACK = 0, WHITE, GREY, RED, GREEN, BLUE, CYAN, YELLOW, MAGENTA, 
        DARK_RED, DARK_GREEN, DARK_BLUE, LIGHT_RED, LIGHT_GREEN, LIGHT_BLUE,
ORANGE
    };
 
    /// 스타일 배열
    enum Style
    {
        BOLD = 0, ITALIC, UNDERLINE, STRIKE
    };
 
    typedef std::set<Style> STYLES;
 
 
private:
    /// 라인 정의
    typedef struct LINE
    {
        std::string text;    ///< 라인 문자열
        int         color;   ///< 라인 색깔
        STYLES      styles;  ///< 라인 스타일
    } LINE;
 
    typedef std::list<LINE> LINES;
 
    LINES  m_Lines;          ///< 기록할 라인들
    int    m_DefaultColor;   ///< 기본 색깔
    STYLES m_DefaultStyles;  ///< 기본 스타일
 
 
public:
    /// \brief 생성자
    RTF();
 
    /// \brief 소멸자
    virtual ~RTF();
 
 
public:
    /// \brief 기본 색깔과 스타일을 가지는 라인을 추가한다.
    /// \param fmt 가변 인자 포맷
    /// \param ... 가변 인자들
    void add(const char* fmt, ...);
 
    /// \brief 색깔과 스타일을 지정해서 라인을 추가한다.
    /// \param color 색깔
    /// \param styles 스타일
    /// \param fmt 가변 인자 포맷
    /// \param ... 가변 인자들
    void add(Color color, const STYLES& styles, const char* fmt, ...);
 
    /// \brief 가지고 있는 내용을 실제 파일에다가 기록한다.
    /// \param filename 파일 이름
    void flush(const std::string& filename);
 
 
public:
    /// \name 기본 색깔 반환/설정
    /// \{ 
    int getDefaultColor() const { return m_DefaultColor; }
    void setDefaultColor(Color color) { m_DefaultColor = color; }
    /// \} 
 
    /// \name 기본 스타일 반환/설정
    /// \{ 
    const STYLES& getDefaultStyles() const { return m_DefaultStyles; }
    void setDefaultStyles(const STYLES& styles) { m_DefaultStyles = styles; }
    /// \} 
};
 
#endif //__RTF_H__
RTF.cpp
#include "RTF.h"
#include <fstream>
#include <stdio.h>
 
//////////////////////////////////////////////////////////////////////////////
/// \brief 생성자
//////////////////////////////////////////////////////////////////////////////
RTF::RTF()
: m_DefaultColor(BLACK)
{
}
 
//////////////////////////////////////////////////////////////////////////////
/// \brief 소멸자
//////////////////////////////////////////////////////////////////////////////
RTF::~RTF()
{
    m_Lines.clear();
}
 
//////////////////////////////////////////////////////////////////////////////
/// \brief 기본 색깔과 스타일을 가지는 라인을 추가한다.
/// \param fmt 가변 인자 포맷
/// \param ... 가변 인자들
//////////////////////////////////////////////////////////////////////////////
void RTF::add(const char* fmt, ...)
{
    int nchars = 0;
    int buflen = 512;
    char* buf = NULL;
 
    va_list valist;
    va_start(valist, fmt);
 
    do {
        buflen = buflen * 2;
        buf = reinterpret_cast<char*>(::realloc(buf, buflen));
        memset(buf, 0, buflen);
        nchars = vsprintf(buf, fmt, valist);
    } while (nchars < 0 || nchars > buflen);
 
    va_end(valist);
 
    LINE line;
    line.text = buf;
    line.color = m_DefaultColor;
    line.styles = m_DefaultStyles;
    m_Lines.push_back(line);
 
    ::free(buf);
}
 
//////////////////////////////////////////////////////////////////////////////
/// \brief 색깔과 스타일을 지정해서 라인을 추가한다.
/// \param color 색깔
/// \param styles 스타일
/// \param fmt 가변 인자 포맷
/// \param ... 가변 인자들
//////////////////////////////////////////////////////////////////////////////
void RTF::add(Color color, const STYLES& styles, const char* fmt, ...)
{
    int nchars = 0;
    int buflen = 512;
    char* buf = NULL;
 
    va_list valist;
    va_start(valist, fmt);
 
    do {
        buflen = buflen * 2;
        buf = reinterpret_cast<char*>(::realloc(buf, buflen));
        memset(buf, 0, buflen);
        nchars = vsprintf(buf, fmt, valist);
    } while (nchars < 0 || nchars > buflen);
 
    va_end(valist);
 
    LINE line;
    line.text = buf;
    line.color = color;
    line.styles = styles;
    m_Lines.push_back(line);
 
    ::free(buf);
}
 
//////////////////////////////////////////////////////////////////////////////
/// \brief 가지고 있는 내용을 실제 파일에다가 기록한다.
/// \param filename 파일 이름
//////////////////////////////////////////////////////////////////////////////
void RTF::flush(const std::string& filename)
{
    std::ofstream file(filename.c_str(), std::ios::out | std::ios::trunc);
    if (!file) return;
 
    // RTF 헤더를 쓴다.
    file << "{\\rtf1\\ansi\\ansicpg949\\deff0{\\fonttbl{\\f0
굴림체;}}\\fs20\n" << std::endl;
 
    // 컬러 테이블을 쓴다.
    file << "{\\colortbl;" << std::endl;
    file << "\\red255\\green255\\blue255;" << std::endl;
    file << "\\red128\\green128\\blue128;" << std::endl;
    file << "\\red255\\green0\\blue0;" << std::endl;
    file << "\\red0\\green255\\blue0;" << std::endl;
    file << "\\red0\\green0\\blue255;" << std::endl;
    file << "\\red0\\green255\\blue255;" << std::endl;
    file << "\\red255\\green255\\blue0;" << std::endl;
    file << "\\red255\\green0\\blue255;" << std::endl;
    file << "\\red128\\green0\\blue0;" << std::endl;
    file << "\\red0\\green128\\blue0;" << std::endl;
    file << "\\red0\\green0\\blue128;" << std::endl;
    file << "\\red255\\green128\\blue128;" << std::endl;
    file << "\\red128\\green255\\blue128;" << std::endl;
    file << "\\red128\\green128\\blue255;" << std::endl;
    file << "\\red255\\green128\\blue0;" << std::endl;
    file << "}" << std::endl;
 
    for (LINES::const_iterator itr(m_Lines.begin());
        itr != m_Lines.end(); ++itr)
    {
        const LINE& line = *itr;
        file << "{\\pard ";
 
        if (line.styles.find(BOLD) != line.styles.end())
            file << "\\b";
 
        if (line.styles.find(ITALIC) != line.styles.end())
            file << "\\i";
 
        if (line.styles.find(UNDERLINE) != line.styles.end())
            file << "\\ul";
 
        if (line.styles.find(STRIKE) != line.styles.end())
            file << "\\strike";
 
        file << "\\cf" << line.color << " ";
        file << line.text;
        file << "\\par}";
    }
 
    // 끝 부분의 괄호를 써 준다.
    file << "}" << std::endl;
}

kb/rtfwriter.txt · 마지막으로 수정됨: 2014/11/10 19:35 (바깥 편집)