//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop
                                                              
#include "GTree.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TGTree_Form *GTree_Form;
//---------------------------------------------------------------------------


#include "main.h"
#include "ide_main.h"
#include "ide_tree.h"
#include "ide_hint.h"

#include "gui.h"
#include "ide_library.h"
#include "ide_msgbox.h"

//[2009.06.01.월][추가!!!]
#include "editor_top.h"


__fastcall TGTree_Form::TGTree_Form(TComponent* Owner)
        : TForm(Owner)
{
  //[VAR]
  //{
      //배경 bmp 경로.
      AnsiString  bmp_path;

      int         temp;

      int         i;
  //}

  //[환경변수]
  //{
      //[2007.10.02.화][추가!!!]
      IDE_Get_Option(&_ide_option);

  //}

  //[form]
  //{
      this->Left     = 0;
      this->Top      = ((Tide_tree_Form *)Owner)->_captionbar_Form->Top +
                       ((Tide_tree_Form *)Owner)->_captionbar_Form->Height - 1;
      this->Width    = ((TForm *)Owner)->Width;
      this->Height   = ((TForm *)Owner)->Height - this->Top;

      this->Color    = clWhite;

  //}

  //[bmp]
  //{
      //실제 그림 영역을 생성한다.
      _bmp_ = new Graphics::TBitmap;

      //그림 영역 크기 설정.
      _bmp_->Width       = Screen->Width;
      _bmp_->Height      = Screen->Height;

      //24bit bitmap 으로 지정한다.
      _bmp_->PixelFormat = pf24bit;
  //}

  //[배경화면]
  //{
      //------------------------------------------------------------------------------
      //실제 그림 영역을 생성한다.
      _bmp_back_ = new Graphics::TBitmap;

      //[그림 경로]
      //{
          if(IDE_BACKBMP_entire)
          {
            //한개의 그림을 전체영역으로 사용하는 경우.
            _bmp_path = (AnsiString)_ide_option->ideBackpicturePath;

            //[확인]
            //[
                //[2007.12.04.화][추가!!!]
                //그림이 있는지 먼저 확인한다.
                if(FileExists(_bmp_path) != true)
                {
                  //그림이 존재하지 않는 경우는 기본 그림으로 대체한다.
                  _bmp_path = IDE_BACKBMP_entire_path;

                }

                //기본 그림이 있는지 한번더 확인한다.
                if(FileExists(_bmp_path) != true)
                {
                  //기본 그림 역시 존재하지 않는다면 그냥 표시하지 않는다.
                  _bmp_path = "";

                }

            //}

          }
          else
          {
            //지정된 전용 그림을 사용한다.
            _bmp_path = (AnsiString)_ide_option->treeBackPicturePath;

            //[확인]
            //[
                //[2007.12.04.화][추가!!!]
                //그림이 있는지 먼저 확인한다.
                if(FileExists(_bmp_path) != true)
                {
                  //그림이 존재하지 않는 경우는 기본 그림으로 대체한다.
                  _bmp_path = IDE_BACKBMP_tree_path;

                }

                //기본 그림이 있는지 한번더 확인한다.
                if(FileExists(_bmp_path) != true)
                {
                  //기본 그림 역시 존재하지 않는다면 그냥 표시하지 않는다.
                  _bmp_path = "";

                }

            //}

          }

      //}

      //[그림 확인]
      //{
          //[2007.12.04.화][추가!!!]
          //만일 그림이 없는 경우는 처리하지 않는다.
          if(_bmp_path == "")
          {
            //이 경우는 배경을 전부 흰색으로 칠해 주어야 한다.

            //크기지정.
            _bmp_back_->Width  = Screen->Width;
            _bmp_back_->Height = Screen->Height;

            //색칠하기.
            _bmp_back_->Canvas->Brush->Color = clWhite;
            _bmp_back_->Canvas->FillRect(_bmp_back_->Canvas->ClipRect);

          }
          else
          {
            //그림 읽어 들이기.
            BMP_LoadJpeg(_bmp_back_, _bmp_path, Screen->Width, Screen->Height, d_BMP_load_tile);

          }

      //}

      //24bit bitmap 으로 지정한다.
      _bmp_back_->PixelFormat = pf24bit;

      //배경 그림을 밝게 하여 문자가 잘 보기게 만든다.
      BMP_Brightness(_bmp_back_, _ide_option->tree_back_brightness);
      //------------------------------------------------------------------------------

  //}

  //[tree 엄지그림]
  //{
      //[tree-p]
      //{
          //그림 경로 얻기.
          bmp_path = ExtractFilePath(Application->ExeName) + "sysbmp\\tree\\tree_p.bmp";

          //bmp 읽기.
          _Tree_Bmp_Create_Load(&_bmp_tree_p, bmp_path);
      //}

      //[tree-m]
      //{
          //그림 경로 얻기.
          bmp_path = ExtractFilePath(Application->ExeName) + "sysbmp\\tree\\tree_m.bmp";

          //bmp 읽기.
          _Tree_Bmp_Create_Load(&_bmp_tree_m, bmp_path);
      //}

      //[tree-i]
      //{
          //그림 경로 얻기.
          bmp_path = ExtractFilePath(Application->ExeName) + "sysbmp\\tree\\tree_i.bmp";

          //bmp 읽기.
          _Tree_Bmp_Create_Load(&_bmp_tree_i, bmp_path);
      //}

      //[tree-3]
      //{
          //그림 경로 얻기.
          bmp_path = ExtractFilePath(Application->ExeName) + "sysbmp\\tree\\tree_3.bmp";

          //bmp 읽기.
          _Tree_Bmp_Create_Load(&_bmp_tree_3, bmp_path);
      //}

      //[tree-end]
      //{
          //그림 경로 얻기.
          bmp_path = ExtractFilePath(Application->ExeName) + "sysbmp\\tree\\tree_end.bmp";

          //bmp 읽기.
          _Tree_Bmp_Create_Load(&_bmp_tree_end, bmp_path);
      //}
  //}

  //[tree 항목 엄지그림]
  //{
      //[root]{---------------------------------------------------------------------------
      //그림 경로 얻기.
      bmp_path = ExtractFilePath(Application->ExeName) + "sysbmp\\11_11\\root.bmp";
      //bmp 읽기.
      _Tree_Bmp_Create_Load(&(_bmp_item[d_ITEMBMP_root]), bmp_path);
      //[define]{-------------------------------------------------------------------------
      //그림 경로 얻기.
      bmp_path = ExtractFilePath(Application->ExeName) + "sysbmp\\11_11\\define.bmp";
      //bmp 읽기.
      _Tree_Bmp_Create_Load(&(_bmp_item[d_ITEMBMP_define]), bmp_path);
      //[function]{-----------------------------------------------------------------------
      //그림 경로 얻기.
      bmp_path = ExtractFilePath(Application->ExeName) + "sysbmp\\11_11\\function.bmp";
      //bmp 읽기.
      _Tree_Bmp_Create_Load(&(_bmp_item[d_ITEMBMP_function]), bmp_path);
      //[global]{-------------------------------------------------------------------------
      //그림 경로 얻기.
      bmp_path = ExtractFilePath(Application->ExeName) + "sysbmp\\11_11\\global.bmp";
      //bmp 읽기.
      _Tree_Bmp_Create_Load(&(_bmp_item[d_ITEMBMP_global]), bmp_path);
      //[struct]{-------------------------------------------------------------------------
      //그림 경로 얻기.
      bmp_path = ExtractFilePath(Application->ExeName) + "sysbmp\\11_11\\struct.bmp";
      //bmp 읽기.
      _Tree_Bmp_Create_Load(&(_bmp_item[d_ITEMBMP_struct]), bmp_path);
      //[struct-def]{---------------------------------------------------------------------
      //그림 경로 얻기.
      bmp_path = ExtractFilePath(Application->ExeName) + "sysbmp\\11_11\\struct_def.bmp";
      //bmp 읽기.
      _Tree_Bmp_Create_Load(&(_bmp_item[d_ITEMBMP_struct_def]), bmp_path);
      //[union]{--------------------------------------------------------------------------
      //그림 경로 얻기.
      bmp_path = ExtractFilePath(Application->ExeName) + "sysbmp\\11_11\\union.bmp";
      //bmp 읽기.
      _Tree_Bmp_Create_Load(&(_bmp_item[d_ITEMBMP_union]), bmp_path);
      //[union-def]{----------------------------------------------------------------------
      //그림 경로 얻기.
      bmp_path = ExtractFilePath(Application->ExeName) + "sysbmp\\11_11\\union_def.bmp";
      //bmp 읽기.
      _Tree_Bmp_Create_Load(&(_bmp_item[d_ITEMBMP_union_def]), bmp_path);
      //[var]{----------------------------------------------------------------------------
      //그림 경로 얻기.
      bmp_path = ExtractFilePath(Application->ExeName) + "sysbmp\\11_11\\item.bmp";
      //bmp 읽기.
      _Tree_Bmp_Create_Load(&(_bmp_item[d_ITEMBMP_item]), bmp_path);
      //[folder]{-------------------------------------------------------------------------
      //그림 경로 얻기.
      bmp_path = ExtractFilePath(Application->ExeName) + "sysbmp\\11_11\\folder.bmp";
      //bmp 읽기.
      _Tree_Bmp_Create_Load(&(_bmp_item[d_ITEMBMP_folder]), bmp_path);
      //[*.c 문서]{-----------------------------------------------------------------------
      //그림 경로 얻기.
      bmp_path = ExtractFilePath(Application->ExeName) + "sysbmp\\11_11\\file_c.bmp";
      //bmp 읽기.
      _Tree_Bmp_Create_Load(&(_bmp_item[d_ITEMBMP_file_c]), bmp_path);
      //[*.h 문서]{-----------------------------------------------------------------------
      //그림 경로 얻기.
      bmp_path = ExtractFilePath(Application->ExeName) + "sysbmp\\11_11\\file_h.bmp";
      //bmp 읽기.
      _Tree_Bmp_Create_Load(&(_bmp_item[d_ITEMBMP_file_h]), bmp_path);
      //[*.x 문서]{-----------------------------------------------------------------------
      //그림 경로 얻기.
      bmp_path = ExtractFilePath(Application->ExeName) + "sysbmp\\11_11\\file_x.bmp";
      //bmp 읽기.
      _Tree_Bmp_Create_Load(&(_bmp_item[d_ITEMBMP_file_x]), bmp_path);
      //[api]{----------------------------------------------------------------------------
      //그림 경로 얻기.
      bmp_path = ExtractFilePath(Application->ExeName) + "sysbmp\\11_11\\api.bmp";
      //bmp 읽기.
      _Tree_Bmp_Create_Load(&(_bmp_item[d_ITEMBMP_api]), bmp_path);
      //}---------------------------------------------------------------------------------
  //}

  //[tree 초기화]
  //{
      for(i = 0; i < d_TREE_max; i++)
      {
        //[초기화]
        //{
            //[2009.09.13.일][중요추가!!!]{----------------------------------------------
            //처음에는 동적생성되므로 관련 변수를 초기화 주어야 한다.
            //_Tree_Init() 함수 안에서 동적 생성시 _tree[i].items 이 NULL 이 아닌 경우는
            //자동으로 삭제하기 때문에 반드시 NULL 로 초기화 해주어야 한다.
            //}--------------------------------------------------------------------------

            _tree[i].items = NULL;
            _tree[i].size  = 0;

        //}

        //처음에는 아무 항목도 없으므로 생성하지 않고 0 을 입력한다.
        _Tree_Init(&(_tree[i]), 0);

      }

      //기본 적으로 0 번 tree 를 보여준다.
      _tree_select_index = 0;
  //}

  //[글꼴 설정]
  //{
      //[기본 끌꼴 등록]{------------------------------------------------
      //모든 프로그램에서 기본적으로 사용하는 [system 글꼴] 을 등록한다.
      FONTPACK_SetDefault(&_font);
      //}----------------------------------------------------------------

      _font.margin_size   = 0;

      _font.offset_left   = 0;
      _font.offset_right  = 0;
      _font.offset_top    = 1;
      _font.offset_bottom = 0;

      //[2010.01.26.화][추가!!!]{---
      _font.en_offset_left  = 0;
      _font.en_offset_right = 0;
      //}---------------------------

      //[행높이 구하기]{-----------------------------------------------------------------------------------
      //[글꼴] 의 크기를 알기 위한 CRLF 문자 출력.
      FONT_Out_Moonja(_bmp_, &_font, 0, 0, IDE_COLOR_1, IDE_COLOR_2, false, 0x0d0a, &temp, &_line_height);
      //---------------------------------------------------------------------------------------------------
  //}

  //[좌표정보 초기화]
  //{
      //------------------------------------
      //tree 를 그릴 기본 영역의 절대 원점.
      _item_xy.tree_x = 3;
      _item_xy.tree_y = 1;

      _item_xy.line_height = _line_height;
      //------------------------------------
  //}

  //[컨트롤 그리기]
  //{
      //기본적으로 0 번 tree 를 표시한다.
      _TreeView(_tree_select_index, false);
  //}

  //[빠른항목]
  //{
      //[2009.02.02.월][추가!!!]
      
      _popupMenu = new Tide_popup_Form(Application);

      //[초기화]
      //{
          //[임시항목]
          //{
              _popupMenu->_subitem.str[0]       = " 추가 ";
              _popupMenu->_subitem.str[1]       = " 삭제 ";
              _popupMenu->_subitem.str[2]       = " .하위항목 모두열기 ";
              _popupMenu->_subitem.str[3]       = "  하위항목 모두닫기 ";
              _popupMenu->_subitem.str[4]       = " .같은단계 모두열기 ";
              _popupMenu->_subitem.str[5]       = "  같은단계 모두닫기 ";
              _popupMenu->_subitem.str[6]       = " .전체 열기 ";
              _popupMenu->_subitem.str[7]       = "  전체 닫기 ";

              _popupMenu->_subitem.count        = 8;
              _popupMenu->_subitem.select_index = -1;

          //}

          //[동작함수 등록]
          //{
              _popupMenu->_EVENT_ItemSelect = _EVENT_PopupMenu_Prj;

          //}

          //반드시 한번만 초기화 해야 한다.
          _popupMenu->_Init();

      //}

  //}

  return;

}

__fastcall TGTree_Form::~TGTree_Form(void)
{
  //[소멸]

  return;

  //[VAR]
  //{
      int  i;
  //}

  delete _bmp_;
  delete _bmp_back_;

  delete _bmp_tree_p;
  delete _bmp_tree_m;
  delete _bmp_tree_i;
  delete _bmp_tree_3;
  delete _bmp_tree_end;

  for(i = 0; i < d_ITEMBMP_max; i++)
  {
    delete _bmp_item[i];

  }

  //[주의!!!]
  //{
      //_popupMenu = new Tide_popup_Form(Application); 로 이 프로그램 전체 단위로
      //동적 생성 했으므로 여기서 삭제하면 에러가 된다.
      //그냥 두면 프로그램 차원에서 자동으로 삭제 된다.
      //delete _popup_menu_;
  //}
    
  return;

}

//[서브클래싱]------------------------------------------------------------------

void __fastcall TGTree_Form::WndProc(Messages::TMessage  &Message)
{
  //[2006.12.12.화][생성!!!]{-----------------------------------------------------
  //TForm 의 경우는 바탕을 칠하고 OnPaint() 를 발생하게 되므로 실제 _Draw() 를
  //OnPaint() 에서 사용하는 경우는 크기가 변경되는 경우 바로 칠해지지 않아서
  //하얀색 바탕이 그대로 나오게 되어 보기 좋지 않게 된다.
  //따라서 TForm 자체의 바탕을 그리는 WM_ERASEBKGND 에서 바로 _Draw() 를 사용하여
  //그리고 OnPaint() 는 처리하지 않는다.
  //C++Builder 와 같이 완벽하게 처리되는 깜박임이 전혀 없는 화면을 만들수 있다.
  //}-----------------------------------------------------------------------------

  switch(Message.Msg)
  {
    case  WM_ERASEBKGND :
    {
      _Draw();

      //바로 죵료하지 않으면 WM_ERASEBKGND 메세지가 다음 TForm::WndProc(Message); 에서
      //다시 처리 되어 TForm->Color 로 칠해지게 되어 _Draw() 로 그린 것이 다 지워지므로
      //바로 종료한다.
      return;

    } break;

    case  WM_KILLFOCUS :
    {




    } break;

  }

  //[기본처리]
  //{
      //기본 메세지는 반드시 처리 되어야 한다.
      TForm::WndProc(Message);
  //}

  return;

}

//------------------------------------------------------------------------------

void __fastcall TGTree_Form::_TreeView(int   pTREEindex,
                                           bool  pCONTROL)
{
  //[2006.11.20.월][생성!!!]{----------------
  //지정된 순번의 tree 를 표시한다.
  //이는 tree 가 tab 으로 선택되기 때문이다.
  //}----------------------------------------

  //[VAR]
  //{
      int   w, h;
  //}

  //[바탕색]
  //{

      //[배경 그림으로 지우기]
      //{
          //배경 그림으로 바탕을 지운다.
          BitBlt(_bmp_->Canvas->Handle, 0, 0,
                 _bmp_->Width, _bmp_->Height,
                 _bmp_back_->Canvas->Handle, 0, 0, SRCCOPY);
      //}
  //}

  //[테두리 만들기]
  //{
      _bmp_->Canvas->Pen->Color   = _ide_option->color_0;
      _bmp_->Canvas->Pen->Width   = 1;
      _bmp_->Canvas->Brush->Style = bsClear;
      _bmp_->Canvas->Rectangle(_bmp_->Canvas->ClipRect);
  //}

  //[tree 표시하기]
  //{
      //지정 탭에 따라 표시해 주어야 한다.
      _Tree(&(_tree[pTREEindex]), pCONTROL);
  //}

  //[view]{-------------
  //그린 것을 보여준다.
  _Draw();
  //}-------------------

  _Scroll_Set();


  return;

}

void __fastcall TGTree_Form::_Tree(struct TREE  *pTREE,
                                       bool          pCONTROL)
{
  //[2006.11.16.목][생성!!!]{-------------------------------------------------------------
  //tree 구조체 정보를 참고하여 tree 를 그려준다.
  //사용한 [엄지그림] 은 투명하게 그려져야 하므로 BMP_Copy_Transparent() 함수를 사용한다.
  //
  //[2006.11.23.목][수정!!!]
  //1) 현재 선택되 있는 행이 '+', '-' 인 경우는 즉시 서로를 변환하고 해당 처리를 한다.
  //   또한, [선택행] 에 해당하는 선택된 itemindex 값도 같이 구해서 기록해 주어야 한다.
  //2) item 에 해당하지 않는 행을 선택한 경우는 선택된 행이 없는것으로 한다.
  //3) 선택된 [항목] 의 경우는 [문자열] 을 반전한다.

  //[2007.04.03.수][수정!!!]
  //[선택] 된 항목의 배경을 테마색으로 바꾸었다.(너무 진한것은 보기 좋지 않아서...)
  //}-------------------------------------------------------------------------------------

  //[VAR]
  //{
      int  i;

      //보이는 행중 처리되는 행을 가진다.(BASE : 0);
      //모든 item 이 표시되는 것은 아니므로 index 와 혼동하지 않도록 주의한다.
      int  line_number;

      //[옹이] 가 가진 직계 [가지] 의 마지막 itemindex.
      int  node_end_itemindex;
      //[옹이] 가 가지고 있는 가장 마지막 item 의 itemindex.
      int  node_last_itemindex;

      int  w, h;

      int  level;

      //실제 값은 보존되야 하므로 같은 이름의 값을 이 변수에 복사하여 사용한다.
      int  select_line      = -1;
      int  select_itemindex = -1;

      //[문자열] 이 표시될 위치를 기록한다.
      //이는 [항목-엄지그림] 의 표시 유/무 에 따라 문자열의 표시 위치가 바뀌기 때문이다.
      int  text_x;
      int  text_y;

      //[2007.04.03.수][수]
      int   color_select;

      //[2009.06.02.화][추가!!!]
      int   fontColor;

  //}

  //[선택색 얻기]
  //{
      //[2007.04.03.수][추가!!!]
      //선택된 항목의 바탕색을 테마색으로 바꾼다.
      BMP_Get_Bright_Color(_ide_option->color_0, IDE_BRIGHT_tree_select, &color_select);
  //}

  //[초기화]
  //{
      select_line = pTREE->select_line;
  //}

  for(i = 0, line_number = 0;
      i < pTREE->items_count;
      i++, line_number++)
  {
    //[문자색 구분]
    //{
        //[2009.06.02.화][추가!!!]{--------------------------------------
        //가시성을 높이기 위하여 각각의 항목마다 다른 문자색을 적용한다.
        //}--------------------------------------------------------------

        if(pTREE->items[i].bmpindex == d_ITEMBMP_folder) fontColor = IDE_COLOR_4;//_ide_option->color_0;
        else                                             fontColor = IDE_COLOR_1;

    //}

    //0, 1 번 줄기는 앞에 세로 줄기가 올수 없다.
    if(pTREE->items[i].level >= 2)
    {
      //[item 앞의 모든 세로 줄기 표시]
      //{
          //[설명!!!]{--------------------------------------------------
          //현재 item 의 지나가는 세로 줄기를 그려주되,
          //앞의 level 의 모든 줄기가 [열려] 있는 경우만 그려주면 된다.
          //}-----------------------------------------------------------

          for(//현재 item 의 level 보다 2 단계 높은 level 부터 검사한다.
              level = pTREE->items[i].level - 2;
              //0 번 줄기까지 전부 검사하여 처리한다.
              level >= 0;
              level--)
          {
            if(((pTREE->level_open_close_bit >> level) & 1) == 1)
            {
              //줄기가 현재 [열려] 있는 상태이므로 세로 줄기를 그려준다.

              //[좌표정보 구하기]
              //{
                  //----------------------------------
                  _item_xy.line_number = line_number;
                  _item_xy.item_level  = level;

                  _Tree_Get_XY(&_item_xy);
                  //----------------------------------
              //}

              //[그리기]
              //{
                  //---------------------------------------------------------------------------
                  //세로 줄기를 그린다.
                  _bmp_->Canvas->Pen->Color   = _ide_option->color_0;
                  _bmp_->Canvas->Pen->Width   = 1;

                  _bmp_->Canvas->MoveTo(_item_xy.vline_top_x, _item_xy.vline_top_y);
                  _bmp_->Canvas->LineTo(_item_xy.vline_bottom_x, _item_xy.vline_bottom_y + 1);
                  //---------------------------------------------------------------------------
              //}
            }

          }
      //}
    }

    //0 번 줄기는 앞에 아무것도 배치하지 않으므로 처리하지 않는다.
    if(pTREE->items[i].level > 0)
    {
      //[item 바로 앞 기호]
      //{
          //[좌표정보 구하기]
          //{
              //------------------------------------------------
              _item_xy.line_number = line_number;
              _item_xy.item_level  = pTREE->items[i].level - 1;

              _Tree_Get_XY(&_item_xy);
              //------------------------------------------------
          //}

          //[그리기]
          //{
              //2 종류가 있으므로 구분하여 처리한다.

              //[[옹이] 의 줄기 정보 얻기]
              //{
                  //이 item 이 해당 [옹이] 의 마지막 직계 item 인지 구분하여 처리한다.
                  _Tree_Get_ThisItemNode_LastItemIndex(pTREE, i, NULL, &node_end_itemindex, &node_last_itemindex);
                  
              //}

              if((i == node_end_itemindex))// &&
                 //(pTREE->items[i].level != pTREE->items[node_last_itemindex].level ))

              {
                //이 item 이 [옹이] 의 마지막 item 이므로 <끝> [엄지그림] 을 배치한다.

                //[선 그리기]
                //{
                    _bmp_->Canvas->Pen->Color   = _ide_option->color_0;
                    _bmp_->Canvas->Pen->Width   = 1;

                    //투명하게 그리므로 중간부터 그리면 보인다.
                    //그러므로, [엄지그림] 의 아래 테두리 부터 그린다.
                    _bmp_->Canvas->MoveTo(_item_xy.vline_top_x, _item_xy.vline_top_y);
                    _bmp_->Canvas->LineTo(_item_xy.icon_top_x, _item_xy.icon_top_y);

                    _bmp_->Canvas->MoveTo(_item_xy.icon_right_x, _item_xy.icon_right_y);
                    _bmp_->Canvas->LineTo(_item_xy.hline_right_x + 1, _item_xy.hline_right_y);
                //}

                //[엄지그림 표시]
                //{
                    BMP_Copy_Transparent(_bmp_tree_end, 0, 0, _bmp_tree_end->Width, _bmp_tree_end->Height,
                                         _bmp_, _item_xy.icon_x, _item_xy.icon_y, 9, 9,
                                         clWhite);
                //}

                //[줄기 close 처리]
                //{
                    //현재 level 의 줄기가 [닫혀] 있는 상태임을 기록한다.
                    //item 이 매달린 [옹이] 의 줄기가 되므로 level 이 하나 높다.
                    pTREE->level_open_close_bit &= (~(1 << (pTREE->items[i].level - 1)));
                //}

              }
              else
              {
                //item 이 계속되는 경우로 <3발이> [엄지그림] 을 배치한다.

                //[선 그리기]
                //{
                    _bmp_->Canvas->Pen->Color   = _ide_option->color_0;
                    _bmp_->Canvas->Pen->Width   = 1;

                    //투명하게 그리므로 중간부터 그리면 보인다.
                    //그러므로, [엄지그림] 의 아래 테두리 부터 그린다.
                    _bmp_->Canvas->MoveTo(_item_xy.vline_top_x, _item_xy.vline_top_y);
                    _bmp_->Canvas->LineTo(_item_xy.icon_top_x, _item_xy.icon_top_y);

                    _bmp_->Canvas->MoveTo(_item_xy.icon_right_x, _item_xy.icon_right_y);
                    _bmp_->Canvas->LineTo(_item_xy.hline_right_x + 1, _item_xy.hline_right_y);

                    _bmp_->Canvas->MoveTo(_item_xy.icon_bottom_x, _item_xy.icon_bottom_y);
                    _bmp_->Canvas->LineTo(_item_xy.vline_bottom_x, _item_xy.vline_bottom_y + 1);
                //}

                //[엄지그림 표시]
                //{
                    BMP_Copy_Transparent(_bmp_tree_3, 0, 0, _bmp_tree_3->Width, _bmp_tree_3->Height,
                                         _bmp_, _item_xy.icon_x, _item_xy.icon_y, 9, 9,
                                         clWhite);
                //}
              }
          //}
      //}
    }

    //[좌표정보 구하기]
    //{
        //--------------------------------------------
        _item_xy.line_number = line_number;
        _item_xy.item_level  = pTREE->items[i].level;

        _Tree_Get_XY(&_item_xy);
        //--------------------------------------------
    //}

    //[선택 itemindex 구하기]
    //{
        //--------------------------------------------------------------
        //현재 tree 의 선택된 [행] 에 해당하는 itemindex 인지 검사한다.
        if(select_line == line_number)
        {
          //[기록]
          //{
              //이 경우는 현재 [항목] 이 지정행의 [항목] 이 된다.
              //현재 [항목] 이 선택된 것으로 보고 해당 index 를 기록한다.
              pTREE->select_itemindex = i;
          //}

          select_itemindex = i;
          select_line      = -1;

        }
        //--------------------------------------------------------------
    //}

    if(pCONTROL == true)
    {
      //[설명!!!]{--------------------------------------------------
      //아래의 동작은 단순히 tree 를 그릴때는 사용되지 않아야 하고,
      //반드시 [항목] 을 선택한 경우만 처리 되어야 한다.
      //즉, '+'. '-' 전환 동작이 필요한 경우만 처리되어야 한다.
      //}-----------------------------------------------------------

      //[선택 [항목] 변환 처리]
      //{
          //------------------------------------------
          //이는 '+', '-' 의 경우 상호 전환을 해준다.
          if(select_itemindex == i)
          {
            //'+', '-' 의 변환 처리를 수행한다.
            switch(pTREE->items[i].kind)
            {
              case '+' :
              {
                //'-' 로 전환한다.
                pTREE->items[i].kind = '-';

              } break;

              case '-' :
              {
                //'+' 로 전환한다.
                pTREE->items[i].kind = '+';

              } break;

            }

            select_itemindex = -1;

          }
          //------------------------------------------
      //}
    }

    //[항목-엄지그림]
    //{
        //--------------------------------------------------------------------------------
        //지정된 [항목-엄지그림] 이 있다면 표시한다.

        if(pTREE->items[i].bmpindex >= 0)
        {
          //[엄지그림] 을 표시한다.
          BMP_Copy_Transparent(_bmp_item[pTREE->items[i].bmpindex], 0, 0,
                               _bmp_item[pTREE->items[i].bmpindex]->Width,
                               _bmp_item[pTREE->items[i].bmpindex]->Height,
                               _bmp_, _item_xy.item_icon_x, _item_xy.item_icon_y, 11, 11,
                               clWhite);

        }
        //--------------------------------------------------------------------------------
    //}

    //[문자열 표시 위치 기록]
    //{
        //--------------------------------------------------------------
        //[항목-엄지그림] 을 표시한 경우는 문자열의 표시 위치가 바뀐다.
        //따라서 문자열 표시 위치를 기록한다.
        if(pTREE->items[i].bmpindex == -1)
        {
          //[항목-엄지그림] 을 사용하지 않은 경우는 기본 위치가 된다.
          text_x = _item_xy.text_x;
          text_y = _item_xy.text_y;

        }
        else
        {
          text_x = _item_xy.text2_x;
          text_y = _item_xy.text2_y;

        }
        //--------------------------------------------------------------
    //}

    switch(pTREE->items[i].kind)
    {
      case '+' :
      {
        //[닫힌 옹이]{-----------------------------------------------------------------
        //다른 것과 달리 해당 [옹이] 만 표시하고 하위 [항목] 은 표시 하지 않아야 한다.
        //[옹이] 의 정보를 추출하여 가지고 있는 가지의 수를 알고 이 부분은 건너 뛴다.
        //}----------------------------------------------------------------------------

        //[그리기]
        //{
            //[엄지그림] 을 표시한다.
            BMP_Copy_Transparent(_bmp_tree_p, 0, 0, _bmp_tree_p->Width, _bmp_tree_p->Height,
                                 _bmp_, _item_xy.icon_x, _item_xy.icon_y, 9, 9,
                                 clWhite);

            //[선택구분처리]
            //{
                //[주의!!!]{---------------------------------------------------------------------
                //select_index 값은 나중에 수정되는 값이므로 이전 값이 적용된후 수정된 값이 다시
                //적용되어 중복 사용될수 있다.
                //따라서 line 관련 값으로 바로 비교 할수 있도록한다.
                //}------------------------------------------------------------------------------

                //현 항목이 선택된 경우는 문자열을 반전한다.
                if(pTREE->select_line != line_number)
                {
                  //문자열을 표시한다.
                  FONT_Out_StyleString2(_bmp_, &_font, text_x, text_y,
                                        fontColor, IDE_COLOR_2, true,
                                        d_FONTSTYLE_default,
                                        pTREE->items[i].txt,
                                        d_FONT_underline_no, true, 0, IDE_COLOR_1,
                                        &w, &h);

                }
                else
                {
                  //이 경우는 [선택] 된 것으로 보고 문자열을 반전표시한다.
                  //문자열을 표시한다.
                  FONT_Out_StyleString2(_bmp_, &_font, text_x, text_y,
                                        IDE_COLOR_3, color_select/*IDE_COLOR_0*/, false,
                                        d_FONTSTYLE_default,
                                        pTREE->items[i].txt,
                                        d_FONT_underline_no, true, 0, IDE_COLOR_1,
                                        &w, &h);

                }
            //}
        //}

        //[하위 항목 처리]
        //{
            //[+] 옹이의 경우는 자신만 표시하고, 하위 항목은 표시 하지 않아야 한다.

            //이 [옹이] 가 가진 가장 마지막 item 의 index 를 얻는다.
            _Tree_Get_Node_LastItemIndex(pTREE, i, &node_end_itemindex, &node_last_itemindex);

            //마지막 하위 항목까지 처리하지 않아야 한다.
            i = node_last_itemindex;
        //}

      } break;

      case '-' :
      {
        //[열린 옹이]{-----------------------------------------
        //[옹이] 자신은 물론이고 하위 모든 [항목] 도 표시한다.
        //}----------------------------------------------------

        //[그리기]
        //{
            //줄기를 그린다.
            _bmp_->Canvas->Pen->Color   = _ide_option->color_0;
            _bmp_->Canvas->Pen->Width   = 1;
            //투명하게 그리므로 중간부터 그리면 보인다.
            //그러므로, [엄지그림] 의 아래 테두리 부터 그린다.
            _bmp_->Canvas->MoveTo(_item_xy.icon_bottom_x, _item_xy.icon_bottom_y);
            _bmp_->Canvas->LineTo(_item_xy.vline_bottom_x, _item_xy.vline_bottom_y + 1);

            //[엄지그림] 을 표시한다.
            BMP_Copy_Transparent(_bmp_tree_m, 0, 0, _bmp_tree_m->Width, _bmp_tree_m->Height,
                                 _bmp_, _item_xy.icon_x, _item_xy.icon_y, 9, 9,
                                 clWhite);

            //[선택구분처리]
            //{
                //현 항목이 선택된 경우는 문자열을 반전한다.
                if(pTREE->select_line != line_number)
                {
                  //문자열을 표시한다.
                  FONT_Out_StyleString2(_bmp_, &_font, text_x, text_y,
                                        fontColor, IDE_COLOR_2, true,
                                        d_FONTSTYLE_default,
                                        pTREE->items[i].txt,
                                        d_FONT_underline_no, true, 0, IDE_COLOR_1,
                                        &w, &h);

                }
                else
                {
                  //이 경우는 [선택] 된 것으로 보고 문자열을 반전표시한다.
                  //문자열을 표시한다.
                  FONT_Out_StyleString2(_bmp_, &_font, text_x, text_y,
                                        IDE_COLOR_3, color_select/*IDE_COLOR_0*/, false,
                                        d_FONTSTYLE_default,
                                        pTREE->items[i].txt,
                                        d_FONT_underline_no, true, 0, IDE_COLOR_1,
                                        &w, &h);

                }
            //}
        //}

        //[줄기 open 처리]
        //{
            //현재 level 의 줄기가 [열려] 있는 상태임을 기록한다.
            pTREE->level_open_close_bit |= (1 << pTREE->items[i].level);

        //}

      } break;

      case '.' :
      {
        //[단순 항목]{--------------------
        //해당 [항목] 을 무조건 표시한다.
        //}-------------------------------

        //[그리기]
        //{
            //[엄지그림] 을 표시한다.
            BMP_Copy_Transparent(_bmp_tree_i, 0, 0, _bmp_tree_i->Width, _bmp_tree_i->Height,
                                 _bmp_, _item_xy.icon_x, _item_xy.icon_y, 9, 9,
                                 clWhite);

            //[선택구분처리]
            //{
                //현 항목이 선택된 경우는 문자열을 반전한다.
                if(pTREE->select_line != line_number)
                {
                  //문자열을 표시한다.
                  FONT_Out_StyleString2(_bmp_, &_font, text_x, text_y,
                                        fontColor, IDE_COLOR_2, true,
                                        d_FONTSTYLE_default,
                                        pTREE->items[i].txt,
                                        d_FONT_underline_no, true, 0, IDE_COLOR_1,
                                        &w, &h);

                }
                else
                {
                  //이 경우는 [선택] 된 것으로 보고 문자열을 반전표시한다.
                  //문자열을 표시한다.
                  FONT_Out_StyleString2(_bmp_, &_font, text_x, text_y,
                                        IDE_COLOR_3, color_select/*IDE_COLOR_0*/, false,
                                        d_FONTSTYLE_default,
                                        pTREE->items[i].txt,
                                        d_FONT_underline_no, true, 0, IDE_COLOR_1,
                                        &w, &h);

                }
            //}
        //}

      } break;

    }

  }

  //[가장 마지막 행을 기록한다]
  //{
      //-----------------------------------------------------------------------------
      //이는 그려진 아래의 무효 영역을 선택한 경우 이전에 선택된 [항목] 의 [선택] 을
      //해제 시키는 작업을 수월하게 하기 위한 것이다.
      pTREE->last_line = line_number
                         //위의 for 문에서 ++  된후 종료하므로 -1 을 해준다.
                         - 1;
      //-----------------------------------------------------------------------------
  //}

  return;

}

void __fastcall TGTree_Form::_Tree_Get_XY(struct ITEMXY  *prITEMxy)
{
  //[2006.11.20.월][생성!!!]{-----------------------------------------------
  //전달된 기본정보를 사용하여 item 하나를 그려주기 위한 여러 [좌표정보] 를
  //계산하여 반환한다.
  //}-----------------------------------------------------------------------

  //[VAR]
  //{
      //org_x, org_y 의 값을 가진다.
      //표기를 단순하게 하기 위한 것이다.
      //실제 item 한개를 그리는 자체 기준점이 된다.
      int X, Y;
  //}

  //[기본 행 정보 구하기]
  //{
      //------------------------------------------------------------------------
      prITEMxy->mh = (prITEMxy->line_height / 2) + (prITEMxy->line_height % 2);
      prITEMxy->ml = prITEMxy->line_height - prITEMxy->mh;
      //------------------------------------------------------------------------
  //}

  //[기준원점 구하기]
  //{
      //------------------------------------------------------------------------------------
      prITEMxy->org_x = prITEMxy->tree_x + (prITEMxy->item_level * 11);
      prITEMxy->org_y = prITEMxy->tree_y + (prITEMxy->line_number * prITEMxy->line_height);

      X = prITEMxy->org_x;
      Y = prITEMxy->org_y;
      //------------------------------------------------------------------------------------
  //}

  //[좌표 계산]
  //{
      //--------------------------------------------------------
      prITEMxy->icon_x         = X;
      prITEMxy->icon_y         = Y + prITEMxy->mh - 5;
      //--------------------------------------------------------
      prITEMxy->icon_middle_x  = X + 4;
      prITEMxy->icon_middle_y  = Y + prITEMxy->mh - 1;
      //--------------------------------------------------------
      prITEMxy->icon_top_x     = X + 4;
      prITEMxy->icon_top_y     = Y + prITEMxy->mh - 5;
      //--------------------------------------------------------
      prITEMxy->icon_right_x   = X + 8;
      prITEMxy->icon_right_y   = Y + prITEMxy->mh - 1;
      //--------------------------------------------------------
      prITEMxy->icon_bottom_x  = X + 4;
      prITEMxy->icon_bottom_y  = Y + prITEMxy->mh + 4 - 1;
      //--------------------------------------------------------
      prITEMxy->vline_top_x    = X + 4;
      prITEMxy->vline_top_y    = Y;
      //--------------------------------------------------------
      prITEMxy->vline_bottom_x = X + 4;
      prITEMxy->vline_bottom_y = Y + prITEMxy->line_height - 1;
      //--------------------------------------------------------
      prITEMxy->hline_right_x  = X + 11;
      prITEMxy->hline_right_y  = Y + prITEMxy->mh - 1;
      //--------------------------------------------------------
      prITEMxy->text_x         = X + 11;
      prITEMxy->text_y         = Y;
      //--------------------------------------------------------
      prITEMxy->text2_x        = X + 25;
      prITEMxy->text2_y        = Y;
      //--------------------------------------------------------
      prITEMxy->item_icon_x    = X + 11;
      prITEMxy->item_icon_y    = Y + prITEMxy->mh - 6;
      //--------------------------------------------------------
  //}

  return;

}

void __fastcall TGTree_Form::_Item_Init(struct TREEITEM  *pTREEitem)
{
  //[2006.11.19.일][생성!!!]{--------------------------
  //[항목] 한개를 넘겨 받아서 기본 값으로 초기화 한다.
  //}--------------------------------------------------

  pTREEitem->kind     = '.';
  pTREEitem->level    = 0;
  pTREEitem->name[0]  = '\0';
  pTREEitem->txt[0]   = '\0';

  //기본적으로 [항목-엄지그림] 은 사용하지 않는 것으로 한다.
  pTREEitem->bmpindex = -1;

  //[2009.01.27.화][추가!!!]
  //{
      //{DATABASE} 의 record-index 를 초기화 한다(기보적으로 아무것도 해당하지 않는다).

      pTREEitem->dbRecIndex = -1;

  //}

  return;

}

void __fastcall TGTree_Form::_Item_Text(struct TREEITEM  *pTreeItem,
                                            char             *pText)
{
  //[2009.10.04.일][생성!!!]{-----------------------------------------------
  //<text> 항목을 추가 하는 경우는 반드시 이 함수를 사용해서 처리해야 한다.
  //그렇지 않을 경우 저장공간을 넘는 문자열의 경우는 문제가 될수 있다.
  //이 함수는 저장공간을 넘는 문자열의 경우는 자동으로 공간의 크기에 맞게
  //"..." 를 뒤에 붙여 보기 좋게 잘라내준다.
  //}-----------------------------------------------------------------------

  //[VAR]
  //{
      int   textLength;

  //}

  //문자열 길이 얻기.
  textLength = STR_Length(pText);


  //문자열 끝의 '\0' 도 저장해야 하므로---------v
  if(textLength <= (OPT_Tree_Item_Text_length - 1))
  {
    //이 경우는 그대로 저장하면 된다.

    STR_Assign(pTreeItem->txt, pText);

  }
  else
  {
    //[설명!!!]{--------------------------------------------------------------------------------
    //이 경우는 저장 공간을 초과 하므로 <OPT_Tree_Item_Text_length> 크기에서 "..." 와 '\0' 까지
    //포함하여 4 Byte 를 제외한 길이만큼만 저장한다.
    //즉, 무조건 <OPT_Tree_Item_Text_length> 크기에 딱 맞춘다.
    //}-----------------------------------------------------------------------------------------

    STR_SetLength(pText, (OPT_Tree_Item_Text_length - 4),
                  //채울 문자는 큰 의미는 없으므로 그냥 공백으로 처리한다.
                  ' ',
                  pTreeItem->txt);

    //뒤에 "..." 를 추가한다.
    STR_Add(pTreeItem->txt, "...");

  }

  return;

}

void __fastcall TGTree_Form::_Tree_Delete(struct TREE  *pTree)
{
  //[2009.09.13.일][생성!!!]{-----------------------------------------
  //현재 <Tree> 의 항목저장소를 전부 삭제하고 관련 초기화를 수행한다.
  //}-----------------------------------------------------------------

  //이미 생성된 것이 있다면 삭제한다.
  if(pTree->items != NULL)
  {
    //이미 생성된 것을 삭제한다.
    delete [] pTree->items;

    //포인터를 초기화 한다.
    pTree->items = NULL;

    //저장소 크기를 초기화한다.
    pTree->size = 0;

  }

  return;

}

void __fastcall TGTree_Form::_Tree_Create(struct TREE  *pTree,
                                              //생성할 크기(관리할 항목 총수).
                                              int           pSize)
{
  //[2009.09.13.일][생성!!!]{----------------------------------------------------------
  //<Tree> 를 지정 크기로 동적 생성하되, 이전에 생성한 것이 있다면 삭제해 주어야 한다.
  //}----------------------------------------------------------------------------------

  //[VAR]
  //{
      int  i;
  //}

  //[삭제]
  //{
      //이미 생성된 것이 있다면 자동으로 삭제해준다.
      _Tree_Delete(pTree);

  //}

  //[<Tree> 동적 생성]
  //{
      //초기에는 지정 크기로 동적 생성한다(향후 더 커질수 있다).
      pTree->items = new  struct TREEITEM [pSize];

      //생성한 크기로 초기화 한다.
      pTree->size  = pSize;

  //}

  return;

}

void __fastcall TGTree_Form::_Tree_ReSize(struct TREE  *pTree)
{
  //[2009.09.13.일][생성!!!]{------------------------------------------------------
  //생성된 <Tree> 에 추가할 공간이 있는지 먼저 검사하고, 더이상 저장할 곳이 없다면
  //지정 크기만큼 더해서 다시 생성해 준다.
  //}------------------------------------------------------------------------------

  //[VAR]
  //{
      //새로 생성된 저장공간.
      struct TREEITEM  *newItems = NULL;

      //새로생성된 크기.
      int               newSize  = 0;

      int               i;

  //}

  //[저장할 공간이 있는가?]
  //{
      //총 크기와 저장된 항목수가 같은 경우는 이미 꽉찬 것이다.
      //아직 저장할 공간이 있다면 이 함수를 여기서 종료한다.
      if(!(pTree->size <= pTree->items_count)) return;

  //}

  //[!]{-------------------------------------------------------------
  //여기까지 온 것은 이미 저장공간이 꽉찬 것으로 다시 생성해야 한다.
  //}----------------------------------------------------------------

  //[다시 생성]
  //{
      //[!]{------------------------------------------------
      //일단 새로 공간을 생성한다.
      //<새크기> = <현재크기> + <지정추가크기> 로 생성한다.
      //}---------------------------------------------------

      //새로 생성될 크기를 계산한다.
      newSize = pTree->size + Opt_Tree_AddSize;

      newItems = new  struct TREEITEM [newSize];

  //}

  //[복사]
  //{
      //새로 생성된 곳으로 기존의 자료를 복사한다.

      for(i = 0; i < pTree->size; i++)
      {
        newItems[i] = pTree->items[i];

      }

  //}

  //[삭제]
  //{
      //이미 생성된 것이 있다면 자동으로 삭제해준다.
      _Tree_Delete(pTree);

  //}

  //[정보 수정]
  //{
      //[!]{---------------------------------------
      //새로 생성된 저장소위치로 다시 기록해 준다.
      //나머지 정보는 그대로 두면 된다.
      //}------------------------------------------

      pTree->items = newItems;

      pTree->size  = newSize;

  //}

  return;

}

void __fastcall TGTree_Form::_Tree_Init(struct TREE  *pTree,
                                            //[2009.09.13.일][추가!!!]
                                            //초기화시 저장소 크기를 지정할수 있게 한다.
                                            //0 인 경우는 저장소를 동적 생성하지 않는다.
                                            int           pSize)
{
  //[2006.11.19.일][생성!!!]{-------------------------------------------------------
  //전달받은 [트리] 구조체 정보 전부를 초기화 한다.
  //
  //[2009.09.13.일][대폭수정!!!]----------------------------------------------------
  //초기화시 [항목 저장소] 의 크기를 지정하여 동적 생성할수 있도록 전부 수정하였다.
  //}-------------------------------------------------------------------------------

  //[VAR]
  //{
      int  i;
  //}

  //[<Tree> 동적 생성]
  //{
      //[2009.09.13.일][주요수정!!!]{----------------------------
      //초기에는 지정 크기로 동적 생성한다(향후 더 커질수 있다).
      //단, 크기가 0 으로 지정된 경우는 생성하지 않는다.
      //}--------------------------------------------------------

      if(pSize != 0)
      {
        _Tree_Create(pTree, pSize);

      }

  //}

  for(i = 0; i < pTree->size; i++)
  {
    //해당 항목을 초기화 한다.
    _Item_Init(&(pTree->items[i]));

  }

  //count 초기화.
  pTree->items_count          = 0;

  //level 관리 초기화.
  //일단 모두 level 이 닫힌것으로 본다.
  pTree->level_open_close_bit = 0x00000000;

  //일단 모두 선택되지 않은 것이다.
  pTree->select_line          = -1;
  pTree->select_itemindex     = -1;
  pTree->last_line            = -1;

  pTree->scroll_position      = 0;

  return;

}

void __fastcall TGTree_Form::_Tree_Get_ItemIndex_withNAME(struct TREE  *pTREE,
                                                              char         *pITEMname,
                                                              int          *rITEMindex)
{
  //[2006.11.19.일][생성!!!]{----------------------------------------------
  //지정된 tree 에서 item 의 [이름] 을 가지고 해당 item 의 <item-index> 를
  //추출하여 반환한다.
  //<name> 은 중복 되지 않는다.
  //}----------------------------------------------------------------------

  //[VAR]
  //{
      int  i;
  //}

  for(i = 0; i < pTREE->items_count; i++)
  {
    if(STR_Match(pITEMname, pTREE->items[i].name) == true)
    {
      //같은 [이름] 의 [옹이] 를 찾은 것이므로, 해당 <item-index> 를 반환한다.
      (*rITEMindex) = i;

      return;

    }

  }

  //찾는 것이 없는 경우는 -1 을 반환한다.
  (*rITEMindex) = -1;

  return;

}

void __fastcall TGTree_Form::_Tree_Get_ItemIndex_withText(struct TREE  *pTree,
                                                              char         *pItemText,
                                                              int          *rItemIndex)
{
  //[2009.08.18.화][생성!!!]{--------------------------------------------------------
  //지정된 <Tree> 에서 [항목] 의 <text> 를 가지고 해당 item 의 <itemindex> 를
  //추출하여 반환한다.
  //<Text> 는 중복 될수 있으므로 특수한 경우만 사용한다.
  //
  //이 함수는 금일 [설계묶음] 안의 [함수묶음] 에 [수학함수] 가 사용되었는지 확인하는
  //함수를 만들다가 필요가 있어서 만든다.
  //[API 창] 의 항목은 모두 <text> 도 겹치지 않으므로 여기서 [수학함수] [옹이] 를
  //<text> 로 찾기 위하여 만들게 되었다.
  //}--------------------------------------------------------------------------------

  //[VAR]
  //{
      int  i;

  //}

  for(i = 0; i < pTree->items_count; i++)
  {
    if(STR_Match(pItemText, pTree->items[i].txt) == true)
    {
      //같은 [이름] 의 [옹이] 를 찾은 것이므로, 해당 <item-index> 를 반환한다.
      (*rItemIndex) = i;

      return;

    }

  }

  //찾는 것이 없는 경우는 -1 을 반환한다.
  (*rItemIndex) = -1;

  return;

}

void __fastcall TGTree_Form::_Tree_Get_NodeInfo(struct TREE  *pTREE,
                                                    //지정 [옹이] 의 [이름].
                                                    char         *pNODEname,
                                                    //지정 [옹이] 의 tree 상에서의 item-index.
                                                    int          *rNODEindex,
                                                    //지정 [옹이] 의 순수한 직계 [가지] 의 마지막 item-index.
                                                    int          *rNODEendITEMindex,
                                                    //지정 [옹이] 의 가장 마지막 [가지] 의 item-index.
                                                    int          *rNODElastITEMindex)
{
  //[2006.11.19.일][생성!!!]{-------------------------------------------------------------
  //지정 [옹이] 의 tree 상에서의 item-index 와 가지고 있는 가장 마지막 [가지] 의
  //tree 상의 item-index 값을 반환한다.
  //[옹이] 의 기본 정보를 반환한다.
  //
  //[2006.11.21.화][수정!!!]--------------------------------------------------------------
  //[옹이] 자체의 마지막 직계 [가지] 의  item-index 를 rNODEendITEMindex 로 반환한다.
  //이는 [옹이] 의 level 보다 한단계 낮은 level 을 가진 마지막 item 이 해당한다.
  //이는 한단계 낮은 level 이 나올때마다 계속 그 itemindex 를 기록하면 자동으로 해결된다.
  //}-------------------------------------------------------------------------------------

  //[VAR]
  //{
      int  node_index;
      int  node_level;
      int  i;
  //}

  //[[옹이] 자체 item-index 얻기]
  //{
      //pNODEname 와 일치하는 [옹이] 의 <item-index> 를 얻는다.
      _Tree_Get_ItemIndex_withNAME(pTREE, pNODEname, &node_index);

      //[반환]{-------------------
      (*rNODEindex) = node_index;
      //}-------------------------
  //}

  //[자체 level 값]
  //{
      node_level = pTREE->items[node_index].level;
  //}

  //[마지막 [가지] 의 item-index]
  //{
      //[설명!!!]{---------------------------------------------------------------
      //[옹이] 가 가진 [가지] 중 가장 마지막 [가지] 의 item-index 를 얻는다.
      //[옹이] 의 level 보다 같거나 작은 level 값을 가진 item 의 바로 전 item 이
      //마지막 [가지] 가 된다.
      //}------------------------------------------------------------------------

      for(//[옹이] 위치 다음부터 검사를 해야한다.
          i = node_index + 1;
          i < pTREE->items_count;
          i++)
      {
        if((node_level + 1) == pTREE->items[i].level)
        {
          //[옹이] 의 직계 item 이 발견될때마다 계속 itemindex 를 기록한다.
          (*rNODEendITEMindex) = i;
        }

        if(node_level >= pTREE->items[i].level)
        {
          //이 item 바로 이전 item 이 마지막 [가지] item 이 된다.

          //[반환]{----------------------
          (*rNODElastITEMindex) = i - 1;
          //}----------------------------

          return;

        }

      }
  //}

  //[반환]{-------------------------------------------------------------------------------
  //여기까지 온것은 하위 항목만 있는 것이므로 가장 마지막에 검사한 itemindex 를 기록한다.
  (*rNODElastITEMindex) = i - 1;
  //}-------------------------------------------------------------------------------------

  return;

}

void __fastcall TGTree_Form::_Tree_Get_Node_LastItemIndex(struct TREE  *pTREE,
                                                              //지정 [옹이] 의 index.
                                                              int           pNODEindex,
                                                              //지정 [옹이] 의 순수한 직계 [가지] 의 마지막 item-index.
                                                              int          *rNODEendITEMindex,
                                                              //지정 [옹이] 의 가장 마지막 가지의 item-index.
                                                              int          *rNODElastITEMindex)
{
  //[2006.11.20.월][생성!!!]{-------------------------------------------------------------
  //지정 [옹이] 가 가지고 있는 가장 마지막 item 의 tree 상에서의 index 값을 반환한다.
  //
  //[2006.11.21.화][수정!!!]--------------------------------------------------------------
  //[옹이] 자체의 마지막 직계 [가지] 의  item-index 를 rNODEendITEMindex 로 반환한다.
  //이는 [옹이] 의 level 보다 한단계 낮은 level 을 가진 마지막 item 이 해당한다.
  //이는 한단계 낮은 level 이 나올때마다 계속 그 itemindex 를 기록하면 자동으로 해결된다.
  //
  //[2009.02.02.월][수정!!!]--------------------------------------------------------------
  //반환통로가 NULL 이라면 반환하지 않는 것으로 수정한다.
  //}-------------------------------------------------------------------------------------

  //[VAR]
  //{
      int  node_level;
      int  i;
  //}

  //[초기화]
  //{
      //[2009.08.18.화][추가!!!]{-----------------------------------------------------
      //반환값은 미리 초기화 해줘야한다.
      //그렇지 않으면, 아예 항목이 없어서 함수를 종료하는 경우 반환값을 반환하지 않아
      //쓰레기값 그대로 남겨지게된다.
      //}-----------------------------------------------------------------------------

      if(rNODEendITEMindex  != NULL) { (*rNODEendITEMindex)  = -1; }

      if(rNODElastITEMindex != NULL) { (*rNODElastITEMindex) = -1; }

  //}

  //[자체 level 값]
  //{
      node_level = pTREE->items[pNODEindex].level;
  //}

  //[마지막 [가지] 의 item-index]
  //{
      //[설명!!!]{---------------------------------------------------------------
      //[옹이] 가 가진 [가지] 중 가장 마지막 [가지] 의 item-index 를 얻는다.
      //[옹이] 의 level 보다 같거나 작은 level 값을 가진 item 의 바로 전 item 이
      //마지막 [가지] 가 된다.
      //}------------------------------------------------------------------------

      for(//[옹이] 위치 다음부터 검사를 해야한다.
          i = pNODEindex + 1;
          i < pTREE->items_count;
          i++)
      {
        if((node_level + 1) == pTREE->items[i].level)
        {
          //[옹이] 의 직계 item 이 발견될때마다 계속 itemindex 를 기록한다.

          if(rNODEendITEMindex != NULL) { (*rNODEendITEMindex) = i; }

        }

        if(node_level >= pTREE->items[i].level)
        {
          //이 item 바로 이전 item 이 마지막 [가지] item 이 된다.

          if(rNODElastITEMindex != NULL) { (*rNODElastITEMindex) = i - 1; }

          return;

        }

      }
  //}

  //[반환]
  //{
      //여기까지 온것은 하위 항목만 있는 것이므로 가장 마지막에 검사한 itemindex 를 기록한다.
      if(rNODElastITEMindex != NULL) { (*rNODElastITEMindex) = i - 1; }

  //}

  return;

}

void __fastcall TGTree_Form::_Tree_Get_Node_LastItemIndex2(struct TREE  *pTree,
                                                               //지정 [옹이] 의 name.
                                                               char         *pNodeName,
                                                               //이 [옹이] 의 <itemindex> 를 반환한다.
                                                               int          *rNodeItemIndex,
                                                               //지정 [옹이] 의 순수한 [직계 가지] 의 마지막 item-index.
                                                               int          *rNodeJikgyeLastItemIndex,
                                                               //지정 [옹이] 의 가장 마지막 가지의 item-index.
                                                               int          *rNodeLastItemIndex)
{
  //[2009.01.30.금][생성!!!]{----------------------------------------------------------------------------------
  //지정 [옹이] 의 [직계가지] 와 [모든 하위 가지] 각각의 마지막 [항목] 의 itemindex 를 구해서 반환한다.
  //_Tree_Get_Node_LastItemIndex() 함수와 모든 기능은 같으나 단지 [옹이] 의 이름을 사용한다는 것만 다르다.
  //따라서, [옹이] 의 <itemindex> 를 <name> 으로 구한뒤 _Tree_Get_Node_LastItemIndex() 함수를 사용하여 구한다.
  //
  //[인수] 가 NULL 인 경우는 사용하지 않는 것으로 간주하고 아무것도 반환하지 않아야 한다.
  //}----------------------------------------------------------------------------------------------------------

  //[VAR]
  //{
      int  nodeItemIndex;

      int  nodeJikgyeLastItemIndex;

      int  nodeLastItemIndex;

  //}


  //[[옹이] 자체 <itemindex> 얻기]
  //{
      //일단, <name> 에 해당하는 [옹이] 의 <itemindex> 를 구한다.
      _Tree_Get_ItemIndex_withNAME(pTree, pNodeName, &nodeItemIndex);

      //[정보 반환]
      //{
          if(rNodeItemIndex != NULL) { (*rNodeItemIndex) = nodeItemIndex; }

      //}

  //}

  //[정보 얻기]
  //{
      //이미 존재하는 함수로 간단하게 구할수 있다.

      _Tree_Get_Node_LastItemIndex(pTree,
                                   nodeItemIndex,
                                   &nodeJikgyeLastItemIndex,
                                   &nodeLastItemIndex);

      //[정보 반환]
      //{
          if(rNodeJikgyeLastItemIndex != NULL) { (*rNodeJikgyeLastItemIndex) = nodeJikgyeLastItemIndex; }

          if(rNodeLastItemIndex       != NULL) { (*rNodeLastItemIndex)       = nodeLastItemIndex;       }

      //}

  //}

  return;

}

void __fastcall TGTree_Form::_Tree_Get_ThisItemNode_LastItemIndex(struct TREE  *pTREE,
                                                                      //지정 itemindex.
                                                                      int           pITEMindex,
                                                                      //[2009.02.02.월][추가!!!]
                                                                      int          *rNodeIndex,
                                                                      //지정 [옹이] 의 순수한 직계 [가지] 의 마지막 item-index.
                                                                      int          *rNODEendITEMindex,
                                                                      //이 itemindex 를 포함하는 [옹이] 의 마지막 itemindex.
                                                                      int          *rNODElastITEMindex)
{
  //[2006.11.21.화][생성!!!]{----------------------------------------------------
  //지정 item-index 를 가진 [옹이] 의 가장 마지막 item-index 를 구해서 반환한다.
  //
  //[2009.02.02.월][수정!!!]-----------------------------------------------------
  //반환 통로가 NULL 인 경우는 반환하지 않는다.
  //이는 _Tree_Get_Node_LastItemIndex() 함수에서 자동 처리 된다.
  //}----------------------------------------------------------------------------

  //[VAR]
  //{
      int  node_index;
      int  item_level;
      int  i;
  //}

  //[[옹이] 찾기]
  //{
      //[방법]{--------------------------------------------------
      //pITEMindex 를 포함하는 [옹이] 의 item-index  를 얻는다.
      //지정 위치부터 거꾸로 검사하여 보다 작은 level 의 item 이
      //이 pITEMindex 를 포함한 [옹이] 가 된다.
      //}--------------------------------------------------------

      //지정 item 의 level 을 구한다.
      item_level = pTREE->items[pITEMindex].level;

      for(//지정 item 이전 item 부터 거꾸로 검사한다.
          i = pITEMindex;// - 1;
          i >= 0;
          i--)
      {
        if(pTREE->items[i].level < item_level)
        {
          //이 item 이 바로 지정 pITEMindex 을 가진 [옹이] 가 된다.
          node_index = i;

          if(rNodeIndex != NULL) { (*rNodeIndex) = node_index; }

          goto GET_LAST_INDEX;

        }

      }

  //}

  //[예외처리]
  //{
      //여기까지 온것은 찾은 것이 없는 것이다.
      if(rNodeIndex != NULL)         { (*rNodeIndex) = -1;         }

      if(rNODEendITEMindex != NULL)  { (*rNODEendITEMindex)  = -1; }

      if(rNODElastITEMindex != NULL) { (*rNODElastITEMindex) = -1; }

  //}

  GET_LAST_INDEX:

  //[[옹이] 마지막 itemindex 구하기]
  //{
      //[옹이] 의 마지막 item-index 를 구한다.
      _Tree_Get_Node_LastItemIndex(pTREE, node_index, rNODEendITEMindex, rNODElastITEMindex);

  //}

  return;

}

void __fastcall TGTree_Form::_Tree_Make_InsertPosition(struct TREE  *pTREE,
                                                           //끼워넣을 위치.(이 공간을 비워야 한다.)
                                                           int           pINSERTindex)
{
  //[2006.11.20.월][생성!!!]{----------------------------------------------
  //tree 상에서 item 을 끼워 넣을 공간을 지정 index 위치에 만든다.
  //이는 해당 위치의 item 을 도미노로 한씩 뒤로 밀어내면 된다.
  //이는 서로 겹치지 않도록 가장 뒤의 item 부터 다음 위치로 이동하면 된다.
  //}----------------------------------------------------------------------

  //[VAR]
  //{
      int  i;
  //}

  for(i = pTREE->items_count - 1; i >= pINSERTindex; i--)
  {
     //item 을 다음칸으로 이동한다.
     pTREE->items[i + 1] = pTREE->items[i];

  }

  //이제 pINSERTindex 의 위치가 비워졌다.

  return;

}

bool __fastcall TGTree_Form::_Tree_Add_NodeItem(struct TREE      *pTREE,
                                                    char             *pNODEname,
                                                    struct TREEITEM  *pITEM)
{
  //[2006.11.19.일][생성!!!]{------------------------------------------------
  //지정 [옹이] 이에 [가지] 를 추가한다.
  //
  //[2009.09.13.일][중요수정!!!]---------------------------------------------
  //추가할수 있는 처리 용량을 넘은 경우는 저장소를 재생성하고 더 크게 만든뒤
  //여기에 다시 추가한다.
  //}------------------------------------------------------------------------

  //[방법]
  //{
      //----------------------------------------------------------------------------------
      //1) [트리] 에서 pNODEname 에 해당하는 [옹이] 를 찾는다.
      //2) [옹이] 의 가장 마지막에 해당 가지를 추가한다.
      //3) [가지] 가 추가되면 [트리] 의 모든 index 가 변경되므로 같이 수정해 주어야 한다.
      //
      //level 은 [옹이] 의 level 보다 자동으로 한단계 낮은 값을 갖게 된다.
      //----------------------------------------------------------------------------------

      //[끼워넣는 위치]
      //{
          //------------------------------------------------------------------------------
          //끼워넣는 위치는 해당 [옹이] 와 같은 <level> 의 다음 item 의 시작 위치가 된다.
          //즉, 추가되는 item 은 [옹이] 의 가장 마지막에 추가하게 된다.
          //------------------------------------------------------------------------------
      //}

      //[2009.01.27.화][추가!!!]
      //{
          //[옹이] 에 추가 하는 경우 [옹이] 가 [일반 가지] 인 경우(하부 가지가 아무것도 없는 경우)는
          //이 [옹이] 에 하부 [가지] 가 추가 되므로 [옹이] 를 만들어 주어야 한다.
          //기보적으로는 [+] 로 아직 열어 놓지는 않는다.
          //이미 [+] 또는 [-] 인 경우는 그대로 두면 된다.

      //}

  //}

  //[VAR]
  //{
      //pNODEname 에 해당하는 [옹이] 의 <item-index>.
      int  node_index;
      int  node_end_itemindex;
      int  node_last_itemindex;

      //item 을 끼워넣을 위치.
      int  insert_index;

      int  i;

  //}

  //[저장할수 있는 상태인가?]
  //{
      //[2009.09.13.일][중요추가!!!]{--------------------------------------
      //저장소가 이미 꽉찬경우는 전용 함수로 더 크게 생성하고, 새로 생성된
      //저장소에 추가해 주어야 한다.
      //}------------------------------------------------------------------

      _Tree_ReSize(pTREE);

  //}

  //[해당 [옹이] 정보 얻기]
  //{
      _Tree_Get_NodeInfo(pTREE, pNODEname, &node_index, &node_end_itemindex, &node_last_itemindex);

  //}

  //[끼워넣을 위치 얻기]
  //{
      //지정 [옹이] 의 가장 마지막 [가지] 위치 바로 다음이 되어야 한다.
      insert_index = node_last_itemindex + 1;

  //}

  //[level 값 정의]
  //{
      //새로 추가되는 item 의 <level> 은 추가하는 [옹이] 의 <level> 보다
      //한단계 작은 값을 주면 된다.
      pITEM->level = pTREE->items[node_index].level + 1;

  //}

  //[추가 공간 만들기]
  //{
      //item 을 tree 에 추가할 공간을 만든다.
      _Tree_Make_InsertPosition(pTREE, insert_index);

  //}

  //[item 추가]
  //{
      pTREE->items[insert_index] = (*pITEM);

  //}

  //[item 증가]
  //{
      //item 을 하나 추가 하였으므로 수를 증가한다.
      pTREE->items_count++;

  //}

  //[옹이 종류 바꾸기]
  //{
      //[2009.01.27.화][추가!!!]{-----------------------------------------------
      //현재 [옹이] 가 [+] 나 [-] 가 아닌 경우는 기본적으로 [+] 로 만들어 준다.
      //이제 하부 [가지] 가 생겼으므로.
      //}-----------------------------------------------------------------------

      if(pTREE->items[node_index].kind == '.')
      {
        pTREE->items[node_index].kind = '+';

      }

  //}

  //이상없이 처리 되었다.
  return(true);

}

void __fastcall TGTree_Form::_Tree_Add_Item(struct TREE      *pTREE,
                                                struct TREEITEM  *pITEM)
{
  //[2006.11.20.월][생성!!!]{------------------------------------------------
  //해당 tree 에 item 을 추가한다.
  //
  //[2009.09.13.일][중요수정!!!]---------------------------------------------
  //추가할수 있는 처리 용량을 넘은 경우는 저장소를 재생성하고 더 크게 만든뒤
  //여기에 다시 추가한다.
  //}------------------------------------------------------------------------

  //[저장할수 있는 상태인가?]
  //{
      //[2009.09.13.일][중요추가!!!]{--------------------------------------
      //저장소가 이미 꽉찬경우는 전용 함수로 더 크게 생성하고, 새로 생성된
      //저장소에 추가해 주어야 한다.
      //}------------------------------------------------------------------

      _Tree_ReSize(pTREE);

  //}

  //[item 추가]
  //{
      pTREE->items[pTREE->items_count] = (*pITEM);

  //}

  //[item 증가]
  //{
      //item 을 하나 추가 하였으므로 수를 증가한다.
      pTREE->items_count++;

  //}

  return;

}

void __fastcall TGTree_Form::_Resize(void)
{
  //[2006.10.26.목][생성!!!]{--
  //크기를 조정한다.
  //}--------------------------

  this->Width    = this->Parent->Width;
  this->Height   = this->Parent->Height - this->Top;

  return;

}

void __fastcall TGTree_Form::_Draw(void)
{
  //[2006.10.31.화][생성!!!]

  BitBlt(this->Canvas->Handle, 0, 0,
         this->Width, this->Height,
         _bmp_->Canvas->Handle, 0, 0, SRCCOPY);

  return;

}

void __fastcall TGTree_Form::_V_Scroll(int  pPOSITION)
{
  //[VAR]
  //{
      int  w, h;
  //}

  //[바탕색]
  //{
      //[배경 그림으로 지우기]
      //{
          //배경 그림으로 바탕을 지운다.
          BitBlt(_bmp_->Canvas->Handle, 0, 0,
                 _bmp_->Width, _bmp_->Height,
                 _bmp_back_->Canvas->Handle, 0, 0, SRCCOPY);
      //}
  //}

  //[테두리 만들기]
  //{
      _bmp_->Canvas->Pen->Color   = _ide_option->color_0;
      _bmp_->Canvas->Pen->Width   = 1;
      _bmp_->Canvas->Brush->Style = bsClear;
      _bmp_->Canvas->Rectangle(_bmp_->Canvas->ClipRect);
  //}

  //[좌표정보 수정]
  //{
      //-----------------------------------------------------
      //좌표 정보의 y 좌표를 scrol 에 맞게 수정한다.
      _item_xy.tree_y = 1 + (-1) * pPOSITION * _line_height;
      //-----------------------------------------------------
  //}

  //[컨트롤 그리기]
  //{
      //선택된 tab 의 tree 를 그린다.
      _TreeView(_tree_select_index, false);
  //}

  //[view]{-------------
  //그린 것을 보여준다.
  _Draw();
  //}-------------------

  return;

}

void __fastcall TGTree_Form::_Tree_Bmp_Create_Load(Graphics::TBitmap **pBITMAP,
                                                       AnsiString          pBMPname)
{
  //[2006.11.24.금][생성!!!]{--------------------------------------------
  //bmp 를 생성한후 지정 이름의 bmp 를 읽어 들이고 tree 용으로 설정한다.
  //여기서 bmp 를 생성하므로 **포인터로 전달 받아서 처리해야 한다.
  //}--------------------------------------------------------------------

  //[bmp 설정]
  //{
      //----------------------------------
      //실제 그림 영역을 생성한다.
      (*pBITMAP) = new Graphics::TBitmap;

      //그림 읽어 들이기.
      (*pBITMAP)->LoadFromFile(pBMPname);

      //24bit bitmap 으로 지정.
      (*pBITMAP)->PixelFormat = pf24bit;
      //----------------------------------
  //}

  //[그림색 변환]
  //{
      //-------------------------------------------------------
      //계속 바뀌지 않으므로 여기서 한번만 색을 변환하면 된다.
      BMP_Self_ChangeColor2((*pBITMAP),
                            //검정색 -> 테두리색.
                            clBlack, _ide_option->color_0,
                            //흰  색 -> 바탕색.
                            clWhite, IDE_COLOR_2);
      //-------------------------------------------------------
  //}

  return;

}

void __fastcall TGTree_Form::_Scroll_Set(void)
{
  //[2006.11.29.수][생성!!!]{---------------------------------------
  //tree 의 보여지는 행 수에 따라 scrollbar 를 재설정한다.
  //단, 현재 보이는 영역의 문서는 스크롤 대상이 아니므로 제외 한다.
  //}---------------------------------------------------------------

  //[VAR]
  //{
      //표시 영역의 충 줄수.
      int  view_line = 0;

      //스크롤되는 총 줄수.(표시 영역 밖의 문서의 총 행수가 된다.)
      int  scroll_line = 0;

      //순수한 문서 전체 행수.
      int  total_line  = 0;
  //}

  //[검사]{------------------------
  if(this->Parent == NULL) return;
  //}------------------------------

  //[계산]
  //{
      //문서를 보여주는 영역의 행수를 구한다.
      view_line   = (this->Height - ((Tide_tree_Form *)(this->Parent))->_tabs_Form->Height) / _line_height;

      //전체 문서 행수를 구한다.
      total_line  = _Get_ViewLineCount(&(_tree[_tree_select_index]));//(_tree[_tree_select_index].last_line + 1);

      //스크롤 되는 문서의 행수를 구한다.
      scroll_line = total_line - view_line;

      //만일 모든 문서가 표시 영역에 있는 경우는 scroll 되는 양은 없다.
      if(scroll_line < 0)
      {
        scroll_line = 0;

      }
  //}

  //[수직 스크롤바 설정]
  //{
      //[주의!!!][2006.11.30.목]{----------------------------------------------------------
      //<thumb> 크기는 항상 문서 총량의 1/4 크기를 갖도록 비율을 고정한다.
      //순수하게 <보이는행 / 전체 문서행> 의 비율을 사용하는 경우, 전체 문서행이 너무 커서
      //보이는 문서행이 상대적으로 너무 작은 경우는 <thumb> 가 아예 보이지 않게 된다.
      //1/4 의 비율이 가장 보기 좋고 동작이 용이하다.
      //}----------------------------------------------------------------------------------

      //현재 보이는 영역의 행수.
      ((Tide_tree_Form *)(this->Parent))->_scroll_v_Form->_DesignSize(total_line / 4);

      //스크롤 될 문서의 총 행수.
      ((Tide_tree_Form *)(this->Parent))->_scroll_v_Form->_Max(scroll_line);
  //}

  return ;

}

void __fastcall TGTree_Form::_Get_ItemIndex_withLINE(struct TREE    *pTREE,
                                                         int             pLINEnumber,
                                                         int            *rITEMindex,
                                                         int            *rTEXTx,
                                                         int            *rTEXTy)
{
  //[2006.12.08.금][생성!!!]{---------------------------------------------------------
  //실제 그리지는 않고 가상적으로 처리하여 지정한 행의 정보를 반환한다.
  //이는 마우스포인터가 위치한 행의 항목 문자열을 [귀뜸말] 로 표시해 주기 위한것이다.
  //
  //이 함수는 Tree() 함수를 그대로 사용하고 일부를 삭제한것으로 자세한 내용은
  //해당 함수를 참고한다.
  //}---------------------------------------------------------------------------------

  //[VAR]
  //{
      int  i;

      //보이는 행중 처리되는 행을 가진다.(BASE : 0);
      //모든 item 이 표시되는 것은 아니므로 index 와 혼동하지 않도록 주의한다.
      int  line_number;

      //[옹이] 가 가진 직계 [가지] 의 마지막 itemindex.
      int  node_end_itemindex;
      //[옹이] 가 가지고 있는 가장 마지막 item 의 itemindex.
      int  node_last_itemindex;

      int  level;

      //[문자열] 이 표시될 위치를 기록한다.
      //이는 [항목-엄지그림] 의 표시 유/무 에 따라 문자열의 표시 위치가 바뀌기 때문이다.
      int  text_x;
      int  text_y;
  //}

  for(i = 0, line_number = 0;
      i < pTREE->items_count;
      i++, line_number++)
  {
    //0, 1 번 줄기는 앞에 세로 줄기가 올수 없다.
    if(pTREE->items[i].level >= 2)
    {
      //[item 앞의 모든 세로 줄기 표시]
      //{
          //[설명!!!]{--------------------------------------------------
          //현재 item 의 지나가는 세로 줄기를 그려주되,
          //앞의 level 의 모든 줄기가 [열려] 있는 경우만 그려주면 된다.
          //}-----------------------------------------------------------

          for(//현재 item 의 level 보다 2 단계 높은 level 부터 검사한다.
              level = pTREE->items[i].level - 2;
              //0 번 줄기까지 전부 검사하여 처리한다.
              level >= 0;
              level--)
          {
            if(((pTREE->level_open_close_bit >> level) & 1) == 1)
            {
              //줄기가 현재 [열려] 있는 상태이므로 세로 줄기를 그려준다.

              //[좌표정보 구하기]
              //{
                  //----------------------------------
                  //_item_xy.line_number = line_number;
                  //_item_xy.item_level  = level;

                  //_Tree_Get_XY(&_item_xy);
                  //----------------------------------
              //}

            }

          }
      //}
    }

    //0 번 줄기는 앞에 아무것도 배치하지 않으므로 처리하지 않는다.
    if(pTREE->items[i].level > 0)
    {
      //[item 바로 앞 기호]
      //{
          //[좌표정보 구하기]
          //{
              //------------------------------------------------
              //_item_xy.line_number = line_number;
              //_item_xy.item_level  = pTREE->items[i].level - 1;

              //_Tree_Get_XY(&_item_xy);
              //------------------------------------------------
          //}

          //[그리기]
          //{
              //2 종류가 있으므로 구분하여 처리한다.

              //[[옹이] 의 줄기 정보 얻기]
              //{
                  //이 item 이 해당 [옹이] 의 마지막 직계 item 인지 구분하여 처리한다.
                  _Tree_Get_ThisItemNode_LastItemIndex(pTREE, i, NULL, &node_end_itemindex, &node_last_itemindex);
                  
              //}

              if(i == node_end_itemindex)
              {
                //이 item 이 [옹이] 의 마지막 item 이므로 <끝> [엄지그림] 을 배치한다.

                //[줄기 close 처리]
                //{
                    //현재 level 의 줄기가 [닫혀] 있는 상태임을 기록한다.
                    //item 이 매달린 [옹이] 의 줄기가 되므로 level 이 하나 높다.
                    pTREE->level_open_close_bit &= (~(1 << (pTREE->items[i].level - 1)));
                //}
              }
          //}
      //}
    }

    //[좌표정보 구하기]
    //{
        //--------------------------------------------
        _item_xy.line_number = line_number;
        _item_xy.item_level  = pTREE->items[i].level;

        _Tree_Get_XY(&_item_xy);
        //--------------------------------------------
    //}

    //[문자열 표시 위치 기록]
    //{
        //--------------------------------------------------------------
        //[항목-엄지그림] 을 표시한 경우는 문자열의 표시 위치가 바뀐다.
        //따라서 문자열 표시 위치를 기록한다.
        if(pTREE->items[i].bmpindex == -1)
        {
          //[항목-엄지그림] 을 사용하지 않은 경우는 기본 위치가 된다.
          text_x = _item_xy.text_x;
          text_y = _item_xy.text_y;

        }
        else
        {
          text_x = _item_xy.text2_x;
          text_y = _item_xy.text2_y;

        }
        //--------------------------------------------------------------
    //}

    //[선택 행 itemindex 구하기]
    //{
        //현재 tree 의 지정 [행] 에 해당하는 itemindex 인지 검사한다.
        if(pLINEnumber == line_number)
        {
          //[정보 반환]{---------
         (*rITEMindex) = i;
         (*rTEXTx)     = text_x;
         (*rTEXTy)     = text_y;
         //}---------------------

          return;

        }
    //}

    switch(pTREE->items[i].kind)
    {
      case '+' :
      {
        //[닫힌 옹이]{-----------------------------------------------------------------
        //다른 것과 달리 해당 [옹이] 만 표시하고 하위 [항목] 은 표시 하지 않아야 한다.
        //[옹이] 의 정보를 추출하여 가지고 있는 가지의 수를 알고 이 부분은 건너 뛴다.
        //}----------------------------------------------------------------------------

        //[하위 항목 처리]
        //{
            //[+] 옹이의 경우는 자신만 표시하고, 하위 항목은 표시 하지 않아야 한다.

            //이 [옹이] 가 가진 가장 마지막 item 의 index 를 얻는다.
            _Tree_Get_Node_LastItemIndex(pTREE, i, &node_end_itemindex, &node_last_itemindex);

            //마지막 하위 항목까지 처리하지 않아야 한다.
            i = node_last_itemindex;
        //}

      } break;

      case '-' :
      {
        //[줄기 open 처리]
        //{
            //현재 level 의 줄기가 [열려] 있는 상태임을 기록한다.
            pTREE->level_open_close_bit |= (1 << pTREE->items[i].level);

        //}

      } break;

      case '.' :
      {

      } break;

    }

  }

  //[정보 반환]{-------------------------------
  //여기까지 온것은 해당하는 것이 없는 것이다.
  (*rITEMindex) = -1;
  (*rTEXTx)     = 0;
  (*rTEXTy)     = 0;
  //}------------------------------------------

  return;

}

int __fastcall TGTree_Form::_Get_ViewLineCount(struct TREE  *pTREE)
{
  //[2006.12.11.월][생성!!!]{--------------------------
  //실제 그리지는 않고 출력시 보이는 총 행수를 구한다.
  //}--------------------------------------------------

  //[VAR]
  //{
      int  i;

      //보이는 행중 처리되는 행을 가진다.(BASE : 0);
      //모든 item 이 표시되는 것은 아니므로 index 와 혼동하지 않도록 주의한다.
      int  line_number;

      //[옹이] 가 가진 직계 [가지] 의 마지막 itemindex.
      int  node_end_itemindex;
      //[옹이] 가 가지고 있는 가장 마지막 item 의 itemindex.
      int  node_last_itemindex;
  //}

  for(i = 0, line_number = 0;
      i < pTREE->items_count;
      i++, line_number++)
  {
    switch(pTREE->items[i].kind)
    {
      case '+' :
      {
        //[닫힌 옹이]{-----------------------------------------------------------------
        //다른 것과 달리 해당 [옹이] 만 표시하고 하위 [항목] 은 표시 하지 않아야 한다.
        //[옹이] 의 정보를 추출하여 가지고 있는 가지의 수를 알고 이 부분은 건너 뛴다.
        //}----------------------------------------------------------------------------

        //[하위 항목 처리]
        //{
            //[+] 옹이의 경우는 자신만 표시하고, 하위 항목은 표시 하지 않아야 한다.

            //이 [옹이] 가 가진 가장 마지막 item 의 index 를 얻는다.
            _Tree_Get_Node_LastItemIndex(pTREE, i, &node_end_itemindex, &node_last_itemindex);

            //마지막 하위 항목까지 처리하지 않아야 한다.
            i = node_last_itemindex;
        //}

      } break;

      case '-' :
      case '.' :
      {

      } break;

    }

  }

  //[총 행수 반환]
  //{
      return(line_number);
  //}

}

void __fastcall TGTree_Form::_Tree_Get_Node_ItemCount(struct TREE  *pTree,
                                                          //지정 [옹이] 의 [이름].
                                                          char         *pNodeName,
                                                          //이 [옹이] 의 item-index.
                                                          int          *rNodeItemindex,
                                                          //지정 [옹이] 의 직계 가지 수.
                                                          int          *rItemCount)
{
  //[2009.01.27.화][생성!!!]{------------------------------
  //지정 [옹이] 의 [직계 가지] 의 총 수를 구해서 반환한다.
  //즉, [가지] 안의 또다른 하위 [가지] 는 해당하지 않는다.
  //}------------------------------------------------------

  //[VAR]
  //{
      int  nodeIndex;
      int  nodeLevel;
      int  nodeItemLevel;
      int  nodeItemCount;
      int  i;

  //}

  //[[옹이] 자체 item-index 얻기]
  //{
      _Tree_Get_ItemIndex_withNAME(pTree, pNodeName, &nodeIndex);

      if(rNodeItemindex != NULL)
      {
        //NULL 인 경우는 반환하지 않는다.
        (*rNodeItemindex) = nodeIndex;

      }

  //}

  //[Level 값 얻기]
  //{
      //지정 [옹이] 자체의 <Level>.
      nodeLevel     = pTree->items[nodeIndex].level;

      //지정 [옹이] 의 [직계 가지] 의 <Level>.
      nodeItemLevel = nodeLevel + 1;

  //}

  //[직계 가지 수 구하기]
  //{
      //[직계가지] 는 [옹이] 의 <Level + 1> 의 <Level> 을 갖는다.

      for(//[옹이] 위치 다음부터 검사를 해야한다.
          i = nodeIndex + 1, nodeItemCount = 0;
          i < pTree->items_count;
          i++)
      {
        if     (pTree->items[i].level == nodeItemLevel)
        {
          //[옹이] 의 [직계 가지] 에 해당한다.
          nodeItemCount++;

        }
        else if(pTree->items[i].level < nodeItemLevel)
        {
          //[직계 가지] 의 <Level> 보다 작은 것은 현재 [옹이] 가 끝난 것이다.
          //여기서 종료한다.
          break;

        }

      }

  //}

  //[반환]
  //{
      (*rItemCount) = nodeItemCount;

  //}

  return;

}

void __fastcall TGTree_Form::_Tree_Get_Node_ItemIndex_withText(struct TREE  *pTree,
                                                                   //지정 [옹이] 의 [이름].
                                                                   char         *pNodeName,
                                                                   //검사할 <text> 항목.
                                                                   char         *pItemText,
                                                                   //[대/소] 문자 구분 여부(true:구분).
                                                                   bool          pCase,
                                                                   //이 [옹이] 의 item-index.
                                                                   int          *rNodeItemindex,
                                                                   //<text> 를 가진 itemindex.
                                                                   int          *rItemindex)
{
  //[2009.01.29.목][생성!!!]{-------------------------------------------------------------------------------
  //지정 [옹이] 의 [직계 가지] 만을 대상으로, <text> 항목이 일치 하는 항목의 item-index 를 찾아서 반환한다.
  //즉, [가지] 안의 또 다른 하위 [가지] 는 대상으로 하지 않는다.
  //반환 [인수] 가 NULL 인 경우는 반환하지 않는다.
  //}-------------------------------------------------------------------------------------------------------

  //[VAR]
  //{
      int  nodeIndex;
      int  nodeLevel;
      int  nodeItemLevel;
      int  i;

  //}

  //[[옹이] 자체 item-index 얻기]
  //{
      _Tree_Get_ItemIndex_withNAME(pTree, pNodeName, &nodeIndex);

      if(rNodeItemindex != NULL) { (*rNodeItemindex) = nodeIndex; }

  //}

  //[Level 값 얻기]
  //{
      //지정 [옹이] 자체의 <Level>.
      nodeLevel     = pTree->items[nodeIndex].level;

      //지정 [옹이] 의 [직계 가지] 의 <Level>.
      nodeItemLevel = nodeLevel + 1;

  //}

  //[직계 가지 안에서 검사]
  //{
      //[직계가지] 는 [옹이] 의 <Level + 1> 의 <Level> 을 갖는다.
      //[직계가지] 만을 대상으로 일치 하는 <text> 를 가지는 항목의 index 를 구해서 반환한다.

      for(//[옹이] 위치 다음부터 검사를 해야한다.
          i = nodeIndex + 1;
          i < pTree->items_count;
          i++)
      {
        if     (pTree->items[i].level == nodeItemLevel)
        {
          //[옹이] 의 [직계 가지] 에 해당한다.

          if(pCase == true)
          {
            if(STR_Match(pTree->items[i].txt, pItemText) == true)
            {
              //해당하는 것을 찾았다.
              if(rItemindex != NULL) { (*rItemindex) = i; }

              return;

            }

          }
          else
          {
            if(STR_Match_NoCase(pTree->items[i].txt, pItemText) == true)
            {
              //해당하는 것을 찾았다.
              if(rItemindex != NULL) { (*rItemindex) = i; }

              return;

            }

          }

        }
        else if(pTree->items[i].level < nodeItemLevel)
        {
          //[직계 가지] 의 <Level> 보다 작은 것은 현재 [옹이] 가 끝난 것이다.
          //여기서 종료한다.
          break;

        }

      }

  //}

  //[예외처리]
  //{
      //여기까지 온것은 해당하는 것이 아무것도 없는 것이다.
      if(rItemindex != NULL) { (*rItemindex) = -1; }

  //}

  return;

}

bool __fastcall TGTree_Form::_Tree_Delete_Item(struct TREE  *pTree,
                                                   //삭제할 itemIndex.
                                                   int           pDeleteItemIndex)
{
  //[2009.02.01.일][생성!!!]{-----------------------------------------------
  //지정한 [항목] 을 해당 [tree] 에서 [삭제] 한다.
  //item.name 등 다른 정보는 그대로 둔다.
  //즉, 아주 기본적인 처리만 수행하는 것이다.
  //실제는 [삭제] 가 아니라 삭제할 범위만큼을 끌어다 맞추는 것이다.
  //
  //[중요!!!]
  //1) 이 함수는 지정된 [힝목] 에 속한 하위 항목도 전부 자동으로 삭제한다.
  //2) 만일 삭제 되고 있는 항목이 다른 [옹이] 의 하위 항목인 경우이고
  //   지금 삭제 되는 항목이 유일한 항목이하면 더이상 [옹이] 에는 아무것도
  //   하위 항목이 없어지게 되므로 [+]/[-] 인 경우 [.] 로 바꿔 주어야 한다.
  //}-----------------------------------------------------------------------

  //[VAR]
  //{
      //삭제 시작 위치.
      int  deleteStartIndex;

      //삭제 끝 위치.
      int  deleteEndIndex;

      //삭제되는 [힝목] 수.
      int  deleteCount;

      int  i;

      int  nodeIndex;

      int  nodeLastItemIndex;

  //}

  //[유효한 항목인가?]
  //{
      //삭제할 항목이 이 [tree] 범위 내에 존재하는지 확인한다.
      if(!((0 <= pDeleteItemIndex) && (pDeleteItemIndex < pTree->items_count))) return(false);

  //}

  //[직계옹이 위치 얻기]
  //{
      //[!]{----------------------------------------------------------------------------
      //지금 [삭제] 대상이 되는 [항목] 의 [직계옹이] 위치를 얻는다.
      //이는 삭제 뒤 이 [옹이] 의 하위 [가지] 가 하나도 없을 경우의 처리를 위한 것이다.
      //삭제 된 뒤에는 정확한 위치를 얻을수 없으므로 미리 구해 놓는다.
      //}-------------------------------------------------------------------------------

      _Tree_Get_NodeIndex_of_ThisItem(pTree, pDeleteItemIndex, &nodeIndex);

  //}

  //[초기화]
  //{
      deleteStartIndex = pDeleteItemIndex;
      deleteEndIndex   = -1;
      deleteCount      = 0;

  //}

  //[지정 항목의 범위 구하기]
  //{
      //[!]{---------------------------------------------------------------
      //이 [항목] 이 하위 항목을 가지고 있는지 확인도 해야 하므로 겸사겸사
      //해당 항목의 영향 범위를 구한다.
      //}------------------------------------------------------------------

      _Tree_Get_Node_LastItemIndex(pTree, deleteStartIndex, NULL, &deleteEndIndex);

  //}

  //[삭제 정보 구하기]
  //{
      deleteCount = (deleteEndIndex - deleteStartIndex) + 1;

  //}

  //[삭제]
  //{
      //지정 구간을 뒤의 것을 앞으로 끌어 당겨 붙임으로써 삭제한다.

      for(i = deleteStartIndex; i < (pTree->items_count - deleteCount); i++)
      {
        pTree->items[i] = pTree->items[i + deleteCount];

      }

  //}

  //[후처리]
  //{
      //[tree] 가 수정 되었으므로 관련 정보도 같이 수정한다.
      pTree->items_count     -= deleteCount;

      pTree->select_line      = -1;

      pTree->select_itemindex = -1;

  //}

  //[직계옹이처리]
  //{
      //[방법]{---------------------------------------------------------------------
      //만일 [직계옹이] 가 있는 경우, 지금 삭제된 [가지] 가 유일한 [가지] 인 경우는
      //더이상 하위 [가지] 가 존재 하지 않으므로 [옹이] 에서 해제해 주어야 한다.
      //[+]/[-] 인 경우가 되므로 이것을 [.] 으로 바꿔 주어야 한다.
      //}---------------------------------------------------------------------------

      //[옹이 최종 항목 위치 구하기]
      //{
          //[예외처리]
          //{
              //찾는 [직계옹이] 가 존재하지 않는다면 더이상 처리 하지 않는다.
              //단, 이상없이 처리는 된 것이다.
              if(nodeIndex < 0) return(true);

          //}

          _Tree_Get_Node_LastItemIndex(pTree, nodeIndex, NULL, &nodeLastItemIndex);

      //}

      if(nodeIndex == nodeLastItemIndex)
      {
        //이 경우는 지금 [직계옹이] 는 하위 [가지] 를 하나도 갖지 않은 것이므로 [옹이] 에서 해제 한다.
        pTree->items[nodeIndex].kind = '.';

      }

  //}

  return(true);

}

bool __fastcall TGTree_Form::_Tree_Delete_AllSubItem(struct TREE  *pTree,
                                                         //삭제할 하위 항목의 [옹이] itemIndex.
                                                         int    pDeleteNodeIndex)
{
  //[2009.04.01.수][생성!!!]{-----------------------------------------------
  //지정한 [옹이] 는 그대로 두고 하위 항목을 몽땅 삭제한다.
  //
  //[중요!!!]---------------------------------------------------------------
  //1) 이 함수는 지정된 [힝목] 에 속한 하위 항목도 전부 자동으로 삭제한다.
  //2) 만일 삭제 되고 있는 항목이 다른 [옹이] 의 하위 항목인 경우이고
  //   지금 삭제 되는 항목이 유일한 항목이하면 더이상 [옹이] 에는 아무것도
  //   하위 항목이 없어지게 되므로 [+]/[-] 인 경우 [.] 로 바꿔 주어야 한다.
  //}-----------------------------------------------------------------------

  //[VAR]
  //{
      //삭제 시작 위치.
      int  deleteStartIndex;

      //삭제 끝 위치.
      int  deleteEndIndex;

      //삭제되는 [힝목] 수.
      int  deleteCount;

      int  i;

  //}

  //[유효한 항목인가?]
  //{
      //삭제할 항목이 이 [tree] 범위 내에 존재하는지 확인한다.
      if(!((0 <= pDeleteNodeIndex) && (pDeleteNodeIndex < pTree->items_count))) return(false);

  //}

  //[초기화]
  //{
      //삭제 되는 것은 지정 [옹이] 위치 다음부터 해당한다.
      deleteStartIndex = pDeleteNodeIndex + 1;
      deleteEndIndex   = -1;
      deleteCount      = 0;

  //}

  //[지정 항목의 범위 구하기]
  //{
      //[!]{---------------------------------------------------------------
      //이 [항목] 이 하위 항목을 가지고 있는지 확인도 해야 하므로 겸사겸사
      //해당 항목의 영향 범위를 구한다.
      //}------------------------------------------------------------------

      _Tree_Get_Node_LastItemIndex(pTree, pDeleteNodeIndex, NULL, &deleteEndIndex);

  //}

  //[삭제 정보 구하기]
  //{
      deleteCount = (deleteEndIndex - deleteStartIndex) + 1;

  //}

  //[삭제]
  //{
      //지정 구간을 뒤의 것을 앞으로 끌어 당겨 붙임으로써 삭제한다.

      for(i = deleteStartIndex; i < (pTree->items_count - deleteCount); i++)
      {
        pTree->items[i] = pTree->items[i + deleteCount];

      }

  //}

  //[후처리]
  //{
      //[tree] 가 수정 되었으므로 관련 정보도 같이 수정한다.
      pTree->items_count     -= deleteCount;

      pTree->select_line      = -1;

      pTree->select_itemindex = -1;

  //}

  //[옹이처리]
  //{
      //[방법]{-------------------------------------------------------------------------
      //현재 [옹이] 의 하위 가지가 전부 삭제 되었으므로 [옹이] 에서 해제해 주어야 한다.
      //[+]/[-] 인 경우가 되므로 이것을 [.] 으로 바꿔 주어야 한다.
      //}-------------------------------------------------------------------------------

      //이 경우는 지금 [옹이] 는 하위 [가지] 를 하나도 갖지 않은 것이므로 [옹이] 에서 해제 한다.
      pTree->items[pDeleteNodeIndex].kind = '.';

  //}

  return(true);

}

void __fastcall TGTree_Form::_Tree_Get_NodeIndex_of_ThisItem(struct TREE  *pTree,
                                                                 //지정 itemIndex.
                                                                 int           pItemIndex,
                                                                 //직계 [옹이] 의 itemIndex.
                                                                 int          *rNodeIndex)
{
  //[2009.02.02.월][생성!!!]{---------------------------------------------
  //지정 [항목] 을 포함하고 있는 [직계 옹이] 의 index 를 찾아서 반환한다.
  //}---------------------------------------------------------------------

  //[VAR]
  //{
      int  i;

  //}

  //[유효한 항목인가?]
  //{
      //지정 항목이 이 [tree] 범위 내에 존재하는지 확인한다.
      if(!((0 <= pItemIndex) && (pItemIndex < pTree->items_count)))
      {
        //범위에 해당하지 않는 것으로 간주하고 -1 을 반환한다.

        (*rNodeIndex) = -1;

        return;

      }

  //}

  //[직계옹이 찾기]
  //{
      //[옹이] 는 [가지] 보다 앞쪽에 있으므로 지정 위치부터 거꾸로 검사한다.
      for(i = pItemIndex; i >= 0; i--)
      {
        //[직계 옹이] 는 현재 항목보다 <level> 이 -1 작다.
        if(pTree->items[i].level == (pTree->items[pItemIndex].level - 1))
        {
          //해당하는 [직계옹이] 를 찾았다.

          (*rNodeIndex) = i;

          return;

        }

      }

  //}

  //[예외처리]
  //{
      //여기까지 온것은 찾는 것이 없는 것이다.
      (*rNodeIndex) = -1;

  //}

  return;

}

//------------------------------------------------------------------------------
//[EVENT]-----------------------------------------------------------------------
//------------------------------------------------------------------------------

void __fastcall TGTree_Form::FormMouseDown(TObject *Sender,
      TMouseButton Button, TShiftState Shift, int X, int Y)
{
  //[2006.11.23.목][생성!!!]{--------------------------------
  //'+', '-' 등의 조작과 [항목] 선택표시 등을 처리해야 한다.
  //}--------------------------------------------------------

  //[VAR]
  //{
      struct ITEMXY  itemxy;
      int            line_number;
      int            itemindex;
      int            text_x;
      int            text_y;

  //}

  //[2006.11.04.토][생성!!!]{---------------------------------------
  //[휠마우스] 를 사용하게 하기 위하여 반드시 포커스를 주어야 한다.
  this->SetFocus();
  //}---------------------------------------------------------------

  switch(Button)
  {
    case  mbLeft :
    case  mbRight : //<---[2009.05.31.일][추가!!!]
    {
      //마우스 왼쪽 버튼인 경우만 동작을 처리한다.

      //[마우스포인터가 위치한 행 구하기]
      //{
          line_number                           = ((-1) * _item_xy.tree_y + Y - 1) / _item_xy.line_height;
          _tree[_tree_select_index].select_line = line_number;

      //}

      //[무효 행인지 확인]
      //{
          if(_tree[_tree_select_index].select_line > _tree[_tree_select_index].last_line)
          {
            //실제 그려진 tree 영역을 벗어난 아래의 공백인 경우는 해당 선택 정보는 해제해야 한다.
            _tree[_tree_select_index].select_line      = -1;
            _tree[_tree_select_index].select_itemindex = -1;

          }
      //}

      //[itemindex 구하기]
      //{
          //현재 마우스포인터가 위치한 행의 항목 itemindex 를 얻는다.
          _Get_ItemIndex_withLINE(&(_tree[_tree_select_index]),
                                    line_number,
                                    &itemindex,
                                    &text_x,
                                    &text_y);
      //}

      //[좌표수정]
      //{
          //[귀뜸말] 은 main_Form 의 (Left, Top) 이 원점이 되므로 이 tree 안에 표시 되도록
          //좌표를 수정해 준다.
          text_x += (ide_tree_Form->Left + this->Left - 2);
          text_y += (ide_tree_Form->Top + this->Top - 1);

      //}

      //[변경 내용 반영]
      //{
          //문자열앞의 영역에 있는 경우만 표시한다.
          //이는 [문자열] 을 선택하는데 [귀뜸말] 이 문자열을 가리는 경우를 방지하기 위한 것이다.
          if((X < text_x) && (Button == mbLeft))
          {
            //[다시 그린다]
            //{
                //이 함수 안에서 '+', '-' 전환 처리등을 모두 처리한다.
                //동작관련 으로 다시 그리는 것이므로 true 로 설정하여 그린다.
                _TreeView(_tree_select_index, true);

            //}

          }
          else
          {
            //[다시 그린다]
            //{
                //이 함수 안에서 선택 표시만 처리한다.
                //동작과는 관련이 없으므로 false 로 설정하여 그린다.
                _TreeView(_tree_select_index, false);

            //}

          }

      //}

    } break;

  }

  return;

}

void __fastcall TGTree_Form::FormMouseWheel(TObject *Sender,
      TShiftState Shift, int WheelDelta, TPoint &MousePos, bool &Handled)
{
  //[2006.11.04.토][생성!!!]{---------------------------------------------
  //휠이 동작하는 경우는 _position 의 값을 1 씩 변화 시킨다.
  //WheelDelta 는 변화값이나 자체에 큰 의미는 없으므로 위/아래 어느쪽으로
  //휠이 움직였는지 확인하는 정도로 사용하고 값을 사용하지는 않는다.
  //}---------------------------------------------------------------------

  //[주의!!!]
  //{
      //---------------------------------------------------------------
      //반드시 true 로 설정하여 순수하게 직접 컨트롤 할수 있도록 한다.
      //그렇지 않은 경우 한번 스크롤시 3 번정도 이 함수가 호출되므로
      //원치 않는 동작이 생긴다.
      Handled = true;
      //이제 정확하게 스크롤 한 단계마다 이 함수는 한번씩 call 된다.
      //---------------------------------------------------------------
  //}

  //[휠동작]
  //{
      //_position 값을 수정하고 자동으로 다시 scrollbar 를 그려준다.
      if     (WheelDelta > 0)
      {
        ide_tree_Form->_scroll_v_Form->_position -= 3;
        ide_tree_Form->_scroll_v_Form->_Position(ide_tree_Form->_scroll_v_Form->_position);

      }
      else if(WheelDelta < 0)
      {
        ide_tree_Form->_scroll_v_Form->_position += 3;
        ide_tree_Form->_scroll_v_Form->_Position(ide_tree_Form->_scroll_v_Form->_position);

      }
  //}

  return;

}

void __fastcall TGTree_Form::FormMouseMove(TObject *Sender,
      TShiftState Shift, int X, int Y)
{
  //[2006.12.08.금][생성!!!]{---------------------------------------------------------
  //마우스가 tree 위를 움직이는 경우는 마우스 포인터가 위치한 행의 itemindex 를
  //찾아서 해당 항목의 문자열을 [귀뜸말] 로 지정 항목 위치에 표시해 주어야 한다.
  //이는 항목의 문자열이 너무 긴 경우 다 보이지 않게 되는 경우가 발생하기 때문이다.
  //
  //[귀뜸말] 창이 뜨면 해당 행을 가리게 되므로 이 [귀뜸말] 창을 벗어나지 않는한
  //다시 FormMouseMove() 이벤트가 발생하지 않으므로 중복 처리방지는 하지 않아도 된다.
  //}---------------------------------------------------------------------------------

  //[VAR]
  //{
      struct ITEMXY  itemxy;
      int            line_number;
      int            itemindex;
      int            text_x;
      int            text_y;

  //}

  //[마우스포인터가 위치한 행 구하기]
  //{
      line_number = ((-1) * _item_xy.tree_y + Y - 1) / _item_xy.line_height;
  //}

  //[itemindex 구하기]
  //{
      //현재 마우스포인터가 위치한 행의 항목 itemindex 를 얻는다.
      _Get_ItemIndex_withLINE(&(_tree[_tree_select_index]),
                              line_number,
                              &itemindex,
                              &text_x,
                              &text_y);
  //}

  //[예외]
  //{
      //지정행에 [항목] 이 없는 경우는 처리하지 않으며 이미 [귀뜸말] 이 보이는
      //경우는 사라지게 한다.
      if(itemindex == -1)
      {
        ide_hint_Form->_HideHint();

        return;

      }
  //}

  //[좌표수정]
  //{
      //-------------------------------------------------------------------------------
      //[귀뜸말] 은 main_Form 의 (Left, Top) 이 원점이 되므로 이 tree 안에 표시 되도록
      //좌표를 수정해 준다.
      text_x += (ide_tree_Form->Left + this->Left - 2);
      text_y += (ide_tree_Form->Top + this->Top - 1);
      //-------------------------------------------------------------------------------
  //}

  //[귀뜸말 표시]
  //{
      //문자열앞의 영역에 있는 경우만 표시한다.
      //이는 [문자열] 을 선택하는데 [귀뜸말] 이 문자열을 가리는 경우를 방지하기 위한 것이다.
      if(X < text_x)
      {
        ide_hint_Form->_ShowHint(text_x, text_y,
                                 (AnsiString)(_tree[_tree_select_index].items[itemindex].txt));

      }
      else
      {
        //다른 영역인 경우는 [귀뜸말] 을 감춘다.
        ide_hint_Form->_HideHint();

      }
  //}

  return;

}

void __fastcall TGTree_Form::FormMouseUp(TObject *Sender,
      TMouseButton Button, TShiftState Shift, int X, int Y)
{
  //[2007.02.06.화][생성!!!]{----------------------------------
  //[선택영역] 이 형성되고 있는 상태라면 여기서 종료해야 한다.

  //[선택영역] 의 경우는 마우스 [왼쪽버튼] 인 경우로 한정한다.
  //}----------------------------------------------------------

  switch(Button)
  {
    case mbLeft :
    {


    } break;

    case mbRight :
    {
      //[해당 [빠른목록] 만들기]
      //{
          //[2009.05.31.일][수정!!!]{-------------------------------
          //현재 보이는 [정보창] 에 맞는 [빠른목록] 을 만들어 준다.
          //}-------------------------------------------------------

          _PopupMemu_Set(_tree_select_index);

      //}

      if(ide_hint_Form->Visible == false)
      {
        //[2009.05.31.일][수정!!!]{----------------------------------
        //깜박거리지 않도록 [귀뜸말] 이 보이지 않는 경우만 보여준다.
        //}----------------------------------------------------------

        //[팝업메뉴] 를 보여준다.
        _popupMenu->_Popup(main_Form->Left + this->Parent->Left + this->Left + X,
                           main_Form->Top  + this->Parent->Top  + this->Top  + Y);

      }

    } break;

  }

  return;

}

void __fastcall TGTree_Form::FormDblClick(TObject *Sender)
{
  //[2009.01.30.금][생성!!!]{---------------------------------------------------------
  //[더블클릭] 의 경우는 해당 문서를 열어 주어야 한다.
  //이미 항목 의 선택 정보는 _tree[_tree_select_index].select_itemindex 에 들어 있다.
  //이 것을 사용하여 <text> 를 얻으면 간단하게 해당 문서 경로를 얻을수 있다.
  //}---------------------------------------------------------------------------------

  //전용 처리 함수를 사용하여 처리한다.
  IDE_Tree_Item_DoubleClick();

  return;

}

//------------------------------------------------------------------------------
//[빠른목록 관련]---------------------------------------------------------------
//------------------------------------------------------------------------------

void __fastcall TGTree_Form::_PopupMemu_Set(//[빠른목록] 을 설정할 대상을 설정한다.
                                                int  pTreeIndex)
{
  //[2009.05.31.일][생성!!!]{--------------------------------------------------------
  //이전과 달리 각각의 [Tree] 는 각각의 [빠른목록] 을 가지도록 수정한다.
  //이는 항목수가 늘었기 때문으로 구조가 복잡해지고 기능이 많아진 만큼 별도로 관리할
  //필요가 생겼기 때문이다.
  //}--------------------------------------------------------------------------------

  //[VAR]
  //{
      int  i;

  //}

  switch(pTreeIndex)
  {
    case  d_TREE_project :
    {
      //[항목 만들기]
      //{
          i = 0;

          _popupMenu->_subitem.str[i++] = " 추가 ";
          _popupMenu->_subitem.str[i++] = " 삭제 ";
          _popupMenu->_subitem.str[i++] = " .하위항목 모두열기 ";
          _popupMenu->_subitem.str[i++] = "  하위항목 모두닫기 ";
          _popupMenu->_subitem.str[i++] = " .같은단계 모두열기 ";
          _popupMenu->_subitem.str[i++] = "  같은단계 모두닫기 ";
          _popupMenu->_subitem.str[i++] = " .전체 열기 ";
          _popupMenu->_subitem.str[i++] = "  전체 닫기 ";

          _popupMenu->_subitem.count        = i;
          _popupMenu->_subitem.select_index = -1;

      //}

      //[동작함수 등록]{------------------------------------
      _popupMenu->_EVENT_ItemSelect = _EVENT_PopupMenu_Prj;
      //[초기화]--------------------------------------------
      //반드시 한번만 초기화 해야 한다.
      _popupMenu->_Init();
      //}---------------------------------------------------

    } break;

    case  d_TREE_info :
    {
      //[항목 만들기]
      //{
          i = 0;

          _popupMenu->_subitem.str[i++] = " .하위항목 모두열기 ";
          _popupMenu->_subitem.str[i++] = "  하위항목 모두닫기 ";
          _popupMenu->_subitem.str[i++] = " .같은단계 모두열기 ";
          _popupMenu->_subitem.str[i++] = "  같은단계 모두닫기 ";
          _popupMenu->_subitem.str[i++] = " .전체 열기 ";
          _popupMenu->_subitem.str[i++] = "  전체 닫기 ";

          _popupMenu->_subitem.count        = i;
          _popupMenu->_subitem.select_index = -1;

      //}

      //[동작함수 등록]{-------------------------------------
      _popupMenu->_EVENT_ItemSelect = _EVENT_PopupMenu_Info;
      //[초기화]---------------------------------------------
      //반드시 한번만 초기화 해야 한다.
      _popupMenu->_Init();
      //}----------------------------------------------------

    } break;

    case  d_TREE_api :
    {
      //[항목 만들기]
      //{
          i = 0;

          _popupMenu->_subitem.str[i++] = " 설계묶음에 추가 ";
          _popupMenu->_subitem.str[i++] = " .하위항목 모두열기 ";
          _popupMenu->_subitem.str[i++] = "  하위항목 모두닫기 ";
          _popupMenu->_subitem.str[i++] = " .같은단계 모두열기 ";
          _popupMenu->_subitem.str[i++] = "  같은단계 모두닫기 ";
          _popupMenu->_subitem.str[i++] = " .전체 열기 ";
          _popupMenu->_subitem.str[i++] = "  전체 닫기 ";

          _popupMenu->_subitem.count        = i;
          _popupMenu->_subitem.select_index = -1;

      //}

      //[동작함수 등록]{------------------------------------
      _popupMenu->_EVENT_ItemSelect = _EVENT_PopupMenu_Api;
      //[초기화]--------------------------------------------
      //반드시 한번만 초기화 해야 한다.
      _popupMenu->_Init();
      //}---------------------------------------------------

    } break;

    case  d_TREE_system :
    {
      //[항목 만들기]
      //{
          i = 0;

          _popupMenu->_subitem.str[i++] = " .하위항목 모두열기 ";
          _popupMenu->_subitem.str[i++] = "  하위항목 모두닫기 ";
          _popupMenu->_subitem.str[i++] = " .같은단계 모두열기 ";
          _popupMenu->_subitem.str[i++] = "  같은단계 모두닫기 ";
          _popupMenu->_subitem.str[i++] = " .전체 열기 ";
          _popupMenu->_subitem.str[i++] = "  전체 닫기 ";

          _popupMenu->_subitem.count        = i;
          _popupMenu->_subitem.select_index = -1;

      //}

      //[동작함수 등록]{---------------------------------------
      _popupMenu->_EVENT_ItemSelect = _EVENT_PopupMenu_System;
      //[초기화]-----------------------------------------------
      //반드시 한번만 초기화 해야 한다.
      _popupMenu->_Init();
      //}------------------------------------------------------

    } break;

  }

  return;

}

void __fastcall TGTree_Form::_EVENT_PopupMenu_Prj(void)
{
  //[2009.02.02.월][생성!!!]{-------------------------------------
  //[바른항목] 에서 항목이 선택된 경우 이 함수를 호출하게 되는데,
  //선택된 항목의 index 를 구하여 해당 항목의 처리를 수행한다.
  //}-------------------------------------------------------------

  //[VAR]
  //{
      char   menuStr[OPT_lineStrSize];

  //}

  //[촛점설정]
  //{
      //동작 전에 항상 대상에 촛점을 맞춘다.
      this->SetFocus();

  //}

  //[정보얻기]
  //{
      STR_Assign(menuStr, _popupMenu->_subitem.str[_popupMenu->_subitem.select_index].c_str());

  //}

  if     (STR_Match(menuStr, " 추가 "))
  {
    //현재 [옹이] 에 새로운 항목을 추가 한다.
    IDE_Tree_Item_Add();

  }
  else if(STR_Match(menuStr, " 삭제 "))
  {
    //현재 선택된 항목을 삭제 한다.
    IDE_Tree_Item_Delete();

  }
  else if(STR_Match(menuStr, " .하위항목 모두열기 "))
  {
    _Tree_ThisItemExpandAll(d_TREE_project, _tree[d_TREE_project].select_itemindex);

  }
  else if(STR_Match(menuStr, "  하위항목 모두닫기 "))
  {
    _Tree_ThisItemCloseAll(d_TREE_project, _tree[d_TREE_project].select_itemindex);

  }
  else if(STR_Match(menuStr, " .같은단계 모두열기 "))
  {
    _Tree_ThisLevelExpandAll(d_TREE_project, _tree[d_TREE_project].items[_tree[d_TREE_project].select_itemindex].level);

  }
  else if(STR_Match(menuStr, "  같은단계 모두닫기 "))
  {
    _Tree_ThisLevelCloseAll(d_TREE_project, _tree[d_TREE_project].items[_tree[d_TREE_project].select_itemindex].level);

  }
  else if(STR_Match(menuStr, " .전체 열기 "))
  {
    _Tree_ExpandAll(d_TREE_project);

  }
  else if(STR_Match(menuStr, "  전체 닫기 "))
  {
    _Tree_CloseAll(d_TREE_project);

  }

  return;

}

void __fastcall TGTree_Form::_EVENT_PopupMenu_Info(void)
{
  //[2009.05.31.일][생성!!!]{-------------
  //[설계정보] 의 [빠른목록] 을 처리한다.
  //}-------------------------------------

  //[VAR]
  //{
      char   menuStr[OPT_lineStrSize];

  //}

  //[촛점설정]
  //{
      //동작 전에 항상 대상에 촛점을 맞춘다.
      this->SetFocus();

  //}

  //[정보얻기]
  //{
      STR_Assign(menuStr, _popupMenu->_subitem.str[_popupMenu->_subitem.select_index].c_str());

  //}

  if     (STR_Match(menuStr, " .하위항목 모두열기 "))
  {
    _Tree_ThisItemExpandAll(d_TREE_info, _tree[d_TREE_info].select_itemindex);

  }
  else if(STR_Match(menuStr, "  하위항목 모두닫기 "))
  {
    _Tree_ThisItemCloseAll(d_TREE_info, _tree[d_TREE_info].select_itemindex);

  }
  else if(STR_Match(menuStr, " .같은단계 모두열기 "))
  {
    _Tree_ThisLevelExpandAll(d_TREE_info, _tree[d_TREE_info].items[_tree[d_TREE_info].select_itemindex].level);

  }
  else if(STR_Match(menuStr, "  같은단계 모두닫기 "))
  {
    _Tree_ThisLevelCloseAll(d_TREE_info, _tree[d_TREE_info].items[_tree[d_TREE_info].select_itemindex].level);

  }
  else if(STR_Match(menuStr, " .전체 열기 "))
  {
    _Tree_ExpandAll(d_TREE_info);

  }
  else if(STR_Match(menuStr, "  전체 닫기 "))
  {
    _Tree_CloseAll(d_TREE_info);

  }

  return;

}

void __fastcall TGTree_Form::_EVENT_PopupMenu_Api(void)
{
  //[2009.05.31.일][생성!!!]{--------
  //[API] 의 [빠른목록] 을 처리한다.
  //}--------------------------------

  //[VAR]
  //{
      char   menuStr[OPT_lineStrSize];

  //}

  //[촛점설정]
  //{
      //동작 전에 항상 대상에 촛점을 맞춘다.
      this->SetFocus();

  //}

  //[정보얻기]
  //{
      STR_Assign(menuStr, _popupMenu->_subitem.str[_popupMenu->_subitem.select_index].c_str());

  //}

  if     (STR_Match(menuStr, " 설계묶음에 추가 "))
  {
    //[2009.06.01.월][추가!!!]{---------------------------------------------------
    //현재 선택 항목의 지정 [함수묶음] 을 현재 [설계묶음] 의 해당 경로로 복사하고
    //[설계묶음] 에 추가한다.
    //}---------------------------------------------------------------------------

    Ide_Tree_Api_Add_Glib_To_Gprj();

  }
  else if(STR_Match(menuStr, " .하위항목 모두열기 "))
  {
    _Tree_ThisItemExpandAll(d_TREE_api, _tree[d_TREE_api].select_itemindex);

  }
  else if(STR_Match(menuStr, "  하위항목 모두닫기 "))
  {
    _Tree_ThisItemCloseAll(d_TREE_api, _tree[d_TREE_api].select_itemindex);

  }
  else if(STR_Match(menuStr, " .같은단계 모두열기 "))
  {
    _Tree_ThisLevelExpandAll(d_TREE_api, _tree[d_TREE_api].items[_tree[d_TREE_api].select_itemindex].level);

  }
  else if(STR_Match(menuStr, "  같은단계 모두닫기 "))
  {
    _Tree_ThisLevelCloseAll(d_TREE_api, _tree[d_TREE_api].items[_tree[d_TREE_api].select_itemindex].level);

  }
  else if(STR_Match(menuStr, " .전체 열기 "))
  {
    _Tree_ExpandAll(d_TREE_api);

  }
  else if(STR_Match(menuStr, "  전체 닫기 "))
  {
    _Tree_CloseAll(d_TREE_api);

  }

  return;

}

void __fastcall TGTree_Form::_EVENT_PopupMenu_System(void)
{
  //[2009.05.31.일][생성!!!]{-------------
  //[설계정보] 의 [빠른목록] 을 처리한다.
  //}-------------------------------------

  //[VAR]
  //{
      char   menuStr[OPT_lineStrSize];

  //}

  //[촛점설정]
  //{
      //동작 전에 항상 대상에 촛점을 맞춘다.
      this->SetFocus();

  //}

  //[정보얻기]
  //{
      STR_Assign(menuStr, _popupMenu->_subitem.str[_popupMenu->_subitem.select_index].c_str());

  //}

  if     (STR_Match(menuStr, " .하위항목 모두열기 "))
  {
    _Tree_ThisItemExpandAll(d_TREE_system, _tree[d_TREE_system].select_itemindex);

  }
  else if(STR_Match(menuStr, "  하위항목 모두닫기 "))
  {
    _Tree_ThisItemCloseAll(d_TREE_system, _tree[d_TREE_system].select_itemindex);

  }
  else if(STR_Match(menuStr, " .같은단계 모두열기 "))
  {
    _Tree_ThisLevelExpandAll(d_TREE_system, _tree[d_TREE_system].items[_tree[d_TREE_system].select_itemindex].level);

  }
  else if(STR_Match(menuStr, "  같은단계 모두닫기 "))
  {
    _Tree_ThisLevelCloseAll(d_TREE_system, _tree[d_TREE_system].items[_tree[d_TREE_system].select_itemindex].level);

  }
  else if(STR_Match(menuStr, " .전체 열기 "))
  {
    _Tree_ExpandAll(d_TREE_system);

  }
  else if(STR_Match(menuStr, "  전체 닫기 "))
  {
    _Tree_CloseAll(d_TREE_system);

  }

  return;

}

void __fastcall TGTree_Form::_Tree_ExpandAll(//처리 대상.
                                                 int  pTreeIndex)
{
  //[2009.05.31.일][생성!!!]{-------------------
  //전달받은 [Tree] 의 모든 항목을 펼쳐준다.
  //<kind>: '+' 것만 전부 '-' 로 바꿔주면 된다.
  //}-------------------------------------------

  //[VAR]
  //{
      int  i;

  //}

  for(i = 0; i < _tree[pTreeIndex].items_count; i++)
  {
    if(_tree[pTreeIndex].items[i].kind == '+') _tree[pTreeIndex].items[i].kind = '-';

  }

  //다시 그리기.
  _TreeView(pTreeIndex, false);

  return;

}

void __fastcall TGTree_Form::_Tree_CloseAll(//처리 대상.
                                                int  pTreeIndex)
{
  //[2009.05.31.일][생성!!!]{-------------------
  //전달받은 [Tree] 의 모든 항목을 접어준다.
  //<kind>: '-' 것만 전부 '+' 로 바꿔주면 된다.
  //}-------------------------------------------

  //[VAR]
  //{
      int  i;

  //}

  for(i = 0; i < _tree[pTreeIndex].items_count; i++)
  {
    if(_tree[pTreeIndex].items[i].kind == '-') _tree[pTreeIndex].items[i].kind = '+';

  }

  //다시 그리기.
  _TreeView(pTreeIndex, false);

  return;

}

void __fastcall TGTree_Form::_Tree_ThisItemExpandAll(//처리 대상.
                                                         int  pTreeIndex,
                                                         int  pItemIndex)
{
  //[2009.05.31.일][생성!!!]{---------------------------------------
  //전달받은 [Tree] 의 지정된 항목의 모든 하위 항목가지만 펼쳐준다.
  //<kind>: '+' 것만 전부 '-' 로 바꿔주면 된다.
  //}---------------------------------------------------------------

  //[VAR]
  //{
      int  i;

  //}

  //[지정 항목 펼치기]{-------------------------------------------------------------------------------
  //일단 현재 지정된 [항목] 이 [옹이] 인 경우는 이것부터 펼쳐준다.
  if(_tree[pTreeIndex].items[pItemIndex].kind == '+') _tree[pTreeIndex].items[pItemIndex].kind = '-';
  //}-------------------------------------------------------------------------------------------------

  for(i = pItemIndex + 1; i < _tree[pTreeIndex].items_count; i++)
  {
    //형재 항목보다 하위단계만 처리한다.
    if(_tree[pTreeIndex].items[pItemIndex].level < _tree[pTreeIndex].items[i].level)
    {
      if(_tree[pTreeIndex].items[i].kind == '+') _tree[pTreeIndex].items[i].kind = '-';

    }
    else
    {
      //이 경우는 더이상 항위항목이 아니므로 종료한다.
      break;

    }

  }

  //다시 그리기.
  _TreeView(pTreeIndex, false);

  return;

}

void __fastcall TGTree_Form::_Tree_ThisItemCloseAll(//처리 대상.
                                                        int  pTreeIndex,
                                                        int  pItemIndex)
{
  //[2009.05.31.일][생성!!!]{---------------------------------------
  //전달받은 [Tree] 의 지정된 항목의 모든 하위 항목가지만 접어준다.
  //<kind>: '-' 것만 전부 '+' 로 바꿔주면 된다.
  //}---------------------------------------------------------------

  //[VAR]
  //{
      int  i;

  //}

  //[지정 항목 펼치기]{-------------------------------------------------------------------------------
  //일단 현재 지정된 [항목] 이 [옹이] 인 경우는 이것부터 펼쳐준다.
  if(_tree[pTreeIndex].items[pItemIndex].kind == '-') _tree[pTreeIndex].items[pItemIndex].kind = '+';
  //}-------------------------------------------------------------------------------------------------

  for(i = pItemIndex + 1; i < _tree[pTreeIndex].items_count; i++)
  {
    //형재 항목보다 하위단계만 처리한다.
    if(_tree[pTreeIndex].items[pItemIndex].level < _tree[pTreeIndex].items[i].level)
    {
      if(_tree[pTreeIndex].items[i].kind == '-') _tree[pTreeIndex].items[i].kind = '+';

    }
    else
    {
      //이 경우는 더이상 항위항목이 아니므로 종료한다.
      break;

    }

  }

  //다시 그리기.
  _TreeView(pTreeIndex, false);

  return;

}

void __fastcall TGTree_Form::_Tree_ThisLevelExpandAll(//처리 대상.
                                                          int  pTreeIndex,
                                                          int  pLevel)
{
  //[2009.05.31.일][생성!!!]{-------------------------------------------
  //전달받은 [Tree] 의 지정된 <level> 에 해당하는 단계만 전부 펼쳐준다,
  //<kind>: '+' 것만 전부 '-' 로 바꿔주면 된다.
  //}-------------------------------------------------------------------

  //[VAR]
  //{
      int  i;

  //}

  for(i = 0; i < _tree[pTreeIndex].items_count; i++)
  {
    //형재 항목보다 하위단계만 처리한다.
    if(_tree[pTreeIndex].items[i].level == pLevel)
    {
      if(_tree[pTreeIndex].items[i].kind == '+') _tree[pTreeIndex].items[i].kind = '-';

    }

  }

  //다시 그리기.
  _TreeView(pTreeIndex, false);

  return;

}

void __fastcall TGTree_Form::_Tree_ThisLevelCloseAll(//처리 대상.
                                                         int  pTreeIndex,
                                                         int  pLevel)
{
  //[2009.05.31.일][생성!!!]{-------------------------------------------
  //전달받은 [Tree] 의 지정된 <level> 에 해당하는 단계만 전부 접어준다,
  //<kind>: '-' 것만 전부 '+' 로 바꿔주면 된다.
  //}-------------------------------------------------------------------

  //[VAR]
  //{
      int  i;

  //}

  for(i = 0; i < _tree[pTreeIndex].items_count; i++)
  {
    //형재 항목보다 하위단계만 처리한다.
    if(_tree[pTreeIndex].items[i].level == pLevel)
    {
      if(_tree[pTreeIndex].items[i].kind == '-') _tree[pTreeIndex].items[i].kind = '+';

    }

  }

  //다시 그리기.
  _TreeView(pTreeIndex, false);

  return;

}

//------------------------------------------------------------------------------
//[배경화면관련]----------------------------------------------------------------
//------------------------------------------------------------------------------

void __fastcall TGTree_Form::_BACKBMP_Brightness(int  pBrightness)
{
  //[2007.10.05.금][생성!!!]{----
  //바탕 그림의 밝기를 조정한다.
  //}----------------------------

  //[VAR]
  //{
      AnsiString  _bmp_path;

  //}

  //[배경화면]
  //{
      //[그림 경로]
      //{
          if(IDE_BACKBMP_entire)
          {
            //한개의 그림을 전체영역으로 사용하는 경우.
            _bmp_path = (AnsiString)_ide_option->ideBackpicturePath;

            //[확인]
            //[
                //[2007.12.04.화][추가!!!]
                //그림이 있는지 먼저 확인한다.
                if(FileExists(_bmp_path) != true)
                {
                  //그림이 존재하지 않는 경우는 기본 그림으로 대체한다.
                  _bmp_path = IDE_BACKBMP_entire_path;

                }

                //기본 그림이 있는지 한번더 확인한다.
                if(FileExists(_bmp_path) != true)
                {
                  //기본 그림 역시 존재하지 않는다면 그냥 표시하지 않는다.
                  _bmp_path = "";

                }

            //}

          }
          else
          {
            //지정된 전용 그림을 사용한다.
            _bmp_path = (AnsiString)_ide_option->treeBackPicturePath;

            //[확인]
            //[
                //[2007.12.04.화][추가!!!]
                //그림이 있는지 먼저 확인한다.
                if(FileExists(_bmp_path) != true)
                {
                  //그림이 존재하지 않는 경우는 기본 그림으로 대체한다.
                  _bmp_path = IDE_BACKBMP_tree_path;

                }

                //기본 그림이 있는지 한번더 확인한다.
                if(FileExists(_bmp_path) != true)
                {
                  //기본 그림 역시 존재하지 않는다면 그냥 표시하지 않는다.
                  _bmp_path = "";

                }

            //}

          }

      //}

      //[그림 확인]
      //{
          //[2007.12.04.화][추가!!!]
          //만일 그림이 없는 경우는 처리하지 않는다.
          if(_bmp_path == "")
          {
            //이 경우는 배경을 전부 흰색으로 칠해 주어야 한다.

            //크기지정.
            _bmp_back_->Width  = Screen->Width;
            _bmp_back_->Height = Screen->Height;

            //색칠하기.
            _bmp_back_->Canvas->Brush->Color = clWhite;
            _bmp_back_->Canvas->FillRect(_bmp_back_->Canvas->ClipRect);

          }
          else
          {
            //그림 읽어 들이기.
            BMP_LoadJpeg(_bmp_back_, _bmp_path, Screen->Width, Screen->Height, d_BMP_load_tile);

          }

      //}

      //24bit bitmap 으로 지정한다.
      _bmp_back_->PixelFormat = pf24bit;

      //배경 그림을 밝게 하여 문자가 잘 보기게 만든다.
      BMP_Brightness(_bmp_back_, _ide_option->tree_back_brightness);

  //}

  //[다시 그려서 보여주기]
  //{
      //선택된 tab 의 tree 를 그린다.
      _TreeView(_tree_select_index, false);

  //}

  return;

}

void __fastcall TGTree_Form::_BACKBMP_ChangeJpeg(AnsiString  pJpegFilePath)
{
  //[2007.12.02.일][생성!!!]{----------------
  //바탕 그림을 지정 그림으로 다시 그려준다.
  //}----------------------------------------

  //그림 읽어 들이기.
  BMP_LoadJpeg(_bmp_back_, pJpegFilePath, Screen->Width, Screen->Height, d_BMP_load_tile);

  //24bit bitmap 으로 지정한다.
  _bmp_back_->PixelFormat = pf24bit;

  //배경 그림을 밝게 하여 문자가 잘 보기게 만든다.
  BMP_Brightness(_bmp_back_, _ide_option->tree_back_brightness);

  //[다시 그려서 보여주기]
  //{
      //선택된 tab 의 tree 를 그린다.
      _TreeView(_tree_select_index, false);

  //}

  return;

}



